All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/16] Various patches from our internal tree
@ 2015-03-01  7:09 Emmanuel Grumbach
  2015-03-01  7:10 ` [PATCH 01/16] mac80211: Update beacon's timing and DTIM count on every beacon Emmanuel Grumbach
                   ` (16 more replies)
  0 siblings, 17 replies; 20+ messages in thread
From: Emmanuel Grumbach @ 2015-03-01  7:09 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Emmanuel Grumbach

Hi Johannes,

Here is a sync from out internal tree. This includes a few
patches from you as well.
This is currently based on mac80211.git, but it applies on
mac80211-next.git as well.

Alexander Bondar (1):
  mac80211: Update beacon's timing and DTIM count on every beacon

Arik Nemtsov (4):
  mac80211: TDLS: support VHT between peers
  mac80211: allow TDLS setup code to take wdev lock
  mac80211: update TDLS sta spatial streams before auth
  mac80211: allow iterating inactive interfaces

Avri Altman (1):
  mac80211: tell drivers the user TX power restriction

Eliad Peller (1):
  cfg80211: add operating classes 128-130

Johannes Berg (5):
  mac80211: fix another suspend vs. association race
  mac80211: don't do driver suspend with auth/assoc in progress
  mac80211: start queues if driver rejected wowlan
  mac80211: check and dequeue skb in ieee80211_tx_prepare_skb()
  nl80211: prohibit mixing 'any' and regular wowlan triggers

Luciano Coelho (4):
  mac80211: handle drv_add_interface failures properly during reconfig
  mac80211: remove useless double check for open_count in
    __ieee80211_suspend()
  mac80211: remove duplicate check for quiescing when queueing work
  mac80211: remove channel_switch_beacon operation

 include/net/mac80211.h        |  77 ++++++++++++++++++-------
 include/uapi/linux/nl80211.h  |   2 +
 net/mac80211/cfg.c            |  49 ++++++++++++----
 net/mac80211/chan.c           |   4 +-
 net/mac80211/debugfs_netdev.c |   2 +-
 net/mac80211/driver-ops.h     |  13 -----
 net/mac80211/ieee80211_i.h    |   6 +-
 net/mac80211/iface.c          |  12 ++--
 net/mac80211/mlme.c           |  70 +++++++++++++++--------
 net/mac80211/pm.c             |  28 +++++++++-
 net/mac80211/tdls.c           | 127 ++++++++++++++++++++++++++++++++++--------
 net/mac80211/trace.h          |  25 ---------
 net/mac80211/tx.c             |   9 +++
 net/mac80211/util.c           |  83 ++++++++++++++++++++++-----
 net/mac80211/vht.c            |   4 --
 net/wireless/nl80211.c        |  22 ++++++++
 net/wireless/util.c           |   1 +
 17 files changed, 388 insertions(+), 146 deletions(-)

-- 
1.9.1


^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 01/16] mac80211: Update beacon's timing and DTIM count on every beacon
  2015-03-01  7:09 [PATCH 00/16] Various patches from our internal tree Emmanuel Grumbach
@ 2015-03-01  7:10 ` Emmanuel Grumbach
  2015-03-01  7:10 ` [PATCH 02/16] cfg80211: add operating classes 128-130 Emmanuel Grumbach
                   ` (15 subsequent siblings)
  16 siblings, 0 replies; 20+ messages in thread
From: Emmanuel Grumbach @ 2015-03-01  7:10 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Alexander Bondar, Emmanuel Grumbach

From: Alexander Bondar <alexander.bondar@intel.com>

Beacon's timestamp, device system time associated with this beacon and
DTIM count parameters are not updated in the associated vif context
if the latest beacon's content is identical to the previously received.
It make sense to update these changing parameters on every beacon so the
driver can get most updated values. This may be necessary, for example,
to avoid either beacons' drift effect or device time stamp overrun.
IMPORTANT: Three sync_* parameters - sync_ts, sync_device_ts and
sync_dtim_count would possibly be out of sync by the time the driver will
use them. The synchronized view is currently guaranteed only in certain
callbacks.

Signed-off-by: Alexander Bondar <alexander.bondar@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
---
 include/net/mac80211.h |  7 +++++--
 net/mac80211/mlme.c    | 32 ++++++++++++++++++++------------
 2 files changed, 25 insertions(+), 14 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index d52914b..3a029f0 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -337,12 +337,15 @@ enum ieee80211_rssi_event {
  *	HW flag %IEEE80211_HW_TIMING_BEACON_ONLY is set, then this can
  *	only come from a beacon, but might not become valid until after
  *	association when a beacon is received (which is notified with the
- *	%BSS_CHANGED_DTIM flag.)
+ *	%BSS_CHANGED_DTIM flag.). See also sync_dtim_count important notice.
  * @sync_device_ts: the device timestamp corresponding to the sync_tsf,
  *	the driver/device can use this to calculate synchronisation
- *	(see @sync_tsf)
+ *	(see @sync_tsf). See also sync_dtim_count important notice.
  * @sync_dtim_count: Only valid when %IEEE80211_HW_TIMING_BEACON_ONLY
  *	is requested, see @sync_tsf/@sync_device_ts.
+ *	IMPORTANT: These three sync_* parameters would possibly be out of sync
+ *	by the time the driver will use them. The synchronized view is currently
+ *	guaranteed only in certain callbacks.
  * @beacon_int: beacon interval
  * @assoc_capability: capabilities taken from assoc resp
  * @basic_rates: bitmap of basic rates, each bit stands for an
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 10ac632..cf3ae93 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3419,6 +3419,26 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
 	if (ifmgd->csa_waiting_bcn)
 		ieee80211_chswitch_post_beacon(sdata);
 
+	/*
+	 * Update beacon timing and dtim count on every beacon appearance. This
+	 * will allow the driver to use the most updated values. Do it before
+	 * comparing this one with last received beacon.
+	 * IMPORTANT: These parameters would possibly be out of sync by the time
+	 * the driver will use them. The synchronized view is currently
+	 * guaranteed only in certain callbacks.
+	 */
+	if (local->hw.flags & IEEE80211_HW_TIMING_BEACON_ONLY) {
+		sdata->vif.bss_conf.sync_tsf =
+			le64_to_cpu(mgmt->u.beacon.timestamp);
+		sdata->vif.bss_conf.sync_device_ts =
+			rx_status->device_timestamp;
+		if (elems.tim)
+			sdata->vif.bss_conf.sync_dtim_count =
+				elems.tim->dtim_count;
+		else
+			sdata->vif.bss_conf.sync_dtim_count = 0;
+	}
+
 	if (ncrc == ifmgd->beacon_crc && ifmgd->beacon_crc_valid)
 		return;
 	ifmgd->beacon_crc = ncrc;
@@ -3446,18 +3466,6 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
 		else
 			bss_conf->dtim_period = 1;
 
-		if (local->hw.flags & IEEE80211_HW_TIMING_BEACON_ONLY) {
-			sdata->vif.bss_conf.sync_tsf =
-				le64_to_cpu(mgmt->u.beacon.timestamp);
-			sdata->vif.bss_conf.sync_device_ts =
-				rx_status->device_timestamp;
-			if (elems.tim)
-				sdata->vif.bss_conf.sync_dtim_count =
-					elems.tim->dtim_count;
-			else
-				sdata->vif.bss_conf.sync_dtim_count = 0;
-		}
-
 		changed |= BSS_CHANGED_BEACON_INFO;
 		ifmgd->have_beacon = true;
 
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 02/16] cfg80211: add operating classes 128-130
  2015-03-01  7:09 [PATCH 00/16] Various patches from our internal tree Emmanuel Grumbach
  2015-03-01  7:10 ` [PATCH 01/16] mac80211: Update beacon's timing and DTIM count on every beacon Emmanuel Grumbach
@ 2015-03-01  7:10 ` Emmanuel Grumbach
  2015-03-01  7:10 ` [PATCH 03/16] mac80211: TDLS: support VHT between peers Emmanuel Grumbach
                   ` (14 subsequent siblings)
  16 siblings, 0 replies; 20+ messages in thread
From: Emmanuel Grumbach @ 2015-03-01  7:10 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Eliad Peller, Eliad Peller, Emmanuel Grumbach

From: Eliad Peller <eliad@wizery.com>

Operating classes 128-130 are defined in the 11ac
spec for the 5GHz band.

Update ieee80211_operating_class_to_band() to support them.

Signed-off-by: Eliad Peller <eliadx.peller@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
---
 net/wireless/util.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/net/wireless/util.c b/net/wireless/util.c
index 6903dbd..f7b3598 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -1296,6 +1296,7 @@ bool ieee80211_operating_class_to_band(u8 operating_class,
 	switch (operating_class) {
 	case 112:
 	case 115 ... 127:
+	case 128 ... 130:
 		*band = IEEE80211_BAND_5GHZ;
 		return true;
 	case 81:
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 03/16] mac80211: TDLS: support VHT between peers
  2015-03-01  7:09 [PATCH 00/16] Various patches from our internal tree Emmanuel Grumbach
  2015-03-01  7:10 ` [PATCH 01/16] mac80211: Update beacon's timing and DTIM count on every beacon Emmanuel Grumbach
  2015-03-01  7:10 ` [PATCH 02/16] cfg80211: add operating classes 128-130 Emmanuel Grumbach
@ 2015-03-01  7:10 ` Emmanuel Grumbach
  2015-03-01  7:10 ` [PATCH 04/16] mac80211: fix another suspend vs. association race Emmanuel Grumbach
                   ` (13 subsequent siblings)
  16 siblings, 0 replies; 20+ messages in thread
