diff options
author | Hante Meuleman <meuleman@broadcom.com> | 2013-02-08 09:53:52 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-02-08 14:51:40 -0500 |
commit | 2fde59d93f8ac5525213996b5e98efb8f4d8c88c (patch) | |
tree | 1a484d63173e0dd710f373ba42ee40c740053168 /drivers/net/wireless/brcm80211/brcmfmac | |
parent | 1ce3086ccd81793fd6affb350826a0c41dc3ef37 (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.c | 109 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/p2p.c | 226 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/p2p.h | 6 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | 12 |
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"); | |||
42 | int brcmf_msg_level; | 42 | int brcmf_msg_level; |
43 | module_param(brcmf_msg_level, int, 0); | 43 | module_param(brcmf_msg_level, int, 0); |
44 | 44 | ||
45 | /* P2P0 enable */ | ||
46 | static int brcmf_p2p_enable; | ||
47 | #ifdef CONFIG_BRCMDBG | ||
48 | module_param_named(p2pon, brcmf_p2p_enable, int, 0); | ||
49 | MODULE_PARM_DESC(p2pon, "enable p2p management functionality"); | ||
50 | #endif | ||
45 | 51 | ||
46 | char *brcmf_ifname(struct brcmf_pub *drvr, int ifidx) | 52 | char *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 | ||
596 | static 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 | |||
606 | int brcmf_net_attach(struct brcmf_if *ifp) | 602 | int 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 | ||
640 | static 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 | |||
647 | static 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 | |||
654 | static 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 | |||
661 | static 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 | |||
670 | static 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 | |||
677 | static 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 | |||
699 | fail: | ||
700 | return -EBADE; | ||
701 | } | ||
702 | |||
644 | struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx, | 703 | struct 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 | */ |
412 | static int brcmf_p2p_set_firmware(struct brcmf_p2p_info *p2p) | 413 | static 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 | */ |
441 | static void brcmf_p2p_generate_bss_mac(struct brcmf_p2p_info *p2p) | 440 | static 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 | */ | ||
513 | static 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 | */ |
591 | static s32 brcmf_p2p_deinit_discovery(struct brcmf_p2p_info *p2p) | 515 | static 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); | ||
652 | exit: | 584 | exit: |
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 | */ |
1359 | void brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg, | 1291 | s32 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 | } | ||
1355 | exit: | ||
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 | */ |
1378 | void brcmf_p2p_detach(struct brcmf_p2p_info *p2p) | 1365 | void 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 | */ |
68 | enum brcmf_p2p_status { | 68 | enum 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 | ||
111 | void brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg, | 112 | s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg); |
112 | struct brcmf_cfg80211_vif *vif); | ||
113 | void brcmf_p2p_detach(struct brcmf_p2p_info *p2p); | 113 | void brcmf_p2p_detach(struct brcmf_p2p_info *p2p); |
114 | struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name, | 114 | struct 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 | ||
4870 | cfg80211_p2p_attach_out: | ||
4871 | wl_deinit_priv(cfg); | ||
4872 | |||
4865 | cfg80211_attach_out: | 4873 | cfg80211_attach_out: |
4866 | brcmf_free_vif(vif); | 4874 | brcmf_free_vif(vif); |
4867 | wiphy_free(wiphy); | 4875 | wiphy_free(wiphy); |