char *buf, *bufp;
        u32 buflen;
        s32 err;
-       struct brcmf_pub *drvr = container_of(work, struct brcmf_pub,
-                                                   multicast_work);
 
        brcmf_dbg(TRACE, "enter\n");
 
-       ifp = drvr->iflist[0];
+       ifp = container_of(work, struct brcmf_if, multicast_work);
        ndev = ifp->ndev;
 
        /* Determine initial value of allmulti flag */
 _brcmf_set_mac_address(struct work_struct *work)
 {
        struct brcmf_if *ifp;
-       struct net_device *ndev;
        s32 err;
 
-       struct brcmf_pub *drvr = container_of(work, struct brcmf_pub,
-                                                   setmacaddr_work);
-
        brcmf_dbg(TRACE, "enter\n");
 
-       ifp = drvr->iflist[0];
-       ndev = ifp->ndev;
-
-       err = brcmf_fil_iovar_data_set(ifp, "cur_etheraddr", drvr->macvalue,
+       ifp = container_of(work, struct brcmf_if, setmacaddr_work);
+       err = brcmf_fil_iovar_data_set(ifp, "cur_etheraddr", ifp->mac_addr,
                                       ETH_ALEN);
        if (err < 0) {
                brcmf_dbg(ERROR, "Setting cur_etheraddr failed, %d\n", err);
        } else {
                brcmf_dbg(TRACE, "MAC address updated to %pM\n",
-                         drvr->macvalue);
-               memcpy(ndev->dev_addr, drvr->macvalue, ETH_ALEN);
+                         ifp->mac_addr);
+               memcpy(ifp->ndev->dev_addr, ifp->mac_addr, ETH_ALEN);
        }
 }
 
 static int brcmf_netdev_set_mac_address(struct net_device *ndev, void *addr)
 {
        struct brcmf_if *ifp = netdev_priv(ndev);
-       struct brcmf_pub *drvr = ifp->drvr;
        struct sockaddr *sa = (struct sockaddr *)addr;
 
-       memcpy(&drvr->macvalue, sa->sa_data, ETH_ALEN);
-       schedule_work(&drvr->setmacaddr_work);
+       memcpy(&ifp->mac_addr, sa->sa_data, ETH_ALEN);
+       schedule_work(&ifp->setmacaddr_work);
        return 0;
 }
 
 static void brcmf_netdev_set_multicast_list(struct net_device *ndev)
 {
        struct brcmf_if *ifp = netdev_priv(ndev);
-       struct brcmf_pub *drvr = ifp->drvr;
 
-       schedule_work(&drvr->multicast_work);
+       schedule_work(&ifp->multicast_work);
 }
 
 static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        if (drvr->bus_if->drvr_up == 0)
                return 0;
 
-       brcmf_cfg80211_down(drvr->config);
+       brcmf_cfg80211_down(ndev);
 
        /* Set state and stop OS transmissions */
        drvr->bus_if->drvr_up = false;
 
        brcmf_dbg(TRACE, "ifidx %d\n", ifp->idx);
 
-       if (ifp->idx == 0) {    /* do it only for primary eth0 */
-               /* If bus is not ready, can't continue */
-               if (bus_if->state != BRCMF_BUS_DATA) {
-                       brcmf_dbg(ERROR, "failed bus is not ready\n");
-                       return -EAGAIN;
-               }
+       /* If bus is not ready, can't continue */
+       if (bus_if->state != BRCMF_BUS_DATA) {
+               brcmf_dbg(ERROR, "failed bus is not ready\n");
+               return -EAGAIN;
+       }
 
-               atomic_set(&drvr->pend_8021x_cnt, 0);
+       atomic_set(&drvr->pend_8021x_cnt, 0);
 
-               memcpy(ndev->dev_addr, drvr->mac, ETH_ALEN);
+       memcpy(ndev->dev_addr, drvr->mac, ETH_ALEN);
 
-               /* Get current TOE mode from dongle */
-               if (brcmf_fil_iovar_int_get(ifp, "toe_ol", &toe_ol) >= 0
-                   && (toe_ol & TOE_TX_CSUM_OL) != 0)
-                       drvr->iflist[ifp->idx]->ndev->features |=
-                               NETIF_F_IP_CSUM;
-               else
-                       drvr->iflist[ifp->idx]->ndev->features &=
-                               ~NETIF_F_IP_CSUM;
-       }
+       /* Get current TOE mode from dongle */
+       if (brcmf_fil_iovar_int_get(ifp, "toe_ol", &toe_ol) >= 0
+           && (toe_ol & TOE_TX_CSUM_OL) != 0)
+               drvr->iflist[ifp->idx]->ndev->features |=
+                       NETIF_F_IP_CSUM;
+       else
+               drvr->iflist[ifp->idx]->ndev->features &=
+                       ~NETIF_F_IP_CSUM;
 
        /* make sure RF is ready for work */
        brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 0);
        /* Allow transmit calls */
        netif_start_queue(ndev);
        drvr->bus_if->drvr_up = true;