From: Emmanuel Grumbach @ 2015-03-01  7:10 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Arik Nemtsov, Arik Nemtsov, Emmanuel Grumbach

From: Arik Nemtsov <arik@wizery.com>

Add the AID and VHT-cap/operation IEs during TDLS setup. Remove the
block of TDLS peers when setting HT-caps of the peer station.

Signed-off-by: Arik Nemtsov <arikx.nemtsov@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
---
 net/mac80211/ieee80211_i.h |  2 ++
 net/mac80211/tdls.c        | 86 +++++++++++++++++++++++++++++++++++++++++++---
 net/mac80211/util.c        | 35 +++++++++++++++++++
 net/mac80211/vht.c         |  4 ---
 4 files changed, 118 insertions(+), 9 deletions(-)

diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 3afe368..2891e40 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1967,6 +1967,8 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
 			       u16 prot_mode);
 u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,
 			       u32 cap);
+u8 *ieee80211_ie_build_vht_oper(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,
+				const struct cfg80211_chan_def *chandef);
 int ieee80211_parse_bitrates(struct cfg80211_chan_def *chandef,
 			     const struct ieee80211_supported_band *sband,
 			     const u8 *srates, int srates_len, u32 *rates);
diff --git a/net/mac80211/tdls.c b/net/mac80211/tdls.c
index c9f9752..5bcd542 100644
--- a/net/mac80211/tdls.c
+++ b/net/mac80211/tdls.c
@@ -193,6 +193,17 @@ static void ieee80211_tdls_add_link_ie(struct ieee80211_sub_if_data *sdata,
 	memcpy(lnkid->resp_sta, rsp_addr, ETH_ALEN);
 }
 
+static void
+ieee80211_tdls_add_aid(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
+{
+	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+	u8 *pos = (void *)skb_put(skb, 4);
+
+	*pos++ = WLAN_EID_AID;
+	*pos++ = 2; /* len */
+	put_unaligned_le16(ifmgd->aid, pos);
+}
+
 /* translate numbering in the WMM parameter IE to the mac80211 notation */
 static enum ieee80211_ac_numbers ieee80211_ac_from_wmm(int ac)
 {
@@ -271,6 +282,7 @@ ieee80211_tdls_add_setup_start_ies(struct ieee80211_sub_if_data *sdata,
 	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_supported_band *sband;
 	struct ieee80211_sta_ht_cap ht_cap;
+	struct ieee80211_sta_vht_cap vht_cap;
 	struct sta_info *sta = NULL;
 	size_t offset = 0, noffset;
 	u8 *pos;
@@ -368,12 +380,60 @@ ieee80211_tdls_add_setup_start_ies(struct ieee80211_sub_if_data *sdata,
 		ieee80211_ie_build_ht_cap(pos, &ht_cap, ht_cap.cap);
 	}
 
-	rcu_read_unlock();
-
 	if (ht_cap.ht_supported &&
 	    (ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40))
 		ieee80211_tdls_add_bss_coex_ie(skb);
 
+	ieee80211_tdls_add_link_ie(sdata, skb, peer, initiator);
+
+	/* add any custom IEs that go before VHT capabilities */
+	if (extra_ies_len) {
+		static const u8 before_vht_cap[] = {
+			WLAN_EID_SUPP_RATES,
+			WLAN_EID_COUNTRY,
+			WLAN_EID_EXT_SUPP_RATES,
+			WLAN_EID_SUPPORTED_CHANNELS,
+			WLAN_EID_RSN,
+			WLAN_EID_EXT_CAPABILITY,
+			WLAN_EID_QOS_CAPA,
+			WLAN_EID_FAST_BSS_TRANSITION,
+			WLAN_EID_TIMEOUT_INTERVAL,
+			WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
+			WLAN_EID_MULTI_BAND,
+		};
+		noffset = ieee80211_ie_split(extra_ies, extra_ies_len,
+					     before_vht_cap,
+					     ARRAY_SIZE(before_vht_cap),
+					     offset);
+		pos = skb_put(skb, noffset - offset);
+		memcpy(pos, extra_ies + offset, noffset - offset);
+		offset = noffset;
+	}
+
+	/* build the VHT-cap similarly to the HT-cap */
+	memcpy(&vht_cap, &sband->vht_cap, sizeof(vht_cap));
+	if (action_code == WLAN_TDLS_SETUP_REQUEST && vht_cap.vht_supported) {
+		ieee80211_apply_vhtcap_overrides(sdata, &vht_cap);
+
+		/* the AID is present only when VHT is implemented */
+		ieee80211_tdls_add_aid(sdata, skb);
+
+		pos = skb_put(skb, sizeof(struct ieee80211_vht_cap) + 2);
+		ieee80211_ie_build_vht_cap(pos, &vht_cap, vht_cap.cap);
+	} else if (action_code == WLAN_TDLS_SETUP_RESPONSE &&
+		   vht_cap.vht_supported && sta->sta.vht_cap.vht_supported) {
+		/* the peer caps are already intersected with our own */
+		memcpy(&vht_cap, &sta->sta.vht_cap, sizeof(vht_cap));
+
+		/* the AID is present only when VHT is implemented */
+		ieee80211_tdls_add_aid(sdata, skb);
+
+		pos = skb_put(skb, sizeof(struct ieee80211_vht_cap) + 2);
+		ieee80211_ie_build_vht_cap(pos, &vht_cap, vht_cap.cap);
+	}
+
+	rcu_read_unlock();
+
 	/* add any remaining IEs */
 	if (extra_ies_len) {
 		noffset = extra_ies_len;
@@ -381,7 +441,6 @@ ieee80211_tdls_add_setup_start_ies(struct ieee80211_sub_if_data *sdata,
 		memcpy(pos, extra_ies + offset, noffset - offset);
 	}
 
-	ieee80211_tdls_add_link_ie(sdata, skb, peer, initiator);
 }
 
 static void
@@ -394,6 +453,7 @@ ieee80211_tdls_add_setup_cfm_ies(struct ieee80211_sub_if_data *sdata,
 	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 	size_t offset = 0, noffset;
 	struct sta_info *sta, *ap_sta;
+	enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
 	u8 *pos;
 
 	rcu_read_lock();
@@ -453,6 +513,21 @@ ieee80211_tdls_add_setup_cfm_ies(struct ieee80211_sub_if_data *sdata,
 		}
 	}
 
+	ieee80211_tdls_add_link_ie(sdata, skb, peer, initiator);
+
+	/* only include VHT-operation if not on the 2.4GHz band */
+	if (band != IEEE80211_BAND_2GHZ && !ap_sta->sta.vht_cap.vht_supported &&
+	    sta->sta.vht_cap.vht_supported) {
+		struct ieee80211_chanctx_conf *chanctx_conf =
+				rcu_dereference(sdata->vif.chanctx_conf);
+		if (!WARN_ON(!chanctx_conf)) {
+			pos = skb_put(skb, 2 +
+				      sizeof(struct ieee80211_vht_operation));
+			ieee80211_ie_build_vht_oper(pos, &sta->sta.vht_cap,
+						    &chanctx_conf->def);
+		}
+	}
+
 	rcu_read_unlock();
 
 	/* add any remaining IEs */
@@ -461,8 +536,6 @@ ieee80211_tdls_add_setup_cfm_ies(struct ieee80211_sub_if_data *sdata,
 		pos = skb_put(skb, noffset - offset);
 		memcpy(pos, extra_ies + offset, noffset - offset);
 	}
-
-	ieee80211_tdls_add_link_ie(sdata, skb, peer, initiator);
 }
 
 static void
@@ -708,8 +781,11 @@ ieee80211_tdls_build_mgmt_packet_data(struct ieee80211_sub_if_data *sdata,
 			       26 + /* max(WMM-info, WMM-param) */
 			       2 + max(sizeof(struct ieee80211_ht_cap),
 				       sizeof(struct ieee80211_ht_operation)) +
+			       2 + max(sizeof(struct ieee80211_vht_cap),
+				       sizeof(struct ieee80211_vht_operation)) +
 			       50 + /* supported channels */
 			       3 + /* 40/20 BSS coex */
+			       4 + /* AID */
 			       extra_ies_len +
 			       sizeof(struct ieee80211_tdls_lnkie));
 	if (!skb)
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 8428f4a..eec9444 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -2344,6 +2344,41 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
 	return pos + sizeof(struct ieee80211_ht_operation);
 }
 
+u8 *ieee80211_ie_build_vht_oper(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,
+				const struct cfg80211_chan_def *chandef)
+{
+	struct ieee80211_vht_operation *vht_oper;
+
+	*pos++ = WLAN_EID_VHT_OPERATION;
+	*pos++ = sizeof(struct ieee80211_vht_operation);
+	vht_oper = (struct ieee80211_vht_operation *)pos;
+	vht_oper->center_freq_seg1_idx = ieee80211_frequency_to_channel(
+							chandef->center_freq1);
+	if (chandef->center_freq2)
+		vht_oper->center_freq_seg2_idx =
+			ieee80211_frequency_to_channel(chandef->center_freq2);
+
+	switch (chandef->width) {
+	case NL80211_CHAN_WIDTH_160:
+		vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_160MHZ;
+		break;
+	case NL80211_CHAN_WIDTH_80P80:
+		vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80P80MHZ;
+		break;
+	case NL80211_CHAN_WIDTH_80:
+		vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80MHZ;
+		break;
+	default:
+		vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_USE_HT;
+		break;
+	}
+
+	/* don't require special VHT peer rates */
+	vht_oper->basic_mcs_set = cpu_to_le16(0xffff);
+
+	return pos + sizeof(struct ieee80211_vht_operation);
+}
+
 void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan,
 				  const struct ieee80211_ht_operation *ht_oper,
 				  struct cfg80211_chan_def *chandef)
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c
index 85f9596..80694d5 100644
--- a/net/mac80211/vht.c
+++ b/net/mac80211/vht.c
@@ -129,10 +129,6 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
 	if (!vht_cap_ie || !sband->vht_cap.vht_supported)
 		return;
 
