From 7ed85b65ab611ba841d508ae4ff8c45fa0c48c80 Mon Sep 17 00:00:00 2001 From: Stanislav Yakovlev Date: Mon, 16 Apr 2012 06:38:30 -0400 Subject: net/wireless: ipw2200: Fix WARN_ON occurring in wiphy_register called by ipw_pci_probe The problem was found by Stefan Lippers-Hollmann http://marc.info/?l=linux-wireless&m=132720334512946&w=2 WARNING: at /tmp/buildd/linux-aptosid-3.2/debian/build/source_i386_none/net/wireless/core.c:562 wiphy_register+0x45/0x38d [cfg80211]() Hardware name: TravelMate 290 \xffffffff\xffffffff\xffffffff\xffffffff\xffffffff\xffffffff\xffffffff\xffffffff\xffffffff\xffffffff\xffffffff\xffffffff\xffffffff\xffffffff\xffffffff\xffffffff\xffffffff Modules linked in: ipw2200(+) iTCO_wdt libipw joydev drm snd_seq snd_timer snd_seq_device iTCO_vendor_support yenta_socket snd intel_agp i2c_i801 pcmcia_rsrc cfg80211 soundcore parport_pc psmouse parport rng_core snd_page_alloc serio_raw pcspkr i2c_algo_bit intel_gtt pcmcia_core evdev irda crc_ccitt rfkill lib80211 processor container ac battery shpchp pci_hotplug button ext4 mbcache jbd2 crc16 dm_mod sd_mod sr_mod crc_t10dif cdrom ata_generic pata_acpi ata_piix libata scsi_mod firewire_ohci firewire_core crc_itu_t 8139too 8139cp mii uhci_hcd ehci_hcd usbcore usb_common [last unloaded: scsi_wait_scan] Pid: 328, comm: modprobe Not tainted 3.2-1.slh.4-aptosid-686 #1 Call Trace: [] ? warn_slowpath_common+0x7c/0x8f [] ? wiphy_register+0x45/0x38d [cfg80211] [] ? wiphy_register+0x45/0x38d [cfg80211] [] ? warn_slowpath_null+0x1b/0x1f [] ? wiphy_register+0x45/0x38d [cfg80211] [] ? internal_create_group+0xf5/0xff [] ? ipw_pci_probe+0xa9a/0xbd0 [ipw2200] [] ? arch_local_irq_save+0xf/0x14 [] ? pci_device_probe+0x53/0x9a [] ? driver_probe_device+0x94/0x124 [] ? pci_match_id+0x15/0x34 [] ? __driver_attach+0x40/0x5b [] ? bus_for_each_dev+0x37/0x60 [] ? driver_attach+0x17/0x1a [] ? driver_probe_device+0x124/0x124 [] ? bus_add_driver+0x92/0x1d1 [] ? 0xe099cfff [] ? driver_register+0x7d/0xd4 [] ? jump_label_module_notify+0xec/0x167 [] ? 0xe099cfff [] ? __pci_register_driver+0x32/0x87 [] ? 0xe099cfff [] ? ipw_init+0x2e/0x72 [ipw2200] [] ? do_one_initcall+0x7d/0x132 [] ? __blocking_notifier_call_chain+0x47/0x4f [] ? sys_init_module+0x13a4/0x159c [] ? sysenter_do_call+0x12/0x28 This warning appears only if we apply Ben Hutchings' fix http://marc.info/?l=linux-wireless&m=132720195012653&w=2 for the bug reported by Cesare Leonardi http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=656813 with cfg80211 warning during device registration ("cfg80211: failed to add phy80211 symlink to netdev!"). We separate device bring up and registration with network stack to avoid the problem. After that Ben Hutchings' fix can be applied to fix the bug. Cc: stable@kernel.org Signed-off-by: Stanislav Yakovlev Tested-by: Stefan Lippers-Hollmann Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2x00/ipw2200.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) (limited to 'drivers/net/wireless/ipw2x00') diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index b3707dadad15..9a6d99048c17 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -11443,20 +11443,6 @@ static void ipw_bg_down(struct work_struct *work) mutex_unlock(&priv->mutex); } -/* Called by register_netdev() */ -static int ipw_net_init(struct net_device *dev) -{ - int rc = 0; - struct ipw_priv *priv = libipw_priv(dev); - - mutex_lock(&priv->mutex); - if (ipw_up(priv)) - rc = -EIO; - mutex_unlock(&priv->mutex); - - return rc; -} - static int ipw_wdev_init(struct net_device *dev) { int i, rc = 0; @@ -11725,7 +11711,6 @@ static void ipw_prom_free(struct ipw_priv *priv) #endif static const struct net_device_ops ipw_netdev_ops = { - .ndo_init = ipw_net_init, .ndo_open = ipw_net_open, .ndo_stop = ipw_net_stop, .ndo_set_rx_mode = ipw_net_set_multicast_list, @@ -11848,6 +11833,12 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev, goto out_release_irq; } + if (ipw_up(priv)) { + mutex_unlock(&priv->mutex); + err = -EIO; + goto out_remove_sysfs; + } + mutex_unlock(&priv->mutex); err = register_netdev(net_dev); if (err) { -- cgit v1.2.3 From b4050790d0a6bfec76e2186d461123cf9586aa34 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 22 Jan 2012 03:09:35 +0000 Subject: ipw2200: Fix order of device registration Currently cfg80211 fails to create a "phy80211" symlink in sysfs from the net device to the wiphy device. The latter needs to be registered first. Compile-tested only. Reported-by: Cesare Leonardi Signed-off-by: Ben Hutchings Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2x00/ipw2200.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'drivers/net/wireless/ipw2x00') diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 9a6d99048c17..0036737fe8e3 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -11840,16 +11840,17 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev, } mutex_unlock(&priv->mutex); - err = register_netdev(net_dev); + + err = ipw_wdev_init(net_dev); if (err) { - IPW_ERROR("failed to register network device\n"); + IPW_ERROR("failed to register wireless device\n"); goto out_remove_sysfs; } - err = ipw_wdev_init(net_dev); + err = register_netdev(net_dev); if (err) { - IPW_ERROR("failed to register wireless device\n"); - goto out_unregister_netdev; + IPW_ERROR("failed to register network device\n"); + goto out_unregister_wiphy; } #ifdef CONFIG_IPW2200_PROMISCUOUS @@ -11858,10 +11859,8 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev, if (err) { IPW_ERROR("Failed to register promiscuous network " "device (error %d).\n", err); - wiphy_unregister(priv->ieee->wdev.wiphy); - kfree(priv->ieee->a_band.channels); - kfree(priv->ieee->bg_band.channels); - goto out_unregister_netdev; + unregister_netdev(priv->net_dev); + goto out_unregister_wiphy; } } #endif @@ -11873,8 +11872,10 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev, return 0; - out_unregister_netdev: - unregister_netdev(priv->net_dev); + out_unregister_wiphy: + wiphy_unregister(priv->ieee->wdev.wiphy); + kfree(priv->ieee->a_band.channels); + kfree(priv->ieee->bg_band.channels); out_remove_sysfs: sysfs_remove_group(&pdev->dev.kobj, &ipw_attribute_group); out_release_irq: -- cgit v1.2.3 From e19d8baf8cfcc0b96d7578a22801d16400d877bd Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 22 Jan 2012 03:11:12 +0000 Subject: ipw2100: Fix order of device registration Currently cfg80211 fails to create a "phy80211" symlink in sysfs from the net device to the wiphy device. The latter needs to be registered first. Compile-tested only. Signed-off-by: Ben Hutchings Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2x00/ipw2100.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'drivers/net/wireless/ipw2x00') diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index c72136c07774..9cfae0c08707 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c @@ -1963,10 +1963,8 @@ static int ipw2100_wdev_init(struct net_device *dev) wdev->wiphy->n_cipher_suites = ARRAY_SIZE(ipw_cipher_suites); set_wiphy_dev(wdev->wiphy, &priv->pci_dev->dev); - if (wiphy_register(wdev->wiphy)) { - ipw2100_down(priv); + if (wiphy_register(wdev->wiphy)) return -EIO; - } return 0; } @@ -6331,6 +6329,11 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, printk(KERN_INFO DRV_NAME ": Detected Intel PRO/Wireless 2100 Network Connection\n"); + err = ipw2100_wdev_init(dev); + if (err) + goto fail; + registered = 1; + /* Bring up the interface. Pre 0.46, after we registered the * network device we would call ipw2100_up. This introduced a race * condition with newer hotplug configurations (network was coming @@ -6347,11 +6350,7 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, "Error calling register_netdev.\n"); goto fail; } - registered = 1; - - err = ipw2100_wdev_init(dev); - if (err) - goto fail; + registered = 2; mutex_lock(&priv->action_mutex); @@ -6390,13 +6389,16 @@ out: fail_unlock: mutex_unlock(&priv->action_mutex); - wiphy_unregister(priv->ieee->wdev.wiphy); - kfree(priv->ieee->bg_band.channels); fail: if (dev) { - if (registered) + if (registered >= 2) unregister_netdev(dev); + if (registered) { + wiphy_unregister(priv->ieee->wdev.wiphy); + kfree(priv->ieee->bg_band.channels); + } + ipw2100_hw_stop_adapter(priv); ipw2100_disable_interrupts(priv); -- cgit v1.2.3