All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/5] mac80211: stations per virtual interface, netdev reduction
@ 2009-11-25 16:46 Johannes Berg
  2009-11-25 16:46 ` [PATCH v2 1/5] mac80211: move cmntr flag out of rx flags Johannes Berg
                   ` (4 more replies)
  0 siblings, 5 replies; 12+ messages in thread
From: Johannes Berg @ 2009-11-25 16:46 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless

This patchset finally converts station to fully be
managed per virtual interface.

There are also two patches to remove the use of netdevs
in mac80211.

I've been running with this for a while with a few
other scenarios too (like hwsim AP test) so I'm pretty
confident it works. And this time it actually does work
in more test scenarios ...

johannes


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

* [PATCH v2 1/5] mac80211: move cmntr flag out of rx flags
  2009-11-25 16:46 [PATCH v2 0/5] mac80211: stations per virtual interface, netdev reduction Johannes Berg
@ 2009-11-25 16:46 ` Johannes Berg
  2009-11-25 16:46 ` [PATCH v2 2/5] mac80211: move aMPDU RX reorder code Johannes Berg
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 12+ messages in thread
From: Johannes Berg @ 2009-11-25 16:46 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless

The RX flags should soon be used only for flags
that cannot change within an a-MPDU, so move the
cooked monitor flag into the RX status flags.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
 include/net/mac80211.h     |    4 ++++
 net/mac80211/ieee80211_i.h |    3 +--
 net/mac80211/rx.c          |    4 ++--
 3 files changed, 7 insertions(+), 4 deletions(-)