-	/* don't support VHT for TDLS peers for now */
-	if (test_sta_flag(sta, WLAN_STA_TDLS_PEER))
-		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
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 04/16] mac80211: fix another suspend vs. association race
  2015-03-01  7:09 [PATCH 00/16] Various patches from our internal tree Emmanuel Grumbach
                   ` (2 preceding siblings ...)
  2015-03-01  7:10 ` [PATCH 03/16] mac80211: TDLS: support VHT between peers Emmanuel Grumbach
@ 2015-03-01  7:10 ` Emmanuel Grumbach
  2015-03-01  7:10 ` [PATCH 05/16] mac80211: handle drv_add_interface failures properly during reconfig Emmanuel Grumbach
                   ` (12 subsequent siblings)
  16 siblings, 0 replies; 20+ messages in thread
From: Emmanuel Grumbach @ 2015-03-01  7:10 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

Since cfg80211 disconnects, but has no insight into the association
process, it can happen that it disconnects while association is in
progress. We then try to abort association in mac80211, but this is
only later so the association can complete between the two.

This results in removing an interface from the driver while bound
to the channel context, obviously causing confusion and issues.

Solve this by also checking if we're associated during quiesce and
if so deauthenticating. The frame will no longer go out to the AP
which is a bit unfortunate, but it'll resolve the crash (and before
we would have suspended without telling the AP as well.)

I'm working on a better, but more complex solution as well, which
should avoid that problem.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/mlme.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index cf3ae93..c5f3bd6 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3985,6 +3985,34 @@ void ieee80211_mgd_quiesce(struct ieee80211_sub_if_data *sdata)
 				      IEEE80211_DEAUTH_FRAME_LEN);
 	}
 
+	/* This is a bit of a hack - we should find a better and more generic
+	 * solution to this. Normally when suspending, cfg80211 will in fact
+	 * deauthenticate. However, it doesn't (and cannot) stop an ongoing
+	 * auth (not so important) or assoc (this is the problem) process.
+	 *
+	 * As a consequence, it can happen that we are in the process of both
+	 * associating and suspending, and receive an association response
+	 * after cfg80211 has checked if it needs to disconnect, but before
+	 * we actually set the flag to drop incoming frames. This will then
+	 * cause the workqueue flush to process the association response in
+	 * the suspend, resulting in a successful association just before it
+	 * tries to remove the interface from the driver, which now though
+	 * has a channel context assigned ... this results in issues.
+	 *
+	 * To work around this (for now) simply deauth here again if we're
+	 * now connected.
+	 */
+	if (ifmgd->associated && !sdata->local->wowlan) {
+		u8 bssid[ETH_ALEN];
+		struct cfg80211_deauth_request req = {
+			.reason_code = WLAN_REASON_DEAUTH_LEAVING,
+			.bssid = bssid,
+		};
+
+		memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN);
+		ieee80211_mgd_deauth(sdata, &req);
+	}
+
 	sdata_unlock(sdata);
 }
 
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 05/16] mac80211: handle drv_add_interface failures properly during reconfig
  2015-03-01  7:09 [PATCH 00/16] Various patches from our internal tree Emmanuel Grumbach
                   ` (3 preceding siblings ...)
  2015-03-01  7:10 ` [PATCH 04/16] mac80211: fix another suspend vs. association race Emmanuel Grumbach
@ 2015-03-01  7:10 ` Emmanuel Grumbach
  2015-03-01  7:10 ` [PATCH 06/16] mac80211: tell drivers the user TX power restriction Emmanuel Grumbach
                   ` (11 subsequent siblings)
  16 siblings, 0 replies; 20+ messages in thread
From: Emmanuel Grumbach @ 2015-03-01  7:10 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Luciano Coelho, Emmanuel Grumbach

From: Luciano Coelho <luciano.coelho@intel.com>

If any interface fails to be added to the driver in during reconfig,
we should remove all the successfully added interfaces and report
reconfig failure, so things can be cleaned up properly.  Failing to do
so can lead to subsequent failures and leave the drivers in a messed
up state.

Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
---
 net/mac80211/util.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index eec9444..32788674 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1811,8 +1811,25 @@ int ieee80211_reconfig(struct ieee80211_local *local)
 	list_for_each_entry(sdata, &local->interfaces, list) {
 		if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
 		    sdata->vif.type != NL80211_IFTYPE_MONITOR &&
-		    ieee80211_sdata_running(sdata))
+		    ieee80211_sdata_running(sdata)) {
 			res = drv_add_interface(local, sdata);
+			if (WARN_ON(res))
+				break;
+		}
+	}
+
+	/* If adding any of the interfaces failed above, roll back and
+	 * report failure.
+	 */
+	if (res) {
+		list_for_each_entry_continue_reverse(sdata, &local->interfaces,
+						     list)
+			if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
+			    sdata->vif.type != NL80211_IFTYPE_MONITOR &&
+			    ieee80211_sdata_running(sdata))
+				drv_remove_interface(local, sdata);
+		ieee80211_handle_reconfig_failure(local);
+		return res;
 	}
 
 	/* add channel contexts */
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 06/16] mac80211: tell drivers the user TX power restriction
  2015-03-01  7:09 [PATCH 00/16] Various patches from our internal tree Emmanuel Grumbach
                   ` (4 preceding siblings ...)
  2015-03-01  7:10 ` [PATCH 05/16] mac80211: handle drv_add_interface failures properly during reconfig Emmanuel Grumbach
@ 2015-03-01  7:10 ` Emmanuel Grumbach
  2015-03-04  9:34   ` Johannes Berg
  2015-03-01  7:10 ` [PATCH 07/16] mac80211: don't do driver suspend with auth/assoc in progress Emmanuel Grumbach
                   ` (10 subsequent siblings)
  16 siblings, 1 reply; 20+ messages in thread
From: Emmanuel Grumbach @ 2015-03-01  7:10 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Avri Altman, Emmanuel Grumbach

From: Avri Altman <avri.altman@intel.com>

Allow drivers to obtain the user's TX power restrictions in
order to be able to  apply it properly on (for example)
hardware scanning which operations on a set of channels,
in which case mac80211 cannot properly apply the per-channel
regulatory limits, and the currently exposed txpower value,
which is the minimum  of the user setting, channel regulatory
and possible 11h AP reduction isn't  appropriate to use
since scanning is done on many channels.

Note that drivers need to be careful when using this value
and must ensure that  regulatory is maintained, i.e. the
new value cannot be used as-is.

