Commit 8d96e796 authored by Zhu Yi's avatar Zhu Yi Committed by John W. Linville

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: default avatarZhu Yi <yi.zhu@intel.com>
Signed-off-by: default avatarSamuel Ortiz <samuel.ortiz@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent cb2107be
...@@ -317,6 +317,7 @@ void *iwm_if_alloc(int sizeof_bus, struct device *dev, ...@@ -317,6 +317,7 @@ void *iwm_if_alloc(int sizeof_bus, struct device *dev,
void iwm_if_free(struct iwm_priv *iwm); void iwm_if_free(struct iwm_priv *iwm);
int iwm_mode_to_nl80211_iftype(int mode); int iwm_mode_to_nl80211_iftype(int mode);
int iwm_priv_init(struct iwm_priv *iwm); 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_reset(struct iwm_priv *iwm);
void iwm_tx_credit_init_pools(struct iwm_priv *iwm, void iwm_tx_credit_init_pools(struct iwm_priv *iwm,
struct iwm_umac_notif_alive *alive); struct iwm_umac_notif_alive *alive);
......
...@@ -219,6 +219,16 @@ int iwm_priv_init(struct iwm_priv *iwm) ...@@ -219,6 +219,16 @@ int iwm_priv_init(struct iwm_priv *iwm)
return 0; 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. * We reset all the structures, and we reset the UMAC.
* After calling this routine, you're expected to reload * After calling this routine, you're expected to reload
......
...@@ -114,14 +114,20 @@ void *iwm_if_alloc(int sizeof_bus, struct device *dev, ...@@ -114,14 +114,20 @@ void *iwm_if_alloc(int sizeof_bus, struct device *dev,
iwm = wdev_to_iwm(wdev); iwm = wdev_to_iwm(wdev);
iwm->bus_ops = if_ops; iwm->bus_ops = if_ops;
iwm->wdev = wdev; 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); wdev->iftype = iwm_mode_to_nl80211_iftype(iwm->conf.mode);
ndev = alloc_netdev_mq(0, "wlan%d", ether_setup, ndev = alloc_netdev_mq(0, "wlan%d", ether_setup,
IWM_TX_QUEUES); IWM_TX_QUEUES);
if (!ndev) { if (!ndev) {
dev_err(dev, "no memory for network device instance\n"); dev_err(dev, "no memory for network device instance\n");
goto out_wdev; goto out_priv;
} }
ndev->netdev_ops = &iwm_netdev_ops; ndev->netdev_ops = &iwm_netdev_ops;
...@@ -141,6 +147,9 @@ void *iwm_if_alloc(int sizeof_bus, struct device *dev, ...@@ -141,6 +147,9 @@ void *iwm_if_alloc(int sizeof_bus, struct device *dev,
out_ndev: out_ndev:
free_netdev(ndev); free_netdev(ndev);
out_priv:
iwm_priv_deinit(iwm);
out_wdev: out_wdev:
iwm_wdev_free(iwm); iwm_wdev_free(iwm);
return ERR_PTR(ret); return ERR_PTR(ret);
...@@ -148,15 +157,11 @@ void *iwm_if_alloc(int sizeof_bus, struct device *dev, ...@@ -148,15 +157,11 @@ void *iwm_if_alloc(int sizeof_bus, struct device *dev,
void iwm_if_free(struct iwm_priv *iwm) void iwm_if_free(struct iwm_priv *iwm)
{ {
int i;
if (!iwm_to_ndev(iwm)) if (!iwm_to_ndev(iwm))
return; return;
unregister_netdev(iwm_to_ndev(iwm)); unregister_netdev(iwm_to_ndev(iwm));
free_netdev(iwm_to_ndev(iwm)); free_netdev(iwm_to_ndev(iwm));
iwm_wdev_free(iwm); iwm_wdev_free(iwm);
destroy_workqueue(iwm->rx_wq); iwm_priv_deinit(iwm);
for (i = 0; i < IWM_TX_QUEUES; i++)
destroy_workqueue(iwm->txq[i].wq);
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment