aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/brcm80211/brcmfmac
diff options
context:
space:
mode:
authorHante Meuleman <meuleman@broadcom.com>2013-02-08 09:53:52 -0500
committerJohn W. Linville <linville@tuxdriver.com>2013-02-08 14:51:40 -0500
commit2fde59d93f8ac5525213996b5e98efb8f4d8c88c (patch)
tree1a484d63173e0dd710f373ba42ee40c740053168 /drivers/net/wireless/brcm80211/brcmfmac
parent1ce3086ccd81793fd6affb350826a0c41dc3ef37 (diff)
brcmfmac: Create p2p0 netdev via module variable.
Add module variable with which a p2p0 netdev can be created. This netdev can be used by wpa-supplicant to configure and set up the p2p client/GO. Reviewed-by: Arend Van Spriel <arend@broadcom.com> Reviewed-by: Pieter-Paul Giesberts <pieterpg@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>
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmfmac')
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c109
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/p2p.c226
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/p2p.h6
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c12
4 files changed, 213 insertions, 140 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
index 451b89c83d2b..65176c620aa6 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
@@ -42,6 +42,12 @@ MODULE_LICENSE("Dual BSD/GPL");
42int brcmf_msg_level; 42int brcmf_msg_level;
43module_param(brcmf_msg_level, int, 0); 43module_param(brcmf_msg_level, int, 0);
44 44
45/* P2P0 enable */
46static int brcmf_p2p_enable;
47#ifdef CONFIG_BRCMDBG
48module_param_named(p2pon, brcmf_p2p_enable, int, 0);
49MODULE_PARM_DESC(p2pon, "enable p2p management functionality");
50#endif
45 51
46char *brcmf_ifname(struct brcmf_pub *drvr, int ifidx) 52char *brcmf_ifname(struct brcmf_pub *drvr, int ifidx)
47{ 53{
@@ -593,16 +599,6 @@ static const struct net_device_ops brcmf_netdev_ops_pri = {
593 .ndo_set_rx_mode = brcmf_netdev_set_multicast_list 599 .ndo_set_rx_mode = brcmf_netdev_set_multicast_list
594}; 600};
595 601
596static const struct net_device_ops brcmf_netdev_ops_virt = {
597 .ndo_open = brcmf_cfg80211_up,
598 .ndo_stop = brcmf_cfg80211_down,
599 .ndo_get_stats = brcmf_netdev_get_stats,
600 .ndo_do_ioctl = brcmf_netdev_ioctl_entry,
601 .ndo_start_xmit = brcmf_netdev_start_xmit,
602 .ndo_set_mac_address = brcmf_netdev_set_mac_address,
603 .ndo_set_rx_mode = brcmf_netdev_set_multicast_list
604};
605
606int brcmf_net_attach(struct brcmf_if *ifp) 602int brcmf_net_attach(struct brcmf_if *ifp)
607{ 603{
608 struct brcmf_pub *drvr = ifp->drvr; 604 struct brcmf_pub *drvr = ifp->drvr;
@@ -613,10 +609,7 @@ int brcmf_net_attach(struct brcmf_if *ifp)
613 ndev = ifp->ndev; 609 ndev = ifp->ndev;
614 610
615 /* set appropriate operations */ 611 /* set appropriate operations */
616 if (!ifp->bssidx) 612 ndev->netdev_ops = &brcmf_netdev_ops_pri;
617 ndev->netdev_ops = &brcmf_netdev_ops_pri;
618 else
619 ndev->netdev_ops = &brcmf_netdev_ops_virt;
620 613
621 ndev->hard_header_len = ETH_HLEN + drvr->hdrlen; 614 ndev->hard_header_len = ETH_HLEN + drvr->hdrlen;
622 ndev->ethtool_ops = &brcmf_ethtool_ops; 615 ndev->ethtool_ops = &brcmf_ethtool_ops;
@@ -627,6 +620,9 @@ int brcmf_net_attach(struct brcmf_if *ifp)
627 /* set the mac address */ 620 /* set the mac address */
628 memcpy(ndev->dev_addr, ifp->mac_addr, ETH_ALEN); 621 memcpy(ndev->dev_addr, ifp->mac_addr, ETH_ALEN);
629 622
623 INIT_WORK(&ifp->setmacaddr_work, _brcmf_set_mac_address);
624 INIT_WORK(&ifp->multicast_work, _brcmf_set_multicast_list);
625
630 if (register_netdev(ndev) != 0) { 626 if (register_netdev(ndev) != 0) {
631 brcmf_err("couldn't register the net device\n"); 627 brcmf_err("couldn't register the net device\n");
632 goto fail; 628 goto fail;
@@ -641,6 +637,69 @@ fail:
641 return -EBADE; 637 return -EBADE;
642} 638}
643 639
640static int brcmf_net_p2p_open(struct net_device *ndev)
641{
642 brcmf_dbg(TRACE, "Enter\n");
643
644 return brcmf_cfg80211_up(ndev);
645}
646
647static int brcmf_net_p2p_stop(struct net_device *ndev)
648{
649 brcmf_dbg(TRACE, "Enter\n");
650
651 return brcmf_cfg80211_down(ndev);
652}
653
654static int brcmf_net_p2p_do_ioctl(struct net_device *ndev,
655 struct ifreq *ifr, int cmd)
656{
657 brcmf_dbg(TRACE, "Enter\n");
658 return 0;
659}
660
661static netdev_tx_t brcmf_net_p2p_start_xmit(struct sk_buff *skb,
662 struct net_device *ndev)
663{
664 if (skb)
665 dev_kfree_skb_any(skb);
666
667 return NETDEV_TX_OK;
668}
669
670static const struct net_device_ops brcmf_netdev_ops_p2p = {
671 .ndo_open = brcmf_net_p2p_open,
672 .ndo_stop = brcmf_net_p2p_stop,
673 .ndo_do_ioctl = brcmf_net_p2p_do_ioctl,
674 .ndo_start_xmit = brcmf_net_p2p_start_xmit
675};
676
677static int brcmf_net_p2p_attach(struct brcmf_if *ifp)
678{
679 struct net_device *ndev;
680
681 brcmf_dbg(TRACE, "Enter, idx=%d mac=%pM\n", ifp->bssidx,
682 ifp->mac_addr);
683 ndev = ifp->ndev;
684
685 ndev->netdev_ops = &brcmf_netdev_ops_p2p;
686
687 /* set the mac address */
688 memcpy(ndev->dev_addr, ifp->mac_addr, ETH_ALEN);
689
690 if (register_netdev(ndev) != 0) {
691 brcmf_err("couldn't register the p2p net device\n");
692 goto fail;
693 }
694
695 brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name);
696
697 return 0;
698
699fail:
700 return -EBADE;
701}
702
644struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx, 703struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
645 char *name, u8 *mac_addr) 704 char *name, u8 *mac_addr)
646{ 705{
@@ -682,8 +741,6 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
682 ifp->ifidx = ifidx; 741 ifp->ifidx = ifidx;
683 ifp->bssidx = bssidx; 742 ifp->bssidx = bssidx;
684 743
685 INIT_WORK(&ifp->setmacaddr_work, _brcmf_set_mac_address);
686 INIT_WORK(&ifp->multicast_work, _brcmf_set_multicast_list);
687 744
688 init_waitqueue_head(&ifp->pend_8021x_wait); 745 init_waitqueue_head(&ifp->pend_8021x_wait);
689 746
@@ -717,8 +774,10 @@ void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
717 netif_stop_queue(ifp->ndev); 774 netif_stop_queue(ifp->ndev);
718 } 775 }
719 776
720 cancel_work_sync(&ifp->setmacaddr_work); 777 if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
721 cancel_work_sync(&ifp->multicast_work); 778 cancel_work_sync(&ifp->setmacaddr_work);
779 cancel_work_sync(&ifp->multicast_work);
780 }
722 781
723 unregister_netdev(ifp->ndev); 782 unregister_netdev(ifp->ndev);
724 drvr->iflist[bssidx] = NULL; 783 drvr->iflist[bssidx] = NULL;
@@ -776,6 +835,7 @@ int brcmf_bus_start(struct device *dev)
776 struct brcmf_bus *bus_if = dev_get_drvdata(dev); 835 struct brcmf_bus *bus_if = dev_get_drvdata(dev);
777 struct brcmf_pub *drvr = bus_if->drvr; 836 struct brcmf_pub *drvr = bus_if->drvr;
778 struct brcmf_if *ifp; 837 struct brcmf_if *ifp;
838 struct brcmf_if *p2p_ifp;
779 839
780 brcmf_dbg(TRACE, "\n"); 840 brcmf_dbg(TRACE, "\n");
781 841
@@ -791,6 +851,13 @@ int brcmf_bus_start(struct device *dev)
791 if (IS_ERR(ifp)) 851 if (IS_ERR(ifp))
792 return PTR_ERR(ifp); 852 return PTR_ERR(ifp);
793 853
854 if (brcmf_p2p_enable)
855 p2p_ifp = brcmf_add_if(drvr, 1, 0, "p2p%d", NULL);
856 else
857 p2p_ifp = NULL;
858 if (IS_ERR(p2p_ifp))
859 p2p_ifp = NULL;
860
794 /* signal bus ready */ 861 /* signal bus ready */
795 bus_if->state = BRCMF_BUS_DATA; 862 bus_if->state = BRCMF_BUS_DATA;
796 863
@@ -817,8 +884,14 @@ fail:
817 brcmf_cfg80211_detach(drvr->config); 884 brcmf_cfg80211_detach(drvr->config);
818 free_netdev(ifp->ndev); 885 free_netdev(ifp->ndev);
819 drvr->iflist[0] = NULL; 886 drvr->iflist[0] = NULL;
887 if (p2p_ifp) {
888 free_netdev(p2p_ifp->ndev);
889 drvr->iflist[1] = NULL;
890 }
820 return ret; 891 return ret;
821 } 892 }
893 if ((brcmf_p2p_enable) && (p2p_ifp))
894 brcmf_net_p2p_attach(p2p_ifp);
822 895
823 return 0; 896 return 0;
824} 897}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
index 1c854f607d5b..c04d596be5be 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
@@ -407,22 +407,21 @@ static void brcmf_p2p_print_actframe(bool tx, void *frame, u32 frame_len)
407/** 407/**
408 * brcmf_p2p_set_firmware() - prepare firmware for peer-to-peer operation. 408 * brcmf_p2p_set_firmware() - prepare firmware for peer-to-peer operation.
409 * 409 *
410 * @p2p: P2P specific data. 410 * @ifp: ifp to use for iovars (primary).
411 * @p2p_mac: mac address to configure for p2p_da_override
411 */ 412 */
412static int brcmf_p2p_set_firmware(struct brcmf_p2p_info *p2p) 413static int brcmf_p2p_set_firmware(struct brcmf_if *ifp, u8 *p2p_mac)
413{ 414{
414 struct net_device *ndev = cfg_to_ndev(p2p->cfg);
415 u8 null_eth_addr[] = { 0, 0, 0, 0, 0, 0 };
416 s32 ret = 0; 415 s32 ret = 0;
417 416
418 brcmf_fil_iovar_int_set(netdev_priv(ndev), "apsta", 1); 417 brcmf_fil_iovar_int_set(ifp, "apsta", 1);
419 418
420 /* In case of COB type, firmware has default mac address 419 /* In case of COB type, firmware has default mac address
421 * After Initializing firmware, we have to set current mac address to 420 * After Initializing firmware, we have to set current mac address to
422 * firmware for P2P device address 421 * firmware for P2P device address
423 */ 422 */
424 ret = brcmf_fil_iovar_data_set(netdev_priv(ndev), "p2p_da_override", 423 ret = brcmf_fil_iovar_data_set(ifp, "p2p_da_override", p2p_mac,
425 null_eth_addr, sizeof(null_eth_addr)); 424 ETH_ALEN);
426 if (ret) 425 if (ret)
427 brcmf_err("failed to update device address ret %d\n", ret); 426 brcmf_err("failed to update device address ret %d\n", ret);
428 427
@@ -440,11 +439,15 @@ static int brcmf_p2p_set_firmware(struct brcmf_p2p_info *p2p)
440 */ 439 */
441static void brcmf_p2p_generate_bss_mac(struct brcmf_p2p_info *p2p) 440static void brcmf_p2p_generate_bss_mac(struct brcmf_p2p_info *p2p)
442{ 441{
442 struct brcmf_if *pri_ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp;
443 struct brcmf_if *p2p_ifp = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif->ifp;
444
443 /* Generate the P2P Device Address. This consists of the device's 445 /* Generate the P2P Device Address. This consists of the device's
444 * primary MAC address with the locally administered bit set. 446 * primary MAC address with the locally administered bit set.
445 */ 447 */
446 memcpy(p2p->dev_addr, p2p->cfg->pub->mac, ETH_ALEN); 448 memcpy(p2p->dev_addr, pri_ifp->mac_addr, ETH_ALEN);
447 p2p->dev_addr[0] |= 0x02; 449 p2p->dev_addr[0] |= 0x02;
450 memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN);
448 451
449 /* Generate the P2P Interface Address. If the discovery and connection 452 /* Generate the P2P Interface Address. If the discovery and connection
450 * BSSCFGs need to simultaneously co-exist, then this address must be 453 * BSSCFGs need to simultaneously co-exist, then this address must be
@@ -503,111 +506,25 @@ static s32 brcmf_p2p_set_discover_state(struct brcmf_if *ifp, u8 state,
503} 506}
504 507
505/** 508/**
506 * brcmf_p2p_init_discovery() - enable discovery in the firmware.
507 *
508 * @p2p: P2P specific data.
509 *
510 * Configures the firmware to allow P2P peer discovery. Creates the
511 * virtual interface and consequently the P2P device for it.
512 */
513static s32 brcmf_p2p_init_discovery(struct brcmf_p2p_info *p2p)
514{
515 struct net_device *ndev = cfg_to_ndev(p2p->cfg);
516 struct brcmf_cfg80211_vif *vif;
517 struct brcmf_if *ifp;
518 struct p2p_bss *bss_dev;
519 s32 index;
520 s32 ret;
521
522 brcmf_dbg(TRACE, "enter\n");
523
524 bss_dev = &p2p->bss_idx[P2PAPI_BSSCFG_DEVICE];
525 if (bss_dev->vif != NULL) {
526 brcmf_dbg(INFO, "do nothing, already initialized\n");
527 return 0;
528 }
529
530 /* Enable P2P Discovery in the firmware */
531 ret = brcmf_fil_iovar_int_set(netdev_priv(ndev), "p2p_disc", 1);
532 if (ret < 0) {
533 brcmf_err("set discover error\n");
534 return ret;
535 }
536
537 /* obtain bsscfg index for P2P discovery */
538 ret = brcmf_fil_iovar_int_get(netdev_priv(ndev), "p2p_dev", &index);
539 if (ret < 0) {
540 brcmf_err("retrieving discover bsscfg index failed\n");
541 return ret;
542 }
543
544 /*
545 * need brcmf_if for setting the discovery state.
546 */
547 ifp = kzalloc(sizeof(*vif->ifp), GFP_KERNEL);
548 if (!ifp) {
549 brcmf_err("could not create discovery if\n");
550 return -ENOMEM;
551 }
552
553 /* set required fields */
554 ifp->drvr = p2p->cfg->pub;
555 ifp->ifidx = 0;
556 ifp->bssidx = index;
557
558 /* Set the initial discovery state to SCAN */
559 ret = brcmf_p2p_set_discover_state(ifp, WL_P2P_DISC_ST_SCAN, 0, 0);
560
561 if (ret != 0) {
562 brcmf_err("unable to set WL_P2P_DISC_ST_SCAN\n");
563 (void)brcmf_fil_iovar_int_set(netdev_priv(ndev), "p2p_disc", 0);
564 kfree(ifp);
565 return ret;
566 }
567
568 /* create a vif for it */
569 vif = brcmf_alloc_vif(p2p->cfg, NL80211_IFTYPE_P2P_DEVICE, false);
570 if (IS_ERR(vif)) {
571 brcmf_err("could not create discovery vif\n");
572 kfree(ifp);
573 return PTR_ERR(vif);
574 }
575
576 vif->ifp = ifp;
577 ifp->vif = vif;
578 bss_dev->vif = vif;
579
580 return 0;
581}
582
583/**
584 * brcmf_p2p_deinit_discovery() - disable P2P device discovery. 509 * brcmf_p2p_deinit_discovery() - disable P2P device discovery.
585 * 510 *
586 * @p2p: P2P specific data. 511 * @p2p: P2P specific data.
587 * 512 *
588 * Resets the discovery state and disables it in firmware. The virtual 513 * Resets the discovery state and disables it in firmware.
589 * interface and P2P device are freed.
590 */ 514 */
591static s32 brcmf_p2p_deinit_discovery(struct brcmf_p2p_info *p2p) 515static s32 brcmf_p2p_deinit_discovery(struct brcmf_p2p_info *p2p)
592{ 516{
593 struct net_device *ndev = cfg_to_ndev(p2p->cfg); 517 struct brcmf_cfg80211_vif *vif;
594 struct brcmf_if *ifp;
595 struct p2p_bss *bss_dev;
596 brcmf_dbg(TRACE, "enter\n");
597 518
598 bss_dev = &p2p->bss_idx[P2PAPI_BSSCFG_DEVICE]; 519 brcmf_dbg(TRACE, "enter\n");
599 ifp = bss_dev->vif->ifp;
600 520
601 /* Set the discovery state to SCAN */ 521 /* Set the discovery state to SCAN */
602 (void)brcmf_p2p_set_discover_state(ifp, WL_P2P_DISC_ST_SCAN, 0, 0); 522 vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
523 (void)brcmf_p2p_set_discover_state(vif->ifp, WL_P2P_DISC_ST_SCAN, 0, 0);
603 524
604 /* Disable P2P discovery in the firmware */ 525 /* Disable P2P discovery in the firmware */
605 (void)brcmf_fil_iovar_int_set(netdev_priv(ndev), "p2p_disc", 0); 526 vif = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif;
606 527 (void)brcmf_fil_iovar_int_set(vif->ifp, "p2p_disc", 0);
607 /* remove discovery interface */
608 brcmf_free_vif(bss_dev->vif);
609 bss_dev->vif = NULL;
610 kfree(ifp);
611 528
612 return 0; 529 return 0;
613} 530}
@@ -626,18 +543,30 @@ static int brcmf_p2p_enable_discovery(struct brcmf_p2p_info *p2p)
626 543
627 brcmf_dbg(TRACE, "enter\n"); 544 brcmf_dbg(TRACE, "enter\n");
628 vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif; 545 vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
629 if (vif) { 546 if (!vif) {
630 brcmf_dbg(INFO, "DISCOVERY init already done\n"); 547 brcmf_err("P2P config device not available\n");
548 ret = -EPERM;
631 goto exit; 549 goto exit;
632 } 550 }
633 551
634 ret = brcmf_p2p_init_discovery(p2p); 552 if (test_bit(BRCMF_P2P_STATUS_ENABLED, &p2p->status)) {
635 if (ret < 0) { 553 brcmf_dbg(INFO, "P2P config device already configured\n");
636 brcmf_err("init discovery error %d\n", ret);
637 goto exit; 554 goto exit;
638 } 555 }
639 556
557 /* Re-initialize P2P Discovery in the firmware */
558 vif = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif;
559 ret = brcmf_fil_iovar_int_set(vif->ifp, "p2p_disc", 1);
560 if (ret < 0) {
561 brcmf_err("set p2p_disc error\n");
562 goto exit;
563 }
640 vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif; 564 vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
565 ret = brcmf_p2p_set_discover_state(vif->ifp, WL_P2P_DISC_ST_SCAN, 0, 0);
566 if (ret < 0) {
567 brcmf_err("unable to set WL_P2P_DISC_ST_SCAN\n");
568 goto exit;
569 }
641 570
642 /* 571 /*
643 * Set wsec to any non-zero value in the discovery bsscfg 572 * Set wsec to any non-zero value in the discovery bsscfg
@@ -646,9 +575,12 @@ static int brcmf_p2p_enable_discovery(struct brcmf_p2p_info *p2p)
646 * initiate WPS with us if this bit is not set. 575 * initiate WPS with us if this bit is not set.
647 */ 576 */
648 ret = brcmf_fil_bsscfg_int_set(vif->ifp, "wsec", AES_ENABLED); 577 ret = brcmf_fil_bsscfg_int_set(vif->ifp, "wsec", AES_ENABLED);
649 if (ret < 0) 578 if (ret < 0) {
650 brcmf_err("wsec error %d\n", ret); 579 brcmf_err("wsec error %d\n", ret);
580 goto exit;
581 }
651 582
583 set_bit(BRCMF_P2P_STATUS_ENABLED, &p2p->status);
652exit: 584exit:
653 return ret; 585 return ret;
654} 586}
@@ -1356,20 +1288,75 @@ exit:
1356 * 1288 *
1357 * @cfg: driver private data for cfg80211 interface. 1289 * @cfg: driver private data for cfg80211 interface.
1358 */ 1290 */
1359void brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg, 1291s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg)
1360 struct brcmf_cfg80211_vif *vif)
1361{ 1292{
1293 struct brcmf_if *pri_ifp;
1294 struct brcmf_if *p2p_ifp;
1295 struct brcmf_cfg80211_vif *p2p_vif;
1362 struct brcmf_p2p_info *p2p; 1296 struct brcmf_p2p_info *p2p;
1297 struct brcmf_pub *drvr;
1298 s32 bssidx;
1299 s32 err = 0;
1363 1300
1364 p2p = &cfg->p2p; 1301 p2p = &cfg->p2p;
1365
1366 p2p->cfg = cfg; 1302 p2p->cfg = cfg;
1367 p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif = vif; 1303
1368 brcmf_p2p_generate_bss_mac(p2p); 1304 drvr = cfg->pub;
1369 brcmf_p2p_set_firmware(p2p); 1305
1370 init_completion(&p2p->send_af_done); 1306 pri_ifp = drvr->iflist[0];
1307 p2p_ifp = drvr->iflist[1];
1308
1309 p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif = pri_ifp->vif;
1310
1311 if (p2p_ifp) {
1312 p2p_vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_STATION,
1313 false);
1314 if (IS_ERR(p2p_vif)) {
1315 brcmf_err("could not create discovery vif\n");
1316 err = -ENOMEM;
1317 goto exit;
1318 }
1319
1320 p2p_vif->ifp = p2p_ifp;
1321 p2p_ifp->vif = p2p_vif;
1322 p2p_vif->wdev.netdev = p2p_ifp->ndev;
1323 p2p_ifp->ndev->ieee80211_ptr = &p2p_vif->wdev;
1324 SET_NETDEV_DEV(p2p_ifp->ndev, wiphy_dev(cfg->wiphy));
1325
1326 p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif;
1327
1328 brcmf_p2p_generate_bss_mac(p2p);
1329 brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr);
1330
1331 /* Initialize P2P Discovery in the firmware */
1332 err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1);
1333 if (err < 0) {
1334 brcmf_err("set p2p_disc error\n");
1335 brcmf_free_vif(p2p_vif);
1336 goto exit;
1337 }
1338 /* obtain bsscfg index for P2P discovery */
1339 err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bssidx);
1340 if (err < 0) {
1341 brcmf_err("retrieving discover bsscfg index failed\n");
1342 brcmf_free_vif(p2p_vif);
1343 goto exit;
1344 }
1345 /* Verify that firmware uses same bssidx as driver !! */
1346 if (p2p_ifp->bssidx != bssidx) {
1347 brcmf_err("Incorrect bssidx=%d, compared to p2p_ifp->bssidx=%d\n",
1348 bssidx, p2p_ifp->bssidx);
1349 brcmf_free_vif(p2p_vif);
1350 goto exit;
1351 }
1352
1353 init_completion(&p2p->send_af_done);
1354 }
1355exit:
1356 return err;
1371} 1357}
1372 1358
1359
1373/** 1360/**
1374 * brcmf_p2p_detach() - detach P2P. 1361 * brcmf_p2p_detach() - detach P2P.
1375 * 1362 *
@@ -1377,10 +1364,15 @@ void brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg,
1377 */ 1364 */
1378void brcmf_p2p_detach(struct brcmf_p2p_info *p2p) 1365void brcmf_p2p_detach(struct brcmf_p2p_info *p2p)
1379{ 1366{
1380 if (p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif != NULL) { 1367 struct brcmf_cfg80211_vif *vif;
1381 brcmf_p2p_cancel_remain_on_channel( 1368
1382 p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif->ifp); 1369 vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
1370 if (vif != NULL) {
1371 brcmf_p2p_cancel_remain_on_channel(vif->ifp);
1383 brcmf_p2p_deinit_discovery(p2p); 1372 brcmf_p2p_deinit_discovery(p2p);
1373 /* remove discovery interface */
1374 brcmf_free_vif(vif);
1375 p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
1384 } 1376 }
1385 /* just set it all to zero */ 1377 /* just set it all to zero */
1386 memset(p2p, 0, sizeof(*p2p)); 1378 memset(p2p, 0, sizeof(*p2p));
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.h b/drivers/net/wireless/brcm80211/brcmfmac/p2p.h
index 0594018a7f9e..8fed9a323511 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.h
@@ -66,7 +66,8 @@ struct p2p_bss {
66 * @BRCMF_P2P_STATUS_DISCOVER_LISTEN: P2P listen, remaining on channel. 66 * @BRCMF_P2P_STATUS_DISCOVER_LISTEN: P2P listen, remaining on channel.
67 */ 67 */
68enum brcmf_p2p_status { 68enum brcmf_p2p_status {
69 BRCMF_P2P_STATUS_IF_ADD = 0, 69 BRCMF_P2P_STATUS_ENABLED,
70 BRCMF_P2P_STATUS_IF_ADD,
70 BRCMF_P2P_STATUS_IF_DEL, 71 BRCMF_P2P_STATUS_IF_DEL,
71 BRCMF_P2P_STATUS_IF_DELETING, 72 BRCMF_P2P_STATUS_IF_DELETING,
72 BRCMF_P2P_STATUS_IF_CHANGING, 73 BRCMF_P2P_STATUS_IF_CHANGING,
@@ -108,8 +109,7 @@ struct brcmf_p2p_info {
108 struct completion send_af_done; 109 struct completion send_af_done;
109}; 110};
110 111
111void brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg, 112s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg);
112 struct brcmf_cfg80211_vif *vif);
113void brcmf_p2p_detach(struct brcmf_p2p_info *p2p); 113void brcmf_p2p_detach(struct brcmf_p2p_info *p2p);
114struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name, 114struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name,
115 enum nl80211_iftype type, u32 *flags, 115 enum nl80211_iftype type, u32 *flags,
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
index 7ae84a0d5cf9..301157514be5 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
@@ -4857,11 +4857,19 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
4857 brcmf_err("Failed to init iwm_priv (%d)\n", err); 4857 brcmf_err("Failed to init iwm_priv (%d)\n", err);
4858 goto cfg80211_attach_out; 4858 goto cfg80211_attach_out;
4859 } 4859 }
4860 brcmf_p2p_attach(cfg, vif);
4861
4862 ifp->vif = vif; 4860 ifp->vif = vif;
4861
4862 err = brcmf_p2p_attach(cfg);
4863 if (err) {
4864 brcmf_err("P2P initilisation failed (%d)\n", err);
4865 goto cfg80211_p2p_attach_out;
4866 }
4867
4863 return cfg; 4868 return cfg;
4864 4869
4870cfg80211_p2p_attach_out:
4871 wl_deinit_priv(cfg);
4872
4865cfg80211_attach_out: 4873cfg80211_attach_out:
4866 brcmf_free_vif(vif); 4874 brcmf_free_vif(vif);
4867 wiphy_free(wiphy); 4875 wiphy_free(wiphy);