diff options
author | Zhu Yi <yi.zhu@intel.com> | 2009-06-15 21:36:13 +0200 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-06-19 17:50:15 +0200 |
commit | 8d96e7960b6b520eb52be6e1eb7c794da5db9555 (patch) | |
tree | 8df4c510bef677704318d0868fa9a6748ff4ef5c /drivers/net | |
parent | netxen: fix tx ring accounting (diff) | |
download | linux-8d96e7960b6b520eb52be6e1eb7c794da5db9555.tar.xz linux-8d96e7960b6b520eb52be6e1eb7c794da5db9555.zip |
iwmc3200wifi: check for iwm_priv_init error
We need to check for iwm_priv_init() errors and do proper cleanups.
Otherwise we may fail to catch the create_singlethread_workqueue()
error which will cause a kernel oops when destroy_workqueue() later.
Signed-off-by: Zhu Yi <yi.zhu@intel.com>
Signed-off-by: Samuel Ortiz <samuel.ortiz@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/iwmc3200wifi/iwm.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/iwmc3200wifi/main.c | 10 | ||||
-rw-r--r-- | drivers/net/wireless/iwmc3200wifi/netdev.c | 19 |
3 files changed, 23 insertions, 7 deletions
diff --git a/drivers/net/wireless/iwmc3200wifi/iwm.h b/drivers/net/wireless/iwmc3200wifi/iwm.h index 635c16ee6186..2237448e0427 100644 --- a/drivers/net/wireless/iwmc3200wifi/iwm.h +++ b/drivers/net/wireless/iwmc3200wifi/iwm.h @@ -317,6 +317,7 @@ void *iwm_if_alloc(int sizeof_bus, struct device *dev, void iwm_if_free(struct iwm_priv *iwm); int iwm_mode_to_nl80211_iftype(int mode); int iwm_priv_init(struct iwm_priv *iwm); +void iwm_priv_deinit(struct iwm_priv *iwm); void iwm_reset(struct iwm_priv *iwm); void iwm_tx_credit_init_pools(struct iwm_priv *iwm, struct iwm_umac_notif_alive *alive); diff --git a/drivers/net/wireless/iwmc3200wifi/main.c b/drivers/net/wireless/iwmc3200wifi/main.c index 6a2640f16b6d..4d3c423d8ffc 100644 --- a/drivers/net/wireless/iwmc3200wifi/main.c +++ b/drivers/net/wireless/iwmc3200wifi/main.c @@ -219,6 +219,16 @@ int iwm_priv_init(struct iwm_priv *iwm) return 0; } +void iwm_priv_deinit(struct iwm_priv *iwm) +{ + int i; + + for (i = 0; i < IWM_TX_QUEUES; i++) + destroy_workqueue(iwm->txq[i].wq); + + destroy_workqueue(iwm->rx_wq); +} + /* * We reset all the structures, and we reset the UMAC. * After calling this routine, you're expected to reload diff --git a/drivers/net/wireless/iwmc3200wifi/netdev.c b/drivers/net/wireless/iwmc3200wifi/netdev.c index 68e2c3b6c7a1..88dd82649b47 100644 --- a/drivers/net/wireless/iwmc3200wifi/netdev.c +++ b/drivers/net/wireless/iwmc3200wifi/netdev.c @@ -114,14 +114,20 @@ void *iwm_if_alloc(int sizeof_bus, struct device *dev, iwm = wdev_to_iwm(wdev); iwm->bus_ops = if_ops; iwm->wdev = wdev; - iwm_priv_init(iwm); + + ret = iwm_priv_init(iwm); + if (ret) { + dev_err(dev, "failed to init iwm_priv\n"); + goto out_wdev; + } + wdev->iftype = iwm_mode_to_nl80211_iftype(iwm->conf.mode); ndev = alloc_netdev_mq(0, "wlan%d", ether_setup, IWM_TX_QUEUES); if (!ndev) { dev_err(dev, "no memory for network device instance\n"); - goto out_wdev; + goto out_priv; } ndev->netdev_ops = &iwm_netdev_ops; @@ -141,6 +147,9 @@ void *iwm_if_alloc(int sizeof_bus, struct device *dev, out_ndev: free_netdev(ndev); + out_priv: + iwm_priv_deinit(iwm); + out_wdev: iwm_wdev_free(iwm); return ERR_PTR(ret); @@ -148,15 +157,11 @@ void *iwm_if_alloc(int sizeof_bus, struct device *dev, void iwm_if_free(struct iwm_priv *iwm) { - int i; - if (!iwm_to_ndev(iwm)) return; unregister_netdev(iwm_to_ndev(iwm)); free_netdev(iwm_to_ndev(iwm)); iwm_wdev_free(iwm); - destroy_workqueue(iwm->rx_wq); - for (i = 0; i < IWM_TX_QUEUES; i++) - destroy_workqueue(iwm->txq[i].wq); + iwm_priv_deinit(iwm); } |