diff options
author | Johannes Berg <johannes.berg@intel.com> | 2012-10-26 10:13:06 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2012-10-30 04:33:40 -0400 |
commit | 50febf6a1a9270b3558671864a27b23f671598ab (patch) | |
tree | ba700ee435487e31857d165f836ea084983d10cb /net/mac80211 | |
parent | 8a2fbedcdc9bec1d613961f97cb87d6b71a66076 (diff) |
mac80211: use a counter for remain-on-channel cookie
Instead of using the pointer which can be re-used
fairly quickly due to allocator patterns and then
makes debugging difficult, maintain a counter and
use its value. Since it's a 64-bit value it can't
really wrap, but catch that case anyway since it
most likely points to a bug somewhere.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/cfg.c | 21 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 3 | ||||
-rw-r--r-- | net/mac80211/offchannel.c | 7 |
3 files changed, 20 insertions, 11 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 986e9a139d42..eebb70b0aa11 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -2382,13 +2382,22 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
2382 | list_add_tail(&roc->list, &local->roc_list); | 2382 | list_add_tail(&roc->list, &local->roc_list); |
2383 | 2383 | ||
2384 | /* | 2384 | /* |
2385 | * cookie is either the roc (for normal roc) | 2385 | * cookie is either the roc cookie (for normal roc) |
2386 | * or the SKB (for mgmt TX) | 2386 | * or the SKB (for mgmt TX) |
2387 | */ | 2387 | */ |
2388 | if (txskb) | 2388 | if (!txskb) { |
2389 | /* local->mtx protects this */ | ||
2390 | local->roc_cookie_counter++; | ||
2391 | roc->cookie = local->roc_cookie_counter; | ||
2392 | /* wow, you wrapped 64 bits ... more likely a bug */ | ||
2393 | if (WARN_ON(roc->cookie == 0)) { | ||
2394 | roc->cookie = 1; | ||
2395 | local->roc_cookie_counter++; | ||
2396 | } | ||
2397 | *cookie = roc->cookie; | ||
2398 | } else { | ||
2389 | *cookie = (unsigned long)txskb; | 2399 | *cookie = (unsigned long)txskb; |
2390 | else | 2400 | } |
2391 | *cookie = (unsigned long)roc; | ||
2392 | 2401 | ||
2393 | return 0; | 2402 | return 0; |
2394 | } | 2403 | } |
@@ -2423,7 +2432,7 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local, | |||
2423 | struct ieee80211_roc_work *dep, *tmp2; | 2432 | struct ieee80211_roc_work *dep, *tmp2; |
2424 | 2433 | ||
2425 | list_for_each_entry_safe(dep, tmp2, &roc->dependents, list) { | 2434 | list_for_each_entry_safe(dep, tmp2, &roc->dependents, list) { |
2426 | if (!mgmt_tx && (unsigned long)dep != cookie) | 2435 | if (!mgmt_tx && dep->cookie != cookie) |
2427 | continue; | 2436 | continue; |
2428 | else if (mgmt_tx && dep->mgmt_tx_cookie != cookie) | 2437 | else if (mgmt_tx && dep->mgmt_tx_cookie != cookie) |
2429 | continue; | 2438 | continue; |
@@ -2435,7 +2444,7 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local, | |||
2435 | return 0; | 2444 | return 0; |
2436 | } | 2445 | } |
2437 | 2446 | ||
2438 | if (!mgmt_tx && (unsigned long)roc != cookie) | 2447 | if (!mgmt_tx && roc->cookie != cookie) |
2439 | continue; | 2448 | continue; |
2440 | else if (mgmt_tx && roc->mgmt_tx_cookie != cookie) | 2449 | else if (mgmt_tx && roc->mgmt_tx_cookie != cookie) |
2441 | continue; | 2450 | continue; |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index a1f7c139308e..d272e0cabc37 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -356,7 +356,7 @@ struct ieee80211_roc_work { | |||
356 | 356 | ||
357 | u32 duration, req_duration; | 357 | u32 duration, req_duration; |
358 | struct sk_buff *frame; | 358 | struct sk_buff *frame; |
359 | u64 mgmt_tx_cookie; | 359 | u64 cookie, mgmt_tx_cookie; |
360 | }; | 360 | }; |
361 | 361 | ||
362 | /* flags used in struct ieee80211_if_managed.flags */ | 362 | /* flags used in struct ieee80211_if_managed.flags */ |
@@ -1142,6 +1142,7 @@ struct ieee80211_local { | |||
1142 | struct list_head roc_list; | 1142 | struct list_head roc_list; |
1143 | struct work_struct hw_roc_start, hw_roc_done; | 1143 | struct work_struct hw_roc_start, hw_roc_done; |
1144 | unsigned long hw_roc_start_time; | 1144 | unsigned long hw_roc_start_time; |
1145 | u64 roc_cookie_counter; | ||
1145 | 1146 | ||
1146 | struct idr ack_status_frames; | 1147 | struct idr ack_status_frames; |
1147 | spinlock_t ack_status_lock; | 1148 | spinlock_t ack_status_lock; |
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index c349f3aaf59e..0cd42d52880c 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c | |||
@@ -204,7 +204,7 @@ void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc) | |||
204 | roc->frame = NULL; | 204 | roc->frame = NULL; |
205 | } | 205 | } |
206 | } else { | 206 | } else { |
207 | cfg80211_ready_on_channel(&roc->sdata->wdev, (unsigned long)roc, | 207 | cfg80211_ready_on_channel(&roc->sdata->wdev, roc->cookie, |
208 | roc->chan, roc->chan_type, | 208 | roc->chan, roc->chan_type, |
209 | roc->req_duration, GFP_KERNEL); | 209 | roc->req_duration, GFP_KERNEL); |
210 | } | 210 | } |
@@ -320,9 +320,8 @@ void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc) | |||
320 | 320 | ||
321 | if (!roc->mgmt_tx_cookie) | 321 | if (!roc->mgmt_tx_cookie) |
322 | cfg80211_remain_on_channel_expired(&roc->sdata->wdev, | 322 | cfg80211_remain_on_channel_expired(&roc->sdata->wdev, |
323 | (unsigned long)roc, | 323 | roc->cookie, roc->chan, |
324 | roc->chan, roc->chan_type, | 324 | roc->chan_type, GFP_KERNEL); |
325 | GFP_KERNEL); | ||
326 | 325 | ||
327 | list_for_each_entry_safe(dep, tmp, &roc->dependents, list) | 326 | list_for_each_entry_safe(dep, tmp, &roc->dependents, list) |
328 | ieee80211_roc_notify_destroy(dep); | 327 | ieee80211_roc_notify_destroy(dep); |