aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/cfg.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-06-11 11:09:41 -0400
committerJohannes Berg <johannes.berg@intel.com>2012-06-13 04:11:31 -0400
commite979e33c3972044e1be5e46552a02c3b9c0bc7a7 (patch)
treed34aea2a3a922b13cb85f5cf4077cad105cd50b2 /net/mac80211/cfg.c
parent535588e61a007416f46cf08b4ccb6cc73b3f6fb0 (diff)
mac80211: allow cancelling dependent ROCs
In my redesign of remain-on-channel I forgot that an item could be cancelled when it's a dependent item that is part of another item. Allow cancelling such items by removing them from the dependents list. Note that when we cancel the main item, all its dependents are also cancelled. It would be possible to not do that, but would need tricks to promote an item from dependent to top-level and is tricky in the HW ROC case. Reported-by: Ilan Peer <ilan.peer@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/cfg.c')
-rw-r--r--net/mac80211/cfg.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 93d203cf8c12..9a974579ba89 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2305,6 +2305,21 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local,
2305 2305
2306 mutex_lock(&local->mtx); 2306 mutex_lock(&local->mtx);
2307 list_for_each_entry_safe(roc, tmp, &local->roc_list, list) { 2307 list_for_each_entry_safe(roc, tmp, &local->roc_list, list) {
2308 struct ieee80211_roc_work *dep, *tmp2;
2309
2310 list_for_each_entry_safe(dep, tmp2, &roc->dependents, list) {
2311 if (!mgmt_tx && (unsigned long)dep != cookie)
2312 continue;
2313 else if (mgmt_tx && dep->mgmt_tx_cookie != cookie)
2314 continue;
2315 /* found dependent item -- just remove it */
2316 list_del(&dep->list);
2317 mutex_unlock(&local->mtx);
2318
2319 ieee80211_roc_notify_destroy(dep);
2320 return 0;
2321 }
2322
2308 if (!mgmt_tx && (unsigned long)roc != cookie) 2323 if (!mgmt_tx && (unsigned long)roc != cookie)
2309 continue; 2324 continue;
2310 else if (mgmt_tx && roc->mgmt_tx_cookie != cookie) 2325 else if (mgmt_tx && roc->mgmt_tx_cookie != cookie)
@@ -2319,6 +2334,13 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local,
2319 return -ENOENT; 2334 return -ENOENT;
2320 } 2335 }
2321 2336
2337 /*
2338 * We found the item to cancel, so do that. Note that it
2339 * may have dependents, which we also cancel (and send
2340 * the expired signal for.) Not doing so would be quite
2341 * tricky here, but we may need to fix it later.
2342 */
2343
2322 if (local->ops->remain_on_channel) { 2344 if (local->ops->remain_on_channel) {
2323 if (found->started) { 2345 if (found->started) {
2324 ret = drv_cancel_remain_on_channel(local); 2346 ret = drv_cancel_remain_on_channel(local);