mac80211: merge another round of upstream fixes

Signed-off-by: Felix Fietkau <nbd@openwrt.org>

SVN-Revision: 38918
This commit is contained in:
Felix Fietkau 2013-11-26 11:25:31 +00:00
parent bb2b428a5c
commit 78f4ab6fc0
4 changed files with 584 additions and 31 deletions

View file

@ -2967,28 +2967,42 @@
enum nl80211_radar_event event, gfp_t gfp);
@@ -4282,7 +4283,8 @@ bool cfg80211_reg_can_beacon(struct wiph
* @dev: the device which switched channels
* @chandef: the new channel definition
*
- * Acquires wdev_lock, so must only be called from sleepable driver context!
+ * Caller must acquire wdev_lock, therefore must only be called from sleepable
+ * driver context!
*/
void cfg80211_ch_switch_notify(struct net_device *dev,
struct cfg80211_chan_def *chandef);
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -1508,6 +1508,9 @@ enum nl80211_commands {
@@ -1508,6 +1508,12 @@ enum nl80211_commands {
* to react to radar events, e.g. initiate a channel switch or leave the
* IBSS network.
*
+ * @NL80211_ATTR_SUPPORT_5_10_MHZ: A flag indicating that the device supports
+ * 5 MHz and 10 MHz channel bandwidth.
+ * @NL80211_ATTR_SUPPORT_5_MHZ: A flag indicating that the device supports
+ * 5 MHz channel bandwidth.
+ *
+ * @NL80211_ATTR_SUPPORT_10_MHZ: A flag indicating that the device supports
+ * 10 MHz channel bandwidth.
+ *
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
@@ -1824,6 +1827,8 @@ enum nl80211_attrs {
@@ -1824,6 +1830,9 @@ enum nl80211_attrs {
NL80211_ATTR_HANDLE_DFS,
+ NL80211_ATTR_SUPPORT_5_10_MHZ,
+ NL80211_ATTR_SUPPORT_5_MHZ,
+ NL80211_ATTR_SUPPORT_10_MHZ,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -2224,10 +2229,9 @@ enum nl80211_band_attr {
@@ -2224,10 +2233,9 @@ enum nl80211_band_attr {
* @NL80211_FREQUENCY_ATTR_FREQ: Frequency in MHz
* @NL80211_FREQUENCY_ATTR_DISABLED: Channel is disabled in current
* regulatory domain.
@ -3002,7 +3016,7 @@
* @NL80211_FREQUENCY_ATTR_RADAR: Radar detection is mandatory
* on this channel in current regulatory domain.
* @NL80211_FREQUENCY_ATTR_MAX_TX_POWER: Maximum transmission power in mBm
@@ -2254,8 +2258,8 @@ enum nl80211_frequency_attr {
@@ -2254,8 +2262,8 @@ enum nl80211_frequency_attr {
__NL80211_FREQUENCY_ATTR_INVALID,
NL80211_FREQUENCY_ATTR_FREQ,
NL80211_FREQUENCY_ATTR_DISABLED,
@ -3013,7 +3027,7 @@
NL80211_FREQUENCY_ATTR_RADAR,
NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
NL80211_FREQUENCY_ATTR_DFS_STATE,
@@ -2271,6 +2275,9 @@ enum nl80211_frequency_attr {
@@ -2271,6 +2279,9 @@ enum nl80211_frequency_attr {
};
#define NL80211_FREQUENCY_ATTR_MAX_TX_POWER NL80211_FREQUENCY_ATTR_MAX_TX_POWER
@ -3023,7 +3037,7 @@
/**
* enum nl80211_bitrate_attr - bitrate attributes
@@ -2413,8 +2420,9 @@ enum nl80211_sched_scan_match_attr {
@@ -2413,8 +2424,9 @@ enum nl80211_sched_scan_match_attr {
* @NL80211_RRF_DFS: DFS support is required to be used
* @NL80211_RRF_PTP_ONLY: this is only for Point To Point links
* @NL80211_RRF_PTMP_ONLY: this is only for Point To Multi Point links
@ -3035,7 +3049,7 @@
*/
enum nl80211_reg_rule_flags {
NL80211_RRF_NO_OFDM = 1<<0,
@@ -2424,10 +2432,17 @@ enum nl80211_reg_rule_flags {
@@ -2424,10 +2436,17 @@ enum nl80211_reg_rule_flags {
NL80211_RRF_DFS = 1<<4,
NL80211_RRF_PTP_ONLY = 1<<5,
NL80211_RRF_PTMP_ONLY = 1<<6,
@ -3057,15 +3071,76 @@
*
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1050,6 +1050,7 @@ static int ieee80211_stop_ap(struct wiph
@@ -846,7 +846,7 @@ static int ieee80211_set_probe_resp(stru
if (!resp || !resp_len)
return 1;
- old = rtnl_dereference(sdata->u.ap.probe_resp);
+ old = sdata_dereference(sdata->u.ap.probe_resp, sdata);
new = kzalloc(sizeof(struct probe_resp) + resp_len, GFP_KERNEL);
if (!new)
@@ -870,7 +870,8 @@ int ieee80211_assign_beacon(struct ieee8
int size, err;
u32 changed = BSS_CHANGED_BEACON;
- old = rtnl_dereference(sdata->u.ap.beacon);
+ old = sdata_dereference(sdata->u.ap.beacon, sdata);
+
/* Need to have a beacon head if we don't have one yet */
if (!params->head && !old)
@@ -947,7 +948,7 @@ static int ieee80211_start_ap(struct wip
BSS_CHANGED_P2P_PS;
int err;
- old = rtnl_dereference(sdata->u.ap.beacon);
+ old = sdata_dereference(sdata->u.ap.beacon, sdata);
if (old)
return -EALREADY;
@@ -1001,7 +1002,8 @@ static int ieee80211_start_ap(struct wip
err = drv_start_ap(sdata->local, sdata);
if (err) {
- old = rtnl_dereference(sdata->u.ap.beacon);
+ old = sdata_dereference(sdata->u.ap.beacon, sdata);
+
if (old)
kfree_rcu(old, rcu_head);
RCU_INIT_POINTER(sdata->u.ap.beacon, NULL);
@@ -1032,7 +1034,7 @@ static int ieee80211_change_beacon(struc
if (sdata->vif.csa_active)
return -EBUSY;
- old = rtnl_dereference(sdata->u.ap.beacon);
+ old = sdata_dereference(sdata->u.ap.beacon, sdata);
if (!old)
return -ENOENT;
@@ -1050,15 +1052,18 @@ static int ieee80211_stop_ap(struct wiph
struct ieee80211_local *local = sdata->local;
struct beacon_data *old_beacon;
struct probe_resp *old_probe_resp;
+ struct cfg80211_chan_def chandef;
old_beacon = rtnl_dereference(sdata->u.ap.beacon);
- old_beacon = rtnl_dereference(sdata->u.ap.beacon);
+ old_beacon = sdata_dereference(sdata->u.ap.beacon, sdata);
if (!old_beacon)
@@ -1091,8 +1092,10 @@ static int ieee80211_stop_ap(struct wiph
return -ENOENT;
- old_probe_resp = rtnl_dereference(sdata->u.ap.probe_resp);
+ old_probe_resp = sdata_dereference(sdata->u.ap.probe_resp, sdata);
/* abort any running channel switch */
sdata->vif.csa_active = false;
- cancel_work_sync(&sdata->csa_finalize_work);
+ kfree(sdata->u.ap.next_beacon);
+ sdata->u.ap.next_beacon = NULL;
+
cancel_work_sync(&sdata->u.ap.request_smps_work);
/* turn off carrier for this interface and dependent VLANs */
@@ -1091,8 +1096,10 @@ static int ieee80211_stop_ap(struct wiph
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
if (sdata->wdev.cac_started) {
@ -3077,6 +3152,128 @@
GFP_KERNEL);
}
@@ -1368,7 +1375,7 @@ static int sta_apply_parameters(struct i
changed |=
ieee80211_mps_set_sta_local_pm(sta,
params->local_pm);
- ieee80211_bss_info_change_notify(sdata, changed);
+ ieee80211_mbss_info_change_notify(sdata, changed);
#endif
}
@@ -1953,7 +1960,7 @@ static int ieee80211_change_bss(struct w
enum ieee80211_band band;
u32 changed = 0;
- if (!rtnl_dereference(sdata->u.ap.beacon))
+ if (!sdata_dereference(sdata->u.ap.beacon, sdata))
return -ENOENT;
band = ieee80211_get_sdata_band(sdata);
@@ -2964,27 +2971,33 @@ void ieee80211_csa_finalize_work(struct
struct ieee80211_local *local = sdata->local;
int err, changed = 0;
+ sdata_lock(sdata);
+ /* AP might have been stopped while waiting for the lock. */
+ if (!sdata->vif.csa_active)
+ goto unlock;
+
if (!ieee80211_sdata_running(sdata))
- return;
+ goto unlock;
sdata->radar_required = sdata->csa_radar_required;
- err = ieee80211_vif_change_channel(sdata, &local->csa_chandef,
- &changed);
+ err = ieee80211_vif_change_channel(sdata, &changed);
if (WARN_ON(err < 0))
- return;
+ goto unlock;
if (!local->use_chanctx) {
- local->_oper_chandef = local->csa_chandef;
+ local->_oper_chandef = sdata->csa_chandef;
ieee80211_hw_config(local, 0);
}
ieee80211_bss_info_change_notify(sdata, changed);
+ sdata->vif.csa_active = false;
switch (sdata->vif.type) {
case NL80211_IFTYPE_AP:
err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon);
if (err < 0)
- return;
+ goto unlock;
+
changed |= err;
kfree(sdata->u.ap.next_beacon);
sdata->u.ap.next_beacon = NULL;
@@ -2998,20 +3011,22 @@ void ieee80211_csa_finalize_work(struct
case NL80211_IFTYPE_MESH_POINT:
err = ieee80211_mesh_finish_csa(sdata);
if (err < 0)
- return;
+ goto unlock;
break;
#endif
default:
WARN_ON(1);
- return;
+ goto unlock;
}
- sdata->vif.csa_active = false;
ieee80211_wake_queues_by_reason(&sdata->local->hw,
IEEE80211_MAX_QUEUE_MAP,
IEEE80211_QUEUE_STOP_REASON_CSA);
- cfg80211_ch_switch_notify(sdata->dev, &local->csa_chandef);
+ cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef);
+
+unlock:
+ sdata_unlock(sdata);
}
static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
@@ -3024,6 +3039,8 @@ static int ieee80211_channel_switch(stru
struct ieee80211_if_mesh __maybe_unused *ifmsh;
int err, num_chanctx;
+ lockdep_assert_held(&sdata->wdev.mtx);
+
if (!list_empty(&local->roc_list) || local->scanning)
return -EBUSY;
@@ -3120,9 +3137,17 @@ static int ieee80211_channel_switch(stru
params->chandef.chan->band)
return -EINVAL;
+ ifmsh->chsw_init = true;
+ if (!ifmsh->pre_value)
+ ifmsh->pre_value = 1;
+ else
+ ifmsh->pre_value++;
+
err = ieee80211_mesh_csa_beacon(sdata, params, true);
- if (err < 0)
+ if (err < 0) {
+ ifmsh->chsw_init = false;
return err;
+ }
break;
#endif
default:
@@ -3136,7 +3161,7 @@ static int ieee80211_channel_switch(stru
IEEE80211_MAX_QUEUE_MAP,
IEEE80211_QUEUE_STOP_REASON_CSA);
- local->csa_chandef = params->chandef;
+ sdata->csa_chandef = params->chandef;
sdata->vif.csa_active = true;
ieee80211_bss_info_change_notify(sdata, err);
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -749,6 +749,7 @@ static void ieee80211_do_stop(struct iee
@ -3112,7 +3309,44 @@
break;
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1398,10 +1398,12 @@ void ieee80211_dfs_cac_timer_work(struct
@@ -886,8 +886,7 @@ static void ieee80211_chswitch_work(stru
if (!ifmgd->associated)
goto out;
- ret = ieee80211_vif_change_channel(sdata, &local->csa_chandef,
- &changed);
+ ret = ieee80211_vif_change_channel(sdata, &changed);
if (ret) {
sdata_info(sdata,
"vif channel switch failed, disconnecting\n");
@@ -897,7 +896,7 @@ static void ieee80211_chswitch_work(stru
}
if (!local->use_chanctx) {
- local->_oper_chandef = local->csa_chandef;
+ local->_oper_chandef = sdata->csa_chandef;
/* Call "hw_config" only if doing sw channel switch.
* Otherwise update the channel directly
*/
@@ -908,7 +907,7 @@ static void ieee80211_chswitch_work(stru
}
/* XXX: shouldn't really modify cfg80211-owned data! */
- ifmgd->associated->channel = local->csa_chandef.chan;
+ ifmgd->associated->channel = sdata->csa_chandef.chan;
/* XXX: wait for a beacon first? */
ieee80211_wake_queues_by_reason(&local->hw,
@@ -1035,7 +1034,7 @@ ieee80211_sta_process_chanswitch(struct
}
mutex_unlock(&local->chanctx_mtx);
- local->csa_chandef = csa_ie.chandef;
+ sdata->csa_chandef = csa_ie.chandef;
if (csa_ie.mode)
ieee80211_stop_queues_by_reason(&local->hw,
@@ -1398,10 +1397,12 @@ void ieee80211_dfs_cac_timer_work(struct
struct ieee80211_sub_if_data *sdata =
container_of(delayed_work, struct ieee80211_sub_if_data,
dfs_cac_timer_work);
@ -3267,6 +3501,21 @@
NL80211_RADAR_CAC_ABORTED,
GFP_KERNEL);
}
@@ -2459,14 +2462,9 @@ int ieee80211_send_action_csa(struct iee
WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT : 0x00;
put_unaligned_le16(WLAN_REASON_MESH_CHAN, pos); /* Reason Cd */
pos += 2;
- if (!ifmsh->pre_value)
- ifmsh->pre_value = 1;
- else
- ifmsh->pre_value++;
pre_value = cpu_to_le16(ifmsh->pre_value);
memcpy(pos, &pre_value, 2); /* Precedence Value */
pos += 2;
- ifmsh->chsw_init = true;
}
ieee80211_tx_skb(sdata, skb);
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -277,6 +277,32 @@ void cfg80211_set_dfs_state(struct wiphy
@ -3649,16 +3898,17 @@
if (chan->flags & IEEE80211_CHAN_RADAR) {
if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR))
goto nla_put_failure;
@@ -1229,7 +1229,7 @@ static int nl80211_send_wiphy(struct cfg
@@ -1229,7 +1229,8 @@ static int nl80211_send_wiphy(struct cfg
nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP))
goto nla_put_failure;
if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ) &&
- nla_put_flag(msg, WIPHY_FLAG_SUPPORTS_5_10_MHZ))
+ nla_put_flag(msg, NL80211_ATTR_SUPPORT_5_10_MHZ))
+ (nla_put_flag(msg, NL80211_ATTR_SUPPORT_5_MHZ) ||
+ nla_put_flag(msg, NL80211_ATTR_SUPPORT_10_MHZ)))
goto nla_put_failure;
state->split_start++;
@@ -2170,7 +2170,7 @@ static inline u64 wdev_id(struct wireles
@@ -2170,7 +2171,7 @@ static inline u64 wdev_id(struct wireles
}
static int nl80211_send_chandef(struct sk_buff *msg,
@ -3667,7 +3917,59 @@
{
WARN_ON(!cfg80211_chandef_valid(chandef));
@@ -5653,7 +5653,7 @@ static int nl80211_start_radar_detection
@@ -3219,6 +3220,7 @@ static int nl80211_start_ap(struct sk_bu
return PTR_ERR(params.acl);
}
+ wdev_lock(wdev);
err = rdev_start_ap(rdev, dev, &params);
if (!err) {
wdev->preset_chandef = params.chandef;
@@ -3227,6 +3229,7 @@ static int nl80211_start_ap(struct sk_bu
wdev->ssid_len = params.ssid_len;
memcpy(wdev->ssid, params.ssid, wdev->ssid_len);
}
+ wdev_unlock(wdev);
kfree(params.acl);
@@ -3255,7 +3258,11 @@ static int nl80211_set_beacon(struct sk_
if (err)
return err;
- return rdev_change_beacon(rdev, dev, &params);
+ wdev_lock(wdev);
+ err = rdev_change_beacon(rdev, dev, &params);
+ wdev_unlock(wdev);
+
+ return err;
}
static int nl80211_stop_ap(struct sk_buff *skb, struct genl_info *info)
@@ -4461,7 +4468,9 @@ static int nl80211_set_bss(struct sk_buf
{
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 bss_parameters params;
+ int err;
memset(&params, 0, sizeof(params));
/* default to not changing parameters */
@@ -4527,7 +4536,11 @@ static int nl80211_set_bss(struct sk_buf
dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
return -EOPNOTSUPP;
- return rdev_change_bss(rdev, dev, &params);
+ wdev_lock(wdev);
+ err = rdev_change_bss(rdev, dev, &params);
+ wdev_unlock(wdev);
+
+ return err;
}
static const struct nla_policy reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = {
@@ -5653,7 +5666,7 @@ static int nl80211_start_radar_detection
if (err == 0)
return -EINVAL;
@ -3676,7 +3978,45 @@
return -EINVAL;
if (!rdev->ops->start_radar_detection)
@@ -10882,7 +10882,7 @@ EXPORT_SYMBOL(cfg80211_cqm_txe_notify);
@@ -5793,7 +5806,11 @@ skip_beacons:
if (info->attrs[NL80211_ATTR_CH_SWITCH_BLOCK_TX])
params.block_tx = true;
- return rdev_channel_switch(rdev, dev, &params);
+ wdev_lock(wdev);
+ err = rdev_channel_switch(rdev, dev, &params);
+ wdev_unlock(wdev);
+
+ return err;
}
static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
@@ -10809,21 +10826,18 @@ void cfg80211_ch_switch_notify(struct ne
struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
- trace_cfg80211_ch_switch_notify(dev, chandef);
+ ASSERT_WDEV_LOCK(wdev);
- wdev_lock(wdev);
+ trace_cfg80211_ch_switch_notify(dev, chandef);
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
wdev->iftype != NL80211_IFTYPE_P2P_GO &&
wdev->iftype != NL80211_IFTYPE_ADHOC &&
wdev->iftype != NL80211_IFTYPE_MESH_POINT))
- goto out;
+ return;
wdev->channel = chandef->chan;
nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL);
-out:
- wdev_unlock(wdev);
- return;
}
EXPORT_SYMBOL(cfg80211_ch_switch_notify);
@@ -10882,7 +10896,7 @@ EXPORT_SYMBOL(cfg80211_cqm_txe_notify);
void
nl80211_radar_notify(struct cfg80211_registered_device *rdev,
@ -4772,3 +5112,216 @@
mr->cur_tp = MINSTREL_TRUNC(tp);
}
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
@@ -3984,18 +3984,20 @@ static void ar9003_hw_quick_drop_apply(s
int quick_drop;
s32 t[3], f[3] = {5180, 5500, 5785};
- if (!(pBase->miscConfiguration & BIT(1)))
+ if (!(pBase->miscConfiguration & BIT(4)))
return;
- if (freq < 4000)
- quick_drop = eep->modalHeader2G.quick_drop;
- else {
- t[0] = eep->base_ext1.quick_drop_low;
- t[1] = eep->modalHeader5G.quick_drop;
- t[2] = eep->base_ext1.quick_drop_high;
- quick_drop = ar9003_hw_power_interpolate(freq, f, t, 3);
+ if (AR_SREV_9300(ah) || AR_SREV_9580(ah) || AR_SREV_9340(ah)) {
+ if (freq < 4000) {
+ quick_drop = eep->modalHeader2G.quick_drop;
+ } else {
+ t[0] = eep->base_ext1.quick_drop_low;
+ t[1] = eep->modalHeader5G.quick_drop;
+ t[2] = eep->base_ext1.quick_drop_high;
+ quick_drop = ar9003_hw_power_interpolate(freq, f, t, 3);
+ }
+ REG_RMW_FIELD(ah, AR_PHY_AGC, AR_PHY_AGC_QUICK_DROP, quick_drop);
}
- REG_RMW_FIELD(ah, AR_PHY_AGC, AR_PHY_AGC_QUICK_DROP, quick_drop);
}
static void ar9003_hw_txend_to_xpa_off_apply(struct ath_hw *ah, bool is2ghz)
@@ -4035,7 +4037,7 @@ static void ar9003_hw_xlna_bias_strength
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
u8 bias;
- if (!(eep->baseEepHeader.featureEnable & 0x40))
+ if (!(eep->baseEepHeader.miscConfiguration & 0x40))
return;
if (!AR_SREV_9300(ah))
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -735,6 +735,7 @@ struct ieee80211_sub_if_data {
int csa_counter_offset_beacon;
int csa_counter_offset_presp;
bool csa_radar_required;
+ struct cfg80211_chan_def csa_chandef;
/* used to reconfigure hardware SM PS */
struct work_struct recalc_smps;
@@ -811,6 +812,9 @@ static inline void sdata_unlock(struct i
__release(&sdata->wdev.mtx);
}
+#define sdata_dereference(p, sdata) \
+ rcu_dereference_protected(p, lockdep_is_held(&sdata->wdev.mtx))
+
static inline void
sdata_assert_lock(struct ieee80211_sub_if_data *sdata)
{
@@ -1098,7 +1102,6 @@ struct ieee80211_local {
enum mac80211_scan_state next_scan_state;
struct delayed_work scan_work;
struct ieee80211_sub_if_data __rcu *scan_sdata;
- struct cfg80211_chan_def csa_chandef;
/* For backward compatibility only -- do not use */
struct cfg80211_chan_def _oper_chandef;
@@ -1236,6 +1239,7 @@ struct ieee80211_csa_ie {
u8 mode;
u8 count;
u8 ttl;
+ u16 pre_value;
};
/* Parsed Information Elements */
@@ -1738,7 +1742,6 @@ ieee80211_vif_change_bandwidth(struct ie
/* NOTE: only use ieee80211_vif_change_channel() for channel switch */
int __must_check
ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata,
- const struct cfg80211_chan_def *chandef,
u32 *changed);
void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata);
void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata);
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -411,12 +411,12 @@ int ieee80211_vif_use_channel(struct iee
}
int ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata,
- const struct cfg80211_chan_def *chandef,
u32 *changed)
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_chanctx_conf *conf;
struct ieee80211_chanctx *ctx;
+ const struct cfg80211_chan_def *chandef = &sdata->csa_chandef;
int ret;
u32 chanctx_changed = 0;
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -550,12 +550,12 @@ int ieee80211_ibss_finish_csa(struct iee
capability);
/* XXX: should not really modify cfg80211 data */
if (cbss) {
- cbss->channel = sdata->local->csa_chandef.chan;
+ cbss->channel = sdata->csa_chandef.chan;
cfg80211_put_bss(sdata->local->hw.wiphy, cbss);
}
}
- ifibss->chandef = sdata->local->csa_chandef;
+ ifibss->chandef = sdata->csa_chandef;
/* generate the beacon */
err = ieee80211_ibss_csa_beacon(sdata, NULL);
@@ -922,7 +922,7 @@ ieee80211_ibss_process_chanswitch(struct
IEEE80211_MAX_QUEUE_MAP,
IEEE80211_QUEUE_STOP_REASON_CSA);
- sdata->local->csa_chandef = params.chandef;
+ sdata->csa_chandef = params.chandef;
sdata->vif.csa_active = true;
ieee80211_bss_info_change_notify(sdata, err);
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -943,14 +943,19 @@ ieee80211_mesh_process_chnswitch(struct
params.chandef.chan->center_freq);
params.block_tx = csa_ie.mode & WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT;
- if (beacon)
+ if (beacon) {
ifmsh->chsw_ttl = csa_ie.ttl - 1;
- else
- ifmsh->chsw_ttl = 0;
+ if (ifmsh->pre_value >= csa_ie.pre_value)
+ return false;
+ ifmsh->pre_value = csa_ie.pre_value;
+ }
- if (ifmsh->chsw_ttl > 0)
+ if (ifmsh->chsw_ttl < ifmsh->mshcfg.dot11MeshTTL) {
if (ieee80211_mesh_csa_beacon(sdata, &params, false) < 0)
return false;
+ } else {
+ return false;
+ }
sdata->csa_radar_required = params.radar_required;
@@ -959,7 +964,7 @@ ieee80211_mesh_process_chnswitch(struct
IEEE80211_MAX_QUEUE_MAP,
IEEE80211_QUEUE_STOP_REASON_CSA);
- sdata->local->csa_chandef = params.chandef;
+ sdata->csa_chandef = params.chandef;
sdata->vif.csa_active = true;
ieee80211_bss_info_change_notify(sdata, err);
@@ -1163,7 +1168,6 @@ static int mesh_fwd_csa_frame(struct iee
offset_ttl = (len < 42) ? 7 : 10;
*(pos + offset_ttl) -= 1;
*(pos + offset_ttl + 1) &= ~WLAN_EID_CHAN_SWITCH_PARAM_INITIATOR;
- sdata->u.mesh.chsw_ttl = *(pos + offset_ttl);
memcpy(mgmt_fwd, mgmt, len);
eth_broadcast_addr(mgmt_fwd->da);
@@ -1182,7 +1186,7 @@ static void mesh_rx_csa_frame(struct iee
u16 pre_value;
bool fwd_csa = true;
size_t baselen;
- u8 *pos, ttl;
+ u8 *pos;
if (mgmt->u.action.u.measurement.action_code !=
WLAN_ACTION_SPCT_CHL_SWITCH)
@@ -1193,8 +1197,8 @@ static void mesh_rx_csa_frame(struct iee
u.action.u.chan_switch.variable);
ieee802_11_parse_elems(pos, len - baselen, false, &elems);
- ttl = elems.mesh_chansw_params_ie->mesh_ttl;
- if (!--ttl)
+ ifmsh->chsw_ttl = elems.mesh_chansw_params_ie->mesh_ttl;
+ if (!--ifmsh->chsw_ttl)
fwd_csa = false;
pre_value = le16_to_cpu(elems.mesh_chansw_params_ie->mesh_pre_value);
--- a/net/mac80211/spectmgmt.c
+++ b/net/mac80211/spectmgmt.c
@@ -78,6 +78,8 @@ int ieee80211_parse_ch_switch_ie(struct
if (elems->mesh_chansw_params_ie) {
csa_ie->ttl = elems->mesh_chansw_params_ie->mesh_ttl;
csa_ie->mode = elems->mesh_chansw_params_ie->mesh_flags;
+ csa_ie->pre_value = le16_to_cpu(
+ elems->mesh_chansw_params_ie->mesh_pre_value);
}
new_freq = ieee80211_channel_to_frequency(new_chan_no, new_band);
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -1109,7 +1109,9 @@ void ath6kl_cfg80211_ch_switch_notify(st
(mode == WMI_11G_HT20) ?
NL80211_CHAN_HT20 : NL80211_CHAN_NO_HT);
+ mutex_lock(vif->wdev->mtx);
cfg80211_ch_switch_notify(vif->ndev, &chandef);
+ mutex_unlock(vif->wdev->mtx);
}
static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,

View file

@ -1,6 +1,6 @@
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2113,7 +2113,7 @@ static int ieee80211_scan(struct wiphy *
@@ -2117,7 +2117,7 @@ static int ieee80211_scan(struct wiphy *
* the frames sent while scanning on other channel will be
* lost)
*/

View file

@ -10,7 +10,7 @@
u8 uapsd_queues;
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2294,7 +2294,9 @@ static int ieee80211_get_tx_power(struct
@@ -2298,7 +2298,9 @@ static int ieee80211_get_tx_power(struct
struct ieee80211_local *local = wiphy_priv(wiphy);
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);

View file

@ -36,9 +36,9 @@
u8 ps_dtim_period;
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -1511,6 +1511,9 @@ enum nl80211_commands {
* @NL80211_ATTR_SUPPORT_5_10_MHZ: A flag indicating that the device supports
* 5 MHz and 10 MHz channel bandwidth.
@@ -1514,6 +1514,9 @@ enum nl80211_commands {
* @NL80211_ATTR_SUPPORT_10_MHZ: A flag indicating that the device supports
* 10 MHz channel bandwidth.
*
+ * @NL80211_ATTR_WIPHY_ANTENNA_GAIN: Configured antenna gain. Used to reduce
+ * transmit power to stay within regulatory limits. u32, dBi.
@ -46,9 +46,9 @@
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
@@ -1829,6 +1832,8 @@ enum nl80211_attrs {
NL80211_ATTR_SUPPORT_5_10_MHZ,
@@ -1833,6 +1836,8 @@ enum nl80211_attrs {
NL80211_ATTR_SUPPORT_5_MHZ,
NL80211_ATTR_SUPPORT_10_MHZ,
+ NL80211_ATTR_WIPHY_ANTENNA_GAIN,
+
@ -57,7 +57,7 @@
__NL80211_ATTR_AFTER_LAST,
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2304,6 +2304,19 @@ static int ieee80211_get_tx_power(struct
@@ -2308,6 +2308,19 @@ static int ieee80211_get_tx_power(struct
return 0;
}
@ -77,7 +77,7 @@
static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev,
const u8 *addr)
{
@@ -3839,6 +3852,7 @@ struct cfg80211_ops mac80211_config_ops
@@ -3861,6 +3874,7 @@ struct cfg80211_ops mac80211_config_ops
.set_wiphy_params = ieee80211_set_wiphy_params,
.set_tx_power = ieee80211_set_tx_power,
.get_tx_power = ieee80211_get_tx_power,
@ -87,7 +87,7 @@
CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1182,6 +1182,7 @@ struct ieee80211_local {
@@ -1185,6 +1185,7 @@ struct ieee80211_local {
int dynamic_ps_forced_timeout;
int user_power_level; /* in dBm, for all interfaces */
@ -147,7 +147,7 @@
};
/* policy for the key attributes */
@@ -2038,6 +2039,22 @@ static int nl80211_set_wiphy(struct sk_b
@@ -2039,6 +2040,22 @@ static int nl80211_set_wiphy(struct sk_b
goto bad_res;
}