Signed-off-by: Avri Altman <avri.altman@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
---
 include/net/mac80211.h        |  9 +++++++++
 net/mac80211/cfg.c            | 44 +++++++++++++++++++++++++++++++++----------
 net/mac80211/chan.c           |  4 ++--
 net/mac80211/debugfs_netdev.c |  2 +-
 net/mac80211/ieee80211_i.h    |  4 +---
 net/mac80211/iface.c          | 12 ++++++------
 6 files changed, 53 insertions(+), 22 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 3a029f0..78ecfe5 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -264,6 +264,7 @@ struct ieee80211_vif_chanctx_switch {
  *	note that this is only called when it changes after the channel
  *	context had been assigned.
  * @BSS_CHANGED_OCB: OCB join status changed
+ * @BSS_CHANGED_USER_TXPOWER: User TX power setting changed for this interface
  */
 enum ieee80211_bss_change {
 	BSS_CHANGED_ASSOC		= 1<<0,
@@ -289,6 +290,7 @@ enum ieee80211_bss_change {
 	BSS_CHANGED_BEACON_INFO		= 1<<20,
 	BSS_CHANGED_BANDWIDTH		= 1<<21,
 	BSS_CHANGED_OCB                 = 1<<22,
+	BSS_CHANGED_USER_TXPOWER	= 1<<23,
 
 	/* when adding here, make sure to change ieee80211_reconfig */
 };
@@ -385,6 +387,12 @@ enum ieee80211_rssi_event {
  *	NL80211_TX_POWER_LIMITED (allow using less than specified from
  *	userspace), whereas TPC is disabled if %txpower_type is set to
  *	NL80211_TX_POWER_FIXED (use value configured from userspace)
+ * @user_power_level: TX power limit requested by the user (in dBm).
+ *	This must be used carefully, it isn't restricted by regulatory.
+ *	However, it could be used for example for hardware scanning to limit
+ *	the TX power to the user-requested level, while also limiting to the
+ *	correct per-channel regulatory. Similarly for other out-of-channel
+ *	activities where mac80211 cannot correctly set the TX power level.
  * @p2p_noa_attr: P2P NoA attribute for P2P powersave
  */
 struct ieee80211_bss_conf {
@@ -421,6 +429,7 @@ struct ieee80211_bss_conf {
 	bool hidden_ssid;
 	int txpower;
 	enum nl80211_tx_power_setting txpower_type;
+	int user_power_level;
 	struct ieee80211_p2p_noa_attr p2p_noa_attr;
 };
 
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index dd4ff36..02f1125 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2142,30 +2142,44 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
 	struct ieee80211_local *local = wiphy_priv(wiphy);
 	struct ieee80211_sub_if_data *sdata;
 	enum nl80211_tx_power_setting txp_type = type;
-	bool update_txp_type = false;
 
 	if (wdev) {
+		int old_user_level, new_user_level;
+		u32 change = 0;
+
 		sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
+		old_user_level = sdata->vif.bss_conf.user_power_level;
+		new_user_level = old_user_level;
 
 		switch (type) {
 		case NL80211_TX_POWER_AUTOMATIC:
-			sdata->user_power_level = IEEE80211_UNSET_POWER_LEVEL;
+			new_user_level = IEEE80211_UNSET_POWER_LEVEL;
 			txp_type = NL80211_TX_POWER_LIMITED;
 			break;
 		case NL80211_TX_POWER_LIMITED:
 		case NL80211_TX_POWER_FIXED:
 			if (mbm < 0 || (mbm % 100))
 				return -EOPNOTSUPP;
-			sdata->user_power_level = MBM_TO_DBM(mbm);
+			new_user_level = MBM_TO_DBM(mbm);
 			break;
 		}
 
 		if (txp_type != sdata->vif.bss_conf.txpower_type) {
-			update_txp_type = true;
 			sdata->vif.bss_conf.txpower_type = txp_type;
+			change |= BSS_CHANGED_TXPOWER;
+		}
+
+		if (old_user_level != new_user_level) {
+			change |= BSS_CHANGED_USER_TXPOWER;
+			sdata->vif.bss_conf.user_power_level = new_user_level;
 		}
 
-		ieee80211_recalc_txpower(sdata, update_txp_type);
+		if (!change)
+			return 0;
+
+		if (__ieee80211_recalc_txpower(sdata))
+			change |= BSS_CHANGED_TXPOWER;
+		ieee80211_bss_info_change_notify(sdata, change);
 
 		return 0;
 	}
@@ -2185,13 +2199,23 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
 
 	mutex_lock(&local->iflist_mtx);
 	list_for_each_entry(sdata, &local->interfaces, list) {
-		sdata->user_power_level = local->user_power_level;
-		if (txp_type != sdata->vif.bss_conf.txpower_type)
-			update_txp_type = true;
+		u32 change = 0;
+
+		if (sdata->vif.bss_conf.user_power_level !=
+				local->user_power_level) {
+			change |= BSS_CHANGED_USER_TXPOWER;
+			sdata->vif.bss_conf.user_power_level =
+						local->user_power_level;
+		}
+
+		if (__ieee80211_recalc_txpower(sdata) ||
+		    txp_type != sdata->vif.bss_conf.txpower_type)
+			change |= BSS_CHANGED_TXPOWER;
 		sdata->vif.bss_conf.txpower_type = txp_type;
+
+		if (change)
+			ieee80211_bss_info_change_notify(sdata, change);
 	}
-	list_for_each_entry(sdata, &local->interfaces, list)
-		ieee80211_recalc_txpower(sdata, update_txp_type);
 	mutex_unlock(&local->iflist_mtx);
 
 	return 0;
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index 5bcd4e5..0259671 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -655,7 +655,7 @@ out:
 	}
 
 	if (new_ctx && ieee80211_chanctx_num_assigned(local, new_ctx) > 0) {
-		ieee80211_recalc_txpower(sdata, false);
+		ieee80211_recalc_txpower(sdata);
 		ieee80211_recalc_chanctx_min_def(local, new_ctx);
 	}
 
@@ -1387,7 +1387,7 @@ static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local)
 				ieee80211_bss_info_change_notify(sdata,
 								 changed);
 
-			ieee80211_recalc_txpower(sdata, false);
+			ieee80211_recalc_txpower(sdata);
 		}
 
 		ieee80211_recalc_chanctx_chantype(local, ctx);
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index c68896a..40cea0c 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -191,7 +191,7 @@ IEEE80211_IF_FILE(flags, flags, HEX);
 IEEE80211_IF_FILE(state, state, LHEX);
 IEEE80211_IF_FILE(txpower, vif.bss_conf.txpower, DEC);
 IEEE80211_IF_FILE(ap_power_level, ap_power_level, DEC);
-IEEE80211_IF_FILE(user_power_level, user_power_level, DEC);
+IEEE80211_IF_FILE(user_power_level, vif.bss_conf.user_power_level, DEC);
 
 static ssize_t
 ieee80211_if_fmt_hw_queues(const struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 2891e40..09cdd25 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -867,7 +867,6 @@ struct ieee80211_sub_if_data {
 	u8 needed_rx_chains;
 	enum ieee80211_smps_mode smps_mode;
 
-	int user_power_level; /* in dBm */
 	int ap_power_level; /* in dBm */
 
 	bool radar_required;
@@ -1621,8 +1620,7 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local);
 void ieee80211_del_virtual_monitor(struct ieee80211_local *local);
 
 bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata);
-void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata,
-			      bool update_bss);
+void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata);
 
 static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata)
 {
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 81a2751..b49812f 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -58,8 +58,9 @@ bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata)
 	power = ieee80211_chandef_max_power(&chanctx_conf->def);
 	rcu_read_unlock();
 
-	if (sdata->user_power_level != IEEE80211_UNSET_POWER_LEVEL)
-		power = min(power, sdata->user_power_level);
+	if (sdata->vif.bss_conf.user_power_level !=
+	    IEEE80211_UNSET_POWER_LEVEL)
+		power = min(power, sdata->vif.bss_conf.user_power_level);
 
 	if (sdata->ap_power_level != IEEE80211_UNSET_POWER_LEVEL)
 		power = min(power, sdata->ap_power_level);
@@ -73,10 +74,9 @@ bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata)
 	return false;
 }
 
-void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata,
-			      bool update_bss)
+void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata)
 {
-	if (__ieee80211_recalc_txpower(sdata) || update_bss)
+	if (__ieee80211_recalc_txpower(sdata))
 		ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_TXPOWER);
 }
 
@@ -1745,7 +1745,7 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
 	ieee80211_set_default_queues(sdata);
 
 	sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL;
-	sdata->user_power_level = local->user_power_level;
+	sdata->vif.bss_conf.user_power_level = local->user_power_level;
 
 	sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
 
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 07/16] mac80211: don't do driver suspend with auth/assoc in progress
  2015-03-01  7:09 [PATCH 00/16] Various patches from our internal tree Emmanuel Grumbach
                   ` (5 preceding siblings ...)
  2015-03-01  7:10 ` [PATCH 06/16] mac80211: tell drivers the user TX power restriction Emmanuel Grumbach
@ 2015-03-01  7:10 ` Emmanuel Grumbach
  2015-03-01  7:10 ` [PATCH 08/16] mac80211: remove useless double check for open_count in __ieee80211_suspend() Emmanuel Grumbach
                   ` (9 subsequent siblings)
  16 siblings, 0 replies; 20+ messages in thread
From: Emmanuel Grumbach @ 2015-03-01  7:10 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

Drivers can't really be expected to suspend properly while auth
or assoc is in progress since then they don't have any state
they could keep with WoWLAN, nor can they actually finish the
authentication or association. In fact, keeping this can cause
subtle issues with drivers like iwlwifi that refuse WoWLAN if
not associated, but have trouble figuring out what's going on
in the middle of association.

In any case, regardless of possible driver issues in this area,
it doesn't make sense for mac80211 to try to WoWLAN-suspend in
the middle of such operations, so stop them before.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/pm.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index ca405b6..bd185f3 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -61,7 +61,24 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
 
 	local->wowlan = wowlan && local->open_count;
 	if (local->wowlan) {
-		int err = drv_suspend(local, wowlan);
+		int err;
+
+		/* Drivers don't expect to suspend while some operations like
+		 * authenticating or associating are in progress. It doesn't
+		 * make sense anyway to accept that, since the authentication
+		 * or association would never finish since the driver can't do
+		 * that on its own.
+		 * Thus, clean up in-progress auth/assoc first.
+		 */
+		list_for_each_entry(sdata, &local->interfaces, list) {
+			if (!ieee80211_sdata_running(sdata))
+				continue;
+			if (sdata->vif.type != NL80211_IFTYPE_STATION)
+				continue;
+			ieee80211_mgd_quiesce(sdata);
+		}
+
+		err = drv_suspend(local, wowlan);
 		if (err < 0) {
 			local->quiescing = false;
 			local->wowlan = false;
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 08/16] mac80211: remove useless double check for open_count in __ieee80211_suspend()
  2015-03-01  7:09 [PATCH 00/16] Various patches from our internal tree Emmanuel Grumbach
                   ` (6 preceding siblings ...)
  2015-03-01  7:10 ` [PATCH 07/16] mac80211: don't do driver suspend with auth/assoc in progress Emmanuel Grumbach
@ 2015-03-01  7:10 ` Emmanuel Grumbach
  2015-03-01  7:10 ` [PATCH 09/16] mac80211: start queues if driver rejected wowlan Emmanuel Grumbach
                   ` (8 subsequent siblings)
  16 siblings, 0 replies; 20+ messages in thread
From: Emmanuel Grumbach @ 2015-03-01  7:10 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Luciano Coelho, Emmanuel Grumbach

From: Luciano Coelho <luciano.coelho@intel.com>

We check local->open_count at the top of the __ieee80211_suspend(), so
there's no need to check for it again.  open_count is protected by the
rtnl, so there's no chance for it to have change between the two
calls.

Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
---
 net/mac80211/pm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index bd185f3..46ffe3a 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -59,7 +59,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
 	cancel_work_sync(&local->dynamic_ps_enable_work);
 	del_timer_sync(&local->dynamic_ps_timer);
 
