diff options
author | Daniel Drake <dsd@gentoo.org> | 2006-04-30 17:09:07 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2006-05-05 16:55:22 -0400 |
commit | d57336e3f2dd7c2d1fbe4a8323029869fb6e1f00 (patch) | |
tree | 5724c4017f744df284fb9f18e5b9c8a8bcb7fbcf /net/ieee80211/softmac/ieee80211softmac_assoc.c | |
parent | 995c99268e0b12eb3c8939211ba5368dd92d98d9 (diff) |
[PATCH] softmac: make non-operational after being stopped
zd1211 with softmac and wpa_supplicant revealed an issue with softmac
and the use of workqueues. Some of the work functions actually
reschedule themselves, so this meant that there could still be
pending work after flush_scheduled_work() had been called during
ieee80211softmac_stop().
This patch introduces a "running" flag which is used to ensure that
rescheduling does not happen in this situation.
I also used this flag to ensure that softmac's hooks into ieee80211 are
non-operational once the stop operation has been started. This simply
makes softmac a little more robust, because I could crash it easily
by receiving frames in the short timeframe after shutting down softmac
and before turning off the ZD1211 radio. (ZD1211 is now fixed as well!)
Signed-off-by: Daniel Drake <dsd@gentoo.org>
Acked-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/ieee80211/softmac/ieee80211softmac_assoc.c')
-rw-r--r-- | net/ieee80211/softmac/ieee80211softmac_assoc.c | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c index fb79ce7d6439..57ea9f6f465c 100644 --- a/net/ieee80211/softmac/ieee80211softmac_assoc.c +++ b/net/ieee80211/softmac/ieee80211softmac_assoc.c | |||
@@ -51,11 +51,12 @@ ieee80211softmac_assoc(struct ieee80211softmac_device *mac, struct ieee80211soft | |||
51 | spin_lock_irqsave(&mac->lock, flags); | 51 | spin_lock_irqsave(&mac->lock, flags); |
52 | mac->associnfo.associating = 1; | 52 | mac->associnfo.associating = 1; |
53 | mac->associated = 0; /* just to make sure */ | 53 | mac->associated = 0; /* just to make sure */ |
54 | spin_unlock_irqrestore(&mac->lock, flags); | ||
55 | 54 | ||
56 | /* Set a timer for timeout */ | 55 | /* Set a timer for timeout */ |
57 | /* FIXME: make timeout configurable */ | 56 | /* FIXME: make timeout configurable */ |
58 | schedule_delayed_work(&mac->associnfo.timeout, 5 * HZ); | 57 | if (likely(mac->running)) |
58 | schedule_delayed_work(&mac->associnfo.timeout, 5 * HZ); | ||
59 | spin_unlock_irqrestore(&mac->lock, flags); | ||
59 | } | 60 | } |
60 | 61 | ||
61 | void | 62 | void |
@@ -319,6 +320,9 @@ ieee80211softmac_handle_assoc_response(struct net_device * dev, | |||
319 | u16 status = le16_to_cpup(&resp->status); | 320 | u16 status = le16_to_cpup(&resp->status); |
320 | struct ieee80211softmac_network *network = NULL; | 321 | struct ieee80211softmac_network *network = NULL; |
321 | unsigned long flags; | 322 | unsigned long flags; |
323 | |||
324 | if (unlikely(!mac->running)) | ||
325 | return -ENODEV; | ||
322 | 326 | ||
323 | spin_lock_irqsave(&mac->lock, flags); | 327 | spin_lock_irqsave(&mac->lock, flags); |
324 | 328 | ||
@@ -377,10 +381,16 @@ ieee80211softmac_handle_disassoc(struct net_device * dev, | |||
377 | { | 381 | { |
378 | struct ieee80211softmac_device *mac = ieee80211_priv(dev); | 382 | struct ieee80211softmac_device *mac = ieee80211_priv(dev); |
379 | unsigned long flags; | 383 | unsigned long flags; |
384 | |||
385 | if (unlikely(!mac->running)) | ||
386 | return -ENODEV; | ||
387 | |||
380 | if (memcmp(disassoc->header.addr2, mac->associnfo.bssid, ETH_ALEN)) | 388 | if (memcmp(disassoc->header.addr2, mac->associnfo.bssid, ETH_ALEN)) |
381 | return 0; | 389 | return 0; |
390 | |||
382 | if (memcmp(disassoc->header.addr1, mac->dev->dev_addr, ETH_ALEN)) | 391 | if (memcmp(disassoc->header.addr1, mac->dev->dev_addr, ETH_ALEN)) |
383 | return 0; | 392 | return 0; |
393 | |||
384 | dprintk(KERN_INFO PFX "got disassoc frame\n"); | 394 | dprintk(KERN_INFO PFX "got disassoc frame\n"); |
385 | netif_carrier_off(dev); | 395 | netif_carrier_off(dev); |
386 | spin_lock_irqsave(&mac->lock, flags); | 396 | spin_lock_irqsave(&mac->lock, flags); |
@@ -400,6 +410,9 @@ ieee80211softmac_handle_reassoc_req(struct net_device * dev, | |||
400 | struct ieee80211softmac_device *mac = ieee80211_priv(dev); | 410 | struct ieee80211softmac_device *mac = ieee80211_priv(dev); |
401 | struct ieee80211softmac_network *network; | 411 | struct ieee80211softmac_network *network; |
402 | 412 | ||
413 | if (unlikely(!mac->running)) | ||
414 | return -ENODEV; | ||
415 | |||
403 | network = ieee80211softmac_get_network_by_bssid(mac, resp->header.addr3); | 416 | network = ieee80211softmac_get_network_by_bssid(mac, resp->header.addr3); |
404 | if (!network) { | 417 | if (!network) { |
405 | dprintkl(KERN_INFO PFX "reassoc request from unknown network\n"); | 418 | dprintkl(KERN_INFO PFX "reassoc request from unknown network\n"); |