aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/sta_info.h
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2008-02-25 10:27:46 -0500
committerJohn W. Linville <linville@tuxdriver.com>2008-03-06 15:30:46 -0500
commitd0709a65181beb787ef3f58cfe45536a2bb254c8 (patch)
tree29e5f36583b0e0a3f11b291347e57672eab41dad /net/mac80211/sta_info.h
parent5cf121c3cdb955583bf0c5d28c992b7968a4aa1a (diff)
mac80211: RCU-ify STA info structure access
This makes access to the STA hash table/list use RCU to protect against freeing of items. However, it's not a true RCU, the copy step is missing: whenever somebody changes a STA item it is simply updated. This is an existing race condition that is now somewhat understandable. This patch also fixes the race key freeing vs. STA destruction by making sure that sta_info_destroy() is always called under RTNL and frees the key. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/sta_info.h')
-rw-r--r--net/mac80211/sta_info.h61
1 files changed, 42 insertions, 19 deletions
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index b9dfb6fa893a..787124c253af 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -12,7 +12,6 @@
12#include <linux/list.h> 12#include <linux/list.h>
13#include <linux/types.h> 13#include <linux/types.h>
14#include <linux/if_ether.h> 14#include <linux/if_ether.h>
15#include <linux/kref.h>
16#include "ieee80211_key.h" 15#include "ieee80211_key.h"
17 16
18/** 17/**
@@ -134,8 +133,14 @@ struct sta_ampdu_mlme {
134 u8 dialog_token_allocator; 133 u8 dialog_token_allocator;
135}; 134};
136 135
136
137/* see __sta_info_unlink */
138#define STA_INFO_PIN_STAT_NORMAL 0
139#define STA_INFO_PIN_STAT_PINNED 1
140#define STA_INFO_PIN_STAT_DESTROY 2
141
142
137struct sta_info { 143struct sta_info {
138 struct kref kref;
139 struct list_head list; 144 struct list_head list;
140 struct sta_info *hnext; /* next entry in hash table list */ 145 struct sta_info *hnext; /* next entry in hash table list */
141 146
@@ -166,8 +171,8 @@ struct sta_info {
166 /* last rates used to send a frame to this STA */ 171 /* last rates used to send a frame to this STA */
167 int last_txrate_idx, last_nonerp_txrate_idx; 172 int last_txrate_idx, last_nonerp_txrate_idx;
168 173
169 struct net_device *dev; /* which net device is this station associated 174 /* sub_if_data this sta belongs to */
170 * to */ 175 struct ieee80211_sub_if_data *sdata;
171 176
172 struct ieee80211_key *key; 177 struct ieee80211_key *key;
173 178
@@ -199,6 +204,12 @@ struct sta_info {
199 204
200 u16 listen_interval; 205 u16 listen_interval;
201 206
207 /*
208 * for use by the internal lifetime management,
209 * see __sta_info_unlink
210 */
211 u8 pin_status;
212
202 struct ieee80211_ht_info ht_info; /* 802.11n HT capabilities 213 struct ieee80211_ht_info ht_info; /* 802.11n HT capabilities
203 of this STA */ 214 of this STA */
204 struct sta_ampdu_mlme ampdu_mlme; 215 struct sta_ampdu_mlme ampdu_mlme;
@@ -262,25 +273,37 @@ static inline enum plink_state sta_plink_state(struct sta_info *sta)
262 */ 273 */
263#define STA_INFO_CLEANUP_INTERVAL (10 * HZ) 274#define STA_INFO_CLEANUP_INTERVAL (10 * HZ)
264 275
265static inline void __sta_info_get(struct sta_info *sta) 276/*
266{ 277 * Get a STA info, must have be under RCU read lock.
267 kref_get(&sta->kref); 278 */
268} 279struct sta_info *sta_info_get(struct ieee80211_local *local, u8 *addr);
269 280/*
270struct sta_info * sta_info_get(struct ieee80211_local *local, u8 *addr); 281 * Get STA info by index, BROKEN!
282 */
271struct sta_info *sta_info_get_by_idx(struct ieee80211_local *local, int idx, 283struct sta_info *sta_info_get_by_idx(struct ieee80211_local *local, int idx,
272 struct net_device *dev); 284 struct net_device *dev);
273void sta_info_put(struct sta_info *sta); 285/*
274struct sta_info *sta_info_add(struct ieee80211_local *local, 286 * Add a new STA info, must be under RCU read lock
275 struct net_device *dev, u8 *addr, gfp_t gfp); 287 * because otherwise the returned reference isn't
276void sta_info_remove(struct sta_info *sta); 288 * necessarily valid long enough.
277void sta_info_free(struct sta_info *sta); 289 */
278void sta_info_init(struct ieee80211_local *local); 290struct sta_info *sta_info_add(struct ieee80211_sub_if_data *sdata,
279int sta_info_start(struct ieee80211_local *local); 291 u8 *addr);
280void sta_info_stop(struct ieee80211_local *local); 292/*
281void sta_info_flush(struct ieee80211_local *local, struct net_device *dev); 293 * Unlink a STA info from the hash table/list.
294 * This can NULL the STA pointer if somebody else
295 * has already unlinked it.
296 */
297void sta_info_unlink(struct sta_info **sta);
282 298
299void sta_info_destroy(struct sta_info *sta);
283void sta_info_set_tim_bit(struct sta_info *sta); 300void sta_info_set_tim_bit(struct sta_info *sta);
284void sta_info_clear_tim_bit(struct sta_info *sta); 301void sta_info_clear_tim_bit(struct sta_info *sta);
285 302
303void sta_info_init(struct ieee80211_local *local);
304int sta_info_start(struct ieee80211_local *local);
305void sta_info_stop(struct ieee80211_local *local);
306void sta_info_flush(struct ieee80211_local *local,
307 struct ieee80211_sub_if_data *sdata);
308
286#endif /* STA_INFO_H */ 309#endif /* STA_INFO_H */