aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArend van Spriel <arend@broadcom.com>2012-11-14 21:46:09 -0500
committerJohn W. Linville <linville@tuxdriver.com>2012-11-16 14:28:49 -0500
commitbdf5ff516b453137cecb71e60ff860ec0a704509 (patch)
tree2e0dca2869b5546623305d9ef1e0c63145d1aba4
parent699b5e5b0ba19b41ddd31ea5dc87d3c5e512342c (diff)
brcmfmac: fix for multiple netdevice interface support
virtual netdevice interface like P2P client and GO need different callbacks for .open and .down. This patch adds those. Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> Reviewed-by: Hante Meuleman <meuleman@broadcom.com> Signed-off-by: Arend van Spriel <arend@broadcom.com> Signed-off-by: Franky Lin <frankyl@broadcom.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd.h4
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c101
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c25
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h4
4 files changed, 67 insertions, 67 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
index a41e1c69f8c5..499c5c240e04 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
@@ -513,8 +513,6 @@ struct brcmf_pub {
513 struct mutex proto_block; 513 struct mutex proto_block;
514 unsigned char proto_buf[BRCMF_DCMD_MAXLEN]; 514 unsigned char proto_buf[BRCMF_DCMD_MAXLEN];
515 515
516 struct work_struct setmacaddr_work;
517 struct work_struct multicast_work;
518 u8 macvalue[ETH_ALEN]; 516 u8 macvalue[ETH_ALEN];
519 atomic_t pend_8021x_cnt; 517 atomic_t pend_8021x_cnt;
520 wait_queue_head_t pend_8021x_wait; 518 wait_queue_head_t pend_8021x_wait;
@@ -556,6 +554,8 @@ struct brcmf_if {
556 struct brcmf_cfg80211_vif *vif; 554 struct brcmf_cfg80211_vif *vif;
557 struct net_device *ndev; 555 struct net_device *ndev;
558 struct net_device_stats stats; 556 struct net_device_stats stats;
557 struct work_struct setmacaddr_work;
558 struct work_struct multicast_work;
559 int idx; 559 int idx;
560 s32 bssidx; 560 s32 bssidx;
561 u8 mac_addr[ETH_ALEN]; 561 u8 mac_addr[ETH_ALEN];
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
index f10203410b39..32b73550e5ad 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
@@ -105,12 +105,10 @@ static void _brcmf_set_multicast_list(struct work_struct *work)
105 char *buf, *bufp; 105 char *buf, *bufp;
106 u32 buflen; 106 u32 buflen;
107 s32 err; 107 s32 err;
108 struct brcmf_pub *drvr = container_of(work, struct brcmf_pub,
109 multicast_work);
110 108
111 brcmf_dbg(TRACE, "enter\n"); 109 brcmf_dbg(TRACE, "enter\n");
112 110
113 ifp = drvr->iflist[0]; 111 ifp = container_of(work, struct brcmf_if, multicast_work);
114 ndev = ifp->ndev; 112 ndev = ifp->ndev;
115 113
116 /* Determine initial value of allmulti flag */ 114 /* Determine initial value of allmulti flag */
@@ -165,45 +163,37 @@ static void
165_brcmf_set_mac_address(struct work_struct *work) 163_brcmf_set_mac_address(struct work_struct *work)
166{ 164{
167 struct brcmf_if *ifp; 165 struct brcmf_if *ifp;
168 struct net_device *ndev;
169 s32 err; 166 s32 err;
170 167
171 struct brcmf_pub *drvr = container_of(work, struct brcmf_pub,
172 setmacaddr_work);
173
174 brcmf_dbg(TRACE, "enter\n"); 168 brcmf_dbg(TRACE, "enter\n");
175 169
176 ifp = drvr->iflist[0]; 170 ifp = container_of(work, struct brcmf_if, setmacaddr_work);
177 ndev = ifp->ndev; 171 err = brcmf_fil_iovar_data_set(ifp, "cur_etheraddr", ifp->mac_addr,
178
179 err = brcmf_fil_iovar_data_set(ifp, "cur_etheraddr", drvr->macvalue,
180 ETH_ALEN); 172 ETH_ALEN);
181 if (err < 0) { 173 if (err < 0) {
182 brcmf_dbg(ERROR, "Setting cur_etheraddr failed, %d\n", err); 174 brcmf_dbg(ERROR, "Setting cur_etheraddr failed, %d\n", err);
183 } else { 175 } else {
184 brcmf_dbg(TRACE, "MAC address updated to %pM\n", 176 brcmf_dbg(TRACE, "MAC address updated to %pM\n",
185 drvr->macvalue); 177 ifp->mac_addr);
186 memcpy(ndev->dev_addr, drvr->macvalue, ETH_ALEN); 178 memcpy(ifp->ndev->dev_addr, ifp->mac_addr, ETH_ALEN);
187 } 179 }
188} 180}
189 181
190static int brcmf_netdev_set_mac_address(struct net_device *ndev, void *addr) 182static int brcmf_netdev_set_mac_address(struct net_device *ndev, void *addr)
191{ 183{
192 struct brcmf_if *ifp = netdev_priv(ndev); 184 struct brcmf_if *ifp = netdev_priv(ndev);
193 struct brcmf_pub *drvr = ifp->drvr;
194 struct sockaddr *sa = (struct sockaddr *)addr; 185 struct sockaddr *sa = (struct sockaddr *)addr;
195 186
196 memcpy(&drvr->macvalue, sa->sa_data, ETH_ALEN); 187 memcpy(&ifp->mac_addr, sa->sa_data, ETH_ALEN);
197 schedule_work(&drvr->setmacaddr_work); 188 schedule_work(&ifp->setmacaddr_work);
198 return 0; 189 return 0;
199} 190}
200 191
201static void brcmf_netdev_set_multicast_list(struct net_device *ndev) 192static void brcmf_netdev_set_multicast_list(struct net_device *ndev)
202{ 193{
203 struct brcmf_if *ifp = netdev_priv(ndev); 194 struct brcmf_if *ifp = netdev_priv(ndev);
204 struct brcmf_pub *drvr = ifp->drvr;
205 195
206 schedule_work(&drvr->multicast_work); 196 schedule_work(&ifp->multicast_work);
207} 197}
208 198
209static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev) 199static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev)
@@ -582,7 +572,7 @@ static int brcmf_netdev_stop(struct net_device *ndev)
582 if (drvr->bus_if->drvr_up == 0) 572 if (drvr->bus_if->drvr_up == 0)
583 return 0; 573 return 0;
584 574
585 brcmf_cfg80211_down(drvr->config); 575 brcmf_cfg80211_down(ndev);
586 576
587 /* Set state and stop OS transmissions */ 577 /* Set state and stop OS transmissions */
588 drvr->bus_if->drvr_up = false; 578 drvr->bus_if->drvr_up = false;
@@ -601,26 +591,24 @@ static int brcmf_netdev_open(struct net_device *ndev)
601 591
602 brcmf_dbg(TRACE, "ifidx %d\n", ifp->idx); 592 brcmf_dbg(TRACE, "ifidx %d\n", ifp->idx);
603 593
604 if (ifp->idx == 0) { /* do it only for primary eth0 */ 594 /* If bus is not ready, can't continue */
605 /* If bus is not ready, can't continue */ 595 if (bus_if->state != BRCMF_BUS_DATA) {
606 if (bus_if->state != BRCMF_BUS_DATA) { 596 brcmf_dbg(ERROR, "failed bus is not ready\n");
607 brcmf_dbg(ERROR, "failed bus is not ready\n"); 597 return -EAGAIN;
608 return -EAGAIN; 598 }
609 }
610 599
611 atomic_set(&drvr->pend_8021x_cnt, 0); 600 atomic_set(&drvr->pend_8021x_cnt, 0);
612 601
613 memcpy(ndev->dev_addr, drvr->mac, ETH_ALEN); 602 memcpy(ndev->dev_addr, drvr->mac, ETH_ALEN);
614 603
615 /* Get current TOE mode from dongle */ 604 /* Get current TOE mode from dongle */
616 if (brcmf_fil_iovar_int_get(ifp, "toe_ol", &toe_ol) >= 0 605 if (brcmf_fil_iovar_int_get(ifp, "toe_ol", &toe_ol) >= 0
617 && (toe_ol & TOE_TX_CSUM_OL) != 0) 606 && (toe_ol & TOE_TX_CSUM_OL) != 0)
618 drvr->iflist[ifp->idx]->ndev->features |= 607 drvr->iflist[ifp->idx]->ndev->features |=
619 NETIF_F_IP_CSUM; 608 NETIF_F_IP_CSUM;
620 else 609 else
621 drvr->iflist[ifp->idx]->ndev->features &= 610 drvr->iflist[ifp->idx]->ndev->features &=
622 ~NETIF_F_IP_CSUM; 611 ~NETIF_F_IP_CSUM;
623 }
624 612
625 /* make sure RF is ready for work */ 613 /* make sure RF is ready for work */
626 brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 0); 614 brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 0);
@@ -628,7 +616,7 @@ static int brcmf_netdev_open(struct net_device *ndev)
628 /* Allow transmit calls */ 616 /* Allow transmit calls */
629 netif_start_queue(ndev); 617 netif_start_queue(ndev);
630 drvr->bus_if->drvr_up = true; 618 drvr->bus_if->drvr_up = true;
631 if (brcmf_cfg80211_up(drvr->config)) { 619 if (brcmf_cfg80211_up(ndev)) {
632 brcmf_dbg(ERROR, "failed to bring up cfg80211\n"); 620 brcmf_dbg(ERROR, "failed to bring up cfg80211\n");
633 return -1; 621 return -1;
634 } 622 }
@@ -646,16 +634,30 @@ static const struct net_device_ops brcmf_netdev_ops_pri = {
646 .ndo_set_rx_mode = brcmf_netdev_set_multicast_list 634 .ndo_set_rx_mode = brcmf_netdev_set_multicast_list
647}; 635};
648 636
637static const struct net_device_ops brcmf_netdev_ops_virt = {
638 .ndo_open = brcmf_cfg80211_up,
639 .ndo_stop = brcmf_cfg80211_down,
640 .ndo_get_stats = brcmf_netdev_get_stats,
641 .ndo_do_ioctl = brcmf_netdev_ioctl_entry,
642 .ndo_start_xmit = brcmf_netdev_start_xmit,
643 .ndo_set_mac_address = brcmf_netdev_set_mac_address,
644 .ndo_set_rx_mode = brcmf_netdev_set_multicast_list
645};
646
649int brcmf_net_attach(struct brcmf_if *ifp) 647int brcmf_net_attach(struct brcmf_if *ifp)
650{ 648{
651 struct brcmf_pub *drvr = ifp->drvr; 649 struct brcmf_pub *drvr = ifp->drvr;
652 struct net_device *ndev; 650 struct net_device *ndev;
653 u8 temp_addr[ETH_ALEN]; 651 u8 temp_addr[ETH_ALEN];
654 652
655 brcmf_dbg(TRACE, "ifidx %d\n", ifp->idx); 653 brcmf_dbg(TRACE, "ifidx %d mac %pM\n", ifp->idx, ifp->mac_addr);
654 ndev = ifp->ndev;
656 655
657 ndev = drvr->iflist[ifp->idx]->ndev; 656 /* set appropriate operations */
658 ndev->netdev_ops = &brcmf_netdev_ops_pri; 657 if (!ifp->idx)
658 ndev->netdev_ops = &brcmf_netdev_ops_pri;
659 else
660 ndev->netdev_ops = &brcmf_netdev_ops_virt;
659 661
660 /* 662 /*
661 * determine mac address to use 663 * determine mac address to use
@@ -665,13 +667,6 @@ int brcmf_net_attach(struct brcmf_if *ifp)
665 else 667 else
666 memcpy(temp_addr, drvr->mac, ETH_ALEN); 668 memcpy(temp_addr, drvr->mac, ETH_ALEN);
667 669
668 if (ifp->idx == 1) {
669 brcmf_dbg(TRACE, "ACCESS POINT MAC:\n");
670 /* ACCESSPOINT INTERFACE CASE */
671 temp_addr[0] |= 0X02; /* set bit 2 ,
672 - Locally Administered address */
673
674 }
675 ndev->hard_header_len = ETH_HLEN + drvr->hdrlen; 670 ndev->hard_header_len = ETH_HLEN + drvr->hdrlen;
676 ndev->ethtool_ops = &brcmf_ethtool_ops; 671 ndev->ethtool_ops = &brcmf_ethtool_ops;
677 672
@@ -729,6 +724,10 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, int ifidx, s32 bssidx,
729 drvr->iflist[ifidx] = ifp; 724 drvr->iflist[ifidx] = ifp;
730 ifp->idx = ifidx; 725 ifp->idx = ifidx;
731 ifp->bssidx = bssidx; 726 ifp->bssidx = bssidx;
727
728 INIT_WORK(&ifp->setmacaddr_work, _brcmf_set_mac_address);
729 INIT_WORK(&ifp->multicast_work, _brcmf_set_multicast_list);
730
732 if (mac_addr != NULL) 731 if (mac_addr != NULL)
733 memcpy(&ifp->mac_addr, mac_addr, ETH_ALEN); 732 memcpy(&ifp->mac_addr, mac_addr, ETH_ALEN);
734 733
@@ -760,6 +759,9 @@ void brcmf_del_if(struct brcmf_pub *drvr, int ifidx)
760 netif_stop_queue(ifp->ndev); 759 netif_stop_queue(ifp->ndev);
761 } 760 }
762 761
762 cancel_work_sync(&ifp->setmacaddr_work);
763 cancel_work_sync(&ifp->multicast_work);
764
763 unregister_netdev(ifp->ndev); 765 unregister_netdev(ifp->ndev);
764 drvr->iflist[ifidx] = NULL; 766 drvr->iflist[ifidx] = NULL;
765 if (ifidx == 0) 767 if (ifidx == 0)
@@ -801,9 +803,6 @@ int brcmf_attach(uint bus_hdrlen, struct device *dev)
801 /* attach firmware event handler */ 803 /* attach firmware event handler */
802 brcmf_fweh_attach(drvr); 804 brcmf_fweh_attach(drvr);
803 805
804 INIT_WORK(&drvr->setmacaddr_work, _brcmf_set_mac_address);
805 INIT_WORK(&drvr->multicast_work, _brcmf_set_multicast_list);
806
807 INIT_LIST_HEAD(&drvr->bus_if->dcmd_list); 806 INIT_LIST_HEAD(&drvr->bus_if->dcmd_list);
808 807
809 init_waitqueue_head(&drvr->pend_8021x_wait); 808 init_waitqueue_head(&drvr->pend_8021x_wait);
@@ -904,8 +903,6 @@ void brcmf_detach(struct device *dev)
904 brcmf_bus_detach(drvr); 903 brcmf_bus_detach(drvr);
905 904
906 if (drvr->prot) { 905 if (drvr->prot) {
907 cancel_work_sync(&drvr->setmacaddr_work);
908 cancel_work_sync(&drvr->multicast_work);
909 brcmf_proto_detach(drvr); 906 brcmf_proto_detach(drvr);
910 } 907 }
911 908
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
index e6d2d40ad8d5..14cf71b4251c 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
@@ -4526,19 +4526,18 @@ default_conf_out:
4526 4526
4527} 4527}
4528 4528
4529static s32 __brcmf_cfg80211_up(struct brcmf_cfg80211_info *cfg) 4529static s32 __brcmf_cfg80211_up(struct brcmf_if *ifp)
4530{ 4530{
4531 struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
4532
4533 set_bit(BRCMF_VIF_STATUS_READY, &ifp->vif->sme_state); 4531 set_bit(BRCMF_VIF_STATUS_READY, &ifp->vif->sme_state);
4532 if (ifp->idx)
4533 return 0;
4534 4534
4535 return brcmf_config_dongle(cfg); 4535 return brcmf_config_dongle(ifp->drvr->config);
4536} 4536}
4537 4537
4538static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_info *cfg) 4538static s32 __brcmf_cfg80211_down(struct brcmf_if *ifp)
4539{ 4539{
4540 struct net_device *ndev = cfg_to_ndev(cfg); 4540 struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
4541 struct brcmf_if *ifp = netdev_priv(ndev);
4542 4541
4543 /* 4542 /*
4544 * While going down, if associated with AP disassociate 4543 * While going down, if associated with AP disassociate
@@ -4563,23 +4562,27 @@ static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_info *cfg)
4563 return 0; 4562 return 0;
4564} 4563}
4565 4564
4566s32 brcmf_cfg80211_up(struct brcmf_cfg80211_info *cfg) 4565s32 brcmf_cfg80211_up(struct net_device *ndev)
4567{ 4566{
4567 struct brcmf_if *ifp = netdev_priv(ndev);
4568 struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
4568 s32 err = 0; 4569 s32 err = 0;
4569 4570
4570 mutex_lock(&cfg->usr_sync); 4571 mutex_lock(&cfg->usr_sync);
4571 err = __brcmf_cfg80211_up(cfg); 4572 err = __brcmf_cfg80211_up(ifp);
4572 mutex_unlock(&cfg->usr_sync); 4573 mutex_unlock(&cfg->usr_sync);
4573 4574
4574 return err; 4575 return err;
4575} 4576}
4576 4577
4577s32 brcmf_cfg80211_down(struct brcmf_cfg80211_info *cfg) 4578s32 brcmf_cfg80211_down(struct net_device *ndev)
4578{ 4579{
4580 struct brcmf_if *ifp = netdev_priv(ndev);
4581 struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
4579 s32 err = 0; 4582 s32 err = 0;
4580 4583
4581 mutex_lock(&cfg->usr_sync); 4584 mutex_lock(&cfg->usr_sync);
4582 err = __brcmf_cfg80211_down(cfg); 4585 err = __brcmf_cfg80211_down(ifp);
4583 mutex_unlock(&cfg->usr_sync); 4586 mutex_unlock(&cfg->usr_sync);
4584 4587
4585 return err; 4588 return err;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h
index 80ba2ea378e4..e2ef8519ea84 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h
@@ -455,7 +455,7 @@ brcmf_cfg80211_connect_info *cfg_to_conn(struct brcmf_cfg80211_info *cfg)
455 455
456struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr); 456struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr);
457void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg); 457void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg);
458s32 brcmf_cfg80211_up(struct brcmf_cfg80211_info *cfg); 458s32 brcmf_cfg80211_up(struct net_device *ndev);
459s32 brcmf_cfg80211_down(struct brcmf_cfg80211_info *cfg); 459s32 brcmf_cfg80211_down(struct net_device *ndev);
460 460
461#endif /* _wl_cfg80211_h_ */ 461#endif /* _wl_cfg80211_h_ */