diff options
author | Zhu Yi <yi.zhu@intel.com> | 2009-06-15 15:36:13 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-06-19 11:50:15 -0400 |
commit | 8d96e7960b6b520eb52be6e1eb7c794da5db9555 (patch) | |
tree | 8df4c510bef677704318d0868fa9a6748ff4ef5c /drivers/net/wireless/iwmc3200wifi | |
parent | cb2107be43d2fc5eadec58b92b54bf32c00bfff3 (diff) |
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/wireless/iwmc3200wifi')
-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, | |||
317 | void iwm_if_free(struct iwm_priv *iwm); | 317 | void iwm_if_free(struct iwm_priv *iwm); |
318 | int iwm_mode_to_nl80211_iftype(int mode); | 318 | int iwm_mode_to_nl80211_iftype(int mode); |
319 | int iwm_priv_init(struct iwm_priv *iwm); | 319 | int iwm_priv_init(struct iwm_priv *iwm); |
320 | void iwm_priv_deinit(struct iwm_priv *iwm); | ||
320 | void iwm_reset(struct iwm_priv *iwm); | 321 | void iwm_reset(struct iwm_priv *iwm); |
321 | void iwm_tx_credit_init_pools(struct iwm_priv *iwm, | 322 | void iwm_tx_credit_init_pools(struct iwm_priv *iwm, |
322 | struct iwm_umac_notif_alive *alive); | 323 | 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) | |||
219 | return 0; | 219 | return 0; |
220 | } | 220 | } |
221 | 221 | ||
222 | void iwm_priv_deinit(struct iwm_priv *iwm) | ||
223 | { | ||
224 | int i; | ||
225 | |||
226 | for (i = 0; i < IWM_TX_QUEUES; i++) | ||
227 | destroy_workqueue(iwm->txq[i].wq); | ||
228 | |||
229 | destroy_workqueue(iwm->rx_wq); | ||
230 | } | ||
231 | |||
222 | /* | 232 | /* |
223 | * We reset all the structures, and we reset the UMAC. | 233 | * We reset all the structures, and we reset the UMAC. |
224 | * After calling this routine, you're expected to reload | 234 | * 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, | |||
114 | iwm = wdev_to_iwm(wdev); | 114 | iwm = wdev_to_iwm(wdev); |
115 | iwm->bus_ops = if_ops; | 115 | iwm->bus_ops = if_ops; |
116 | iwm->wdev = wdev; | 116 | iwm->wdev = wdev; |
117 | iwm_priv_init(iwm); | 117 | |
118 | ret = iwm_priv_init(iwm); | ||
119 | if (ret) { | ||
120 | dev_err(dev, "failed to init iwm_priv\n"); | ||
121 | goto out_wdev; | ||
122 | } | ||
123 | |||
118 | wdev->iftype = iwm_mode_to_nl80211_iftype(iwm->conf.mode); | 124 | wdev->iftype = iwm_mode_to_nl80211_iftype(iwm->conf.mode); |
119 | 125 | ||
120 | ndev = alloc_netdev_mq(0, "wlan%d", ether_setup, | 126 | ndev = alloc_netdev_mq(0, "wlan%d", ether_setup, |
121 | IWM_TX_QUEUES); | 127 | IWM_TX_QUEUES); |
122 | if (!ndev) { | 128 | if (!ndev) { |
123 | dev_err(dev, "no memory for network device instance\n"); | 129 | dev_err(dev, "no memory for network device instance\n"); |
124 | goto out_wdev; | 130 | goto out_priv; |
125 | } | 131 | } |
126 | 132 | ||
127 | ndev->netdev_ops = &iwm_netdev_ops; | 133 | ndev->netdev_ops = &iwm_netdev_ops; |
@@ -141,6 +147,9 @@ void *iwm_if_alloc(int sizeof_bus, struct device *dev, | |||
141 | out_ndev: | 147 | out_ndev: |
142 | free_netdev(ndev); | 148 | free_netdev(ndev); |
143 | 149 | ||
150 | out_priv: | ||
151 | iwm_priv_deinit(iwm); | ||
152 | |||
144 | out_wdev: | 153 | out_wdev: |
145 | iwm_wdev_free(iwm); | 154 | iwm_wdev_free(iwm); |
146 | return ERR_PTR(ret); | 155 | return ERR_PTR(ret); |
@@ -148,15 +157,11 @@ void *iwm_if_alloc(int sizeof_bus, struct device *dev, | |||
148 | 157 | ||
149 | void iwm_if_free(struct iwm_priv *iwm) | 158 | void iwm_if_free(struct iwm_priv *iwm) |
150 | { | 159 | { |
151 | int i; | ||
152 | |||
153 | if (!iwm_to_ndev(iwm)) | 160 | if (!iwm_to_ndev(iwm)) |
154 | return; | 161 | return; |
155 | 162 | ||
156 | unregister_netdev(iwm_to_ndev(iwm)); | 163 | unregister_netdev(iwm_to_ndev(iwm)); |
157 | free_netdev(iwm_to_ndev(iwm)); | 164 | free_netdev(iwm_to_ndev(iwm)); |
158 | iwm_wdev_free(iwm); | 165 | iwm_wdev_free(iwm); |
159 | destroy_workqueue(iwm->rx_wq); | 166 | iwm_priv_deinit(iwm); |
160 | for (i = 0; i < IWM_TX_QUEUES; i++) | ||
161 | destroy_workqueue(iwm->txq[i].wq); | ||
162 | } | 167 | } |