Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH] mac80211: use separate spinlock for sta flags
@ 2008-06-18 12:58 Johannes Berg
  0 siblings, 0 replies; only message in thread
From: Johannes Berg @ 2008-06-18 12:58 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless, David Ellingsworth, Michael Buesch

David Ellingsworth posted a bug that was only noticable on UP/NO-PREEMP=
T
and Michael correctly analysed it to be a spin_lock_bh() section within
a spin_lock_irqsave() section. This adds a separate spinlock for the
sta_info flags to fix that issue and avoid having to take much care
about where the sta flag manipulation functions are called.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Reported-By: =EF=BB=BFDavid Ellingsworth <david@identd.dyndns.org>
---
 net/mac80211/sta_info.c |    1 +
 net/mac80211/sta_info.h |   40 +++++++++++++++++++++++++++------------=
-
 2 files changed, 28 insertions(+), 13 deletions(-)

--- everything.orig/net/mac80211/sta_info.h	2008-06-18 10:07:24.0000000=
00 +0200
+++ everything/net/mac80211/sta_info.h	2008-06-18 11:58:32.000000000 +0=
200
@@ -164,6 +164,7 @@ struct sta_ampdu_mlme {
  * @aid: STA's unique AID (1..2007, 0 =3D not assigned yet),
  *	only used in AP (and IBSS?) mode
  * @flags: STA flags, see &enum ieee80211_sta_info_flags
+ * @flaglock: spinlock for flags accesses
  * @ps_tx_buf: buffer of frames to transmit to this station
  *	when it leaves power saving state
  * @tx_filtered: buffer of frames we already tried to transmit
@@ -186,6 +187,7 @@ struct sta_info {
 	struct rate_control_ref *rate_ctrl;
 	void *rate_ctrl_priv;
 	spinlock_t lock;
+	spinlock_t flaglock;
 	struct ieee80211_ht_info ht_info;
 	u64 supp_rates[IEEE80211_NUM_BANDS];
 	u8 addr[ETH_ALEN];
@@ -198,7 +200,10 @@ struct sta_info {
 	 */
 	u8 pin_status;
=20
-	/* frequently updated information, locked with lock spinlock */
+	/*
+	 * frequently updated, locked with own spinlock (flaglock),
+	 * use the accessors defined below
+	 */
 	u32 flags;
=20
 	/*
@@ -293,34 +298,41 @@ static inline enum plink_state sta_plink
=20
 static inline void set_sta_flags(struct sta_info *sta, const u32 flags=
)
 {
-	spin_lock_bh(&sta->lock);
+	unsigned long irqfl;
+
+	spin_lock_irqsave(&sta->flaglock, irqfl);
 	sta->flags |=3D flags;
-	spin_unlock_bh(&sta->lock);
+	spin_unlock_irqrestore(&sta->flaglock, irqfl);
 }
=20
 static inline void clear_sta_flags(struct sta_info *sta, const u32 fla=
gs)
 {
-	spin_lock_bh(&sta->lock);
+	unsigned long irqfl;
+
+	spin_lock_irqsave(&sta->flaglock, irqfl);
 	sta->flags &=3D ~flags;
-	spin_unlock_bh(&sta->lock);
+	spin_unlock_irqrestore(&sta->flaglock, irqfl);
 }
=20
 static inline void set_and_clear_sta_flags(struct sta_info *sta,
 					   const u32 set, const u32 clear)
 {
-	spin_lock_bh(&sta->lock);
+	unsigned long irqfl;
+
+	spin_lock_irqsave(&sta->flaglock, irqfl);
 	sta->flags |=3D set;
 	sta->flags &=3D ~clear;
-	spin_unlock_bh(&sta->lock);
+	spin_unlock_irqrestore(&sta->flaglock, irqfl);
 }
=20
 static inline u32 test_sta_flags(struct sta_info *sta, const u32 flags=
)
 {
 	u32 ret;
+	unsigned long irqfl;
=20
-	spin_lock_bh(&sta->lock);
+	spin_lock_irqsave(&sta->flaglock, irqfl);
 	ret =3D sta->flags & flags;
-	spin_unlock_bh(&sta->lock);
+	spin_unlock_irqrestore(&sta->flaglock, irqfl);
=20
 	return ret;
 }
@@ -329,11 +341,12 @@ static inline u32 test_and_clear_sta_fla
 					   const u32 flags)
 {
 	u32 ret;
+	unsigned long irqfl;
=20
-	spin_lock_bh(&sta->lock);
+	spin_lock_irqsave(&sta->flaglock, irqfl);
 	ret =3D sta->flags & flags;
 	sta->flags &=3D ~flags;
-	spin_unlock_bh(&sta->lock);
+	spin_unlock_irqrestore(&sta->flaglock, irqfl);
=20
 	return ret;
 }
@@ -341,10 +354,11 @@ static inline u32 test_and_clear_sta_fla
 static inline u32 get_sta_flags(struct sta_info *sta)
 {
 	u32 ret;
+	unsigned long irqfl;
=20
-	spin_lock_bh(&sta->lock);
+	spin_lock_irqsave(&sta->flaglock, irqfl);
 	ret =3D sta->flags;
-	spin_unlock_bh(&sta->lock);
+	spin_unlock_irqrestore(&sta->flaglock, irqfl);
=20
 	return ret;
 }
--- everything.orig/net/mac80211/sta_info.c	2008-06-18 11:56:44.0000000=
00 +0200
+++ everything/net/mac80211/sta_info.c	2008-06-18 11:56:58.000000000 +0=
200
@@ -235,6 +235,7 @@ struct sta_info *sta_info_alloc(struct i
 		return NULL;
=20
 	spin_lock_init(&sta->lock);
+	spin_lock_init(&sta->flaglock);
=20
 	memcpy(sta->addr, addr, ETH_ALEN);
 	sta->local =3D local;


--
To unsubscribe from this list: send the line "unsubscribe linux-wireles=
s" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2008-06-18 12:58 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-06-18 12:58 [PATCH] mac80211: use separate spinlock for sta flags Johannes Berg

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox