aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rndis_wlan.c
diff options
context:
space:
mode:
authorJussi Kivilinna <jussi.kivilinna@mbnet.fi>2009-04-21 12:48:07 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-04-22 16:57:20 -0400
commit8d4d99ae89a8845a1d63b0529dd98da28dc0ff65 (patch)
tree40f248e8dee1f73d33fa8fe9c75ddea14e39cc21 /drivers/net/wireless/rndis_wlan.c
parentcaa6dfadebee2098e9c5ece1d5efae96a6926d0f (diff)
rndis_wlan: fix initialization order for workqueue&workers
rndis_wext_link_change() might be called from rndis_command() at initialization stage and priv->workqueue/priv->work have not been initialized yet. This causes invalid opcode at rndis_wext_bind on some brands of bcm4320. Fix by initializing workqueue/workers in rndis_wext_bind() before rndis_command is used. Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/rndis_wlan.c')
-rw-r--r--drivers/net/wireless/rndis_wlan.c17
1 files changed, 12 insertions, 5 deletions
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 4b11ceae5b64..9ef547d6724e 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -2384,6 +2384,12 @@ static int rndis_wext_bind(struct usbnet *usbdev, struct usb_interface *intf)
2384 mutex_init(&priv->command_lock); 2384 mutex_init(&priv->command_lock);
2385 spin_lock_init(&priv->stats_lock); 2385 spin_lock_init(&priv->stats_lock);
2386 2386
2387 /* because rndis_command() sleeps we need to use workqueue */
2388 priv->workqueue = create_singlethread_workqueue("rndis_wlan");
2389 INIT_WORK(&priv->work, rndis_wext_worker);
2390 INIT_DELAYED_WORK(&priv->stats_work, rndis_update_wireless_stats);
2391 INIT_DELAYED_WORK(&priv->scan_work, rndis_get_scan_results);
2392
2387 /* try bind rndis_host */ 2393 /* try bind rndis_host */
2388 retval = generic_rndis_bind(usbdev, intf, FLAG_RNDIS_PHYM_WIRELESS); 2394 retval = generic_rndis_bind(usbdev, intf, FLAG_RNDIS_PHYM_WIRELESS);
2389 if (retval < 0) 2395 if (retval < 0)
@@ -2454,17 +2460,18 @@ static int rndis_wext_bind(struct usbnet *usbdev, struct usb_interface *intf)
2454 disassociate(usbdev, 1); 2460 disassociate(usbdev, 1);
2455 netif_carrier_off(usbdev->net); 2461 netif_carrier_off(usbdev->net);
2456 2462
2457 /* because rndis_command() sleeps we need to use workqueue */
2458 priv->workqueue = create_singlethread_workqueue("rndis_wlan");
2459 INIT_DELAYED_WORK(&priv->stats_work, rndis_update_wireless_stats);
2460 queue_delayed_work(priv->workqueue, &priv->stats_work, 2463 queue_delayed_work(priv->workqueue, &priv->stats_work,
2461 round_jiffies_relative(STATS_UPDATE_JIFFIES)); 2464 round_jiffies_relative(STATS_UPDATE_JIFFIES));
2462 INIT_DELAYED_WORK(&priv->scan_work, rndis_get_scan_results);
2463 INIT_WORK(&priv->work, rndis_wext_worker);
2464 2465
2465 return 0; 2466 return 0;
2466 2467
2467fail: 2468fail:
2469 cancel_delayed_work_sync(&priv->stats_work);
2470 cancel_delayed_work_sync(&priv->scan_work);
2471 cancel_work_sync(&priv->work);
2472 flush_workqueue(priv->workqueue);
2473 destroy_workqueue(priv->workqueue);
2474
2468 kfree(priv); 2475 kfree(priv);
2469 return retval; 2476 return retval;
2470} 2477}