brcm80211: fmac: change function bus_txdata parameter
[deliverable/linux.git] / drivers / net / wireless / brcm80211 / brcmfmac / dhd_linux.c
index 4acbac5a74c6ee41a44981cd886c89172408eb2c..1cfe9f3dbe0e8c3068ec9c355e8a937404c59ab6 100644 (file)
@@ -43,7 +43,6 @@
 #include "dhd_proto.h"
 #include "dhd_dbg.h"
 #include "wl_cfg80211.h"
-#include "bcmchip.h"
 
 MODULE_AUTHOR("Broadcom Corporation");
 MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN fullmac driver.");
@@ -58,7 +57,6 @@ struct brcmf_if {
        struct net_device *ndev;
        struct net_device_stats stats;
        int idx;                /* iface idx in dongle */
-       int state;              /* interface state */
        u8 mac_addr[ETH_ALEN];  /* assigned MAC address */
 };
 
@@ -78,22 +76,9 @@ struct brcmf_info {
 };
 
 /* Error bits */
+int brcmf_msg_level = BRCMF_ERROR_VAL;
 module_param(brcmf_msg_level, int, 0);
 
-
-static int brcmf_net2idx(struct brcmf_info *drvr_priv, struct net_device *ndev)
-{
-       int i = 0;
-
-       while (i < BRCMF_MAX_IFS) {
-               if (drvr_priv->iflist[i] && drvr_priv->iflist[i]->ndev == ndev)
-                       return i;
-               i++;
-       }
-
-       return BRCMF_BAD_IF;
-}
-
 int brcmf_ifname2idx(struct brcmf_info *drvr_priv, char *name)
 {
        int i = BRCMF_MAX_IFS;
@@ -285,14 +270,9 @@ _brcmf_set_mac_address(struct work_struct *work)
 
 static int brcmf_netdev_set_mac_address(struct net_device *ndev, void *addr)
 {
-       struct brcmf_info *drvr_priv = *(struct brcmf_info **)
-                                       netdev_priv(ndev);
+       struct brcmf_if *ifp = netdev_priv(ndev);
+       struct brcmf_info *drvr_priv = ifp->info;
        struct sockaddr *sa = (struct sockaddr *)addr;
-       int ifidx;
-
-       ifidx = brcmf_net2idx(drvr_priv, ndev);
-       if (ifidx == BRCMF_BAD_IF)
-               return -1;
 
        memcpy(&drvr_priv->macvalue, sa->sa_data, ETH_ALEN);
        schedule_work(&drvr_priv->setmacaddr_work);
@@ -301,13 +281,8 @@ static int brcmf_netdev_set_mac_address(struct net_device *ndev, void *addr)
 
 static void brcmf_netdev_set_multicast_list(struct net_device *ndev)
 {
-       struct brcmf_info *drvr_priv = *(struct brcmf_info **)
-                                       netdev_priv(ndev);
-       int ifidx;
-
-       ifidx = brcmf_net2idx(drvr_priv, ndev);
-       if (ifidx == BRCMF_BAD_IF)
-               return;
+       struct brcmf_if *ifp = netdev_priv(ndev);
+       struct brcmf_info *drvr_priv = ifp->info;
 
        schedule_work(&drvr_priv->multicast_work);
 }
@@ -317,7 +292,7 @@ int brcmf_sendpkt(struct brcmf_pub *drvr, int ifidx, struct sk_buff *pktbuf)
        struct brcmf_info *drvr_priv = drvr->info;
 
        /* Reject if down */
-       if (!drvr->up || (drvr->busstate == BRCMF_BUS_DOWN))
+       if (!drvr->up || (drvr->bus_if->state == BRCMF_BUS_DOWN))
                return -ENODEV;
 
        /* Update multicast statistic */
@@ -335,29 +310,29 @@ int brcmf_sendpkt(struct brcmf_pub *drvr, int ifidx, struct sk_buff *pktbuf)
        brcmf_proto_hdrpush(drvr, ifidx, pktbuf);
 
        /* Use bus module to send data frame */
-       return brcmf_sdbrcm_bus_txdata(drvr->bus, pktbuf);
+       return brcmf_sdbrcm_bus_txdata(drvr->dev, pktbuf);
 }
 
 static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 {
        int ret;
-       struct brcmf_info *drvr_priv = *(struct brcmf_info **)
-                                       netdev_priv(ndev);
-       int ifidx;
+       struct brcmf_if *ifp = netdev_priv(ndev);
+       struct brcmf_info *drvr_priv = ifp->info;
 
        brcmf_dbg(TRACE, "Enter\n");
 
        /* Reject if down */
-       if (!drvr_priv->pub.up || (drvr_priv->pub.busstate == BRCMF_BUS_DOWN)) {
-               brcmf_dbg(ERROR, "xmit rejected pub.up=%d busstate=%d\n",
-                         drvr_priv->pub.up, drvr_priv->pub.busstate);
+       if (!drvr_priv->pub.up ||
+           (drvr_priv->pub.bus_if->state == BRCMF_BUS_DOWN)) {
+               brcmf_dbg(ERROR, "xmit rejected pub.up=%d state=%d\n",
+                         drvr_priv->pub.up,
+                         drvr_priv->pub.bus_if->state);
                netif_stop_queue(ndev);
                return -ENODEV;
        }
 
-       ifidx = brcmf_net2idx(drvr_priv, ndev);
-       if (ifidx == BRCMF_BAD_IF) {
-               brcmf_dbg(ERROR, "bad ifidx %d\n", ifidx);
+       if (!drvr_priv->iflist[ifp->idx]) {
+               brcmf_dbg(ERROR, "bad ifidx %d\n", ifp->idx);
                netif_stop_queue(ndev);
                return -ENODEV;
        }
@@ -367,20 +342,20 @@ static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev)
                struct sk_buff *skb2;
 
                brcmf_dbg(INFO, "%s: insufficient headroom\n",
-                         brcmf_ifname(&drvr_priv->pub, ifidx));
+                         brcmf_ifname(&drvr_priv->pub, ifp->idx));
                drvr_priv->pub.tx_realloc++;
                skb2 = skb_realloc_headroom(skb, drvr_priv->pub.hdrlen);
                dev_kfree_skb(skb);
                skb = skb2;
                if (skb == NULL) {
                        brcmf_dbg(ERROR, "%s: skb_realloc_headroom failed\n",
-                                 brcmf_ifname(&drvr_priv->pub, ifidx));
+                                 brcmf_ifname(&drvr_priv->pub, ifp->idx));
                        ret = -ENOMEM;
                        goto done;
                }
        }
 
