aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/sta_info.h
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2008-05-02 19:02:02 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-05-14 16:29:34 -0400
commit07346f81e87d6e4cca7ae9adfa711d0c61c87b56 (patch)
tree237450c49843e0e19afc79356240a891da64d9fa /net/mac80211/sta_info.h
parent3434fbd39862d471c92b66c28cd449deea8e9f90 (diff)
mac80211: proper STA info locking
As discussed earlier, we can unify locking in struct sta_info and use just a single spinlock protecting all members of the structure that need protection. Many don't, but one of the especially bad ones is the 'flags' member that can currently be clobbered when RX and TX is being processed on different CPUs at the same time. Because having four spinlocks for different, mostly exclusive parts of a single structure is overkill, this patch also kills the ampdu and mesh plink spinlocks and uses just a single one for everything. Because none of the spinlocks are nested, this is safe. It remains to be seen whether or not we should make the sta flags use atomic bit operations instead, for now though this is a safe thing and using atomic operations instead will be very simple using the new static inline functions this patch introduces for accessing sta->flags. Since spin_lock_bh() is used with this lock, there shouldn't be any contention even if aggregation is enabled at around the same time as both requires frame transmission/reception which is in a bh context. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Cc: Tomas Winkler <tomasw@gmail.com> Cc: Ron Rindjunsky <ron.rindjunsky@intel.com> Cc: Luis Carlos Cobo <luisca@cozybit.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/sta_info.h')
-rw-r--r--net/mac80211/sta_info.h72
1 files changed, 63 insertions, 9 deletions
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index f8c95bc9659c..97a61c39ad90 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -129,23 +129,19 @@ enum plink_state {
129 * 129 *
130 * @tid_state_rx: TID's state in Rx session state machine. 130 * @tid_state_rx: TID's state in Rx session state machine.
131 * @tid_rx: aggregation info for Rx per TID 131 * @tid_rx: aggregation info for Rx per TID
132 * @ampdu_rx: for locking sections in aggregation Rx flow
133 * @tid_state_tx: TID's state in Tx session state machine. 132 * @tid_state_tx: TID's state in Tx session state machine.
134 * @tid_tx: aggregation info for Tx per TID 133 * @tid_tx: aggregation info for Tx per TID
135 * @addba_req_num: number of times addBA request has been sent. 134 * @addba_req_num: number of times addBA request has been sent.
136 * @ampdu_tx: for locking sectionsi in aggregation Tx flow
137 * @dialog_token_allocator: dialog token enumerator for each new session; 135 * @dialog_token_allocator: dialog token enumerator for each new session;
138 */ 136 */
139struct sta_ampdu_mlme { 137struct sta_ampdu_mlme {
140 /* rx */ 138 /* rx */
141 u8 tid_state_rx[STA_TID_NUM]; 139 u8 tid_state_rx[STA_TID_NUM];
142 struct tid_ampdu_rx *tid_rx[STA_TID_NUM]; 140 struct tid_ampdu_rx *tid_rx[STA_TID_NUM];
143 spinlock_t ampdu_rx;
144 /* tx */ 141 /* tx */
145 u8 tid_state_tx[STA_TID_NUM]; 142 u8 tid_state_tx[STA_TID_NUM];
146 struct tid_ampdu_tx *tid_tx[STA_TID_NUM]; 143 struct tid_ampdu_tx *tid_tx[STA_TID_NUM];
147 u8 addba_req_num[STA_TID_NUM]; 144 u8 addba_req_num[STA_TID_NUM];
148 spinlock_t ampdu_tx;
149 u8 dialog_token_allocator; 145 u8 dialog_token_allocator;
150}; 146};
151 147
@@ -177,6 +173,8 @@ struct sta_ampdu_mlme {
177 * @rx_bytes: Number of bytes received from this STA 173 * @rx_bytes: Number of bytes received from this STA
178 * @supp_rates: Bitmap of supported rates (per band) 174 * @supp_rates: Bitmap of supported rates (per band)
179 * @ht_info: HT capabilities of this STA 175 * @ht_info: HT capabilities of this STA
176 * @lock: used for locking all fields that require locking, see comments
177 * in the header file.
180 */ 178 */
181struct sta_info { 179struct sta_info {
182 /* General information, mostly static */ 180 /* General information, mostly static */
@@ -187,6 +185,7 @@ struct sta_info {
187 struct ieee80211_key *key; 185 struct ieee80211_key *key;
188 struct rate_control_ref *rate_ctrl; 186 struct rate_control_ref *rate_ctrl;
189 void *rate_ctrl_priv; 187 void *rate_ctrl_priv;
188 spinlock_t lock;
190 struct ieee80211_ht_info ht_info; 189 struct ieee80211_ht_info ht_info;
191 u64 supp_rates[IEEE80211_NUM_BANDS]; 190 u64 supp_rates[IEEE80211_NUM_BANDS];
192 u8 addr[ETH_ALEN]; 191 u8 addr[ETH_ALEN];
@@ -199,7 +198,7 @@ struct sta_info {
199 */ 198 */
200 u8 pin_status; 199 u8 pin_status;
201 200
202 /* frequently updated information, needs locking? */ 201 /* frequently updated information, locked with lock spinlock */
203 u32 flags; 202 u32 flags;
204 203
205 /* 204 /*
@@ -251,7 +250,7 @@ struct sta_info {
251 int channel_use_raw; 250 int channel_use_raw;
252 251
253 /* 252 /*
254 * Aggregation information, comes with own locking. 253 * Aggregation information, locked with lock.
255 */ 254 */
256 struct sta_ampdu_mlme ampdu_mlme; 255 struct sta_ampdu_mlme ampdu_mlme;
257 u8 timer_to_tid[STA_TID_NUM]; /* identity mapping to ID timers */ 256 u8 timer_to_tid[STA_TID_NUM]; /* identity mapping to ID timers */
@@ -270,9 +269,6 @@ struct sta_info {
270 enum plink_state plink_state; 269 enum plink_state plink_state;
271 u32 plink_timeout; 270 u32 plink_timeout;
272 struct timer_list plink_timer; 271 struct timer_list plink_timer;
273 spinlock_t plink_lock; /* For peer_state reads / updates and other
274 updates in the structure. Ensures robust
275 transitions for the peerlink FSM */
276#endif 272#endif
277 273
278#ifdef CONFIG_MAC80211_DEBUGFS 274#ifdef CONFIG_MAC80211_DEBUGFS
@@ -299,6 +295,64 @@ static inline enum plink_state sta_plink_state(struct sta_info *sta)
299 return PLINK_LISTEN; 295 return PLINK_LISTEN;
300} 296}
301 297
298static inline void set_sta_flags(struct sta_info *sta, const u32 flags)
299{
300 spin_lock_bh(&sta->lock);
301 sta->flags |= flags;
302 spin_unlock_bh(&sta->lock);
303}
304
305static inline void clear_sta_flags(struct sta_info *sta, const u32 flags)
306{
307 spin_lock_bh(&sta->lock);
308 sta->flags &= ~flags;
309 spin_unlock_bh(&sta->lock);
310}
311
312static inline void set_and_clear_sta_flags(struct sta_info *sta,
313 const u32 set, const u32 clear)
314{
315 spin_lock_bh(&sta->lock);
316 sta->flags |= set;
317 sta->flags &= ~clear;
318 spin_unlock_bh(&sta->lock);
319}
320
321static inline u32 test_sta_flags(struct sta_info *sta, const u32 flags)
322{
323 u32 ret;
324
325 spin_lock_bh(&sta->lock);
326 ret = sta->flags & flags;
327 spin_unlock_bh(&sta->lock);
328
329 return ret;
330}
331
332static inline u32 test_and_clear_sta_flags(struct sta_info *sta,
333 const u32 flags)
334{
335 u32 ret;
336
337 spin_lock_bh(&sta->lock);
338 ret = sta->flags & flags;
339 sta->flags &= ~flags;
340 spin_unlock_bh(&sta->lock);
341
342 return ret;
343}
344
345static inline u32 get_sta_flags(struct sta_info *sta)
346{
347 u32 ret;
348
349 spin_lock_bh(&sta->lock);
350 ret = sta->flags;
351 spin_unlock_bh(&sta->lock);
352
353 return ret;
354}
355
302 356
303/* Maximum number of concurrently registered stations */ 357/* Maximum number of concurrently registered stations */
304#define MAX_STA_COUNT 2007 358#define MAX_STA_COUNT 2007