iwmc3200wifi: check for iwm_priv_init error
authorZhu Yi <yi.zhu@intel.com>
Mon, 15 Jun 2009 19:36:13 +0000 (21:36 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Fri, 19 Jun 2009 15:50:15 +0000 (11:50 -0400)
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>
drivers/net/wireless/iwmc3200wifi/iwm.h
drivers/net/wireless/iwmc3200wifi/main.c
drivers/net/wireless/iwmc3200wifi/netdev.c

index 635c16e..2237448 100644 (file)
@@ -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);
index 6a2640f..4d3c423 100644 (file)
@@ -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
index 68e2c3b..88dd826 100644 (file)
@@ -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);
 }