diff options
Diffstat (limited to 'drivers/net/wireless/ath/wil6210/cfg80211.c')
| -rw-r--r-- | drivers/net/wireless/ath/wil6210/cfg80211.c | 458 |
1 files changed, 347 insertions, 111 deletions
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index cdbb393863f3..d18e81fae5f1 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c | |||
| @@ -48,9 +48,29 @@ static struct ieee80211_channel wil_60ghz_channels[] = { | |||
| 48 | CHAN60G(1, 0), | 48 | CHAN60G(1, 0), |
| 49 | CHAN60G(2, 0), | 49 | CHAN60G(2, 0), |
| 50 | CHAN60G(3, 0), | 50 | CHAN60G(3, 0), |
| 51 | /* channel 4 not supported yet */ | 51 | CHAN60G(4, 0), |
| 52 | }; | 52 | }; |
| 53 | 53 | ||
| 54 | static int wil_num_supported_channels(struct wil6210_priv *wil) | ||
| 55 | { | ||
| 56 | int num_channels = ARRAY_SIZE(wil_60ghz_channels); | ||
| 57 | |||
| 58 | if (!test_bit(WMI_FW_CAPABILITY_CHANNEL_4, wil->fw_capabilities)) | ||
| 59 | num_channels--; | ||
| 60 | |||
| 61 | return num_channels; | ||
| 62 | } | ||
| 63 | |||
| 64 | void update_supported_bands(struct wil6210_priv *wil) | ||
| 65 | { | ||
| 66 | struct wiphy *wiphy = wil_to_wiphy(wil); | ||
| 67 | |||
| 68 | wil_dbg_misc(wil, "update supported bands"); | ||
| 69 | |||
| 70 | wiphy->bands[NL80211_BAND_60GHZ]->n_channels = | ||
| 71 | wil_num_supported_channels(wil); | ||
| 72 | } | ||
| 73 | |||
| 54 | /* Vendor id to be used in vendor specific command and events | 74 | /* Vendor id to be used in vendor specific command and events |
| 55 | * to user space. | 75 | * to user space. |
| 56 | * NOTE: The authoritative place for definition of QCA_NL80211_VENDOR_ID, | 76 | * NOTE: The authoritative place for definition of QCA_NL80211_VENDOR_ID, |
| @@ -199,7 +219,9 @@ wil_mgmt_stypes[NUM_NL80211_IFTYPES] = { | |||
| 199 | .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | | 219 | .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | |
| 200 | BIT(IEEE80211_STYPE_PROBE_RESP >> 4) | | 220 | BIT(IEEE80211_STYPE_PROBE_RESP >> 4) | |
| 201 | BIT(IEEE80211_STYPE_ASSOC_RESP >> 4) | | 221 | BIT(IEEE80211_STYPE_ASSOC_RESP >> 4) | |
| 202 | BIT(IEEE80211_STYPE_DISASSOC >> 4), | 222 | BIT(IEEE80211_STYPE_DISASSOC >> 4) | |
| 223 | BIT(IEEE80211_STYPE_AUTH >> 4) | | ||
| 224 | BIT(IEEE80211_STYPE_REASSOC_RESP >> 4), | ||
| 203 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | 225 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | |
| 204 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | | 226 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | |
| 205 | BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | | 227 | BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | |
| @@ -276,6 +298,8 @@ int wil_cid_fill_sinfo(struct wil6210_vif *vif, int cid, | |||
| 276 | struct wil_net_stats *stats = &wil->sta[cid].stats; | 298 | struct wil_net_stats *stats = &wil->sta[cid].stats; |
| 277 | int rc; | 299 | int rc; |
| 278 | 300 | ||
| 301 | memset(&reply, 0, sizeof(reply)); | ||
| 302 | |||
| 279 | rc = wmi_call(wil, WMI_NOTIFY_REQ_CMDID, vif->mid, &cmd, sizeof(cmd), | 303 | rc = wmi_call(wil, WMI_NOTIFY_REQ_CMDID, vif->mid, &cmd, sizeof(cmd), |
| 280 | WMI_NOTIFY_REQ_DONE_EVENTID, &reply, sizeof(reply), 20); | 304 | WMI_NOTIFY_REQ_DONE_EVENTID, &reply, sizeof(reply), 20); |
| 281 | if (rc) | 305 | if (rc) |
| @@ -300,14 +324,14 @@ int wil_cid_fill_sinfo(struct wil6210_vif *vif, int cid, | |||
| 300 | 324 | ||
| 301 | sinfo->generation = wil->sinfo_gen; | 325 | sinfo->generation = wil->sinfo_gen; |
| 302 | 326 | ||
| 303 | sinfo->filled = BIT(NL80211_STA_INFO_RX_BYTES) | | 327 | sinfo->filled = BIT_ULL(NL80211_STA_INFO_RX_BYTES) | |
| 304 | BIT(NL80211_STA_INFO_TX_BYTES) | | 328 | BIT_ULL(NL80211_STA_INFO_TX_BYTES) | |
| 305 | BIT(NL80211_STA_INFO_RX_PACKETS) | | 329 | BIT_ULL(NL80211_STA_INFO_RX_PACKETS) | |
| 306 | BIT(NL80211_STA_INFO_TX_PACKETS) | | 330 | BIT_ULL(NL80211_STA_INFO_TX_PACKETS) | |
| 307 | BIT(NL80211_STA_INFO_RX_BITRATE) | | 331 | BIT_ULL(NL80211_STA_INFO_RX_BITRATE) | |
| 308 | BIT(NL80211_STA_INFO_TX_BITRATE) | | 332 | BIT_ULL(NL80211_STA_INFO_TX_BITRATE) | |
| 309 | BIT(NL80211_STA_INFO_RX_DROP_MISC) | | 333 | BIT_ULL(NL80211_STA_INFO_RX_DROP_MISC) | |
| 310 | BIT(NL80211_STA_INFO_TX_FAILED); | 334 | BIT_ULL(NL80211_STA_INFO_TX_FAILED); |
| 311 | 335 | ||
| 312 | sinfo->txrate.flags = RATE_INFO_FLAGS_60G; | 336 | sinfo->txrate.flags = RATE_INFO_FLAGS_60G; |
| 313 | sinfo->txrate.mcs = le16_to_cpu(reply.evt.bf_mcs); | 337 | sinfo->txrate.mcs = le16_to_cpu(reply.evt.bf_mcs); |
| @@ -320,7 +344,7 @@ int wil_cid_fill_sinfo(struct wil6210_vif *vif, int cid, | |||
| 320 | sinfo->tx_failed = stats->tx_errors; | 344 | sinfo->tx_failed = stats->tx_errors; |
| 321 | 345 | ||
| 322 | if (test_bit(wil_vif_fwconnected, vif->status)) { | 346 | if (test_bit(wil_vif_fwconnected, vif->status)) { |
| 323 | sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); | 347 | sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL); |
| 324 | if (test_bit(WMI_FW_CAPABILITY_RSSI_REPORTING, | 348 | if (test_bit(WMI_FW_CAPABILITY_RSSI_REPORTING, |
| 325 | wil->fw_capabilities)) | 349 | wil->fw_capabilities)) |
| 326 | sinfo->signal = reply.evt.rssi; | 350 | sinfo->signal = reply.evt.rssi; |
| @@ -687,11 +711,12 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, | |||
| 687 | 711 | ||
| 688 | wil_dbg_misc(wil, "scan: wdev=0x%p iftype=%d\n", wdev, wdev->iftype); | 712 | wil_dbg_misc(wil, "scan: wdev=0x%p iftype=%d\n", wdev, wdev->iftype); |
| 689 | 713 | ||
| 690 | /* check we are client side */ | 714 | /* scan is supported on client interfaces and on AP interface */ |
| 691 | switch (wdev->iftype) { | 715 | switch (wdev->iftype) { |
| 692 | case NL80211_IFTYPE_STATION: | 716 | case NL80211_IFTYPE_STATION: |
| 693 | case NL80211_IFTYPE_P2P_CLIENT: | 717 | case NL80211_IFTYPE_P2P_CLIENT: |
| 694 | case NL80211_IFTYPE_P2P_DEVICE: | 718 | case NL80211_IFTYPE_P2P_DEVICE: |
| 719 | case NL80211_IFTYPE_AP: | ||
| 695 | break; | 720 | break; |
| 696 | default: | 721 | default: |
| 697 | return -EOPNOTSUPP; | 722 | return -EOPNOTSUPP; |
| @@ -868,6 +893,26 @@ static void wil_print_crypto(struct wil6210_priv *wil, | |||
| 868 | c->control_port_no_encrypt); | 893 | c->control_port_no_encrypt); |
| 869 | } | 894 | } |
| 870 | 895 | ||
| 896 | static const char * | ||
| 897 | wil_get_auth_type_name(enum nl80211_auth_type auth_type) | ||
| 898 | { | ||
| 899 | switch (auth_type) { | ||
| 900 | case NL80211_AUTHTYPE_OPEN_SYSTEM: | ||
| 901 | return "OPEN_SYSTEM"; | ||
| 902 | case NL80211_AUTHTYPE_SHARED_KEY: | ||
| 903 | return "SHARED_KEY"; | ||
| 904 | case NL80211_AUTHTYPE_FT: | ||
| 905 | return "FT"; | ||
| 906 | case NL80211_AUTHTYPE_NETWORK_EAP: | ||
| 907 | return "NETWORK_EAP"; | ||
| 908 | case NL80211_AUTHTYPE_SAE: | ||
| 909 | return "SAE"; | ||
| 910 | case NL80211_AUTHTYPE_AUTOMATIC: | ||
| 911 | return "AUTOMATIC"; | ||
| 912 | default: | ||
| 913 | return "unknown"; | ||
| 914 | } | ||
| 915 | } | ||
| 871 | static void wil_print_connect_params(struct wil6210_priv *wil, | 916 | static void wil_print_connect_params(struct wil6210_priv *wil, |
| 872 | struct cfg80211_connect_params *sme) | 917 | struct cfg80211_connect_params *sme) |
| 873 | { | 918 | { |
| @@ -881,11 +926,73 @@ static void wil_print_connect_params(struct wil6210_priv *wil, | |||
| 881 | if (sme->ssid) | 926 | if (sme->ssid) |
| 882 | print_hex_dump(KERN_INFO, " SSID: ", DUMP_PREFIX_OFFSET, | 927 | print_hex_dump(KERN_INFO, " SSID: ", DUMP_PREFIX_OFFSET, |
| 883 | 16, 1, sme->ssid, sme->ssid_len, true); | 928 | 16, 1, sme->ssid, sme->ssid_len, true); |
| 929 | if (sme->prev_bssid) | ||
| 930 | wil_info(wil, " Previous BSSID=%pM\n", sme->prev_bssid); | ||
| 931 | wil_info(wil, " Auth Type: %s\n", | ||
| 932 | wil_get_auth_type_name(sme->auth_type)); | ||
| 884 | wil_info(wil, " Privacy: %s\n", sme->privacy ? "secure" : "open"); | 933 | wil_info(wil, " Privacy: %s\n", sme->privacy ? "secure" : "open"); |
| 885 | wil_info(wil, " PBSS: %d\n", sme->pbss); | 934 | wil_info(wil, " PBSS: %d\n", sme->pbss); |
| 886 | wil_print_crypto(wil, &sme->crypto); | 935 | wil_print_crypto(wil, &sme->crypto); |
| 887 | } | 936 | } |
| 888 | 937 | ||
| 938 | static int wil_ft_connect(struct wiphy *wiphy, | ||
| 939 | struct net_device *ndev, | ||
| 940 | struct cfg80211_connect_params *sme) | ||
| 941 | { | ||
| 942 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | ||
| 943 | struct wil6210_vif *vif = ndev_to_vif(ndev); | ||
| 944 | struct wmi_ft_auth_cmd auth_cmd; | ||
| 945 | int rc; | ||
| 946 | |||
| 947 | if (!test_bit(WMI_FW_CAPABILITY_FT_ROAMING, wil->fw_capabilities)) { | ||
| 948 | wil_err(wil, "FT: FW does not support FT roaming\n"); | ||
| 949 | return -EOPNOTSUPP; | ||
| 950 | } | ||
| 951 | |||
| 952 | if (!sme->prev_bssid) { | ||
| 953 | wil_err(wil, "FT: prev_bssid was not set\n"); | ||
| 954 | return -EINVAL; | ||
| 955 | } | ||
| 956 | |||
| 957 | if (ether_addr_equal(sme->prev_bssid, sme->bssid)) { | ||
| 958 | wil_err(wil, "FT: can not roam to same AP\n"); | ||
| 959 | return -EINVAL; | ||
| 960 | } | ||
| 961 | |||
| 962 | if (!test_bit(wil_vif_fwconnected, vif->status)) { | ||
| 963 | wil_err(wil, "FT: roam while not connected\n"); | ||
| 964 | return -EINVAL; | ||
| 965 | } | ||
| 966 | |||
| 967 | if (vif->privacy != sme->privacy) { | ||
| 968 | wil_err(wil, "FT: privacy mismatch, current (%d) roam (%d)\n", | ||
| 969 | vif->privacy, sme->privacy); | ||
| 970 | return -EINVAL; | ||
| 971 | } | ||
| 972 | |||
| 973 | if (sme->pbss) { | ||
| 974 | wil_err(wil, "FT: roam is not valid for PBSS\n"); | ||
| 975 | return -EINVAL; | ||
| 976 | } | ||
| 977 | |||
| 978 | memset(&auth_cmd, 0, sizeof(auth_cmd)); | ||
| 979 | auth_cmd.channel = sme->channel->hw_value - 1; | ||
| 980 | ether_addr_copy(auth_cmd.bssid, sme->bssid); | ||
| 981 | |||
| 982 | wil_info(wil, "FT: roaming\n"); | ||
| 983 | |||
| 984 | set_bit(wil_vif_ft_roam, vif->status); | ||
| 985 | rc = wmi_send(wil, WMI_FT_AUTH_CMDID, vif->mid, | ||
| 986 | &auth_cmd, sizeof(auth_cmd)); | ||
| 987 | if (rc == 0) | ||
| 988 | mod_timer(&vif->connect_timer, | ||
| 989 | jiffies + msecs_to_jiffies(5000)); | ||
| 990 | else | ||
| 991 | clear_bit(wil_vif_ft_roam, vif->status); | ||
| 992 | |||
| 993 | return rc; | ||
| 994 | } | ||
| 995 | |||
| 889 | static int wil_cfg80211_connect(struct wiphy *wiphy, | 996 | static int wil_cfg80211_connect(struct wiphy *wiphy, |
| 890 | struct net_device *ndev, | 997 | struct net_device *ndev, |
| 891 | struct cfg80211_connect_params *sme) | 998 | struct cfg80211_connect_params *sme) |
| @@ -898,14 +1005,23 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, | |||
| 898 | const u8 *rsn_eid; | 1005 | const u8 *rsn_eid; |
| 899 | int ch; | 1006 | int ch; |
| 900 | int rc = 0; | 1007 | int rc = 0; |
| 1008 | bool is_ft_roam = false; | ||
| 1009 | u8 network_type; | ||
| 901 | enum ieee80211_bss_type bss_type = IEEE80211_BSS_TYPE_ESS; | 1010 | enum ieee80211_bss_type bss_type = IEEE80211_BSS_TYPE_ESS; |
| 902 | 1011 | ||
| 903 | wil_dbg_misc(wil, "connect, mid=%d\n", vif->mid); | 1012 | wil_dbg_misc(wil, "connect, mid=%d\n", vif->mid); |
| 904 | wil_print_connect_params(wil, sme); | 1013 | wil_print_connect_params(wil, sme); |
| 905 | 1014 | ||
| 906 | if (test_bit(wil_vif_fwconnecting, vif->status) || | 1015 | if (sme->auth_type == NL80211_AUTHTYPE_FT) |
| 1016 | is_ft_roam = true; | ||
| 1017 | if (sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC && | ||
| 907 | test_bit(wil_vif_fwconnected, vif->status)) | 1018 | test_bit(wil_vif_fwconnected, vif->status)) |
| 908 | return -EALREADY; | 1019 | is_ft_roam = true; |
| 1020 | |||
| 1021 | if (!is_ft_roam) | ||
| 1022 | if (test_bit(wil_vif_fwconnecting, vif->status) || | ||
| 1023 | test_bit(wil_vif_fwconnected, vif->status)) | ||
| 1024 | return -EALREADY; | ||
| 909 | 1025 | ||
| 910 | if (sme->ie_len > WMI_MAX_IE_LEN) { | 1026 | if (sme->ie_len > WMI_MAX_IE_LEN) { |
| 911 | wil_err(wil, "IE too large (%td bytes)\n", sme->ie_len); | 1027 | wil_err(wil, "IE too large (%td bytes)\n", sme->ie_len); |
| @@ -915,8 +1031,13 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, | |||
| 915 | rsn_eid = sme->ie ? | 1031 | rsn_eid = sme->ie ? |
| 916 | cfg80211_find_ie(WLAN_EID_RSN, sme->ie, sme->ie_len) : | 1032 | cfg80211_find_ie(WLAN_EID_RSN, sme->ie, sme->ie_len) : |
| 917 | NULL; | 1033 | NULL; |
| 918 | if (sme->privacy && !rsn_eid) | 1034 | if (sme->privacy && !rsn_eid) { |
| 919 | wil_info(wil, "WSC connection\n"); | 1035 | wil_info(wil, "WSC connection\n"); |
| 1036 | if (is_ft_roam) { | ||
| 1037 | wil_err(wil, "No WSC with FT roam\n"); | ||
| 1038 | return -EINVAL; | ||
| 1039 | } | ||
| 1040 | } | ||
| 920 | 1041 | ||
| 921 | if (sme->pbss) | 1042 | if (sme->pbss) |
| 922 | bss_type = IEEE80211_BSS_TYPE_PBSS; | 1043 | bss_type = IEEE80211_BSS_TYPE_PBSS; |
| @@ -938,6 +1059,45 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, | |||
| 938 | vif->privacy = sme->privacy; | 1059 | vif->privacy = sme->privacy; |
| 939 | vif->pbss = sme->pbss; | 1060 | vif->pbss = sme->pbss; |
| 940 | 1061 | ||
| 1062 | rc = wmi_set_ie(vif, WMI_FRAME_ASSOC_REQ, sme->ie_len, sme->ie); | ||
| 1063 | if (rc) | ||
| 1064 | goto out; | ||
| 1065 | |||
| 1066 | switch (bss->capability & WLAN_CAPABILITY_DMG_TYPE_MASK) { | ||
| 1067 | case WLAN_CAPABILITY_DMG_TYPE_AP: | ||
| 1068 | network_type = WMI_NETTYPE_INFRA; | ||
| 1069 | break; | ||
| 1070 | case WLAN_CAPABILITY_DMG_TYPE_PBSS: | ||
| 1071 | network_type = WMI_NETTYPE_P2P; | ||
| 1072 | break; | ||
| 1073 | default: | ||
| 1074 | wil_err(wil, "Unsupported BSS type, capability= 0x%04x\n", | ||
| 1075 | bss->capability); | ||
| 1076 | rc = -EINVAL; | ||
| 1077 | goto out; | ||
| 1078 | } | ||
| 1079 | |||
| 1080 | ch = bss->channel->hw_value; | ||
| 1081 | if (ch == 0) { | ||
| 1082 | wil_err(wil, "BSS at unknown frequency %dMhz\n", | ||
| 1083 | bss->channel->center_freq); | ||
| 1084 | rc = -EOPNOTSUPP; | ||
| 1085 | goto out; | ||
| 1086 | } | ||
| 1087 | |||
| 1088 | if (is_ft_roam) { | ||
| 1089 | if (network_type != WMI_NETTYPE_INFRA) { | ||
| 1090 | wil_err(wil, "FT: Unsupported BSS type, capability= 0x%04x\n", | ||
| 1091 | bss->capability); | ||
| 1092 | rc = -EINVAL; | ||
| 1093 | goto out; | ||
| 1094 | } | ||
| 1095 | rc = wil_ft_connect(wiphy, ndev, sme); | ||
| 1096 | if (rc == 0) | ||
| 1097 | vif->bss = bss; | ||
| 1098 | goto out; | ||
| 1099 | } | ||
| 1100 | |||
| 941 | if (vif->privacy) { | 1101 | if (vif->privacy) { |
| 942 | /* For secure assoc, remove old keys */ | 1102 | /* For secure assoc, remove old keys */ |
| 943 | rc = wmi_del_cipher_key(vif, 0, bss->bssid, | 1103 | rc = wmi_del_cipher_key(vif, 0, bss->bssid, |
| @@ -954,28 +1114,9 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, | |||
| 954 | } | 1114 | } |
| 955 | } | 1115 | } |
| 956 | 1116 | ||
| 957 | /* WMI_SET_APPIE_CMD. ie may contain rsn info as well as other info | ||
| 958 | * elements. Send it also in case it's empty, to erase previously set | ||
| 959 | * ies in FW. | ||
| 960 | */ | ||
| 961 | rc = wmi_set_ie(vif, WMI_FRAME_ASSOC_REQ, sme->ie_len, sme->ie); | ||
| 962 | if (rc) | ||
| 963 | goto out; | ||
| 964 | |||
| 965 | /* WMI_CONNECT_CMD */ | 1117 | /* WMI_CONNECT_CMD */ |
| 966 | memset(&conn, 0, sizeof(conn)); | 1118 | memset(&conn, 0, sizeof(conn)); |
| 967 | switch (bss->capability & WLAN_CAPABILITY_DMG_TYPE_MASK) { | 1119 | conn.network_type = network_type; |
| 968 | case WLAN_CAPABILITY_DMG_TYPE_AP: | ||
| 969 | conn.network_type = WMI_NETTYPE_INFRA; | ||
| 970 | break; | ||
| 971 | case WLAN_CAPABILITY_DMG_TYPE_PBSS: | ||
| 972 | conn.network_type = WMI_NETTYPE_P2P; | ||
| 973 | break; | ||
| 974 | default: | ||
| 975 | wil_err(wil, "Unsupported BSS type, capability= 0x%04x\n", | ||
| 976 | bss->capability); | ||
| 977 | goto out; | ||
| 978 | } | ||
| 979 | if (vif->privacy) { | 1120 | if (vif->privacy) { |
| 980 | if (rsn_eid) { /* regular secure connection */ | 1121 | if (rsn_eid) { /* regular secure connection */ |
| 981 | conn.dot11_auth_mode = WMI_AUTH11_SHARED; | 1122 | conn.dot11_auth_mode = WMI_AUTH11_SHARED; |
| @@ -995,14 +1136,6 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, | |||
| 995 | 1136 | ||
| 996 | conn.ssid_len = min_t(u8, ssid_eid[1], 32); | 1137 | conn.ssid_len = min_t(u8, ssid_eid[1], 32); |
| 997 | memcpy(conn.ssid, ssid_eid+2, conn.ssid_len); | 1138 | memcpy(conn.ssid, ssid_eid+2, conn.ssid_len); |
| 998 | |||
| 999 | ch = bss->channel->hw_value; | ||
| 1000 | if (ch == 0) { | ||
| 1001 | wil_err(wil, "BSS at unknown frequency %dMhz\n", | ||
| 1002 | bss->channel->center_freq); | ||
| 1003 | rc = -EOPNOTSUPP; | ||
| 1004 | goto out; | ||
| 1005 | } | ||
| 1006 | conn.channel = ch - 1; | 1139 | conn.channel = ch - 1; |
| 1007 | 1140 | ||
| 1008 | ether_addr_copy(conn.bssid, bss->bssid); | 1141 | ether_addr_copy(conn.bssid, bss->bssid); |
| @@ -1081,55 +1214,57 @@ int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
| 1081 | u64 *cookie) | 1214 | u64 *cookie) |
| 1082 | { | 1215 | { |
| 1083 | const u8 *buf = params->buf; | 1216 | const u8 *buf = params->buf; |
| 1084 | size_t len = params->len, total; | 1217 | size_t len = params->len; |
| 1085 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | 1218 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); |
| 1086 | struct wil6210_vif *vif = wdev_to_vif(wil, wdev); | 1219 | struct wil6210_vif *vif = wdev_to_vif(wil, wdev); |
| 1087 | int rc; | 1220 | int rc; |
| 1088 | bool tx_status = false; | 1221 | bool tx_status; |
| 1089 | struct ieee80211_mgmt *mgmt_frame = (void *)buf; | ||
| 1090 | struct wmi_sw_tx_req_cmd *cmd; | ||
| 1091 | struct { | ||
| 1092 | struct wmi_cmd_hdr wmi; | ||
| 1093 | struct wmi_sw_tx_complete_event evt; | ||
| 1094 | } __packed evt; | ||
| 1095 | |||
| 1096 | /* Note, currently we do not support the "wait" parameter, user-space | ||
| 1097 | * must call remain_on_channel before mgmt_tx or listen on a channel | ||
| 1098 | * another way (AP/PCP or connected station) | ||
| 1099 | * in addition we need to check if specified "chan" argument is | ||
| 1100 | * different from currently "listened" channel and fail if it is. | ||
| 1101 | */ | ||
| 1102 | 1222 | ||
| 1103 | wil_dbg_misc(wil, "mgmt_tx mid %d\n", vif->mid); | 1223 | wil_dbg_misc(wil, "mgmt_tx: channel %d offchan %d, wait %d\n", |
| 1104 | wil_hex_dump_misc("mgmt tx frame ", DUMP_PREFIX_OFFSET, 16, 1, buf, | 1224 | params->chan ? params->chan->hw_value : -1, |
| 1105 | len, true); | 1225 | params->offchan, |
| 1226 | params->wait); | ||
| 1106 | 1227 | ||
| 1107 | if (len < sizeof(struct ieee80211_hdr_3addr)) | 1228 | /* Note, currently we support the "wait" parameter only on AP mode. |
| 1108 | return -EINVAL; | 1229 | * In other modes, user-space must call remain_on_channel before |
| 1230 | * mgmt_tx or listen on a channel other than active one. | ||
| 1231 | */ | ||
| 1109 | 1232 | ||
| 1110 | total = sizeof(*cmd) + len; | 1233 | if (params->chan && params->chan->hw_value == 0) { |
| 1111 | if (total < len) | 1234 | wil_err(wil, "invalid channel\n"); |
| 1112 | return -EINVAL; | 1235 | return -EINVAL; |
| 1236 | } | ||
| 1113 | 1237 | ||
| 1114 | cmd = kmalloc(total, GFP_KERNEL); | 1238 | if (wdev->iftype != NL80211_IFTYPE_AP) { |
| 1115 | if (!cmd) { | 1239 | wil_dbg_misc(wil, |
| 1116 | rc = -ENOMEM; | 1240 | "send WMI_SW_TX_REQ_CMDID on non-AP interfaces\n"); |
| 1241 | rc = wmi_mgmt_tx(vif, buf, len); | ||
| 1117 | goto out; | 1242 | goto out; |
| 1118 | } | 1243 | } |
| 1119 | 1244 | ||
| 1120 | memcpy(cmd->dst_mac, mgmt_frame->da, WMI_MAC_LEN); | 1245 | if (!params->chan || params->chan->hw_value == vif->channel) { |
| 1121 | cmd->len = cpu_to_le16(len); | 1246 | wil_dbg_misc(wil, |
| 1122 | memcpy(cmd->payload, buf, len); | 1247 | "send WMI_SW_TX_REQ_CMDID for on-channel\n"); |
| 1248 | rc = wmi_mgmt_tx(vif, buf, len); | ||
| 1249 | goto out; | ||
| 1250 | } | ||
| 1123 | 1251 | ||
| 1124 | rc = wmi_call(wil, WMI_SW_TX_REQ_CMDID, vif->mid, cmd, total, | 1252 | if (params->offchan == 0) { |
| 1125 | WMI_SW_TX_COMPLETE_EVENTID, &evt, sizeof(evt), 2000); | 1253 | wil_err(wil, |
| 1126 | if (rc == 0) | 1254 | "invalid channel params: current %d requested %d, off-channel not allowed\n", |
| 1127 | tx_status = !evt.evt.status; | 1255 | vif->channel, params->chan->hw_value); |
| 1256 | return -EBUSY; | ||
| 1257 | } | ||
| 1128 | 1258 | ||
| 1129 | kfree(cmd); | 1259 | /* use the wmi_mgmt_tx_ext only on AP mode and off-channel */ |
| 1130 | out: | 1260 | rc = wmi_mgmt_tx_ext(vif, buf, len, params->chan->hw_value, |
| 1261 | params->wait); | ||
| 1262 | |||
| 1263 | out: | ||
| 1264 | tx_status = (rc == 0); | ||
| 1131 | cfg80211_mgmt_tx_status(wdev, cookie ? *cookie : 0, buf, len, | 1265 | cfg80211_mgmt_tx_status(wdev, cookie ? *cookie : 0, buf, len, |
| 1132 | tx_status, GFP_KERNEL); | 1266 | tx_status, GFP_KERNEL); |
| 1267 | |||
| 1133 | return rc; | 1268 | return rc; |
| 1134 | } | 1269 | } |
| 1135 | 1270 | ||
| @@ -1196,9 +1331,9 @@ wil_find_sta_by_key_usage(struct wil6210_priv *wil, u8 mid, | |||
| 1196 | return &wil->sta[cid]; | 1331 | return &wil->sta[cid]; |
| 1197 | } | 1332 | } |
| 1198 | 1333 | ||
| 1199 | static void wil_set_crypto_rx(u8 key_index, enum wmi_key_usage key_usage, | 1334 | void wil_set_crypto_rx(u8 key_index, enum wmi_key_usage key_usage, |
| 1200 | struct wil_sta_info *cs, | 1335 | struct wil_sta_info *cs, |
| 1201 | struct key_params *params) | 1336 | struct key_params *params) |
| 1202 | { | 1337 | { |
| 1203 | struct wil_tid_crypto_rx_single *cc; | 1338 | struct wil_tid_crypto_rx_single *cc; |
| 1204 | int tid; | 1339 | int tid; |
| @@ -1281,13 +1416,19 @@ static int wil_cfg80211_add_key(struct wiphy *wiphy, | |||
| 1281 | params->seq_len, params->seq); | 1416 | params->seq_len, params->seq); |
| 1282 | 1417 | ||
| 1283 | if (IS_ERR(cs)) { | 1418 | if (IS_ERR(cs)) { |
| 1284 | wil_err(wil, "Not connected, %pM %s[%d] PN %*phN\n", | 1419 | /* in FT, sta info may not be available as add_key may be |
| 1285 | mac_addr, key_usage_str[key_usage], key_index, | 1420 | * sent by host before FW sends WMI_CONNECT_EVENT |
| 1286 | params->seq_len, params->seq); | 1421 | */ |
| 1287 | return -EINVAL; | 1422 | if (!test_bit(wil_vif_ft_roam, vif->status)) { |
| 1423 | wil_err(wil, "Not connected, %pM %s[%d] PN %*phN\n", | ||
| 1424 | mac_addr, key_usage_str[key_usage], key_index, | ||
| 1425 | params->seq_len, params->seq); | ||
| 1426 | return -EINVAL; | ||
| 1427 | } | ||
| 1288 | } | 1428 | } |
| 1289 | 1429 | ||
| 1290 | wil_del_rx_key(key_index, key_usage, cs); | 1430 | if (!IS_ERR(cs)) |
| 1431 | wil_del_rx_key(key_index, key_usage, cs); | ||
| 1291 | 1432 | ||
| 1292 | if (params->seq && params->seq_len != IEEE80211_GCMP_PN_LEN) { | 1433 | if (params->seq && params->seq_len != IEEE80211_GCMP_PN_LEN) { |
| 1293 | wil_err(wil, | 1434 | wil_err(wil, |
| @@ -1300,7 +1441,10 @@ static int wil_cfg80211_add_key(struct wiphy *wiphy, | |||
| 1300 | 1441 | ||
| 1301 | rc = wmi_add_cipher_key(vif, key_index, mac_addr, params->key_len, | 1442 | rc = wmi_add_cipher_key(vif, key_index, mac_addr, params->key_len, |
| 1302 | params->key, key_usage); | 1443 | params->key, key_usage); |
| 1303 | if (!rc) | 1444 | if (!rc && !IS_ERR(cs)) |
| 1445 | /* in FT set crypto will take place upon receiving | ||
| 1446 | * WMI_RING_EN_EVENTID event | ||
| 1447 | */ | ||
| 1304 | wil_set_crypto_rx(key_index, key_usage, cs, params); | 1448 | wil_set_crypto_rx(key_index, key_usage, cs, params); |
| 1305 | 1449 | ||
| 1306 | return rc; | 1450 | return rc; |
| @@ -1463,21 +1607,36 @@ static void wil_print_bcon_data(struct cfg80211_beacon_data *b) | |||
| 1463 | } | 1607 | } |
| 1464 | 1608 | ||
| 1465 | /* internal functions for device reset and starting AP */ | 1609 | /* internal functions for device reset and starting AP */ |
| 1466 | static int _wil_cfg80211_set_ies(struct wil6210_vif *vif, | 1610 | static u8 * |
| 1467 | struct cfg80211_beacon_data *bcon) | 1611 | _wil_cfg80211_get_proberesp_ies(const u8 *proberesp, u16 proberesp_len, |
| 1612 | u16 *ies_len) | ||
| 1468 | { | 1613 | { |
| 1469 | int rc; | 1614 | u8 *ies = NULL; |
| 1470 | u16 len = 0, proberesp_len = 0; | ||
| 1471 | u8 *ies = NULL, *proberesp = NULL; | ||
| 1472 | 1615 | ||
| 1473 | if (bcon->probe_resp) { | 1616 | if (proberesp) { |
| 1474 | struct ieee80211_mgmt *f = | 1617 | struct ieee80211_mgmt *f = |
| 1475 | (struct ieee80211_mgmt *)bcon->probe_resp; | 1618 | (struct ieee80211_mgmt *)proberesp; |
| 1476 | size_t hlen = offsetof(struct ieee80211_mgmt, | 1619 | size_t hlen = offsetof(struct ieee80211_mgmt, |
| 1477 | u.probe_resp.variable); | 1620 | u.probe_resp.variable); |
| 1478 | proberesp = f->u.probe_resp.variable; | 1621 | |
| 1479 | proberesp_len = bcon->probe_resp_len - hlen; | 1622 | ies = f->u.probe_resp.variable; |
| 1623 | if (ies_len) | ||
| 1624 | *ies_len = proberesp_len - hlen; | ||
| 1480 | } | 1625 | } |
| 1626 | |||
| 1627 | return ies; | ||
| 1628 | } | ||
| 1629 | |||
| 1630 | static int _wil_cfg80211_set_ies(struct wil6210_vif *vif, | ||
| 1631 | struct cfg80211_beacon_data *bcon) | ||
| 1632 | { | ||
| 1633 | int rc; | ||
| 1634 | u16 len = 0, proberesp_len = 0; | ||
| 1635 | u8 *ies = NULL, *proberesp; | ||
| 1636 | |||
| 1637 | proberesp = _wil_cfg80211_get_proberesp_ies(bcon->probe_resp, | ||
| 1638 | bcon->probe_resp_len, | ||
| 1639 | &proberesp_len); | ||
| 1481 | rc = _wil_cfg80211_merge_extra_ies(proberesp, | 1640 | rc = _wil_cfg80211_merge_extra_ies(proberesp, |
| 1482 | proberesp_len, | 1641 | proberesp_len, |
| 1483 | bcon->proberesp_ies, | 1642 | bcon->proberesp_ies, |
| @@ -1521,6 +1680,9 @@ static int _wil_cfg80211_start_ap(struct wiphy *wiphy, | |||
| 1521 | struct wireless_dev *wdev = ndev->ieee80211_ptr; | 1680 | struct wireless_dev *wdev = ndev->ieee80211_ptr; |
| 1522 | u8 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype); | 1681 | u8 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype); |
| 1523 | u8 is_go = (wdev->iftype == NL80211_IFTYPE_P2P_GO); | 1682 | u8 is_go = (wdev->iftype == NL80211_IFTYPE_P2P_GO); |
| 1683 | u16 proberesp_len = 0; | ||
| 1684 | u8 *proberesp; | ||
| 1685 | bool ft = false; | ||
| 1524 | 1686 | ||
| 1525 | if (pbss) | 1687 | if (pbss) |
| 1526 | wmi_nettype = WMI_NETTYPE_P2P; | 1688 | wmi_nettype = WMI_NETTYPE_P2P; |
| @@ -1533,6 +1695,25 @@ static int _wil_cfg80211_start_ap(struct wiphy *wiphy, | |||
| 1533 | 1695 | ||
| 1534 | wil_set_recovery_state(wil, fw_recovery_idle); | 1696 | wil_set_recovery_state(wil, fw_recovery_idle); |
| 1535 | 1697 | ||
| 1698 | proberesp = _wil_cfg80211_get_proberesp_ies(bcon->probe_resp, | ||
| 1699 | bcon->probe_resp_len, | ||
| 1700 | &proberesp_len); | ||
| 1701 | /* check that the probe response IEs has a MDE */ | ||
| 1702 | if ((proberesp && proberesp_len > 0 && | ||
| 1703 | cfg80211_find_ie(WLAN_EID_MOBILITY_DOMAIN, | ||
| 1704 | proberesp, | ||
| 1705 | proberesp_len))) | ||
| 1706 | ft = true; | ||
| 1707 | |||
| 1708 | if (ft) { | ||
| 1709 | if (!test_bit(WMI_FW_CAPABILITY_FT_ROAMING, | ||
| 1710 | wil->fw_capabilities)) { | ||
| 1711 | wil_err(wil, "FW does not support FT roaming\n"); | ||
| 1712 | return -ENOTSUPP; | ||
| 1713 | } | ||
| 1714 | set_bit(wil_vif_ft_roam, vif->status); | ||
| 1715 | } | ||
| 1716 | |||
| 1536 | mutex_lock(&wil->mutex); | 1717 | mutex_lock(&wil->mutex); |
| 1537 | 1718 | ||
| 1538 | if (!wil_has_other_active_ifaces(wil, ndev, true, false)) { | 1719 | if (!wil_has_other_active_ifaces(wil, ndev, true, false)) { |
| @@ -1694,6 +1875,7 @@ static int wil_cfg80211_stop_ap(struct wiphy *wiphy, | |||
| 1694 | mutex_lock(&wil->mutex); | 1875 | mutex_lock(&wil->mutex); |
| 1695 | 1876 | ||
| 1696 | wmi_pcp_stop(vif); | 1877 | wmi_pcp_stop(vif); |
| 1878 | clear_bit(wil_vif_ft_roam, vif->status); | ||
| 1697 | 1879 | ||
| 1698 | if (last) | 1880 | if (last) |
| 1699 | __wil_down(wil); | 1881 | __wil_down(wil); |
| @@ -1713,8 +1895,9 @@ static int wil_cfg80211_add_station(struct wiphy *wiphy, | |||
| 1713 | struct wil6210_vif *vif = ndev_to_vif(dev); | 1895 | struct wil6210_vif *vif = ndev_to_vif(dev); |
| 1714 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | 1896 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); |
| 1715 | 1897 | ||
| 1716 | wil_dbg_misc(wil, "add station %pM aid %d mid %d\n", | 1898 | wil_dbg_misc(wil, "add station %pM aid %d mid %d mask 0x%x set 0x%x\n", |
| 1717 | mac, params->aid, vif->mid); | 1899 | mac, params->aid, vif->mid, |
| 1900 | params->sta_flags_mask, params->sta_flags_set); | ||
| 1718 | 1901 | ||
| 1719 | if (!disable_ap_sme) { | 1902 | if (!disable_ap_sme) { |
| 1720 | wil_err(wil, "not supported with AP SME enabled\n"); | 1903 | wil_err(wil, "not supported with AP SME enabled\n"); |
| @@ -1755,7 +1938,7 @@ static int wil_cfg80211_change_station(struct wiphy *wiphy, | |||
| 1755 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | 1938 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); |
| 1756 | int authorize; | 1939 | int authorize; |
| 1757 | int cid, i; | 1940 | int cid, i; |
| 1758 | struct vring_tx_data *txdata = NULL; | 1941 | struct wil_ring_tx_data *txdata = NULL; |
| 1759 | 1942 | ||
| 1760 | wil_dbg_misc(wil, "change station %pM mask 0x%x set 0x%x mid %d\n", | 1943 | wil_dbg_misc(wil, "change station %pM mask 0x%x set 0x%x mid %d\n", |
| 1761 | mac, params->sta_flags_mask, params->sta_flags_set, | 1944 | mac, params->sta_flags_mask, params->sta_flags_set, |
| @@ -1775,20 +1958,20 @@ static int wil_cfg80211_change_station(struct wiphy *wiphy, | |||
| 1775 | return -ENOLINK; | 1958 | return -ENOLINK; |
| 1776 | } | 1959 | } |
| 1777 | 1960 | ||
| 1778 | for (i = 0; i < ARRAY_SIZE(wil->vring2cid_tid); i++) | 1961 | for (i = 0; i < ARRAY_SIZE(wil->ring2cid_tid); i++) |
| 1779 | if (wil->vring2cid_tid[i][0] == cid) { | 1962 | if (wil->ring2cid_tid[i][0] == cid) { |
| 1780 | txdata = &wil->vring_tx_data[i]; | 1963 | txdata = &wil->ring_tx_data[i]; |
| 1781 | break; | 1964 | break; |
| 1782 | } | 1965 | } |
| 1783 | 1966 | ||
| 1784 | if (!txdata) { | 1967 | if (!txdata) { |
| 1785 | wil_err(wil, "vring data not found\n"); | 1968 | wil_err(wil, "ring data not found\n"); |
| 1786 | return -ENOLINK; | 1969 | return -ENOLINK; |
| 1787 | } | 1970 | } |
| 1788 | 1971 | ||
| 1789 | authorize = params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED); | 1972 | authorize = params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED); |
| 1790 | txdata->dot1x_open = authorize ? 1 : 0; | 1973 | txdata->dot1x_open = authorize ? 1 : 0; |
| 1791 | wil_dbg_misc(wil, "cid %d vring %d authorize %d\n", cid, i, | 1974 | wil_dbg_misc(wil, "cid %d ring %d authorize %d\n", cid, i, |
| 1792 | txdata->dot1x_open); | 1975 | txdata->dot1x_open); |
| 1793 | 1976 | ||
| 1794 | return 0; | 1977 | return 0; |
| @@ -2035,6 +2218,54 @@ wil_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev, | |||
| 2035 | return 0; | 2218 | return 0; |
| 2036 | } | 2219 | } |
| 2037 | 2220 | ||
| 2221 | static int | ||
| 2222 | wil_cfg80211_update_ft_ies(struct wiphy *wiphy, struct net_device *dev, | ||
| 2223 | struct cfg80211_update_ft_ies_params *ftie) | ||
| 2224 | { | ||
| 2225 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | ||
| 2226 | struct wil6210_vif *vif = ndev_to_vif(dev); | ||
| 2227 | struct cfg80211_bss *bss; | ||
| 2228 | struct wmi_ft_reassoc_cmd reassoc; | ||
| 2229 | int rc = 0; | ||
| 2230 | |||
| 2231 | wil_dbg_misc(wil, "update ft ies, mid=%d\n", vif->mid); | ||
| 2232 | wil_hex_dump_misc("FT IE ", DUMP_PREFIX_OFFSET, 16, 1, | ||
| 2233 | ftie->ie, ftie->ie_len, true); | ||
| 2234 | |||
| 2235 | if (!test_bit(WMI_FW_CAPABILITY_FT_ROAMING, wil->fw_capabilities)) { | ||
| 2236 | wil_err(wil, "FW does not support FT roaming\n"); | ||
| 2237 | return -EOPNOTSUPP; | ||
| 2238 | } | ||
| 2239 | |||
| 2240 | rc = wmi_update_ft_ies(vif, ftie->ie_len, ftie->ie); | ||
| 2241 | if (rc) | ||
| 2242 | return rc; | ||
| 2243 | |||
| 2244 | if (!test_bit(wil_vif_ft_roam, vif->status)) | ||
| 2245 | /* vif is not roaming */ | ||
| 2246 | return 0; | ||
| 2247 | |||
| 2248 | /* wil_vif_ft_roam is set. wil_cfg80211_update_ft_ies is used as | ||
| 2249 | * a trigger for reassoc | ||
| 2250 | */ | ||
| 2251 | |||
| 2252 | bss = vif->bss; | ||
| 2253 | if (!bss) { | ||
| 2254 | wil_err(wil, "FT: bss is NULL\n"); | ||
| 2255 | return -EINVAL; | ||
| 2256 | } | ||
| 2257 | |||
| 2258 | memset(&reassoc, 0, sizeof(reassoc)); | ||
| 2259 | ether_addr_copy(reassoc.bssid, bss->bssid); | ||
| 2260 | |||
| 2261 | rc = wmi_send(wil, WMI_FT_REASSOC_CMDID, vif->mid, | ||
| 2262 | &reassoc, sizeof(reassoc)); | ||
| 2263 | if (rc) | ||
| 2264 | wil_err(wil, "FT: reassoc failed (%d)\n", rc); | ||
| 2265 | |||
| 2266 | return rc; | ||
| 2267 | } | ||
| 2268 | |||
| 2038 | static const struct cfg80211_ops wil_cfg80211_ops = { | 2269 | static const struct cfg80211_ops wil_cfg80211_ops = { |
| 2039 | .add_virtual_intf = wil_cfg80211_add_iface, | 2270 | .add_virtual_intf = wil_cfg80211_add_iface, |
| 2040 | .del_virtual_intf = wil_cfg80211_del_iface, | 2271 | .del_virtual_intf = wil_cfg80211_del_iface, |
| @@ -2070,6 +2301,7 @@ static const struct cfg80211_ops wil_cfg80211_ops = { | |||
| 2070 | .resume = wil_cfg80211_resume, | 2301 | .resume = wil_cfg80211_resume, |
| 2071 | .sched_scan_start = wil_cfg80211_sched_scan_start, | 2302 | .sched_scan_start = wil_cfg80211_sched_scan_start, |
| 2072 | .sched_scan_stop = wil_cfg80211_sched_scan_stop, | 2303 | .sched_scan_stop = wil_cfg80211_sched_scan_stop, |
| 2304 | .update_ft_ies = wil_cfg80211_update_ft_ies, | ||
| 2073 | }; | 2305 | }; |
| 2074 | 2306 | ||
| 2075 | static void wil_wiphy_init(struct wiphy *wiphy) | 2307 | static void wil_wiphy_init(struct wiphy *wiphy) |
| @@ -2277,7 +2509,9 @@ static int wil_rf_sector_get_cfg(struct wiphy *wiphy, | |||
| 2277 | struct { | 2509 | struct { |
| 2278 | struct wmi_cmd_hdr wmi; | 2510 | struct wmi_cmd_hdr wmi; |
| 2279 | struct wmi_get_rf_sector_params_done_event evt; | 2511 | struct wmi_get_rf_sector_params_done_event evt; |
| 2280 | } __packed reply; | 2512 | } __packed reply = { |
| 2513 | .evt = {.status = WMI_RF_SECTOR_STATUS_NOT_SUPPORTED_ERROR}, | ||
| 2514 | }; | ||
| 2281 | struct sk_buff *msg; | 2515 | struct sk_buff *msg; |
| 2282 | struct nlattr *nl_cfgs, *nl_cfg; | 2516 | struct nlattr *nl_cfgs, *nl_cfg; |
| 2283 | u32 i; | 2517 | u32 i; |
| @@ -2323,7 +2557,6 @@ static int wil_rf_sector_get_cfg(struct wiphy *wiphy, | |||
| 2323 | cmd.sector_idx = cpu_to_le16(sector_index); | 2557 | cmd.sector_idx = cpu_to_le16(sector_index); |
| 2324 | cmd.sector_type = sector_type; | 2558 | cmd.sector_type = sector_type; |
| 2325 | cmd.rf_modules_vec = rf_modules_vec & 0xFF; | 2559 | cmd.rf_modules_vec = rf_modules_vec & 0xFF; |
| 2326 | memset(&reply, 0, sizeof(reply)); | ||
| 2327 | rc = wmi_call(wil, WMI_GET_RF_SECTOR_PARAMS_CMDID, vif->mid, | 2560 | rc = wmi_call(wil, WMI_GET_RF_SECTOR_PARAMS_CMDID, vif->mid, |
| 2328 | &cmd, sizeof(cmd), WMI_GET_RF_SECTOR_PARAMS_DONE_EVENTID, | 2561 | &cmd, sizeof(cmd), WMI_GET_RF_SECTOR_PARAMS_DONE_EVENTID, |
| 2329 | &reply, sizeof(reply), | 2562 | &reply, sizeof(reply), |
| @@ -2398,7 +2631,9 @@ static int wil_rf_sector_set_cfg(struct wiphy *wiphy, | |||
| 2398 | struct { | 2631 | struct { |
| 2399 | struct wmi_cmd_hdr wmi; | 2632 | struct wmi_cmd_hdr wmi; |
| 2400 | struct wmi_set_rf_sector_params_done_event evt; | 2633 | struct wmi_set_rf_sector_params_done_event evt; |
| 2401 | } __packed reply; | 2634 | } __packed reply = { |
| 2635 | .evt = {.status = WMI_RF_SECTOR_STATUS_NOT_SUPPORTED_ERROR}, | ||
| 2636 | }; | ||
| 2402 | struct nlattr *nl_cfg; | 2637 | struct nlattr *nl_cfg; |
| 2403 | struct wmi_rf_sector_info *si; | 2638 | struct wmi_rf_sector_info *si; |
| 2404 | 2639 | ||
| @@ -2481,7 +2716,6 @@ static int wil_rf_sector_set_cfg(struct wiphy *wiphy, | |||
| 2481 | } | 2716 | } |
| 2482 | 2717 | ||
| 2483 | cmd.rf_modules_vec = rf_modules_vec & 0xFF; | 2718 | cmd.rf_modules_vec = rf_modules_vec & 0xFF; |
| 2484 | memset(&reply, 0, sizeof(reply)); | ||
| 2485 | rc = wmi_call(wil, WMI_SET_RF_SECTOR_PARAMS_CMDID, vif->mid, | 2719 | rc = wmi_call(wil, WMI_SET_RF_SECTOR_PARAMS_CMDID, vif->mid, |
| 2486 | &cmd, sizeof(cmd), WMI_SET_RF_SECTOR_PARAMS_DONE_EVENTID, | 2720 | &cmd, sizeof(cmd), WMI_SET_RF_SECTOR_PARAMS_DONE_EVENTID, |
| 2487 | &reply, sizeof(reply), | 2721 | &reply, sizeof(reply), |
| @@ -2505,7 +2739,9 @@ static int wil_rf_sector_get_selected(struct wiphy *wiphy, | |||
| 2505 | struct { | 2739 | struct { |
| 2506 | struct wmi_cmd_hdr wmi; | 2740 | struct wmi_cmd_hdr wmi; |
| 2507 | struct wmi_get_selected_rf_sector_index_done_event evt; | 2741 | struct wmi_get_selected_rf_sector_index_done_event evt; |
| 2508 | } __packed reply; | 2742 | } __packed reply = { |
| 2743 | .evt = {.status = WMI_RF_SECTOR_STATUS_NOT_SUPPORTED_ERROR}, | ||
| 2744 | }; | ||
| 2509 | struct sk_buff *msg; | 2745 | struct sk_buff *msg; |
| 2510 | 2746 | ||
| 2511 | if (!test_bit(WMI_FW_CAPABILITY_RF_SECTORS, wil->fw_capabilities)) | 2747 | if (!test_bit(WMI_FW_CAPABILITY_RF_SECTORS, wil->fw_capabilities)) |
| @@ -2545,7 +2781,6 @@ static int wil_rf_sector_get_selected(struct wiphy *wiphy, | |||
| 2545 | memset(&cmd, 0, sizeof(cmd)); | 2781 | memset(&cmd, 0, sizeof(cmd)); |
| 2546 | cmd.cid = (u8)cid; | 2782 | cmd.cid = (u8)cid; |
| 2547 | cmd.sector_type = sector_type; | 2783 | cmd.sector_type = sector_type; |
| 2548 | memset(&reply, 0, sizeof(reply)); | ||
| 2549 | rc = wmi_call(wil, WMI_GET_SELECTED_RF_SECTOR_INDEX_CMDID, vif->mid, | 2784 | rc = wmi_call(wil, WMI_GET_SELECTED_RF_SECTOR_INDEX_CMDID, vif->mid, |
| 2550 | &cmd, sizeof(cmd), | 2785 | &cmd, sizeof(cmd), |
| 2551 | WMI_GET_SELECTED_RF_SECTOR_INDEX_DONE_EVENTID, | 2786 | WMI_GET_SELECTED_RF_SECTOR_INDEX_DONE_EVENTID, |
| @@ -2586,14 +2821,15 @@ static int wil_rf_sector_wmi_set_selected(struct wil6210_priv *wil, | |||
| 2586 | struct { | 2821 | struct { |
| 2587 | struct wmi_cmd_hdr wmi; | 2822 | struct wmi_cmd_hdr wmi; |
| 2588 | struct wmi_set_selected_rf_sector_index_done_event evt; | 2823 | struct wmi_set_selected_rf_sector_index_done_event evt; |
| 2589 | } __packed reply; | 2824 | } __packed reply = { |
| 2825 | .evt = {.status = WMI_RF_SECTOR_STATUS_NOT_SUPPORTED_ERROR}, | ||
| 2826 | }; | ||
| 2590 | int rc; | 2827 | int rc; |
| 2591 | 2828 | ||
| 2592 | memset(&cmd, 0, sizeof(cmd)); | 2829 | memset(&cmd, 0, sizeof(cmd)); |
| 2593 | cmd.sector_idx = cpu_to_le16(sector_index); | 2830 | cmd.sector_idx = cpu_to_le16(sector_index); |
| 2594 | cmd.sector_type = sector_type; | 2831 | cmd.sector_type = sector_type; |
| 2595 | cmd.cid = (u8)cid; | 2832 | cmd.cid = (u8)cid; |
| 2596 | memset(&reply, 0, sizeof(reply)); | ||
| 2597 | rc = wmi_call(wil, WMI_SET_SELECTED_RF_SECTOR_INDEX_CMDID, mid, | 2833 | rc = wmi_call(wil, WMI_SET_SELECTED_RF_SECTOR_INDEX_CMDID, mid, |
| 2598 | &cmd, sizeof(cmd), | 2834 | &cmd, sizeof(cmd), |
| 2599 | WMI_SET_SELECTED_RF_SECTOR_INDEX_DONE_EVENTID, | 2835 | WMI_SET_SELECTED_RF_SECTOR_INDEX_DONE_EVENTID, |
