ipw2200: fix oops on missing firmware
For non-monitor interfaces, the syntax for alloc_ieee80211/free_80211
is wrong. Because alloc_ieee80211 only creates (wiphy_new) a wiphy, but
free_80211() does wiphy_unregister() also. This is only correct when
the later wiphy_register() is called successfully, which apparently
is not the case for your fw doesn't exist one.
Signed-off-by: Zhu Yi <yi.zhu@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c
index 240cff1..a741d37 100644
--- a/drivers/net/wireless/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/ipw2x00/ipw2100.c
@@ -6325,8 +6325,10 @@
fail:
if (dev) {
- if (registered)
+ if (registered) {
+ unregister_ieee80211(priv->ieee);
unregister_netdev(dev);
+ }
ipw2100_hw_stop_adapter(priv);
@@ -6383,6 +6385,7 @@
/* Unregister the device first - this results in close()
* being called if the device is open. If we free storage
* first, then close() will crash. */
+ unregister_ieee80211(priv->ieee);
unregister_netdev(dev);
/* ipw2100_down will ensure that there is no more pending work
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c
index 8d58e6e..04341a2 100644
--- a/drivers/net/wireless/ipw2x00/ipw2200.c
+++ b/drivers/net/wireless/ipw2x00/ipw2200.c
@@ -11821,6 +11821,7 @@
if (err) {
IPW_ERROR("Failed to register promiscuous network "
"device (error %d).\n", err);
+ unregister_ieee80211(priv->ieee);
unregister_netdev(priv->net_dev);
goto out_remove_sysfs;
}
@@ -11871,6 +11872,7 @@
mutex_unlock(&priv->mutex);
+ unregister_ieee80211(priv->ieee);
unregister_netdev(priv->net_dev);
if (priv->rxq) {
diff --git a/drivers/net/wireless/ipw2x00/libipw.h b/drivers/net/wireless/ipw2x00/libipw.h
index bf45391..f42ade6 100644
--- a/drivers/net/wireless/ipw2x00/libipw.h
+++ b/drivers/net/wireless/ipw2x00/libipw.h
@@ -1020,6 +1020,7 @@
/* ieee80211.c */
extern void free_ieee80211(struct net_device *dev, int monitor);
extern struct net_device *alloc_ieee80211(int sizeof_priv, int monitor);
+extern void unregister_ieee80211(struct libipw_device *ieee);
extern int libipw_change_mtu(struct net_device *dev, int new_mtu);
extern void libipw_networks_age(struct libipw_device *ieee,
diff --git a/drivers/net/wireless/ipw2x00/libipw_module.c b/drivers/net/wireless/ipw2x00/libipw_module.c
index a0e9f6a..be5b809 100644
--- a/drivers/net/wireless/ipw2x00/libipw_module.c
+++ b/drivers/net/wireless/ipw2x00/libipw_module.c
@@ -235,16 +235,19 @@
libipw_networks_free(ieee);
/* free cfg80211 resources */
- if (!monitor) {
- wiphy_unregister(ieee->wdev.wiphy);
- kfree(ieee->a_band.channels);
- kfree(ieee->bg_band.channels);
+ if (!monitor)
wiphy_free(ieee->wdev.wiphy);
- }
free_netdev(dev);
}
+void unregister_ieee80211(struct libipw_device *ieee)
+{
+ wiphy_unregister(ieee->wdev.wiphy);
+ kfree(ieee->a_band.channels);
+ kfree(ieee->bg_band.channels);
+}
+
#ifdef CONFIG_LIBIPW_DEBUG
static int debug = 0;
@@ -330,3 +333,4 @@
EXPORT_SYMBOL(alloc_ieee80211);
EXPORT_SYMBOL(free_ieee80211);
+EXPORT_SYMBOL(unregister_ieee80211);