aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwmc3200wifi
diff options
context:
space:
mode:
authorZhu Yi <yi.zhu@intel.com>2009-06-15 15:36:13 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-06-19 11:50:15 -0400
commit8d96e7960b6b520eb52be6e1eb7c794da5db9555 (patch)
tree8df4c510bef677704318d0868fa9a6748ff4ef5c /drivers/net/wireless/iwmc3200wifi
parentcb2107be43d2fc5eadec58b92b54bf32c00bfff3 (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.h1
-rw-r--r--drivers/net/wireless/iwmc3200wifi/main.c10
-rw-r--r--drivers/net/wireless/iwmc3200wifi/netdev.c19
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,
317void iwm_if_free(struct iwm_priv *iwm); 317void iwm_if_free(struct iwm_priv *iwm);
318int iwm_mode_to_nl80211_iftype(int mode); 318int iwm_mode_to_nl80211_iftype(int mode);
319int iwm_priv_init(struct iwm_priv *iwm); 319int iwm_priv_init(struct iwm_priv *iwm);
320void iwm_priv_deinit(struct iwm_priv *iwm);
320void iwm_reset(struct iwm_priv *iwm); 321void iwm_reset(struct iwm_priv *iwm);
321void iwm_tx_credit_init_pools(struct iwm_priv *iwm, 322void 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
222void 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
149void iwm_if_free(struct iwm_priv *iwm) 158void 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}