-	local->wowlan = wowlan && local->open_count;
+	local->wowlan = wowlan;
 	if (local->wowlan) {
 		int err;
 
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 09/16] mac80211: start queues if driver rejected wowlan
  2015-03-01  7:09 [PATCH 00/16] Various patches from our internal tree Emmanuel Grumbach
                   ` (7 preceding siblings ...)
  2015-03-01  7:10 ` [PATCH 08/16] mac80211: remove useless double check for open_count in __ieee80211_suspend() Emmanuel Grumbach
@ 2015-03-01  7:10 ` Emmanuel Grumbach
  2015-03-01  7:10 ` [PATCH 10/16] mac80211: allow TDLS setup code to take wdev lock Emmanuel Grumbach
                   ` (7 subsequent siblings)
  16 siblings, 0 replies; 20+ messages in thread
From: Emmanuel Grumbach @ 2015-03-01  7:10 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

If the driver rejects WoWLAN, restart the queues before returning
to cfg80211. cfg80211 will return to mac80211, but not before it
disconnects all interfaces. If we don't start the queues, any of
the packets needed for disconnecting won't be transmitted, which
is strange. Fix that.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/pm.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index 46ffe3a..ac6ad62 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -97,6 +97,13 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
 			return err;
 		} else if (err > 0) {
 			WARN_ON(err != 1);
+			/* cfg80211 will call back into mac80211 to disconnect
+			 * all interfaces, allow that to proceed properly
+			 */
+			ieee80211_wake_queues_by_reason(hw,
+					IEEE80211_MAX_QUEUE_MAP,
+					IEEE80211_QUEUE_STOP_REASON_SUSPEND,
+					false);
 			return err;
 		} else {
 			goto suspend;
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 10/16] mac80211: allow TDLS setup code to take wdev lock
  2015-03-01  7:09 [PATCH 00/16] Various patches from our internal tree Emmanuel Grumbach
                   ` (8 preceding siblings ...)
  2015-03-01  7:10 ` [PATCH 09/16] mac80211: start queues if driver rejected wowlan Emmanuel Grumbach
@ 2015-03-01  7:10 ` Emmanuel Grumbach
  2015-03-01  7:10 ` [PATCH 11/16] mac80211: remove duplicate check for quiescing when queueing work Emmanuel Grumbach
                   ` (6 subsequent siblings)
  16 siblings, 0 replies; 20+ messages in thread
From: Emmanuel Grumbach @ 2015-03-01  7:10 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Arik Nemtsov, Arik Nemtsov, Emmanuel Grumbach

From: Arik Nemtsov <arik@wizery.com>

TDLS off-channel can be allowed in channels marked with GO_CONCURRENT,
provided the device is connected to an AP on the same UNII.
When relaxing the NO-IR requirements for TDLS, we might hit flows in
cfg80211_reg_can_beacon that acquire the wdev lock. Take some measures
to allow this during TDLS setup.
Acquire the RCU read lock later in the flow that invokes
cfg80211_reg_can_beacon.
Avoid taking local->mtx when preparing the setup packet to avoid
circular deadlocks with mac80211 code that is invoked with wdev-mtx
held.

Signed-off-by: Arik Nemtsov <arikx.nemtsov@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
---
 net/mac80211/tdls.c | 41 ++++++++++++++++++++++++-----------------
 1 file changed, 24 insertions(+), 17 deletions(-)

diff --git a/net/mac80211/tdls.c b/net/mac80211/tdls.c
index 5bcd542..bc7e404 100644
--- a/net/mac80211/tdls.c
+++ b/net/mac80211/tdls.c
@@ -287,17 +287,6 @@ ieee80211_tdls_add_setup_start_ies(struct ieee80211_sub_if_data *sdata,
 	size_t offset = 0, noffset;
 	u8 *pos;
 
-	rcu_read_lock();
-
-	/* we should have the peer STA if we're already responding */
-	if (action_code == WLAN_TDLS_SETUP_RESPONSE) {
-		sta = sta_info_get(sdata, peer);
-		if (WARN_ON_ONCE(!sta)) {
-			rcu_read_unlock();
-			return;
-		}
-	}
-
 	ieee80211_add_srates_ie(sdata, skb, false, band);
 	ieee80211_add_ext_srates_ie(sdata, skb, false, band);
 	ieee80211_tdls_add_supp_channels(sdata, skb);
@@ -350,6 +339,17 @@ ieee80211_tdls_add_setup_start_ies(struct ieee80211_sub_if_data *sdata,
 		offset = noffset;
 	}
 
+	rcu_read_lock();
+
+	/* we should have the peer STA if we're already responding */
+	if (action_code == WLAN_TDLS_SETUP_RESPONSE) {
+		sta = sta_info_get(sdata, peer);
+		if (WARN_ON_ONCE(!sta)) {
+			rcu_read_unlock();
+			return;
+		}
+	}
+
 	/*
 	 * with TDLS we can switch channels, and HT-caps are not necessarily
 	 * the same on all bands. The specification limits the setup to a
@@ -983,7 +983,7 @@ ieee80211_tdls_mgmt_setup(struct wiphy *wiphy, struct net_device *dev,
 	if (!is_zero_ether_addr(sdata->u.mgd.tdls_peer) &&
 	    !ether_addr_equal(sdata->u.mgd.tdls_peer, peer)) {
 		ret = -EBUSY;
-		goto exit;
+		goto out_unlock;
 	}
 
 	/*
@@ -998,27 +998,34 @@ ieee80211_tdls_mgmt_setup(struct wiphy *wiphy, struct net_device *dev,
 		if (!sta_info_get(sdata, peer)) {
 			rcu_read_unlock();
 			ret = -ENOLINK;
-			goto exit;
+			goto out_unlock;
 		}
 		rcu_read_unlock();
 	}
 
 	ieee80211_flush_queues(local, sdata, false);
+	memcpy(sdata->u.mgd.tdls_peer, peer, ETH_ALEN);
+	mutex_unlock(&local->mtx);
 
+	/* we cannot take the mutex while preparing the setup packet */
 	ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer, action_code,
 					      dialog_token, status_code,
 					      peer_capability, initiator,
 					      extra_ies, extra_ies_len, 0,
 					      NULL);
-	if (ret < 0)
-		goto exit;
+	if (ret < 0) {
+		mutex_lock(&local->mtx);
+		eth_zero_addr(sdata->u.mgd.tdls_peer);
+		mutex_unlock(&local->mtx);
+		return ret;
+	}
 
-	memcpy(sdata->u.mgd.tdls_peer, peer, ETH_ALEN);
 	ieee80211_queue_delayed_work(&sdata->local->hw,
 				     &sdata->u.mgd.tdls_peer_del_work,
 				     TDLS_PEER_SETUP_TIMEOUT);
+	return 0;
 
-exit:
+out_unlock:
 	mutex_unlock(&local->mtx);
 	return ret;
 }
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 11/16] mac80211: remove duplicate check for quiescing when queueing work
  2015-03-01  7:09 [PATCH 00/16] Various patches from our internal tree Emmanuel Grumbach
                   ` (9 preceding siblings ...)
  2015-03-01  7:10 ` [PATCH 10/16] mac80211: allow TDLS setup code to take wdev lock Emmanuel Grumbach
@ 2015-03-01  7:10 ` Emmanuel Grumbach
  2015-03-01  7:10 ` [PATCH 12/16] mac80211: update TDLS sta spatial streams before auth Emmanuel Grumbach
                   ` (5 subsequent siblings)
  16 siblings, 0 replies; 20+ messages in thread
From: Emmanuel Grumbach @ 2015-03-01  7:10 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Luciano Coelho, Emmanuel Grumbach

From: Luciano Coelho <luciano.coelho@intel.com>

In ieee80211_queue_work() we check if we're quiescing or suspended, so
it's not necessary to check for quiescing before calling this
function.  Remove duplicate checks.

Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
---
 net/mac80211/mlme.c | 10 ----------
 1 file changed, 10 deletions(-)

diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index c5f3bd6..bc2975e 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1621,9 +1621,6 @@ void ieee80211_dynamic_ps_timer(unsigned long data)
 {
 	struct ieee80211_local *local = (void *) data;
 
-	if (local->quiescing || local->suspended)
-		return;
-
 	ieee80211_queue_work(&local->hw, &local->dynamic_ps_enable_work);
 }
 
@@ -3899,12 +3896,8 @@ static void ieee80211_sta_bcn_mon_timer(unsigned long data)
 {
 	struct ieee80211_sub_if_data *sdata =
 		(struct ieee80211_sub_if_data *) data;
-	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 
-	if (local->quiescing)
-		return;
-
 	if (sdata->vif.csa_active && !ifmgd->csa_waiting_bcn)
 		return;
 
@@ -3920,9 +3913,6 @@ static void ieee80211_sta_conn_mon_timer(unsigned long data)
 	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 	struct ieee80211_local *local = sdata->local;
 
-	if (local->quiescing)
-		return;
-
 	if (sdata->vif.csa_active && !ifmgd->csa_waiting_bcn)
 		return;
 
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 12/16] mac80211: update TDLS sta spatial streams before auth
  2015-03-01  7:09 [PATCH 00/16] Various patches from our internal tree Emmanuel Grumbach
                   ` (10 preceding siblings ...)
  2015-03-01  7:10 ` [PATCH 11/16] mac80211: remove duplicate check for quiescing when queueing work Emmanuel Grumbach
@ 2015-03-01  7:10 ` Emmanuel Grumbach
  2015-03-01  7:10 ` [PATCH 13/16] mac80211: check and dequeue skb in ieee80211_tx_prepare_skb() Emmanuel Grumbach
                   ` (4 subsequent siblings)
  16 siblings, 0 replies; 20+ messages in thread
