Path: news.gmane.org!not-for-mail From: Stanislaw Gruszka Newsgroups: gmane.linux.kernel.wireless.general Subject: [PATCH] ipw2x00: fix rtnl mutex deadlock Date: Wed, 14 Sep 2011 16:47:50 +0200 Lines: 173 Approved: news@gmane.org Message-ID: <1316011670-6787-1-git-send-email-sgruszka@redhat.com> NNTP-Posting-Host: lo.gmane.org X-Trace: dough.gmane.org 1316011688 20989 80.91.229.12 (14 Sep 2011 14:48:08 GMT) X-Complaints-To: usenet@dough.gmane.org NNTP-Posting-Date: Wed, 14 Sep 2011 14:48:08 +0000 (UTC) Cc: linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Andrew Morton , "Rafael J. Wysocki" , Maciej Rutecki , Michael Witten , Witold Baryluk , Stanislaw Gruszka To: "John W. Linville" Original-X-From: linux-wireless-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org Wed Sep 14 16:48:02 2011 Return-path: Envelope-to: glkwg-linux-wireless-1dZseelyfdZg9hUCZPvPmw@public.gmane.org Original-Received: from vger.kernel.org ([209.132.180.67]) by lo.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1R3qkr-0005Xu-KZ for glkwg-linux-wireless-1dZseelyfdZg9hUCZPvPmw@public.gmane.org; Wed, 14 Sep 2011 16:48:02 +0200 Original-Received: (majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org) by vger.kernel.org via listexpand id S1755562Ab1INOr7 (ORCPT ); Wed, 14 Sep 2011 10:47:59 -0400 Original-Received: from mx1.redhat.com ([209.132.183.28]:50585 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751756Ab1INOr7 (ORCPT ); Wed, 14 Sep 2011 10:47:59 -0400 Original-Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p8EEldiu028562 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Wed, 14 Sep 2011 10:47:40 -0400 Original-Received: from localhost (dhcp-27-35.brq.redhat.com [10.34.27.35]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id p8EElaD3010274; Wed, 14 Sep 2011 10:47:37 -0400 X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Original-Sender: linux-wireless-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org Xref: news.gmane.org gmane.linux.kernel.wireless.general:77103 Archived-At: This fix regression introduced by: commit: ecb4433550f0620f3d1471ae7099037ede30a91e Author: Stanislaw Gruszka Date: Fri Aug 12 14:00:59 2011 +0200 mac80211: fix suspend/resume races with unregister hw Above commit add rtnl_lock() into wiphy_register(), what cause deadlock when initializing ipw2x00 driver, which itself call wiphy_register() from register_netdev() internal callback with rtnl mutex taken. To fix move wiphy_register() outside register_netdev(). This solution have side effect of not creating /sys/class/net/wlanX/phy80211 link, but that's a minor issue we can live with. Bisected-by: Witold Baryluk Bisected-by: Michael Witten Tested-by: Witold Baryluk Tested-by: Michael Witten Signed-off-by: Stanislaw Gruszka --- ecb4433550f0620f3d1471ae7099037ede30a91e was CCed to stable but we drop it there, when bug was reported. So this patch is only intended to 3.1 drivers/net/wireless/ipw2x00/ipw2100.c | 21 +++++++++++----- drivers/net/wireless/ipw2x00/ipw2200.c | 39 +++++++++++++++++++++---------- 2 files changed, 40 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 3774dd0..ef9ad79 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c @@ -1903,15 +1903,17 @@ static void ipw2100_down(struct ipw2100_priv *priv) static int ipw2100_net_init(struct net_device *dev) { struct ipw2100_priv *priv = libipw_priv(dev); + + return ipw2100_up(priv, 1); +} + +static int ipw2100_wdev_init(struct net_device *dev) +{ + struct ipw2100_priv *priv = libipw_priv(dev); const struct libipw_geo *geo = libipw_get_geo(priv->ieee); struct wireless_dev *wdev = &priv->ieee->wdev; - int ret; int i; - ret = ipw2100_up(priv, 1); - if (ret) - return ret; - memcpy(wdev->wiphy->perm_addr, priv->mac_addr, ETH_ALEN); /* fill-out priv->ieee->bg_band */ @@ -6350,9 +6352,13 @@ 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; mutex_lock(&priv->action_mutex); - registered = 1; IPW_DEBUG_INFO("%s: Bound to %s\n", dev->name, pci_name(pci_dev)); @@ -6389,7 +6395,8 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, fail_unlock: mutex_unlock(&priv->action_mutex); - + wiphy_unregister(priv->ieee->wdev.wiphy); + kfree(priv->ieee->bg_band.channels); fail: if (dev) { if (registered) diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 87813c3..4ffebed 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -11425,16 +11425,23 @@ static void ipw_bg_down(struct work_struct *work) /* 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; struct ipw_priv *priv = libipw_priv(dev); const struct libipw_geo *geo = libipw_get_geo(priv->ieee); struct wireless_dev *wdev = &priv->ieee->wdev; - mutex_lock(&priv->mutex); - - if (ipw_up(priv)) { - rc = -EIO; - goto out; - } memcpy(wdev->wiphy->perm_addr, priv->mac_addr, ETH_ALEN); @@ -11519,13 +11526,9 @@ static int ipw_net_init(struct net_device *dev) set_wiphy_dev(wdev->wiphy, &priv->pci_dev->dev); /* With that information in place, we can now register the wiphy... */ - if (wiphy_register(wdev->wiphy)) { + if (wiphy_register(wdev->wiphy)) rc = -EIO; - goto out; - } - out: - mutex_unlock(&priv->mutex); return rc; } @@ -11832,14 +11835,22 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev, goto out_remove_sysfs; } + err = ipw_wdev_init(net_dev); + if (err) { + IPW_ERROR("failed to register wireless device\n"); + goto out_unregister_netdev; + } + #ifdef CONFIG_IPW2200_PROMISCUOUS if (rtap_iface) { err = ipw_prom_alloc(priv); if (err) { IPW_ERROR("Failed to register promiscuous network " "device (error %d).\n", err); - unregister_netdev(priv->net_dev); - goto out_remove_sysfs; + wiphy_unregister(priv->ieee->wdev.wiphy); + kfree(priv->ieee->a_band.channels); + kfree(priv->ieee->bg_band.channels); + goto out_unregister_netdev; } } #endif @@ -11851,6 +11862,8 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev, return 0; + out_unregister_netdev: + unregister_netdev(priv->net_dev); out_remove_sysfs: sysfs_remove_group(&pdev->dev.kobj, &ipw_attribute_group); out_release_irq: -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org More majordomo info at http://vger.kernel.org/majordomo-info.html