-       ret = brcmf_sendpkt(&drvr_priv->pub, ifidx, skb);
+       ret = brcmf_sendpkt(&drvr_priv->pub, ifp->idx, skb);
 
 done:
        if (ret)
@@ -424,26 +399,21 @@ static int brcmf_host_event(struct brcmf_info *drvr_priv, int *ifidx,
        return bcmerror;
 }
 
-void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx, struct sk_buff *skb,
-                 int numpkt)
+void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx,
+                   struct sk_buff_head *skb_list)
 {
        struct brcmf_info *drvr_priv = drvr->info;
        unsigned char *eth;
        uint len;
        void *data;
-       struct sk_buff *pnext, *save_pktbuf;
-       int i;
+       struct sk_buff *skb, *pnext;
        struct brcmf_if *ifp;
        struct brcmf_event_msg event;
 
        brcmf_dbg(TRACE, "Enter\n");
 
-       save_pktbuf = skb;
-
-       for (i = 0; skb && i < numpkt; i++, skb = pnext) {
-
-               pnext = skb->next;
-               skb->next = NULL;
+       skb_queue_walk_safe(skb_list, skb, pnext) {
+               skb_unlink(skb, skb_list);
 
                /* Get the protocol, maintain skb around eth_type_trans()
                 * The main reason for this hack is for the limitation of
@@ -464,6 +434,12 @@ void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx, struct sk_buff *skb,
                if (ifp == NULL)
                        ifp = drvr_priv->iflist[0];
 
+               if (!ifp || !ifp->ndev ||
+                   ifp->ndev->reg_state != NETREG_REGISTERED) {
+                       brcmu_pkt_buf_free_skb(skb);
+                       continue;
+               }
+
                skb->dev = ifp->ndev;
                skb->protocol = eth_type_trans(skb, skb->dev);
 
@@ -482,12 +458,10 @@ void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx, struct sk_buff *skb,
                                          skb_mac_header(skb),
                                          &event, &data);
 
-               if (drvr_priv->iflist[ifidx] &&
-                   !drvr_priv->iflist[ifidx]->state)
+               if (drvr_priv->iflist[ifidx]) {
                        ifp = drvr_priv->iflist[ifidx];
-
-               if (ifp->ndev)
                        ifp->ndev->last_rx = jiffies;
+               }
 
                drvr->dstats.rx_bytes += skb->len;
                drvr->rx_packets++;     /* Local count */
@@ -524,19 +498,11 @@ void brcmf_txcomplete(struct brcmf_pub *drvr, struct sk_buff *txp, bool success)
 
 static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev)
 {
-       struct brcmf_info *drvr_priv = *(struct brcmf_info **)
-                                       netdev_priv(ndev);
-       struct brcmf_if *ifp;
-       int ifidx;
+       struct brcmf_if *ifp = netdev_priv(ndev);
+       struct brcmf_info *drvr_priv = ifp->info;
 
        brcmf_dbg(TRACE, "Enter\n");
 
-       ifidx = brcmf_net2idx(drvr_priv, ndev);
-       if (ifidx == BRCMF_BAD_IF)
-               return NULL;
-
-       ifp = drvr_priv->iflist[ifidx];
-
        if (drvr_priv->pub.up)
                /* Use the protocol to get dongle stats */
                brcmf_proto_dstats(&drvr_priv->pub);
@@ -637,12 +603,11 @@ static int brcmf_toe_set(struct brcmf_info *drvr_priv, int ifidx, u32 toe_ol)
 static void brcmf_ethtool_get_drvinfo(struct net_device *ndev,
                                    struct ethtool_drvinfo *info)
 {
-       struct brcmf_info *drvr_priv = *(struct brcmf_info **)
-                                       netdev_priv(ndev);
+       struct brcmf_if *ifp = netdev_priv(ndev);
+       struct brcmf_info *drvr_priv = ifp->info;
 
        sprintf(info->driver, KBUILD_MODNAME);
        sprintf(info->version, "%lu", drvr_priv->pub.drv_version);
-       sprintf(info->fw_version, "%s", BCM4329_FW_NAME);
        sprintf(info->bus_info, "%s",
                dev_name(brcmf_bus_get_device(drvr_priv->pub.bus)));
 }
@@ -765,14 +730,12 @@ static int brcmf_ethtool(struct brcmf_info *drvr_priv, void __user *uaddr)
 static int brcmf_netdev_ioctl_entry(struct net_device *ndev, struct ifreq *ifr,
                                    int cmd)
 {
-       struct brcmf_info *drvr_priv = *(struct brcmf_info **)
-                                       netdev_priv(ndev);
-       int ifidx;
+       struct brcmf_if *ifp = netdev_priv(ndev);
+       struct brcmf_info *drvr_priv = ifp->info;
 
-       ifidx = brcmf_net2idx(drvr_priv, ndev);
-       brcmf_dbg(TRACE, "ifidx %d, cmd 0x%04x\n", ifidx, cmd);
+       brcmf_dbg(TRACE, "ifidx %d, cmd 0x%04x\n", ifp->idx, cmd);
 
-       if (ifidx == BRCMF_BAD_IF)
+       if (!drvr_priv->iflist[ifp->idx])
                return -1;
 
        if (cmd == SIOCETHTOOL)
@@ -788,22 +751,19 @@ s32 brcmf_exec_dcmd(struct net_device *ndev, u32 cmd, void *arg, u32 len)
        s32 err = 0;
        int buflen = 0;
        bool is_set_key_cmd;
-       struct brcmf_info *drvr_priv = *(struct brcmf_info **)
-                                       netdev_priv(ndev);
-       int ifidx;
+       struct brcmf_if *ifp = netdev_priv(ndev);
+       struct brcmf_info *drvr_priv = ifp->info;
 
        memset(&dcmd, 0, sizeof(dcmd));
        dcmd.cmd = cmd;
        dcmd.buf = arg;
        dcmd.len = len;
 
-       ifidx = brcmf_net2idx(drvr_priv, ndev);
-
        if (dcmd.buf != NULL)
                buflen = min_t(uint, dcmd.len, BRCMF_DCMD_MAXLEN);
 
        /* send to dongle (must be up, and wl) */
-       if ((drvr_priv->pub.busstate != BRCMF_BUS_DATA)) {
+       if ((drvr_priv->pub.bus_if->state != BRCMF_BUS_DATA)) {
                brcmf_dbg(ERROR, "DONGLE_DOWN\n");
                err = -EIO;
                goto done;
@@ -826,7 +786,7 @@ s32 brcmf_exec_dcmd(struct net_device *ndev, u32 cmd, void *arg, u32 len)
        if (is_set_key_cmd)
                brcmf_netdev_wait_pend8021x(ndev);
 
-       err = brcmf_proto_dcmd(&drvr_priv->pub, ifidx, &dcmd, buflen);
+       err = brcmf_proto_dcmd(&drvr_priv->pub, ifp->idx, &dcmd, buflen);
 
 done:
        if (err > 0)
@@ -837,7 +797,8 @@ done:
 
 static int brcmf_netdev_stop(struct net_device *ndev)
 {
-       struct brcmf_pub *drvr = *(struct brcmf_pub **) netdev_priv(ndev);
+       struct brcmf_if *ifp = netdev_priv(ndev);
+       struct brcmf_pub *drvr = &ifp->info->pub;
 
        brcmf_dbg(TRACE, "Enter\n");
        brcmf_cfg80211_down(drvr->config);
@@ -853,16 +814,14 @@ static int brcmf_netdev_stop(struct net_device *ndev)
 
 static int brcmf_netdev_open(struct net_device *ndev)
 {
-       struct brcmf_info *drvr_priv = *(struct brcmf_info **)
-                                       netdev_priv(ndev);
+       struct brcmf_if *ifp = netdev_priv(ndev);
+       struct brcmf_info *drvr_priv = ifp->info;
        u32 toe_ol;
-       int ifidx = brcmf_net2idx(drvr_priv, ndev);
        s32 ret = 0;
 
-       brcmf_dbg(TRACE, "ifidx %d\n", ifidx);
-
-       if (ifidx == 0) {       /* do it only for primary eth0 */
+       brcmf_dbg(TRACE, "ifidx %d\n", ifp->idx);
 
+       if (ifp->idx == 0) {    /* do it only for primary eth0 */
                /* try to bring up bus */
                ret = brcmf_bus_start(&drvr_priv->pub);
                if (ret != 0) {
@@ -874,12 +833,12 @@ static int brcmf_netdev_open(struct net_device *ndev)
                memcpy(ndev->dev_addr, drvr_priv->pub.mac, ETH_ALEN);
 
                /* Get current TOE mode from dongle */
-               if (brcmf_toe_get(drvr_priv, ifidx, &toe_ol) >= 0
+               if (brcmf_toe_get(drvr_priv, ifp->idx, &toe_ol) >= 0
                    && (toe_ol & TOE_TX_CSUM_OL) != 0)
-                       drvr_priv->iflist[ifidx]->ndev->features |=
+                       drvr_priv->iflist[ifp->idx]->ndev->features |=
                                NETIF_F_IP_CSUM;
                else
-                       drvr_priv->iflist[ifidx]->ndev->features &=
+                       drvr_priv->iflist[ifp->idx]->ndev->features &=
                                ~NETIF_F_IP_CSUM;
        }
        /* Allow transmit calls */
@@ -893,75 +852,62 @@ static int brcmf_netdev_open(struct net_device *ndev)
        return ret;
 }
 
+static const struct net_device_ops brcmf_netdev_ops_pri = {
+       .ndo_open = brcmf_netdev_open,
+       .ndo_stop = brcmf_netdev_stop,
+       .ndo_get_stats = brcmf_netdev_get_stats,
+       .ndo_do_ioctl = brcmf_netdev_ioctl_entry,
+       .ndo_start_xmit = brcmf_netdev_start_xmit,
+       .ndo_set_mac_address = brcmf_netdev_set_mac_address,
+       .ndo_set_rx_mode = brcmf_netdev_set_multicast_list
+};
+
 int
-brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, struct net_device *ndev,
-            char *name, u8 *mac_addr, u32 flags, u8 bssidx)
+brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, char *name, u8 *mac_addr)
 {
        struct brcmf_if *ifp;
-       int ret = 0, err = 0;
+       struct net_device *ndev;
 
-       brcmf_dbg(TRACE, "idx %d, handle->%p\n", ifidx, ndev);
+       brcmf_dbg(TRACE, "idx %d\n", ifidx);
 
        ifp = drvr_priv->iflist[ifidx];
-       if (!ifp) {
-               ifp = kmalloc(sizeof(struct brcmf_if), GFP_ATOMIC);
-               if (!ifp)
-                       return -ENOMEM;
+       /*
+        * Delete the existing interface before overwriting it
+        * in case we missed the BRCMF_E_IF_DEL event.
+        */
+       if (ifp) {
+               brcmf_dbg(ERROR, "ERROR: netdev:%s already exists, try free & unregister\n",
+                         ifp->ndev->name);
+               netif_stop_queue(ifp->ndev);
+               unregister_netdev(ifp->ndev);
+               free_netdev(ifp->ndev);
+               drvr_priv->iflist[ifidx] = NULL;
+       }
+
+       /* Allocate netdev, including space for private structure */
+       ndev = alloc_netdev(sizeof(struct brcmf_if), name, ether_setup);
+       if (!ndev) {
+               brcmf_dbg(ERROR, "OOM - alloc_netdev\n");
+               return -ENOMEM;
        }
 
-       memset(ifp, 0, sizeof(struct brcmf_if));
+       ifp = netdev_priv(ndev);
+       ifp->ndev = ndev;
        ifp->info = drvr_priv;
        drvr_priv->iflist[ifidx] = ifp;
+       ifp->idx = ifidx;
        if (mac_addr != NULL)
                memcpy(&ifp->mac_addr, mac_addr, ETH_ALEN);
 
-       if (ndev == NULL) {
-               ifp->state = BRCMF_E_IF_ADD;
-               ifp->idx = ifidx;
-               /*
-                * Delete the existing interface before overwriting it
-                * in case we missed the BRCMF_E_IF_DEL event.
-                */
-               if (ifp->ndev != NULL) {
-                       brcmf_dbg(ERROR, "ERROR: netdev:%s already exists, try free & unregister\n",
-                                 ifp->ndev->name);
-                       netif_stop_queue(ifp->ndev);
-                       unregister_netdev(ifp->ndev);
-                       free_netdev(ifp->ndev);
-               }
-
-               /* Allocate netdev, including space for private structure */
-               ifp->ndev = alloc_netdev(sizeof(drvr_priv), "wlan%d",
-                                        ether_setup);
-               if (!ifp->ndev) {
-                       brcmf_dbg(ERROR, "OOM - alloc_netdev\n");
-                       ret = -ENOMEM;
-               }
-
-               if (ret == 0) {
-                       memcpy(netdev_priv(ifp->ndev), &drvr_priv,
-                              sizeof(drvr_priv));
-                       err = brcmf_net_attach(&drvr_priv->pub, ifp->idx);
-                       if (err != 0) {
-                               brcmf_dbg(ERROR, "brcmf_net_attach failed, err %d\n",
-                                         err);
-                               ret = -EOPNOTSUPP;
-                       } else {
-                               brcmf_dbg(TRACE, " ==== pid:%x, net_device for if:%s created ===\n",
-                                         current->pid, ifp->ndev->name);
-                               ifp->state = 0;
-                       }
-               }
-
-               if (ret < 0) {
-                       if (ifp->ndev)
-                               free_netdev(ifp->ndev);
+       if (brcmf_net_attach(&drvr_priv->pub, ifp->idx)) {
+               brcmf_dbg(ERROR, "brcmf_net_attach failed");
+               free_netdev(ifp->ndev);
+               drvr_priv->iflist[ifidx] = NULL;
+               return -EOPNOTSUPP;
+       }
 
-                       drvr_priv->iflist[ifp->idx] = NULL;
-                       kfree(ifp);
-               }
-       } else
-               ifp->ndev = ndev;
+       brcmf_dbg(TRACE, " ==== pid:%x, net_device for if:%s created ===\n",
+                 current->pid, ifp->ndev->name);
 
        return 0;
 }
@@ -977,47 +923,37 @@ void brcmf_del_if(struct brcmf_info *drvr_priv, int ifidx)
                brcmf_dbg(ERROR, "Null interface\n");
                return;
        }
+       if (ifp->ndev) {
+               if (ifidx == 0) {
+                       if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
+                               rtnl_lock();
+                               brcmf_netdev_stop(ifp->ndev);
+                               rtnl_unlock();
+                       }
+               } else {
+                       netif_stop_queue(ifp->ndev);
+               }
 
-       ifp->state = BRCMF_E_IF_DEL;
-       ifp->idx = ifidx;
-       if (ifp->ndev != NULL) {
-               netif_stop_queue(ifp->ndev);
                unregister_netdev(ifp->ndev);
-               free_netdev(ifp->ndev);
                drvr_priv->iflist[ifidx] = NULL;
-               kfree(ifp);
+               if (ifidx == 0)
+                       brcmf_cfg80211_detach(drvr_priv->pub.config);
+               free_netdev(ifp->ndev);
        }
 }
 
-struct brcmf_pub *brcmf_attach(struct brcmf_bus *bus, uint bus_hdrlen)
+struct brcmf_pub *brcmf_attach(struct brcmf_sdio *bus, uint bus_hdrlen,
+                              struct device *dev)
 {
        struct brcmf_info *drvr_priv = NULL;
-       struct net_device *ndev;
 
        brcmf_dbg(TRACE, "Enter\n");
 
-       /* Allocate netdev, including space for private structure */
-       ndev = alloc_netdev(sizeof(drvr_priv), "wlan%d", ether_setup);
-       if (!ndev) {
-               brcmf_dbg(ERROR, "OOM - alloc_netdev\n");
-               goto fail;
-       }
-
        /* Allocate primary brcmf_info */
        drvr_priv = kzalloc(sizeof(struct brcmf_info), GFP_ATOMIC);
        if (!drvr_priv)
                goto fail;
 
-       /*
-        * Save the brcmf_info into the priv
-        */
-       memcpy(netdev_priv(ndev), &drvr_priv, sizeof(drvr_priv));
-
-       if (brcmf_add_if(drvr_priv, 0, ndev, ndev->name, NULL, 0, 0) ==
-           BRCMF_BAD_IF)
-               goto fail;
-
-       ndev->netdev_ops = NULL;
        mutex_init(&drvr_priv->proto_block);
 
        /* Link to info module */
@@ -1026,6 +962,8 @@ struct brcmf_pub *brcmf_attach(struct brcmf_bus *bus, uint bus_hdrlen)
        /* Link to bus module */
        drvr_priv->pub.bus = bus;
        drvr_priv->pub.hdrlen = bus_hdrlen;
+       drvr_priv->pub.bus_if = dev_get_drvdata(dev);
+       drvr_priv->pub.dev = dev;
 
        /* Attach and link in the protocol */
        if (brcmf_proto_attach(&drvr_priv->pub) != 0) {
@@ -1033,29 +971,12 @@ struct brcmf_pub *brcmf_attach(struct brcmf_bus *bus, uint bus_hdrlen)
                goto fail;
        }
 
-       /* Attach and link in the cfg80211 */
-       drvr_priv->pub.config =
-                       brcmf_cfg80211_attach(ndev,
-                                             brcmf_bus_get_device(bus),
-                                             &drvr_priv->pub);
-       if (drvr_priv->pub.config == NULL) {
-               brcmf_dbg(ERROR, "wl_cfg80211_attach failed\n");
-               goto fail;
-       }
-
        INIT_WORK(&drvr_priv->setmacaddr_work, _brcmf_set_mac_address);
        INIT_WORK(&drvr_priv->multicast_work, _brcmf_set_multicast_list);
 
-       /*
-        * Save the brcmf_info into the priv
-        */
-       memcpy(netdev_priv(ndev), &drvr_priv, sizeof(drvr_priv));
-
        return &drvr_priv->pub;
 
 fail:
-       if (ndev)
-               free_netdev(ndev);
        if (drvr_priv)
                brcmf_detach(&drvr_priv->pub);
 
@@ -1079,7 +1000,7 @@ int brcmf_bus_start(struct brcmf_pub *drvr)
        }
 
        /* If bus is not ready, can't come up */
-       if (drvr_priv->pub.busstate != BRCMF_BUS_DATA) {
+       if (drvr_priv->pub.bus_if->state != BRCMF_BUS_DATA) {
                brcmf_dbg(ERROR, "failed bus is not ready\n");
                return -ENODEV;
        }
@@ -1123,16 +1044,6 @@ int brcmf_bus_start(struct brcmf_pub *drvr)
        return 0;
 }
 
-static struct net_device_ops brcmf_netdev_ops_pri = {
-       .ndo_open = brcmf_netdev_open,
-       .ndo_stop = brcmf_netdev_stop,
-       .ndo_get_stats = brcmf_netdev_get_stats,
-       .ndo_do_ioctl = brcmf_netdev_ioctl_entry,
-       .ndo_start_xmit = brcmf_netdev_start_xmit,
-       .ndo_set_mac_address = brcmf_netdev_set_mac_address,
-       .ndo_set_rx_mode = brcmf_netdev_set_multicast_list
-};
-
 int brcmf_net_attach(struct brcmf_pub *drvr, int ifidx)
 {
        struct brcmf_info *drvr_priv = drvr->info;
@@ -1169,6 +1080,18 @@ int brcmf_net_attach(struct brcmf_pub *drvr, int ifidx)
 
        memcpy(ndev->dev_addr, temp_addr, ETH_ALEN);
 
+       /* attach to cfg80211 for primary interface */
+       if (!ifidx) {
+               drvr->config =
+                       brcmf_cfg80211_attach(ndev,
+                                             brcmf_bus_get_device(drvr->bus),
+                                             drvr);
+               if (drvr->config == NULL) {
+                       brcmf_dbg(ERROR, "wl_cfg80211_attach failed\n");
+                       goto fail;
+               }
+       }
+
        if (register_netdev(ndev) != 0) {
                brcmf_dbg(ERROR, "couldn't register the net device\n");
                goto fail;
@@ -1210,21 +1133,13 @@ void brcmf_detach(struct brcmf_pub *drvr)
        if (drvr) {
                drvr_priv = drvr->info;
                if (drvr_priv) {
-                       struct brcmf_if *ifp;
                        int i;
 
-                       for (i = 1; i < BRCMF_MAX_IFS; i++)
+                       /* make sure primary interface removed last */
+                       for (i = BRCMF_MAX_IFS-1; i > -1; i--)
                                if (drvr_priv->iflist[i])
                                        brcmf_del_if(drvr_priv, i);
 
-                       ifp = drvr_priv->iflist[0];
-                       if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
-                               rtnl_lock();
-                               brcmf_netdev_stop(ifp->ndev);
-                               rtnl_unlock();
-                               unregister_netdev(ifp->ndev);
-                       }
-
                        cancel_work_sync(&drvr_priv->setmacaddr_work);
                        cancel_work_sync(&drvr_priv->multicast_work);
 
@@ -1233,43 +1148,11 @@ void brcmf_detach(struct brcmf_pub *drvr)
                        if (drvr->prot)
                                brcmf_proto_detach(drvr);
 
-                       brcmf_cfg80211_detach(drvr->config);
-
-                       free_netdev(ifp->ndev);
-                       kfree(ifp);
                        kfree(drvr_priv);
                }
        }
 }
 
-static void __exit brcmf_module_cleanup(void)
-{
-       brcmf_dbg(TRACE, "Enter\n");
-
-       brcmf_bus_unregister();
-}
-
-static int __init brcmf_module_init(void)
-{
-       int error;
-
-       brcmf_dbg(TRACE, "Enter\n");
-
-       error = brcmf_bus_register();
-
-       if (error) {
-               brcmf_dbg(ERROR, "brcmf_bus_register failed\n");
-               goto failed;
-       }
-       return 0;
-
-failed:
-       return -EINVAL;
-}
-
-module_init(brcmf_module_init);
-module_exit(brcmf_module_cleanup);
-
 int brcmf_os_proto_block(struct brcmf_pub *drvr)
 {
        struct brcmf_info *drvr_priv = drvr->info;
@@ -1302,7 +1185,8 @@ static int brcmf_get_pend_8021x_cnt(struct brcmf_info *drvr_priv)
 
 int brcmf_netdev_wait_pend8021x(struct net_device *ndev)
 {
-       struct brcmf_info *drvr_priv = *(struct brcmf_info **)netdev_priv(ndev);
+       struct brcmf_if *ifp = netdev_priv(ndev);
+       struct brcmf_info *drvr_priv = ifp->info;
        int timeout = 10 * HZ / 1000;
        int ntimes = MAX_WAIT_FOR_8021X_TX;
        int pend = brcmf_get_pend_8021x_cnt(drvr_priv);
This page took 0.033954 seconds and 5 git commands to generate.