--- wireless-testing.orig/include/net/mac80211.h	2009-11-19 14:38:32.000000000 +0100
+++ wireless-testing/include/net/mac80211.h	2009-11-19 14:38:33.000000000 +0100
@@ -513,6 +513,9 @@ ieee80211_tx_info_clear_status(struct ie
  * @RX_FLAG_HT: HT MCS was used and rate_idx is MCS index
  * @RX_FLAG_40MHZ: HT40 (40 MHz) was used
  * @RX_FLAG_SHORT_GI: Short guard interval was used
+ * @RX_FLAG_INTERNAL_CMTR: set internally after frame was reported
+ *	on cooked monitor to avoid double-reporting it for multiple
+ *	virtual interfaces
  */
 enum mac80211_rx_flags {
 	RX_FLAG_MMIC_ERROR	= 1<<0,
@@ -526,6 +529,7 @@ enum mac80211_rx_flags {
 	RX_FLAG_HT		= 1<<9,
 	RX_FLAG_40MHZ		= 1<<10,
 	RX_FLAG_SHORT_GI	= 1<<11,
+	RX_FLAG_INTERNAL_CMTR	= 1<<12,
 };
 
 /**
--- wireless-testing.orig/net/mac80211/ieee80211_i.h	2009-11-19 14:38:32.000000000 +0100
+++ wireless-testing/net/mac80211/ieee80211_i.h	2009-11-19 14:38:33.000000000 +0100
@@ -163,8 +163,7 @@ typedef unsigned __bitwise__ ieee80211_r
 /* frame is destined to interface currently processed (incl. multicast frames) */
 #define IEEE80211_RX_RA_MATCH		BIT(1)
 #define IEEE80211_RX_AMSDU		BIT(2)
-#define IEEE80211_RX_CMNTR_REPORTED	BIT(3)
-#define IEEE80211_RX_FRAGMENTED		BIT(4)
+#define IEEE80211_RX_FRAGMENTED		BIT(3)
 
 struct ieee80211_rx_data {
 	struct sk_buff *skb;
--- wireless-testing.orig/net/mac80211/rx.c	2009-11-19 14:38:32.000000000 +0100
+++ wireless-testing/net/mac80211/rx.c	2009-11-19 14:38:33.000000000 +0100
@@ -1868,7 +1868,7 @@ static void ieee80211_rx_cooked_monitor(
 	struct net_device *prev_dev = NULL;
 	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
 
-	if (rx->flags & IEEE80211_RX_CMNTR_REPORTED)
+	if (status->flag & RX_FLAG_INTERNAL_CMTR)
 		goto out_free_skb;
 
 	if (skb_headroom(skb) < sizeof(*rthdr) &&
@@ -1929,7 +1929,7 @@ static void ieee80211_rx_cooked_monitor(
 	} else
 		goto out_free_skb;
 
-	rx->flags |= IEEE80211_RX_CMNTR_REPORTED;
+	status->flag |= RX_FLAG_INTERNAL_CMTR;
 	return;
 
  out_free_skb:



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

* [PATCH v2 2/5] mac80211: move aMPDU RX reorder code
  2009-11-25 16:46 [PATCH v2 0/5] mac80211: stations per virtual interface, netdev reduction Johannes Berg
  2009-11-25 16:46 ` [PATCH v2 1/5] mac80211: move cmntr flag out of rx flags Johannes Berg
@ 2009-11-25 16:46 ` Johannes Berg
  2009-11-25 16:46 ` [PATCH v2 3/5] mac80211: correctly place " Johannes Berg
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 12+ messages in thread
From: Johannes Berg @ 2009-11-25 16:46 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless

This code should be part of RX handlers, so move it
to the place where it belongs without changing it.
A follow-up patch will do the changes to hook it up.
The sole purpose of this code move is to make the
other patch readable, it doesn't change the code at
all except that it now requires a different static
function declaration (which will go away too).

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
 net/mac80211/rx.c |  459 ++++++++++++++++++++++++++----------------------------
 1 file changed, 229 insertions(+), 230 deletions(-)

--- wireless-testing.orig/net/mac80211/rx.c	2009-11-19 01:14:17.000000000 +0100
+++ wireless-testing/net/mac80211/rx.c	2009-11-19 01:14:21.000000000 +0100
@@ -27,9 +27,9 @@
 #include "tkip.h"
 #include "wme.h"
 
-static void ieee80211_release_reorder_frames(struct ieee80211_hw *hw,
-					     struct tid_ampdu_rx *tid_agg_rx,
-					     u16 head_seq_num);
+static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
+					 struct sk_buff *skb,
+					 struct ieee80211_rate *rate);
 
 /*
  * monitor mode reception
@@ -534,6 +534,232 @@ ieee80211_rx_mesh_check(struct ieee80211
 	return RX_CONTINUE;
 }
 
+#define SEQ_MODULO 0x1000
+#define SEQ_MASK   0xfff
+
+static inline int seq_less(u16 sq1, u16 sq2)
+{
+	return ((sq1 - sq2) & SEQ_MASK) > (SEQ_MODULO >> 1);
+}
+
+static inline u16 seq_inc(u16 sq)
+{
+	return (sq + 1) & SEQ_MASK;
+}
+
+static inline u16 seq_sub(u16 sq1, u16 sq2)
+{
+	return (sq1 - sq2) & SEQ_MASK;
+}
+
+
+static void ieee80211_release_reorder_frame(struct ieee80211_hw *hw,
+					    struct tid_ampdu_rx *tid_agg_rx,
+					    int index)
+{
+	struct ieee80211_supported_band *sband;
+	struct ieee80211_rate *rate = NULL;
+	struct sk_buff *skb = tid_agg_rx->reorder_buf[index];
+	struct ieee80211_rx_status *status;
+
+	if (!skb)
+		goto no_frame;
+
+	status = IEEE80211_SKB_RXCB(skb);
+
+	/* release the reordered frames to stack */
+	sband = hw->wiphy->bands[status->band];
+	if (!(status->flag & RX_FLAG_HT))
+		rate = &sband->bitrates[status->rate_idx];
+	__ieee80211_rx_handle_packet(hw, skb, rate);
+	tid_agg_rx->stored_mpdu_num--;
+	tid_agg_rx->reorder_buf[index] = NULL;
+
+no_frame:
+	tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num);
+}
+
+static void ieee80211_release_reorder_frames(struct ieee80211_hw *hw,
+					     struct tid_ampdu_rx *tid_agg_rx,
+					     u16 head_seq_num)
+{
+	int index;
+
+	while (seq_less(tid_agg_rx->head_seq_num, head_seq_num)) {
+		index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
+							tid_agg_rx->buf_size;
+		ieee80211_release_reorder_frame(hw, tid_agg_rx, index);
+	}
+}
+
+/*
+ * Timeout (in jiffies) for skb's that are waiting in the RX reorder buffer. If
+ * the skb was added to the buffer longer than this time ago, the earlier
+ * frames that have not yet been received are assumed to be lost and the skb
+ * can be released for processing. This may also release other skb's from the
+ * reorder buffer if there are no additional gaps between the frames.
+ */
+#define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10)
+
+/*
+ * As this function belongs to the RX path it must be under
+ * rcu_read_lock protection. It returns false if the frame
+ * can be processed immediately, true if it was consumed.
+ */
+static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
+					     struct tid_ampdu_rx *tid_agg_rx,
+					     struct sk_buff *skb)
+{
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+	u16 sc = le16_to_cpu(hdr->seq_ctrl);
+	u16 mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4;
+	u16 head_seq_num, buf_size;
+	int index;
+
+	buf_size = tid_agg_rx->buf_size;
+	head_seq_num = tid_agg_rx->head_seq_num;
+
+	/* frame with out of date sequence number */
+	if (seq_less(mpdu_seq_num, head_seq_num)) {
+		dev_kfree_skb(skb);
+		return true;
+	}
+
+	/*
+	 * If frame the sequence number exceeds our buffering window
+	 * size release some previous frames to make room for this one.
+	 */
+	if (!seq_less(mpdu_seq_num, head_seq_num + buf_size)) {
+		head_seq_num = seq_inc(seq_sub(mpdu_seq_num, buf_size));
+		/* release stored frames up to new head to stack */
+		ieee80211_release_reorder_frames(hw, tid_agg_rx, head_seq_num);
+	}
+
+	/* Now the new frame is always in the range of the reordering buffer */
+
+	index = seq_sub(mpdu_seq_num, tid_agg_rx->ssn) % tid_agg_rx->buf_size;
+
+	/* check if we already stored this frame */
+	if (tid_agg_rx->reorder_buf[index]) {
+		dev_kfree_skb(skb);
+		return true;
+	}
+
+	/*
+	 * If the current MPDU is in the right order and nothing else
+	 * is stored we can process it directly, no need to buffer it.
+	 */
+	if (mpdu_seq_num == tid_agg_rx->head_seq_num &&
+	    tid_agg_rx->stored_mpdu_num == 0) {
+		tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num);
+		return false;
+	}
+
+	/* put the frame in the reordering buffer */
+	tid_agg_rx->reorder_buf[index] = skb;
+	tid_agg_rx->reorder_time[index] = jiffies;
+	tid_agg_rx->stored_mpdu_num++;
+	/* release the buffer until next missing frame */
+	index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
+						tid_agg_rx->buf_size;
+	if (!tid_agg_rx->reorder_buf[index] &&
+	    tid_agg_rx->stored_mpdu_num > 1) {
+		/*
+		 * No buffers ready to be released, but check whether any
+		 * frames in the reorder buffer have timed out.
+		 */
+		int j;
+		int skipped = 1;
+		for (j = (index + 1) % tid_agg_rx->buf_size; j != index;
+		     j = (j + 1) % tid_agg_rx->buf_size) {
+			if (!tid_agg_rx->reorder_buf[j]) {
+				skipped++;
+				continue;
+			}
+			if (!time_after(jiffies, tid_agg_rx->reorder_time[j] +
+					HT_RX_REORDER_BUF_TIMEOUT))
+				break;
+
+#ifdef CONFIG_MAC80211_HT_DEBUG
+			if (net_ratelimit())
+				printk(KERN_DEBUG "%s: release an RX reorder "
+				       "frame due to timeout on earlier "
+				       "frames\n",
+				       wiphy_name(hw->wiphy));
+#endif
+			ieee80211_release_reorder_frame(hw, tid_agg_rx, j);
+
+			/*
+			 * Increment the head seq# also for the skipped slots.
+			 */
+			tid_agg_rx->head_seq_num =
+				(tid_agg_rx->head_seq_num + skipped) & SEQ_MASK;
+			skipped = 0;
+		}
+	} else while (tid_agg_rx->reorder_buf[index]) {
+		ieee80211_release_reorder_frame(hw, tid_agg_rx, index);
+		index =	seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
+							tid_agg_rx->buf_size;
+	}
+
+	return true;
+}
+
+/*
+ * Reorder MPDUs from A-MPDUs, keeping them on a buffer. Returns
+ * true if the MPDU was buffered, false if it should be processed.
+ */
+static bool ieee80211_rx_reorder_ampdu(struct ieee80211_local *local,
+				       struct sk_buff *skb)
+{
+	struct ieee80211_hw *hw = &local->hw;
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+	struct sta_info *sta;
+	struct tid_ampdu_rx *tid_agg_rx;
+	u16 sc;
+	int tid;
+
+	if (!ieee80211_is_data_qos(hdr->frame_control))
+		return false;
+
+	/*
+	 * filter the QoS data rx stream according to
+	 * STA/TID and check if this STA/TID is on aggregation
+	 */
+
+	sta = sta_info_get(local, hdr->addr2);
+	if (!sta)
+		return false;
+
+	tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
+
+	if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL)
+		return false;
+
+	tid_agg_rx = sta->ampdu_mlme.tid_rx[tid];
+
+	/* qos null data frames are excluded */
+	if (unlikely(hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_NULLFUNC)))
+		return false;
+
+	/* new, potentially un-ordered, ampdu frame - process it */
+
+	/* reset session timer */
+	if (tid_agg_rx->timeout)
+		mod_timer(&tid_agg_rx->session_timer,
+			  TU_TO_EXP_TIME(tid_agg_rx->timeout));
+
+	/* if this mpdu is fragmented - terminate rx aggregation session */
+	sc = le16_to_cpu(hdr->seq_ctrl);
+	if (sc & IEEE80211_SCTL_FRAG) {
+		ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->sta.addr,
+			tid, 0, WLAN_REASON_QSTA_REQUIRE_SETUP);
+		dev_kfree_skb(skb);
+		return true;
+	}
+
+	return ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb);
+}
 
 static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
@@ -2187,233 +2413,6 @@ static void __ieee80211_rx_handle_packet
 		dev_kfree_skb(skb);
 }
 
-#define SEQ_MODULO 0x1000
-#define SEQ_MASK   0xfff
-
-static inline int seq_less(u16 sq1, u16 sq2)
-{
-	return ((sq1 - sq2) & SEQ_MASK) > (SEQ_MODULO >> 1);
-}
-
-static inline u16 seq_inc(u16 sq)
-{
-	return (sq + 1) & SEQ_MASK;
-}
-
-static inline u16 seq_sub(u16 sq1, u16 sq2)
-{
-	return (sq1 - sq2) & SEQ_MASK;
-}
-
-
-static void ieee80211_release_reorder_frame(struct ieee80211_hw *hw,
-					    struct tid_ampdu_rx *tid_agg_rx,
-					    int index)
-{
-	struct ieee80211_supported_band *sband;
-	struct ieee80211_rate *rate = NULL;
-	struct sk_buff *skb = tid_agg_rx->reorder_buf[index];
-	struct ieee80211_rx_status *status;
-
-	if (!skb)
-		goto no_frame;
-
-	status = IEEE80211_SKB_RXCB(skb);
-
-	/* release the reordered frames to stack */
-	sband = hw->wiphy->bands[status->band];
-	if (!(status->flag & RX_FLAG_HT))
-		rate = &sband->bitrates[status->rate_idx];
-	__ieee80211_rx_handle_packet(hw, skb, rate);
-	tid_agg_rx->stored_mpdu_num--;
-	tid_agg_rx->reorder_buf[index] = NULL;
-
-no_frame:
-	tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num);
-}
-
-static void ieee80211_release_reorder_frames(struct ieee80211_hw *hw,
-					     struct tid_ampdu_rx *tid_agg_rx,
-					     u16 head_seq_num)
-{
-	int index;
-
-	while (seq_less(tid_agg_rx->head_seq_num, head_seq_num)) {
-		index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
-							tid_agg_rx->buf_size;
-		ieee80211_release_reorder_frame(hw, tid_agg_rx, index);
-	}
-}
-
-/*
- * Timeout (in jiffies) for skb's that are waiting in the RX reorder buffer. If
- * the skb was added to the buffer longer than this time ago, the earlier
- * frames that have not yet been received are assumed to be lost and the skb
- * can be released for processing. This may also release other skb's from the
- * reorder buffer if there are no additional gaps between the frames.
- */
-#define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10)
-
-/*
- * As this function belongs to the RX path it must be under
- * rcu_read_lock protection. It returns false if the frame
- * can be processed immediately, true if it was consumed.
- */
-static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
-					     struct tid_ampdu_rx *tid_agg_rx,
-					     struct sk_buff *skb)
-{
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-	u16 sc = le16_to_cpu(hdr->seq_ctrl);
-	u16 mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4;
-	u16 head_seq_num, buf_size;
-	int index;
-
-	buf_size = tid_agg_rx->buf_size;
-	head_seq_num = tid_agg_rx->head_seq_num;
-
-	/* frame with out of date sequence number */
-	if (seq_less(mpdu_seq_num, head_seq_num)) {
-		dev_kfree_skb(skb);
-		return true;
-	}
-
-	/*
-	 * If frame the sequence number exceeds our buffering window
-	 * size release some previous frames to make room for this one.
-	 */
-	if (!seq_less(mpdu_seq_num, head_seq_num + buf_size)) {
-		head_seq_num = seq_inc(seq_sub(mpdu_seq_num, buf_size));
-		/* release stored frames up to new head to stack */
-		ieee80211_release_reorder_frames(hw, tid_agg_rx, head_seq_num);
-	}
-
-	/* Now the new frame is always in the range of the reordering buffer */
-
-	index = seq_sub(mpdu_seq_num, tid_agg_rx->ssn) % tid_agg_rx->buf_size;
-
-	/* check if we already stored this frame */
-	if (tid_agg_rx->reorder_buf[index]) {
-		dev_kfree_skb(skb);
-		return true;
-	}
-
-	/*
-	 * If the current MPDU is in the right order and nothing else
-	 * is stored we can process it directly, no need to buffer it.
-	 */
-	if (mpdu_seq_num == tid_agg_rx->head_seq_num &&
-	    tid_agg_rx->stored_mpdu_num == 0) {
-		tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num);
-		return false;
-	}
-
-	/* put the frame in the reordering buffer */
-	tid_agg_rx->reorder_buf[index] = skb;
-	tid_agg_rx->reorder_time[index] = jiffies;
-	tid_agg_rx->stored_mpdu_num++;
-	/* release the buffer until next missing frame */
-	index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
-						tid_agg_rx->buf_size;
-	if (!tid_agg_rx->reorder_buf[index] &&
-	    tid_agg_rx->stored_mpdu_num > 1) {
-		/*
-		 * No buffers ready to be released, but check whether any
-		 * frames in the reorder buffer have timed out.
-		 */
-		int j;
-		int skipped = 1;
-		for (j = (index + 1) % tid_agg_rx->buf_size; j != index;
-		     j = (j + 1) % tid_agg_rx->buf_size) {
-			if (!tid_agg_rx->reorder_buf[j]) {
-				skipped++;
-				continue;
-			}
-			if (!time_after(jiffies, tid_agg_rx->reorder_time[j] +
-					HT_RX_REORDER_BUF_TIMEOUT))
-				break;
-
-#ifdef CONFIG_MAC80211_HT_DEBUG
-			if (net_ratelimit())
-				printk(KERN_DEBUG "%s: release an RX reorder "
-				       "frame due to timeout on earlier "
-				       "frames\n",
-				       wiphy_name(hw->wiphy));
-#endif
-			ieee80211_release_reorder_frame(hw, tid_agg_rx, j);
-
-			/*
-			 * Increment the head seq# also for the skipped slots.
-			 */
-			tid_agg_rx->head_seq_num =
-				(tid_agg_rx->head_seq_num + skipped) & SEQ_MASK;
-			skipped = 0;
-		}
-	} else while (tid_agg_rx->reorder_buf[index]) {
-		ieee80211_release_reorder_frame(hw, tid_agg_rx, index);
-		index =	seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
-							tid_agg_rx->buf_size;
-	}
-
-	return true;
-}
-
-/*
- * Reorder MPDUs from A-MPDUs, keeping them on a buffer. Returns
- * true if the MPDU was buffered, false if it should be processed.
- */
-static bool ieee80211_rx_reorder_ampdu(struct ieee80211_local *local,
-				       struct sk_buff *skb)
-{
-	struct ieee80211_hw *hw = &local->hw;
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-	struct sta_info *sta;
-	struct tid_ampdu_rx *tid_agg_rx;
-	u16 sc;
-	int tid;
-
-	if (!ieee80211_is_data_qos(hdr->frame_control))
-		return false;
-
-	/*
-	 * filter the QoS data rx stream according to
-	 * STA/TID and check if this STA/TID is on aggregation
-	 */
-
-	sta = sta_info_get(local, hdr->addr2);
-	if (!sta)
-		return false;
-
-	tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
-
-	if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL)
-		return false;
-
-	tid_agg_rx = sta->ampdu_mlme.tid_rx[tid];
-
-	/* qos null data frames are excluded */
-	if (unlikely(hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_NULLFUNC)))
-		return false;
-
-	/* new, potentially un-ordered, ampdu frame - process it */
-
-	/* reset session timer */
-	if (tid_agg_rx->timeout)
-		mod_timer(&tid_agg_rx->session_timer,
-			  TU_TO_EXP_TIME(tid_agg_rx->timeout));
-
-	/* if this mpdu is fragmented - terminate rx aggregation session */
-	sc = le16_to_cpu(hdr->seq_ctrl);
-	if (sc & IEEE80211_SCTL_FRAG) {
-		ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->sta.addr,
-			tid, 0, WLAN_REASON_QSTA_REQUIRE_SETUP);
-		dev_kfree_skb(skb);
-		return true;
-	}
-
-	return ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb);
-}
-
 /*
  * This is the receive path handler. It is called by a low level driver when an
  * 802.11 MPDU is received from the hardware.



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

* [PATCH v2 3/5] mac80211: correctly place aMPDU RX reorder code
  2009-11-25 16:46 [PATCH v2 0/5] mac80211: stations per virtual interface, netdev reduction Johannes Berg
  2009-11-25 16:46 ` [PATCH v2 1/5] mac80211: move cmntr flag out of rx flags Johannes Berg
  2009-11-25 16:46 ` [PATCH v2 2/5] mac80211: move aMPDU RX reorder code Johannes Berg
@ 2009-11-25 16:46 ` Johannes Berg
  2009-12-03 18:13   ` reinette chatre
  2009-11-25 16:46 ` [PATCH v2 4/5] mac80211: make station management completely depend on vif Johannes Berg
  2009-11-25 16:46 ` [PATCH v2 5/5] mac80211: reduce reliance on netdev Johannes Berg
  4 siblings, 1 reply; 12+ messages in thread
From: Johannes Berg @ 2009-11-25 16:46 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless

As indicated by the comment, the aMPDU RX reorder code
should logically be after ieee80211_rx_h_check(). The
previous patch moved the code there, and this patch now
hooks it up in that place by introducing a list of skbs
that are then processed by the remaining handlers. The
list may be empty if the function is buffering the skb
to release it later.

The only change needed to the RX data is that the crypto
handler needs to clear the key that may be set from a
previous loop iteration, and that not everything can be
in the rx flags now.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
v2: ieee80211_rx_reorder_ampdu must not ignore the return
    value of ieee80211_sta_manage_reorder_buf()

 net/mac80211/ieee80211_i.h |    1 
 net/mac80211/rx.c          |  168 +++++++++++++++++++++++++--------------------
 2 files changed, 96 insertions(+), 73 deletions(-)

--- wireless-testing.orig/net/mac80211/rx.c	2009-11-25 16:23:44.000000000 +0100
+++ wireless-testing/net/mac80211/rx.c	2009-11-25 17:43:56.000000000 +0100
@@ -27,10 +27,6 @@
 #include "tkip.h"
 #include "wme.h"
 
-static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
-					 struct sk_buff *skb,
-					 struct ieee80211_rate *rate);
-
 /*
  * monitor mode reception
  *
@@ -555,7 +551,8 @@ static inline u16 seq_sub(u16 sq1, u16 s
 
 static void ieee80211_release_reorder_frame(struct ieee80211_hw *hw,
 					    struct tid_ampdu_rx *tid_agg_rx,
-					    int index)
+					    int index,
+					    struct sk_buff_head *frames)
 {
 	struct ieee80211_supported_band *sband;
 	struct ieee80211_rate *rate = NULL;
@@ -571,9 +568,9 @@ static void ieee80211_release_reorder_fr
 	sband = hw->wiphy->bands[status->band];
 	if (!(status->flag & RX_FLAG_HT))
 		rate = &sband->bitrates[status->rate_idx];
-	__ieee80211_rx_handle_packet(hw, skb, rate);
 	tid_agg_rx->stored_mpdu_num--;
 	tid_agg_rx->reorder_buf[index] = NULL;
+	skb_queue_tail(frames, skb);
 
 no_frame:
 	tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num);
@@ -581,14 +578,15 @@ no_frame:
 
 static void ieee80211_release_reorder_frames(struct ieee80211_hw *hw,
 					     struct tid_ampdu_rx *tid_agg_rx,
-					     u16 head_seq_num)
+					     u16 head_seq_num,
+					     struct sk_buff_head *frames)
 {
 	int index;
 
 	while (seq_less(tid_agg_rx->head_seq_num, head_seq_num)) {
 		index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
 							tid_agg_rx->buf_size;
-		ieee80211_release_reorder_frame(hw, tid_agg_rx, index);
+		ieee80211_release_reorder_frame(hw, tid_agg_rx, index, frames);
 	}
 }
 
@@ -608,7 +606,8 @@ static void ieee80211_release_reorder_fr
  */
 static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
 					     struct tid_ampdu_rx *tid_agg_rx,
-					     struct sk_buff *skb)
+					     struct sk_buff *skb,
+					     struct sk_buff_head *frames)
 {
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
 	u16 sc = le16_to_cpu(hdr->seq_ctrl);
@@ -632,7 +631,8 @@ static bool ieee80211_sta_manage_reorder
 	if (!seq_less(mpdu_seq_num, head_seq_num + buf_size)) {
 		head_seq_num = seq_inc(seq_sub(mpdu_seq_num, buf_size));
 		/* release stored frames up to new head to stack */
-		ieee80211_release_reorder_frames(hw, tid_agg_rx, head_seq_num);
+		ieee80211_release_reorder_frames(hw, tid_agg_rx, head_seq_num,
+						 frames);
 	}
 
 	/* Now the new frame is always in the range of the reordering buffer */
@@ -687,7 +687,8 @@ static bool ieee80211_sta_manage_reorder
 				       "frames\n",
 				       wiphy_name(hw->wiphy));
 #endif
-			ieee80211_release_reorder_frame(hw, tid_agg_rx, j);
+			ieee80211_release_reorder_frame(hw, tid_agg_rx,
+							j, frames);
 
 			/*
 			 * Increment the head seq# also for the skipped slots.
@@ -697,7 +698,7 @@ static bool ieee80211_sta_manage_reorder
 			skipped = 0;
 		}
 	} else while (tid_agg_rx->reorder_buf[index]) {
-		ieee80211_release_reorder_frame(hw, tid_agg_rx, index);
+		ieee80211_release_reorder_frame(hw, tid_agg_rx, index, frames);
 		index =	seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
 							tid_agg_rx->buf_size;
 	}
@@ -709,38 +710,39 @@ static bool ieee80211_sta_manage_reorder
  * Reorder MPDUs from A-MPDUs, keeping them on a buffer. Returns
  * true if the MPDU was buffered, false if it should be processed.
  */
-static bool ieee80211_rx_reorder_ampdu(struct ieee80211_local *local,
-				       struct sk_buff *skb)
+static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx,
+				       struct sk_buff_head *frames)
 {
+	struct sk_buff *skb = rx->skb;
+	struct ieee80211_local *local = rx->local;
 	struct ieee80211_hw *hw = &local->hw;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-	struct sta_info *sta;
+	struct sta_info *sta = rx->sta;
 	struct tid_ampdu_rx *tid_agg_rx;
 	u16 sc;
 	int tid;
 
 	if (!ieee80211_is_data_qos(hdr->frame_control))
-		return false;
+		goto dont_reorder;
 
 	/*
 	 * filter the QoS data rx stream according to
 	 * STA/TID and check if this STA/TID is on aggregation
 	 */
 
-	sta = sta_info_get(local, hdr->addr2);
 	if (!sta)
-		return false;
+		goto dont_reorder;
 
 	tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
 
 	if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL)
-		return false;
+		goto dont_reorder;
 
 	tid_agg_rx = sta->ampdu_mlme.tid_rx[tid];
 
 	/* qos null data frames are excluded */
 	if (unlikely(hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_NULLFUNC)))
-		return false;
+		goto dont_reorder;
 
 	/* new, potentially un-ordered, ampdu frame - process it */
 
@@ -755,10 +757,14 @@ static bool ieee80211_rx_reorder_ampdu(s
 		ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->sta.addr,
 			tid, 0, WLAN_REASON_QSTA_REQUIRE_SETUP);
 		dev_kfree_skb(skb);
-		return true;
+		return;
 	}
 
-	return ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb);
+	if (ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb, frames))
+		return;
+
+ dont_reorder:
+	__skb_queue_tail(frames, skb);
 }
 
 static ieee80211_rx_result debug_noinline
@@ -863,6 +869,9 @@ ieee80211_rx_h_decrypt(struct ieee80211_
 	if (!(rx->flags & IEEE80211_RX_RA_MATCH))
 		return RX_CONTINUE;
 
+	/* start without a key */
+	rx->key = NULL;
+
 	if (rx->sta)
 		stakey = rcu_dereference(rx->sta->key);
 
@@ -1815,7 +1824,7 @@ ieee80211_rx_h_data(struct ieee80211_rx_
 }
 
 static ieee80211_rx_result debug_noinline
-ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx)
+ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames)
 {
 	struct ieee80211_local *local = rx->local;
 	struct ieee80211_hw *hw = &local->hw;
@@ -1845,7 +1854,8 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_
 				  TU_TO_EXP_TIME(tid_agg_rx->timeout));
 
 		/* release stored frames up to start of BAR */
-		ieee80211_release_reorder_frames(hw, tid_agg_rx, start_seq_num);
+		ieee80211_release_reorder_frames(hw, tid_agg_rx, start_seq_num,
+						 frames);
 		kfree_skb(skb);
 		return RX_QUEUED;
 	}
@@ -2168,8 +2178,11 @@ static void ieee80211_invoke_rx_handlers
 					 struct sk_buff *skb,
 					 struct ieee80211_rate *rate)
 {
+	struct sk_buff_head reorder_release;
 	ieee80211_rx_result res = RX_DROP_MONITOR;
 
+	__skb_queue_head_init(&reorder_release);
+
 	rx->skb = skb;
 	rx->sdata = sdata;
 
@@ -2177,50 +2190,72 @@ static void ieee80211_invoke_rx_handlers
 	do {				\
 		res = rxh(rx);		\
 		if (res != RX_CONTINUE)	\
-			goto rxh_done;  \
+			goto rxh_next;  \
 	} while (0);
 
+	/*
+	 * NB: the rxh_next label works even if we jump
+	 *     to it from here because then the list will
+	 *     be empty, which is a trivial check
+	 */
 	CALL_RXH(ieee80211_rx_h_passive_scan)
 	CALL_RXH(ieee80211_rx_h_check)
-	CALL_RXH(ieee80211_rx_h_decrypt)
-	CALL_RXH(ieee80211_rx_h_check_more_data)
-	CALL_RXH(ieee80211_rx_h_sta_process)
-	CALL_RXH(ieee80211_rx_h_defragment)
-	CALL_RXH(ieee80211_rx_h_ps_poll)
-	CALL_RXH(ieee80211_rx_h_michael_mic_verify)
-	/* must be after MMIC verify so header is counted in MPDU mic */
-	CALL_RXH(ieee80211_rx_h_remove_qos_control)
-	CALL_RXH(ieee80211_rx_h_amsdu)
+
+	ieee80211_rx_reorder_ampdu(rx, &reorder_release);
+
+	while ((skb = __skb_dequeue(&reorder_release))) {
+		/*
+		 * all the other fields are valid across frames
+		 * that belong to an aMPDU since they are on the
+		 * same TID from the same station
+		 */
+		rx->skb = skb;
+
+		CALL_RXH(ieee80211_rx_h_decrypt)
+		CALL_RXH(ieee80211_rx_h_check_more_data)
+		CALL_RXH(ieee80211_rx_h_sta_process)
+		CALL_RXH(ieee80211_rx_h_defragment)
+		CALL_RXH(ieee80211_rx_h_ps_poll)
+		CALL_RXH(ieee80211_rx_h_michael_mic_verify)
+		/* must be after MMIC verify so header is counted in MPDU mic */
+		CALL_RXH(ieee80211_rx_h_remove_qos_control)
+		CALL_RXH(ieee80211_rx_h_amsdu)
 #ifdef CONFIG_MAC80211_MESH
-	if (ieee80211_vif_is_mesh(&sdata->vif))
-		CALL_RXH(ieee80211_rx_h_mesh_fwding);
+		if (ieee80211_vif_is_mesh(&sdata->vif))
+			CALL_RXH(ieee80211_rx_h_mesh_fwding);
 #endif
-	CALL_RXH(ieee80211_rx_h_data)
-	CALL_RXH(ieee80211_rx_h_ctrl)
-	CALL_RXH(ieee80211_rx_h_action)
-	CALL_RXH(ieee80211_rx_h_mgmt)
+		CALL_RXH(ieee80211_rx_h_data)
+
+		/* special treatment -- needs the queue */
+		res = ieee80211_rx_h_ctrl(rx, &reorder_release);
+		if (res != RX_CONTINUE)
+			goto rxh_next;
+
+		CALL_RXH(ieee80211_rx_h_action)
+		CALL_RXH(ieee80211_rx_h_mgmt)
 
 #undef CALL_RXH
 
- rxh_done:
-	switch (res) {
-	case RX_DROP_MONITOR:
-		I802_DEBUG_INC(sdata->local->rx_handlers_drop);
-		if (rx->sta)
-			rx->sta->rx_dropped++;
-		/* fall through */
-	case RX_CONTINUE:
-		ieee80211_rx_cooked_monitor(rx, rate);
-		break;
-	case RX_DROP_UNUSABLE:
-		I802_DEBUG_INC(sdata->local->rx_handlers_drop);
-		if (rx->sta)
-			rx->sta->rx_dropped++;
-		dev_kfree_skb(rx->skb);
-		break;
-	case RX_QUEUED:
-		I802_DEBUG_INC(sdata->local->rx_handlers_queued);
-		break;
+ rxh_next:
+		switch (res) {
+		case RX_DROP_MONITOR:
+			I802_DEBUG_INC(sdata->local->rx_handlers_drop);
+			if (rx->sta)
+				rx->sta->rx_dropped++;
+			/* fall through */
+		case RX_CONTINUE:
+			ieee80211_rx_cooked_monitor(rx, rate);
+			break;
+		case RX_DROP_UNUSABLE:
+			I802_DEBUG_INC(sdata->local->rx_handlers_drop);
+			if (rx->sta)
+				rx->sta->rx_dropped++;
+			dev_kfree_skb(rx->skb);
+			break;
+		case RX_QUEUED:
+			I802_DEBUG_INC(sdata->local->rx_handlers_queued);
+			break;
+		}
 	}
 }
 
@@ -2494,20 +2529,7 @@ void ieee80211_rx(struct ieee80211_hw *h
 		return;
 	}
 
-	/*
-	 * In theory, the block ack reordering should happen after duplicate
-	 * removal (ieee80211_rx_h_check(), which is an RX handler). As such,
-	 * the call to ieee80211_rx_reorder_ampdu() should really be moved to
-	 * happen as a new RX handler between ieee80211_rx_h_check and
-	 * ieee80211_rx_h_decrypt. This cleanup may eventually happen, but for
-	 * the time being, the call can be here since RX reorder buf processing
-	 * will implicitly skip duplicates. We could, in theory at least,
-	 * process frames that ieee80211_rx_h_passive_scan would drop (e.g.,
-	 * frames from other than operational channel), but that should not
-	 * happen in normal networks.
-	 */
-	if (!ieee80211_rx_reorder_ampdu(local, skb))
-		__ieee80211_rx_handle_packet(hw, skb, rate);
+	__ieee80211_rx_handle_packet(hw, skb, rate);
 
 	rcu_read_unlock();
 
--- wireless-testing.orig/net/mac80211/ieee80211_i.h	2009-11-25 16:23:43.000000000 +0100
+++ wireless-testing/net/mac80211/ieee80211_i.h	2009-11-25 16:24:18.000000000 +0100
@@ -164,6 +164,7 @@ typedef unsigned __bitwise__ ieee80211_r
 #define IEEE80211_RX_RA_MATCH		BIT(1)
 #define IEEE80211_RX_AMSDU		BIT(2)
 #define IEEE80211_RX_FRAGMENTED		BIT(3)
+/* only add flags here that do not change with subframes of an aMPDU */
 
 struct ieee80211_rx_data {
 	struct sk_buff *skb;



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

* [PATCH v2 4/5] mac80211: make station management completely depend on vif
  2009-11-25 16:46 [PATCH v2 0/5] mac80211: stations per virtual interface, netdev reduction Johannes Berg
                   ` (2 preceding siblings ...)
  2009-11-25 16:46 ` [PATCH v2 3/5] mac80211: correctly place " Johannes Berg
@ 2009-11-25 16:46 ` Johannes Berg
  2009-11-25 19:27   ` [PATCH v3 " Johannes Berg
  2009-11-25 16:46 ` [PATCH v2 5/5] mac80211: reduce reliance on netdev Johannes Berg
  4 siblings, 1 reply; 12+ messages in thread
From: Johannes Berg @ 2009-11-25 16:46 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless

The station management currently uses the virtual
interface, but you cannot add the same station to
multiple virtual interfaces if you're communicating
with it in multiple ways.

This restriction should be lifted so that in the
future we can, for instance, support bluetooth 3
with an access point that mac80211 is already
associated to.

We can do that by requiring all sta_info_get users
to provide the virtual interface and making the RX
code aware that an address may match more than one
station struct. Thanks to the previous patches this
one isn't all that large and except for the RX and
TX status paths changes has low complexity.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
v2: add missing sta_info_get()

 net/mac80211/agg-rx.c     |    3 -
 net/mac80211/agg-tx.c     |    4 -
 net/mac80211/cfg.c        |   25 +++------
 net/mac80211/ibss.c       |    2 
 net/mac80211/key.c        |    2 
 net/mac80211/mesh_hwmp.c  |    2 
 net/mac80211/mesh_plink.c |    4 -
 net/mac80211/mlme.c       |   10 +--
 net/mac80211/rx.c         |  119 ++++++++++++++++++++++++----------------------
 net/mac80211/sta_info.c   |   18 ++++--
 net/mac80211/sta_info.h   |   29 ++++++++++-
 net/mac80211/status.c     |    8 +--
 net/mac80211/tx.c         |    9 +--
 13 files changed, 134 insertions(+), 101 deletions(-)

--- wireless-testing.orig/net/mac80211/sta_info.h	2009-11-25 17:41:38.000000000 +0100
+++ wireless-testing/net/mac80211/sta_info.h	2009-11-25 17:45:52.000000000 +0100
@@ -403,9 +403,34 @@ static inline u32 get_sta_flags(struct s
 #define STA_INFO_CLEANUP_INTERVAL (10 * HZ)
 
 /*
- * Get a STA info, must have be under RCU read lock.
+ * Get a STA info, must be under RCU read lock.
  */
-struct sta_info *sta_info_get(struct ieee80211_local *local, const u8 *addr);
+struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,
+			      const u8 *addr);
+
+static inline
+void for_each_sta_info_type_check(struct ieee80211_local *local,
+				  const u8 *addr,
+				  struct sta_info *sta,
+				  struct sta_info *nxt)
+{
+}
+
+#define for_each_sta_info(local, _addr, sta, nxt) 			\
+	for (	/* initialise loop */					\
+		sta = rcu_dereference(local->sta_hash[STA_HASH(_addr)]),\
+		nxt = sta ? rcu_dereference(sta->hnext) : NULL;		\
+		/* typecheck */						\
+		for_each_sta_info_type_check(local, (_addr), sta, nxt),	\
+		/* continue condition */				\
+		sta;							\
+		/* advance loop */					\
+		sta = nxt,						\
+		nxt = sta ? rcu_dereference(sta->hnext) : NULL		\
+	     )								\
+	/* compare address and run code only if it matches */		\
+	if (memcmp(sta->sta.addr, (_addr), ETH_ALEN) == 0)
+
 /*
  * Get STA info by index, BROKEN!
  */
--- wireless-testing.orig/net/mac80211/sta_info.c	2009-11-25 17:41:38.000000000 +0100
+++ wireless-testing/net/mac80211/sta_info.c	2009-11-25 17:45:52.000000000 +0100
@@ -103,13 +103,16 @@ static int sta_info_hash_del(struct ieee
 }
 
 /* protected by RCU */
-struct sta_info *sta_info_get(struct ieee80211_local *local, const u8 *addr)
+struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,
+			      const u8 *addr)
 {
+	struct ieee80211_local *local = sdata->local;
 	struct sta_info *sta;
 
 	sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]);
 	while (sta) {
-		if (memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)
+		if (sta->sdata == sdata &&
+		    memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)
 			break;
 		sta = rcu_dereference(sta->hnext);
 	}
@@ -377,7 +380,7 @@ int sta_info_insert(struct sta_info *sta
 
 	spin_lock_irqsave(&local->sta_lock, flags);
 	/* check if STA exists already */
-	if (sta_info_get(local, sta->sta.addr)) {
+	if (sta_info_get(sdata, sta->sta.addr)) {
 		spin_unlock_irqrestore(&local->sta_lock, flags);
 		err = -EEXIST;
 		goto out_free;
@@ -843,11 +846,12 @@ void ieee80211_sta_expire(struct ieee802
 struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw,
 					       const u8 *addr)
 {
-	struct sta_info *sta = sta_info_get(hw_to_local(hw), addr);
+	struct sta_info *sta, *nxt;
 
-	if (!sta)
-		return NULL;
-	return &sta->sta;
+	/* Just return a random station ... first in list ... */
+	for_each_sta_info(hw_to_local(hw), addr, sta, nxt)
+		return &sta->sta;
+	return NULL;
 }
 EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_hw);
 
--- wireless-testing.orig/net/mac80211/ibss.c	2009-11-25 17:41:38.000000000 +0100
+++ wireless-testing/net/mac80211/ibss.c	2009-11-25 17:45:52.000000000 +0100
@@ -252,7 +252,7 @@ static void ieee80211_rx_bss_info(struct
 
 		rcu_read_lock();
 
-		sta = sta_info_get(local, mgmt->sa);
+		sta = sta_info_get(sdata, mgmt->sa);
 		if (sta) {
 			u32 prev_rates;
 
--- wireless-testing.orig/net/mac80211/key.c	2009-11-25 17:41:39.000000000 +0100
+++ wireless-testing/net/mac80211/key.c	2009-11-25 17:45:52.000000000 +0100
@@ -421,7 +421,7 @@ void ieee80211_key_link(struct ieee80211
 			 */
 
 			/* same here, the AP could be using QoS */
-			ap = sta_info_get(key->local, key->sdata->u.mgd.bssid);
+			ap = sta_info_get(key->sdata, key->sdata->u.mgd.bssid);
 			if (ap) {
 				if (test_sta_flags(ap, WLAN_STA_WME))
 					key->conf.flags |=
--- wireless-testing.orig/net/mac80211/mesh_hwmp.c	2009-11-25 17:41:39.000000000 +0100
+++ wireless-testing/net/mac80211/mesh_hwmp.c	2009-11-25 17:45:52.000000000 +0100
@@ -335,7 +335,7 @@ static u32 hwmp_route_info_get(struct ie
 	bool process = true;
 
 	rcu_read_lock();
-	sta = sta_info_get(local, mgmt->sa);
+	sta = sta_info_get(sdata, mgmt->sa);
 	if (!sta) {
 		rcu_read_unlock();
 		return 0;
--- wireless-testing.orig/net/mac80211/mesh_plink.c	2009-11-25 17:41:38.000000000 +0100
+++ wireless-testing/net/mac80211/mesh_plink.c	2009-11-25 17:45:52.000000000 +0100
@@ -234,7 +234,7 @@ void mesh_neighbour_update(u8 *hw_addr, 
 
 	rcu_read_lock();
 
-	sta = sta_info_get(local, hw_addr);
+	sta = sta_info_get(sdata, hw_addr);
 	if (!sta) {
 		sta = mesh_plink_alloc(sdata, hw_addr, rates);
 		if (!sta) {
@@ -455,7 +455,7 @@ void mesh_rx_plink_frame(struct ieee8021
 
 	rcu_read_lock();
 
-	sta = sta_info_get(local, mgmt->sa);
+	sta = sta_info_get(sdata, mgmt->sa);
 	if (!sta && ftype != PLINK_OPEN) {
 		mpl_dbg("Mesh plink: cls or cnf from unknown peer\n");
 		rcu_read_unlock();
--- wireless-testing.orig/net/mac80211/mlme.c	2009-11-25 17:41:38.000000000 +0100
+++ wireless-testing/net/mac80211/mlme.c	2009-11-25 17:45:52.000000000 +0100
@@ -202,7 +202,7 @@ static u32 ieee80211_enable_ht(struct ie
 		ieee80211_hw_config(local, 0);
 
 		rcu_read_lock();
-		sta = sta_info_get(local, bssid);
+		sta = sta_info_get(sdata, bssid);
 		if (sta)
 			rate_control_rate_update(local, sband, sta,
 						 IEEE80211_RC_HT_CHANGED);
@@ -1120,7 +1120,7 @@ static void ieee80211_set_disassoc(struc
 	netif_carrier_off(sdata->dev);
 
 	rcu_read_lock();
-	sta = sta_info_get(local, bssid);
+	sta = sta_info_get(sdata, bssid);
 	if (sta)
 		ieee80211_sta_tear_down_BA_sessions(sta);
 	rcu_read_unlock();
@@ -1159,7 +1159,7 @@ static void ieee80211_set_disassoc(struc
 
 	rcu_read_lock();
 
-	sta = sta_info_get(local, bssid);
+	sta = sta_info_get(sdata, bssid);
 	if (!sta) {
 		rcu_read_unlock();
 		return;
@@ -1539,7 +1539,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee
 	rcu_read_lock();
 
 	/* Add STA entry for the AP */
-	sta = sta_info_get(local, wk->bss->cbss.bssid);
+	sta = sta_info_get(sdata, wk->bss->cbss.bssid);
 	if (!sta) {
 		newsta = true;
 
@@ -1907,7 +1907,7 @@ static void ieee80211_rx_mgmt_beacon(str
 
 		rcu_read_lock();
 
-		sta = sta_info_get(local, bssid);
+		sta = sta_info_get(sdata, bssid);
 		if (WARN_ON(!sta)) {
 			rcu_read_unlock();
 			return;
--- wireless-testing.orig/net/mac80211/rx.c	2009-11-25 17:43:56.000000000 +0100
+++ wireless-testing/net/mac80211/rx.c	2009-11-25 17:45:52.000000000 +0100
@@ -1472,7 +1472,6 @@ ieee80211_deliver_skb(struct ieee80211_r
 {
 	struct ieee80211_sub_if_data *sdata = rx->sdata;
 	struct net_device *dev = sdata->dev;
-	struct ieee80211_local *local = rx->local;
 	struct sk_buff *skb, *xmit_skb;
 	struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data;
 	struct sta_info *dsta;
@@ -1495,8 +1494,8 @@ ieee80211_deliver_skb(struct ieee80211_r
 				printk(KERN_DEBUG "%s: failed to clone "
 				       "multicast frame\n", dev->name);
 		} else {
-			dsta = sta_info_get(local, skb->data);
-			if (dsta && dsta->sdata->dev == dev) {
+			dsta = sta_info_get(sdata, skb->data);
+			if (dsta) {
 				/*
 				 * The destination station is associated to
 				 * this AP (in this VLAN), so send the frame
@@ -2363,6 +2362,8 @@ static void __ieee80211_rx_handle_packet
 	int prepares;
 	struct ieee80211_sub_if_data *prev = NULL;
 	struct sk_buff *skb_new;
+	struct sta_info *sta, *tmp;
+	bool found_sta = false;
 
 	hdr = (struct ieee80211_hdr *)skb->data;
 	memset(&rx, 0, sizeof(rx));
@@ -2379,68 +2380,76 @@ static void __ieee80211_rx_handle_packet
 	ieee80211_parse_qos(&rx);
 	ieee80211_verify_alignment(&rx);
 
-	rx.sta = sta_info_get(local, hdr->addr2);
-	if (rx.sta)
-		rx.sdata = rx.sta->sdata;
-
-	if (rx.sdata && ieee80211_is_data(hdr->frame_control)) {
-		rx.flags |= IEEE80211_RX_RA_MATCH;
-		prepares = prepare_for_handlers(rx.sdata, &rx, hdr);
-		if (prepares) {
-			if (status->flag & RX_FLAG_MMIC_ERROR) {
-				if (rx.flags & IEEE80211_RX_RA_MATCH)
-					ieee80211_rx_michael_mic_report(hdr, &rx);
-			} else
-				prev = rx.sdata;
+	if (ieee80211_is_data(hdr->frame_control)) {
+		for_each_sta_info(local, hdr->addr2, sta, tmp) {
+			rx.sta = sta;
+			found_sta = true;
+			rx.sdata = sta->sdata;
+
+			rx.flags |= IEEE80211_RX_RA_MATCH;
+			prepares = prepare_for_handlers(rx.sdata, &rx, hdr);
+			if (prepares) {
+				if (status->flag & RX_FLAG_MMIC_ERROR) {
+					if (rx.flags & IEEE80211_RX_RA_MATCH)
+						ieee80211_rx_michael_mic_report(hdr, &rx);
+				} else
+					prev = rx.sdata;
+			}
 		}
-	} else list_for_each_entry_rcu(sdata, &local->interfaces, list) {
-		if (!netif_running(sdata->dev))
-			continue;
+	}
+	if (!found_sta) {
+		list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+			if (!netif_running(sdata->dev))
+				continue;
+
+			if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
+			    sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+				continue;
 
-		if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
-		    sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
-			continue;
+			rx.sta = sta_info_get(sdata, hdr->addr2);
 
-		rx.flags |= IEEE80211_RX_RA_MATCH;
-		prepares = prepare_for_handlers(sdata, &rx, hdr);
+			rx.flags |= IEEE80211_RX_RA_MATCH;
+			prepares = prepare_for_handlers(sdata, &rx, hdr);
 
-		if (!prepares)
-			continue;
+			if (!prepares)
+				continue;
 
-		if (status->flag & RX_FLAG_MMIC_ERROR) {
-			rx.sdata = sdata;
-			if (rx.flags & IEEE80211_RX_RA_MATCH)
-				ieee80211_rx_michael_mic_report(hdr, &rx);
-			continue;
-		}
+			if (status->flag & RX_FLAG_MMIC_ERROR) {
+				rx.sdata = sdata;
+				if (rx.flags & IEEE80211_RX_RA_MATCH)
+					ieee80211_rx_michael_mic_report(hdr,
+									&rx);
+				continue;
+			}
 
-		/*
-		 * frame is destined for this interface, but if it's not
-		 * also for the previous one we handle that after the
-		 * loop to avoid copying the SKB once too much
-		 */
+			/*
+			 * frame is destined for this interface, but if it's
+			 * not also for the previous one we handle that after
+			 * the loop to avoid copying the SKB once too much
+			 */
 
-		if (!prev) {
-			prev = sdata;
-			continue;
-		}
+			if (!prev) {
+				prev = sdata;
+				continue;
+			}
 
-		/*
-		 * frame was destined for the previous interface
-		 * so invoke RX handlers for it
-		 */
+			/*
+			 * frame was destined for the previous interface
+			 * so invoke RX handlers for it
+			 */
 
-		skb_new = skb_copy(skb, GFP_ATOMIC);
-		if (!skb_new) {
-			if (net_ratelimit())
-				printk(KERN_DEBUG "%s: failed to copy "
-				       "multicast frame for %s\n",
-				       wiphy_name(local->hw.wiphy),
-				       prev->dev->name);
-			continue;
+			skb_new = skb_copy(skb, GFP_ATOMIC);
+			if (!skb_new) {
+				if (net_ratelimit())
+					printk(KERN_DEBUG "%s: failed to copy "
+					       "multicast frame for %s\n",
+					       wiphy_name(local->hw.wiphy),
+					       prev->dev->name);
+				continue;
+			}
+			ieee80211_invoke_rx_handlers(prev, &rx, skb_new, rate);
+			prev = sdata;
 		}
-		ieee80211_invoke_rx_handlers(prev, &rx, skb_new, rate);
-		prev = sdata;
 	}
 	if (prev)
 		ieee80211_invoke_rx_handlers(prev, &rx, skb, rate);
--- wireless-testing.orig/net/mac80211/agg-tx.c	2009-11-25 17:41:38.000000000 +0100
+++ wireless-testing/net/mac80211/agg-tx.c	2009-11-25 17:45:52.000000000 +0100
@@ -441,7 +441,7 @@ void ieee80211_start_tx_ba_cb(struct iee
 	}
 
 	rcu_read_lock();
-	sta = sta_info_get(local, ra);
+	sta = sta_info_get(sdata, ra);
 	if (!sta) {
 		rcu_read_unlock();
 #ifdef CONFIG_MAC80211_HT_DEBUG
@@ -564,7 +564,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee
 #endif /* CONFIG_MAC80211_HT_DEBUG */
 
 	rcu_read_lock();
-	sta = sta_info_get(local, ra);
+	sta = sta_info_get(sdata, ra);
 	if (!sta) {
 #ifdef CONFIG_MAC80211_HT_DEBUG
 		printk(KERN_DEBUG "Could not find station: %pM\n", ra);
--- wireless-testing.orig/net/mac80211/agg-rx.c	2009-11-25 17:41:38.000000000 +0100
+++ wireless-testing/net/mac80211/agg-rx.c	2009-11-25 17:45:52.000000000 +0100
@@ -83,12 +83,11 @@ void __ieee80211_stop_rx_ba_session(stru
 void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid,
 					u16 initiator, u16 reason)
 {
-	struct ieee80211_local *local = sdata->local;
 	struct sta_info *sta;
 
 	rcu_read_lock();
 
-	sta = sta_info_get(local, ra);
+	sta = sta_info_get(sdata, ra);
 	if (!sta) {
 		rcu_read_unlock();
 		return;
--- wireless-testing.orig/net/mac80211/cfg.c	2009-11-25 17:41:39.000000000 +0100
+++ wireless-testing/net/mac80211/cfg.c	2009-11-25 17:45:52.000000000 +0100
@@ -150,7 +150,7 @@ static int ieee80211_add_key(struct wiph
 	rcu_read_lock();
 
 	if (mac_addr) {
-		sta = sta_info_get(sdata->local, mac_addr);
+		sta = sta_info_get(sdata, mac_addr);
 		if (!sta) {
 			ieee80211_key_free(key);
 			err = -ENOENT;
@@ -181,7 +181,7 @@ static int ieee80211_del_key(struct wiph
 	if (mac_addr) {
 		ret = -ENOENT;
 
-		sta = sta_info_get(sdata->local, mac_addr);
+		sta = sta_info_get(sdata, mac_addr);
 		if (!sta)
 			goto out_unlock;
 
@@ -228,7 +228,7 @@ static int ieee80211_get_key(struct wiph
 	rcu_read_lock();
 
 	if (mac_addr) {
-		sta = sta_info_get(sdata->local, mac_addr);
+		sta = sta_info_get(sdata, mac_addr);
 		if (!sta)
 			goto out;
 
@@ -414,15 +414,13 @@ static int ieee80211_dump_station(struct
 static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev,
 				 u8 *mac, struct station_info *sinfo)
 {
-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	struct sta_info *sta;
 	int ret = -ENOENT;
 
 	rcu_read_lock();
 
-	/* XXX: verify sta->dev == dev */
-
-	sta = sta_info_get(local, mac);
+	sta = sta_info_get(sdata, mac);
 	if (sta) {
 		ret = 0;
 		sta_set_sinfo(sta, sinfo);
@@ -778,8 +776,7 @@ static int ieee80211_del_station(struct 
 	if (mac) {
 		rcu_read_lock();
 
-		/* XXX: get sta belonging to dev */
-		sta = sta_info_get(local, mac);
+		sta = sta_info_get(sdata, mac);
 		if (!sta) {
 			rcu_read_unlock();
 			return -ENOENT;
@@ -800,14 +797,14 @@ static int ieee80211_change_station(stru
 				    u8 *mac,
 				    struct station_parameters *params)
 {
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	struct ieee80211_local *local = wiphy_priv(wiphy);
 	struct sta_info *sta;
 	struct ieee80211_sub_if_data *vlansdata;
 
 	rcu_read_lock();
 
-	/* XXX: get sta belonging to dev */
-	sta = sta_info_get(local, mac);
+	sta = sta_info_get(sdata, mac);
 	if (!sta) {
 		rcu_read_unlock();
 		return -ENOENT;
@@ -846,7 +843,6 @@ static int ieee80211_change_station(stru
 static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev,
 				 u8 *dst, u8 *next_hop)
 {
-	struct ieee80211_local *local = wiphy_priv(wiphy);
 	struct ieee80211_sub_if_data *sdata;
 	struct mesh_path *mpath;
 	struct sta_info *sta;
@@ -855,7 +851,7 @@ static int ieee80211_add_mpath(struct wi
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
 	rcu_read_lock();
-	sta = sta_info_get(local, next_hop);
+	sta = sta_info_get(sdata, next_hop);
 	if (!sta) {
 		rcu_read_unlock();
 		return -ENOENT;
@@ -894,7 +890,6 @@ static int ieee80211_change_mpath(struct
 				    struct net_device *dev,
 				    u8 *dst, u8 *next_hop)
 {
-	struct ieee80211_local *local = wiphy_priv(wiphy);
 	struct ieee80211_sub_if_data *sdata;
 	struct mesh_path *mpath;
 	struct sta_info *sta;
@@ -903,7 +898,7 @@ static int ieee80211_change_mpath(struct
 
 	rcu_read_lock();
 
-	sta = sta_info_get(local, next_hop);
+	sta = sta_info_get(sdata, next_hop);
 	if (!sta) {
 		rcu_read_unlock();
 		return -ENOENT;
--- wireless-testing.orig/net/mac80211/tx.c	2009-11-25 17:41:38.000000000 +0100
+++ wireless-testing/net/mac80211/tx.c	2009-11-25 17:45:52.000000000 +0100
@@ -1054,7 +1054,7 @@ ieee80211_tx_prepare(struct ieee80211_su
 	if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
 		tx->sta = rcu_dereference(sdata->u.vlan.sta);
 	if (!tx->sta)
-		tx->sta = sta_info_get(local, hdr->addr1);
+		tx->sta = sta_info_get(sdata, hdr->addr1);
 
 	if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) &&
 	    (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION)) {
@@ -1760,9 +1760,8 @@ netdev_tx_t ieee80211_subif_start_xmit(s
 	 */
 	if (!is_multicast_ether_addr(hdr.addr1)) {
 		rcu_read_lock();
-		sta = sta_info_get(local, hdr.addr1);
-		/* XXX: in the future, use sdata to look up the sta */
-		if (sta && sta->sdata == sdata)
+		sta = sta_info_get(sdata, hdr.addr1);
+		if (sta)
 			sta_flags = get_sta_flags(sta);
 		rcu_read_unlock();
 	}
@@ -1921,7 +1920,7 @@ static bool ieee80211_tx_pending_skb(str
 		ieee80211_tx(sdata, skb, true);
 	} else {
 		hdr = (struct ieee80211_hdr *)skb->data;
-		sta = sta_info_get(local, hdr->addr1);
+		sta = sta_info_get(sdata, hdr->addr1);
 
 		ret = __ieee80211_tx(local, &skb, sta, true);
 		if (ret != IEEE80211_TX_OK)
--- wireless-testing.orig/net/mac80211/status.c	2009-11-25 17:41:38.000000000 +0100
+++ wireless-testing/net/mac80211/status.c	2009-11-25 17:45:52.000000000 +0100
@@ -180,7 +180,7 @@ void ieee80211_tx_status(struct ieee8021
 	struct ieee80211_tx_status_rtap_hdr *rthdr;
 	struct ieee80211_sub_if_data *sdata;
 	struct net_device *prev_dev = NULL;
-	struct sta_info *sta;
+	struct sta_info *sta, *tmp;
 	int retry_count = -1, i;
 
 	for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
@@ -199,9 +199,11 @@ void ieee80211_tx_status(struct ieee8021
 
 	sband = local->hw.wiphy->bands[info->band];
 
-	sta = sta_info_get(local, hdr->addr1);
+	for_each_sta_info(local, hdr->addr1, sta, tmp) {
+		/* skip wrong virtual interface */
+		if (memcmp(hdr->addr2, sta->sdata->dev->dev_addr, ETH_ALEN))
+			continue;
 
-	if (sta) {
 		if (!(info->flags & IEEE80211_TX_STAT_ACK) &&
 		    test_sta_flags(sta, WLAN_STA_PS_STA)) {
 			/*



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

* [PATCH v2 5/5] mac80211: reduce reliance on netdev
  2009-11-25 16:46 [PATCH v2 0/5] mac80211: stations per virtual interface, netdev reduction Johannes Berg
                   ` (3 preceding siblings ...)
  2009-11-25 16:46 ` [PATCH v2 4/5] mac80211: make station management completely depend on vif Johannes Berg
@ 2009-11-25 16:46 ` Johannes Berg
  4 siblings, 0 replies; 12+ messages in thread
From: Johannes Berg @ 2009-11-25 16:46 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless

For bluetooth 3, we will most likely not have
a netdev for a virtual interface (sdata), so
prepare for that by reducing the reliance on
having a netdev. This patch moves the name
and address fields into the sdata struct and
uses them from there all over. Some work is
needed to keep them sync'ed, but that's not
a lot of work and in slow paths anyway.

In doing so, this also reduces the number of
pointer dereferences in many places, because
of things like sdata->dev->dev_addr becoming
sdata->vif.addr.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
 include/net/mac80211.h        |    2 +
 net/mac80211/agg-rx.c         |    6 ++--
 net/mac80211/agg-tx.c         |   14 ++++-----
 net/mac80211/cfg.c            |    2 -
 net/mac80211/debugfs_key.c    |    2 -
 net/mac80211/debugfs_netdev.c |   55 +++----------------------------------
 net/mac80211/debugfs_netdev.h |    9 ++----
 net/mac80211/debugfs_sta.c    |    2 -
 net/mac80211/driver-ops.h     |    4 +-
 net/mac80211/driver-trace.h   |   12 +++-----
 net/mac80211/ht.c             |    6 ++--
 net/mac80211/ibss.c           |   32 ++++++++++-----------
 net/mac80211/ieee80211_i.h    |    5 ++-
 net/mac80211/iface.c          |   62 +++++++++++++++++++++++++++++++++++++++---
 net/mac80211/main.c           |   17 ++++++++---
 net/mac80211/mesh.c           |    4 +-
 net/mac80211/mesh_hwmp.c      |   18 ++++++------
 net/mac80211/mesh_pathtbl.c   |    6 ++--
 net/mac80211/mesh_plink.c     |    2 -
 net/mac80211/mlme.c           |   62 +++++++++++++++++++++---------------------
 net/mac80211/pm.c             |    2 -
 net/mac80211/rx.c             |   43 ++++++++++++++---------------
 net/mac80211/scan.c           |    2 -
 net/mac80211/spectmgmt.c      |    4 +-
 net/mac80211/sta_info.c       |    8 ++---
 net/mac80211/status.c         |    2 -
 net/mac80211/tx.c             |   33 ++++++++++------------
 net/mac80211/util.c           |   14 ++++-----
 28 files changed, 223 insertions(+), 207 deletions(-)

--- wireless-testing.orig/net/mac80211/agg-rx.c	2009-11-20 11:42:57.000000000 +0100
+++ wireless-testing/net/mac80211/agg-rx.c	2009-11-20 11:43:00.000000000 +0100
@@ -135,7 +135,7 @@ static void ieee80211_send_addba_resp(st
 
 	if (!skb) {
 		printk(KERN_DEBUG "%s: failed to allocate buffer "
-		       "for addba resp frame\n", sdata->dev->name);
+		       "for addba resp frame\n", sdata->name);
 		return;
 	}
 
@@ -143,10 +143,10 @@ static void ieee80211_send_addba_resp(st
 	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
 	memset(mgmt, 0, 24);
 	memcpy(mgmt->da, da, ETH_ALEN);
-	memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
+	memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
 	if (sdata->vif.type == NL80211_IFTYPE_AP ||
 	    sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
-		memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN);
+		memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
 	else if (sdata->vif.type == NL80211_IFTYPE_STATION)
 		memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
 
--- wireless-testing.orig/net/mac80211/agg-tx.c	2009-11-20 11:42:57.000000000 +0100
+++ wireless-testing/net/mac80211/agg-tx.c	2009-11-20 11:43:00.000000000 +0100
@@ -58,17 +58,17 @@ static void ieee80211_send_addba_request
 
 	if (!skb) {
 		printk(KERN_ERR "%s: failed to allocate buffer "
-				"for addba request frame\n", sdata->dev->name);
+				"for addba request frame\n", sdata->name);
 		return;
 	}
 	skb_reserve(skb, local->hw.extra_tx_headroom);
 	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
 	memset(mgmt, 0, 24);
 	memcpy(mgmt->da, da, ETH_ALEN);
-	memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
+	memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
 	if (sdata->vif.type == NL80211_IFTYPE_AP ||
 	    sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
-		memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN);
+		memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
 	else if (sdata->vif.type == NL80211_IFTYPE_STATION)
 		memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
 
@@ -104,7 +104,7 @@ void ieee80211_send_bar(struct ieee80211
 	skb = dev_alloc_skb(sizeof(*bar) + local->hw.extra_tx_headroom);
 	if (!skb) {
 		printk(KERN_ERR "%s: failed to allocate buffer for "
-			"bar frame\n", sdata->dev->name);
+			"bar frame\n", sdata->name);
 		return;
 	}
 	skb_reserve(skb, local->hw.extra_tx_headroom);
@@ -113,7 +113,7 @@ void ieee80211_send_bar(struct ieee80211
 	bar->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
 					 IEEE80211_STYPE_BACK_REQ);
 	memcpy(bar->ra, ra, ETH_ALEN);
-	memcpy(bar->ta, sdata->dev->dev_addr, ETH_ALEN);
+	memcpy(bar->ta, sdata->vif.addr, ETH_ALEN);
 	bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL;
 	bar_control |= (u16)IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA;
 	bar_control |= (u16)(tid << 12);
@@ -489,7 +489,7 @@ void ieee80211_start_tx_ba_cb_irqsafe(st
 #ifdef CONFIG_MAC80211_HT_DEBUG
 		if (net_ratelimit())
 			printk(KERN_WARNING "%s: Not enough memory, "
-			       "dropping start BA session", skb->dev->name);
+			       "dropping start BA session", sdata->name);
 #endif
 		return;
 	}
@@ -621,7 +621,7 @@ void ieee80211_stop_tx_ba_cb_irqsafe(str
 #ifdef CONFIG_MAC80211_HT_DEBUG
 		if (net_ratelimit())
 			printk(KERN_WARNING "%s: Not enough memory, "
-			       "dropping stop BA session", skb->dev->name);
+			       "dropping stop BA session", sdata->name);
 #endif
 		return;
 	}
--- wireless-testing.orig/net/mac80211/ht.c	2009-11-20 11:42:17.000000000 +0100
+++ wireless-testing/net/mac80211/ht.c	2009-11-20 11:43:00.000000000 +0100
@@ -106,7 +106,7 @@ void ieee80211_send_delba(struct ieee802
 
 	if (!skb) {
 		printk(KERN_ERR "%s: failed to allocate buffer "
-					"for delba frame\n", sdata->dev->name);
+					"for delba frame\n", sdata->name);
 		return;
 	}
 
@@ -114,10 +114,10 @@ void ieee80211_send_delba(struct ieee802
 	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
 	memset(mgmt, 0, 24);
 	memcpy(mgmt->da, da, ETH_ALEN);
-	memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
+	memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
 	if (sdata->vif.type == NL80211_IFTYPE_AP ||
 	    sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
-		memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN);
+		memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
 	else if (sdata->vif.type == NL80211_IFTYPE_STATION)
 		memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
 
--- wireless-testing.orig/net/mac80211/ibss.c	2009-11-20 11:42:57.000000000 +0100
+++ wireless-testing/net/mac80211/ibss.c	2009-11-20 11:43:00.000000000 +0100
@@ -117,7 +117,7 @@ static void __ieee80211_sta_join_ibss(st
 	mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
 					  IEEE80211_STYPE_PROBE_RESP);
 	memset(mgmt->da, 0xff, ETH_ALEN);
-	memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
+	memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
 	memcpy(mgmt->bssid, ifibss->bssid, ETH_ALEN);
 	mgmt->u.beacon.beacon_int = cpu_to_le16(beacon_int);
 	mgmt->u.beacon.timestamp = cpu_to_le64(tsf);
@@ -266,7 +266,7 @@ static void ieee80211_rx_bss_info(struct
 				printk(KERN_DEBUG "%s: updated supp_rates set "
 				    "for %pM based on beacon info (0x%llx | "
 				    "0x%llx -> 0x%llx)\n",
-				    sdata->dev->name,
+				    sdata->name,
 				    sta->sta.addr,
 				    (unsigned long long) prev_rates,
 				    (unsigned long long) supp_rates,
@@ -364,7 +364,7 @@ static void ieee80211_rx_bss_info(struct
 #ifdef CONFIG_MAC80211_IBSS_DEBUG
 		printk(KERN_DEBUG "%s: beacon TSF higher than "
 		       "local TSF - IBSS merge with BSSID %pM\n",
-		       sdata->dev->name, mgmt->bssid);
+		       sdata->name, mgmt->bssid);
 #endif
 		ieee80211_sta_join_ibss(sdata, bss);
 		ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, supp_rates);
@@ -393,7 +393,7 @@ struct sta_info *ieee80211_ibss_add_sta(
 	if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) {
 		if (net_ratelimit())
 			printk(KERN_DEBUG "%s: No room for a new IBSS STA entry %pM\n",
-			       sdata->dev->name, addr);
+			       sdata->name, addr);
 		return NULL;
 	}
 
@@ -402,7 +402,7 @@ struct sta_info *ieee80211_ibss_add_sta(
 
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
 	printk(KERN_DEBUG "%s: Adding new IBSS station %pM (dev=%s)\n",
-	       wiphy_name(local->hw.wiphy), addr, sdata->dev->name);
+	       wiphy_name(local->hw.wiphy), addr, sdata->name);
 #endif
 
 	sta = sta_info_alloc(sdata, addr, GFP_ATOMIC);
@@ -466,7 +466,7 @@ static void ieee80211_sta_merge_ibss(str
 		return;
 
 	printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other "
-	       "IBSS networks with same SSID (merge)\n", sdata->dev->name);
+	       "IBSS networks with same SSID (merge)\n", sdata->name);
 
 	ieee80211_request_internal_scan(sdata, ifibss->ssid, ifibss->ssid_len);
 }
@@ -488,13 +488,13 @@ static void ieee80211_sta_create_ibss(st
 		 * random number generator get different BSSID. */
 		get_random_bytes(bssid, ETH_ALEN);
 		for (i = 0; i < ETH_ALEN; i++)
-			bssid[i] ^= sdata->dev->dev_addr[i];
+			bssid[i] ^= sdata->vif.addr[i];
 		bssid[0] &= ~0x01;
 		bssid[0] |= 0x02;
 	}
 
 	printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %pM\n",
-	       sdata->dev->name, bssid);
+	       sdata->name, bssid);
 
 	sband = local->hw.wiphy->bands[ifibss->channel->band];
 
@@ -523,7 +523,7 @@ static void ieee80211_sta_find_ibss(stru
 	active_ibss = ieee80211_sta_active_ibss(sdata);
 #ifdef CONFIG_MAC80211_IBSS_DEBUG
 	printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n",
-	       sdata->dev->name, active_ibss);
+	       sdata->name, active_ibss);
 #endif /* CONFIG_MAC80211_IBSS_DEBUG */
 
 	if (active_ibss)
@@ -552,7 +552,7 @@ static void ieee80211_sta_find_ibss(stru
 
 		printk(KERN_DEBUG "%s: Selected IBSS BSSID %pM"
 		       " based on configured SSID\n",
-		       sdata->dev->name, bss->cbss.bssid);
+		       sdata->name, bss->cbss.bssid);
 
 		ieee80211_sta_join_ibss(sdata, bss);
 		ieee80211_rx_bss_put(local, bss);
@@ -571,7 +571,7 @@ static void ieee80211_sta_find_ibss(stru
 	} else if (time_after(jiffies, ifibss->last_scan_completed +
 					IEEE80211_SCAN_INTERVAL)) {
 		printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to "
-		       "join\n", sdata->dev->name);
+		       "join\n", sdata->name);
 
 		ieee80211_request_internal_scan(sdata, ifibss->ssid,
 						ifibss->ssid_len);
@@ -585,7 +585,7 @@ static void ieee80211_sta_find_ibss(stru
 				return;
 			}
 			printk(KERN_DEBUG "%s: IBSS not allowed on"
-			       " %d MHz\n", sdata->dev->name,
+			       " %d MHz\n", sdata->name,
 			       local->hw.conf.channel->center_freq);
 
 			/* No IBSS found - decrease scan interval and continue
@@ -619,7 +619,7 @@ static void ieee80211_rx_mgmt_probe_req(
 #ifdef CONFIG_MAC80211_IBSS_DEBUG
 	printk(KERN_DEBUG "%s: RX ProbeReq SA=%pM DA=%pM BSSID=%pM"
 	       " (tx_last_beacon=%d)\n",
-	       sdata->dev->name, mgmt->sa, mgmt->da,
+	       sdata->name, mgmt->sa, mgmt->da,
 	       mgmt->bssid, tx_last_beacon);
 #endif /* CONFIG_MAC80211_IBSS_DEBUG */
 
@@ -637,7 +637,7 @@ static void ieee80211_rx_mgmt_probe_req(
 #ifdef CONFIG_MAC80211_IBSS_DEBUG
 		printk(KERN_DEBUG "%s: Invalid SSID IE in ProbeReq "
 		       "from %pM\n",
-		       sdata->dev->name, mgmt->sa);
+		       sdata->name, mgmt->sa);
 #endif
 		return;
 	}
@@ -657,7 +657,7 @@ static void ieee80211_rx_mgmt_probe_req(
 	memcpy(resp->da, mgmt->sa, ETH_ALEN);
 #ifdef CONFIG_MAC80211_IBSS_DEBUG
 	printk(KERN_DEBUG "%s: Sending ProbeResp to %pM\n",
-	       sdata->dev->name, resp->da);
+	       sdata->name, resp->da);
 #endif /* CONFIG_MAC80211_IBSS_DEBUG */
 	IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
 	ieee80211_tx_skb(sdata, skb);
@@ -671,7 +671,7 @@ static void ieee80211_rx_mgmt_probe_resp
 	size_t baselen;
 	struct ieee802_11_elems elems;
 
-	if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN))
+	if (memcmp(mgmt->da, sdata->vif.addr, ETH_ALEN))
 		return; /* ignore ProbeResp to foreign address */
 
 	baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
--- wireless-testing.orig/net/mac80211/status.c	2009-11-20 11:42:57.000000000 +0100
+++ wireless-testing/net/mac80211/status.c	2009-11-20 11:43:00.000000000 +0100
@@ -167,7 +167,7 @@ void ieee80211_tx_status(struct ieee8021
 
 	for_each_sta_info(local, hdr->addr1, sta, tmp) {
 		/* skip wrong virtual interface */
-		if (memcmp(hdr->addr2, sta->sdata->dev->dev_addr, ETH_ALEN))
+		if (memcmp(hdr->addr2, sta->sdata->vif.addr, ETH_ALEN))
 			continue;
 
 		if (!(info->flags & IEEE80211_TX_STAT_ACK) &&
--- wireless-testing.orig/net/mac80211/main.c	2009-11-20 11:41:40.000000000 +0100
+++ wireless-testing/net/mac80211/main.c	2009-11-20 11:43:00.000000000 +0100
@@ -32,7 +32,6 @@
 #include "led.h"
 #include "cfg.h"
 #include "debugfs.h"
-#include "debugfs_netdev.h"
 
 void ieee80211_configure_filter(struct ieee80211_local *local)
 {
@@ -173,7 +172,7 @@ void ieee80211_bss_info_change_notify(st
 	} else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
 		sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid;
 	else if (sdata->vif.type == NL80211_IFTYPE_AP)
-		sdata->vif.bss_conf.bssid = sdata->dev->dev_addr;
+		sdata->vif.bss_conf.bssid = sdata->vif.addr;
 	else if (ieee80211_vif_is_mesh(&sdata->vif)) {
 		sdata->vif.bss_conf.bssid = zero;
 	} else {
@@ -672,11 +671,19 @@ static int __init ieee80211_init(void)
 
 	ret = rc80211_pid_init();
 	if (ret)
-		return ret;
+		goto err_pid;
 
-	ieee80211_debugfs_netdev_init();
+	ret = ieee80211_iface_init();
+	if (ret)
+		goto err_netdev;
 
 	return 0;
+ err_netdev:
+	rc80211_pid_exit();
+ err_pid:
+	rc80211_minstrel_exit();
+
+	return ret;
 }
 
 static void __exit ieee80211_exit(void)
@@ -693,7 +700,7 @@ static void __exit ieee80211_exit(void)
 	if (mesh_allocated)
 		ieee80211s_stop();
 
-	ieee80211_debugfs_netdev_exit();
+	ieee80211_iface_exit();
 }
 
 
--- wireless-testing.orig/net/mac80211/mesh.c	2009-11-20 11:41:40.000000000 +0100
+++ wireless-testing/net/mac80211/mesh.c	2009-11-20 11:43:00.000000000 +0100
@@ -457,7 +457,7 @@ static void ieee80211_mesh_housekeeping(
 
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
 	printk(KERN_DEBUG "%s: running mesh housekeeping\n",
-	       sdata->dev->name);
+	       sdata->name);
 #endif
 
 	ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT);
@@ -565,7 +565,7 @@ static void ieee80211_mesh_rx_bcn_presp(
 
 	/* ignore ProbeResp to foreign address */
 	if (stype == IEEE80211_STYPE_PROBE_RESP &&
-	    compare_ether_addr(mgmt->da, sdata->dev->dev_addr))
+	    compare_ether_addr(mgmt->da, sdata->vif.addr))
 		return;
 
 	baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
--- wireless-testing.orig/net/mac80211/mesh_hwmp.c	2009-11-20 11:42:57.000000000 +0100
+++ wireless-testing/net/mac80211/mesh_hwmp.c	2009-11-20 11:43:00.000000000 +0100
@@ -128,9 +128,9 @@ static int mesh_path_sel_frame_tx(enum m
 					  IEEE80211_STYPE_ACTION);
 
 	memcpy(mgmt->da, da, ETH_ALEN);
-	memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
+	memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
 	/* BSSID == SA */
-	memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN);
+	memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
 	mgmt->u.action.category = MESH_PATH_SEL_CATEGORY;
 	mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION;
 
@@ -222,7 +222,7 @@ int mesh_path_error_tx(u8 ttl, u8 *targe
 					  IEEE80211_STYPE_ACTION);
 
 	memcpy(mgmt->da, ra, ETH_ALEN);
-	memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
+	memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
 	/* BSSID is left zeroed, wildcard value */
 	mgmt->u.action.category = MESH_PATH_SEL_CATEGORY;
 	mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION;
@@ -374,7 +374,7 @@ static u32 hwmp_route_info_get(struct ie
 		new_metric = MAX_METRIC;
 	exp_time = TU_TO_EXP_TIME(orig_lifetime);
 
-	if (memcmp(orig_addr, sdata->dev->dev_addr, ETH_ALEN) == 0) {
+	if (memcmp(orig_addr, sdata->vif.addr, ETH_ALEN) == 0) {
 		/* This MP is the originator, we are not interested in this
 		 * frame, except for updating transmitter's path info.
 		 */
@@ -486,7 +486,7 @@ static void hwmp_preq_frame_process(stru
 
 	mhwmp_dbg("received PREQ from %pM\n", orig_addr);
 
-	if (memcmp(target_addr, sdata->dev->dev_addr, ETH_ALEN) == 0) {
+	if (memcmp(target_addr, sdata->vif.addr, ETH_ALEN) == 0) {
 		mhwmp_dbg("PREQ is for us\n");
 		forward = false;
 		reply = true;
@@ -579,7 +579,7 @@ static void hwmp_prep_frame_process(stru
 	 * replies
 	 */
 	target_addr = PREP_IE_TARGET_ADDR(prep_elem);
-	if (memcmp(target_addr, sdata->dev->dev_addr, ETH_ALEN) == 0)
+	if (memcmp(target_addr, sdata->vif.addr, ETH_ALEN) == 0)
 		/* destination, no forwarding required */
 		return;
 
@@ -890,7 +890,7 @@ void mesh_path_start_discovery(struct ie
 		target_flags = MP_F_RF;
 
 	spin_unlock_bh(&mpath->state_lock);
-	mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->dev->dev_addr,
+	mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->vif.addr,
 			cpu_to_le32(ifmsh->sn), target_flags, mpath->dst,
 			cpu_to_le32(mpath->sn), broadcast_addr, 0,
 			ttl, cpu_to_le32(lifetime), 0,
@@ -938,7 +938,7 @@ int mesh_nexthop_lookup(struct sk_buff *
 	if (mpath->flags & MESH_PATH_ACTIVE) {
 		if (time_after(jiffies, mpath->exp_time +
 			msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time))
-				&& !memcmp(sdata->dev->dev_addr, hdr->addr4,
+				&& !memcmp(sdata->vif.addr, hdr->addr4,
 					   ETH_ALEN)
 				&& !(mpath->flags & MESH_PATH_RESOLVING)
 				&& !(mpath->flags & MESH_PATH_FIXED)) {
@@ -1011,7 +1011,7 @@ mesh_path_tx_root_frame(struct ieee80211
 {
 	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
 
-	mesh_path_sel_frame_tx(MPATH_RANN, 0, sdata->dev->dev_addr,
+	mesh_path_sel_frame_tx(MPATH_RANN, 0, sdata->vif.addr,
 			       cpu_to_le32(++ifmsh->sn),
 			       0, NULL, 0, broadcast_addr,
 			       0, MESH_TTL, 0, 0, 0, sdata);
--- wireless-testing.orig/net/mac80211/mesh_pathtbl.c	2009-11-20 11:41:40.000000000 +0100
+++ wireless-testing/net/mac80211/mesh_pathtbl.c	2009-11-20 11:43:00.000000000 +0100
@@ -260,7 +260,7 @@ int mesh_path_add(u8 *dst, struct ieee80
 	int err = 0;
 	u32 hash_idx;
 
-	if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0)
+	if (memcmp(dst, sdata->vif.addr, ETH_ALEN) == 0)
 		/* never add ourselves as neighbours */
 		return -ENOTSUPP;
 
@@ -377,7 +377,7 @@ int mpp_path_add(u8 *dst, u8 *mpp, struc
 	int err = 0;
 	u32 hash_idx;
 
-	if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0)
+	if (memcmp(dst, sdata->vif.addr, ETH_ALEN) == 0)
 		/* never add ourselves as neighbours */
 		return -ENOTSUPP;
 
@@ -605,7 +605,7 @@ void mesh_path_discard_frame(struct sk_b
 	struct mesh_path *mpath;
 	u32 sn = 0;
 
-	if (memcmp(hdr->addr4, sdata->dev->dev_addr, ETH_ALEN) != 0) {
+	if (memcmp(hdr->addr4, sdata->vif.addr, ETH_ALEN) != 0) {
 		u8 *ra, *da;
 
 		da = hdr->addr3;
--- wireless-testing.orig/net/mac80211/mesh_plink.c	2009-11-20 11:42:57.000000000 +0100
+++ wireless-testing/net/mac80211/mesh_plink.c	2009-11-20 11:43:00.000000000 +0100
@@ -169,7 +169,7 @@ static int mesh_plink_frame_tx(struct ie
 	mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
 					  IEEE80211_STYPE_ACTION);
 	memcpy(mgmt->da, da, ETH_ALEN);
-	memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
+	memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
 	/* BSSID is left zeroed, wildcard value */
 	mgmt->u.action.category = MESH_PLINK_CATEGORY;
 	mgmt->u.action.u.plink_action.action_code = action;
--- wireless-testing.orig/net/mac80211/mlme.c	2009-11-20 11:42:57.000000000 +0100
+++ wireless-testing/net/mac80211/mlme.c	2009-11-20 11:43:00.000000000 +0100
@@ -248,7 +248,7 @@ static void ieee80211_send_assoc(struct 
 			    wk->ssid_len);
 	if (!skb) {
 		printk(KERN_DEBUG "%s: failed to allocate buffer for assoc "
-		       "frame\n", sdata->dev->name);
+		       "frame\n", sdata->name);
 		return;
 	}
 	skb_reserve(skb, local->hw.extra_tx_headroom);
@@ -282,7 +282,7 @@ static void ieee80211_send_assoc(struct 
 	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
 	memset(mgmt, 0, 24);
 	memcpy(mgmt->da, wk->bss->cbss.bssid, ETH_ALEN);
-	memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
+	memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
 	memcpy(mgmt->bssid, wk->bss->cbss.bssid, ETH_ALEN);
 
 	if (!is_zero_ether_addr(wk->prev_bssid)) {
@@ -443,7 +443,7 @@ static void ieee80211_send_deauth_disass
 	skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt));
 	if (!skb) {
 		printk(KERN_DEBUG "%s: failed to allocate buffer for "
-		       "deauth/disassoc frame\n", sdata->dev->name);
+		       "deauth/disassoc frame\n", sdata->name);
 		return;
 	}
 	skb_reserve(skb, local->hw.extra_tx_headroom);
@@ -451,7 +451,7 @@ static void ieee80211_send_deauth_disass
 	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
 	memset(mgmt, 0, 24);
 	memcpy(mgmt->da, bssid, ETH_ALEN);
-	memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
+	memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
 	memcpy(mgmt->bssid, bssid, ETH_ALEN);
 	mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | stype);
 	skb_put(skb, 2);
@@ -484,7 +484,7 @@ void ieee80211_send_pspoll(struct ieee80
 	skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*pspoll));
 	if (!skb) {
 		printk(KERN_DEBUG "%s: failed to allocate buffer for "
-		       "pspoll frame\n", sdata->dev->name);
+		       "pspoll frame\n", sdata->name);
 		return;
 	}
 	skb_reserve(skb, local->hw.extra_tx_headroom);
@@ -499,7 +499,7 @@ void ieee80211_send_pspoll(struct ieee80
 	pspoll->aid |= cpu_to_le16(1 << 15 | 1 << 14);
 
 	memcpy(pspoll->bssid, ifmgd->bssid, ETH_ALEN);
-	memcpy(pspoll->ta, sdata->dev->dev_addr, ETH_ALEN);
+	memcpy(pspoll->ta, sdata->vif.addr, ETH_ALEN);
 
 	IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
 	ieee80211_tx_skb(sdata, skb);
@@ -519,7 +519,7 @@ void ieee80211_send_nullfunc(struct ieee
 	skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24);
 	if (!skb) {
 		printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc "
-		       "frame\n", sdata->dev->name);
+		       "frame\n", sdata->name);
 		return;
 	}
 	skb_reserve(skb, local->hw.extra_tx_headroom);
@@ -532,7 +532,7 @@ void ieee80211_send_nullfunc(struct ieee
 		fc |= cpu_to_le16(IEEE80211_FCTL_PM);
 	nullfunc->frame_control = fc;
 	memcpy(nullfunc->addr1, sdata->u.mgd.bssid, ETH_ALEN);
-	memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN);
+	memcpy(nullfunc->addr2, sdata->vif.addr, ETH_ALEN);
 	memcpy(nullfunc->addr3, sdata->u.mgd.bssid, ETH_ALEN);
 
 	IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
@@ -948,7 +948,7 @@ ieee80211_direct_probe(struct ieee80211_
 	wk->tries++;
 	if (wk->tries > IEEE80211_AUTH_MAX_TRIES) {
 		printk(KERN_DEBUG "%s: direct probe to AP %pM timed out\n",
-		       sdata->dev->name, wk->bss->cbss.bssid);
+		       sdata->name, wk->bss->cbss.bssid);
 
 		/*
 		 * Most likely AP is not in the range so remove the
@@ -966,7 +966,7 @@ ieee80211_direct_probe(struct ieee80211_
 	}
 
 	printk(KERN_DEBUG "%s: direct probe to AP %pM (try %d)\n",
-			sdata->dev->name, wk->bss->cbss.bssid,
+			sdata->name, wk->bss->cbss.bssid,
 			wk->tries);
 
 	/*
@@ -993,7 +993,7 @@ ieee80211_authenticate(struct ieee80211_
 	if (wk->tries > IEEE80211_AUTH_MAX_TRIES) {
 		printk(KERN_DEBUG "%s: authentication with AP %pM"
 		       " timed out\n",
-		       sdata->dev->name, wk->bss->cbss.bssid);
+		       sdata->name, wk->bss->cbss.bssid);
 
 		/*
 		 * Most likely AP is not in the range so remove the
@@ -1011,7 +1011,7 @@ ieee80211_authenticate(struct ieee80211_
 	}
 
 	printk(KERN_DEBUG "%s: authenticate with AP %pM (try %d)\n",
-	       sdata->dev->name, wk->bss->cbss.bssid, wk->tries);
+	       sdata->name, wk->bss->cbss.bssid, wk->tries);
 
 	ieee80211_send_auth(sdata, 1, wk->auth_alg, wk->ie, wk->ie_len,
 			    wk->bss->cbss.bssid, NULL, 0, 0);
@@ -1133,7 +1133,7 @@ ieee80211_associate(struct ieee80211_sub
 	if (wk->tries > IEEE80211_ASSOC_MAX_TRIES) {
 		printk(KERN_DEBUG "%s: association with AP %pM"
 		       " timed out\n",
-		       sdata->dev->name, wk->bss->cbss.bssid);
+		       sdata->name, wk->bss->cbss.bssid);
 
 		/*
 		 * Most likely AP is not in the range so remove the
@@ -1151,7 +1151,7 @@ ieee80211_associate(struct ieee80211_sub
 	}
 
 	printk(KERN_DEBUG "%s: associate with AP %pM (try %d)\n",
-	       sdata->dev->name, wk->bss->cbss.bssid, wk->tries);
+	       sdata->name, wk->bss->cbss.bssid, wk->tries);
 	ieee80211_send_assoc(sdata, wk);
 
 	wk->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT;
@@ -1212,7 +1212,7 @@ static void ieee80211_mgd_probe_ap(struc
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
 	if (beacon && net_ratelimit())
 		printk(KERN_DEBUG "%s: detected beacon loss from AP "
-		       "- sending probe request\n", sdata->dev->name);
+		       "- sending probe request\n", sdata->name);
 #endif
 
 	/*
@@ -1269,7 +1269,7 @@ static void ieee80211_auth_completed(str
 				     struct ieee80211_mgd_work *wk)
 {
 	wk->state = IEEE80211_MGD_STATE_IDLE;
-	printk(KERN_DEBUG "%s: authenticated\n", sdata->dev->name);
+	printk(KERN_DEBUG "%s: authenticated\n", sdata->name);
 }
 
 
@@ -1366,7 +1366,7 @@ ieee80211_rx_mgmt_deauth(struct ieee8021
 	reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
 
 	printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n",
-			sdata->dev->name, bssid, reason_code);
+			sdata->name, bssid, reason_code);
 
 	if (!wk) {
 		ieee80211_set_disassoc(sdata, true);
@@ -1400,7 +1400,7 @@ ieee80211_rx_mgmt_disassoc(struct ieee80
 	reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
 
 	printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n",
-			sdata->dev->name, mgmt->sa, reason_code);
+			sdata->name, mgmt->sa, reason_code);
 
 	ieee80211_set_disassoc(sdata, false);
 	return RX_MGMT_CFG80211_DISASSOC;
@@ -1444,7 +1444,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee
 
 	printk(KERN_DEBUG "%s: RX %sssocResp from %pM (capab=0x%x "
 	       "status=%d aid=%d)\n",
-	       sdata->dev->name, reassoc ? "Rea" : "A", mgmt->sa,
+	       sdata->name, reassoc ? "Rea" : "A", mgmt->sa,
 	       capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14))));
 
 	pos = mgmt->u.assoc_resp.variable;
@@ -1458,7 +1458,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee
 		ms = tu * 1024 / 1000;
 		printk(KERN_DEBUG "%s: AP rejected association temporarily; "
 		       "comeback duration %u TU (%u ms)\n",
-		       sdata->dev->name, tu, ms);
+		       sdata->name, tu, ms);
 		wk->timeout = jiffies + msecs_to_jiffies(ms);
 		if (ms > IEEE80211_ASSOC_TIMEOUT)
 			run_again(ifmgd, jiffies + msecs_to_jiffies(ms));
@@ -1467,23 +1467,23 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee
 
 	if (status_code != WLAN_STATUS_SUCCESS) {
 		printk(KERN_DEBUG "%s: AP denied association (code=%d)\n",
-		       sdata->dev->name, status_code);
+		       sdata->name, status_code);
 		wk->state = IEEE80211_MGD_STATE_IDLE;
 		return RX_MGMT_CFG80211_ASSOC;
 	}
 
 	if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14)))
 		printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not "
-		       "set\n", sdata->dev->name, aid);
+		       "set\n", sdata->name, aid);
 	aid &= ~(BIT(15) | BIT(14));
 
 	if (!elems.supp_rates) {
 		printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n",
-		       sdata->dev->name);
+		       sdata->name);
 		return RX_MGMT_NONE;
 	}
 
-	printk(KERN_DEBUG "%s: associated\n", sdata->dev->name);
+	printk(KERN_DEBUG "%s: associated\n", sdata->name);
 	ifmgd->aid = aid;
 
 	rcu_read_lock();
@@ -1498,7 +1498,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee
 		sta = sta_info_alloc(sdata, wk->bss->cbss.bssid, GFP_KERNEL);
 		if (!sta) {
 			printk(KERN_DEBUG "%s: failed to alloc STA entry for"
-			       " the AP\n", sdata->dev->name);
+			       " the AP\n", sdata->name);
 			return RX_MGMT_NONE;
 		}
 
@@ -1576,7 +1576,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee
 		int err = sta_info_insert(sta);
 		if (err) {
 			printk(KERN_DEBUG "%s: failed to insert STA entry for"
-			       " the AP (error %d)\n", sdata->dev->name, err);
+			       " the AP (error %d)\n", sdata->name, err);
 			rcu_read_unlock();
 			return RX_MGMT_NONE;
 		}
@@ -1671,7 +1671,7 @@ static void ieee80211_rx_mgmt_probe_resp
 
 	ASSERT_MGD_MTX(ifmgd);
 
-	if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN))
+	if (memcmp(mgmt->da, sdata->vif.addr, ETH_ALEN))
 		return; /* ignore ProbeResp to foreign address */
 
 	baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
@@ -1686,7 +1686,7 @@ static void ieee80211_rx_mgmt_probe_resp
 	/* direct probe may be part of the association flow */
 	if (wk && wk->state == IEEE80211_MGD_STATE_PROBE) {
 		printk(KERN_DEBUG "%s: direct probe responded\n",
-		       sdata->dev->name);
+		       sdata->name);
 		wk->tries = 0;
 		wk->state = IEEE80211_MGD_STATE_AUTH;
 		WARN_ON(ieee80211_authenticate(sdata, wk) != RX_MGMT_NONE);
@@ -1779,7 +1779,7 @@ static void ieee80211_rx_mgmt_beacon(str
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
 		if (net_ratelimit()) {
 			printk(KERN_DEBUG "%s: cancelling probereq poll due "
-			       "to a received beacon\n", sdata->dev->name);
+			       "to a received beacon\n", sdata->name);
 		}
 #endif
 		ifmgd->flags &= ~IEEE80211_STA_BEACON_POLL;
@@ -2554,7 +2554,7 @@ int ieee80211_mgd_deauth(struct ieee8021
 	mutex_unlock(&ifmgd->mtx);
 
 	printk(KERN_DEBUG "%s: deauthenticating from %pM by local choice (reason=%d)\n",
-	       sdata->dev->name, bssid, req->reason_code);
+	       sdata->name, bssid, req->reason_code);
 
 	ieee80211_send_deauth_disassoc(sdata, bssid,
 			IEEE80211_STYPE_DEAUTH, req->reason_code,
@@ -2583,7 +2583,7 @@ int ieee80211_mgd_disassoc(struct ieee80
 	}
 
 	printk(KERN_DEBUG "%s: disassociating from %pM by local choice (reason=%d)\n",
-	       sdata->dev->name, req->bss->bssid, req->reason_code);
+	       sdata->name, req->bss->bssid, req->reason_code);
 
 	ieee80211_set_disassoc(sdata, false);
 
--- wireless-testing.orig/net/mac80211/rx.c	2009-11-20 11:42:57.000000000 +0100
+++ wireless-testing/net/mac80211/rx.c	2009-11-20 11:43:00.000000000 +0100
@@ -287,15 +287,15 @@ ieee80211_rx_monitor(struct ieee80211_lo
 	skb->protocol = htons(ETH_P_802_2);
 
 	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
-		if (!netif_running(sdata->dev))
-			continue;
-
 		if (sdata->vif.type != NL80211_IFTYPE_MONITOR)
 			continue;
 
 		if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES)
 			continue;
 
+		if (!netif_running(sdata->dev))
+			continue;
+
 		if (prev_dev) {
 			skb2 = skb_clone(skb, GFP_ATOMIC);
 			if (skb2) {
@@ -480,7 +480,7 @@ ieee80211_rx_mesh_check(struct ieee80211
 {
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
 	unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control);
-	char *dev_addr = rx->sdata->dev->dev_addr;
+	char *dev_addr = rx->sdata->vif.addr;
 
 	if (ieee80211_is_data(hdr->frame_control)) {
 		if (is_multicast_ether_addr(hdr->addr1)) {
@@ -1028,7 +1028,7 @@ static void ap_sta_ps_start(struct sta_i
 	drv_sta_notify(local, &sdata->vif, STA_NOTIFY_SLEEP, &sta->sta);
 #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
 	printk(KERN_DEBUG "%s: STA %pM aid %d enters power save mode\n",
-	       sdata->dev->name, sta->sta.addr, sta->sta.aid);
+	       sdata->name, sta->sta.addr, sta->sta.aid);
 #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
 }
 
@@ -1042,13 +1042,13 @@ static void ap_sta_ps_end(struct sta_inf
 
 #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
 	printk(KERN_DEBUG "%s: STA %pM aid %d exits power save mode\n",
-	       sdata->dev->name, sta->sta.addr, sta->sta.aid);
+	       sdata->name, sta->sta.addr, sta->sta.aid);
 #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
 
 	if (test_sta_flags(sta, WLAN_STA_PS_DRIVER)) {
 #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
 		printk(KERN_DEBUG "%s: STA %pM aid %d driver-ps-blocked\n",
-		       sdata->dev->name, sta->sta.addr, sta->sta.aid);
+		       sdata->name, sta->sta.addr, sta->sta.aid);
 #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
 		return;
 	}
@@ -1160,7 +1160,7 @@ ieee80211_reassemble_add(struct ieee8021
 		printk(KERN_DEBUG "%s: RX reassembly removed oldest "
 		       "fragment entry (idx=%d age=%lu seq=%d last_frag=%d "
 		       "addr1=%pM addr2=%pM\n",
-		       sdata->dev->name, idx,
+		       sdata->name, idx,
 		       jiffies - entry->first_frag_time, entry->seq,
 		       entry->last_frag, hdr->addr1, hdr->addr2);
 #endif
@@ -1428,7 +1428,6 @@ static int
 __ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
 {
 	struct ieee80211_sub_if_data *sdata = rx->sdata;
-	struct net_device *dev = sdata->dev;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
 
 	if (ieee80211_has_a4(hdr->frame_control) &&
@@ -1440,7 +1439,7 @@ __ieee80211_data_to_8023(struct ieee8021
 	     (sdata->vif.type == NL80211_IFTYPE_STATION && sdata->u.mgd.use_4addr)))
 		return -1;
 
-	return ieee80211_data_to_8023(rx->skb, dev->dev_addr, sdata->vif.type);
+	return ieee80211_data_to_8023(rx->skb, sdata->vif.addr, sdata->vif.type);
 }
 
 /*
@@ -1457,7 +1456,7 @@ static bool ieee80211_frame_allowed(stru
 	 * of whether the frame was encrypted or not.
 	 */
 	if (ehdr->h_proto == htons(ETH_P_PAE) &&
-	    (compare_ether_addr(ehdr->h_dest, rx->sdata->dev->dev_addr) == 0 ||
+	    (compare_ether_addr(ehdr->h_dest, rx->sdata->vif.addr) == 0 ||
 	     compare_ether_addr(ehdr->h_dest, pae_group_addr) == 0))
 		return true;
 
@@ -1725,7 +1724,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80
 
 	/* Frame has reached destination.  Don't forward */
 	if (!is_multicast_ether_addr(hdr->addr1) &&
-	    compare_ether_addr(sdata->dev->dev_addr, hdr->addr3) == 0)
+	    compare_ether_addr(sdata->vif.addr, hdr->addr3) == 0)
 		return RX_CONTINUE;
 
 	mesh_hdr->ttl--;
@@ -1742,10 +1741,10 @@ ieee80211_rx_h_mesh_fwding(struct ieee80
 
 			if (!fwd_skb && net_ratelimit())
 				printk(KERN_DEBUG "%s: failed to clone mesh frame\n",
-						   sdata->dev->name);
+						   sdata->name);
 
 			fwd_hdr =  (struct ieee80211_hdr *) fwd_skb->data;
-			memcpy(fwd_hdr->addr2, sdata->dev->dev_addr, ETH_ALEN);
+			memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN);
 			info = IEEE80211_SKB_CB(fwd_skb);
 			memset(info, 0, sizeof(*info));
 			info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
@@ -1874,7 +1873,7 @@ static void ieee80211_process_sa_query_r
 	struct sk_buff *skb;
 	struct ieee80211_mgmt *resp;
 
-	if (compare_ether_addr(mgmt->da, sdata->dev->dev_addr) != 0) {
+	if (compare_ether_addr(mgmt->da, sdata->vif.addr) != 0) {
 		/* Not to own unicast address */
 		return;
 	}
@@ -1898,7 +1897,7 @@ static void ieee80211_process_sa_query_r
 	resp = (struct ieee80211_mgmt *) skb_put(skb, 24);
 	memset(resp, 0, 24);
 	memcpy(resp->da, mgmt->sa, ETH_ALEN);
-	memcpy(resp->sa, sdata->dev->dev_addr, ETH_ALEN);
+	memcpy(resp->sa, sdata->vif.addr, ETH_ALEN);
 	memcpy(resp->bssid, sdata->u.mgd.bssid, ETH_ALEN);
 	resp->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
 					  IEEE80211_STYPE_ACTION);
@@ -2278,7 +2277,7 @@ static int prepare_for_handlers(struct i
 		if (!bssid && !sdata->u.mgd.use_4addr)
 			return 0;
 		if (!multicast &&
-		    compare_ether_addr(sdata->dev->dev_addr, hdr->addr1) != 0) {
+		    compare_ether_addr(sdata->vif.addr, hdr->addr1) != 0) {
 			if (!(sdata->dev->flags & IFF_PROMISC))
 				return 0;
 			rx->flags &= ~IEEE80211_RX_RA_MATCH;
@@ -2295,7 +2294,7 @@ static int prepare_for_handlers(struct i
 				return 0;
 			rx->flags &= ~IEEE80211_RX_RA_MATCH;
 		} else if (!multicast &&
-			   compare_ether_addr(sdata->dev->dev_addr,
+			   compare_ether_addr(sdata->vif.addr,
 					      hdr->addr1) != 0) {
 			if (!(sdata->dev->flags & IFF_PROMISC))
 				return 0;
@@ -2312,7 +2311,7 @@ static int prepare_for_handlers(struct i
 		break;
 	case NL80211_IFTYPE_MESH_POINT:
 		if (!multicast &&
-		    compare_ether_addr(sdata->dev->dev_addr,
+		    compare_ether_addr(sdata->vif.addr,
 				       hdr->addr1) != 0) {
 			if (!(sdata->dev->flags & IFF_PROMISC))
 				return 0;
@@ -2323,11 +2322,11 @@ static int prepare_for_handlers(struct i
 	case NL80211_IFTYPE_AP_VLAN:
 	case NL80211_IFTYPE_AP:
 		if (!bssid) {
-			if (compare_ether_addr(sdata->dev->dev_addr,
+			if (compare_ether_addr(sdata->vif.addr,
 					       hdr->addr1))
 				return 0;
 		} else if (!ieee80211_bssid_match(bssid,
-					sdata->dev->dev_addr)) {
+					sdata->vif.addr)) {
 			if (!(rx->flags & IEEE80211_RX_IN_SCAN))
 				return 0;
 			rx->flags &= ~IEEE80211_RX_RA_MATCH;
@@ -2446,7 +2445,7 @@ static void __ieee80211_rx_handle_packet
 					printk(KERN_DEBUG "%s: failed to copy "
 					       "multicast frame for %s\n",
 					       wiphy_name(local->hw.wiphy),
-					       prev->dev->name);
+					       prev->name);
 				continue;
 			}
 			ieee80211_invoke_rx_handlers(prev, &rx, skb_new, rate);
--- wireless-testing.orig/net/mac80211/scan.c	2009-11-20 11:41:40.000000000 +0100
+++ wireless-testing/net/mac80211/scan.c	2009-11-20 11:43:00.000000000 +0100
@@ -147,7 +147,7 @@ ieee80211_scan_rx(struct ieee80211_sub_i
 	presp = ieee80211_is_probe_resp(fc);
 	if (presp) {
 		/* ignore ProbeResp to foreign address */
-		if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN))
+		if (memcmp(mgmt->da, sdata->vif.addr, ETH_ALEN))
 			return RX_DROP_MONITOR;
 
 		presp = true;
--- wireless-testing.orig/net/mac80211/spectmgmt.c	2009-11-20 11:41:40.000000000 +0100
+++ wireless-testing/net/mac80211/spectmgmt.c	2009-11-20 11:43:00.000000000 +0100
@@ -35,7 +35,7 @@ static void ieee80211_send_refuse_measur
 
 	if (!skb) {
 		printk(KERN_ERR "%s: failed to allocate buffer for "
-				"measurement report frame\n", sdata->dev->name);
+				"measurement report frame\n", sdata->name);
 		return;
 	}
 
@@ -43,7 +43,7 @@ static void ieee80211_send_refuse_measur
 	msr_report = (struct ieee80211_mgmt *)skb_put(skb, 24);
 	memset(msr_report, 0, 24);
 	memcpy(msr_report->da, da, ETH_ALEN);
-	memcpy(msr_report->sa, sdata->dev->dev_addr, ETH_ALEN);
+	memcpy(msr_report->sa, sdata->vif.addr, ETH_ALEN);
 	memcpy(msr_report->bssid, bssid, ETH_ALEN);
 	msr_report->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
 						IEEE80211_STYPE_ACTION);
--- wireless-testing.orig/net/mac80211/sta_info.c	2009-11-20 11:42:57.000000000 +0100
+++ wireless-testing/net/mac80211/sta_info.c	2009-11-20 11:43:00.000000000 +0100
@@ -372,7 +372,7 @@ int sta_info_insert(struct sta_info *sta
 		goto out_free;
 	}
 
-	if (WARN_ON(compare_ether_addr(sta->sta.addr, sdata->dev->dev_addr) == 0 ||
+	if (WARN_ON(compare_ether_addr(sta->sta.addr, sdata->vif.addr) == 0 ||
 		    is_multicast_ether_addr(sta->sta.addr))) {
 		err = -EINVAL;
 		goto out_free;
@@ -831,7 +831,7 @@ void ieee80211_sta_expire(struct ieee802
 		if (time_after(jiffies, sta->last_rx + exp_time)) {
 #ifdef CONFIG_MAC80211_IBSS_DEBUG
 			printk(KERN_DEBUG "%s: expiring inactive STA %pM\n",
-			       sdata->dev->name, sta->sta.addr);
+			       sdata->name, sta->sta.addr);
 #endif
 			__sta_info_unlink(&sta);
 			if (sta)
@@ -889,7 +889,7 @@ void ieee80211_sta_ps_deliver_wakeup(str
 
 #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
 	printk(KERN_DEBUG "%s: STA %pM aid %d sending %d filtered/%d PS frames "
-	       "since STA not sleeping anymore\n", sdata->dev->name,
+	       "since STA not sleeping anymore\n", sdata->name,
 	       sta->sta.addr, sta->sta.aid, sent - buffered, buffered);
 #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
 }
@@ -948,7 +948,7 @@ void ieee80211_sta_ps_deliver_poll_respo
 		 */
 		printk(KERN_DEBUG "%s: STA %pM sent PS Poll even "
 		       "though there are no buffered frames for it\n",
-		       sdata->dev->name, sta->sta.addr);
+		       sdata->name, sta->sta.addr);
 #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
 	}
 }
--- wireless-testing.orig/net/mac80211/tx.c	2009-11-20 11:42:57.000000000 +0100
+++ wireless-testing/net/mac80211/tx.c	2009-11-20 11:43:00.000000000 +0100
@@ -223,7 +223,7 @@ ieee80211_tx_h_check_assoc(struct ieee80
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
 			printk(KERN_DEBUG "%s: dropped data frame to not "
 			       "associated station %pM\n",
-			       tx->dev->name, hdr->addr1);
+			       tx->sdata->name, hdr->addr1);
 #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
 			I802_DEBUG_INC(tx->local->tx_handlers_drop_not_assoc);
 			return TX_DROP;
@@ -331,7 +331,7 @@ ieee80211_tx_h_multicast_ps_buf(struct i
 #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
 		if (net_ratelimit())
 			printk(KERN_DEBUG "%s: BC TX buffer full - dropping the oldest frame\n",
-			       tx->dev->name);
+			       tx->sdata->name);
 #endif
 		dev_kfree_skb(skb_dequeue(&tx->sdata->bss->ps_bc_buf));
 	} else
@@ -390,7 +390,7 @@ ieee80211_tx_h_unicast_ps_buf(struct iee
 			if (net_ratelimit()) {
 				printk(KERN_DEBUG "%s: STA %pM TX "
 				       "buffer full - dropping oldest frame\n",
-				       tx->dev->name, sta->sta.addr);
+				       tx->sdata->name, sta->sta.addr);
 			}
 #endif
 			dev_kfree_skb(old);
@@ -415,7 +415,7 @@ ieee80211_tx_h_unicast_ps_buf(struct iee
 #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
 	else if (unlikely(staflags & WLAN_STA_PS_STA)) {
 		printk(KERN_DEBUG "%s: STA %pM in PS mode, but pspoll "
-		       "set -> send frame\n", tx->dev->name,
+		       "set -> send frame\n", tx->sdata->name,
 		       sta->sta.addr);
 	}
 #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
@@ -548,7 +548,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee8021
 		 "%s: Dropped data frame as no usable bitrate found while "
 		 "scanning and associated. Target station: "
 		 "%pM on %d GHz band\n",
-		 tx->dev->name, hdr->addr1,
+		 tx->sdata->name, hdr->addr1,
 		 tx->channel->band ? 5 : 2))
 		return TX_DROP;
 
@@ -1020,7 +1020,6 @@ ieee80211_tx_prepare(struct ieee80211_su
 
 	memset(tx, 0, sizeof(*tx));
 	tx->skb = skb;
-	tx->dev = sdata->dev; /* use original interface */
 	tx->local = local;
 	tx->sdata = sdata;
 	tx->channel = local->hw.conf.channel;
@@ -1473,7 +1472,7 @@ static void ieee80211_xmit(struct ieee80
 					continue;
 				if (tmp_sdata->vif.type != NL80211_IFTYPE_AP)
 					continue;
-				if (compare_ether_addr(tmp_sdata->dev->dev_addr,
+				if (compare_ether_addr(tmp_sdata->vif.addr,
 						       hdr->addr2) == 0) {
 					sdata = tmp_sdata;
 					break;
@@ -1637,7 +1636,7 @@ netdev_tx_t ieee80211_subif_start_xmit(s
 			fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
 			/* RA TA DA SA */
 			memcpy(hdr.addr1, sta->sta.addr, ETH_ALEN);
-			memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
+			memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN);
 			memcpy(hdr.addr3, skb->data, ETH_ALEN);
 			memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
 			hdrlen = 30;
@@ -1651,7 +1650,7 @@ netdev_tx_t ieee80211_subif_start_xmit(s
 		fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
 		/* DA BSSID SA */
 		memcpy(hdr.addr1, skb->data, ETH_ALEN);
-		memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
+		memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN);
 		memcpy(hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN);
 		hdrlen = 24;
 		break;
@@ -1659,7 +1658,7 @@ netdev_tx_t ieee80211_subif_start_xmit(s
 		fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
 		/* RA TA DA SA */
 		memcpy(hdr.addr1, sdata->u.wds.remote_addr, ETH_ALEN);
-		memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
+		memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN);
 		memcpy(hdr.addr3, skb->data, ETH_ALEN);
 		memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
 		hdrlen = 30;
@@ -1673,8 +1672,8 @@ netdev_tx_t ieee80211_subif_start_xmit(s
 			goto fail;
 		}
 
-		if (compare_ether_addr(dev->dev_addr,
-					  skb->data + ETH_ALEN) == 0) {
+		if (compare_ether_addr(sdata->vif.addr,
+				       skb->data + ETH_ALEN) == 0) {
 			hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc,
 					skb->data, skb->data + ETH_ALEN);
 			meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr,
@@ -1704,7 +1703,7 @@ netdev_tx_t ieee80211_subif_start_xmit(s
 				}
 			}
 			hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc,
-					mesh_da, dev->dev_addr);
+					mesh_da, sdata->vif.addr);
 			rcu_read_unlock();
 			if (is_mesh_mcast)
 				meshhdrlen =
@@ -1729,7 +1728,7 @@ netdev_tx_t ieee80211_subif_start_xmit(s
 		if (sdata->u.mgd.use_4addr && ethertype != ETH_P_PAE) {
 			fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
 			/* RA TA DA SA */
-			memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
+			memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN);
 			memcpy(hdr.addr3, skb->data, ETH_ALEN);
 			memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
 			hdrlen = 30;
@@ -1780,7 +1779,7 @@ netdev_tx_t ieee80211_subif_start_xmit(s
 		unlikely(!is_multicast_ether_addr(hdr.addr1) &&
 		      !(sta_flags & WLAN_STA_AUTHORIZED) &&
 		      !(ethertype == ETH_P_PAE &&
-		       compare_ether_addr(dev->dev_addr,
+		       compare_ether_addr(sdata->vif.addr,
 					  skb->data + ETH_ALEN) == 0))) {
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
 		if (net_ratelimit())
@@ -2144,8 +2143,8 @@ struct sk_buff *ieee80211_beacon_get_tim
 		mgmt->frame_control =
 		    cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
 		memset(mgmt->da, 0xff, ETH_ALEN);
-		memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
-		memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN);
+		memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
+		memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
 		mgmt->u.beacon.beacon_int =
 			cpu_to_le16(sdata->vif.bss_conf.beacon_int);
 		mgmt->u.beacon.capab_info = 0x0; /* 0x0 for MPs */
--- wireless-testing.orig/net/mac80211/util.c	2009-11-20 11:41:41.000000000 +0100
+++ wireless-testing/net/mac80211/util.c	2009-11-20 11:43:00.000000000 +0100
@@ -469,7 +469,7 @@ void ieee80211_iterate_active_interfaces
 			break;
 		}
 		if (netif_running(sdata->dev))
-			iterator(data, sdata->dev->dev_addr,
+			iterator(data, sdata->vif.addr,
 				 &sdata->vif);
 	}
 
@@ -503,7 +503,7 @@ void ieee80211_iterate_active_interfaces
 			break;
 		}
 		if (netif_running(sdata->dev))
-			iterator(data, sdata->dev->dev_addr,
+			iterator(data, sdata->vif.addr,
 				 &sdata->vif);
 	}
 
@@ -848,7 +848,7 @@ void ieee80211_send_auth(struct ieee8021
 			    sizeof(*mgmt) + 6 + extra_len);
 	if (!skb) {
 		printk(KERN_DEBUG "%s: failed to allocate buffer for auth "
-		       "frame\n", sdata->dev->name);
+		       "frame\n", sdata->name);
 		return;
 	}
 	skb_reserve(skb, local->hw.extra_tx_headroom);
@@ -858,7 +858,7 @@ void ieee80211_send_auth(struct ieee8021
 	mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
 					  IEEE80211_STYPE_AUTH);
 	memcpy(mgmt->da, bssid, ETH_ALEN);
-	memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
+	memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
 	memcpy(mgmt->bssid, bssid, ETH_ALEN);
 	mgmt->u.auth.auth_alg = cpu_to_le16(auth_alg);
 	mgmt->u.auth.auth_transaction = cpu_to_le16(transaction);
@@ -949,7 +949,7 @@ void ieee80211_send_probe_req(struct iee
 			    ie_len);
 	if (!skb) {
 		printk(KERN_DEBUG "%s: failed to allocate buffer for probe "
-		       "request\n", sdata->dev->name);
+		       "request\n", sdata->name);
 		return;
 	}
 	skb_reserve(skb, local->hw.extra_tx_headroom);
@@ -958,7 +958,7 @@ void ieee80211_send_probe_req(struct iee
 	memset(mgmt, 0, 24);
 	mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
 					  IEEE80211_STYPE_PROBE_REQ);
-	memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
+	memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
 	if (dst) {
 		memcpy(mgmt->da, dst, ETH_ALEN);
 		memcpy(mgmt->bssid, dst, ETH_ALEN);
@@ -1051,7 +1051,7 @@ int ieee80211_reconfig(struct ieee80211_
 		    netif_running(sdata->dev)) {
 			conf.vif = &sdata->vif;
 			conf.type = sdata->vif.type;
-			conf.mac_addr = sdata->dev->dev_addr;
+			conf.mac_addr = sdata->vif.addr;
 			res = drv_add_interface(local, &conf);
 		}
 	}
--- wireless-testing.orig/include/net/mac80211.h	2009-11-20 11:42:54.000000000 +0100
+++ wireless-testing/include/net/mac80211.h	2009-11-20 11:43:00.000000000 +0100
@@ -659,12 +659,14 @@ struct ieee80211_conf {
  * @type: type of this virtual interface
  * @bss_conf: BSS configuration for this interface, either our own
  *	or the BSS we're associated to
+ * @addr: address of this interface
  * @drv_priv: data area for driver use, will always be aligned to
  *	sizeof(void *).
  */
 struct ieee80211_vif {
 	enum nl80211_iftype type;
 	struct ieee80211_bss_conf bss_conf;
+	u8 addr[ETH_ALEN];
 	/* must be last */
 	u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *))));
 };
--- wireless-testing.orig/net/mac80211/driver-ops.h	2009-11-20 11:41:40.000000000 +0100
+++ wireless-testing/net/mac80211/driver-ops.h	2009-11-20 11:43:00.000000000 +0100
@@ -39,7 +39,7 @@ static inline int drv_add_interface(stru
 				    struct ieee80211_if_init_conf *conf)
 {
 	int ret = local->ops->add_interface(&local->hw, conf);
-	trace_drv_add_interface(local, conf->mac_addr, conf->vif, ret);
+	trace_drv_add_interface(local, conf->vif, ret);
 	return ret;
 }
 
@@ -47,7 +47,7 @@ static inline void drv_remove_interface(
 					struct ieee80211_if_init_conf *conf)
 {
 	local->ops->remove_interface(&local->hw, conf);
-	trace_drv_remove_interface(local, conf->mac_addr, conf->vif);
+	trace_drv_remove_interface(local, conf->vif);
 }
 
 static inline int drv_config(struct ieee80211_local *local, u32 changed)
--- wireless-testing.orig/net/mac80211/driver-trace.h	2009-11-20 11:41:40.000000000 +0100
+++ wireless-testing/net/mac80211/driver-trace.h	2009-11-20 11:43:00.000000000 +0100
@@ -70,11 +70,10 @@ TRACE_EVENT(drv_stop,
 
 TRACE_EVENT(drv_add_interface,
 	TP_PROTO(struct ieee80211_local *local,
-		 const u8 *addr,
 		 struct ieee80211_vif *vif,
 		 int ret),
 
-	TP_ARGS(local, addr, vif, ret),
+	TP_ARGS(local, vif, ret),
 
 	TP_STRUCT__entry(
 		LOCAL_ENTRY
@@ -86,7 +85,7 @@ TRACE_EVENT(drv_add_interface,
 	TP_fast_assign(
 		LOCAL_ASSIGN;
 		VIF_ASSIGN;
-		memcpy(__entry->addr, addr, 6);
+		memcpy(__entry->addr, vif->addr, 6);
 		__entry->ret = ret;
 	),
 
@@ -97,10 +96,9 @@ TRACE_EVENT(drv_add_interface,
 );
 
 TRACE_EVENT(drv_remove_interface,
-	TP_PROTO(struct ieee80211_local *local,
-		 const u8 *addr, struct ieee80211_vif *vif),
+	TP_PROTO(struct ieee80211_local *local, struct ieee80211_vif *vif),
 
-	TP_ARGS(local, addr, vif),
+	TP_ARGS(local, vif),
 
 	TP_STRUCT__entry(
 		LOCAL_ENTRY
@@ -111,7 +109,7 @@ TRACE_EVENT(drv_remove_interface,
 	TP_fast_assign(
 		LOCAL_ASSIGN;
 		VIF_ASSIGN;
-		memcpy(__entry->addr, addr, 6);
+		memcpy(__entry->addr, vif->addr, 6);
 	),
 
 	TP_printk(
--- wireless-testing.orig/net/mac80211/iface.c	2009-11-20 11:41:40.000000000 +0100
+++ wireless-testing/net/mac80211/iface.c	2009-11-20 11:43:00.000000000 +0100
@@ -60,6 +60,22 @@ static int ieee80211_change_mtu(struct n
 	return 0;
 }
 
+static int ieee80211_change_mac(struct net_device *dev, void *addr)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	int ret;
+
+	if (netif_running(dev))
+		return -EBUSY;
+
+	ret = eth_mac_addr(dev, addr);
+
+	if (ret == 0)
+		memcpy(sdata->vif.addr, addr, ETH_ALEN);
+
+	return ret;
+}
+
 static inline int identical_mac_addr_allowed(int type1, int type2)
 {
 	return type1 == NL80211_IFTYPE_MONITOR ||
@@ -234,7 +250,7 @@ static int ieee80211_open(struct net_dev
 	default:
 		conf.vif = &sdata->vif;
 		conf.type = sdata->vif.type;
-		conf.mac_addr = dev->dev_addr;
+		conf.mac_addr = sdata->vif.addr;
 		res = drv_add_interface(local, &conf);
 		if (res)
 			goto err_stop;
@@ -514,7 +530,7 @@ static int ieee80211_stop(struct net_dev
 
 		conf.vif = &sdata->vif;
 		conf.type = sdata->vif.type;
-		conf.mac_addr = dev->dev_addr;
+		conf.mac_addr = sdata->vif.addr;
 		/* disable all keys for as long as this netdev is down */
 		ieee80211_disable_keys(sdata);
 		drv_remove_interface(local, &conf);
@@ -651,7 +667,7 @@ static const struct net_device_ops ieee8
 	.ndo_start_xmit		= ieee80211_subif_start_xmit,
 	.ndo_set_multicast_list = ieee80211_set_multicast_list,
 	.ndo_change_mtu 	= ieee80211_change_mtu,
-	.ndo_set_mac_address 	= eth_mac_addr,
+	.ndo_set_mac_address 	= ieee80211_change_mac,
 };
 
 static const struct net_device_ops ieee80211_monitorif_ops = {
@@ -799,6 +815,8 @@ int ieee80211_if_add(struct ieee80211_lo
 	/* don't use IEEE80211_DEV_TO_SUB_IF because it checks too much */
 	sdata = netdev_priv(ndev);
 	ndev->ieee80211_ptr = &sdata->wdev;
+	memcpy(sdata->vif.addr, ndev->dev_addr, ETH_ALEN);
+	memcpy(sdata->name, ndev->name, IFNAMSIZ);
 
 	/* initialise type-independent data */
 	sdata->wdev.wiphy = local->hw.wiphy;
@@ -954,3 +972,41 @@ void ieee80211_recalc_idle(struct ieee80
 	if (chg)
 		ieee80211_hw_config(local, chg);
 }
+
+static int netdev_notify(struct notifier_block *nb,
+			 unsigned long state,
+			 void *ndev)
+{
+	struct net_device *dev = ndev;
+	struct ieee80211_sub_if_data *sdata;
+
+	if (state != NETDEV_CHANGENAME)
+		return 0;
+
+	if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy)
+		return 0;
+
+	if (dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid)
+		return 0;
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+	memcpy(sdata->name, sdata->name, IFNAMSIZ);
+
+	ieee80211_debugfs_rename_netdev(sdata);
+	return 0;
+}
+
+static struct notifier_block mac80211_netdev_notifier = {
+	.notifier_call = netdev_notify,
+};
+
+int ieee80211_iface_init(void)
+{
+	return register_netdevice_notifier(&mac80211_netdev_notifier);
+}
+
+void ieee80211_iface_exit(void)
+{
+	unregister_netdevice_notifier(&mac80211_netdev_notifier);
+}
--- wireless-testing.orig/net/mac80211/debugfs_netdev.c	2009-11-20 11:41:40.000000000 +0100
+++ wireless-testing/net/mac80211/debugfs_netdev.c	2009-11-20 11:43:00.000000000 +0100
@@ -280,16 +280,11 @@ static void add_files(struct ieee80211_s
 	}
 }
 
-static int notif_registered;
-
 void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata)
 {
 	char buf[10+IFNAMSIZ];
 
-	if (!notif_registered)
-		return;
-
-	sprintf(buf, "netdev:%s", sdata->dev->name);
+	sprintf(buf, "netdev:%s", sdata->name);
 	sdata->debugfs.dir = debugfs_create_dir(buf,
 		sdata->local->hw.wiphy->debugfsdir);
 	add_files(sdata);
@@ -304,58 +299,18 @@ void ieee80211_debugfs_remove_netdev(str
 	sdata->debugfs.dir = NULL;
 }
 
-static int netdev_notify(struct notifier_block *nb,
-			 unsigned long state,
-			 void *ndev)
+void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata)
 {
-	struct net_device *dev = ndev;
 	struct dentry *dir;
-	struct ieee80211_sub_if_data *sdata;
-	char buf[10+IFNAMSIZ];
-
-	if (state != NETDEV_CHANGENAME)
-		return 0;
-
-	if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy)
-		return 0;
-
-	if (dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid)
-		return 0;
-
-	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	char buf[10 + IFNAMSIZ];
 
 	dir = sdata->debugfs.dir;
 
 	if (!dir)
-		return 0;
+		return;
 
-	sprintf(buf, "netdev:%s", dev->name);
+	sprintf(buf, "netdev:%s", sdata->name);
 	if (!debugfs_rename(dir->d_parent, dir, dir->d_parent, buf))
 		printk(KERN_ERR "mac80211: debugfs: failed to rename debugfs "
 		       "dir to %s\n", buf);
-
-	return 0;
-}
-
-static struct notifier_block mac80211_debugfs_netdev_notifier = {
-	.notifier_call = netdev_notify,
-};
-
-void ieee80211_debugfs_netdev_init(void)
-{
-	int err;
-
-	err = register_netdevice_notifier(&mac80211_debugfs_netdev_notifier);
-	if (err) {
-		printk(KERN_ERR
-		       "mac80211: failed to install netdev notifier,"
-		       " disabling per-netdev debugfs!\n");
-	} else
-		notif_registered = 1;
-}
-
-void ieee80211_debugfs_netdev_exit(void)
-{
-	unregister_netdevice_notifier(&mac80211_debugfs_netdev_notifier);
-	notif_registered = 0;
 }
--- wireless-testing.orig/net/mac80211/debugfs_netdev.h	2009-11-20 11:41:41.000000000 +0100
+++ wireless-testing/net/mac80211/debugfs_netdev.h	2009-11-20 11:43:00.000000000 +0100
@@ -6,8 +6,7 @@
 #ifdef CONFIG_MAC80211_DEBUGFS
 void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata);
 void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata);
-void ieee80211_debugfs_netdev_init(void);
-void ieee80211_debugfs_netdev_exit(void);
+void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata);
 #else
 static inline void ieee80211_debugfs_add_netdev(
 	struct ieee80211_sub_if_data *sdata)
@@ -15,10 +14,8 @@ static inline void ieee80211_debugfs_add
 static inline void ieee80211_debugfs_remove_netdev(
 	struct ieee80211_sub_if_data *sdata)
 {}
-static inline void ieee80211_debugfs_netdev_init(void)
-{}
-
-static inline void ieee80211_debugfs_netdev_exit(void)
+static inline void ieee80211_debugfs_rename_netdev(
+	struct ieee80211_sub_if_data *sdata)
 {}
 #endif
 
--- wireless-testing.orig/net/mac80211/ieee80211_i.h	2009-11-20 11:42:57.000000000 +0100
+++ wireless-testing/net/mac80211/ieee80211_i.h	2009-11-20 11:43:00.000000000 +0100
@@ -140,7 +140,6 @@ typedef unsigned __bitwise__ ieee80211_t
 
 struct ieee80211_tx_data {
 	struct sk_buff *skb;
-	struct net_device *dev;
 	struct ieee80211_local *local;
 	struct ieee80211_sub_if_data *sdata;
 	struct sta_info *sta;
@@ -433,6 +432,8 @@ struct ieee80211_sub_if_data {
 
 	int drop_unencrypted;
 
+	char name[IFNAMSIZ];
+
 	/*
 	 * keep track of whether the HT opmode (stored in
 	 * vif.bss_info.ht_operation_mode) is valid.
@@ -937,6 +938,8 @@ void ieee80211_rx_bss_put(struct ieee802
 			  struct ieee80211_bss *bss);
 
 /* interface handling */
+int ieee80211_iface_init(void);
+void ieee80211_iface_exit(void);
 int ieee80211_if_add(struct ieee80211_local *local, const char *name,
 		     struct net_device **new_dev, enum nl80211_iftype type,
 		     struct vif_params *params);
--- wireless-testing.orig/net/mac80211/debugfs_sta.c	2009-11-20 11:41:40.000000000 +0100
+++ wireless-testing/net/mac80211/debugfs_sta.c	2009-11-20 11:43:00.000000000 +0100
@@ -44,7 +44,7 @@ static const struct file_operations sta_
 		STA_OPS(name)
 
 STA_FILE(aid, sta.aid, D);
-STA_FILE(dev, sdata->dev->name, S);
+STA_FILE(dev, sdata->name, S);
 STA_FILE(rx_packets, rx_packets, LU);
 STA_FILE(tx_packets, tx_packets, LU);
 STA_FILE(rx_bytes, rx_bytes, LU);
--- wireless-testing.orig/net/mac80211/debugfs_key.c	2009-11-20 11:41:40.000000000 +0100
+++ wireless-testing/net/mac80211/debugfs_key.c	2009-11-20 11:43:00.000000000 +0100
@@ -56,7 +56,7 @@ KEY_CONF_FILE(keyidx, D);
 KEY_CONF_FILE(hw_key_idx, D);
 KEY_FILE(flags, X);
 KEY_FILE(tx_rx_count, D);
-KEY_READ(ifindex, sdata->dev->ifindex, 20, "%d\n");
+KEY_READ(ifindex, sdata->name, IFNAMSIZ + 2, "%s\n");
 KEY_OPS(ifindex);
 
 static ssize_t key_algorithm_read(struct file *file,
--- wireless-testing.orig/net/mac80211/cfg.c	2009-11-20 11:42:57.000000000 +0100
+++ wireless-testing/net/mac80211/cfg.c	2009-11-20 11:43:00.000000000 +0100
@@ -729,7 +729,7 @@ static int ieee80211_add_station(struct 
 	} else
 		sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
-	if (compare_ether_addr(mac, dev->dev_addr) == 0)
+	if (compare_ether_addr(mac, sdata->vif.addr) == 0)
 		return -EINVAL;
 
 	if (is_multicast_ether_addr(mac))
--- wireless-testing.orig/net/mac80211/pm.c	2009-11-20 11:41:41.000000000 +0100
+++ wireless-testing/net/mac80211/pm.c	2009-11-20 11:43:00.000000000 +0100
@@ -102,7 +102,7 @@ int __ieee80211_suspend(struct ieee80211
 
 		conf.vif = &sdata->vif;
 		conf.type = sdata->vif.type;
-		conf.mac_addr = sdata->dev->dev_addr;
+		conf.mac_addr = sdata->vif.addr;
 		drv_remove_interface(local, &conf);
 	}
 



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

* [PATCH v3 4/5] mac80211: make station management completely depend on vif
  2009-11-25 16:46 ` [PATCH v2 4/5] mac80211: make station management completely depend on vif Johannes Berg
@ 2009-11-25 19:27   ` Johannes Berg
  2009-12-01  9:51     ` Johannes Berg
  0 siblings, 1 reply; 12+ messages in thread
From: Johannes Berg @ 2009-11-25 19:27 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless

The station management currently uses the virtual
interface, but you cannot add the same station to
multiple virtual interfaces if you're communicating
with it in multiple ways.

This restriction should be lifted so that in the
future we can, for instance, support bluetooth 3
with an access point that mac80211 is already
associated to.

We can do that by requiring all sta_info_get users
to provide the virtual interface and making the RX
code aware that an address may match more than one
station struct. Thanks to the previous patches this
one isn't all that large and except for the RX and
TX status paths changes has low complexity.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
v2: add missing sta_info_get()
v3: diff against the right tree

 net/mac80211/agg-rx.c     |    3 -
 net/mac80211/agg-tx.c     |    4 -
 net/mac80211/cfg.c        |   25 +++------
 net/mac80211/ibss.c       |    2 
 net/mac80211/key.c        |    2 
 net/mac80211/mesh_hwmp.c  |    2 
 net/mac80211/mesh_plink.c |    4 -
 net/mac80211/mlme.c       |   10 +--
 net/mac80211/rx.c         |  119 ++++++++++++++++++++++++----------------------
 net/mac80211/sta_info.c   |   18 ++++--
 net/mac80211/sta_info.h   |   29 ++++++++++-
 net/mac80211/status.c     |    8 +--
 net/mac80211/tx.c         |    9 +--
 13 files changed, 134 insertions(+), 101 deletions(-)

--- wireless-testing.orig/net/mac80211/sta_info.h	2009-11-25 20:24:18.000000000 +0100
+++ wireless-testing/net/mac80211/sta_info.h	2009-11-25 20:26:34.000000000 +0100
@@ -403,9 +403,34 @@ static inline u32 get_sta_flags(struct s
 #define STA_INFO_CLEANUP_INTERVAL (10 * HZ)
 
 /*
- * Get a STA info, must have be under RCU read lock.
+ * Get a STA info, must be under RCU read lock.
  */
-struct sta_info *sta_info_get(struct ieee80211_local *local, const u8 *addr);
+struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,
+			      const u8 *addr);
+
+static inline
+void for_each_sta_info_type_check(struct ieee80211_local *local,
+				  const u8 *addr,
+				  struct sta_info *sta,
+				  struct sta_info *nxt)
+{
+}
+
+#define for_each_sta_info(local, _addr, sta, nxt) 			\
+	for (	/* initialise loop */					\
+		sta = rcu_dereference(local->sta_hash[STA_HASH(_addr)]),\
+		nxt = sta ? rcu_dereference(sta->hnext) : NULL;		\
+		/* typecheck */						\
+		for_each_sta_info_type_check(local, (_addr), sta, nxt),	\
+		/* continue condition */				\
+		sta;							\
+		/* advance loop */					\
+		sta = nxt,						\
+		nxt = sta ? rcu_dereference(sta->hnext) : NULL		\
+	     )								\
+	/* compare address and run code only if it matches */		\
+	if (memcmp(sta->sta.addr, (_addr), ETH_ALEN) == 0)
+
 /*
  * Get STA info by index, BROKEN!
  */
--- wireless-testing.orig/net/mac80211/sta_info.c	2009-11-25 20:24:18.000000000 +0100
+++ wireless-testing/net/mac80211/sta_info.c	2009-11-25 20:26:34.000000000 +0100
@@ -103,13 +103,16 @@ static int sta_info_hash_del(struct ieee
 }
 
 /* protected by RCU */
-struct sta_info *sta_info_get(struct ieee80211_local *local, const u8 *addr)
+struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,
+			      const u8 *addr)
 {
+	struct ieee80211_local *local = sdata->local;
 	struct sta_info *sta;
 
 	sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]);
 	while (sta) {
-		if (memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)
+		if (sta->sdata == sdata &&
+		    memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)
 			break;
 		sta = rcu_dereference(sta->hnext);
 	}
@@ -377,7 +380,7 @@ int sta_info_insert(struct sta_info *sta
 
 	spin_lock_irqsave(&local->sta_lock, flags);
 	/* check if STA exists already */
-	if (sta_info_get(local, sta->sta.addr)) {
+	if (sta_info_get(sdata, sta->sta.addr)) {
 		spin_unlock_irqrestore(&local->sta_lock, flags);
 		err = -EEXIST;
 		goto out_free;
@@ -843,11 +846,12 @@ void ieee80211_sta_expire(struct ieee802
 struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw,
 					       const u8 *addr)
 {
-	struct sta_info *sta = sta_info_get(hw_to_local(hw), addr);
+	struct sta_info *sta, *nxt;
 
-	if (!sta)
-		return NULL;
-	return &sta->sta;
+	/* Just return a random station ... first in list ... */
+	for_each_sta_info(hw_to_local(hw), addr, sta, nxt)
+		return &sta->sta;
+	return NULL;
 }
 EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_hw);
 
--- wireless-testing.orig/net/mac80211/ibss.c	2009-11-25 20:24:19.000000000 +0100
+++ wireless-testing/net/mac80211/ibss.c	2009-11-25 20:26:34.000000000 +0100
@@ -252,7 +252,7 @@ static void ieee80211_rx_bss_info(struct
 
 		rcu_read_lock();
 
-		sta = sta_info_get(local, mgmt->sa);
+		sta = sta_info_get(sdata, mgmt->sa);
 		if (sta) {
 			u32 prev_rates;
 
--- wireless-testing.orig/net/mac80211/key.c	2009-11-25 20:24:19.000000000 +0100
+++ wireless-testing/net/mac80211/key.c	2009-11-25 20:26:34.000000000 +0100
@@ -421,7 +421,7 @@ void ieee80211_key_link(struct ieee80211
 			 */
 
 			/* same here, the AP could be using QoS */
-			ap = sta_info_get(key->local, key->sdata->u.mgd.bssid);
+			ap = sta_info_get(key->sdata, key->sdata->u.mgd.bssid);
 			if (ap) {
 				if (test_sta_flags(ap, WLAN_STA_WME))
 					key->conf.flags |=
--- wireless-testing.orig/net/mac80211/mesh_hwmp.c	2009-11-25 20:24:19.000000000 +0100
+++ wireless-testing/net/mac80211/mesh_hwmp.c	2009-11-25 20:26:34.000000000 +0100
@@ -335,7 +335,7 @@ static u32 hwmp_route_info_get(struct ie
 	bool process = true;
 
 	rcu_read_lock();
-	sta = sta_info_get(local, mgmt->sa);
+	sta = sta_info_get(sdata, mgmt->sa);
 	if (!sta) {
 		rcu_read_unlock();
 		return 0;
--- wireless-testing.orig/net/mac80211/mesh_plink.c	2009-11-25 20:24:18.000000000 +0100
+++ wireless-testing/net/mac80211/mesh_plink.c	2009-11-25 20:26:34.000000000 +0100
@@ -234,7 +234,7 @@ void mesh_neighbour_update(u8 *hw_addr, 
 
 	rcu_read_lock();
 
-	sta = sta_info_get(local, hw_addr);
+	sta = sta_info_get(sdata, hw_addr);
 	if (!sta) {
 		sta = mesh_plink_alloc(sdata, hw_addr, rates);
 		if (!sta) {
@@ -455,7 +455,7 @@ void mesh_rx_plink_frame(struct ieee8021
 
 	rcu_read_lock();
 
-	sta = sta_info_get(local, mgmt->sa);
+	sta = sta_info_get(sdata, mgmt->sa);
 	if (!sta && ftype != PLINK_OPEN) {
 		mpl_dbg("Mesh plink: cls or cnf from unknown peer\n");
 		rcu_read_unlock();
--- wireless-testing.orig/net/mac80211/mlme.c	2009-11-25 20:24:21.000000000 +0100
+++ wireless-testing/net/mac80211/mlme.c	2009-11-25 20:26:34.000000000 +0100
@@ -202,7 +202,7 @@ static u32 ieee80211_enable_ht(struct ie
 		ieee80211_hw_config(local, 0);
 
 		rcu_read_lock();
-		sta = sta_info_get(local, bssid);
+		sta = sta_info_get(sdata, bssid);
 		if (sta)
 			rate_control_rate_update(local, sband, sta,
 						 IEEE80211_RC_HT_CHANGED);
@@ -1070,7 +1070,7 @@ static void ieee80211_set_disassoc(struc
 	netif_carrier_off(sdata->dev);
 
 	rcu_read_lock();
-	sta = sta_info_get(local, bssid);
+	sta = sta_info_get(sdata, bssid);
 	if (sta)
 		ieee80211_sta_tear_down_BA_sessions(sta);
 	rcu_read_unlock();
@@ -1109,7 +1109,7 @@ static void ieee80211_set_disassoc(struc
 
 	rcu_read_lock();
 
-	sta = sta_info_get(local, bssid);
+	sta = sta_info_get(sdata, bssid);
 	if (!sta) {
 		rcu_read_unlock();
 		return;
@@ -1489,7 +1489,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee
 	rcu_read_lock();
 
 	/* Add STA entry for the AP */
-	sta = sta_info_get(local, wk->bss->cbss.bssid);
+	sta = sta_info_get(sdata, wk->bss->cbss.bssid);
 	if (!sta) {
 		newsta = true;
 
@@ -1857,7 +1857,7 @@ static void ieee80211_rx_mgmt_beacon(str
 
 		rcu_read_lock();
 
-		sta = sta_info_get(local, bssid);
+		sta = sta_info_get(sdata, bssid);
 		if (WARN_ON(!sta)) {
 			rcu_read_unlock();
 			return;
--- wireless-testing.orig/net/mac80211/rx.c	2009-11-25 20:25:23.000000000 +0100
+++ wireless-testing/net/mac80211/rx.c	2009-11-25 20:26:34.000000000 +0100
@@ -1472,7 +1472,6 @@ ieee80211_deliver_skb(struct ieee80211_r
 {
 	struct ieee80211_sub_if_data *sdata = rx->sdata;
 	struct net_device *dev = sdata->dev;
-	struct ieee80211_local *local = rx->local;
 	struct sk_buff *skb, *xmit_skb;
 	struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data;
 	struct sta_info *dsta;
@@ -1495,8 +1494,8 @@ ieee80211_deliver_skb(struct ieee80211_r
 				printk(KERN_DEBUG "%s: failed to clone "
 				       "multicast frame\n", dev->name);
 		} else {
-			dsta = sta_info_get(local, skb->data);
-			if (dsta && dsta->sdata->dev == dev) {
+			dsta = sta_info_get(sdata, skb->data);
+			if (dsta) {
 				/*
 				 * The destination station is associated to
 				 * this AP (in this VLAN), so send the frame
@@ -2363,6 +2362,8 @@ static void __ieee80211_rx_handle_packet
 	int prepares;
 	struct ieee80211_sub_if_data *prev = NULL;
 	struct sk_buff *skb_new;
+	struct sta_info *sta, *tmp;
+	bool found_sta = false;
 
 	hdr = (struct ieee80211_hdr *)skb->data;
 	memset(&rx, 0, sizeof(rx));
@@ -2379,68 +2380,76 @@ static void __ieee80211_rx_handle_packet
 	ieee80211_parse_qos(&rx);
 	ieee80211_verify_alignment(&rx);
 
-	rx.sta = sta_info_get(local, hdr->addr2);
-	if (rx.sta)
-		rx.sdata = rx.sta->sdata;
-
-	if (rx.sdata && ieee80211_is_data(hdr->frame_control)) {
-		rx.flags |= IEEE80211_RX_RA_MATCH;
-		prepares = prepare_for_handlers(rx.sdata, &rx, hdr);
-		if (prepares) {
-			if (status->flag & RX_FLAG_MMIC_ERROR) {
-				if (rx.flags & IEEE80211_RX_RA_MATCH)
-					ieee80211_rx_michael_mic_report(hdr, &rx);
-			} else
-				prev = rx.sdata;
+	if (ieee80211_is_data(hdr->frame_control)) {
+		for_each_sta_info(local, hdr->addr2, sta, tmp) {
+			rx.sta = sta;
+			found_sta = true;
+			rx.sdata = sta->sdata;
+
+			rx.flags |= IEEE80211_RX_RA_MATCH;
+			prepares = prepare_for_handlers(rx.sdata, &rx, hdr);
+			if (prepares) {
+				if (status->flag & RX_FLAG_MMIC_ERROR) {
+					if (rx.flags & IEEE80211_RX_RA_MATCH)
+						ieee80211_rx_michael_mic_report(hdr, &rx);
+				} else
+					prev = rx.sdata;
+			}
 		}
-	} else list_for_each_entry_rcu(sdata, &local->interfaces, list) {
-		if (!netif_running(sdata->dev))
-			continue;
+	}
+	if (!found_sta) {
+		list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+			if (!netif_running(sdata->dev))
+				continue;
+
+			if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
+			    sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+				continue;
 
-		if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
-		    sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
-			continue;
+			rx.sta = sta_info_get(sdata, hdr->addr2);
 
-		rx.flags |= IEEE80211_RX_RA_MATCH;
-		prepares = prepare_for_handlers(sdata, &rx, hdr);
+			rx.flags |= IEEE80211_RX_RA_MATCH;
+			prepares = prepare_for_handlers(sdata, &rx, hdr);
 
-		if (!prepares)
-			continue;
+			if (!prepares)
+				continue;
 
-		if (status->flag & RX_FLAG_MMIC_ERROR) {
-			rx.sdata = sdata;
-			if (rx.flags & IEEE80211_RX_RA_MATCH)
-				ieee80211_rx_michael_mic_report(hdr, &rx);
-			continue;
-		}
+			if (status->flag & RX_FLAG_MMIC_ERROR) {
+				rx.sdata = sdata;
+				if (rx.flags & IEEE80211_RX_RA_MATCH)
+					ieee80211_rx_michael_mic_report(hdr,
+									&rx);
+				continue;
+			}
 
-		/*
-		 * frame is destined for this interface, but if it's not
-		 * also for the previous one we handle that after the
-		 * loop to avoid copying the SKB once too much
-		 */
+			/*
+			 * frame is destined for this interface, but if it's
+			 * not also for the previous one we handle that after
+			 * the loop to avoid copying the SKB once too much
+			 */
 
-		if (!prev) {
-			prev = sdata;
-			continue;
-		}
+			if (!prev) {
+				prev = sdata;
+				continue;
+			}
 
-		/*
-		 * frame was destined for the previous interface
-		 * so invoke RX handlers for it
-		 */
+			/*
+			 * frame was destined for the previous interface
+			 * so invoke RX handlers for it
+			 */
 
-		skb_new = skb_copy(skb, GFP_ATOMIC);
-		if (!skb_new) {
-			if (net_ratelimit())
-				printk(KERN_DEBUG "%s: failed to copy "
-				       "multicast frame for %s\n",
-				       wiphy_name(local->hw.wiphy),
-				       prev->dev->name);
-			continue;
+			skb_new = skb_copy(skb, GFP_ATOMIC);
+			if (!skb_new) {
+				if (net_ratelimit())
+					printk(KERN_DEBUG "%s: failed to copy "
+					       "multicast frame for %s\n",
+					       wiphy_name(local->hw.wiphy),
+					       prev->dev->name);
+				continue;
+			}
+			ieee80211_invoke_rx_handlers(prev, &rx, skb_new, rate);
+			prev = sdata;
 		}
-		ieee80211_invoke_rx_handlers(prev, &rx, skb_new, rate);
-		prev = sdata;
 	}
 	if (prev)
 		ieee80211_invoke_rx_handlers(prev, &rx, skb, rate);
--- wireless-testing.orig/net/mac80211/agg-tx.c	2009-11-25 20:24:22.000000000 +0100
+++ wireless-testing/net/mac80211/agg-tx.c	2009-11-25 20:26:34.000000000 +0100
@@ -437,7 +437,7 @@ void ieee80211_start_tx_ba_cb(struct iee
 	}
 
 	rcu_read_lock();
-	sta = sta_info_get(local, ra);
+	sta = sta_info_get(sdata, ra);
 	if (!sta) {
 		rcu_read_unlock();
 #ifdef CONFIG_MAC80211_HT_DEBUG
@@ -565,7 +565,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee
 #endif /* CONFIG_MAC80211_HT_DEBUG */
 
 	rcu_read_lock();
-	sta = sta_info_get(local, ra);
+	sta = sta_info_get(sdata, ra);
 	if (!sta) {
 #ifdef CONFIG_MAC80211_HT_DEBUG
 		printk(KERN_DEBUG "Could not find station: %pM\n", ra);
--- wireless-testing.orig/net/mac80211/agg-rx.c	2009-11-25 20:24:22.000000000 +0100
+++ wireless-testing/net/mac80211/agg-rx.c	2009-11-25 20:26:34.000000000 +0100
@@ -83,7 +83,6 @@ void __ieee80211_stop_rx_ba_session(stru
 void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid,
 					u16 initiator, u16 reason)
 {
-	struct ieee80211_local *local = sdata->local;
 	struct sta_info *sta;
 
 	/* stop HW Rx aggregation. ampdu_action existence
@@ -92,7 +91,7 @@ void ieee80211_sta_stop_rx_ba_session(st
 
 	rcu_read_lock();
 
-	sta = sta_info_get(local, ra);
+	sta = sta_info_get(sdata, ra);
 	if (!sta) {
 		rcu_read_unlock();
 		return;
--- wireless-testing.orig/net/mac80211/cfg.c	2009-11-25 20:24:21.000000000 +0100
+++ wireless-testing/net/mac80211/cfg.c	2009-11-25 20:26:34.000000000 +0100
@@ -150,7 +150,7 @@ static int ieee80211_add_key(struct wiph
 	rcu_read_lock();
 
 	if (mac_addr) {
-		sta = sta_info_get(sdata->local, mac_addr);
+		sta = sta_info_get(sdata, mac_addr);
 		if (!sta) {
 			ieee80211_key_free(key);
 			err = -ENOENT;
@@ -181,7 +181,7 @@ static int ieee80211_del_key(struct wiph
 	if (mac_addr) {
 		ret = -ENOENT;
 
-		sta = sta_info_get(sdata->local, mac_addr);
+		sta = sta_info_get(sdata, mac_addr);
 		if (!sta)
 			goto out_unlock;
 
@@ -228,7 +228,7 @@ static int ieee80211_get_key(struct wiph
 	rcu_read_lock();
 
 	if (mac_addr) {
-		sta = sta_info_get(sdata->local, mac_addr);
+		sta = sta_info_get(sdata, mac_addr);
 		if (!sta)
 			goto out;
 
@@ -414,15 +414,13 @@ static int ieee80211_dump_station(struct
 static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev,
 				 u8 *mac, struct station_info *sinfo)
 {
-	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	struct sta_info *sta;
 	int ret = -ENOENT;
 
 	rcu_read_lock();
 
-	/* XXX: verify sta->dev == dev */
-
-	sta = sta_info_get(local, mac);
+	sta = sta_info_get(sdata, mac);
 	if (sta) {
 		ret = 0;
 		sta_set_sinfo(sta, sinfo);
@@ -778,8 +776,7 @@ static int ieee80211_del_station(struct 
 	if (mac) {
 		rcu_read_lock();
 
-		/* XXX: get sta belonging to dev */
-		sta = sta_info_get(local, mac);
+		sta = sta_info_get(sdata, mac);
 		if (!sta) {
 			rcu_read_unlock();
 			return -ENOENT;
@@ -800,14 +797,14 @@ static int ieee80211_change_station(stru
 				    u8 *mac,
 				    struct station_parameters *params)
 {
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	struct ieee80211_local *local = wiphy_priv(wiphy);
 	struct sta_info *sta;
 	struct ieee80211_sub_if_data *vlansdata;
 
 	rcu_read_lock();
 
-	/* XXX: get sta belonging to dev */
-	sta = sta_info_get(local, mac);
+	sta = sta_info_get(sdata, mac);
 	if (!sta) {
 		rcu_read_unlock();
 		return -ENOENT;
@@ -846,7 +843,6 @@ static int ieee80211_change_station(stru
 static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev,
 				 u8 *dst, u8 *next_hop)
 {
-	struct ieee80211_local *local = wiphy_priv(wiphy);
 	struct ieee80211_sub_if_data *sdata;
 	struct mesh_path *mpath;
 	struct sta_info *sta;
@@ -855,7 +851,7 @@ static int ieee80211_add_mpath(struct wi
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
 	rcu_read_lock();
-	sta = sta_info_get(local, next_hop);
+	sta = sta_info_get(sdata, next_hop);
 	if (!sta) {
 		rcu_read_unlock();
 		return -ENOENT;
@@ -894,7 +890,6 @@ static int ieee80211_change_mpath(struct
 				    struct net_device *dev,
 				    u8 *dst, u8 *next_hop)
 {
-	struct ieee80211_local *local = wiphy_priv(wiphy);
 	struct ieee80211_sub_if_data *sdata;
 	struct mesh_path *mpath;
 	struct sta_info *sta;
@@ -903,7 +898,7 @@ static int ieee80211_change_mpath(struct
 
 	rcu_read_lock();
 
-	sta = sta_info_get(local, next_hop);
+	sta = sta_info_get(sdata, next_hop);
 	if (!sta) {
 		rcu_read_unlock();
 		return -ENOENT;
--- wireless-testing.orig/net/mac80211/tx.c	2009-11-25 20:24:18.000000000 +0100
+++ wireless-testing/net/mac80211/tx.c	2009-11-25 20:26:34.000000000 +0100
@@ -1054,7 +1054,7 @@ ieee80211_tx_prepare(struct ieee80211_su
 	if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
 		tx->sta = rcu_dereference(sdata->u.vlan.sta);
 	if (!tx->sta)
-		tx->sta = sta_info_get(local, hdr->addr1);
+		tx->sta = sta_info_get(sdata, hdr->addr1);
 
 	if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) &&
 	    (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION)) {
@@ -1760,9 +1760,8 @@ netdev_tx_t ieee80211_subif_start_xmit(s
 	 */
 	if (!is_multicast_ether_addr(hdr.addr1)) {
 		rcu_read_lock();
-		sta = sta_info_get(local, hdr.addr1);
-		/* XXX: in the future, use sdata to look up the sta */
-		if (sta && sta->sdata == sdata)
+		sta = sta_info_get(sdata, hdr.addr1);
+		if (sta)
 			sta_flags = get_sta_flags(sta);
 		rcu_read_unlock();
 	}
@@ -1921,7 +1920,7 @@ static bool ieee80211_tx_pending_skb(str
 		ieee80211_tx(sdata, skb, true);
 	} else {
 		hdr = (struct ieee80211_hdr *)skb->data;
-		sta = sta_info_get(local, hdr->addr1);
+		sta = sta_info_get(sdata, hdr->addr1);
 
 		ret = __ieee80211_tx(local, &skb, sta, true);
 		if (ret != IEEE80211_TX_OK)
--- wireless-testing.orig/net/mac80211/status.c	2009-11-25 20:24:21.000000000 +0100
+++ wireless-testing/net/mac80211/status.c	2009-11-25 20:26:34.000000000 +0100
@@ -146,7 +146,7 @@ void ieee80211_tx_status(struct ieee8021
 	struct ieee80211_tx_status_rtap_hdr *rthdr;
 	struct ieee80211_sub_if_data *sdata;
 	struct net_device *prev_dev = NULL;
-	struct sta_info *sta;
+	struct sta_info *sta, *tmp;
 	int retry_count = -1, i;
 
 	for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
@@ -165,9 +165,11 @@ void ieee80211_tx_status(struct ieee8021
 
 	sband = local->hw.wiphy->bands[info->band];
 
-	sta = sta_info_get(local, hdr->addr1);
+	for_each_sta_info(local, hdr->addr1, sta, tmp) {
+		/* skip wrong virtual interface */
+		if (memcmp(hdr->addr2, sta->sdata->dev->dev_addr, ETH_ALEN))
+			continue;
 
-	if (sta) {
 		if (!(info->flags & IEEE80211_TX_STAT_ACK) &&
 		    test_sta_flags(sta, WLAN_STA_PS_STA)) {
 			/*



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

* Re: [PATCH v3 4/5] mac80211: make station management completely depend on vif
  2009-11-25 19:27   ` [PATCH v3 " Johannes Berg
@ 2009-12-01  9:51     ` Johannes Berg
  0 siblings, 0 replies; 12+ messages in thread
From: Johannes Berg @ 2009-12-01  9:51 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless

[-- Attachment #1: Type: text/plain, Size: 324 bytes --]

On Wed, 2009-11-25 at 20:27 +0100, Johannes Berg wrote:
...
> Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
> ---
> v2: add missing sta_info_get()
> v3: diff against the right tree

FWIW, the wrong tree here was with the security fix included, so you'll
now want to pick up v2 instead again.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH v2 3/5] mac80211: correctly place aMPDU RX reorder code
  2009-11-25 16:46 ` [PATCH v2 3/5] mac80211: correctly place " Johannes Berg
@ 2009-12-03 18:13   ` reinette chatre
  2009-12-03 18:52     ` Johannes Berg
  2009-12-03 19:14     ` Johannes Berg
  0 siblings, 2 replies; 12+ messages in thread
From: reinette chatre @ 2009-12-03 18:13 UTC (permalink / raw)
  To: Johannes Berg; +Cc: John Linville, linux-wireless

Hi Johannes,

On Wed, 2009-11-25 at 08:46 -0800, Johannes Berg wrote:
> As indicated by the comment, the aMPDU RX reorder code
> should logically be after ieee80211_rx_h_check(). The
> previous patch moved the code there, and this patch now
> hooks it up in that place by introducing a list of skbs
> that are then processed by the remaining handlers. The
> list may be empty if the function is buffering the skb
> to release it later.
> 
> The only change needed to the RX data is that the crypto
> handler needs to clear the key that may be set from a
> previous loop iteration, and that not everything can be
> in the rx flags now.
> 
> Signed-off-by: Johannes Berg <johannes@sipsolutions.net>

I bisected a hang problem to this patch. When associating to an 11n AP
(tested on 5GHz), ping works fine, but trying to copy a large file
causes the system to freeze (keyboard lights start blinking and system
unresponsive. Reverting this patch I can copy large files successfully.

This is also described in
http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=2126.

Here is the panic:

[  729.671546] BUG: unable to handle kernel NULL pointer dereference at (null)
[  729.671656] IP: [<ffffffff81074b89>] __bfs+0xc9/0x270
[  729.671729] PGD 0 
[  729.671796] Oops: 0000 [#1] SMP 
[  729.671900] last sysfs file: /sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0A:00/power_supply/BAT0/energy_full
[  729.671939] CPU 0 
[  729.672008] Modules linked in: iwlagn iwlcore mac80211 cfg80211 i915 drm_kms_helper drm i2c_algo_bit i2c_core ipv6 acpi_cpufreq cpufreq_userspace cpufreq_powersave cpufreq_ondemand cpufreq_conservative cpufreq_stats freq_table container sbs sbshc pcmcia joydev arc4 ecb af_packet yenta_socket psmouse rsrc_nonstatic evdev pcspkr serio_raw pcmcia_core iTCO_wdt iTCO_vendor_support intel_agp button battery sony_laptop rfkill tpm_infineon tpm tpm_bios video output ac processor ext3 jbd mbcache sg sr_mod cdrom sd_mod ahci libata scsi_mod ehci_hcd uhci_hcd usbcore thermal fan thermal_sys [last unloaded: cfg80211]
[  729.672010] Pid: 14639, comm: ssh Not tainted 2.6.32-rc8-wl-60817-gc1f4e0e #96 VGN-Z540N
[  729.672010] RIP: 0010:[<ffffffff81074b89>]  [<ffffffff81074b89>] __bfs+0xc9/0x270
[  729.672010] RSP: 0018:ffff8800020036e0  EFLAGS: 00010002
[  729.672010] RAX: ffffffff81af3f30 RBX: ffffffff81af3f20 RCX: ffff880002003760
[  729.672010] RDX: ffff880002003708 RSI: 0000000000000006 RDI: ffff880002003760
[  729.672010] RBP: ffff880002003740 R08: 0000000000000001 R09: 0000000000000000
[  729.672010] R10: ffff8800955f86b0 R11: 0000000000000000 R12: 0000000000000006
[  729.672010] R13: ffffffff81073810 R14: ffff8800020037a8 R15: 0000000000000000
[  729.672010] FS:  00007fdf4f7d3710(0000) GS:ffff880002000000(0000) knlGS:0000000000000000
[  729.672010] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  729.672010] CR2: 0000000000000000 CR3: 0000000079ff7000 CR4: 00000000000006f0
[  729.672010] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[  729.672010] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
[  729.672010] Process ssh (pid: 14639, threadinfo ffff88005a630000, task ffff8800955f8000)
[  729.672010] Stack:
[  729.672010]  000000000000b520 ffffffff813624c0 ffff88005a631d50 ffffffff00000001
[  729.672010] <0> ffff880002003790 ffff880002003760 ffff88000200375c ffff880002003760
[  729.672010] <0> ffff8800955f86b0 ffffffff814811cd ffff8800955f8000 ffffffff8107a6c0
[  729.672010] Call Trace:
[  729.672010]  <IRQ> 
[  729.672010]  [<ffffffff8107a6c0>] ? check_usage_forwards+0x0/0x110
[  729.672010]  [<ffffffff8107a741>] check_usage_forwards+0x81/0x110
[  729.672010]  [<ffffffff81076210>] mark_lock+0x200/0x640
[  729.672010]  [<ffffffff8107824f>] __lock_acquire+0xabf/0x1d30
[  729.672010]  [<ffffffff8107955b>] lock_acquire+0x9b/0x120
[  729.672010]  [<ffffffff812aff1b>] ? skb_queue_tail+0x2b/0x60
[  729.672010]  [<ffffffff813593a1>] _spin_lock_irqsave+0x41/0x60
[  729.672010]  [<ffffffff812aff1b>] ? skb_queue_tail+0x2b/0x60
[  729.672010]  [<ffffffff81359130>] ? _spin_unlock_irqrestore+0x40/0x60
[  729.672010]  [<ffffffff812aff1b>] skb_queue_tail+0x2b/0x60
[  729.672010]  [<ffffffffa04b11f5>] ieee80211_release_reorder_frame+0x35/0x50 [mac80211]
[  729.672010]  [<ffffffffa04b2f0c>] ieee80211_invoke_rx_handlers+0xb8c/0x1990 [mac80211]
[  729.672010]  [<ffffffff810766bc>] ? mark_held_locks+0x6c/0xa0
[  729.672010]  [<ffffffff81358f30>] ? _write_unlock_irqrestore+0x40/0x60
[  729.672010]  [<ffffffff810768bb>] ? trace_hardirqs_on_caller+0x6b/0x190
[  729.672010]  [<ffffffff810769ed>] ? trace_hardirqs_on+0xd/0x10
[  729.672010]  [<ffffffffa04b3db6>] ? ieee80211_rx+0xa6/0x8f0 [mac80211]
[  729.672010]  [<ffffffffa04b3fef>] ieee80211_rx+0x2df/0x8f0 [mac80211]
[  729.672010]  [<ffffffffa04b3db6>] ? ieee80211_rx+0xa6/0x8f0 [mac80211]
[  729.672010]  [<ffffffff812af1c7>] ? skb_copy_bits+0x167/0x2b0
[  729.672010]  [<ffffffffa04fd2f1>] iwl_rx_reply_rx+0x571/0xee0 [iwlcore]
[  729.672010]  [<ffffffff8100efb5>] ? dump_trace+0x105/0x2c0
[  729.672010]  [<ffffffff811dceb9>] ? debug_dma_unmap_page+0x59/0x60
[  729.672010]  [<ffffffffa0557e89>] iwl_rx_handle+0x149/0x670 [iwlagn]
[  729.672010]  [<ffffffff810766bc>] ? mark_held_locks+0x6c/0xa0
[  729.672010]  [<ffffffffa0559afc>] iwl_irq_tasklet+0x2ec/0x1320 [iwlagn]
[  729.672010]  [<ffffffff810766bc>] ? mark_held_locks+0x6c/0xa0
[  729.672010]  [<ffffffff8104b1d9>] ? tasklet_action+0x49/0xe0
[  729.672010]  [<ffffffff8104b260>] tasklet_action+0xd0/0xe0
[  729.672010]  [<ffffffff8104c78b>] __do_softirq+0xcb/0x200
[  729.672010]  [<ffffffff8100d09c>] call_softirq+0x1c/0x50
[  729.672010]  [<ffffffff8100e80d>] do_softirq+0x7d/0xb0
[  729.672010]  [<ffffffff8104c2c5>] irq_exit+0x95/0xa0
[  729.672010]  [<ffffffff8135e485>] do_IRQ+0x75/0xf0
[  729.672010]  [<ffffffff8100c893>] ret_from_intr+0x0/0xf
[  729.672010]  <EOI> 
[  729.672010]  [<ffffffff8102eccd>] ? flush_tlb_page+0x7d/0x90
[  729.672010]  [<ffffffff8102ec98>] ? flush_tlb_page+0x48/0x90
[  729.672010]  [<ffffffff810f508d>] ? move_page_tables+0x2cd/0x4c0
[  729.672010]  [<ffffffff810f5133>] ? move_page_tables+0x373/0x4c0
[  729.672010]  [<ffffffff810f5879>] ? do_mremap+0x5f9/0x7a0
[  729.672010]  [<ffffffff810f5a7f>] ? sys_mremap+0x5f/0x90
[  729.672010]  [<ffffffff8100bedb>] ? system_call_fastpath+0x16/0x1b
[  729.672010] Code: 0a 89 05 bb f5 da 00 48 8b 41 10 48 85 c0 0f 84 2e 01 00 00 48 8d 98 70 01 00 00 48 05 80 01 00 00 45 85 c0 48 0f 44 d8 4c 8b 3b <49> 8b 07 49 39 df 0f 18 08 74 a4 4c 89 f8 48 2d c0 c2 76 81 48 
[  729.672010] RIP  [<ffffffff81074b89>] __bfs+0xc9/0x270
[  729.672010]  RSP <ffff8800020036e0>
[  729.672010] CR2: 0000000000000000
[  729.672010] ---[ end trace 73a47421077c9586 ]---
[  729.672010] Kernel panic - not syncing: Fatal exception in interrupt
[  729.672010] Pid: 14639, comm: ssh Tainted: G      D    2.6.32-rc8-wl-60817-gc1f4e0e #96
[  729.672010] Call Trace:
[  729.672010]  <IRQ>  [<ffffffff81355ad6>] panic+0x78/0x136
[  729.672010]  [<ffffffff8135a752>] oops_end+0xe2/0xf0
[  729.672010]  [<ffffffff8102aab2>] no_context+0xf2/0x260
[  729.672010]  [<ffffffff8129f7a5>] ? led_trigger_event+0x85/0x90
[  729.672010]  [<ffffffff8102ad45>] __bad_area_nosemaphore+0x125/0x1e0
[  729.672010]  [<ffffffffa04b4f47>] ? __ieee80211_tx+0x147/0x1a0 [mac80211]
[  729.672010]  [<ffffffff8102ae13>] bad_area_nosemaphore+0x13/0x20
[  729.672010]  [<ffffffff8135c174>] do_page_fault+0x2d4/0x380
[  729.672010]  [<ffffffff81073810>] ? usage_match+0x0/0x20
[  729.672010]  [<ffffffff8135994f>] page_fault+0x1f/0x30
[  729.672010]  [<ffffffff81073810>] ? usage_match+0x0/0x20
[  729.672010]  [<ffffffff81074b89>] ? __bfs+0xc9/0x270
[  729.672010]  [<ffffffff8107a6c0>] ? check_usage_forwards+0x0/0x110
[  729.672010]  [<ffffffff8107a741>] check_usage_forwards+0x81/0x110
[  729.672010]  [<ffffffff81076210>] mark_lock+0x200/0x640
[  729.672010]  [<ffffffff8107824f>] __lock_acquire+0xabf/0x1d30
[  729.672010]  [<ffffffff8107955b>] lock_acquire+0x9b/0x120
[  729.672010]  [<ffffffff812aff1b>] ? skb_queue_tail+0x2b/0x60
[  729.672010]  [<ffffffff813593a1>] _spin_lock_irqsave+0x41/0x60
[  729.672010]  [<ffffffff812aff1b>] ? skb_queue_tail+0x2b/0x60
[  729.672010]  [<ffffffff81359130>] ? _spin_unlock_irqrestore+0x40/0x60
[  729.672010]  [<ffffffff812aff1b>] skb_queue_tail+0x2b/0x60
[  729.672010]  [<ffffffffa04b11f5>] ieee80211_release_reorder_frame+0x35/0x50 [mac80211]
[  729.672010]  [<ffffffffa04b2f0c>] ieee80211_invoke_rx_handlers+0xb8c/0x1990 [mac80211]
[  729.672010]  [<ffffffff810766bc>] ? mark_held_locks+0x6c/0xa0
[  729.672010]  [<ffffffff81358f30>] ? _write_unlock_irqrestore+0x40/0x60
[  729.672010]  [<ffffffff810768bb>] ? trace_hardirqs_on_caller+0x6b/0x190
[  729.672010]  [<ffffffff810769ed>] ? trace_hardirqs_on+0xd/0x10
[  729.672010]  [<ffffffffa04b3db6>] ? ieee80211_rx+0xa6/0x8f0 [mac80211]
[  729.672010]  [<ffffffffa04b3fef>] ieee80211_rx+0x2df/0x8f0 [mac80211]
[  729.672010]  [<ffffffffa04b3db6>] ? ieee80211_rx+0xa6/0x8f0 [mac80211]
[  729.672010]  [<ffffffff812af1c7>] ? skb_copy_bits+0x167/0x2b0
[  729.672010]  [<ffffffffa04fd2f1>] iwl_rx_reply_rx+0x571/0xee0 [iwlcore]
[  729.672010]  [<ffffffff8100efb5>] ? dump_trace+0x105/0x2c0
[  729.672010]  [<ffffffff811dceb9>] ? debug_dma_unmap_page+0x59/0x60
[  729.672010]  [<ffffffffa0557e89>] iwl_rx_handle+0x149/0x670 [iwlagn]
[  729.672010]  [<ffffffff810766bc>] ? mark_held_locks+0x6c/0xa0
[  729.672010]  [<ffffffffa0559afc>] iwl_irq_tasklet+0x2ec/0x1320 [iwlagn]
[  729.672010]  [<ffffffff810766bc>] ? mark_held_locks+0x6c/0xa0
[  729.672010]  [<ffffffff8104b1d9>] ? tasklet_action+0x49/0xe0
[  729.672010]  [<ffffffff8104b260>] tasklet_action+0xd0/0xe0
[  729.672010]  [<ffffffff8104c78b>] __do_softirq+0xcb/0x200
[  729.672010]  [<ffffffff8100d09c>] call_softirq+0x1c/0x50
[  729.672010]  [<ffffffff8100e80d>] do_softirq+0x7d/0xb0
[  729.672010]  [<ffffffff8104c2c5>] irq_exit+0x95/0xa0
[  729.672010]  [<ffffffff8135e485>] do_IRQ+0x75/0xf0
[  729.672010]  [<ffffffff8100c893>] ret_from_intr+0x0/0xf
[  729.672010]  <EOI>  [<ffffffff8102eccd>] ? flush_tlb_page+0x7d/0x90
[  729.672010]  [<ffffffff8102ec98>] ? flush_tlb_page+0x48/0x90
[  729.672010]  [<ffffffff810f508d>] ? move_page_tables+0x2cd/0x4c0
[  729.672010]  [<ffffffff810f5133>] ? move_page_tables+0x373/0x4c0
[  729.672010]  [<ffffffff810f5879>] ? do_mremap+0x5f9/0x7a0
[  729.672010]  [<ffffffff810f5a7f>] ? sys_mremap+0x5f/0x90
[  729.672010]  [<ffffffff8100bedb>] ? system_call_fastpath+0x16/0x1b
[  729.682892] ------------[ cut here ]------------
[  729.682936] WARNING: at /home/rchatre/iwlwifi-2.6/arch/x86/kernel/smp.c:117 native_smp_send_reschedule+0x54/0x60()
[  729.682976] Hardware name: VGN-Z540N
[  729.683014] Modules linked in: iwlagn iwlcore mac80211 cfg80211 i915 drm_kms_helper drm i2c_algo_bit i2c_core ipv6 acpi_cpufreq cpufreq_userspace cpufreq_powersave cpufreq_ondemand cpufreq_conservative cpufreq_stats freq_table container sbs sbshc pcmcia joydev arc4 ecb af_packet yenta_socket psmouse rsrc_nonstatic evdev pcspkr serio_raw pcmcia_core iTCO_wdt iTCO_vendor_support intel_agp button battery sony_laptop rfkill tpm_infineon tpm tpm_bios video output ac processor ext3 jbd mbcache sg sr_mod cdrom sd_mod ahci libata scsi_mod ehci_hcd uhci_hcd usbcore thermal fan thermal_sys [last unloaded: cfg80211]
[  729.685583] Pid: 14639, comm: ssh Tainted: G      D    2.6.32-rc8-wl-60817-gc1f4e0e #96
[  729.685623] Call Trace:
[  729.685663]  <IRQ>  [<ffffffff81044deb>] warn_slowpath_common+0x7b/0xc0
[  729.685750]  [<ffffffff81044e44>] warn_slowpath_null+0x14/0x20
[  729.685793]  [<ffffffff810213d4>] native_smp_send_reschedule+0x54/0x60
[  729.685838]  [<ffffffff81030048>] resched_task+0x68/0x70
[  729.685882]  [<ffffffff81036ae9>] check_preempt_wakeup+0x1c9/0x240
[  729.685926]  [<ffffffff810402ff>] try_to_wake_up+0x1af/0x250
[  729.685970]  [<ffffffff810403b2>] default_wake_function+0x12/0x20
[  729.686014]  [<ffffffff810637d6>] autoremove_wake_function+0x16/0x40
[  729.686057]  [<ffffffff8102f8f9>] __wake_up_common+0x59/0x90
[  729.686100]  [<ffffffff81036088>] __wake_up+0x48/0x70
[  729.686151]  [<ffffffffa040aa91>] i915_driver_irq_handler+0x3c1/0x5b0 [i915]
[  729.686196]  [<ffffffff810a42d0>] handle_IRQ_event+0x50/0x160
[  729.686240]  [<ffffffff810a63bd>] handle_edge_irq+0xcd/0x170
[  729.686283]  [<ffffffff8100e862>] handle_irq+0x22/0x30
[  729.686327]  [<ffffffff8135e47c>] do_IRQ+0x6c/0xf0
[  729.686372]  [<ffffffff8100c893>] ret_from_intr+0x0/0xf
[  729.686417]  [<ffffffff81355b70>] ? panic+0x112/0x136
[  729.686459]  [<ffffffff81355b73>] ? panic+0x115/0x136
[  729.686502]  [<ffffffff81355b70>] ? panic+0x112/0x136
[  729.686545]  [<ffffffff8135a752>] ? oops_end+0xe2/0xf0
[  729.686589]  [<ffffffff8102aab2>] ? no_context+0xf2/0x260
[  729.686632]  [<ffffffff8129f7a5>] ? led_trigger_event+0x85/0x90
[  729.686676]  [<ffffffff8102ad45>] ? __bad_area_nosemaphore+0x125/0x1e0
[  729.686724]  [<ffffffffa04b4f47>] ? __ieee80211_tx+0x147/0x1a0 [mac80211]
[  729.686769]  [<ffffffff8102ae13>] ? bad_area_nosemaphore+0x13/0x20
[  729.686813]  [<ffffffff8135c174>] ? do_page_fault+0x2d4/0x380
[  729.686858]  [<ffffffff81073810>] ? usage_match+0x0/0x20
[  729.686884]  [<ffffffff8135994f>] ? page_fault+0x1f/0x30
[  729.686884]  [<ffffffff81073810>] ? usage_match+0x0/0x20
[  729.686884]  [<ffffffff81074b89>] ? __bfs+0xc9/0x270
[  729.686884]  [<ffffffff8107a6c0>] ? check_usage_forwards+0x0/0x110
[  729.686884]  [<ffffffff8107a741>] ? check_usage_forwards+0x81/0x110
[  729.686884]  [<ffffffff81076210>] ? mark_lock+0x200/0x640
[  729.686884]  [<ffffffff8107824f>] ? __lock_acquire+0xabf/0x1d30
[  729.686884]  [<ffffffff8107955b>] ? lock_acquire+0x9b/0x120
[  729.686884]  [<ffffffff812aff1b>] ? skb_queue_tail+0x2b/0x60
[  729.686884]  [<ffffffff813593a1>] ? _spin_lock_irqsave+0x41/0x60
[  729.686884]  [<ffffffff812aff1b>] ? skb_queue_tail+0x2b/0x60
[  729.686884]  [<ffffffff81359130>] ? _spin_unlock_irqrestore+0x40/0x60
[  729.686884]  [<ffffffff812aff1b>] ? skb_queue_tail+0x2b/0x60
[  729.686884]  [<ffffffffa04b11f5>] ? ieee80211_release_reorder_frame+0x35/0x50 [mac80211]
[  729.686884]  [<ffffffffa04b2f0c>] ? ieee80211_invoke_rx_handlers+0xb8c/0x1990 [mac80211]
[  729.686884]  [<ffffffff810766bc>] ? mark_held_locks+0x6c/0xa0
[  729.686884]  [<ffffffff81358f30>] ? _write_unlock_irqrestore+0x40/0x60
[  729.686884]  [<ffffffff810768bb>] ? trace_hardirqs_on_caller+0x6b/0x190
[  729.686884]  [<ffffffff810769ed>] ? trace_hardirqs_on+0xd/0x10
[  729.686884]  [<ffffffffa04b3db6>] ? ieee80211_rx+0xa6/0x8f0 [mac80211]
[  729.686884]  [<ffffffffa04b3fef>] ? ieee80211_rx+0x2df/0x8f0 [mac80211]
[  729.686884]  [<ffffffffa04b3db6>] ? ieee80211_rx+0xa6/0x8f0 [mac80211]
[  729.686884]  [<ffffffff812af1c7>] ? skb_copy_bits+0x167/0x2b0
[  729.686884]  [<ffffffffa04fd2f1>] ? iwl_rx_reply_rx+0x571/0xee0 [iwlcore]
[  729.686884]  [<ffffffff8100efb5>] ? dump_trace+0x105/0x2c0
[  729.686884]  [<ffffffff811dceb9>] ? debug_dma_unmap_page+0x59/0x60
[  729.686884]  [<ffffffffa0557e89>] ? iwl_rx_handle+0x149/0x670 [iwlagn]
[  729.686884]  [<ffffffff810766bc>] ? mark_held_locks+0x6c/0xa0
[  729.686884]  [<ffffffffa0559afc>] ? iwl_irq_tasklet+0x2ec/0x1320 [iwlagn]
[  729.686884]  [<ffffffff810766bc>] ? mark_held_locks+0x6c/0xa0
[  729.686884]  [<ffffffff8104b1d9>] ? tasklet_action+0x49/0xe0
[  729.686884]  [<ffffffff8104b260>] ? tasklet_action+0xd0/0xe0
[  729.686884]  [<ffffffff8104c78b>] ? __do_softirq+0xcb/0x200
[  729.686884]  [<ffffffff8100d09c>] ? call_softirq+0x1c/0x50
[  729.686884]  [<ffffffff8100e80d>] ? do_softirq+0x7d/0xb0
[  729.686884]  [<ffffffff8104c2c5>] ? irq_exit+0x95/0xa0
[  729.686884]  [<ffffffff8135e485>] ? do_IRQ+0x75/0xf0
[  729.686884]  [<ffffffff8100c893>] ? ret_from_intr+0x0/0xf
[  729.686884]  <EOI>  [<ffffffff8102eccd>] ? flush_tlb_page+0x7d/0x90
[  729.686884]  [<ffffffff8102ec98>] ? flush_tlb_page+0x48/0x90
[  729.686884]  [<ffffffff810f508d>] ? move_page_tables+0x2cd/0x4c0
[  729.686884]  [<ffffffff810f5133>] ? move_page_tables+0x373/0x4c0
[  729.686884]  [<ffffffff810f5879>] ? do_mremap+0x5f9/0x7a0
[  729.686884]  [<ffffffff810f5a7f>] ? sys_mremap+0x5f/0x90
[  729.686884]  [<ffffffff8100bedb>] ? system_call_fastpath+0x16/0x1b
[  729.686884] ---[ end trace 73a47421077c9587 ]---

Reinette




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

* Re: [PATCH v2 3/5] mac80211: correctly place aMPDU RX reorder code
  2009-12-03 18:13   ` reinette chatre
@ 2009-12-03 18:52     ` Johannes Berg
  2009-12-03 19:14     ` Johannes Berg
  1 sibling, 0 replies; 12+ messages in thread
From: Johannes Berg @ 2009-12-03 18:52 UTC (permalink / raw)
  To: reinette chatre; +Cc: John Linville, linux-wireless

[-- Attachment #1: Type: text/plain, Size: 438 bytes --]

On Thu, 2009-12-03 at 10:13 -0800, reinette chatre wrote:

> I bisected a hang problem to this patch. When associating to an 11n AP
> (tested on 5GHz), ping works fine, but trying to copy a large file
> causes the system to freeze (keyboard lights start blinking and system
> unresponsive. Reverting this patch I can copy large files successfully.

Ouch. Thanks for the report/information, I'll look into it promptly.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH v2 3/5] mac80211: correctly place aMPDU RX reorder code
  2009-12-03 18:13   ` reinette chatre
  2009-12-03 18:52     ` Johannes Berg
@ 2009-12-03 19:14     ` Johannes Berg
  2009-12-03 19:30       ` reinette chatre
  1 sibling, 1 reply; 12+ messages in thread
From: Johannes Berg @ 2009-12-03 19:14 UTC (permalink / raw)
  To: reinette chatre; +Cc: John Linville, linux-wireless

On Thu, 2009-12-03 at 10:13 -0800, reinette chatre wrote:

> [  729.672010]  [<ffffffff812aff1b>] skb_queue_tail+0x2b/0x60
> [  729.672010]  [<ffffffffa04b11f5>] ieee80211_release_reorder_frame+0x35/0x50 [mac80211]

So Christian beat me to looking at the trace and pointed out that
skb_queue_tail has no business here, we've intentionally not initialised
the spinlock. The patch below should fix it. I suppose I never had
actual reordering in my tests.

johannes

---
 net/mac80211/rx.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- wireless-testing.orig/net/mac80211/rx.c	2009-12-03 20:13:44.000000000 +0100
+++ wireless-testing/net/mac80211/rx.c	2009-12-03 20:13:50.000000000 +0100
@@ -570,7 +570,7 @@ static void ieee80211_release_reorder_fr
 		rate = &sband->bitrates[status->rate_idx];
 	tid_agg_rx->stored_mpdu_num--;
 	tid_agg_rx->reorder_buf[index] = NULL;
-	skb_queue_tail(frames, skb);
+	__skb_queue_tail(frames, skb);
 
 no_frame:
 	tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num);



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

* Re: [PATCH v2 3/5] mac80211: correctly place aMPDU RX reorder code
  2009-12-03 19:14     ` Johannes Berg
@ 2009-12-03 19:30       ` reinette chatre
  0 siblings, 0 replies; 12+ messages in thread
From: reinette chatre @ 2009-12-03 19:30 UTC (permalink / raw)
  To: Johannes Berg; +Cc: John Linville, linux-wireless

Hi Johannes,

On Thu, 2009-12-03 at 11:14 -0800, Johannes Berg wrote:
> ---
>  net/mac80211/rx.c |    2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> --- wireless-testing.orig/net/mac80211/rx.c	2009-12-03 20:13:44.000000000 +0100
> +++ wireless-testing/net/mac80211/rx.c	2009-12-03 20:13:50.000000000 +0100
> @@ -570,7 +570,7 @@ static void ieee80211_release_reorder_fr
>  		rate = &sband->bitrates[status->rate_idx];
>  	tid_agg_rx->stored_mpdu_num--;
>  	tid_agg_rx->reorder_buf[index] = NULL;
> -	skb_queue_tail(frames, skb);
> +	__skb_queue_tail(frames, skb);
>  
>  no_frame:
>  	tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num);
> 
> 

Thank you very much for looking into this so promptly. This patch fixes
the problem.

Tested-by: Reinette Chatre <reinette.chatre@intel.com>

Reinette



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

end of thread, other threads:[~2009-12-03 19:29 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-11-25 16:46 [PATCH v2 0/5] mac80211: stations per virtual interface, netdev reduction Johannes Berg
2009-11-25 16:46 ` [PATCH v2 1/5] mac80211: move cmntr flag out of rx flags Johannes Berg
2009-11-25 16:46 ` [PATCH v2 2/5] mac80211: move aMPDU RX reorder code Johannes Berg
2009-11-25 16:46 ` [PATCH v2 3/5] mac80211: correctly place " Johannes Berg
2009-12-03 18:13   ` reinette chatre
2009-12-03 18:52     ` Johannes Berg
2009-12-03 19:14     ` Johannes Berg
2009-12-03 19:30       ` reinette chatre
2009-11-25 16:46 ` [PATCH v2 4/5] mac80211: make station management completely depend on vif Johannes Berg
2009-11-25 19:27   ` [PATCH v3 " Johannes Berg
2009-12-01  9:51     ` Johannes Berg
2009-11-25 16:46 ` [PATCH v2 5/5] mac80211: reduce reliance on netdev 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.