-       if (brcmf_cfg80211_up(drvr->config)) {
+       if (brcmf_cfg80211_up(ndev)) {
                brcmf_dbg(ERROR, "failed to bring up cfg80211\n");
                return -1;
        }
        .ndo_set_rx_mode = brcmf_netdev_set_multicast_list
 };
 
+static const struct net_device_ops brcmf_netdev_ops_virt = {
+       .ndo_open = brcmf_cfg80211_up,
+       .ndo_stop = brcmf_cfg80211_down,
+       .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_if *ifp)
 {
        struct brcmf_pub *drvr = ifp->drvr;
        struct net_device *ndev;
        u8 temp_addr[ETH_ALEN];
 
-       brcmf_dbg(TRACE, "ifidx %d\n", ifp->idx);
+       brcmf_dbg(TRACE, "ifidx %d mac %pM\n", ifp->idx, ifp->mac_addr);
+       ndev = ifp->ndev;
 
-       ndev = drvr->iflist[ifp->idx]->ndev;
-       ndev->netdev_ops = &brcmf_netdev_ops_pri;
+       /* set appropriate operations */
+       if (!ifp->idx)
+               ndev->netdev_ops = &brcmf_netdev_ops_pri;
+       else
+               ndev->netdev_ops = &brcmf_netdev_ops_virt;
 
        /*
         * determine mac address to use
        else
                memcpy(temp_addr, drvr->mac, ETH_ALEN);
 
-       if (ifp->idx == 1) {
-               brcmf_dbg(TRACE, "ACCESS POINT MAC:\n");
-               /*  ACCESSPOINT INTERFACE CASE */
-               temp_addr[0] |= 0X02;   /* set bit 2 ,
-                        - Locally Administered address  */
-
-       }
        ndev->hard_header_len = ETH_HLEN + drvr->hdrlen;
        ndev->ethtool_ops = &brcmf_ethtool_ops;
 
        drvr->iflist[ifidx] = ifp;
        ifp->idx = ifidx;
        ifp->bssidx = bssidx;
+
+       INIT_WORK(&ifp->setmacaddr_work, _brcmf_set_mac_address);
+       INIT_WORK(&ifp->multicast_work, _brcmf_set_multicast_list);
+
        if (mac_addr != NULL)
                memcpy(&ifp->mac_addr, mac_addr, ETH_ALEN);
 
                        netif_stop_queue(ifp->ndev);
                }
 
+               cancel_work_sync(&ifp->setmacaddr_work);
+               cancel_work_sync(&ifp->multicast_work);
+
                unregister_netdev(ifp->ndev);
                drvr->iflist[ifidx] = NULL;
                if (ifidx == 0)
        /* attach firmware event handler */
        brcmf_fweh_attach(drvr);
 
-       INIT_WORK(&drvr->setmacaddr_work, _brcmf_set_mac_address);
-       INIT_WORK(&drvr->multicast_work, _brcmf_set_multicast_list);
-
        INIT_LIST_HEAD(&drvr->bus_if->dcmd_list);
 
        init_waitqueue_head(&drvr->pend_8021x_wait);
        brcmf_bus_detach(drvr);
 
        if (drvr->prot) {
-               cancel_work_sync(&drvr->setmacaddr_work);
-               cancel_work_sync(&drvr->multicast_work);
                brcmf_proto_detach(drvr);
        }
 
 
 
 }
 
-static s32 __brcmf_cfg80211_up(struct brcmf_cfg80211_info *cfg)
+static s32 __brcmf_cfg80211_up(struct brcmf_if *ifp)
 {
-       struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
-
        set_bit(BRCMF_VIF_STATUS_READY, &ifp->vif->sme_state);
+       if (ifp->idx)
+               return 0;
 
-       return brcmf_config_dongle(cfg);
+       return brcmf_config_dongle(ifp->drvr->config);
 }
 
-static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_info *cfg)
+static s32 __brcmf_cfg80211_down(struct brcmf_if *ifp)
 {
-       struct net_device *ndev = cfg_to_ndev(cfg);
-       struct brcmf_if *ifp = netdev_priv(ndev);
+       struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
 
        /*
         * While going down, if associated with AP disassociate
        return 0;
 }
 
-s32 brcmf_cfg80211_up(struct brcmf_cfg80211_info *cfg)
+s32 brcmf_cfg80211_up(struct net_device *ndev)
 {
+       struct brcmf_if *ifp = netdev_priv(ndev);
+       struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
        s32 err = 0;
 
        mutex_lock(&cfg->usr_sync);
-       err = __brcmf_cfg80211_up(cfg);
+       err = __brcmf_cfg80211_up(ifp);
        mutex_unlock(&cfg->usr_sync);
 
        return err;
 }
 
-s32 brcmf_cfg80211_down(struct brcmf_cfg80211_info *cfg)
+s32 brcmf_cfg80211_down(struct net_device *ndev)
 {
+       struct brcmf_if *ifp = netdev_priv(ndev);
+       struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
        s32 err = 0;
 
        mutex_lock(&cfg->usr_sync);
-       err = __brcmf_cfg80211_down(cfg);
+       err = __brcmf_cfg80211_down(ifp);
        mutex_unlock(&cfg->usr_sync);
 
        return err;