From: Emmanuel Grumbach @ 2015-03-01  7:10 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Arik Nemtsov, Arik Nemtsov, Emmanuel Grumbach

From: Arik Nemtsov <arik@wizery.com>

Make sure the number of spatial streams is correctly updated for a TDLS
station. Usually this is done during rate control init, during the
add_station nl80211 command. Unfortunately TDLS stations only get valid
HT/VHT-cap information in the change_station nl80211 command, and
rate-control init is delayed accordingly.

Some drivers (iwlwifi) assume the nss will be appropriately during the
sta_state(assoc) callback, and this doesn't hold for TDLS. Initialize
the nss earlier for TDLS peers, which also has the benefit of making
sta_state behavior more consistent.

Signed-off-by: Arik Nemtsov <arikx.nemtsov@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
---
 net/mac80211/cfg.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 02f1125..bc33911 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1126,6 +1126,10 @@ static int sta_apply_parameters(struct ieee80211_local *local,
 		ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
 						    params->vht_capa, sta);
 
+	if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) &&
+	    (params->ht_capa || params->vht_capa))
+		ieee80211_sta_set_rx_nss(sta);
+
 	if (params->opmode_notif_used) {
 		/* returned value is only needed for rc update, but the
 		 * rc isn't initialized here yet, so ignore it
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 13/16] mac80211: check and dequeue skb in ieee80211_tx_prepare_skb()
  2015-03-01  7:09 [PATCH 00/16] Various patches from our internal tree Emmanuel Grumbach
                   ` (11 preceding siblings ...)
  2015-03-01  7:10 ` [PATCH 12/16] mac80211: update TDLS sta spatial streams before auth Emmanuel Grumbach
@ 2015-03-01  7:10 ` Emmanuel Grumbach
  2015-03-01  7:10 ` [PATCH 14/16] nl80211: prohibit mixing 'any' and regular wowlan triggers Emmanuel Grumbach
                   ` (3 subsequent siblings)
  16 siblings, 0 replies; 20+ messages in thread
From: Emmanuel Grumbach @ 2015-03-01  7:10 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

The ieee80211_tx_prepare_skb() function currently entirely ignores
the fact that the SKB that is passed in might be split into more
than one due to fragmentation and doesn't check the list of skbs
that the TX handlers may create. In case this happens, it would
leak them.

Fix this and also don't leave the skb next/prev pointers dangling
pointing to the on-stack sk_buff_head.

Reported-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/tx.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 07bd8db..c519f06 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1422,6 +1422,7 @@ bool ieee80211_tx_prepare_skb(struct ieee80211_hw *hw,
 	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 	struct ieee80211_tx_data tx;
+	struct sk_buff *skb2;
 
 	if (ieee80211_tx_prepare(sdata, &tx, skb) == TX_DROP)
 		return false;
@@ -1440,6 +1441,14 @@ bool ieee80211_tx_prepare_skb(struct ieee80211_hw *hw,
 			*sta = NULL;
 	}
 
+	/* this function isn't suitable for fragmented data frames */
+	skb2 = __skb_dequeue(&tx.skbs);
+	if (WARN_ON(skb2 != skb || !skb_queue_empty(&tx.skbs))) {
+		ieee80211_free_txskb(hw, skb2);
+		ieee80211_purge_tx_queue(hw, &tx.skbs);
+		return false;
+	}
+
 	return true;
 }
 EXPORT_SYMBOL(ieee80211_tx_prepare_skb);
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 14/16] nl80211: prohibit mixing 'any' and regular wowlan triggers
  2015-03-01  7:09 [PATCH 00/16] Various patches from our internal tree Emmanuel Grumbach
                   ` (12 preceding siblings ...)
  2015-03-01  7:10 ` [PATCH 13/16] mac80211: check and dequeue skb in ieee80211_tx_prepare_skb() Emmanuel Grumbach
@ 2015-03-01  7:10 ` Emmanuel Grumbach
  2015-03-01  7:10 ` [PATCH 15/16] mac80211: remove channel_switch_beacon operation Emmanuel Grumbach
                   ` (2 subsequent siblings)
  16 siblings, 0 replies; 20+ messages in thread
From: Emmanuel Grumbach @ 2015-03-01  7:10 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

If the device supports waking up on 'any' signal - i.e. it continues
operating as usual and wakes up the host on pretty much anything that
happens, then it makes no sense to also configure the more restricted
WoWLAN mode where the device operates more autonomously but also in a
more restricted fashion.

Currently only cw2100 supports both 'any' and other triggers, but it
seems to be broken as it doesn't configure anything to the device, so
we can't currently get into a situation where both even can correctly
be configured. This is about to change (Intel devices are going to
support both and have different behaviour depending on configuration)
so make sure the conflicting modes cannot be configured.

(It seems that cw2100 advertises 'any' and 'disconnect' as a means of
saying that's what it will always do, but that isn't really the way
this API was meant to be used nor does it actually mean anything as
'any' always implies 'disconnect' already, and the driver doesn't
change device configuration in any way depending on the settings.)

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 include/uapi/linux/nl80211.h |  2 ++
 net/wireless/nl80211.c       | 22 ++++++++++++++++++++++
 2 files changed, 24 insertions(+)

diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 68b294e..26eac5a 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -3694,6 +3694,8 @@ struct nl80211_pattern_support {
  * @NL80211_WOWLAN_TRIG_ANY: wake up on any activity, do not really put
  *	the chip into a special state -- works best with chips that have
  *	support for low-power operation already (flag)
+ *	Note that this mode is incompatible with all of the others, if
+ *	any others are even supported by the device.
  * @NL80211_WOWLAN_TRIG_DISCONNECT: wake up on disconnect, the way disconnect
  *	is detected is implementation-specific (flag)
  * @NL80211_WOWLAN_TRIG_MAGIC_PKT: wake up on magic packet (6x 0xff, followed
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index be25015..8471c66 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -9084,6 +9084,7 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
 	const struct wiphy_wowlan_support *wowlan = rdev->wiphy.wowlan;
 	int err, i;
 	bool prev_enabled = rdev->wiphy.wowlan_config;
+	bool regular = false;
 
 	if (!wowlan)
 		return -EOPNOTSUPP;
@@ -9111,12 +9112,14 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
 		if (!(wowlan->flags & WIPHY_WOWLAN_DISCONNECT))
 			return -EINVAL;
 		new_triggers.disconnect = true;
+		regular = true;
 	}
 
 	if (tb[NL80211_WOWLAN_TRIG_MAGIC_PKT]) {
 		if (!(wowlan->flags & WIPHY_WOWLAN_MAGIC_PKT))
 			return -EINVAL;
 		new_triggers.magic_pkt = true;
+		regular = true;
 	}
 
 	if (tb[NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED])
@@ -9126,24 +9129,28 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
 		if (!(wowlan->flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE))
 			return -EINVAL;
 		new_triggers.gtk_rekey_failure = true;
+		regular = true;
 	}
 
 	if (tb[NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST]) {
 		if (!(wowlan->flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ))
 			return -EINVAL;
 		new_triggers.eap_identity_req = true;
+		regular = true;
 	}
 
 	if (tb[NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE]) {
 		if (!(wowlan->flags & WIPHY_WOWLAN_4WAY_HANDSHAKE))
 			return -EINVAL;
 		new_triggers.four_way_handshake = true;
+		regular = true;
 	}
 
 	if (tb[NL80211_WOWLAN_TRIG_RFKILL_RELEASE]) {
 		if (!(wowlan->flags & WIPHY_WOWLAN_RFKILL_RELEASE))
 			return -EINVAL;
 		new_triggers.rfkill_release = true;
+		regular = true;
 	}
 
 	if (tb[NL80211_WOWLAN_TRIG_PKT_PATTERN]) {
@@ -9152,6 +9159,8 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
 		int rem, pat_len, mask_len, pkt_offset;
 		struct nlattr *pat_tb[NUM_NL80211_PKTPAT];
 
+		regular = true;
+
 		nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN],
 				    rem)
 			n_patterns++;
@@ -9213,6 +9222,7 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
 	}
 
 	if (tb[NL80211_WOWLAN_TRIG_TCP_CONNECTION]) {
+		regular = true;
 		err = nl80211_parse_wowlan_tcp(
 			rdev, tb[NL80211_WOWLAN_TRIG_TCP_CONNECTION],
 			&new_triggers);
@@ -9221,6 +9231,7 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
 	}
 
 	if (tb[NL80211_WOWLAN_TRIG_NET_DETECT]) {
+		regular = true;
 		err = nl80211_parse_wowlan_nd(
 			rdev, wowlan, tb[NL80211_WOWLAN_TRIG_NET_DETECT],
 			&new_triggers);
@@ -9228,6 +9239,17 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
 			goto error;
 	}
 
+	/* The 'any' trigger means the device continues operating more or less
+	 * as in its normal operation mode and wakes up the host on most of the
+	 * normal interrupts (like packet RX, ...)
+	 * It therefore makes little sense to combine with the more constrained
+	 * wakeup trigger modes.
+	 */
+	if (new_triggers.any && regular) {
+		err = -EINVAL;
+		goto error;
+	}
+
 	ntrig = kmemdup(&new_triggers, sizeof(new_triggers), GFP_KERNEL);
 	if (!ntrig) {
 		err = -ENOMEM;
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 15/16] mac80211: remove channel_switch_beacon operation
  2015-03-01  7:09 [PATCH 00/16] Various patches from our internal tree Emmanuel Grumbach
                   ` (13 preceding siblings ...)
  2015-03-01  7:10 ` [PATCH 14/16] nl80211: prohibit mixing 'any' and regular wowlan triggers Emmanuel Grumbach
@ 2015-03-01  7:10 ` Emmanuel Grumbach
  2015-03-01  7:10 ` [PATCH 16/16] mac80211: allow iterating inactive interfaces Emmanuel Grumbach
  2015-03-03  9:47 ` [PATCH 00/16] Various patches from our internal tree Johannes Berg
  16 siblings, 0 replies; 20+ messages in thread
