mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 19:21:31 -04:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking changes from David Miller:
"Noteworthy changes this time around:
1) Multicast rejoin support for team driver, from Jiri Pirko.
2) Centralize and simplify TCP RTT measurement handling in order to
reduce the impact of bad RTO seeding from SYN/ACKs. Also, when
both timestamps and local RTT measurements are available prefer
the later because there are broken middleware devices which
scramble the timestamp.
From Yuchung Cheng.
3) Add TCP_NOTSENT_LOWAT socket option to limit the amount of kernel
memory consumed to queue up unsend user data. From Eric Dumazet.
4) Add a "physical port ID" abstraction for network devices, from
Jiri Pirko.
5) Add a "suppress" operation to influence fib_rules lookups, from
Stefan Tomanek.
6) Add a networking development FAQ, from Paul Gortmaker.
7) Extend the information provided by tcp_probe and add ipv6 support,
from Daniel Borkmann.
8) Use RCU locking more extensively in openvswitch data paths, from
Pravin B Shelar.
9) Add SCTP support to openvswitch, from Joe Stringer.
10) Add EF10 chip support to SFC driver, from Ben Hutchings.
11) Add new SYNPROXY netfilter target, from Patrick McHardy.
12) Compute a rate approximation for sending in TCP sockets, and use
this to more intelligently coalesce TSO frames. Furthermore, add
a new packet scheduler which takes advantage of this estimate when
available. From Eric Dumazet.
13) Allow AF_PACKET fanouts with random selection, from Daniel
Borkmann.
14) Add ipv6 support to vxlan driver, from Cong Wang"
Resolved conflicts as per discussion.
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1218 commits)
openvswitch: Fix alignment of struct sw_flow_key.
netfilter: Fix build errors with xt_socket.c
tcp: Add missing braces to do_tcp_setsockopt
caif: Add missing braces to multiline if in cfctrl_linkup_request
bnx2x: Add missing braces in bnx2x:bnx2x_link_initialize
vxlan: Fix kernel panic on device delete.
net: mvneta: implement ->ndo_do_ioctl() to support PHY ioctls
net: mvneta: properly disable HW PHY polling and ensure adjust_link() works
icplus: Use netif_running to determine device state
ethernet/arc/arc_emac: Fix huge delays in large file copies
tuntap: orphan frags before trying to set tx timestamp
tuntap: purge socket error queue on detach
qlcnic: use standard NAPI weights
ipv6:introduce function to find route for redirect
bnx2x: VF RSS support - VF side
bnx2x: VF RSS support - PF side
vxlan: Notify drivers for listening UDP port changes
net: usbnet: update addr_assign_type if appropriate
driver/net: enic: update enic maintainers and driver
driver/net: enic: Exposing symbols for Cisco's low latency driver
...
This commit is contained in:
commit
cc998ff881
974 changed files with 56740 additions and 23930 deletions
|
|
@ -462,6 +462,14 @@ int wiphy_register(struct wiphy *wiphy)
|
|||
return -EINVAL;
|
||||
#endif
|
||||
|
||||
if (WARN_ON(wiphy->coalesce &&
|
||||
(!wiphy->coalesce->n_rules ||
|
||||
!wiphy->coalesce->n_patterns) &&
|
||||
(!wiphy->coalesce->pattern_min_len ||
|
||||
wiphy->coalesce->pattern_min_len >
|
||||
wiphy->coalesce->pattern_max_len)))
|
||||
return -EINVAL;
|
||||
|
||||
if (WARN_ON(wiphy->ap_sme_capa &&
|
||||
!(wiphy->flags & WIPHY_FLAG_HAVE_AP_SME)))
|
||||
return -EINVAL;
|
||||
|
|
@ -668,6 +676,7 @@ void wiphy_unregister(struct wiphy *wiphy)
|
|||
rdev_set_wakeup(rdev, false);
|
||||
#endif
|
||||
cfg80211_rdev_free_wowlan(rdev);
|
||||
cfg80211_rdev_free_coalesce(rdev);
|
||||
}
|
||||
EXPORT_SYMBOL(wiphy_unregister);
|
||||
|
||||
|
|
|
|||
|
|
@ -79,6 +79,8 @@ struct cfg80211_registered_device {
|
|||
/* netlink port which started critical protocol (0 means not started) */
|
||||
u32 crit_proto_nlportid;
|
||||
|
||||
struct cfg80211_coalesce *coalesce;
|
||||
|
||||
/* must be last because of the way we do wiphy_priv(),
|
||||
* and it should at least be aligned to NETDEV_ALIGN */
|
||||
struct wiphy wiphy __aligned(NETDEV_ALIGN);
|
||||
|
|
|
|||
|
|
@ -167,9 +167,12 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
|
|||
* basic rates
|
||||
*/
|
||||
if (!setup->basic_rates) {
|
||||
enum nl80211_bss_scan_width scan_width;
|
||||
struct ieee80211_supported_band *sband =
|
||||
rdev->wiphy.bands[setup->chandef.chan->band];
|
||||
setup->basic_rates = ieee80211_mandatory_rates(sband);
|
||||
scan_width = cfg80211_chandef_to_scan_width(&setup->chandef);
|
||||
setup->basic_rates = ieee80211_mandatory_rates(sband,
|
||||
scan_width);
|
||||
}
|
||||
|
||||
if (!cfg80211_reg_can_beacon(&rdev->wiphy, &setup->chandef))
|
||||
|
|
|
|||
|
|
@ -621,7 +621,7 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
|
|||
}
|
||||
|
||||
bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_mbm,
|
||||
const u8 *buf, size_t len, gfp_t gfp)
|
||||
const u8 *buf, size_t len, u32 flags, gfp_t gfp)
|
||||
{
|
||||
struct wiphy *wiphy = wdev->wiphy;
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
|
||||
|
|
@ -664,7 +664,7 @@ bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_mbm,
|
|||
/* Indicate the received Action frame to user space */
|
||||
if (nl80211_send_mgmt(rdev, wdev, reg->nlportid,
|
||||
freq, sig_mbm,
|
||||
buf, len, gfp))
|
||||
buf, len, flags, gfp))
|
||||
continue;
|
||||
|
||||
result = true;
|
||||
|
|
|
|||
|
|
@ -349,6 +349,11 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
|
|||
[NL80211_ATTR_IE_RIC] = { .type = NLA_BINARY,
|
||||
.len = IEEE80211_MAX_DATA_LEN },
|
||||
[NL80211_ATTR_PEER_AID] = { .type = NLA_U16 },
|
||||
[NL80211_ATTR_CH_SWITCH_COUNT] = { .type = NLA_U32 },
|
||||
[NL80211_ATTR_CH_SWITCH_BLOCK_TX] = { .type = NLA_FLAG },
|
||||
[NL80211_ATTR_CSA_IES] = { .type = NLA_NESTED },
|
||||
[NL80211_ATTR_CSA_C_OFF_BEACON] = { .type = NLA_U16 },
|
||||
[NL80211_ATTR_CSA_C_OFF_PRESP] = { .type = NLA_U16 },
|
||||
};
|
||||
|
||||
/* policy for the key attributes */
|
||||
|
|
@ -403,6 +408,14 @@ nl80211_wowlan_tcp_policy[NUM_NL80211_WOWLAN_TCP] = {
|
|||
[NL80211_WOWLAN_TCP_WAKE_MASK] = { .len = 1 },
|
||||
};
|
||||
|
||||
/* policy for coalesce rule attributes */
|
||||
static const struct nla_policy
|
||||
nl80211_coalesce_policy[NUM_NL80211_ATTR_COALESCE_RULE] = {
|
||||
[NL80211_ATTR_COALESCE_RULE_DELAY] = { .type = NLA_U32 },
|
||||
[NL80211_ATTR_COALESCE_RULE_CONDITION] = { .type = NLA_U32 },
|
||||
[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN] = { .type = NLA_NESTED },
|
||||
};
|
||||
|
||||
/* policy for GTK rekey offload attributes */
|
||||
static const struct nla_policy
|
||||
nl80211_rekey_policy[NUM_NL80211_REKEY_DATA] = {
|
||||
|
|
@ -976,7 +989,7 @@ static int nl80211_send_wowlan(struct sk_buff *msg,
|
|||
return -ENOBUFS;
|
||||
|
||||
if (dev->wiphy.wowlan->n_patterns) {
|
||||
struct nl80211_wowlan_pattern_support pat = {
|
||||
struct nl80211_pattern_support pat = {
|
||||
.max_patterns = dev->wiphy.wowlan->n_patterns,
|
||||
.min_pattern_len = dev->wiphy.wowlan->pattern_min_len,
|
||||
.max_pattern_len = dev->wiphy.wowlan->pattern_max_len,
|
||||
|
|
@ -997,6 +1010,27 @@ static int nl80211_send_wowlan(struct sk_buff *msg,
|
|||
}
|
||||
#endif
|
||||
|
||||
static int nl80211_send_coalesce(struct sk_buff *msg,
|
||||
struct cfg80211_registered_device *dev)
|
||||
{
|
||||
struct nl80211_coalesce_rule_support rule;
|
||||
|
||||
if (!dev->wiphy.coalesce)
|
||||
return 0;
|
||||
|
||||
rule.max_rules = dev->wiphy.coalesce->n_rules;
|
||||
rule.max_delay = dev->wiphy.coalesce->max_delay;
|
||||
rule.pat.max_patterns = dev->wiphy.coalesce->n_patterns;
|
||||
rule.pat.min_pattern_len = dev->wiphy.coalesce->pattern_min_len;
|
||||
rule.pat.max_pattern_len = dev->wiphy.coalesce->pattern_max_len;
|
||||
rule.pat.max_pkt_offset = dev->wiphy.coalesce->max_pkt_offset;
|
||||
|
||||
if (nla_put(msg, NL80211_ATTR_COALESCE_RULE, sizeof(rule), &rule))
|
||||
return -ENOBUFS;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nl80211_send_band_rateinfo(struct sk_buff *msg,
|
||||
struct ieee80211_supported_band *sband)
|
||||
{
|
||||
|
|
@ -1395,6 +1429,8 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
|
|||
if (state->split) {
|
||||
CMD(crit_proto_start, CRIT_PROTOCOL_START);
|
||||
CMD(crit_proto_stop, CRIT_PROTOCOL_STOP);
|
||||
if (dev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH)
|
||||
CMD(channel_switch, CHANNEL_SWITCH);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NL80211_TESTMODE
|
||||
|
|
@ -1515,6 +1551,12 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
|
|||
dev->wiphy.vht_capa_mod_mask))
|
||||
goto nla_put_failure;
|
||||
|
||||
state->split_start++;
|
||||
break;
|
||||
case 10:
|
||||
if (nl80211_send_coalesce(msg, dev))
|
||||
goto nla_put_failure;
|
||||
|
||||
/* done */
|
||||
state->split_start = 0;
|
||||
break;
|
||||
|
|
@ -5580,6 +5622,111 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
|
|||
return err;
|
||||
}
|
||||
|
||||
static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||
struct net_device *dev = info->user_ptr[1];
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
struct cfg80211_csa_settings params;
|
||||
/* csa_attrs is defined static to avoid waste of stack size - this
|
||||
* function is called under RTNL lock, so this should not be a problem.
|
||||
*/
|
||||
static struct nlattr *csa_attrs[NL80211_ATTR_MAX+1];
|
||||
u8 radar_detect_width = 0;
|
||||
int err;
|
||||
|
||||
if (!rdev->ops->channel_switch ||
|
||||
!(rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* may add IBSS support later */
|
||||
if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
|
||||
dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
|
||||
if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] ||
|
||||
!info->attrs[NL80211_ATTR_CH_SWITCH_COUNT])
|
||||
return -EINVAL;
|
||||
|
||||
/* only important for AP, IBSS and mesh create IEs internally */
|
||||
if (!info->attrs[NL80211_ATTR_CSA_IES])
|
||||
return -EINVAL;
|
||||
|
||||
/* useless if AP is not running */
|
||||
if (!wdev->beacon_interval)
|
||||
return -EINVAL;
|
||||
|
||||
params.count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]);
|
||||
|
||||
err = nl80211_parse_beacon(info->attrs, ¶ms.beacon_after);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = nla_parse_nested(csa_attrs, NL80211_ATTR_MAX,
|
||||
info->attrs[NL80211_ATTR_CSA_IES],
|
||||
nl80211_policy);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = nl80211_parse_beacon(csa_attrs, ¶ms.beacon_csa);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON])
|
||||
return -EINVAL;
|
||||
|
||||
params.counter_offset_beacon =
|
||||
nla_get_u16(csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON]);
|
||||
if (params.counter_offset_beacon >= params.beacon_csa.tail_len)
|
||||
return -EINVAL;
|
||||
|
||||
/* sanity check - counters should be the same */
|
||||
if (params.beacon_csa.tail[params.counter_offset_beacon] !=
|
||||
params.count)
|
||||
return -EINVAL;
|
||||
|
||||
if (csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]) {
|
||||
params.counter_offset_presp =
|
||||
nla_get_u16(csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]);
|
||||
if (params.counter_offset_presp >=
|
||||
params.beacon_csa.probe_resp_len)
|
||||
return -EINVAL;
|
||||
|
||||
if (params.beacon_csa.probe_resp[params.counter_offset_presp] !=
|
||||
params.count)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = nl80211_parse_chandef(rdev, info, ¶ms.chandef);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!cfg80211_reg_can_beacon(&rdev->wiphy, ¶ms.chandef))
|
||||
return -EINVAL;
|
||||
|
||||
err = cfg80211_chandef_dfs_required(wdev->wiphy, ¶ms.chandef);
|
||||
if (err < 0) {
|
||||
return err;
|
||||
} else if (err) {
|
||||
radar_detect_width = BIT(params.chandef.width);
|
||||
params.radar_required = true;
|
||||
}
|
||||
|
||||
err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,
|
||||
params.chandef.chan,
|
||||
CHAN_MODE_SHARED,
|
||||
radar_detect_width);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (info->attrs[NL80211_ATTR_CH_SWITCH_BLOCK_TX])
|
||||
params.block_tx = true;
|
||||
|
||||
return rdev_channel_switch(rdev, dev, ¶ms);
|
||||
}
|
||||
|
||||
static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
|
||||
u32 seq, int flags,
|
||||
struct cfg80211_registered_device *rdev,
|
||||
|
|
@ -5641,6 +5788,7 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
|
|||
goto nla_put_failure;
|
||||
if (nla_put_u16(msg, NL80211_BSS_CAPABILITY, res->capability) ||
|
||||
nla_put_u32(msg, NL80211_BSS_FREQUENCY, res->channel->center_freq) ||
|
||||
nla_put_u32(msg, NL80211_BSS_CHAN_WIDTH, res->scan_width) ||
|
||||
nla_put_u32(msg, NL80211_BSS_SEEN_MS_AGO,
|
||||
jiffies_to_msecs(jiffies - intbss->ts)))
|
||||
goto nla_put_failure;
|
||||
|
|
@ -6321,6 +6469,8 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
|
|||
return -EINVAL;
|
||||
|
||||
switch (ibss.chandef.width) {
|
||||
case NL80211_CHAN_WIDTH_5:
|
||||
case NL80211_CHAN_WIDTH_10:
|
||||
case NL80211_CHAN_WIDTH_20_NOHT:
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_20:
|
||||
|
|
@ -6348,6 +6498,19 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
|
|||
return err;
|
||||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
|
||||
memcpy(&ibss.ht_capa_mask,
|
||||
nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]),
|
||||
sizeof(ibss.ht_capa_mask));
|
||||
|
||||
if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
|
||||
if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
|
||||
return -EINVAL;
|
||||
memcpy(&ibss.ht_capa,
|
||||
nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]),
|
||||
sizeof(ibss.ht_capa));
|
||||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_MCAST_RATE] &&
|
||||
!nl80211_parse_mcast_rate(rdev, ibss.mcast_rate,
|
||||
nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE])))
|
||||
|
|
@ -6430,19 +6593,30 @@ static struct genl_multicast_group nl80211_testmode_mcgrp = {
|
|||
static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||
struct wireless_dev *wdev =
|
||||
__cfg80211_wdev_from_attrs(genl_info_net(info), info->attrs);
|
||||
int err;
|
||||
|
||||
if (!rdev->ops->testmode_cmd)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (IS_ERR(wdev)) {
|
||||
err = PTR_ERR(wdev);
|
||||
if (err != -EINVAL)
|
||||
return err;
|
||||
wdev = NULL;
|
||||
} else if (wdev->wiphy != &rdev->wiphy) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!info->attrs[NL80211_ATTR_TESTDATA])
|
||||
return -EINVAL;
|
||||
|
||||
err = -EOPNOTSUPP;
|
||||
if (rdev->ops->testmode_cmd) {
|
||||
rdev->testmode_info = info;
|
||||
err = rdev_testmode_cmd(rdev,
|
||||
rdev->testmode_info = info;
|
||||
err = rdev_testmode_cmd(rdev, wdev,
|
||||
nla_data(info->attrs[NL80211_ATTR_TESTDATA]),
|
||||
nla_len(info->attrs[NL80211_ATTR_TESTDATA]));
|
||||
rdev->testmode_info = NULL;
|
||||
}
|
||||
rdev->testmode_info = NULL;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
@ -7404,14 +7578,12 @@ static int nl80211_set_cqm_txe(struct genl_info *info,
|
|||
u32 rate, u32 pkts, u32 intvl)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||
struct wireless_dev *wdev;
|
||||
struct net_device *dev = info->user_ptr[1];
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
|
||||
if (rate > 100 || intvl > NL80211_CQM_TXE_MAX_INTVL)
|
||||
return -EINVAL;
|
||||
|
||||
wdev = dev->ieee80211_ptr;
|
||||
|
||||
if (!rdev->ops->set_cqm_txe_config)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
|
|
@ -7426,13 +7598,15 @@ static int nl80211_set_cqm_rssi(struct genl_info *info,
|
|||
s32 threshold, u32 hysteresis)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||
struct wireless_dev *wdev;
|
||||
struct net_device *dev = info->user_ptr[1];
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
|
||||
if (threshold > 0)
|
||||
return -EINVAL;
|
||||
|
||||
wdev = dev->ieee80211_ptr;
|
||||
/* disabling - hysteresis should also be zero then */
|
||||
if (threshold == 0)
|
||||
hysteresis = 0;
|
||||
|
||||
if (!rdev->ops->set_cqm_rssi_config)
|
||||
return -EOPNOTSUPP;
|
||||
|
|
@ -7451,36 +7625,33 @@ static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info)
|
|||
int err;
|
||||
|
||||
cqm = info->attrs[NL80211_ATTR_CQM];
|
||||
if (!cqm) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (!cqm)
|
||||
return -EINVAL;
|
||||
|
||||
err = nla_parse_nested(attrs, NL80211_ATTR_CQM_MAX, cqm,
|
||||
nl80211_attr_cqm_policy);
|
||||
if (err)
|
||||
goto out;
|
||||
return err;
|
||||
|
||||
if (attrs[NL80211_ATTR_CQM_RSSI_THOLD] &&
|
||||
attrs[NL80211_ATTR_CQM_RSSI_HYST]) {
|
||||
s32 threshold;
|
||||
u32 hysteresis;
|
||||
threshold = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
|
||||
hysteresis = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_HYST]);
|
||||
err = nl80211_set_cqm_rssi(info, threshold, hysteresis);
|
||||
} else if (attrs[NL80211_ATTR_CQM_TXE_RATE] &&
|
||||
attrs[NL80211_ATTR_CQM_TXE_PKTS] &&
|
||||
attrs[NL80211_ATTR_CQM_TXE_INTVL]) {
|
||||
u32 rate, pkts, intvl;
|
||||
rate = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_RATE]);
|
||||
pkts = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_PKTS]);
|
||||
intvl = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_INTVL]);
|
||||
err = nl80211_set_cqm_txe(info, rate, pkts, intvl);
|
||||
} else
|
||||
err = -EINVAL;
|
||||
s32 threshold = nla_get_s32(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
|
||||
u32 hysteresis = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_HYST]);
|
||||
|
||||
out:
|
||||
return err;
|
||||
return nl80211_set_cqm_rssi(info, threshold, hysteresis);
|
||||
}
|
||||
|
||||
if (attrs[NL80211_ATTR_CQM_TXE_RATE] &&
|
||||
attrs[NL80211_ATTR_CQM_TXE_PKTS] &&
|
||||
attrs[NL80211_ATTR_CQM_TXE_INTVL]) {
|
||||
u32 rate = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_RATE]);
|
||||
u32 pkts = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_PKTS]);
|
||||
u32 intvl = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_INTVL]);
|
||||
|
||||
return nl80211_set_cqm_txe(info, rate, pkts, intvl);
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info)
|
||||
|
|
@ -7596,12 +7767,11 @@ static int nl80211_send_wowlan_patterns(struct sk_buff *msg,
|
|||
if (!nl_pat)
|
||||
return -ENOBUFS;
|
||||
pat_len = wowlan->patterns[i].pattern_len;
|
||||
if (nla_put(msg, NL80211_WOWLAN_PKTPAT_MASK,
|
||||
DIV_ROUND_UP(pat_len, 8),
|
||||
if (nla_put(msg, NL80211_PKTPAT_MASK, DIV_ROUND_UP(pat_len, 8),
|
||||
wowlan->patterns[i].mask) ||
|
||||
nla_put(msg, NL80211_WOWLAN_PKTPAT_PATTERN,
|
||||
pat_len, wowlan->patterns[i].pattern) ||
|
||||
nla_put_u32(msg, NL80211_WOWLAN_PKTPAT_OFFSET,
|
||||
nla_put(msg, NL80211_PKTPAT_PATTERN, pat_len,
|
||||
wowlan->patterns[i].pattern) ||
|
||||
nla_put_u32(msg, NL80211_PKTPAT_OFFSET,
|
||||
wowlan->patterns[i].pkt_offset))
|
||||
return -ENOBUFS;
|
||||
nla_nest_end(msg, nl_pat);
|
||||
|
|
@ -7942,7 +8112,7 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
|
|||
struct nlattr *pat;
|
||||
int n_patterns = 0;
|
||||
int rem, pat_len, mask_len, pkt_offset;
|
||||
struct nlattr *pat_tb[NUM_NL80211_WOWLAN_PKTPAT];
|
||||
struct nlattr *pat_tb[NUM_NL80211_PKTPAT];
|
||||
|
||||
nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN],
|
||||
rem)
|
||||
|
|
@ -7961,26 +8131,25 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
|
|||
|
||||
nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN],
|
||||
rem) {
|
||||
nla_parse(pat_tb, MAX_NL80211_WOWLAN_PKTPAT,
|
||||
nla_data(pat), nla_len(pat), NULL);
|
||||
nla_parse(pat_tb, MAX_NL80211_PKTPAT, nla_data(pat),
|
||||
nla_len(pat), NULL);
|
||||
err = -EINVAL;
|
||||
if (!pat_tb[NL80211_WOWLAN_PKTPAT_MASK] ||
|
||||
!pat_tb[NL80211_WOWLAN_PKTPAT_PATTERN])
|
||||
if (!pat_tb[NL80211_PKTPAT_MASK] ||
|
||||
!pat_tb[NL80211_PKTPAT_PATTERN])
|
||||
goto error;
|
||||
pat_len = nla_len(pat_tb[NL80211_WOWLAN_PKTPAT_PATTERN]);
|
||||
pat_len = nla_len(pat_tb[NL80211_PKTPAT_PATTERN]);
|
||||
mask_len = DIV_ROUND_UP(pat_len, 8);
|
||||
if (nla_len(pat_tb[NL80211_WOWLAN_PKTPAT_MASK]) !=
|
||||
mask_len)
|
||||
if (nla_len(pat_tb[NL80211_PKTPAT_MASK]) != mask_len)
|
||||
goto error;
|
||||
if (pat_len > wowlan->pattern_max_len ||
|
||||
pat_len < wowlan->pattern_min_len)
|
||||
goto error;
|
||||
|
||||
if (!pat_tb[NL80211_WOWLAN_PKTPAT_OFFSET])
|
||||
if (!pat_tb[NL80211_PKTPAT_OFFSET])
|
||||
pkt_offset = 0;
|
||||
else
|
||||
pkt_offset = nla_get_u32(
|
||||
pat_tb[NL80211_WOWLAN_PKTPAT_OFFSET]);
|
||||
pat_tb[NL80211_PKTPAT_OFFSET]);
|
||||
if (pkt_offset > wowlan->max_pkt_offset)
|
||||
goto error;
|
||||
new_triggers.patterns[i].pkt_offset = pkt_offset;
|
||||
|
|
@ -7994,11 +8163,11 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
|
|||
new_triggers.patterns[i].pattern =
|
||||
new_triggers.patterns[i].mask + mask_len;
|
||||
memcpy(new_triggers.patterns[i].mask,
|
||||
nla_data(pat_tb[NL80211_WOWLAN_PKTPAT_MASK]),
|
||||
nla_data(pat_tb[NL80211_PKTPAT_MASK]),
|
||||
mask_len);
|
||||
new_triggers.patterns[i].pattern_len = pat_len;
|
||||
memcpy(new_triggers.patterns[i].pattern,
|
||||
nla_data(pat_tb[NL80211_WOWLAN_PKTPAT_PATTERN]),
|
||||
nla_data(pat_tb[NL80211_PKTPAT_PATTERN]),
|
||||
pat_len);
|
||||
i++;
|
||||
}
|
||||
|
|
@ -8037,6 +8206,264 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
|
|||
}
|
||||
#endif
|
||||
|
||||
static int nl80211_send_coalesce_rules(struct sk_buff *msg,
|
||||
struct cfg80211_registered_device *rdev)
|
||||
{
|
||||
struct nlattr *nl_pats, *nl_pat, *nl_rule, *nl_rules;
|
||||
int i, j, pat_len;
|
||||
struct cfg80211_coalesce_rules *rule;
|
||||
|
||||
if (!rdev->coalesce->n_rules)
|
||||
return 0;
|
||||
|
||||
nl_rules = nla_nest_start(msg, NL80211_ATTR_COALESCE_RULE);
|
||||
if (!nl_rules)
|
||||
return -ENOBUFS;
|
||||
|
||||
for (i = 0; i < rdev->coalesce->n_rules; i++) {
|
||||
nl_rule = nla_nest_start(msg, i + 1);
|
||||
if (!nl_rule)
|
||||
return -ENOBUFS;
|
||||
|
||||
rule = &rdev->coalesce->rules[i];
|
||||
if (nla_put_u32(msg, NL80211_ATTR_COALESCE_RULE_DELAY,
|
||||
rule->delay))
|
||||
return -ENOBUFS;
|
||||
|
||||
if (nla_put_u32(msg, NL80211_ATTR_COALESCE_RULE_CONDITION,
|
||||
rule->condition))
|
||||
return -ENOBUFS;
|
||||
|
||||
nl_pats = nla_nest_start(msg,
|
||||
NL80211_ATTR_COALESCE_RULE_PKT_PATTERN);
|
||||
if (!nl_pats)
|
||||
return -ENOBUFS;
|
||||
|
||||
for (j = 0; j < rule->n_patterns; j++) {
|
||||
nl_pat = nla_nest_start(msg, j + 1);
|
||||
if (!nl_pat)
|
||||
return -ENOBUFS;
|
||||
pat_len = rule->patterns[j].pattern_len;
|
||||
if (nla_put(msg, NL80211_PKTPAT_MASK,
|
||||
DIV_ROUND_UP(pat_len, 8),
|
||||
rule->patterns[j].mask) ||
|
||||
nla_put(msg, NL80211_PKTPAT_PATTERN, pat_len,
|
||||
rule->patterns[j].pattern) ||
|
||||
nla_put_u32(msg, NL80211_PKTPAT_OFFSET,
|
||||
rule->patterns[j].pkt_offset))
|
||||
return -ENOBUFS;
|
||||
nla_nest_end(msg, nl_pat);
|
||||
}
|
||||
nla_nest_end(msg, nl_pats);
|
||||
nla_nest_end(msg, nl_rule);
|
||||
}
|
||||
nla_nest_end(msg, nl_rules);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nl80211_get_coalesce(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||
struct sk_buff *msg;
|
||||
void *hdr;
|
||||
|
||||
if (!rdev->wiphy.coalesce)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
||||
if (!msg)
|
||||
return -ENOMEM;
|
||||
|
||||
hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
|
||||
NL80211_CMD_GET_COALESCE);
|
||||
if (!hdr)
|
||||
goto nla_put_failure;
|
||||
|
||||
if (rdev->coalesce && nl80211_send_coalesce_rules(msg, rdev))
|
||||
goto nla_put_failure;
|
||||
|
||||
genlmsg_end(msg, hdr);
|
||||
return genlmsg_reply(msg, info);
|
||||
|
||||
nla_put_failure:
|
||||
nlmsg_free(msg);
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
void cfg80211_rdev_free_coalesce(struct cfg80211_registered_device *rdev)
|
||||
{
|
||||
struct cfg80211_coalesce *coalesce = rdev->coalesce;
|
||||
int i, j;
|
||||
struct cfg80211_coalesce_rules *rule;
|
||||
|
||||
if (!coalesce)
|
||||
return;
|
||||
|
||||
for (i = 0; i < coalesce->n_rules; i++) {
|
||||
rule = &coalesce->rules[i];
|
||||
for (j = 0; j < rule->n_patterns; j++)
|
||||
kfree(rule->patterns[j].mask);
|
||||
kfree(rule->patterns);
|
||||
}
|
||||
kfree(coalesce->rules);
|
||||
kfree(coalesce);
|
||||
rdev->coalesce = NULL;
|
||||
}
|
||||
|
||||
static int nl80211_parse_coalesce_rule(struct cfg80211_registered_device *rdev,
|
||||
struct nlattr *rule,
|
||||
struct cfg80211_coalesce_rules *new_rule)
|
||||
{
|
||||
int err, i;
|
||||
const struct wiphy_coalesce_support *coalesce = rdev->wiphy.coalesce;
|
||||
struct nlattr *tb[NUM_NL80211_ATTR_COALESCE_RULE], *pat;
|
||||
int rem, pat_len, mask_len, pkt_offset, n_patterns = 0;
|
||||
struct nlattr *pat_tb[NUM_NL80211_PKTPAT];
|
||||
|
||||
err = nla_parse(tb, NL80211_ATTR_COALESCE_RULE_MAX, nla_data(rule),
|
||||
nla_len(rule), nl80211_coalesce_policy);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (tb[NL80211_ATTR_COALESCE_RULE_DELAY])
|
||||
new_rule->delay =
|
||||
nla_get_u32(tb[NL80211_ATTR_COALESCE_RULE_DELAY]);
|
||||
if (new_rule->delay > coalesce->max_delay)
|
||||
return -EINVAL;
|
||||
|
||||
if (tb[NL80211_ATTR_COALESCE_RULE_CONDITION])
|
||||
new_rule->condition =
|
||||
nla_get_u32(tb[NL80211_ATTR_COALESCE_RULE_CONDITION]);
|
||||
if (new_rule->condition != NL80211_COALESCE_CONDITION_MATCH &&
|
||||
new_rule->condition != NL80211_COALESCE_CONDITION_NO_MATCH)
|
||||
return -EINVAL;
|
||||
|
||||
if (!tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN])
|
||||
return -EINVAL;
|
||||
|
||||
nla_for_each_nested(pat, tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN],
|
||||
rem)
|
||||
n_patterns++;
|
||||
if (n_patterns > coalesce->n_patterns)
|
||||
return -EINVAL;
|
||||
|
||||
new_rule->patterns = kcalloc(n_patterns, sizeof(new_rule->patterns[0]),
|
||||
GFP_KERNEL);
|
||||
if (!new_rule->patterns)
|
||||
return -ENOMEM;
|
||||
|
||||
new_rule->n_patterns = n_patterns;
|
||||
i = 0;
|
||||
|
||||
nla_for_each_nested(pat, tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN],
|
||||
rem) {
|
||||
nla_parse(pat_tb, MAX_NL80211_PKTPAT, nla_data(pat),
|
||||
nla_len(pat), NULL);
|
||||
if (!pat_tb[NL80211_PKTPAT_MASK] ||
|
||||
!pat_tb[NL80211_PKTPAT_PATTERN])
|
||||
return -EINVAL;
|
||||
pat_len = nla_len(pat_tb[NL80211_PKTPAT_PATTERN]);
|
||||
mask_len = DIV_ROUND_UP(pat_len, 8);
|
||||
if (nla_len(pat_tb[NL80211_PKTPAT_MASK]) != mask_len)
|
||||
return -EINVAL;
|
||||
if (pat_len > coalesce->pattern_max_len ||
|
||||
pat_len < coalesce->pattern_min_len)
|
||||
return -EINVAL;
|
||||
|
||||
if (!pat_tb[NL80211_PKTPAT_OFFSET])
|
||||
pkt_offset = 0;
|
||||
else
|
||||
pkt_offset = nla_get_u32(pat_tb[NL80211_PKTPAT_OFFSET]);
|
||||
if (pkt_offset > coalesce->max_pkt_offset)
|
||||
return -EINVAL;
|
||||
new_rule->patterns[i].pkt_offset = pkt_offset;
|
||||
|
||||
new_rule->patterns[i].mask =
|
||||
kmalloc(mask_len + pat_len, GFP_KERNEL);
|
||||
if (!new_rule->patterns[i].mask)
|
||||
return -ENOMEM;
|
||||
new_rule->patterns[i].pattern =
|
||||
new_rule->patterns[i].mask + mask_len;
|
||||
memcpy(new_rule->patterns[i].mask,
|
||||
nla_data(pat_tb[NL80211_PKTPAT_MASK]), mask_len);
|
||||
new_rule->patterns[i].pattern_len = pat_len;
|
||||
memcpy(new_rule->patterns[i].pattern,
|
||||
nla_data(pat_tb[NL80211_PKTPAT_PATTERN]), pat_len);
|
||||
i++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nl80211_set_coalesce(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||
const struct wiphy_coalesce_support *coalesce = rdev->wiphy.coalesce;
|
||||
struct cfg80211_coalesce new_coalesce = {};
|
||||
struct cfg80211_coalesce *n_coalesce;
|
||||
int err, rem_rule, n_rules = 0, i, j;
|
||||
struct nlattr *rule;
|
||||
struct cfg80211_coalesce_rules *tmp_rule;
|
||||
|
||||
if (!rdev->wiphy.coalesce || !rdev->ops->set_coalesce)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!info->attrs[NL80211_ATTR_COALESCE_RULE]) {
|
||||
cfg80211_rdev_free_coalesce(rdev);
|
||||
rdev->ops->set_coalesce(&rdev->wiphy, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
nla_for_each_nested(rule, info->attrs[NL80211_ATTR_COALESCE_RULE],
|
||||
rem_rule)
|
||||
n_rules++;
|
||||
if (n_rules > coalesce->n_rules)
|
||||
return -EINVAL;
|
||||
|
||||
new_coalesce.rules = kcalloc(n_rules, sizeof(new_coalesce.rules[0]),
|
||||
GFP_KERNEL);
|
||||
if (!new_coalesce.rules)
|
||||
return -ENOMEM;
|
||||
|
||||
new_coalesce.n_rules = n_rules;
|
||||
i = 0;
|
||||
|
||||
nla_for_each_nested(rule, info->attrs[NL80211_ATTR_COALESCE_RULE],
|
||||
rem_rule) {
|
||||
err = nl80211_parse_coalesce_rule(rdev, rule,
|
||||
&new_coalesce.rules[i]);
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
err = rdev->ops->set_coalesce(&rdev->wiphy, &new_coalesce);
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
n_coalesce = kmemdup(&new_coalesce, sizeof(new_coalesce), GFP_KERNEL);
|
||||
if (!n_coalesce) {
|
||||
err = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
cfg80211_rdev_free_coalesce(rdev);
|
||||
rdev->coalesce = n_coalesce;
|
||||
|
||||
return 0;
|
||||
error:
|
||||
for (i = 0; i < new_coalesce.n_rules; i++) {
|
||||
tmp_rule = &new_coalesce.rules[i];
|
||||
for (j = 0; j < tmp_rule->n_patterns; j++)
|
||||
kfree(tmp_rule->patterns[j].mask);
|
||||
kfree(tmp_rule->patterns);
|
||||
}
|
||||
kfree(new_coalesce.rules);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||
|
|
@ -9043,7 +9470,30 @@ static struct genl_ops nl80211_ops[] = {
|
|||
.flags = GENL_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_WDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
}
|
||||
},
|
||||
{
|
||||
.cmd = NL80211_CMD_GET_COALESCE,
|
||||
.doit = nl80211_get_coalesce,
|
||||
.policy = nl80211_policy,
|
||||
.internal_flags = NL80211_FLAG_NEED_WIPHY |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
{
|
||||
.cmd = NL80211_CMD_SET_COALESCE,
|
||||
.doit = nl80211_set_coalesce,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_WIPHY |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
{
|
||||
.cmd = NL80211_CMD_CHANNEL_SWITCH,
|
||||
.doit = nl80211_channel_switch,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
};
|
||||
|
||||
static struct genl_multicast_group nl80211_mlme_mcgrp = {
|
||||
|
|
@ -10000,7 +10450,7 @@ EXPORT_SYMBOL(cfg80211_rx_unexpected_4addr_frame);
|
|||
int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
|
||||
struct wireless_dev *wdev, u32 nlportid,
|
||||
int freq, int sig_dbm,
|
||||
const u8 *buf, size_t len, gfp_t gfp)
|
||||
const u8 *buf, size_t len, u32 flags, gfp_t gfp)
|
||||
{
|
||||
struct net_device *netdev = wdev->netdev;
|
||||
struct sk_buff *msg;
|
||||
|
|
@ -10023,7 +10473,9 @@ int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
|
|||
nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq) ||
|
||||
(sig_dbm &&
|
||||
nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) ||
|
||||
nla_put(msg, NL80211_ATTR_FRAME, len, buf))
|
||||
nla_put(msg, NL80211_ATTR_FRAME, len, buf) ||
|
||||
(flags &&
|
||||
nla_put_u32(msg, NL80211_ATTR_RXMGMT_FLAGS, flags)))
|
||||
goto nla_put_failure;
|
||||
|
||||
genlmsg_end(msg, hdr);
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev,
|
|||
int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
|
||||
struct wireless_dev *wdev, u32 nlpid,
|
||||
int freq, int sig_dbm,
|
||||
const u8 *buf, size_t len, gfp_t gfp);
|
||||
const u8 *buf, size_t len, u32 flags, gfp_t gfp);
|
||||
|
||||
void
|
||||
nl80211_radar_notify(struct cfg80211_registered_device *rdev,
|
||||
|
|
@ -74,4 +74,6 @@ nl80211_radar_notify(struct cfg80211_registered_device *rdev,
|
|||
enum nl80211_radar_event event,
|
||||
struct net_device *netdev, gfp_t gfp);
|
||||
|
||||
void cfg80211_rdev_free_coalesce(struct cfg80211_registered_device *rdev);
|
||||
|
||||
#endif /* __NET_WIRELESS_NL80211_H */
|
||||
|
|
|
|||
|
|
@ -516,11 +516,12 @@ static inline void rdev_rfkill_poll(struct cfg80211_registered_device *rdev)
|
|||
|
||||
#ifdef CONFIG_NL80211_TESTMODE
|
||||
static inline int rdev_testmode_cmd(struct cfg80211_registered_device *rdev,
|
||||
struct wireless_dev *wdev,
|
||||
void *data, int len)
|
||||
{
|
||||
int ret;
|
||||
trace_rdev_testmode_cmd(&rdev->wiphy);
|
||||
ret = rdev->ops->testmode_cmd(&rdev->wiphy, data, len);
|
||||
trace_rdev_testmode_cmd(&rdev->wiphy, wdev);
|
||||
ret = rdev->ops->testmode_cmd(&rdev->wiphy, wdev, data, len);
|
||||
trace_rdev_return_int(&rdev->wiphy, ret);
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -923,4 +924,16 @@ static inline void rdev_crit_proto_stop(struct cfg80211_registered_device *rdev,
|
|||
trace_rdev_return_void(&rdev->wiphy);
|
||||
}
|
||||
|
||||
static inline int rdev_channel_switch(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev,
|
||||
struct cfg80211_csa_settings *params)
|
||||
{
|
||||
int ret;
|
||||
|
||||
trace_rdev_channel_switch(&rdev->wiphy, dev, params);
|
||||
ret = rdev->ops->channel_switch(&rdev->wiphy, dev, params);
|
||||
trace_rdev_return_int(&rdev->wiphy, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* __CFG80211_RDEV_OPS */
|
||||
|
|
|
|||
|
|
@ -465,10 +465,6 @@ static int cmp_bss(struct cfg80211_bss *a,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* we can't use compare_ether_addr here since we need a < > operator.
|
||||
* The binary return value of compare_ether_addr isn't enough
|
||||
*/
|
||||
r = memcmp(a->bssid, b->bssid, sizeof(a->bssid));
|
||||
if (r)
|
||||
return r;
|
||||
|
|
@ -651,6 +647,8 @@ static bool cfg80211_combine_bsses(struct cfg80211_registered_device *dev,
|
|||
continue;
|
||||
if (bss->pub.channel != new->pub.channel)
|
||||
continue;
|
||||
if (bss->pub.scan_width != new->pub.scan_width)
|
||||
continue;
|
||||
if (rcu_access_pointer(bss->pub.beacon_ies))
|
||||
continue;
|
||||
ies = rcu_access_pointer(bss->pub.ies);
|
||||
|
|
@ -870,11 +868,12 @@ cfg80211_get_bss_channel(struct wiphy *wiphy, const u8 *ie, size_t ielen,
|
|||
|
||||
/* Returned bss is reference counted and must be cleaned up appropriately. */
|
||||
struct cfg80211_bss*
|
||||
cfg80211_inform_bss(struct wiphy *wiphy,
|
||||
struct ieee80211_channel *channel,
|
||||
const u8 *bssid, u64 tsf, u16 capability,
|
||||
u16 beacon_interval, const u8 *ie, size_t ielen,
|
||||
s32 signal, gfp_t gfp)
|
||||
cfg80211_inform_bss_width(struct wiphy *wiphy,
|
||||
struct ieee80211_channel *channel,
|
||||
enum nl80211_bss_scan_width scan_width,
|
||||
const u8 *bssid, u64 tsf, u16 capability,
|
||||
u16 beacon_interval, const u8 *ie, size_t ielen,
|
||||
s32 signal, gfp_t gfp)
|
||||
{
|
||||
struct cfg80211_bss_ies *ies;
|
||||
struct cfg80211_internal_bss tmp = {}, *res;
|
||||
|
|
@ -892,6 +891,7 @@ cfg80211_inform_bss(struct wiphy *wiphy,
|
|||
|
||||
memcpy(tmp.pub.bssid, bssid, ETH_ALEN);
|
||||
tmp.pub.channel = channel;
|
||||
tmp.pub.scan_width = scan_width;
|
||||
tmp.pub.signal = signal;
|
||||
tmp.pub.beacon_interval = beacon_interval;
|
||||
tmp.pub.capability = capability;
|
||||
|
|
@ -924,14 +924,15 @@ cfg80211_inform_bss(struct wiphy *wiphy,
|
|||
/* cfg80211_bss_update gives us a referenced result */
|
||||
return &res->pub;
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_inform_bss);
|
||||
EXPORT_SYMBOL(cfg80211_inform_bss_width);
|
||||
|
||||
/* Returned bss is reference counted and must be cleaned up appropriately. */
|
||||
struct cfg80211_bss *
|
||||
cfg80211_inform_bss_frame(struct wiphy *wiphy,
|
||||
struct ieee80211_channel *channel,
|
||||
struct ieee80211_mgmt *mgmt, size_t len,
|
||||
s32 signal, gfp_t gfp)
|
||||
cfg80211_inform_bss_width_frame(struct wiphy *wiphy,
|
||||
struct ieee80211_channel *channel,
|
||||
enum nl80211_bss_scan_width scan_width,
|
||||
struct ieee80211_mgmt *mgmt, size_t len,
|
||||
s32 signal, gfp_t gfp)
|
||||
{
|
||||
struct cfg80211_internal_bss tmp = {}, *res;
|
||||
struct cfg80211_bss_ies *ies;
|
||||
|
|
@ -941,7 +942,8 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy,
|
|||
BUILD_BUG_ON(offsetof(struct ieee80211_mgmt, u.probe_resp.variable) !=
|
||||
offsetof(struct ieee80211_mgmt, u.beacon.variable));
|
||||
|
||||
trace_cfg80211_inform_bss_frame(wiphy, channel, mgmt, len, signal);
|
||||
trace_cfg80211_inform_bss_width_frame(wiphy, channel, scan_width, mgmt,
|
||||
len, signal);
|
||||
|
||||
if (WARN_ON(!mgmt))
|
||||
return NULL;
|
||||
|
|
@ -976,6 +978,7 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy,
|
|||
|
||||
memcpy(tmp.pub.bssid, mgmt->bssid, ETH_ALEN);
|
||||
tmp.pub.channel = channel;
|
||||
tmp.pub.scan_width = scan_width;
|
||||
tmp.pub.signal = signal;
|
||||
tmp.pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int);
|
||||
tmp.pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info);
|
||||
|
|
@ -991,7 +994,7 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy,
|
|||
/* cfg80211_bss_update gives us a referenced result */
|
||||
return &res->pub;
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_inform_bss_frame);
|
||||
EXPORT_SYMBOL(cfg80211_inform_bss_width_frame);
|
||||
|
||||
void cfg80211_ref_bss(struct wiphy *wiphy, struct cfg80211_bss *pub)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1293,15 +1293,17 @@ TRACE_EVENT(rdev_return_int_int,
|
|||
|
||||
#ifdef CONFIG_NL80211_TESTMODE
|
||||
TRACE_EVENT(rdev_testmode_cmd,
|
||||
TP_PROTO(struct wiphy *wiphy),
|
||||
TP_ARGS(wiphy),
|
||||
TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev),
|
||||
TP_ARGS(wiphy, wdev),
|
||||
TP_STRUCT__entry(
|
||||
WIPHY_ENTRY
|
||||
WDEV_ENTRY
|
||||
),
|
||||
TP_fast_assign(
|
||||
WIPHY_ASSIGN;
|
||||
WDEV_ASSIGN;
|
||||
),
|
||||
TP_printk(WIPHY_PR_FMT, WIPHY_PR_ARG)
|
||||
TP_printk(WIPHY_PR_FMT WDEV_PR_FMT, WIPHY_PR_ARG, WDEV_PR_ARG)
|
||||
);
|
||||
|
||||
TRACE_EVENT(rdev_testmode_dump,
|
||||
|
|
@ -1841,6 +1843,39 @@ TRACE_EVENT(rdev_crit_proto_stop,
|
|||
WIPHY_PR_ARG, WDEV_PR_ARG)
|
||||
);
|
||||
|
||||
TRACE_EVENT(rdev_channel_switch,
|
||||
TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
|
||||
struct cfg80211_csa_settings *params),
|
||||
TP_ARGS(wiphy, netdev, params),
|
||||
TP_STRUCT__entry(
|
||||
WIPHY_ENTRY
|
||||
NETDEV_ENTRY
|
||||
CHAN_DEF_ENTRY
|
||||
__field(u16, counter_offset_beacon)
|
||||
__field(u16, counter_offset_presp)
|
||||
__field(bool, radar_required)
|
||||
__field(bool, block_tx)
|
||||
__field(u8, count)
|
||||
),
|
||||
TP_fast_assign(
|
||||
WIPHY_ASSIGN;
|
||||
NETDEV_ASSIGN;
|
||||
CHAN_DEF_ASSIGN(¶ms->chandef);
|
||||
__entry->counter_offset_beacon = params->counter_offset_beacon;
|
||||
__entry->counter_offset_presp = params->counter_offset_presp;
|
||||
__entry->radar_required = params->radar_required;
|
||||
__entry->block_tx = params->block_tx;
|
||||
__entry->count = params->count;
|
||||
),
|
||||
TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT
|
||||
", block_tx: %d, count: %u, radar_required: %d"
|
||||
", counter offsets (beacon/presp): %u/%u",
|
||||
WIPHY_PR_ARG, NETDEV_PR_ARG, CHAN_DEF_PR_ARG,
|
||||
__entry->block_tx, __entry->count, __entry->radar_required,
|
||||
__entry->counter_offset_beacon,
|
||||
__entry->counter_offset_presp)
|
||||
);
|
||||
|
||||
/*************************************************************
|
||||
* cfg80211 exported functions traces *
|
||||
*************************************************************/
|
||||
|
|
@ -2391,26 +2426,30 @@ TRACE_EVENT(cfg80211_get_bss,
|
|||
__entry->capa_mask, __entry->capa_val)
|
||||
);
|
||||
|
||||
TRACE_EVENT(cfg80211_inform_bss_frame,
|
||||
TRACE_EVENT(cfg80211_inform_bss_width_frame,
|
||||
TP_PROTO(struct wiphy *wiphy, struct ieee80211_channel *channel,
|
||||
enum nl80211_bss_scan_width scan_width,
|
||||
struct ieee80211_mgmt *mgmt, size_t len,
|
||||
s32 signal),
|
||||
TP_ARGS(wiphy, channel, mgmt, len, signal),
|
||||
TP_ARGS(wiphy, channel, scan_width, mgmt, len, signal),
|
||||
TP_STRUCT__entry(
|
||||
WIPHY_ENTRY
|
||||
CHAN_ENTRY
|
||||
__field(enum nl80211_bss_scan_width, scan_width)
|
||||
__dynamic_array(u8, mgmt, len)
|
||||
__field(s32, signal)
|
||||
),
|
||||
TP_fast_assign(
|
||||
WIPHY_ASSIGN;
|
||||
CHAN_ASSIGN(channel);
|
||||
__entry->scan_width = scan_width;
|
||||
if (mgmt)
|
||||
memcpy(__get_dynamic_array(mgmt), mgmt, len);
|
||||
__entry->signal = signal;
|
||||
),
|
||||
TP_printk(WIPHY_PR_FMT ", " CHAN_PR_FMT "signal: %d",
|
||||
WIPHY_PR_ARG, CHAN_PR_ARG, __entry->signal)
|
||||
TP_printk(WIPHY_PR_FMT ", " CHAN_PR_FMT "(scan_width: %d) signal: %d",
|
||||
WIPHY_PR_ARG, CHAN_PR_ARG, __entry->scan_width,
|
||||
__entry->signal)
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(cfg80211_bss_evt,
|
||||
|
|
|
|||
|
|
@ -33,7 +33,8 @@ ieee80211_get_response_rate(struct ieee80211_supported_band *sband,
|
|||
}
|
||||
EXPORT_SYMBOL(ieee80211_get_response_rate);
|
||||
|
||||
u32 ieee80211_mandatory_rates(struct ieee80211_supported_band *sband)
|
||||
u32 ieee80211_mandatory_rates(struct ieee80211_supported_band *sband,
|
||||
enum nl80211_bss_scan_width scan_width)
|
||||
{
|
||||
struct ieee80211_rate *bitrates;
|
||||
u32 mandatory_rates = 0;
|
||||
|
|
@ -43,10 +44,15 @@ u32 ieee80211_mandatory_rates(struct ieee80211_supported_band *sband)
|
|||
if (WARN_ON(!sband))
|
||||
return 1;
|
||||
|
||||
if (sband->band == IEEE80211_BAND_2GHZ)
|
||||
mandatory_flag = IEEE80211_RATE_MANDATORY_B;
|
||||
else
|
||||
if (sband->band == IEEE80211_BAND_2GHZ) {
|
||||
if (scan_width == NL80211_BSS_CHAN_WIDTH_5 ||
|
||||
scan_width == NL80211_BSS_CHAN_WIDTH_10)
|
||||
mandatory_flag = IEEE80211_RATE_MANDATORY_G;
|
||||
else
|
||||
mandatory_flag = IEEE80211_RATE_MANDATORY_B;
|
||||
} else {
|
||||
mandatory_flag = IEEE80211_RATE_MANDATORY_A;
|
||||
}
|
||||
|
||||
bitrates = sband->bitrates;
|
||||
for (i = 0; i < sband->n_bitrates; i++)
|
||||
|
|
|
|||
Loading…
Reference in a new issue