brcmfmac: Fix rtnl_lock lockup when registering netdev.
authorHante Meuleman <meuleman@broadcom.com>
Fri, 8 Feb 2013 14:53:59 +0000 (15:53 +0100)
committerJohn W. Linville <linville@tuxdriver.com>
Fri, 8 Feb 2013 19:51:42 +0000 (14:51 -0500)
When adding a virtual interface cfg80211 already has taken the
rtnl_lock. So when the netdevice is being registered the
register_netdevice should be used instead of register_netdev.

Reviewed-by: Arend Van Spriel <arend@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Piotr Haber <phaber@broadcom.com>
Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/brcm80211/brcmfmac/dhd.h
drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
drivers/net/wireless/brcm80211/brcmfmac/fweh.c
drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c

index c4a6083fb1a0d2a54e25dc6e310e40cb4e7ca49e..ef6f23be6d32068c551050bf8d87d6e11ccdbb08 100644 (file)
@@ -585,7 +585,7 @@ extern int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
 extern int brcmf_proto_hdrpull(struct brcmf_pub *drvr, u8 *ifidx,
                               struct sk_buff *rxp);
 
-extern int brcmf_net_attach(struct brcmf_if *ifp);
+extern int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked);
 extern struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx,
                                     s32 ifidx, char *name, u8 *mac_addr);
 extern void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx);
index e61be4d357415bcd60fb108f55fa15bfaf41e61b..6e3846ca88be299afcebe2c817835e0a4dd8e365 100644 (file)
@@ -599,10 +599,11 @@ static const struct net_device_ops brcmf_netdev_ops_pri = {
        .ndo_set_rx_mode = brcmf_netdev_set_multicast_list
 };
 
-int brcmf_net_attach(struct brcmf_if *ifp)
+int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked)
 {
        struct brcmf_pub *drvr = ifp->drvr;
        struct net_device *ndev;
+       s32 err;
 
        brcmf_dbg(TRACE, "Enter, idx=%d mac=%pM\n", ifp->bssidx,
                  ifp->mac_addr);
@@ -623,7 +624,11 @@ int brcmf_net_attach(struct brcmf_if *ifp)
        INIT_WORK(&ifp->setmacaddr_work, _brcmf_set_mac_address);
        INIT_WORK(&ifp->multicast_work, _brcmf_set_multicast_list);
 
-       if (register_netdev(ndev) != 0) {
+       if (rtnl_locked)
+               err = register_netdevice(ndev);
+       else
+               err = register_netdev(ndev);
+       if (err != 0) {
                brcmf_err("couldn't register the net device\n");
                goto fail;
        }
@@ -876,7 +881,7 @@ int brcmf_bus_start(struct device *dev)
        if (ret < 0)
                goto fail;
 
-       ret = brcmf_net_attach(ifp);
+       ret = brcmf_net_attach(ifp, false);
 fail:
        if (ret < 0) {
                brcmf_err("failed: %d\n", ret);
index 1fd29b08e632831ca925a68e1adc8806cc16dd36..e9d6f91a1f2beb5b9f2315c5394f3e69096b3ddd 100644 (file)
@@ -200,7 +200,7 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr,
                        return;
 
                if (!drvr->fweh.evt_handler[BRCMF_E_IF])
-                       err = brcmf_net_attach(ifp);
+                       err = brcmf_net_attach(ifp, false);
        }
 
        err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data);
index f283a7e969f04d0b6d1a5f84701f55a57bce685c..6cdb578fc37b0598924f9b1f316d98b4f234a1fe 100644 (file)
@@ -4668,7 +4668,7 @@ static s32 brcmf_notify_vif_event(struct brcmf_if *ifp,
 
                /* waiting process need to set the netdev name */
                wait_for_completion(&event->vif_complete);
-               return brcmf_net_attach(ifp);
+               return brcmf_net_attach(ifp, true);
 
        case BRCMF_E_IF_DEL:
                ifp->vif = NULL;