For the first round of fixes, we have this:
* fix for the sizeof() pointer type issue * a fix for regulatory getting into a restore loop * a fix for rfkill global 'all' state, it needs to be stored everywhere to apply correctly to new rfkill instances * properly refuse CQM RSSI when it cannot actually be used * protect HT TDLS traffic properly in non-HT networks * don't incorrectly advertise 80 MHz support when not allowed -----BEGIN PGP SIGNATURE----- iQIcBAABCAAGBQJV6av+AAoJEDBSmw7B7bqrNYYP/1kZjdk9s4wPHpQndfSWK/sj yTjysh/VXZ5Jyzkcmg337AjEuuJ/SntDXjMXEKTxHHrt5fmHFBvmPErPUY7p7I/t MJqxVnYGypGW4LImyXYRJbejabmPrxtHC+jcWibw24yBCzJGCXF/MeKCotksnvIn IoJDvUHrVFZhfzFRepdozJi1Qy2Y04Q7zXywplW6XFYWxdfDWaWyno/xh+rM8oO7 xSgpkuj4FDfimDBjzJOHwBH3xOlt/uHoB97G0TJbJ6k0R6a8aTz8eK5OWB4rFcn+ BsuQfaWcrGg9fJsoqz4mYlWf/F4Qj/gU9Gr5sBUWWa0xQ7HctcgJ/t27XjUWP7oV VnQ9YQt/SukG3BVf8GuNqaSo7/7oprWHdDYRH0tnvImXCWsUlHM8gv8MrG0UOHGC 4I4qgPLHon6Ui3lNHfivl8iSDFT+jfsMDMWiB6kKZRpUOdEicRrepMoDARVbTYck h6uY4Tx6OQ39evLSXjyrCWb0aOr2WoDCypxEkpE+fgDsWr8yTV0Ti0QZfVqatO3d d4GQb6U5Zkd14ymKtzULa5qjOw1TmnKpxVzSSdrONaPBVdUDsl4QH38gIppFjGsV 61Gn3PXRRgy+VAib/YyIYqilvdhZ2TdXaSVAEyKv6WjKavOFA/8KsDPmJsyKoCSn 1dDOwaiqgfu2bK1PTU9A =xw8r -----END PGP SIGNATURE----- Merge tag 'mac80211-for-davem-2015-09-04' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211 Johannes Berg says: ==================== For the first round of fixes, we have this: * fix for the sizeof() pointer type issue * a fix for regulatory getting into a restore loop * a fix for rfkill global 'all' state, it needs to be stored everywhere to apply correctly to new rfkill instances * properly refuse CQM RSSI when it cannot actually be used * protect HT TDLS traffic properly in non-HT networks * don't incorrectly advertise 80 MHz support when not allowed ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
080fff50a3
8 changed files with 116 additions and 7 deletions
|
@ -477,7 +477,9 @@ struct ieee80211_event {
|
|||
* @chandef: Channel definition for this BSS -- the hardware might be
|
||||
* configured a higher bandwidth than this BSS uses, for example.
|
||||
* @ht_operation_mode: HT operation mode like in &struct ieee80211_ht_operation.
|
||||
* This field is only valid when the channel type is one of the HT types.
|
||||
* This field is only valid when the channel is a wide HT/VHT channel.
|
||||
* Note that with TDLS this can be the case (channel is HT, protection must
|
||||
* be used from this field) even when the BSS association isn't using HT.
|
||||
* @cqm_rssi_thold: Connection quality monitor RSSI threshold, a zero value
|
||||
* implies disabled
|
||||
* @cqm_rssi_hyst: Connection quality monitor RSSI hysteresis
|
||||
|
|
|
@ -2468,6 +2468,10 @@ static int ieee80211_set_cqm_rssi_config(struct wiphy *wiphy,
|
|||
rssi_hyst == bss_conf->cqm_rssi_hyst)
|
||||
return 0;
|
||||
|
||||
if (sdata->vif.driver_flags & IEEE80211_VIF_BEACON_FILTER &&
|
||||
!(sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
bss_conf->cqm_rssi_thold = rssi_thold;
|
||||
bss_conf->cqm_rssi_hyst = rssi_hyst;
|
||||
|
||||
|
|
|
@ -4267,6 +4267,8 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
|
|||
struct ieee80211_supported_band *sband;
|
||||
struct cfg80211_chan_def chandef;
|
||||
int ret;
|
||||
u32 i;
|
||||
bool have_80mhz;
|
||||
|
||||
sband = local->hw.wiphy->bands[cbss->channel->band];
|
||||
|
||||
|
@ -4317,6 +4319,20 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
|
|||
}
|
||||
}
|
||||
|
||||
/* Allow VHT if at least one channel on the sband supports 80 MHz */
|
||||
have_80mhz = false;
|
||||
for (i = 0; i < sband->n_channels; i++) {
|
||||
if (sband->channels[i].flags & (IEEE80211_CHAN_DISABLED |
|
||||
IEEE80211_CHAN_NO_80MHZ))
|
||||
continue;
|
||||
|
||||
have_80mhz = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!have_80mhz)
|
||||
ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
|
||||
|
||||
ifmgd->flags |= ieee80211_determine_chantype(sdata, sband,
|
||||
cbss->channel,
|
||||
ht_cap, ht_oper, vht_oper,
|
||||
|
|
|
@ -716,7 +716,7 @@ static bool rate_control_cap_mask(struct ieee80211_sub_if_data *sdata,
|
|||
|
||||
/* Filter out rates that the STA does not support */
|
||||
*mask &= sta->supp_rates[sband->band];
|
||||
for (i = 0; i < sizeof(mcs_mask); i++)
|
||||
for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++)
|
||||
mcs_mask[i] &= sta->ht_cap.mcs.rx_mask[i];
|
||||
|
||||
sta_vht_cap = sta->vht_cap.vht_mcs.rx_mcs_map;
|
||||
|
|
|
@ -1249,6 +1249,58 @@ static void iee80211_tdls_recalc_chanctx(struct ieee80211_sub_if_data *sdata)
|
|||
mutex_unlock(&local->chanctx_mtx);
|
||||
}
|
||||
|
||||
static int iee80211_tdls_have_ht_peers(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
struct sta_info *sta;
|
||||
bool result = false;
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(sta, &sdata->local->sta_list, list) {
|
||||
if (!sta->sta.tdls || sta->sdata != sdata || !sta->uploaded ||
|
||||
!test_sta_flag(sta, WLAN_STA_AUTHORIZED) ||
|
||||
!test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH) ||
|
||||
!sta->sta.ht_cap.ht_supported)
|
||||
continue;
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
iee80211_tdls_recalc_ht_protection(struct ieee80211_sub_if_data *sdata,
|
||||
struct sta_info *sta)
|
||||
{
|
||||
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
||||
bool tdls_ht;
|
||||
u16 protection = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED |
|
||||
IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT |
|
||||
IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT;
|
||||
u16 opmode;
|
||||
|
||||
/* Nothing to do if the BSS connection uses HT */
|
||||
if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT))
|
||||
return;
|
||||
|
||||
tdls_ht = (sta && sta->sta.ht_cap.ht_supported) ||
|
||||
iee80211_tdls_have_ht_peers(sdata);
|
||||
|
||||
opmode = sdata->vif.bss_conf.ht_operation_mode;
|
||||
|
||||
if (tdls_ht)
|
||||
opmode |= protection;
|
||||
else
|
||||
opmode &= ~protection;
|
||||
|
||||
if (opmode == sdata->vif.bss_conf.ht_operation_mode)
|
||||
return;
|
||||
|
||||
sdata->vif.bss_conf.ht_operation_mode = opmode;
|
||||
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_HT);
|
||||
}
|
||||
|
||||
int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
|
||||
const u8 *peer, enum nl80211_tdls_operation oper)
|
||||
{
|
||||
|
@ -1274,6 +1326,10 @@ int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
|
|||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
/* protect possible bss_conf changes and avoid concurrency in
|
||||
* ieee80211_bss_info_change_notify()
|
||||
*/
|
||||
sdata_lock(sdata);
|
||||
mutex_lock(&local->mtx);
|
||||
tdls_dbg(sdata, "TDLS oper %d peer %pM\n", oper, peer);
|
||||
|
||||
|
@ -1287,16 +1343,18 @@ int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
|
|||
|
||||
iee80211_tdls_recalc_chanctx(sdata);
|
||||
|
||||
rcu_read_lock();
|
||||
mutex_lock(&local->sta_mtx);
|
||||
sta = sta_info_get(sdata, peer);
|
||||
if (!sta) {
|
||||
rcu_read_unlock();
|
||||
mutex_unlock(&local->sta_mtx);
|
||||
ret = -ENOLINK;
|
||||
break;
|
||||
}
|
||||
|
||||
iee80211_tdls_recalc_ht_protection(sdata, sta);
|
||||
|
||||
set_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH);
|
||||
rcu_read_unlock();
|
||||
mutex_unlock(&local->sta_mtx);
|
||||
|
||||
WARN_ON_ONCE(is_zero_ether_addr(sdata->u.mgd.tdls_peer) ||
|
||||
!ether_addr_equal(sdata->u.mgd.tdls_peer, peer));
|
||||
|
@ -1318,6 +1376,11 @@ int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
|
|||
ieee80211_flush_queues(local, sdata, false);
|
||||
|
||||
ret = sta_info_destroy_addr(sdata, peer);
|
||||
|
||||
mutex_lock(&local->sta_mtx);
|
||||
iee80211_tdls_recalc_ht_protection(sdata, NULL);
|
||||
mutex_unlock(&local->sta_mtx);
|
||||
|
||||
iee80211_tdls_recalc_chanctx(sdata);
|
||||
break;
|
||||
default:
|
||||
|
@ -1335,6 +1398,7 @@ int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
|
|||
&sdata->u.mgd.request_smps_work);
|
||||
|
||||
mutex_unlock(&local->mtx);
|
||||
sdata_unlock(sdata);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -120,6 +120,7 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
|
|||
struct ieee80211_sta_vht_cap *vht_cap = &sta->sta.vht_cap;
|
||||
struct ieee80211_sta_vht_cap own_cap;
|
||||
u32 cap_info, i;
|
||||
bool have_80mhz;
|
||||
|
||||
memset(vht_cap, 0, sizeof(*vht_cap));
|
||||
|
||||
|
@ -129,6 +130,20 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
|
|||
if (!vht_cap_ie || !sband->vht_cap.vht_supported)
|
||||
return;
|
||||
|
||||
/* Allow VHT if at least one channel on the sband supports 80 MHz */
|
||||
have_80mhz = false;
|
||||
for (i = 0; i < sband->n_channels; i++) {
|
||||
if (sband->channels[i].flags & (IEEE80211_CHAN_DISABLED |
|
||||
IEEE80211_CHAN_NO_80MHZ))
|
||||
continue;
|
||||
|
||||
have_80mhz = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!have_80mhz)
|
||||
return;
|
||||
|
||||
/*
|
||||
* A VHT STA must support 40 MHz, but if we verify that here
|
||||
* then we break a few things - some APs (e.g. Netgear R6300v2
|
||||
|
|
|
@ -341,7 +341,15 @@ static void __rfkill_switch_all(const enum rfkill_type type, bool blocked)
|
|||
{
|
||||
struct rfkill *rfkill;
|
||||
|
||||
rfkill_global_states[type].cur = blocked;
|
||||
if (type == RFKILL_TYPE_ALL) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_RFKILL_TYPES; i++)
|
||||
rfkill_global_states[i].cur = blocked;
|
||||
} else {
|
||||
rfkill_global_states[type].cur = blocked;
|
||||
}
|
||||
|
||||
list_for_each_entry(rfkill, &rfkill_list, node) {
|
||||
if (rfkill->type != type && type != RFKILL_TYPE_ALL)
|
||||
continue;
|
||||
|
|
|
@ -2625,7 +2625,7 @@ static void restore_regulatory_settings(bool reset_user)
|
|||
* settings, user regulatory settings takes precedence.
|
||||
*/
|
||||
if (is_an_alpha2(alpha2))
|
||||
regulatory_hint_user(user_alpha2, NL80211_USER_REG_HINT_USER);
|
||||
regulatory_hint_user(alpha2, NL80211_USER_REG_HINT_USER);
|
||||
|
||||
spin_lock(®_requests_lock);
|
||||
list_splice_tail_init(&tmp_reg_req_list, ®_requests_list);
|
||||
|
|
Loading…
Reference in a new issue