Commit 080fff50 authored by David S. Miller's avatar David S. Miller
Browse files

Merge tag 'mac80211-for-davem-2015-09-04' of...

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: default avatarDavid S. Miller <davem@davemloft.net>
parents e5a5837d ef9be10c
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -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
+4 −0
Original line number Diff line number Diff line
@@ -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;

+16 −0
Original line number Diff line number Diff line
@@ -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,
+1 −1
Original line number Diff line number Diff line
@@ -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;
+67 −3
Original line number Diff line number Diff line
@@ -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;
}

Loading