diff options
author | Holger Schurig <hs4233@mail.mn-solutions.de> | 2008-04-30 04:51:15 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-05-07 15:02:27 -0400 |
commit | 652e3f208619dfe75867349d6164afe735eaf159 (patch) | |
tree | 71ea986edf7f345b3bafbf7c0e61ab22a7b343e1 | |
parent | a63e5cb22fcc8590abc7d5050118a6d3589ed95f (diff) |
libertas: allow removal of card at any time
This fixes several problems I had:
* when removing the card while the card was scanning or associtating,
it could happen that destroy_workqueue() stuck and didn't return.
* make sure the command function doesn't run while we remove the list
of pending commands
* for still unknown reason, I had calls to lbs_stop_card() with
priv==NULL
Signed-off-by: Holger Schurig <hs4233@mail.mn-solutions.de>
Acked-by: Dan Williams <dcbw@redhat.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/libertas/main.c | 9 |
1 files changed, 7 insertions, 2 deletions
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 223ab3a14a13..0be89573716c 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c | |||
@@ -1166,8 +1166,8 @@ void lbs_remove_card(struct lbs_private *priv) | |||
1166 | 1166 | ||
1167 | dev = priv->dev; | 1167 | dev = priv->dev; |
1168 | 1168 | ||
1169 | cancel_delayed_work(&priv->scan_work); | 1169 | cancel_delayed_work_sync(&priv->scan_work); |
1170 | cancel_delayed_work(&priv->assoc_work); | 1170 | cancel_delayed_work_sync(&priv->assoc_work); |
1171 | destroy_workqueue(priv->work_thread); | 1171 | destroy_workqueue(priv->work_thread); |
1172 | 1172 | ||
1173 | if (priv->psmode == LBS802_11POWERMODEMAX_PSP) { | 1173 | if (priv->psmode == LBS802_11POWERMODEMAX_PSP) { |
@@ -1267,6 +1267,9 @@ void lbs_stop_card(struct lbs_private *priv) | |||
1267 | 1267 | ||
1268 | lbs_deb_enter(LBS_DEB_MAIN); | 1268 | lbs_deb_enter(LBS_DEB_MAIN); |
1269 | 1269 | ||
1270 | if (!priv) | ||
1271 | goto out; | ||
1272 | |||
1270 | netif_stop_queue(priv->dev); | 1273 | netif_stop_queue(priv->dev); |
1271 | netif_carrier_off(priv->dev); | 1274 | netif_carrier_off(priv->dev); |
1272 | 1275 | ||
@@ -1276,6 +1279,7 @@ void lbs_stop_card(struct lbs_private *priv) | |||
1276 | device_remove_file(&dev->dev, &dev_attr_lbs_mesh); | 1279 | device_remove_file(&dev->dev, &dev_attr_lbs_mesh); |
1277 | 1280 | ||
1278 | /* Flush pending command nodes */ | 1281 | /* Flush pending command nodes */ |
1282 | del_timer_sync(&priv->command_timer); | ||
1279 | spin_lock_irqsave(&priv->driver_lock, flags); | 1283 | spin_lock_irqsave(&priv->driver_lock, flags); |
1280 | list_for_each_entry(cmdnode, &priv->cmdpendingq, list) { | 1284 | list_for_each_entry(cmdnode, &priv->cmdpendingq, list) { |
1281 | cmdnode->result = -ENOENT; | 1285 | cmdnode->result = -ENOENT; |
@@ -1286,6 +1290,7 @@ void lbs_stop_card(struct lbs_private *priv) | |||
1286 | 1290 | ||
1287 | unregister_netdev(dev); | 1291 | unregister_netdev(dev); |
1288 | 1292 | ||
1293 | out: | ||
1289 | lbs_deb_leave(LBS_DEB_MAIN); | 1294 | lbs_deb_leave(LBS_DEB_MAIN); |
1290 | } | 1295 | } |
1291 | EXPORT_SYMBOL_GPL(lbs_stop_card); | 1296 | EXPORT_SYMBOL_GPL(lbs_stop_card); |