diff options
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h | 5 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/p2p.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/p2p.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | 255 |
4 files changed, 183 insertions, 86 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h index 7707194d4e7e..2c4ca59c35cf 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h | |||
@@ -39,4 +39,9 @@ struct brcmf_fil_chan_info_le { | |||
39 | __le32 scan_channel; | 39 | __le32 scan_channel; |
40 | }; | 40 | }; |
41 | 41 | ||
42 | struct brcmf_fil_bss_enable_le { | ||
43 | __le32 bsscfg_idx; | ||
44 | __le32 enable; | ||
45 | }; | ||
46 | |||
42 | #endif /* FWIL_TYPES_H_ */ | 47 | #endif /* FWIL_TYPES_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c index fa0127e809ac..d5f97117b266 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c | |||
@@ -691,15 +691,17 @@ void brcmf_p2p_cancel_remain_on_channel(struct brcmf_if *ifp) | |||
691 | * | 691 | * |
692 | * @cfg: driver private data for cfg80211 interface. | 692 | * @cfg: driver private data for cfg80211 interface. |
693 | */ | 693 | */ |
694 | void brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg) | 694 | void brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg, |
695 | struct brcmf_cfg80211_vif *vif) | ||
695 | { | 696 | { |
696 | struct brcmf_p2p_info *p2p; | 697 | struct brcmf_p2p_info *p2p; |
697 | 698 | ||
698 | p2p = &cfg->p2p; | 699 | p2p = &cfg->p2p; |
699 | 700 | ||
700 | p2p->cfg = cfg; | 701 | p2p->cfg = cfg; |
701 | brcmf_p2p_set_firmware(p2p); | 702 | p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif = vif; |
702 | brcmf_p2p_generate_bss_mac(p2p); | 703 | brcmf_p2p_generate_bss_mac(p2p); |
704 | brcmf_p2p_set_firmware(p2p); | ||
703 | } | 705 | } |
704 | 706 | ||
705 | /** | 707 | /** |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.h b/drivers/net/wireless/brcm80211/brcmfmac/p2p.h index 1bf57c180739..4c1819c1fcc7 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.h | |||
@@ -102,7 +102,8 @@ struct brcmf_p2p_info { | |||
102 | struct ieee80211_channel remain_on_channel; | 102 | struct ieee80211_channel remain_on_channel; |
103 | }; | 103 | }; |
104 | 104 | ||
105 | void brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg); | 105 | void brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg, |
106 | struct brcmf_cfg80211_vif *vif); | ||
106 | void brcmf_p2p_detach(struct brcmf_p2p_info *p2p); | 107 | void brcmf_p2p_detach(struct brcmf_p2p_info *p2p); |
107 | struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name, | 108 | struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name, |
108 | enum nl80211_iftype type, u32 *flags, | 109 | 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 311226575583..c94d5361ca8f 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | |||
@@ -3625,9 +3625,37 @@ s32 brcmf_vif_clear_mgmt_ies(struct brcmf_cfg80211_vif *vif) | |||
3625 | } | 3625 | } |
3626 | 3626 | ||
3627 | static s32 | 3627 | static s32 |
3628 | brcmf_config_ap_mgmt_ie(struct brcmf_cfg80211_vif *vif, | ||
3629 | struct cfg80211_beacon_data *beacon) | ||
3630 | { | ||
3631 | s32 err; | ||
3632 | |||
3633 | /* Set Beacon IEs to FW */ | ||
3634 | err = brcmf_vif_set_mgmt_ie(vif, BRCMF_VNDR_IE_BEACON_FLAG, | ||
3635 | beacon->tail, beacon->tail_len); | ||
3636 | if (err) { | ||
3637 | brcmf_err("Set Beacon IE Failed\n"); | ||
3638 | return err; | ||
3639 | } | ||
3640 | brcmf_dbg(TRACE, "Applied Vndr IEs for Beacon\n"); | ||
3641 | |||
3642 | /* Set Probe Response IEs to FW */ | ||
3643 | err = brcmf_vif_set_mgmt_ie(vif, BRCMF_VNDR_IE_PRBRSP_FLAG, | ||
3644 | beacon->proberesp_ies, | ||
3645 | beacon->proberesp_ies_len); | ||
3646 | if (err) | ||
3647 | brcmf_err("Set Probe Resp IE Failed\n"); | ||
3648 | else | ||
3649 | brcmf_dbg(TRACE, "Applied Vndr IEs for Probe Resp\n"); | ||
3650 | |||
3651 | return err; | ||
3652 | } | ||
3653 | |||
3654 | static s32 | ||
3628 | brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, | 3655 | brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, |
3629 | struct cfg80211_ap_settings *settings) | 3656 | struct cfg80211_ap_settings *settings) |
3630 | { | 3657 | { |
3658 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | ||
3631 | s32 ie_offset; | 3659 | s32 ie_offset; |
3632 | struct brcmf_if *ifp = netdev_priv(ndev); | 3660 | struct brcmf_if *ifp = netdev_priv(ndev); |
3633 | struct brcmf_tlv *ssid_ie; | 3661 | struct brcmf_tlv *ssid_ie; |
@@ -3636,6 +3664,8 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, | |||
3636 | struct brcmf_tlv *rsn_ie; | 3664 | struct brcmf_tlv *rsn_ie; |
3637 | struct brcmf_vs_tlv *wpa_ie; | 3665 | struct brcmf_vs_tlv *wpa_ie; |
3638 | struct brcmf_join_params join_params; | 3666 | struct brcmf_join_params join_params; |
3667 | enum nl80211_iftype dev_role; | ||
3668 | struct brcmf_fil_bss_enable_le bss_enable; | ||
3639 | 3669 | ||
3640 | brcmf_dbg(TRACE, "channel_type=%d, beacon_interval=%d, dtim_period=%d,\n", | 3670 | brcmf_dbg(TRACE, "channel_type=%d, beacon_interval=%d, dtim_period=%d,\n", |
3641 | cfg80211_get_chandef_type(&settings->chandef), | 3671 | cfg80211_get_chandef_type(&settings->chandef), |
@@ -3645,9 +3675,21 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, | |||
3645 | settings->ssid, settings->ssid_len, settings->auth_type, | 3675 | settings->ssid, settings->ssid_len, settings->auth_type, |
3646 | settings->inactivity_timeout); | 3676 | settings->inactivity_timeout); |
3647 | 3677 | ||
3648 | if (!test_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state)) { | 3678 | if (ifp->vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif) { |
3649 | brcmf_err("Not in AP creation mode\n"); | 3679 | brcmf_dbg(TRACE, "Role = AP\n"); |
3650 | return -EPERM; | 3680 | dev_role = NL80211_IFTYPE_AP; |
3681 | if (!test_bit(BRCMF_VIF_STATUS_AP_CREATING, | ||
3682 | &ifp->vif->sme_state)) { | ||
3683 | brcmf_err("Not in AP creation mode\n"); | ||
3684 | return -EPERM; | ||
3685 | } | ||
3686 | } else { | ||
3687 | brcmf_dbg(TRACE, "Role = P2P GO\n"); | ||
3688 | dev_role = NL80211_IFTYPE_P2P_GO; | ||
3689 | if (ifp->vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif) { | ||
3690 | ifp = cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp; | ||
3691 | ndev = ifp->ndev; | ||
3692 | } | ||
3651 | } | 3693 | } |
3652 | 3694 | ||
3653 | memset(&ssid_le, 0, sizeof(ssid_le)); | 3695 | memset(&ssid_le, 0, sizeof(ssid_le)); |
@@ -3669,21 +3711,6 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, | |||
3669 | } | 3711 | } |
3670 | 3712 | ||
3671 | brcmf_set_mpc(ndev, 0); | 3713 | brcmf_set_mpc(ndev, 0); |
3672 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1); | ||
3673 | if (err < 0) { | ||
3674 | brcmf_err("BRCMF_C_DOWN error %d\n", err); | ||
3675 | goto exit; | ||
3676 | } | ||
3677 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, 1); | ||
3678 | if (err < 0) { | ||
3679 | brcmf_err("SET INFRA error %d\n", err); | ||
3680 | goto exit; | ||
3681 | } | ||
3682 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 1); | ||
3683 | if (err < 0) { | ||
3684 | brcmf_err("setting AP mode failed %d\n", err); | ||
3685 | goto exit; | ||
3686 | } | ||
3687 | 3714 | ||
3688 | /* find the RSN_IE */ | 3715 | /* find the RSN_IE */ |
3689 | rsn_ie = brcmf_parse_tlvs((u8 *)settings->beacon.tail, | 3716 | rsn_ie = brcmf_parse_tlvs((u8 *)settings->beacon.tail, |
@@ -3711,25 +3738,8 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, | |||
3711 | brcmf_dbg(TRACE, "No WPA(2) IEs found\n"); | 3738 | brcmf_dbg(TRACE, "No WPA(2) IEs found\n"); |
3712 | brcmf_configure_opensecurity(ifp); | 3739 | brcmf_configure_opensecurity(ifp); |
3713 | } | 3740 | } |
3714 | /* Set Beacon IEs to FW */ | ||
3715 | err = brcmf_vif_set_mgmt_ie(ndev_to_vif(ndev), | ||
3716 | BRCMF_VNDR_IE_BEACON_FLAG, | ||
3717 | settings->beacon.tail, | ||
3718 | settings->beacon.tail_len); | ||
3719 | if (err) | ||
3720 | brcmf_err("Set Beacon IE Failed\n"); | ||
3721 | else | ||
3722 | brcmf_dbg(TRACE, "Applied Vndr IEs for Beacon\n"); | ||
3723 | 3741 | ||
3724 | /* Set Probe Response IEs to FW */ | 3742 | brcmf_config_ap_mgmt_ie(ifp->vif, &settings->beacon); |
3725 | err = brcmf_vif_set_mgmt_ie(ndev_to_vif(ndev), | ||
3726 | BRCMF_VNDR_IE_PRBRSP_FLAG, | ||
3727 | settings->beacon.proberesp_ies, | ||
3728 | settings->beacon.proberesp_ies_len); | ||
3729 | if (err) | ||
3730 | brcmf_err("Set Probe Resp IE Failed\n"); | ||
3731 | else | ||
3732 | brcmf_dbg(TRACE, "Applied Vndr IEs for Probe Resp\n"); | ||
3733 | 3743 | ||
3734 | if (settings->beacon_interval) { | 3744 | if (settings->beacon_interval) { |
3735 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_BCNPRD, | 3745 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_BCNPRD, |
@@ -3747,23 +3757,62 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, | |||
3747 | goto exit; | 3757 | goto exit; |
3748 | } | 3758 | } |
3749 | } | 3759 | } |
3750 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1); | 3760 | |
3751 | if (err < 0) { | 3761 | if (dev_role == NL80211_IFTYPE_AP) { |
3752 | brcmf_err("BRCMF_C_UP error (%d)\n", err); | 3762 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1); |
3753 | goto exit; | 3763 | if (err < 0) { |
3764 | brcmf_err("BRCMF_C_DOWN error %d\n", err); | ||
3765 | goto exit; | ||
3766 | } | ||
3754 | brcmf_fil_iovar_int_set(ifp, "apsta", 0); | 3767 | brcmf_fil_iovar_int_set(ifp, "apsta", 0); |
3755 | } | 3768 | } |
3756 | 3769 | ||
3757 | memset(&join_params, 0, sizeof(join_params)); | 3770 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, 1); |
3758 | /* join parameters starts with ssid */ | ||
3759 | memcpy(&join_params.ssid_le, &ssid_le, sizeof(ssid_le)); | ||
3760 | /* create softap */ | ||
3761 | err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID, | ||
3762 | &join_params, sizeof(join_params)); | ||
3763 | if (err < 0) { | 3771 | if (err < 0) { |
3764 | brcmf_err("SET SSID error (%d)\n", err); | 3772 | brcmf_err("SET INFRA error %d\n", err); |
3765 | goto exit; | 3773 | goto exit; |
3766 | } | 3774 | } |
3775 | if (dev_role == NL80211_IFTYPE_AP) { | ||
3776 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 1); | ||
3777 | if (err < 0) { | ||
3778 | brcmf_err("setting AP mode failed %d\n", err); | ||
3779 | goto exit; | ||
3780 | } | ||
3781 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1); | ||
3782 | if (err < 0) { | ||
3783 | brcmf_err("BRCMF_C_UP error (%d)\n", err); | ||
3784 | goto exit; | ||
3785 | } | ||
3786 | |||
3787 | memset(&join_params, 0, sizeof(join_params)); | ||
3788 | /* join parameters starts with ssid */ | ||
3789 | memcpy(&join_params.ssid_le, &ssid_le, sizeof(ssid_le)); | ||
3790 | /* create softap */ | ||
3791 | err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID, | ||
3792 | &join_params, sizeof(join_params)); | ||
3793 | if (err < 0) { | ||
3794 | brcmf_err("SET SSID error (%d)\n", err); | ||
3795 | goto exit; | ||
3796 | } | ||
3797 | brcmf_dbg(TRACE, "AP mode configuration complete\n"); | ||
3798 | } else { | ||
3799 | err = brcmf_fil_bsscfg_data_set(ifp, "ssid", &ssid_le, | ||
3800 | sizeof(ssid_le)); | ||
3801 | if (err < 0) { | ||
3802 | brcmf_err("setting ssid failed %d\n", err); | ||
3803 | goto exit; | ||
3804 | } | ||
3805 | bss_enable.bsscfg_idx = cpu_to_le32(ifp->bssidx); | ||
3806 | bss_enable.enable = cpu_to_le32(1); | ||
3807 | err = brcmf_fil_iovar_data_set(ifp, "bss", &bss_enable, | ||
3808 | sizeof(bss_enable)); | ||
3809 | if (err < 0) { | ||
3810 | brcmf_err("bss_enable config failed %d\n", err); | ||
3811 | goto exit; | ||
3812 | } | ||
3813 | |||
3814 | brcmf_dbg(TRACE, "GO mode configuration complete\n"); | ||
3815 | } | ||
3767 | clear_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state); | 3816 | clear_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state); |
3768 | set_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state); | 3817 | set_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state); |
3769 | 3818 | ||
@@ -3802,10 +3851,41 @@ exit: | |||
3802 | return err; | 3851 | return err; |
3803 | } | 3852 | } |
3804 | 3853 | ||
3854 | static s32 | ||
3855 | brcmf_cfg80211_change_beacon(struct wiphy *wiphy, struct net_device *ndev, | ||
3856 | struct cfg80211_beacon_data *info) | ||
3857 | { | ||
3858 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | ||
3859 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
3860 | s32 err; | ||
3861 | |||
3862 | brcmf_dbg(TRACE, "Enter\n"); | ||
3863 | |||
3864 | if (ifp->vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif) { | ||
3865 | brcmf_dbg(TRACE, "Role = AP\n"); | ||
3866 | if (!test_bit(BRCMF_VIF_STATUS_AP_CREATED, | ||
3867 | &ifp->vif->sme_state)) { | ||
3868 | brcmf_err("AP was not yet created\n"); | ||
3869 | return -EPERM; | ||
3870 | } | ||
3871 | } else { | ||
3872 | brcmf_dbg(TRACE, "Role = P2P GO\n"); | ||
3873 | if (ifp->vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif) { | ||
3874 | ifp = cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp; | ||
3875 | ndev = ifp->ndev; | ||
3876 | } | ||
3877 | } | ||
3878 | |||
3879 | err = brcmf_config_ap_mgmt_ie(ifp->vif, info); | ||
3880 | |||
3881 | return err; | ||
3882 | } | ||
3883 | |||
3805 | static int | 3884 | static int |
3806 | brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, | 3885 | brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, |
3807 | u8 *mac) | 3886 | u8 *mac) |
3808 | { | 3887 | { |
3888 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | ||
3809 | struct brcmf_scb_val_le scbval; | 3889 | struct brcmf_scb_val_le scbval; |
3810 | struct brcmf_if *ifp = netdev_priv(ndev); | 3890 | struct brcmf_if *ifp = netdev_priv(ndev); |
3811 | s32 err; | 3891 | s32 err; |
@@ -3815,6 +3895,8 @@ brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, | |||
3815 | 3895 | ||
3816 | brcmf_dbg(TRACE, "Enter %pM\n", mac); | 3896 | brcmf_dbg(TRACE, "Enter %pM\n", mac); |
3817 | 3897 | ||
3898 | if (ifp->vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif) | ||
3899 | ifp = cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp; | ||
3818 | if (!check_vif_up(ifp->vif)) | 3900 | if (!check_vif_up(ifp->vif)) |
3819 | return -EIO; | 3901 | return -EIO; |
3820 | 3902 | ||
@@ -3824,7 +3906,12 @@ brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, | |||
3824 | &scbval, sizeof(scbval)); | 3906 | &scbval, sizeof(scbval)); |
3825 | if (err) | 3907 | if (err) |
3826 | brcmf_err("SCB_DEAUTHENTICATE_FOR_REASON failed %d\n", err); | 3908 | brcmf_err("SCB_DEAUTHENTICATE_FOR_REASON failed %d\n", err); |
3827 | 3909 | /* | |
3910 | * Wait for the deauth event to come, supplicant will do the | ||
3911 | * delete iface immediately and we will have problem in sending | ||
3912 | * deauth frame if we delete the bss in firmware | ||
3913 | */ | ||
3914 | brcmf_delay(400); | ||
3828 | brcmf_dbg(TRACE, "Exit\n"); | 3915 | brcmf_dbg(TRACE, "Exit\n"); |
3829 | return err; | 3916 | return err; |
3830 | } | 3917 | } |
@@ -3857,6 +3944,7 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
3857 | { | 3944 | { |
3858 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | 3945 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
3859 | const struct ieee80211_mgmt *mgmt; | 3946 | const struct ieee80211_mgmt *mgmt; |
3947 | struct brcmf_if *ifp; | ||
3860 | struct brcmf_cfg80211_vif *vif; | 3948 | struct brcmf_cfg80211_vif *vif; |
3861 | s32 err = 0; | 3949 | s32 err = 0; |
3862 | s32 ie_offset; | 3950 | s32 ie_offset; |
@@ -3868,41 +3956,41 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
3868 | 3956 | ||
3869 | mgmt = (const struct ieee80211_mgmt *)buf; | 3957 | mgmt = (const struct ieee80211_mgmt *)buf; |
3870 | 3958 | ||
3871 | if (ieee80211_is_mgmt(mgmt->frame_control)) { | 3959 | if (!ieee80211_is_mgmt(mgmt->frame_control)) { |
3872 | if (ieee80211_is_probe_resp(mgmt->frame_control)) { | 3960 | brcmf_err("Driver only allows MGMT packet type\n"); |
3873 | /* Right now the only reason to get a probe response */ | 3961 | return -EPERM; |
3874 | /* is for p2p listen response from wpa_supplicant. */ | 3962 | } |
3875 | /* Unfortunately the wpa_supplicant sends it on the */ | ||
3876 | /* primary ndev, while dongle wants it on the p2p */ | ||
3877 | /* vif. Since this is only reason for a probe */ | ||
3878 | /* response to be sent, the vif is taken from cfg. */ | ||
3879 | /* If ever desired to send proberesp for non p2p */ | ||
3880 | /* response then data should be checked for */ | ||
3881 | /* "DIRECT-". Note in future supplicant will take */ | ||
3882 | /* dedicated p2p wdev to do this and then this 'hack'*/ | ||
3883 | /* is not needed anymore. */ | ||
3884 | ie_offset = DOT11_MGMT_HDR_LEN + | ||
3885 | DOT11_BCN_PRB_FIXED_LEN; | ||
3886 | ie_len = len - ie_offset; | ||
3887 | 3963 | ||
3964 | if (ieee80211_is_probe_resp(mgmt->frame_control)) { | ||
3965 | /* Right now the only reason to get a probe response */ | ||
3966 | /* is for p2p listen response or for p2p GO from */ | ||
3967 | /* wpa_supplicant. Unfortunately the probe is send */ | ||
3968 | /* on primary ndev, while dongle wants it on the p2p */ | ||
3969 | /* vif. Since this is only reason for a probe */ | ||
3970 | /* response to be sent, the vif is taken from cfg. */ | ||
3971 | /* If ever desired to send proberesp for non p2p */ | ||
3972 | /* response then data should be checked for */ | ||
3973 | /* "DIRECT-". Note in future supplicant will take */ | ||
3974 | /* dedicated p2p wdev to do this and then this 'hack'*/ | ||
3975 | /* is not needed anymore. */ | ||
3976 | ie_offset = DOT11_MGMT_HDR_LEN + | ||
3977 | DOT11_BCN_PRB_FIXED_LEN; | ||
3978 | ie_len = len - ie_offset; | ||
3979 | ifp = netdev_priv(wdev->netdev); | ||
3980 | vif = ifp->vif; | ||
3981 | if (vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif) | ||
3888 | vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif; | 3982 | vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif; |
3889 | if (vif == NULL) { | 3983 | err = brcmf_vif_set_mgmt_ie(vif, |
3890 | brcmf_err("No p2p device available for probe response\n"); | 3984 | BRCMF_VNDR_IE_PRBRSP_FLAG, |
3891 | err = -ENODEV; | 3985 | &buf[ie_offset], |
3892 | goto exit; | 3986 | ie_len); |
3893 | } | 3987 | cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, true, |
3894 | err = brcmf_vif_set_mgmt_ie(vif, | 3988 | GFP_KERNEL); |
3895 | BRCMF_VNDR_IE_PRBRSP_FLAG, | 3989 | } else { |
3896 | &buf[ie_offset], | 3990 | brcmf_dbg(TRACE, "Unhandled, fc=%04x!!\n", mgmt->frame_control); |
3897 | ie_len); | 3991 | brcmf_dbg_hex_dump(true, buf, len, "payload, len=%Zu\n", len); |
3898 | cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, true, | ||
3899 | GFP_KERNEL); | ||
3900 | goto exit; | ||
3901 | } | ||
3902 | } | 3992 | } |
3903 | brcmf_dbg(TRACE, "Unhandled, is_mgmt %d, fc=%04x!!!!!\n", | 3993 | |
3904 | ieee80211_is_mgmt(mgmt->frame_control), mgmt->frame_control); | ||
3905 | exit: | ||
3906 | return err; | 3994 | return err; |
3907 | } | 3995 | } |
3908 | 3996 | ||
@@ -3946,8 +4034,8 @@ static s32 brcmf_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp, | |||
3946 | "Enter: event %d reason %d\n", e->event_code, e->reason); | 4034 | "Enter: event %d reason %d\n", e->event_code, e->reason); |
3947 | 4035 | ||
3948 | /* Firmware sends us two proberesponses for each idx one. At the */ | 4036 | /* Firmware sends us two proberesponses for each idx one. At the */ |
3949 | /* moment only bsscfgidx 0 is passed up to supplicant */ | 4037 | /* moment anything but bsscfgidx 0 is passed up to supplicant */ |
3950 | if (e->bsscfgidx) | 4038 | if (e->bsscfgidx == 0) |
3951 | return 0; | 4039 | return 0; |
3952 | 4040 | ||
3953 | /* Check if wpa_supplicant has registered for this frame */ | 4041 | /* Check if wpa_supplicant has registered for this frame */ |
@@ -3999,6 +4087,7 @@ static struct cfg80211_ops wl_cfg80211_ops = { | |||
3999 | .flush_pmksa = brcmf_cfg80211_flush_pmksa, | 4087 | .flush_pmksa = brcmf_cfg80211_flush_pmksa, |
4000 | .start_ap = brcmf_cfg80211_start_ap, | 4088 | .start_ap = brcmf_cfg80211_start_ap, |
4001 | .stop_ap = brcmf_cfg80211_stop_ap, | 4089 | .stop_ap = brcmf_cfg80211_stop_ap, |
4090 | .change_beacon = brcmf_cfg80211_change_beacon, | ||
4002 | .del_station = brcmf_cfg80211_del_station, | 4091 | .del_station = brcmf_cfg80211_del_station, |
4003 | .sched_scan_start = brcmf_cfg80211_sched_scan_start, | 4092 | .sched_scan_start = brcmf_cfg80211_sched_scan_start, |
4004 | .sched_scan_stop = brcmf_cfg80211_sched_scan_stop, | 4093 | .sched_scan_stop = brcmf_cfg80211_sched_scan_stop, |
@@ -4727,7 +4816,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, | |||
4727 | brcmf_err("Failed to init iwm_priv (%d)\n", err); | 4816 | brcmf_err("Failed to init iwm_priv (%d)\n", err); |
4728 | goto cfg80211_attach_out; | 4817 | goto cfg80211_attach_out; |
4729 | } | 4818 | } |
4730 | brcmf_p2p_attach(cfg); | 4819 | brcmf_p2p_attach(cfg, vif); |
4731 | 4820 | ||
4732 | ifp->vif = vif; | 4821 | ifp->vif = vif; |
4733 | return cfg; | 4822 | return cfg; |