From: Emmanuel Grumbach @ 2015-03-01  7:10 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Luciano Coelho, Emmanuel Grumbach

From: Luciano Coelho <luciano.coelho@intel.com>

This operation has been replaced by a more generic pre_channel_switch
callback, that can be called for any interface type.  No driver is
using it anymore, and the ones that were using it were not doing any
beacon-related operation anyway.

Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
---
 include/net/mac80211.h    | 26 ++++++++++++--------------
 net/mac80211/cfg.c        |  1 -
 net/mac80211/driver-ops.h | 13 -------------
 net/mac80211/trace.h      | 25 -------------------------
 4 files changed, 12 insertions(+), 53 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 78ecfe5..dcd309b 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2959,20 +2959,21 @@ enum ieee80211_reconfig_type {
  *	Currently, this is only called for managed or P2P client interfaces.
  *	This callback is optional; it must not sleep.
  *
- * @channel_switch_beacon: Starts a channel switch to a new channel.
- *	Beacons are modified to include CSA or ECSA IEs before calling this
- *	function. The corresponding count fields in these IEs must be
- *	decremented, and when they reach 1 the driver must call
- *	ieee80211_csa_finish(). Drivers which use ieee80211_beacon_get()
- *	get the csa counter decremented by mac80211, but must check if it is
- *	1 using ieee80211_csa_is_complete() after the beacon has been
- *	transmitted and then call ieee80211_csa_finish().
- *	If the CSA count starts as zero or 1, this function will not be called,
- *	since there won't be any time to beacon before the switch anyway.
  * @pre_channel_switch: This is an optional callback that is called
  *	before a channel switch procedure is started (ie. when a STA
  *	gets a CSA or an userspace initiated channel-switch), allowing
- *	the driver to prepare for the channel switch.
+ *	the driver to prepare for the channel switch.  For beaconing
+ *	interfaces, the beacons will be modified to include CSA or
+ *	ECSA IEs after this function is called. The corresponding
+ *	count fields in these IEs must be decremented, and when they
+ *	reach 1 the driver must call ieee80211_csa_finish(). Drivers
+ *	which use ieee80211_beacon_get() get the csa counter
+ *	decremented by mac80211, but must check if it is 1 using
+ *	ieee80211_csa_is_complete() after the beacon has been
+ *	transmitted and then call ieee80211_csa_finish().  If the CSA
+ *	count starts as zero or 1, this function will not be called,
+ *	since there won't be any time to beacon before the switch
+ *	anyway.
  * @post_channel_switch: This is an optional callback that is called
  *	after a channel switch procedure is completed, allowing the
  *	driver to go back to a normal configuration.
@@ -3209,9 +3210,6 @@ struct ieee80211_ops {
 				 struct ieee80211_vif *vif,
 				 struct inet6_dev *idev);
 #endif
-	void (*channel_switch_beacon)(struct ieee80211_hw *hw,
-				      struct ieee80211_vif *vif,
-				      struct cfg80211_chan_def *chandef);
 	int (*pre_channel_switch)(struct ieee80211_hw *hw,
 				  struct ieee80211_vif *vif,
 				  struct ieee80211_channel_switch *ch_switch);
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index bc33911..9c5244d 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3287,7 +3287,6 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
 
 	if (changed) {
 		ieee80211_bss_info_change_notify(sdata, changed);
-		drv_channel_switch_beacon(sdata, &params->chandef);
 	} else {
 		/* if the beacon didn't change, we can finalize immediately */
 		ieee80211_csa_finalize(sdata);
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index fdeda17..1ee1981 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -1211,19 +1211,6 @@ static inline void drv_ipv6_addr_change(struct ieee80211_local *local,
 }
 #endif
 
-static inline void
-drv_channel_switch_beacon(struct ieee80211_sub_if_data *sdata,
-			  struct cfg80211_chan_def *chandef)
-{
-	struct ieee80211_local *local = sdata->local;
-
-	if (local->ops->channel_switch_beacon) {
-		trace_drv_channel_switch_beacon(local, sdata, chandef);
-		local->ops->channel_switch_beacon(&local->hw, &sdata->vif,
-						  chandef);
-	}
-}
-
 static inline int
 drv_pre_channel_switch(struct ieee80211_sub_if_data *sdata,
 		       struct ieee80211_channel_switch *ch_switch)
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index 263a956..77c9c93 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -2117,31 +2117,6 @@ TRACE_EVENT(api_radar_detected,
 	)
 );
 
-TRACE_EVENT(drv_channel_switch_beacon,
-	TP_PROTO(struct ieee80211_local *local,
-		 struct ieee80211_sub_if_data *sdata,
-		 struct cfg80211_chan_def *chandef),
-
-	TP_ARGS(local, sdata, chandef),
-
-	TP_STRUCT__entry(
-		LOCAL_ENTRY
-		VIF_ENTRY
-		CHANDEF_ENTRY
-	),
-
-	TP_fast_assign(
-		LOCAL_ASSIGN;
-		VIF_ASSIGN;
-		CHANDEF_ASSIGN(chandef);
-	),
-
-	TP_printk(
-		LOCAL_PR_FMT VIF_PR_FMT " channel switch to " CHANDEF_PR_FMT,
-		LOCAL_PR_ARG, VIF_PR_ARG, CHANDEF_PR_ARG
-	)
-);
-
 TRACE_EVENT(drv_pre_channel_switch,
 	TP_PROTO(struct ieee80211_local *local,
 		 struct ieee80211_sub_if_data *sdata,
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 16/16] mac80211: allow iterating inactive interfaces
  2015-03-01  7:09 [PATCH 00/16] Various patches from our internal tree Emmanuel Grumbach
                   ` (14 preceding siblings ...)
  2015-03-01  7:10 ` [PATCH 15/16] mac80211: remove channel_switch_beacon operation Emmanuel Grumbach
@ 2015-03-01  7:10 ` Emmanuel Grumbach
  2015-03-03  9:47 ` [PATCH 00/16] Various patches from our internal tree Johannes Berg
  16 siblings, 0 replies; 20+ messages in thread
From: Emmanuel Grumbach @ 2015-03-01  7:10 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Arik Nemtsov, Arik Nemtsov, Emmanuel Grumbach

From: Arik Nemtsov <arik@wizery.com>

Sometimes the driver might want to modify private data in interfaces
that are down. One possible use-case is cleaning up interface state
after HW recovery. Some interfaces that were up before the recovery took
place might be down now, but they might still be "dirty".

Introduce a new iterate_interfaces() API and a new ACTIVE iterator flag.
This way the internal implementation of the both active and inactive
APIs remains the same.

Signed-off-by: Arik Nemtsov <arikx.nemtsov@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
---
 include/net/mac80211.h | 35 ++++++++++++++++++++++++++++++-----
 net/mac80211/util.c    | 29 ++++++++++++++++-------------
 2 files changed, 46 insertions(+), 18 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index dcd309b..4a4619d 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -4353,13 +4353,33 @@ void ieee80211_sched_scan_stopped(struct ieee80211_hw *hw);
  *	haven't been re-added to the driver yet.
  * @IEEE80211_IFACE_ITER_RESUME_ALL: During resume, iterate over all
  *	interfaces, even if they haven't been re-added to the driver yet.
+ * @IEEE80211_IFACE_ITER_ACTIVE: Iterate only active interfaces (netdev is up).
  */
 enum ieee80211_interface_iteration_flags {
 	IEEE80211_IFACE_ITER_NORMAL	= 0,
 	IEEE80211_IFACE_ITER_RESUME_ALL	= BIT(0),
+	IEEE80211_IFACE_ITER_ACTIVE	= BIT(1),
 };
 
 /**
+ * ieee80211_iterate_interfaces - iterate interfaces
+ *
+ * This function iterates over the interfaces associated with a given
+ * hardware and calls the callback for them. This includes active as well as
+ * inactive interfaces. This function allows the iterator function to sleep.
+ * Will iterate over a new interface during add_interface().
+ *
+ * @hw: the hardware struct of which the interfaces should be iterated over
+ * @iter_flags: iteration flags, see &enum ieee80211_interface_iteration_flags
+ * @iterator: the iterator function to call
+ * @data: first argument of the iterator function
+ */
+void ieee80211_iterate_interfaces(struct ieee80211_hw *hw, u32 iter_flags,
+				  void (*iterator)(void *data, u8 *mac,
+						   struct ieee80211_vif *vif),
+				  void *data);
+
+/**
  * ieee80211_iterate_active_interfaces - iterate active interfaces
  *
  * This function iterates over the interfaces associated with a given
@@ -4374,11 +4394,16 @@ enum ieee80211_interface_iteration_flags {
  * @iterator: the iterator function to call
  * @data: first argument of the iterator function
  */
-void ieee80211_iterate_active_interfaces(struct ieee80211_hw *hw,
-					 u32 iter_flags,
-					 void (*iterator)(void *data, u8 *mac,
-						struct ieee80211_vif *vif),
-					 void *data);
+static inline void
+ieee80211_iterate_active_interfaces(struct ieee80211_hw *hw, u32 iter_flags,
+				    void (*iterator)(void *data, u8 *mac,
+						     struct ieee80211_vif *vif),
+				    void *data)
+{
+	ieee80211_iterate_interfaces(hw,
+				     iter_flags | IEEE80211_IFACE_ITER_ACTIVE,
+				     iterator, data);
+}
 
 /**
  * ieee80211_iterate_active_interfaces_atomic - iterate active interfaces
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 32788674..37d85d3 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -625,13 +625,14 @@ void ieee80211_wake_vif_queues(struct ieee80211_local *local,
 					reason, true);
 }
 
-static void __iterate_active_interfaces(struct ieee80211_local *local,
-					u32 iter_flags,
-					void (*iterator)(void *data, u8 *mac,
-						struct ieee80211_vif *vif),
-					void *data)
+static void __iterate_interfaces(struct ieee80211_local *local,
+				 u32 iter_flags,
+				 void (*iterator)(void *data, u8 *mac,
+						  struct ieee80211_vif *vif),
+				 void *data)
 {
 	struct ieee80211_sub_if_data *sdata;
+	bool active_only = iter_flags & IEEE80211_IFACE_ITER_ACTIVE;
 
 	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
 		switch (sdata->vif.type) {
@@ -645,9 +646,9 @@ static void __iterate_active_interfaces(struct ieee80211_local *local,
 			break;
 		}
 		if (!(iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL) &&
-		    !(sdata->flags & IEEE80211_SDATA_IN_DRIVER))
+		    active_only && !(sdata->flags & IEEE80211_SDATA_IN_DRIVER))
 			continue;
-		if (ieee80211_sdata_running(sdata))
+		if (ieee80211_sdata_running(sdata) || !active_only)
 			iterator(data, sdata->vif.addr,
 				 &sdata->vif);
 	}
@@ -656,12 +657,12 @@ static void __iterate_active_interfaces(struct ieee80211_local *local,
 				      lockdep_is_held(&local->iflist_mtx) ||
 				      lockdep_rtnl_is_held());
 	if (sdata &&
-	    (iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL ||
+	    (iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL || !active_only ||
 	     sdata->flags & IEEE80211_SDATA_IN_DRIVER))
 		iterator(data, sdata->vif.addr, &sdata->vif);
 }
 
-void ieee80211_iterate_active_interfaces(
+void ieee80211_iterate_interfaces(
 	struct ieee80211_hw *hw, u32 iter_flags,
 	void (*iterator)(void *data, u8 *mac,
 			 struct ieee80211_vif *vif),
@@ -670,10 +671,10 @@ void ieee80211_iterate_active_interfaces(
 	struct ieee80211_local *local = hw_to_local(hw);
 
 	mutex_lock(&local->iflist_mtx);
-	__iterate_active_interfaces(local, iter_flags, iterator, data);
+	__iterate_interfaces(local, iter_flags, iterator, data);
 	mutex_unlock(&local->iflist_mtx);
 }
-EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces);
+EXPORT_SYMBOL_GPL(ieee80211_iterate_interfaces);
 
 void ieee80211_iterate_active_interfaces_atomic(
 	struct ieee80211_hw *hw, u32 iter_flags,
@@ -684,7 +685,8 @@ void ieee80211_iterate_active_interfaces_atomic(
 	struct ieee80211_local *local = hw_to_local(hw);
 
 	rcu_read_lock();
-	__iterate_active_interfaces(local, iter_flags, iterator, data);
+	__iterate_interfaces(local, iter_flags | IEEE80211_IFACE_ITER_ACTIVE,
+			     iterator, data);
 	rcu_read_unlock();
 }
 EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic);
@@ -699,7 +701,8 @@ void ieee80211_iterate_active_interfaces_rtnl(
 
 	ASSERT_RTNL();
 
-	__iterate_active_interfaces(local, iter_flags, iterator, data);
+	__iterate_interfaces(local, iter_flags | IEEE80211_IFACE_ITER_ACTIVE,
+			     iterator, data);
 }
 EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_rtnl);
 
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH 00/16] Various patches from our internal tree
  2015-03-01  7:09 [PATCH 00/16] Various patches from our internal tree Emmanuel Grumbach
                   ` (15 preceding siblings ...)
  2015-03-01  7:10 ` [PATCH 16/16] mac80211: allow iterating inactive interfaces Emmanuel Grumbach
@ 2015-03-03  9:47 ` Johannes Berg
  2015-03-03 10:01   ` Johannes Berg
  16 siblings, 1 reply; 20+ messages in thread
From: Johannes Berg @ 2015-03-03  9:47 UTC (permalink / raw)
  To: Emmanuel Grumbach; +Cc: linux-wireless

All applied, except for 

> Arik Nemtsov (4):
>   mac80211: update TDLS sta spatial streams before auth

this one where I'm trying to see if it can be combined with another
patch.

johannes


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 00/16] Various patches from our internal tree
  2015-03-03  9:47 ` [PATCH 00/16] Various patches from our internal tree Johannes Berg
@ 2015-03-03 10:01   ` Johannes Berg
  0 siblings, 0 replies; 20+ messages in thread
From: Johannes Berg @ 2015-03-03 10:01 UTC (permalink / raw)
  To: Emmanuel Grumbach; +Cc: linux-wireless, Luciano Coelho

On Tue, 2015-03-03 at 10:47 +0100, Johannes Berg wrote:
> All applied, except for 
> 
> > Arik Nemtsov (4):
> >   mac80211: update TDLS sta spatial streams before auth
> 
> this one where I'm trying to see if it can be combined with another
> patch.

And patch 15 broke the TI driver build, so I've dropped that.

johannes


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 06/16] mac80211: tell drivers the user TX power restriction
  2015-03-01  7:10 ` [PATCH 06/16] mac80211: tell drivers the user TX power restriction Emmanuel Grumbach
@ 2015-03-04  9:34   ` Johannes Berg
  0 siblings, 0 replies; 20+ messages in thread
From: Johannes Berg @ 2015-03-04  9:34 UTC (permalink / raw)
  To: Emmanuel Grumbach; +Cc: linux-wireless, Avri Altman

On Sun, 2015-03-01 at 09:10 +0200, Emmanuel Grumbach wrote:
> From: Avri Altman <avri.altman@intel.com>
> 
> Allow drivers to obtain the user's TX power restrictions in
> order to be able to  apply it properly on (for example)
> hardware scanning which operations on a set of channels,
> in which case mac80211 cannot properly apply the per-channel
> regulatory limits, and the currently exposed txpower value,
> which is the minimum  of the user setting, channel regulatory
> and possible 11h AP reduction isn't  appropriate to use
> since scanning is done on many channels.
> 
> Note that drivers need to be careful when using this value
> and must ensure that  regulatory is maintained, i.e. the
> new value cannot be used as-is.

Actually, given that it looks like this conflicts with other things
we're doing, we're probably going to find another approach. I'll drop
this for now from my tree.

johannes


^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2015-03-04  9:34 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-03-01  7:09 [PATCH 00/16] Various patches from our internal tree Emmanuel Grumbach
2015-03-01  7:10 ` [PATCH 01/16] mac80211: Update beacon's timing and DTIM count on every beacon Emmanuel Grumbach
2015-03-01  7:10 ` [PATCH 02/16] cfg80211: add operating classes 128-130 Emmanuel Grumbach
2015-03-01  7:10 ` [PATCH 03/16] mac80211: TDLS: support VHT between peers Emmanuel Grumbach
2015-03-01  7:10 ` [PATCH 04/16] mac80211: fix another suspend vs. association race Emmanuel Grumbach
2015-03-01  7:10 ` [PATCH 05/16] mac80211: handle drv_add_interface failures properly during reconfig Emmanuel Grumbach
2015-03-01  7:10 ` [PATCH 06/16] mac80211: tell drivers the user TX power restriction Emmanuel Grumbach
2015-03-04  9:34   ` Johannes Berg
2015-03-01  7:10 ` [PATCH 07/16] mac80211: don't do driver suspend with auth/assoc in progress Emmanuel Grumbach
2015-03-01  7:10 ` [PATCH 08/16] mac80211: remove useless double check for open_count in __ieee80211_suspend() Emmanuel Grumbach
2015-03-01  7:10 ` [PATCH 09/16] mac80211: start queues if driver rejected wowlan Emmanuel Grumbach
2015-03-01  7:10 ` [PATCH 10/16] mac80211: allow TDLS setup code to take wdev lock Emmanuel Grumbach
2015-03-01  7:10 ` [PATCH 11/16] mac80211: remove duplicate check for quiescing when queueing work Emmanuel Grumbach
2015-03-01  7:10 ` [PATCH 12/16] mac80211: update TDLS sta spatial streams before auth Emmanuel Grumbach
2015-03-01  7:10 ` [PATCH 13/16] mac80211: check and dequeue skb in ieee80211_tx_prepare_skb() Emmanuel Grumbach
2015-03-01  7:10 ` [PATCH 14/16] nl80211: prohibit mixing 'any' and regular wowlan triggers Emmanuel Grumbach
2015-03-01  7:10 ` [PATCH 15/16] mac80211: remove channel_switch_beacon operation Emmanuel Grumbach
2015-03-01  7:10 ` [PATCH 16/16] mac80211: allow iterating inactive interfaces Emmanuel Grumbach
2015-03-03  9:47 ` [PATCH 00/16] Various patches from our internal tree Johannes Berg
2015-03-03 10:01   ` Johannes Berg

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.