Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
这个提交包含在:
@@ -27,9 +27,10 @@ static int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
|
||||
err = rdev_stop_ap(rdev, dev);
|
||||
if (!err) {
|
||||
wdev->beacon_interval = 0;
|
||||
wdev->channel = NULL;
|
||||
memset(&wdev->chandef, 0, sizeof(wdev->chandef));
|
||||
wdev->ssid_len = 0;
|
||||
rdev_set_qos_map(rdev, dev, NULL);
|
||||
nl80211_send_ap_stopped(wdev);
|
||||
}
|
||||
|
||||
return err;
|
||||
|
@@ -642,7 +642,8 @@ int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
|
||||
void
|
||||
cfg80211_get_chan_state(struct wireless_dev *wdev,
|
||||
struct ieee80211_channel **chan,
|
||||
enum cfg80211_chan_mode *chanmode)
|
||||
enum cfg80211_chan_mode *chanmode,
|
||||
u8 *radar_detect)
|
||||
{
|
||||
*chan = NULL;
|
||||
*chanmode = CHAN_MODE_UNDEFINED;
|
||||
@@ -660,6 +661,11 @@ cfg80211_get_chan_state(struct wireless_dev *wdev,
|
||||
!wdev->ibss_dfs_possible)
|
||||
? CHAN_MODE_SHARED
|
||||
: CHAN_MODE_EXCLUSIVE;
|
||||
|
||||
/* consider worst-case - IBSS can try to return to the
|
||||
* original user-specified channel as creator */
|
||||
if (wdev->ibss_dfs_possible)
|
||||
*radar_detect |= BIT(wdev->chandef.width);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@@ -674,17 +680,26 @@ cfg80211_get_chan_state(struct wireless_dev *wdev,
|
||||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
if (wdev->cac_started) {
|
||||
*chan = wdev->channel;
|
||||
*chan = wdev->chandef.chan;
|
||||
*chanmode = CHAN_MODE_SHARED;
|
||||
*radar_detect |= BIT(wdev->chandef.width);
|
||||
} else if (wdev->beacon_interval) {
|
||||
*chan = wdev->channel;
|
||||
*chan = wdev->chandef.chan;
|
||||
*chanmode = CHAN_MODE_SHARED;
|
||||
|
||||
if (cfg80211_chandef_dfs_required(wdev->wiphy,
|
||||
&wdev->chandef))
|
||||
*radar_detect |= BIT(wdev->chandef.width);
|
||||
}
|
||||
return;
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
if (wdev->mesh_id_len) {
|
||||
*chan = wdev->channel;
|
||||
*chan = wdev->chandef.chan;
|
||||
*chanmode = CHAN_MODE_SHARED;
|
||||
|
||||
if (cfg80211_chandef_dfs_required(wdev->wiphy,
|
||||
&wdev->chandef))
|
||||
*radar_detect |= BIT(wdev->chandef.width);
|
||||
}
|
||||
return;
|
||||
case NL80211_IFTYPE_MONITOR:
|
||||
|
@@ -737,7 +737,7 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev)
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_unregister_wdev);
|
||||
|
||||
static struct device_type wiphy_type = {
|
||||
static const struct device_type wiphy_type = {
|
||||
.name = "wlan",
|
||||
};
|
||||
|
||||
|
@@ -211,6 +211,7 @@ struct cfg80211_event {
|
||||
} dc;
|
||||
struct {
|
||||
u8 bssid[ETH_ALEN];
|
||||
struct ieee80211_channel *channel;
|
||||
} ij;
|
||||
};
|
||||
};
|
||||
@@ -258,7 +259,8 @@ int __cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev, bool nowext);
|
||||
int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev, bool nowext);
|
||||
void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid);
|
||||
void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
|
||||
struct ieee80211_channel *channel);
|
||||
int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
|
||||
struct wireless_dev *wdev);
|
||||
|
||||
@@ -443,7 +445,8 @@ static inline unsigned int elapsed_jiffies_msecs(unsigned long start)
|
||||
void
|
||||
cfg80211_get_chan_state(struct wireless_dev *wdev,
|
||||
struct ieee80211_channel **chan,
|
||||
enum cfg80211_chan_mode *chanmode);
|
||||
enum cfg80211_chan_mode *chanmode,
|
||||
u8 *radar_detect);
|
||||
|
||||
int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
|
||||
struct cfg80211_chan_def *chandef);
|
||||
|
@@ -14,7 +14,8 @@
|
||||
#include "rdev-ops.h"
|
||||
|
||||
|
||||
void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid)
|
||||
void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
|
||||
struct ieee80211_channel *channel)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
struct cfg80211_bss *bss;
|
||||
@@ -28,8 +29,7 @@ void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid)
|
||||
if (!wdev->ssid_len)
|
||||
return;
|
||||
|
||||
bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
|
||||
wdev->ssid, wdev->ssid_len,
|
||||
bss = cfg80211_get_bss(wdev->wiphy, channel, bssid, NULL, 0,
|
||||
WLAN_CAPABILITY_IBSS, WLAN_CAPABILITY_IBSS);
|
||||
|
||||
if (WARN_ON(!bss))
|
||||
@@ -54,21 +54,26 @@ void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid)
|
||||
#endif
|
||||
}
|
||||
|
||||
void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp)
|
||||
void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
|
||||
struct ieee80211_channel *channel, gfp_t gfp)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
|
||||
struct cfg80211_event *ev;
|
||||
unsigned long flags;
|
||||
|
||||
trace_cfg80211_ibss_joined(dev, bssid);
|
||||
trace_cfg80211_ibss_joined(dev, bssid, channel);
|
||||
|
||||
if (WARN_ON(!channel))
|
||||
return;
|
||||
|
||||
ev = kzalloc(sizeof(*ev), gfp);
|
||||
if (!ev)
|
||||
return;
|
||||
|
||||
ev->type = EVENT_IBSS_JOINED;
|
||||
memcpy(ev->cr.bssid, bssid, ETH_ALEN);
|
||||
memcpy(ev->ij.bssid, bssid, ETH_ALEN);
|
||||
ev->ij.channel = channel;
|
||||
|
||||
spin_lock_irqsave(&wdev->event_lock, flags);
|
||||
list_add_tail(&ev->list, &wdev->event_list);
|
||||
@@ -117,6 +122,7 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
|
||||
|
||||
wdev->ibss_fixed = params->channel_fixed;
|
||||
wdev->ibss_dfs_possible = params->userspace_handles_dfs;
|
||||
wdev->chandef = params->chandef;
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
wdev->wext.ibss.chandef = params->chandef;
|
||||
#endif
|
||||
@@ -200,6 +206,7 @@ static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext)
|
||||
|
||||
wdev->current_bss = NULL;
|
||||
wdev->ssid_len = 0;
|
||||
memset(&wdev->chandef, 0, sizeof(wdev->chandef));
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
if (!nowext)
|
||||
wdev->wext.ibss.ssid_len = 0;
|
||||
|
@@ -195,7 +195,7 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
|
||||
if (!err) {
|
||||
memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len);
|
||||
wdev->mesh_id_len = setup->mesh_id_len;
|
||||
wdev->channel = setup->chandef.chan;
|
||||
wdev->chandef = setup->chandef;
|
||||
}
|
||||
|
||||
return err;
|
||||
@@ -244,7 +244,7 @@ int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev,
|
||||
err = rdev_libertas_set_mesh_channel(rdev, wdev->netdev,
|
||||
chandef->chan);
|
||||
if (!err)
|
||||
wdev->channel = chandef->chan;
|
||||
wdev->chandef = *chandef;
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -276,7 +276,7 @@ static int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
|
||||
err = rdev_leave_mesh(rdev, dev);
|
||||
if (!err) {
|
||||
wdev->mesh_id_len = 0;
|
||||
wdev->channel = NULL;
|
||||
memset(&wdev->chandef, 0, sizeof(wdev->chandef));
|
||||
rdev_set_qos_map(rdev, dev, NULL);
|
||||
}
|
||||
|
||||
|
@@ -772,7 +772,7 @@ void cfg80211_cac_event(struct net_device *netdev,
|
||||
if (WARN_ON(!wdev->cac_started))
|
||||
return;
|
||||
|
||||
if (WARN_ON(!wdev->channel))
|
||||
if (WARN_ON(!wdev->chandef.chan))
|
||||
return;
|
||||
|
||||
switch (event) {
|
||||
|
@@ -382,6 +382,8 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
|
||||
[NL80211_ATTR_VENDOR_DATA] = { .type = NLA_BINARY },
|
||||
[NL80211_ATTR_QOS_MAP] = { .type = NLA_BINARY,
|
||||
.len = IEEE80211_QOS_MAP_LEN_MAX },
|
||||
[NL80211_ATTR_MAC_HINT] = { .len = ETH_ALEN },
|
||||
[NL80211_ATTR_WIPHY_FREQ_HINT] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
/* policy for the key attributes */
|
||||
@@ -855,6 +857,19 @@ static int nl80211_key_allowed(struct wireless_dev *wdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ieee80211_channel *nl80211_get_valid_chan(struct wiphy *wiphy,
|
||||
struct nlattr *tb)
|
||||
{
|
||||
struct ieee80211_channel *chan;
|
||||
|
||||
if (tb == NULL)
|
||||
return NULL;
|
||||
chan = ieee80211_get_channel(wiphy, nla_get_u32(tb));
|
||||
if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
|
||||
return NULL;
|
||||
return chan;
|
||||
}
|
||||
|
||||
static int nl80211_put_iftypes(struct sk_buff *msg, u32 attr, u16 ifmodes)
|
||||
{
|
||||
struct nlattr *nl_modes = nla_nest_start(msg, attr);
|
||||
@@ -1586,6 +1601,12 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
|
||||
(nla_put_flag(msg, NL80211_ATTR_SUPPORT_5_MHZ) ||
|
||||
nla_put_flag(msg, NL80211_ATTR_SUPPORT_10_MHZ)))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (dev->wiphy.max_ap_assoc_sta &&
|
||||
nla_put_u32(msg, NL80211_ATTR_MAX_AP_ASSOC_STA,
|
||||
dev->wiphy.max_ap_assoc_sta))
|
||||
goto nla_put_failure;
|
||||
|
||||
state->split_start++;
|
||||
break;
|
||||
case 11:
|
||||
@@ -2035,10 +2056,12 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
|
||||
nla_for_each_nested(nl_txq_params,
|
||||
info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS],
|
||||
rem_txq_params) {
|
||||
nla_parse(tb, NL80211_TXQ_ATTR_MAX,
|
||||
nla_data(nl_txq_params),
|
||||
nla_len(nl_txq_params),
|
||||
txq_params_policy);
|
||||
result = nla_parse(tb, NL80211_TXQ_ATTR_MAX,
|
||||
nla_data(nl_txq_params),
|
||||
nla_len(nl_txq_params),
|
||||
txq_params_policy);
|
||||
if (result)
|
||||
return result;
|
||||
result = parse_txq_params(tb, &txq_params);
|
||||
if (result)
|
||||
return result;
|
||||
@@ -3259,7 +3282,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
|
||||
if (!err) {
|
||||
wdev->preset_chandef = params.chandef;
|
||||
wdev->beacon_interval = params.beacon_interval;
|
||||
wdev->channel = params.chandef.chan;
|
||||
wdev->chandef = params.chandef;
|
||||
wdev->ssid_len = params.ssid_len;
|
||||
memcpy(wdev->ssid, params.ssid, wdev->ssid_len);
|
||||
}
|
||||
@@ -3902,8 +3925,8 @@ static struct net_device *get_vlan(struct genl_info *info,
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
static struct nla_policy
|
||||
nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] __read_mostly = {
|
||||
static const struct nla_policy
|
||||
nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] = {
|
||||
[NL80211_STA_WME_UAPSD_QUEUES] = { .type = NLA_U8 },
|
||||
[NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 },
|
||||
};
|
||||
@@ -4604,8 +4627,6 @@ static int parse_reg_rule(struct nlattr *tb[],
|
||||
return -EINVAL;
|
||||
if (!tb[NL80211_ATTR_FREQ_RANGE_END])
|
||||
return -EINVAL;
|
||||
if (!tb[NL80211_ATTR_FREQ_RANGE_MAX_BW])
|
||||
return -EINVAL;
|
||||
if (!tb[NL80211_ATTR_POWER_RULE_MAX_EIRP])
|
||||
return -EINVAL;
|
||||
|
||||
@@ -4615,8 +4636,9 @@ static int parse_reg_rule(struct nlattr *tb[],
|
||||
nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]);
|
||||
freq_range->end_freq_khz =
|
||||
nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]);
|
||||
freq_range->max_bandwidth_khz =
|
||||
nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]);
|
||||
if (tb[NL80211_ATTR_FREQ_RANGE_MAX_BW])
|
||||
freq_range->max_bandwidth_khz =
|
||||
nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]);
|
||||
|
||||
power_rule->max_eirp =
|
||||
nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_EIRP]);
|
||||
@@ -5086,6 +5108,7 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
|
||||
const struct ieee80211_reg_rule *reg_rule;
|
||||
const struct ieee80211_freq_range *freq_range;
|
||||
const struct ieee80211_power_rule *power_rule;
|
||||
unsigned int max_bandwidth_khz;
|
||||
|
||||
reg_rule = ®dom->reg_rules[i];
|
||||
freq_range = ®_rule->freq_range;
|
||||
@@ -5095,6 +5118,11 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
|
||||
if (!nl_reg_rule)
|
||||
goto nla_put_failure_rcu;
|
||||
|
||||
max_bandwidth_khz = freq_range->max_bandwidth_khz;
|
||||
if (!max_bandwidth_khz)
|
||||
max_bandwidth_khz = reg_get_max_bandwidth(regdom,
|
||||
reg_rule);
|
||||
|
||||
if (nla_put_u32(msg, NL80211_ATTR_REG_RULE_FLAGS,
|
||||
reg_rule->flags) ||
|
||||
nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_START,
|
||||
@@ -5102,7 +5130,7 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
|
||||
nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_END,
|
||||
freq_range->end_freq_khz) ||
|
||||
nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_MAX_BW,
|
||||
freq_range->max_bandwidth_khz) ||
|
||||
max_bandwidth_khz) ||
|
||||
nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN,
|
||||
power_rule->max_antenna_gain) ||
|
||||
nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_EIRP,
|
||||
@@ -5178,9 +5206,11 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
|
||||
|
||||
nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES],
|
||||
rem_reg_rules) {
|
||||
nla_parse(tb, NL80211_REG_RULE_ATTR_MAX,
|
||||
nla_data(nl_reg_rule), nla_len(nl_reg_rule),
|
||||
reg_rule_policy);
|
||||
r = nla_parse(tb, NL80211_REG_RULE_ATTR_MAX,
|
||||
nla_data(nl_reg_rule), nla_len(nl_reg_rule),
|
||||
reg_rule_policy);
|
||||
if (r)
|
||||
goto bad_reg;
|
||||
r = parse_reg_rule(tb, &rd->reg_rules[rule_idx]);
|
||||
if (r)
|
||||
goto bad_reg;
|
||||
@@ -5443,6 +5473,7 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
|
||||
enum ieee80211_band band;
|
||||
size_t ie_len;
|
||||
struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1];
|
||||
s32 default_match_rssi = NL80211_SCAN_RSSI_THOLD_OFF;
|
||||
|
||||
if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) ||
|
||||
!rdev->ops->sched_scan_start)
|
||||
@@ -5477,11 +5508,40 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
|
||||
if (n_ssids > wiphy->max_sched_scan_ssids)
|
||||
return -EINVAL;
|
||||
|
||||
if (info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH])
|
||||
/*
|
||||
* First, count the number of 'real' matchsets. Due to an issue with
|
||||
* the old implementation, matchsets containing only the RSSI attribute
|
||||
* (NL80211_SCHED_SCAN_MATCH_ATTR_RSSI) are considered as the 'default'
|
||||
* RSSI for all matchsets, rather than their own matchset for reporting
|
||||
* all APs with a strong RSSI. This is needed to be compatible with
|
||||
* older userspace that treated a matchset with only the RSSI as the
|
||||
* global RSSI for all other matchsets - if there are other matchsets.
|
||||
*/
|
||||
if (info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
|
||||
nla_for_each_nested(attr,
|
||||
info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
|
||||
tmp)
|
||||
n_match_sets++;
|
||||
tmp) {
|
||||
struct nlattr *rssi;
|
||||
|
||||
err = nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
|
||||
nla_data(attr), nla_len(attr),
|
||||
nl80211_match_policy);
|
||||
if (err)
|
||||
return err;
|
||||
/* add other standalone attributes here */
|
||||
if (tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID]) {
|
||||
n_match_sets++;
|
||||
continue;
|
||||
}
|
||||
rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
|
||||
if (rssi)
|
||||
default_match_rssi = nla_get_s32(rssi);
|
||||
}
|
||||
}
|
||||
|
||||
/* However, if there's no other matchset, add the RSSI one */
|
||||
if (!n_match_sets && default_match_rssi != NL80211_SCAN_RSSI_THOLD_OFF)
|
||||
n_match_sets = 1;
|
||||
|
||||
if (n_match_sets > wiphy->max_match_sets)
|
||||
return -EINVAL;
|
||||
@@ -5602,11 +5662,22 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
|
||||
tmp) {
|
||||
struct nlattr *ssid, *rssi;
|
||||
|
||||
nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
|
||||
nla_data(attr), nla_len(attr),
|
||||
nl80211_match_policy);
|
||||
err = nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
|
||||
nla_data(attr), nla_len(attr),
|
||||
nl80211_match_policy);
|
||||
if (err)
|
||||
goto out_free;
|
||||
ssid = tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID];
|
||||
if (ssid) {
|
||||
if (WARN_ON(i >= n_match_sets)) {
|
||||
/* this indicates a programming error,
|
||||
* the loop above should have verified
|
||||
* things properly
|
||||
*/
|
||||
err = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
if (nla_len(ssid) > IEEE80211_MAX_SSID_LEN) {
|
||||
err = -EINVAL;
|
||||
goto out_free;
|
||||
@@ -5615,15 +5686,28 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
|
||||
nla_data(ssid), nla_len(ssid));
|
||||
request->match_sets[i].ssid.ssid_len =
|
||||
nla_len(ssid);
|
||||
/* special attribute - old implemenation w/a */
|
||||
request->match_sets[i].rssi_thold =
|
||||
default_match_rssi;
|
||||
rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
|
||||
if (rssi)
|
||||
request->match_sets[i].rssi_thold =
|
||||
nla_get_s32(rssi);
|
||||
}
|
||||
rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
|
||||
if (rssi)
|
||||
request->rssi_thold = nla_get_u32(rssi);
|
||||
else
|
||||
request->rssi_thold =
|
||||
NL80211_SCAN_RSSI_THOLD_OFF;
|
||||
i++;
|
||||
}
|
||||
|
||||
/* there was no other matchset, so the RSSI one is alone */
|
||||
if (i == 0)
|
||||
request->match_sets[0].rssi_thold = default_match_rssi;
|
||||
|
||||
request->min_rssi_thold = INT_MAX;
|
||||
for (i = 0; i < n_match_sets; i++)
|
||||
request->min_rssi_thold =
|
||||
min(request->match_sets[i].rssi_thold,
|
||||
request->min_rssi_thold);
|
||||
} else {
|
||||
request->min_rssi_thold = NL80211_SCAN_RSSI_THOLD_OFF;
|
||||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_IE]) {
|
||||
@@ -5719,7 +5803,7 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
|
||||
|
||||
err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef);
|
||||
if (!err) {
|
||||
wdev->channel = chandef.chan;
|
||||
wdev->chandef = chandef;
|
||||
wdev->cac_started = true;
|
||||
wdev->cac_start_time = jiffies;
|
||||
}
|
||||
@@ -5751,10 +5835,15 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
|
||||
|
||||
/* useless if AP is not running */
|
||||
if (!wdev->beacon_interval)
|
||||
return -EINVAL;
|
||||
return -ENOTCONN;
|
||||
break;
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
if (!wdev->ssid_len)
|
||||
return -ENOTCONN;
|
||||
break;
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
if (!wdev->mesh_id_len)
|
||||
return -ENOTCONN;
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
@@ -6192,9 +6281,9 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
|
||||
chan = ieee80211_get_channel(&rdev->wiphy,
|
||||
nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
|
||||
if (!chan || (chan->flags & IEEE80211_CHAN_DISABLED))
|
||||
chan = nl80211_get_valid_chan(&rdev->wiphy,
|
||||
info->attrs[NL80211_ATTR_WIPHY_FREQ]);
|
||||
if (!chan)
|
||||
return -EINVAL;
|
||||
|
||||
ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
|
||||
@@ -6347,9 +6436,9 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
|
||||
|
||||
bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
|
||||
|
||||
chan = ieee80211_get_channel(&rdev->wiphy,
|
||||
nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
|
||||
if (!chan || (chan->flags & IEEE80211_CHAN_DISABLED))
|
||||
chan = nl80211_get_valid_chan(&rdev->wiphy,
|
||||
info->attrs[NL80211_ATTR_WIPHY_FREQ]);
|
||||
if (!chan)
|
||||
return -EINVAL;
|
||||
|
||||
ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
|
||||
@@ -6985,6 +7074,9 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
|
||||
|
||||
if (info->attrs[NL80211_ATTR_MAC])
|
||||
connect.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
|
||||
else if (info->attrs[NL80211_ATTR_MAC_HINT])
|
||||
connect.bssid_hint =
|
||||
nla_data(info->attrs[NL80211_ATTR_MAC_HINT]);
|
||||
connect.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
|
||||
connect.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
|
||||
|
||||
@@ -7003,11 +7095,14 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
|
||||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
|
||||
connect.channel =
|
||||
ieee80211_get_channel(wiphy,
|
||||
nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
|
||||
if (!connect.channel ||
|
||||
connect.channel->flags & IEEE80211_CHAN_DISABLED)
|
||||
connect.channel = nl80211_get_valid_chan(
|
||||
wiphy, info->attrs[NL80211_ATTR_WIPHY_FREQ]);
|
||||
if (!connect.channel)
|
||||
return -EINVAL;
|
||||
} else if (info->attrs[NL80211_ATTR_WIPHY_FREQ_HINT]) {
|
||||
connect.channel_hint = nl80211_get_valid_chan(
|
||||
wiphy, info->attrs[NL80211_ATTR_WIPHY_FREQ_HINT]);
|
||||
if (!connect.channel_hint)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -7421,6 +7516,7 @@ static const struct nla_policy nl80211_txattr_policy[NL80211_TXRATE_MAX + 1] = {
|
||||
[NL80211_TXRATE_HT] = { .type = NLA_BINARY,
|
||||
.len = NL80211_MAX_SUPP_HT_RATES },
|
||||
[NL80211_TXRATE_VHT] = { .len = sizeof(struct nl80211_txrate_vht)},
|
||||
[NL80211_TXRATE_GI] = { .type = NLA_U8 },
|
||||
};
|
||||
|
||||
static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
|
||||
@@ -7467,16 +7563,19 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
|
||||
* directly to the enum ieee80211_band values used in cfg80211.
|
||||
*/
|
||||
BUILD_BUG_ON(NL80211_MAX_SUPP_HT_RATES > IEEE80211_HT_MCS_MASK_LEN * 8);
|
||||
nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem)
|
||||
{
|
||||
nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem) {
|
||||
enum ieee80211_band band = nla_type(tx_rates);
|
||||
int err;
|
||||
|
||||
if (band < 0 || band >= IEEE80211_NUM_BANDS)
|
||||
return -EINVAL;
|
||||
sband = rdev->wiphy.bands[band];
|
||||
if (sband == NULL)
|
||||
return -EINVAL;
|
||||
nla_parse(tb, NL80211_TXRATE_MAX, nla_data(tx_rates),
|
||||
nla_len(tx_rates), nl80211_txattr_policy);
|
||||
err = nla_parse(tb, NL80211_TXRATE_MAX, nla_data(tx_rates),
|
||||
nla_len(tx_rates), nl80211_txattr_policy);
|
||||
if (err)
|
||||
return err;
|
||||
if (tb[NL80211_TXRATE_LEGACY]) {
|
||||
mask.control[band].legacy = rateset_to_mask(
|
||||
sband,
|
||||
@@ -7501,6 +7600,12 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
|
||||
mask.control[band].vht_mcs))
|
||||
return -EINVAL;
|
||||
}
|
||||
if (tb[NL80211_TXRATE_GI]) {
|
||||
mask.control[band].gi =
|
||||
nla_get_u8(tb[NL80211_TXRATE_GI]);
|
||||
if (mask.control[band].gi > NL80211_TXRATE_FORCE_LGI)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (mask.control[band].legacy == 0) {
|
||||
/* don't allow empty legacy rates if HT or VHT
|
||||
@@ -7777,8 +7882,8 @@ static int nl80211_get_power_save(struct sk_buff *skb, struct genl_info *info)
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct nla_policy
|
||||
nl80211_attr_cqm_policy[NL80211_ATTR_CQM_MAX + 1] __read_mostly = {
|
||||
static const struct nla_policy
|
||||
nl80211_attr_cqm_policy[NL80211_ATTR_CQM_MAX + 1] = {
|
||||
[NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_U32 },
|
||||
[NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U32 },
|
||||
[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 },
|
||||
@@ -11107,7 +11212,8 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
|
||||
wdev->iftype != NL80211_IFTYPE_MESH_POINT))
|
||||
return;
|
||||
|
||||
wdev->channel = chandef->chan;
|
||||
wdev->chandef = *chandef;
|
||||
wdev->preset_chandef = *chandef;
|
||||
nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL);
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_ch_switch_notify);
|
||||
@@ -11621,6 +11727,35 @@ void cfg80211_crit_proto_stopped(struct wireless_dev *wdev, gfp_t gfp)
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_crit_proto_stopped);
|
||||
|
||||
void nl80211_send_ap_stopped(struct wireless_dev *wdev)
|
||||
{
|
||||
struct wiphy *wiphy = wdev->wiphy;
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
|
||||
struct sk_buff *msg;
|
||||
void *hdr;
|
||||
|
||||
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
||||
if (!msg)
|
||||
return;
|
||||
|
||||
hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_STOP_AP);
|
||||
if (!hdr)
|
||||
goto out;
|
||||
|
||||
if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
|
||||
nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex) ||
|
||||
nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)))
|
||||
goto out;
|
||||
|
||||
genlmsg_end(msg, hdr);
|
||||
|
||||
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(wiphy), msg, 0,
|
||||
NL80211_MCGRP_MLME, GFP_KERNEL);
|
||||
return;
|
||||
out:
|
||||
nlmsg_free(msg);
|
||||
}
|
||||
|
||||
/* initialisation/exit functions */
|
||||
|
||||
int nl80211_init(void)
|
||||
|
@@ -74,6 +74,8 @@ nl80211_radar_notify(struct cfg80211_registered_device *rdev,
|
||||
enum nl80211_radar_event event,
|
||||
struct net_device *netdev, gfp_t gfp);
|
||||
|
||||
void nl80211_send_ap_stopped(struct wireless_dev *wdev);
|
||||
|
||||
void cfg80211_rdev_free_coalesce(struct cfg80211_registered_device *rdev);
|
||||
|
||||
#endif /* __NET_WIRELESS_NL80211_H */
|
||||
|
@@ -91,7 +91,7 @@ static struct regulatory_request __rcu *last_request =
|
||||
/* To trigger userspace events */
|
||||
static struct platform_device *reg_pdev;
|
||||
|
||||
static struct device_type reg_device_type = {
|
||||
static const struct device_type reg_device_type = {
|
||||
.uevent = reg_device_uevent,
|
||||
};
|
||||
|
||||
@@ -522,6 +522,77 @@ bool reg_is_valid_request(const char *alpha2)
|
||||
return alpha2_equal(lr->alpha2, alpha2);
|
||||
}
|
||||
|
||||
static const struct ieee80211_regdomain *reg_get_regdomain(struct wiphy *wiphy)
|
||||
{
|
||||
struct regulatory_request *lr = get_last_request();
|
||||
|
||||
/*
|
||||
* Follow the driver's regulatory domain, if present, unless a country
|
||||
* IE has been processed or a user wants to help complaince further
|
||||
*/
|
||||
if (lr->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE &&
|
||||
lr->initiator != NL80211_REGDOM_SET_BY_USER &&
|
||||
wiphy->regd)
|
||||
return get_wiphy_regdom(wiphy);
|
||||
|
||||
return get_cfg80211_regdom();
|
||||
}
|
||||
|
||||
unsigned int reg_get_max_bandwidth(const struct ieee80211_regdomain *rd,
|
||||
const struct ieee80211_reg_rule *rule)
|
||||
{
|
||||
const struct ieee80211_freq_range *freq_range = &rule->freq_range;
|
||||
const struct ieee80211_freq_range *freq_range_tmp;
|
||||
const struct ieee80211_reg_rule *tmp;
|
||||
u32 start_freq, end_freq, idx, no;
|
||||
|
||||
for (idx = 0; idx < rd->n_reg_rules; idx++)
|
||||
if (rule == &rd->reg_rules[idx])
|
||||
break;
|
||||
|
||||
if (idx == rd->n_reg_rules)
|
||||
return 0;
|
||||
|
||||
/* get start_freq */
|
||||
no = idx;
|
||||
|
||||
while (no) {
|
||||
tmp = &rd->reg_rules[--no];
|
||||
freq_range_tmp = &tmp->freq_range;
|
||||
|
||||
if (freq_range_tmp->end_freq_khz < freq_range->start_freq_khz)
|
||||
break;
|
||||
|
||||
if (freq_range_tmp->max_bandwidth_khz)
|
||||
break;
|
||||
|
||||
freq_range = freq_range_tmp;
|
||||
}
|
||||
|
||||
start_freq = freq_range->start_freq_khz;
|
||||
|
||||
/* get end_freq */
|
||||
freq_range = &rule->freq_range;
|
||||
no = idx;
|
||||
|
||||
while (no < rd->n_reg_rules - 1) {
|
||||
tmp = &rd->reg_rules[++no];
|
||||
freq_range_tmp = &tmp->freq_range;
|
||||
|
||||
if (freq_range_tmp->start_freq_khz > freq_range->end_freq_khz)
|
||||
break;
|
||||
|
||||
if (freq_range_tmp->max_bandwidth_khz)
|
||||
break;
|
||||
|
||||
freq_range = freq_range_tmp;
|
||||
}
|
||||
|
||||
end_freq = freq_range->end_freq_khz;
|
||||
|
||||
return end_freq - start_freq;
|
||||
}
|
||||
|
||||
/* Sanity check on a regulatory rule */
|
||||
static bool is_valid_reg_rule(const struct ieee80211_reg_rule *rule)
|
||||
{
|
||||
@@ -630,7 +701,9 @@ reg_intersect_dfs_region(const enum nl80211_dfs_regions dfs_region1,
|
||||
* Helper for regdom_intersect(), this does the real
|
||||
* mathematical intersection fun
|
||||
*/
|
||||
static int reg_rules_intersect(const struct ieee80211_reg_rule *rule1,
|
||||
static int reg_rules_intersect(const struct ieee80211_regdomain *rd1,
|
||||
const struct ieee80211_regdomain *rd2,
|
||||
const struct ieee80211_reg_rule *rule1,
|
||||
const struct ieee80211_reg_rule *rule2,
|
||||
struct ieee80211_reg_rule *intersected_rule)
|
||||
{
|
||||
@@ -638,7 +711,7 @@ static int reg_rules_intersect(const struct ieee80211_reg_rule *rule1,
|
||||
struct ieee80211_freq_range *freq_range;
|
||||
const struct ieee80211_power_rule *power_rule1, *power_rule2;
|
||||
struct ieee80211_power_rule *power_rule;
|
||||
u32 freq_diff;
|
||||
u32 freq_diff, max_bandwidth1, max_bandwidth2;
|
||||
|
||||
freq_range1 = &rule1->freq_range;
|
||||
freq_range2 = &rule2->freq_range;
|
||||
@@ -652,8 +725,24 @@ static int reg_rules_intersect(const struct ieee80211_reg_rule *rule1,
|
||||
freq_range2->start_freq_khz);
|
||||
freq_range->end_freq_khz = min(freq_range1->end_freq_khz,
|
||||
freq_range2->end_freq_khz);
|
||||
freq_range->max_bandwidth_khz = min(freq_range1->max_bandwidth_khz,
|
||||
freq_range2->max_bandwidth_khz);
|
||||
|
||||
max_bandwidth1 = freq_range1->max_bandwidth_khz;
|
||||
max_bandwidth2 = freq_range2->max_bandwidth_khz;
|
||||
|
||||
/*
|
||||
* In case max_bandwidth1 == 0 and max_bandwith2 == 0 set
|
||||
* output bandwidth as 0 (auto calculation). Next we will
|
||||
* calculate this correctly in handle_channel function.
|
||||
* In other case calculate output bandwidth here.
|
||||
*/
|
||||
if (max_bandwidth1 || max_bandwidth2) {
|
||||
if (!max_bandwidth1)
|
||||
max_bandwidth1 = reg_get_max_bandwidth(rd1, rule1);
|
||||
if (!max_bandwidth2)
|
||||
max_bandwidth2 = reg_get_max_bandwidth(rd2, rule2);
|
||||
}
|
||||
|
||||
freq_range->max_bandwidth_khz = min(max_bandwidth1, max_bandwidth2);
|
||||
|
||||
freq_diff = freq_range->end_freq_khz - freq_range->start_freq_khz;
|
||||
if (freq_range->max_bandwidth_khz > freq_diff)
|
||||
@@ -713,7 +802,8 @@ regdom_intersect(const struct ieee80211_regdomain *rd1,
|
||||
rule1 = &rd1->reg_rules[x];
|
||||
for (y = 0; y < rd2->n_reg_rules; y++) {
|
||||
rule2 = &rd2->reg_rules[y];
|
||||
if (!reg_rules_intersect(rule1, rule2, &dummy_rule))
|
||||
if (!reg_rules_intersect(rd1, rd2, rule1, rule2,
|
||||
&dummy_rule))
|
||||
num_rules++;
|
||||
}
|
||||
}
|
||||
@@ -738,7 +828,8 @@ regdom_intersect(const struct ieee80211_regdomain *rd1,
|
||||
* a memcpy()
|
||||
*/
|
||||
intersected_rule = &rd->reg_rules[rule_idx];
|
||||
r = reg_rules_intersect(rule1, rule2, intersected_rule);
|
||||
r = reg_rules_intersect(rd1, rd2, rule1, rule2,
|
||||
intersected_rule);
|
||||
/*
|
||||
* No need to memset here the intersected rule here as
|
||||
* we're not using the stack anymore
|
||||
@@ -821,18 +912,8 @@ const struct ieee80211_reg_rule *freq_reg_info(struct wiphy *wiphy,
|
||||
u32 center_freq)
|
||||
{
|
||||
const struct ieee80211_regdomain *regd;
|
||||
struct regulatory_request *lr = get_last_request();
|
||||
|
||||
/*
|
||||
* Follow the driver's regulatory domain, if present, unless a country
|
||||
* IE has been processed or a user wants to help complaince further
|
||||
*/
|
||||
if (lr->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE &&
|
||||
lr->initiator != NL80211_REGDOM_SET_BY_USER &&
|
||||
wiphy->regd)
|
||||
regd = get_wiphy_regdom(wiphy);
|
||||
else
|
||||
regd = get_cfg80211_regdom();
|
||||
regd = reg_get_regdomain(wiphy);
|
||||
|
||||
return freq_reg_info_regd(wiphy, center_freq, regd);
|
||||
}
|
||||
@@ -903,6 +984,8 @@ static void handle_channel(struct wiphy *wiphy,
|
||||
const struct ieee80211_freq_range *freq_range = NULL;
|
||||
struct wiphy *request_wiphy = NULL;
|
||||
struct regulatory_request *lr = get_last_request();
|
||||
const struct ieee80211_regdomain *regd;
|
||||
u32 max_bandwidth_khz;
|
||||
|
||||
request_wiphy = wiphy_idx_to_wiphy(lr->wiphy_idx);
|
||||
|
||||
@@ -944,11 +1027,18 @@ static void handle_channel(struct wiphy *wiphy,
|
||||
power_rule = ®_rule->power_rule;
|
||||
freq_range = ®_rule->freq_range;
|
||||
|
||||
if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(40))
|
||||
max_bandwidth_khz = freq_range->max_bandwidth_khz;
|
||||
/* Check if auto calculation requested */
|
||||
if (!max_bandwidth_khz) {
|
||||
regd = reg_get_regdomain(wiphy);
|
||||
max_bandwidth_khz = reg_get_max_bandwidth(regd, reg_rule);
|
||||
}
|
||||
|
||||
if (max_bandwidth_khz < MHZ_TO_KHZ(40))
|
||||
bw_flags = IEEE80211_CHAN_NO_HT40;
|
||||
if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(80))
|
||||
if (max_bandwidth_khz < MHZ_TO_KHZ(80))
|
||||
bw_flags |= IEEE80211_CHAN_NO_80MHZ;
|
||||
if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(160))
|
||||
if (max_bandwidth_khz < MHZ_TO_KHZ(160))
|
||||
bw_flags |= IEEE80211_CHAN_NO_160MHZ;
|
||||
|
||||
if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
|
||||
@@ -1334,6 +1424,7 @@ static void handle_channel_custom(struct wiphy *wiphy,
|
||||
const struct ieee80211_reg_rule *reg_rule = NULL;
|
||||
const struct ieee80211_power_rule *power_rule = NULL;
|
||||
const struct ieee80211_freq_range *freq_range = NULL;
|
||||
u32 max_bandwidth_khz;
|
||||
|
||||
reg_rule = freq_reg_info_regd(wiphy, MHZ_TO_KHZ(chan->center_freq),
|
||||
regd);
|
||||
@@ -1351,11 +1442,16 @@ static void handle_channel_custom(struct wiphy *wiphy,
|
||||
power_rule = ®_rule->power_rule;
|
||||
freq_range = ®_rule->freq_range;
|
||||
|
||||
if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(40))
|
||||
max_bandwidth_khz = freq_range->max_bandwidth_khz;
|
||||
/* Check if auto calculation requested */
|
||||
if (!max_bandwidth_khz)
|
||||
max_bandwidth_khz = reg_get_max_bandwidth(regd, reg_rule);
|
||||
|
||||
if (max_bandwidth_khz < MHZ_TO_KHZ(40))
|
||||
bw_flags = IEEE80211_CHAN_NO_HT40;
|
||||
if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(80))
|
||||
if (max_bandwidth_khz < MHZ_TO_KHZ(80))
|
||||
bw_flags |= IEEE80211_CHAN_NO_80MHZ;
|
||||
if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(160))
|
||||
if (max_bandwidth_khz < MHZ_TO_KHZ(160))
|
||||
bw_flags |= IEEE80211_CHAN_NO_160MHZ;
|
||||
|
||||
chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags;
|
||||
@@ -1683,17 +1779,9 @@ static void reg_process_hint(struct regulatory_request *reg_request)
|
||||
struct wiphy *wiphy = NULL;
|
||||
enum reg_request_treatment treatment;
|
||||
|
||||
if (WARN_ON(!reg_request->alpha2))
|
||||
return;
|
||||
|
||||
if (reg_request->wiphy_idx != WIPHY_IDX_INVALID)
|
||||
wiphy = wiphy_idx_to_wiphy(reg_request->wiphy_idx);
|
||||
|
||||
if (reg_request->initiator == NL80211_REGDOM_SET_BY_DRIVER && !wiphy) {
|
||||
kfree(reg_request);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (reg_request->initiator) {
|
||||
case NL80211_REGDOM_SET_BY_CORE:
|
||||
reg_process_hint_core(reg_request);
|
||||
@@ -1703,23 +1791,33 @@ static void reg_process_hint(struct regulatory_request *reg_request)
|
||||
if (treatment == REG_REQ_OK ||
|
||||
treatment == REG_REQ_ALREADY_SET)
|
||||
return;
|
||||
schedule_delayed_work(®_timeout, msecs_to_jiffies(3142));
|
||||
queue_delayed_work(system_power_efficient_wq,
|
||||
®_timeout, msecs_to_jiffies(3142));
|
||||
return;
|
||||
case NL80211_REGDOM_SET_BY_DRIVER:
|
||||
if (!wiphy)
|
||||
goto out_free;
|
||||
treatment = reg_process_hint_driver(wiphy, reg_request);
|
||||
break;
|
||||
case NL80211_REGDOM_SET_BY_COUNTRY_IE:
|
||||
if (!wiphy)
|
||||
goto out_free;
|
||||
treatment = reg_process_hint_country_ie(wiphy, reg_request);
|
||||
break;
|
||||
default:
|
||||
WARN(1, "invalid initiator %d\n", reg_request->initiator);
|
||||
return;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
/* This is required so that the orig_* parameters are saved */
|
||||
if (treatment == REG_REQ_ALREADY_SET && wiphy &&
|
||||
wiphy->regulatory_flags & REGULATORY_STRICT_REG)
|
||||
wiphy_update_regulatory(wiphy, reg_request->initiator);
|
||||
|
||||
return;
|
||||
|
||||
out_free:
|
||||
kfree(reg_request);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2147,6 +2245,7 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd)
|
||||
const struct ieee80211_reg_rule *reg_rule = NULL;
|
||||
const struct ieee80211_freq_range *freq_range = NULL;
|
||||
const struct ieee80211_power_rule *power_rule = NULL;
|
||||
char bw[32];
|
||||
|
||||
pr_info(" (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp)\n");
|
||||
|
||||
@@ -2155,22 +2254,29 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd)
|
||||
freq_range = ®_rule->freq_range;
|
||||
power_rule = ®_rule->power_rule;
|
||||
|
||||
if (!freq_range->max_bandwidth_khz)
|
||||
snprintf(bw, 32, "%d KHz, AUTO",
|
||||
reg_get_max_bandwidth(rd, reg_rule));
|
||||
else
|
||||
snprintf(bw, 32, "%d KHz",
|
||||
freq_range->max_bandwidth_khz);
|
||||
|
||||
/*
|
||||
* There may not be documentation for max antenna gain
|
||||
* in certain regions
|
||||
*/
|
||||
if (power_rule->max_antenna_gain)
|
||||
pr_info(" (%d KHz - %d KHz @ %d KHz), (%d mBi, %d mBm)\n",
|
||||
pr_info(" (%d KHz - %d KHz @ %s), (%d mBi, %d mBm)\n",
|
||||
freq_range->start_freq_khz,
|
||||
freq_range->end_freq_khz,
|
||||
freq_range->max_bandwidth_khz,
|
||||
bw,
|
||||
power_rule->max_antenna_gain,
|
||||
power_rule->max_eirp);
|
||||
else
|
||||
pr_info(" (%d KHz - %d KHz @ %d KHz), (N/A, %d mBm)\n",
|
||||
pr_info(" (%d KHz - %d KHz @ %s), (N/A, %d mBm)\n",
|
||||
freq_range->start_freq_khz,
|
||||
freq_range->end_freq_khz,
|
||||
freq_range->max_bandwidth_khz,
|
||||
bw,
|
||||
power_rule->max_eirp);
|
||||
}
|
||||
}
|
||||
@@ -2294,7 +2400,8 @@ static int reg_set_rd_driver(const struct ieee80211_regdomain *rd,
|
||||
|
||||
request_wiphy = wiphy_idx_to_wiphy(driver_request->wiphy_idx);
|
||||
if (!request_wiphy) {
|
||||
schedule_delayed_work(®_timeout, 0);
|
||||
queue_delayed_work(system_power_efficient_wq,
|
||||
®_timeout, 0);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
@@ -2354,7 +2461,8 @@ static int reg_set_rd_country_ie(const struct ieee80211_regdomain *rd,
|
||||
|
||||
request_wiphy = wiphy_idx_to_wiphy(country_ie_request->wiphy_idx);
|
||||
if (!request_wiphy) {
|
||||
schedule_delayed_work(®_timeout, 0);
|
||||
queue_delayed_work(system_power_efficient_wq,
|
||||
®_timeout, 0);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@@ -34,6 +34,8 @@ int __init regulatory_init(void);
|
||||
void regulatory_exit(void);
|
||||
|
||||
int set_regdom(const struct ieee80211_regdomain *rd);
|
||||
unsigned int reg_get_max_bandwidth(const struct ieee80211_regdomain *rd,
|
||||
const struct ieee80211_reg_rule *rule);
|
||||
|
||||
bool reg_last_request_cell_base(void);
|
||||
|
||||
|
@@ -2278,11 +2278,6 @@ DECLARE_EVENT_CLASS(cfg80211_rx_evt,
|
||||
TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT, NETDEV_PR_ARG, MAC_PR_ARG(addr))
|
||||
);
|
||||
|
||||
DEFINE_EVENT(cfg80211_rx_evt, cfg80211_ibss_joined,
|
||||
TP_PROTO(struct net_device *netdev, const u8 *addr),
|
||||
TP_ARGS(netdev, addr)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(cfg80211_rx_evt, cfg80211_rx_spurious_frame,
|
||||
TP_PROTO(struct net_device *netdev, const u8 *addr),
|
||||
TP_ARGS(netdev, addr)
|
||||
@@ -2293,6 +2288,24 @@ DEFINE_EVENT(cfg80211_rx_evt, cfg80211_rx_unexpected_4addr_frame,
|
||||
TP_ARGS(netdev, addr)
|
||||
);
|
||||
|
||||
TRACE_EVENT(cfg80211_ibss_joined,
|
||||
TP_PROTO(struct net_device *netdev, const u8 *bssid,
|
||||
struct ieee80211_channel *channel),
|
||||
TP_ARGS(netdev, bssid, channel),
|
||||
TP_STRUCT__entry(
|
||||
NETDEV_ENTRY
|
||||
MAC_ENTRY(bssid)
|
||||
CHAN_ENTRY
|
||||
),
|
||||
TP_fast_assign(
|
||||
NETDEV_ASSIGN;
|
||||
MAC_ASSIGN(bssid, bssid);
|
||||
CHAN_ASSIGN(channel);
|
||||
),
|
||||
TP_printk(NETDEV_PR_FMT ", bssid: " MAC_PR_FMT ", " CHAN_PR_FMT,
|
||||
NETDEV_PR_ARG, MAC_PR_ARG(bssid), CHAN_PR_ARG)
|
||||
);
|
||||
|
||||
TRACE_EVENT(cfg80211_probe_status,
|
||||
TP_PROTO(struct net_device *netdev, const u8 *addr, u64 cookie,
|
||||
bool acked),
|
||||
|
@@ -820,7 +820,8 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev)
|
||||
ev->dc.reason, true);
|
||||
break;
|
||||
case EVENT_IBSS_JOINED:
|
||||
__cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid);
|
||||
__cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid,
|
||||
ev->ij.channel);
|
||||
break;
|
||||
}
|
||||
wdev_unlock(wdev);
|
||||
@@ -1356,7 +1357,7 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
|
||||
*/
|
||||
mutex_lock_nested(&wdev_iter->mtx, 1);
|
||||
__acquire(wdev_iter->mtx);
|
||||
cfg80211_get_chan_state(wdev_iter, &ch, &chmode);
|
||||
cfg80211_get_chan_state(wdev_iter, &ch, &chmode, &radar_detect);
|
||||
wdev_unlock(wdev_iter);
|
||||
|
||||
switch (chmode) {
|
||||
|
在新工单中引用
屏蔽一个用户