1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * NXP Wireless LAN device driver: AP specific command handling 4 * 5 * Copyright 2011-2020 NXP 6 */ 7 8 #include "main.h" 9 #include "11ac.h" 10 #include "11n.h" 11 12 /* This function parses security related parameters from cfg80211_ap_settings 13 * and sets into FW understandable bss_config structure. 14 */ 15 int mwifiex_set_secure_params(struct mwifiex_private *priv, 16 struct mwifiex_uap_bss_param *bss_config, 17 struct cfg80211_ap_settings *params) { 18 int i; 19 struct mwifiex_wep_key wep_key; 20 21 if (!params->privacy) { 22 bss_config->protocol = PROTOCOL_NO_SECURITY; 23 bss_config->key_mgmt = KEY_MGMT_NONE; 24 bss_config->wpa_cfg.length = 0; 25 priv->sec_info.wep_enabled = 0; 26 priv->sec_info.wpa_enabled = 0; 27 priv->sec_info.wpa2_enabled = 0; 28 29 return 0; 30 } 31 32 switch (params->auth_type) { 33 case NL80211_AUTHTYPE_OPEN_SYSTEM: 34 bss_config->auth_mode = WLAN_AUTH_OPEN; 35 break; 36 case NL80211_AUTHTYPE_SHARED_KEY: 37 bss_config->auth_mode = WLAN_AUTH_SHARED_KEY; 38 break; 39 case NL80211_AUTHTYPE_NETWORK_EAP: 40 bss_config->auth_mode = WLAN_AUTH_LEAP; 41 break; 42 default: 43 bss_config->auth_mode = MWIFIEX_AUTH_MODE_AUTO; 44 break; 45 } 46 47 bss_config->key_mgmt_operation |= KEY_MGMT_ON_HOST; 48 49 bss_config->protocol = 0; 50 if (params->crypto.wpa_versions & NL80211_WPA_VERSION_1) 51 bss_config->protocol |= PROTOCOL_WPA; 52 if (params->crypto.wpa_versions & NL80211_WPA_VERSION_2) 53 bss_config->protocol |= PROTOCOL_WPA2; 54 55 for (i = 0; i < params->crypto.n_akm_suites; i++) { 56 switch (params->crypto.akm_suites[i]) { 57 case WLAN_AKM_SUITE_8021X: 58 bss_config->key_mgmt = KEY_MGMT_EAP; 59 break; 60 case WLAN_AKM_SUITE_PSK: 61 bss_config->key_mgmt = KEY_MGMT_PSK; 62 break; 63 case WLAN_AKM_SUITE_SAE: 64 bss_config->key_mgmt = KEY_MGMT_SAE; 65 break; 66 default: 67 break; 68 } 69 } 70 for (i = 0; i < params->crypto.n_ciphers_pairwise; i++) { 71 switch (params->crypto.ciphers_pairwise[i]) { 72 case WLAN_CIPHER_SUITE_WEP40: 73 case WLAN_CIPHER_SUITE_WEP104: 74 break; 75 case WLAN_CIPHER_SUITE_TKIP: 76 if (params->crypto.wpa_versions & NL80211_WPA_VERSION_1) 77 bss_config->wpa_cfg.pairwise_cipher_wpa |= 78 CIPHER_TKIP; 79 if (params->crypto.wpa_versions & NL80211_WPA_VERSION_2) 80 bss_config->wpa_cfg.pairwise_cipher_wpa2 |= 81 CIPHER_TKIP; 82 break; 83 case WLAN_CIPHER_SUITE_CCMP: 84 if (params->crypto.wpa_versions & NL80211_WPA_VERSION_1) 85 bss_config->wpa_cfg.pairwise_cipher_wpa |= 86 CIPHER_AES_CCMP; 87 if (params->crypto.wpa_versions & NL80211_WPA_VERSION_2) 88 bss_config->wpa_cfg.pairwise_cipher_wpa2 |= 89 CIPHER_AES_CCMP; 90 break; 91 default: 92 break; 93 } 94 } 95 96 switch (params->crypto.cipher_group) { 97 case WLAN_CIPHER_SUITE_WEP40: 98 case WLAN_CIPHER_SUITE_WEP104: 99 if (priv->sec_info.wep_enabled) { 100 bss_config->protocol = PROTOCOL_STATIC_WEP; 101 bss_config->key_mgmt = KEY_MGMT_NONE; 102 bss_config->wpa_cfg.length = 0; 103 104 for (i = 0; i < NUM_WEP_KEYS; i++) { 105 wep_key = priv->wep_key[i]; 106 bss_config->wep_cfg[i].key_index = i; 107 108 if (priv->wep_key_curr_index == i) 109 bss_config->wep_cfg[i].is_default = 1; 110 else 111 bss_config->wep_cfg[i].is_default = 0; 112 113 bss_config->wep_cfg[i].length = 114 wep_key.key_length; 115 memcpy(&bss_config->wep_cfg[i].key, 116 &wep_key.key_material, 117 wep_key.key_length); 118 } 119 } 120 break; 121 case WLAN_CIPHER_SUITE_TKIP: 122 bss_config->wpa_cfg.group_cipher = CIPHER_TKIP; 123 break; 124 case WLAN_CIPHER_SUITE_CCMP: 125 bss_config->wpa_cfg.group_cipher = CIPHER_AES_CCMP; 126 break; 127 default: 128 break; 129 } 130 131 return 0; 132 } 133 134 /* This function updates 11n related parameters from IE and sets them into 135 * bss_config structure. 136 */ 137 void 138 mwifiex_set_ht_params(struct mwifiex_private *priv, 139 struct mwifiex_uap_bss_param *bss_cfg, 140 struct cfg80211_ap_settings *params) 141 { 142 const u8 *ht_ie; 143 144 if (!ISSUPP_11NENABLED(priv->adapter->fw_cap_info)) 145 return; 146 147 ht_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, params->beacon.tail, 148 params->beacon.tail_len); 149 if (ht_ie) { 150 memcpy(&bss_cfg->ht_cap, ht_ie + 2, 151 sizeof(struct ieee80211_ht_cap)); 152 priv->ap_11n_enabled = 1; 153 } else { 154 memset(&bss_cfg->ht_cap, 0, sizeof(struct ieee80211_ht_cap)); 155 bss_cfg->ht_cap.cap_info = cpu_to_le16(MWIFIEX_DEF_HT_CAP); 156 bss_cfg->ht_cap.ampdu_params_info = MWIFIEX_DEF_AMPDU; 157 } 158 159 return; 160 } 161 162 /* This function updates 11ac related parameters from IE 163 * and sets them into bss_config structure. 164 */ 165 void mwifiex_set_vht_params(struct mwifiex_private *priv, 166 struct mwifiex_uap_bss_param *bss_cfg, 167 struct cfg80211_ap_settings *params) 168 { 169 const u8 *vht_ie; 170 171 vht_ie = cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, params->beacon.tail, 172 params->beacon.tail_len); 173 if (vht_ie) { 174 memcpy(&bss_cfg->vht_cap, vht_ie + 2, 175 sizeof(struct ieee80211_vht_cap)); 176 priv->ap_11ac_enabled = 1; 177 } else { 178 priv->ap_11ac_enabled = 0; 179 } 180 181 return; 182 } 183 184 /* This function updates 11ac related parameters from IE 185 * and sets them into bss_config structure. 186 */ 187 void mwifiex_set_tpc_params(struct mwifiex_private *priv, 188 struct mwifiex_uap_bss_param *bss_cfg, 189 struct cfg80211_ap_settings *params) 190 { 191 const u8 *tpc_ie; 192 193 tpc_ie = cfg80211_find_ie(WLAN_EID_TPC_REQUEST, params->beacon.tail, 194 params->beacon.tail_len); 195 if (tpc_ie) 196 bss_cfg->power_constraint = *(tpc_ie + 2); 197 else 198 bss_cfg->power_constraint = 0; 199 } 200 201 /* Enable VHT only when cfg80211_ap_settings has VHT IE. 202 * Otherwise disable VHT. 203 */ 204 void mwifiex_set_vht_width(struct mwifiex_private *priv, 205 enum nl80211_chan_width width, 206 bool ap_11ac_enable) 207 { 208 struct mwifiex_adapter *adapter = priv->adapter; 209 struct mwifiex_11ac_vht_cfg vht_cfg; 210 211 vht_cfg.band_config = VHT_CFG_5GHZ; 212 vht_cfg.cap_info = adapter->hw_dot_11ac_dev_cap; 213 214 if (!ap_11ac_enable) { 215 vht_cfg.mcs_tx_set = DISABLE_VHT_MCS_SET; 216 vht_cfg.mcs_rx_set = DISABLE_VHT_MCS_SET; 217 } else { 218 vht_cfg.mcs_tx_set = DEFAULT_VHT_MCS_SET; 219 vht_cfg.mcs_rx_set = DEFAULT_VHT_MCS_SET; 220 } 221 222 vht_cfg.misc_config = VHT_CAP_UAP_ONLY; 223 224 if (ap_11ac_enable && width >= NL80211_CHAN_WIDTH_80) 225 vht_cfg.misc_config |= VHT_BW_80_160_80P80; 226 227 mwifiex_send_cmd(priv, HostCmd_CMD_11AC_CFG, 228 HostCmd_ACT_GEN_SET, 0, &vht_cfg, true); 229 230 return; 231 } 232 233 /* This function finds supported rates IE from beacon parameter and sets 234 * these rates into bss_config structure. 235 */ 236 void 237 mwifiex_set_uap_rates(struct mwifiex_uap_bss_param *bss_cfg, 238 struct cfg80211_ap_settings *params) 239 { 240 struct ieee_types_header *rate_ie; 241 int var_offset = offsetof(struct ieee80211_mgmt, u.beacon.variable); 242 const u8 *var_pos = params->beacon.head + var_offset; 243 int len = params->beacon.head_len - var_offset; 244 u8 rate_len = 0; 245 246 rate_ie = (void *)cfg80211_find_ie(WLAN_EID_SUPP_RATES, var_pos, len); 247 if (rate_ie) { 248 if (rate_ie->len > MWIFIEX_SUPPORTED_RATES) 249 return; 250 memcpy(bss_cfg->rates, rate_ie + 1, rate_ie->len); 251 rate_len = rate_ie->len; 252 } 253 254 rate_ie = (void *)cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, 255 params->beacon.tail, 256 params->beacon.tail_len); 257 if (rate_ie) { 258 if (rate_ie->len > MWIFIEX_SUPPORTED_RATES - rate_len) 259 return; 260 memcpy(bss_cfg->rates + rate_len, rate_ie + 1, rate_ie->len); 261 } 262 263 return; 264 } 265 266 /* This function initializes some of mwifiex_uap_bss_param variables. 267 * This helps FW in ignoring invalid values. These values may or may not 268 * be get updated to valid ones at later stage. 269 */ 270 void mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param *config) 271 { 272 config->bcast_ssid_ctl = 0x7F; 273 config->radio_ctl = 0x7F; 274 config->dtim_period = 0x7F; 275 config->beacon_period = 0x7FFF; 276 config->auth_mode = 0x7F; 277 config->rts_threshold = 0x7FFF; 278 config->frag_threshold = 0x7FFF; 279 config->retry_limit = 0x7F; 280 config->qos_info = 0xFF; 281 } 282 283 /* This function parses BSS related parameters from structure 284 * and prepares TLVs specific to WPA/WPA2 security. 285 * These TLVs are appended to command buffer. 286 */ 287 static void 288 mwifiex_uap_bss_wpa(u8 **tlv_buf, void *cmd_buf, u16 *param_size) 289 { 290 struct host_cmd_tlv_pwk_cipher *pwk_cipher; 291 struct host_cmd_tlv_gwk_cipher *gwk_cipher; 292 struct host_cmd_tlv_passphrase *passphrase; 293 struct host_cmd_tlv_akmp *tlv_akmp; 294 struct mwifiex_uap_bss_param *bss_cfg = cmd_buf; 295 u16 cmd_size = *param_size; 296 u8 *tlv = *tlv_buf; 297 298 tlv_akmp = (struct host_cmd_tlv_akmp *)tlv; 299 tlv_akmp->header.type = cpu_to_le16(TLV_TYPE_UAP_AKMP); 300 tlv_akmp->header.len = cpu_to_le16(sizeof(struct host_cmd_tlv_akmp) - 301 sizeof(struct mwifiex_ie_types_header)); 302 tlv_akmp->key_mgmt_operation = cpu_to_le16(bss_cfg->key_mgmt_operation); 303 tlv_akmp->key_mgmt = cpu_to_le16(bss_cfg->key_mgmt); 304 cmd_size += sizeof(struct host_cmd_tlv_akmp); 305 tlv += sizeof(struct host_cmd_tlv_akmp); 306 307 if (bss_cfg->wpa_cfg.pairwise_cipher_wpa & VALID_CIPHER_BITMAP) { 308 pwk_cipher = (struct host_cmd_tlv_pwk_cipher *)tlv; 309 pwk_cipher->header.type = cpu_to_le16(TLV_TYPE_PWK_CIPHER); 310 pwk_cipher->header.len = 311 cpu_to_le16(sizeof(struct host_cmd_tlv_pwk_cipher) - 312 sizeof(struct mwifiex_ie_types_header)); 313 pwk_cipher->proto = cpu_to_le16(PROTOCOL_WPA); 314 pwk_cipher->cipher = bss_cfg->wpa_cfg.pairwise_cipher_wpa; 315 cmd_size += sizeof(struct host_cmd_tlv_pwk_cipher); 316 tlv += sizeof(struct host_cmd_tlv_pwk_cipher); 317 } 318 319 if (bss_cfg->wpa_cfg.pairwise_cipher_wpa2 & VALID_CIPHER_BITMAP) { 320 pwk_cipher = (struct host_cmd_tlv_pwk_cipher *)tlv; 321 pwk_cipher->header.type = cpu_to_le16(TLV_TYPE_PWK_CIPHER); 322 pwk_cipher->header.len = 323 cpu_to_le16(sizeof(struct host_cmd_tlv_pwk_cipher) - 324 sizeof(struct mwifiex_ie_types_header)); 325 pwk_cipher->proto = cpu_to_le16(PROTOCOL_WPA2); 326 pwk_cipher->cipher = bss_cfg->wpa_cfg.pairwise_cipher_wpa2; 327 cmd_size += sizeof(struct host_cmd_tlv_pwk_cipher); 328 tlv += sizeof(struct host_cmd_tlv_pwk_cipher); 329 } 330 331 if (bss_cfg->wpa_cfg.group_cipher & VALID_CIPHER_BITMAP) { 332 gwk_cipher = (struct host_cmd_tlv_gwk_cipher *)tlv; 333 gwk_cipher->header.type = cpu_to_le16(TLV_TYPE_GWK_CIPHER); 334 gwk_cipher->header.len = 335 cpu_to_le16(sizeof(struct host_cmd_tlv_gwk_cipher) - 336 sizeof(struct mwifiex_ie_types_header)); 337 gwk_cipher->cipher = bss_cfg->wpa_cfg.group_cipher; 338 cmd_size += sizeof(struct host_cmd_tlv_gwk_cipher); 339 tlv += sizeof(struct host_cmd_tlv_gwk_cipher); 340 } 341 342 if (bss_cfg->wpa_cfg.length) { 343 passphrase = (struct host_cmd_tlv_passphrase *)tlv; 344 passphrase->header.type = 345 cpu_to_le16(TLV_TYPE_UAP_WPA_PASSPHRASE); 346 passphrase->header.len = cpu_to_le16(bss_cfg->wpa_cfg.length); 347 memcpy(passphrase->passphrase, bss_cfg->wpa_cfg.passphrase, 348 bss_cfg->wpa_cfg.length); 349 cmd_size += sizeof(struct mwifiex_ie_types_header) + 350 bss_cfg->wpa_cfg.length; 351 tlv += sizeof(struct mwifiex_ie_types_header) + 352 bss_cfg->wpa_cfg.length; 353 } 354 355 *param_size = cmd_size; 356 *tlv_buf = tlv; 357 358 return; 359 } 360 361 /* This function parses WMM related parameters from cfg80211_ap_settings 362 * structure and updates bss_config structure. 363 */ 364 void 365 mwifiex_set_wmm_params(struct mwifiex_private *priv, 366 struct mwifiex_uap_bss_param *bss_cfg, 367 struct cfg80211_ap_settings *params) 368 { 369 const u8 *vendor_ie; 370 const u8 *wmm_ie; 371 static const u8 wmm_oui[] = {0x00, 0x50, 0xf2, 0x02}; 372 373 vendor_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, 374 WLAN_OUI_TYPE_MICROSOFT_WMM, 375 params->beacon.tail, 376 params->beacon.tail_len); 377 if (vendor_ie) { 378 wmm_ie = vendor_ie; 379 if (*(wmm_ie + 1) > sizeof(struct mwifiex_types_wmm_info)) 380 return; 381 memcpy(&bss_cfg->wmm_info, wmm_ie + 382 sizeof(struct ieee_types_header), *(wmm_ie + 1)); 383 priv->wmm_enabled = 1; 384 } else { 385 memset(&bss_cfg->wmm_info, 0, sizeof(bss_cfg->wmm_info)); 386 memcpy(&bss_cfg->wmm_info.oui, wmm_oui, sizeof(wmm_oui)); 387 bss_cfg->wmm_info.subtype = MWIFIEX_WMM_SUBTYPE; 388 bss_cfg->wmm_info.version = MWIFIEX_WMM_VERSION; 389 priv->wmm_enabled = 0; 390 } 391 392 bss_cfg->qos_info = 0x00; 393 return; 394 } 395 /* This function parses BSS related parameters from structure 396 * and prepares TLVs specific to WEP encryption. 397 * These TLVs are appended to command buffer. 398 */ 399 static void 400 mwifiex_uap_bss_wep(u8 **tlv_buf, void *cmd_buf, u16 *param_size) 401 { 402 struct host_cmd_tlv_wep_key *wep_key; 403 u16 cmd_size = *param_size; 404 int i; 405 u8 *tlv = *tlv_buf; 406 struct mwifiex_uap_bss_param *bss_cfg = cmd_buf; 407 408 for (i = 0; i < NUM_WEP_KEYS; i++) { 409 if (bss_cfg->wep_cfg[i].length && 410 (bss_cfg->wep_cfg[i].length == WLAN_KEY_LEN_WEP40 || 411 bss_cfg->wep_cfg[i].length == WLAN_KEY_LEN_WEP104)) { 412 wep_key = (struct host_cmd_tlv_wep_key *)tlv; 413 wep_key->header.type = 414 cpu_to_le16(TLV_TYPE_UAP_WEP_KEY); 415 wep_key->header.len = 416 cpu_to_le16(bss_cfg->wep_cfg[i].length + 2); 417 wep_key->key_index = bss_cfg->wep_cfg[i].key_index; 418 wep_key->is_default = bss_cfg->wep_cfg[i].is_default; 419 memcpy(wep_key->key, bss_cfg->wep_cfg[i].key, 420 bss_cfg->wep_cfg[i].length); 421 cmd_size += sizeof(struct mwifiex_ie_types_header) + 2 + 422 bss_cfg->wep_cfg[i].length; 423 tlv += sizeof(struct mwifiex_ie_types_header) + 2 + 424 bss_cfg->wep_cfg[i].length; 425 } 426 } 427 428 *param_size = cmd_size; 429 *tlv_buf = tlv; 430 431 return; 432 } 433 434 /* This function enable 11D if userspace set the country IE. 435 */ 436 void mwifiex_config_uap_11d(struct mwifiex_private *priv, 437 struct cfg80211_beacon_data *beacon_data) 438 { 439 enum state_11d_t state_11d; 440 const u8 *country_ie; 441 442 country_ie = cfg80211_find_ie(WLAN_EID_COUNTRY, beacon_data->tail, 443 beacon_data->tail_len); 444 if (country_ie) { 445 /* Send cmd to FW to enable 11D function */ 446 state_11d = ENABLE_11D; 447 if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB, 448 HostCmd_ACT_GEN_SET, DOT11D_I, 449 &state_11d, true)) { 450 mwifiex_dbg(priv->adapter, ERROR, 451 "11D: failed to enable 11D\n"); 452 } 453 } 454 } 455 456 /* This function parses BSS related parameters from structure 457 * and prepares TLVs. These TLVs are appended to command buffer. 458 */ 459 static int 460 mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size) 461 { 462 struct host_cmd_tlv_mac_addr *mac_tlv; 463 struct host_cmd_tlv_dtim_period *dtim_period; 464 struct host_cmd_tlv_beacon_period *beacon_period; 465 struct host_cmd_tlv_ssid *ssid; 466 struct host_cmd_tlv_bcast_ssid *bcast_ssid; 467 struct host_cmd_tlv_channel_band *chan_band; 468 struct host_cmd_tlv_frag_threshold *frag_threshold; 469 struct host_cmd_tlv_rts_threshold *rts_threshold; 470 struct host_cmd_tlv_retry_limit *retry_limit; 471 struct host_cmd_tlv_encrypt_protocol *encrypt_protocol; 472 struct host_cmd_tlv_auth_type *auth_type; 473 struct host_cmd_tlv_rates *tlv_rates; 474 struct host_cmd_tlv_ageout_timer *ao_timer, *ps_ao_timer; 475 struct host_cmd_tlv_power_constraint *pwr_ct; 476 struct mwifiex_ie_types_htcap *htcap; 477 struct mwifiex_ie_types_wmmcap *wmm_cap; 478 struct mwifiex_uap_bss_param *bss_cfg = cmd_buf; 479 int i; 480 u16 cmd_size = *param_size; 481 482 mac_tlv = (struct host_cmd_tlv_mac_addr *)tlv; 483 mac_tlv->header.type = cpu_to_le16(TLV_TYPE_UAP_MAC_ADDRESS); 484 mac_tlv->header.len = cpu_to_le16(ETH_ALEN); 485 memcpy(mac_tlv->mac_addr, bss_cfg->mac_addr, ETH_ALEN); 486 cmd_size += sizeof(struct host_cmd_tlv_mac_addr); 487 tlv += sizeof(struct host_cmd_tlv_mac_addr); 488 489 if (bss_cfg->ssid.ssid_len) { 490 ssid = (struct host_cmd_tlv_ssid *)tlv; 491 ssid->header.type = cpu_to_le16(TLV_TYPE_UAP_SSID); 492 ssid->header.len = cpu_to_le16((u16)bss_cfg->ssid.ssid_len); 493 memcpy(ssid->ssid, bss_cfg->ssid.ssid, bss_cfg->ssid.ssid_len); 494 cmd_size += sizeof(struct mwifiex_ie_types_header) + 495 bss_cfg->ssid.ssid_len; 496 tlv += sizeof(struct mwifiex_ie_types_header) + 497 bss_cfg->ssid.ssid_len; 498 499 bcast_ssid = (struct host_cmd_tlv_bcast_ssid *)tlv; 500 bcast_ssid->header.type = cpu_to_le16(TLV_TYPE_UAP_BCAST_SSID); 501 bcast_ssid->header.len = 502 cpu_to_le16(sizeof(bcast_ssid->bcast_ctl)); 503 bcast_ssid->bcast_ctl = bss_cfg->bcast_ssid_ctl; 504 cmd_size += sizeof(struct host_cmd_tlv_bcast_ssid); 505 tlv += sizeof(struct host_cmd_tlv_bcast_ssid); 506 } 507 if (bss_cfg->rates[0]) { 508 tlv_rates = (struct host_cmd_tlv_rates *)tlv; 509 tlv_rates->header.type = cpu_to_le16(TLV_TYPE_UAP_RATES); 510 511 for (i = 0; i < MWIFIEX_SUPPORTED_RATES && bss_cfg->rates[i]; 512 i++) 513 tlv_rates->rates[i] = bss_cfg->rates[i]; 514 515 tlv_rates->header.len = cpu_to_le16(i); 516 cmd_size += sizeof(struct host_cmd_tlv_rates) + i; 517 tlv += sizeof(struct host_cmd_tlv_rates) + i; 518 } 519 if (bss_cfg->channel && 520 (((bss_cfg->band_cfg & BIT(0)) == BAND_CONFIG_BG && 521 bss_cfg->channel <= MAX_CHANNEL_BAND_BG) || 522 ((bss_cfg->band_cfg & BIT(0)) == BAND_CONFIG_A && 523 bss_cfg->channel <= MAX_CHANNEL_BAND_A))) { 524 chan_band = (struct host_cmd_tlv_channel_band *)tlv; 525 chan_band->header.type = cpu_to_le16(TLV_TYPE_CHANNELBANDLIST); 526 chan_band->header.len = 527 cpu_to_le16(sizeof(struct host_cmd_tlv_channel_band) - 528 sizeof(struct mwifiex_ie_types_header)); 529 chan_band->band_config = bss_cfg->band_cfg; 530 chan_band->channel = bss_cfg->channel; 531 cmd_size += sizeof(struct host_cmd_tlv_channel_band); 532 tlv += sizeof(struct host_cmd_tlv_channel_band); 533 } 534 if (bss_cfg->beacon_period >= MIN_BEACON_PERIOD && 535 bss_cfg->beacon_period <= MAX_BEACON_PERIOD) { 536 beacon_period = (struct host_cmd_tlv_beacon_period *)tlv; 537 beacon_period->header.type = 538 cpu_to_le16(TLV_TYPE_UAP_BEACON_PERIOD); 539 beacon_period->header.len = 540 cpu_to_le16(sizeof(struct host_cmd_tlv_beacon_period) - 541 sizeof(struct mwifiex_ie_types_header)); 542 beacon_period->period = cpu_to_le16(bss_cfg->beacon_period); 543 cmd_size += sizeof(struct host_cmd_tlv_beacon_period); 544 tlv += sizeof(struct host_cmd_tlv_beacon_period); 545 } 546 if (bss_cfg->dtim_period >= MIN_DTIM_PERIOD && 547 bss_cfg->dtim_period <= MAX_DTIM_PERIOD) { 548 dtim_period = (struct host_cmd_tlv_dtim_period *)tlv; 549 dtim_period->header.type = 550 cpu_to_le16(TLV_TYPE_UAP_DTIM_PERIOD); 551 dtim_period->header.len = 552 cpu_to_le16(sizeof(struct host_cmd_tlv_dtim_period) - 553 sizeof(struct mwifiex_ie_types_header)); 554 dtim_period->period = bss_cfg->dtim_period; 555 cmd_size += sizeof(struct host_cmd_tlv_dtim_period); 556 tlv += sizeof(struct host_cmd_tlv_dtim_period); 557 } 558 if (bss_cfg->rts_threshold <= MWIFIEX_RTS_MAX_VALUE) { 559 rts_threshold = (struct host_cmd_tlv_rts_threshold *)tlv; 560 rts_threshold->header.type = 561 cpu_to_le16(TLV_TYPE_UAP_RTS_THRESHOLD); 562 rts_threshold->header.len = 563 cpu_to_le16(sizeof(struct host_cmd_tlv_rts_threshold) - 564 sizeof(struct mwifiex_ie_types_header)); 565 rts_threshold->rts_thr = cpu_to_le16(bss_cfg->rts_threshold); 566 cmd_size += sizeof(struct host_cmd_tlv_frag_threshold); 567 tlv += sizeof(struct host_cmd_tlv_frag_threshold); 568 } 569 if ((bss_cfg->frag_threshold >= MWIFIEX_FRAG_MIN_VALUE) && 570 (bss_cfg->frag_threshold <= MWIFIEX_FRAG_MAX_VALUE)) { 571 frag_threshold = (struct host_cmd_tlv_frag_threshold *)tlv; 572 frag_threshold->header.type = 573 cpu_to_le16(TLV_TYPE_UAP_FRAG_THRESHOLD); 574 frag_threshold->header.len = 575 cpu_to_le16(sizeof(struct host_cmd_tlv_frag_threshold) - 576 sizeof(struct mwifiex_ie_types_header)); 577 frag_threshold->frag_thr = cpu_to_le16(bss_cfg->frag_threshold); 578 cmd_size += sizeof(struct host_cmd_tlv_frag_threshold); 579 tlv += sizeof(struct host_cmd_tlv_frag_threshold); 580 } 581 if (bss_cfg->retry_limit <= MWIFIEX_RETRY_LIMIT) { 582 retry_limit = (struct host_cmd_tlv_retry_limit *)tlv; 583 retry_limit->header.type = 584 cpu_to_le16(TLV_TYPE_UAP_RETRY_LIMIT); 585 retry_limit->header.len = 586 cpu_to_le16(sizeof(struct host_cmd_tlv_retry_limit) - 587 sizeof(struct mwifiex_ie_types_header)); 588 retry_limit->limit = (u8)bss_cfg->retry_limit; 589 cmd_size += sizeof(struct host_cmd_tlv_retry_limit); 590 tlv += sizeof(struct host_cmd_tlv_retry_limit); 591 } 592 if ((bss_cfg->protocol & PROTOCOL_WPA) || 593 (bss_cfg->protocol & PROTOCOL_WPA2) || 594 (bss_cfg->protocol & PROTOCOL_EAP)) 595 mwifiex_uap_bss_wpa(&tlv, cmd_buf, &cmd_size); 596 else 597 mwifiex_uap_bss_wep(&tlv, cmd_buf, &cmd_size); 598 599 if ((bss_cfg->auth_mode <= WLAN_AUTH_SHARED_KEY) || 600 (bss_cfg->auth_mode == MWIFIEX_AUTH_MODE_AUTO)) { 601 auth_type = (struct host_cmd_tlv_auth_type *)tlv; 602 auth_type->header.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE); 603 auth_type->header.len = 604 cpu_to_le16(sizeof(struct host_cmd_tlv_auth_type) - 605 sizeof(struct mwifiex_ie_types_header)); 606 auth_type->auth_type = (u8)bss_cfg->auth_mode; 607 cmd_size += sizeof(struct host_cmd_tlv_auth_type); 608 tlv += sizeof(struct host_cmd_tlv_auth_type); 609 } 610 if (bss_cfg->protocol) { 611 encrypt_protocol = (struct host_cmd_tlv_encrypt_protocol *)tlv; 612 encrypt_protocol->header.type = 613 cpu_to_le16(TLV_TYPE_UAP_ENCRY_PROTOCOL); 614 encrypt_protocol->header.len = 615 cpu_to_le16(sizeof(struct host_cmd_tlv_encrypt_protocol) 616 - sizeof(struct mwifiex_ie_types_header)); 617 encrypt_protocol->proto = cpu_to_le16(bss_cfg->protocol); 618 cmd_size += sizeof(struct host_cmd_tlv_encrypt_protocol); 619 tlv += sizeof(struct host_cmd_tlv_encrypt_protocol); 620 } 621 622 if (bss_cfg->ht_cap.cap_info) { 623 htcap = (struct mwifiex_ie_types_htcap *)tlv; 624 htcap->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY); 625 htcap->header.len = 626 cpu_to_le16(sizeof(struct ieee80211_ht_cap)); 627 htcap->ht_cap.cap_info = bss_cfg->ht_cap.cap_info; 628 htcap->ht_cap.ampdu_params_info = 629 bss_cfg->ht_cap.ampdu_params_info; 630 memcpy(&htcap->ht_cap.mcs, &bss_cfg->ht_cap.mcs, 631 sizeof(struct ieee80211_mcs_info)); 632 htcap->ht_cap.extended_ht_cap_info = 633 bss_cfg->ht_cap.extended_ht_cap_info; 634 htcap->ht_cap.tx_BF_cap_info = bss_cfg->ht_cap.tx_BF_cap_info; 635 htcap->ht_cap.antenna_selection_info = 636 bss_cfg->ht_cap.antenna_selection_info; 637 cmd_size += sizeof(struct mwifiex_ie_types_htcap); 638 tlv += sizeof(struct mwifiex_ie_types_htcap); 639 } 640 641 if (bss_cfg->wmm_info.qos_info != 0xFF) { 642 wmm_cap = (struct mwifiex_ie_types_wmmcap *)tlv; 643 wmm_cap->header.type = cpu_to_le16(WLAN_EID_VENDOR_SPECIFIC); 644 wmm_cap->header.len = cpu_to_le16(sizeof(wmm_cap->wmm_info)); 645 memcpy(&wmm_cap->wmm_info, &bss_cfg->wmm_info, 646 sizeof(wmm_cap->wmm_info)); 647 cmd_size += sizeof(struct mwifiex_ie_types_wmmcap); 648 tlv += sizeof(struct mwifiex_ie_types_wmmcap); 649 } 650 651 if (bss_cfg->sta_ao_timer) { 652 ao_timer = (struct host_cmd_tlv_ageout_timer *)tlv; 653 ao_timer->header.type = cpu_to_le16(TLV_TYPE_UAP_AO_TIMER); 654 ao_timer->header.len = cpu_to_le16(sizeof(*ao_timer) - 655 sizeof(struct mwifiex_ie_types_header)); 656 ao_timer->sta_ao_timer = cpu_to_le32(bss_cfg->sta_ao_timer); 657 cmd_size += sizeof(*ao_timer); 658 tlv += sizeof(*ao_timer); 659 } 660 661 if (bss_cfg->power_constraint) { 662 pwr_ct = (void *)tlv; 663 pwr_ct->header.type = cpu_to_le16(TLV_TYPE_PWR_CONSTRAINT); 664 pwr_ct->header.len = cpu_to_le16(sizeof(u8)); 665 pwr_ct->constraint = bss_cfg->power_constraint; 666 cmd_size += sizeof(*pwr_ct); 667 tlv += sizeof(*pwr_ct); 668 } 669 670 if (bss_cfg->ps_sta_ao_timer) { 671 ps_ao_timer = (struct host_cmd_tlv_ageout_timer *)tlv; 672 ps_ao_timer->header.type = 673 cpu_to_le16(TLV_TYPE_UAP_PS_AO_TIMER); 674 ps_ao_timer->header.len = cpu_to_le16(sizeof(*ps_ao_timer) - 675 sizeof(struct mwifiex_ie_types_header)); 676 ps_ao_timer->sta_ao_timer = 677 cpu_to_le32(bss_cfg->ps_sta_ao_timer); 678 cmd_size += sizeof(*ps_ao_timer); 679 tlv += sizeof(*ps_ao_timer); 680 } 681 682 *param_size = cmd_size; 683 684 return 0; 685 } 686 687 /* This function parses custom IEs from IE list and prepares command buffer */ 688 static int mwifiex_uap_custom_ie_prepare(u8 *tlv, void *cmd_buf, u16 *ie_size) 689 { 690 struct mwifiex_ie_list *ap_ie = cmd_buf; 691 struct mwifiex_ie_types_header *tlv_ie = (void *)tlv; 692 693 if (!ap_ie || !ap_ie->len) 694 return -1; 695 696 *ie_size += le16_to_cpu(ap_ie->len) + 697 sizeof(struct mwifiex_ie_types_header); 698 699 tlv_ie->type = cpu_to_le16(TLV_TYPE_MGMT_IE); 700 tlv_ie->len = ap_ie->len; 701 tlv += sizeof(struct mwifiex_ie_types_header); 702 703 memcpy(tlv, ap_ie->ie_list, le16_to_cpu(ap_ie->len)); 704 705 return 0; 706 } 707 708 /* Parse AP config structure and prepare TLV based command structure 709 * to be sent to FW for uAP configuration 710 */ 711 static int 712 mwifiex_cmd_uap_sys_config(struct host_cmd_ds_command *cmd, u16 cmd_action, 713 u32 type, void *cmd_buf) 714 { 715 u8 *tlv; 716 u16 cmd_size, param_size, ie_size; 717 struct host_cmd_ds_sys_config *sys_cfg; 718 719 cmd->command = cpu_to_le16(HostCmd_CMD_UAP_SYS_CONFIG); 720 cmd_size = (u16)(sizeof(struct host_cmd_ds_sys_config) + S_DS_GEN); 721 sys_cfg = (struct host_cmd_ds_sys_config *)&cmd->params.uap_sys_config; 722 sys_cfg->action = cpu_to_le16(cmd_action); 723 tlv = sys_cfg->tlv; 724 725 switch (type) { 726 case UAP_BSS_PARAMS_I: 727 param_size = cmd_size; 728 if (mwifiex_uap_bss_param_prepare(tlv, cmd_buf, ¶m_size)) 729 return -1; 730 cmd->size = cpu_to_le16(param_size); 731 break; 732 case UAP_CUSTOM_IE_I: 733 ie_size = cmd_size; 734 if (mwifiex_uap_custom_ie_prepare(tlv, cmd_buf, &ie_size)) 735 return -1; 736 cmd->size = cpu_to_le16(ie_size); 737 break; 738 default: 739 return -1; 740 } 741 742 return 0; 743 } 744 745 /* This function prepares AP start up command with or without host MLME 746 */ 747 static void mwifiex_cmd_uap_bss_start(struct mwifiex_private *priv, 748 struct host_cmd_ds_command *cmd) 749 { 750 struct mwifiex_ie_types_host_mlme *tlv; 751 int size; 752 753 cmd->command = cpu_to_le16(HostCmd_CMD_UAP_BSS_START); 754 size = S_DS_GEN; 755 756 if (priv->adapter->host_mlme_enabled) { 757 tlv = (struct mwifiex_ie_types_host_mlme *)((u8 *)cmd + size); 758 tlv->header.type = cpu_to_le16(TLV_TYPE_HOST_MLME); 759 tlv->header.len = cpu_to_le16(sizeof(tlv->host_mlme)); 760 tlv->host_mlme = 1; 761 size += sizeof(struct mwifiex_ie_types_host_mlme); 762 } 763 764 cmd->size = cpu_to_le16(size); 765 } 766 767 /* This function prepares AP specific deauth command with mac supplied in 768 * function parameter. 769 */ 770 static int mwifiex_cmd_uap_sta_deauth(struct mwifiex_private *priv, 771 struct host_cmd_ds_command *cmd, u8 *mac) 772 { 773 struct host_cmd_ds_sta_deauth *sta_deauth = &cmd->params.sta_deauth; 774 775 cmd->command = cpu_to_le16(HostCmd_CMD_UAP_STA_DEAUTH); 776 memcpy(sta_deauth->mac, mac, ETH_ALEN); 777 sta_deauth->reason = cpu_to_le16(WLAN_REASON_DEAUTH_LEAVING); 778 779 cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_sta_deauth) + 780 S_DS_GEN); 781 return 0; 782 } 783 784 /* This function prepares AP specific add station command. 785 */ 786 static int mwifiex_cmd_uap_add_station(struct mwifiex_private *priv, 787 struct host_cmd_ds_command *cmd, 788 u16 cmd_action, void *data_buf) 789 { 790 struct host_cmd_ds_add_station *new_sta = &cmd->params.sta_info; 791 struct mwifiex_sta_info *add_sta = (struct mwifiex_sta_info *)data_buf; 792 struct station_parameters *params = add_sta->params; 793 struct mwifiex_sta_node *sta_ptr; 794 u8 *pos; 795 u8 qos_capa; 796 u16 header_len = sizeof(struct mwifiex_ie_types_header); 797 u16 tlv_len; 798 int size; 799 struct mwifiex_ie_types_data *tlv; 800 struct mwifiex_ie_types_sta_flag *sta_flag; 801 int i; 802 803 cmd->command = cpu_to_le16(HostCmd_CMD_ADD_NEW_STATION); 804 new_sta->action = cpu_to_le16(cmd_action); 805 size = sizeof(struct host_cmd_ds_add_station) + S_DS_GEN; 806 807 if (cmd_action == HostCmd_ACT_ADD_STA) 808 sta_ptr = mwifiex_add_sta_entry(priv, add_sta->peer_mac); 809 else 810 sta_ptr = mwifiex_get_sta_entry(priv, add_sta->peer_mac); 811 812 if (!sta_ptr) 813 return -1; 814 815 memcpy(new_sta->peer_mac, add_sta->peer_mac, ETH_ALEN); 816 817 if (cmd_action == HostCmd_ACT_REMOVE_STA) { 818 cmd->size = cpu_to_le16(size); 819 return 0; 820 } 821 822 new_sta->aid = cpu_to_le16(params->aid); 823 new_sta->listen_interval = cpu_to_le32(params->listen_interval); 824 new_sta->cap_info = cpu_to_le16(params->capability); 825 826 pos = new_sta->tlv; 827 828 if (params->sta_flags_set & NL80211_STA_FLAG_WME) 829 sta_ptr->is_wmm_enabled = 1; 830 sta_flag = (struct mwifiex_ie_types_sta_flag *)pos; 831 sta_flag->header.type = cpu_to_le16(TLV_TYPE_UAP_STA_FLAGS); 832 sta_flag->header.len = cpu_to_le16(sizeof(__le32)); 833 sta_flag->sta_flags = cpu_to_le32(params->sta_flags_set); 834 pos += sizeof(struct mwifiex_ie_types_sta_flag); 835 size += sizeof(struct mwifiex_ie_types_sta_flag); 836 837 if (params->ext_capab_len) { 838 tlv = (struct mwifiex_ie_types_data *)pos; 839 tlv->header.type = cpu_to_le16(WLAN_EID_EXT_CAPABILITY); 840 tlv_len = params->ext_capab_len; 841 tlv->header.len = cpu_to_le16(tlv_len); 842 memcpy(tlv->data, params->ext_capab, tlv_len); 843 pos += (header_len + tlv_len); 844 size += (header_len + tlv_len); 845 } 846 847 if (params->link_sta_params.supported_rates_len) { 848 tlv = (struct mwifiex_ie_types_data *)pos; 849 tlv->header.type = cpu_to_le16(WLAN_EID_SUPP_RATES); 850 tlv_len = params->link_sta_params.supported_rates_len; 851 tlv->header.len = cpu_to_le16(tlv_len); 852 memcpy(tlv->data, 853 params->link_sta_params.supported_rates, tlv_len); 854 pos += (header_len + tlv_len); 855 size += (header_len + tlv_len); 856 } 857 858 if (params->uapsd_queues || params->max_sp) { 859 tlv = (struct mwifiex_ie_types_data *)pos; 860 tlv->header.type = cpu_to_le16(WLAN_EID_QOS_CAPA); 861 tlv_len = sizeof(qos_capa); 862 tlv->header.len = cpu_to_le16(tlv_len); 863 qos_capa = params->uapsd_queues | (params->max_sp << 5); 864 memcpy(tlv->data, &qos_capa, tlv_len); 865 pos += (header_len + tlv_len); 866 size += (header_len + tlv_len); 867 sta_ptr->is_wmm_enabled = 1; 868 } 869 870 if (params->link_sta_params.ht_capa) { 871 tlv = (struct mwifiex_ie_types_data *)pos; 872 tlv->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY); 873 tlv_len = sizeof(struct ieee80211_ht_cap); 874 tlv->header.len = cpu_to_le16(tlv_len); 875 memcpy(tlv->data, params->link_sta_params.ht_capa, tlv_len); 876 pos += (header_len + tlv_len); 877 size += (header_len + tlv_len); 878 sta_ptr->is_11n_enabled = 1; 879 sta_ptr->max_amsdu = 880 le16_to_cpu(params->link_sta_params.ht_capa->cap_info) & 881 IEEE80211_HT_CAP_MAX_AMSDU ? 882 MWIFIEX_TX_DATA_BUF_SIZE_8K : 883 MWIFIEX_TX_DATA_BUF_SIZE_4K; 884 } 885 886 if (params->link_sta_params.vht_capa) { 887 tlv = (struct mwifiex_ie_types_data *)pos; 888 tlv->header.type = cpu_to_le16(WLAN_EID_VHT_CAPABILITY); 889 tlv_len = sizeof(struct ieee80211_vht_cap); 890 tlv->header.len = cpu_to_le16(tlv_len); 891 memcpy(tlv->data, params->link_sta_params.vht_capa, tlv_len); 892 pos += (header_len + tlv_len); 893 size += (header_len + tlv_len); 894 sta_ptr->is_11ac_enabled = 1; 895 } 896 897 if (params->link_sta_params.opmode_notif_used) { 898 tlv = (struct mwifiex_ie_types_data *)pos; 899 tlv->header.type = cpu_to_le16(WLAN_EID_OPMODE_NOTIF); 900 tlv_len = sizeof(u8); 901 tlv->header.len = cpu_to_le16(tlv_len); 902 memcpy(tlv->data, ¶ms->link_sta_params.opmode_notif, 903 tlv_len); 904 pos += (header_len + tlv_len); 905 size += (header_len + tlv_len); 906 } 907 908 for (i = 0; i < MAX_NUM_TID; i++) { 909 if (sta_ptr->is_11n_enabled) 910 sta_ptr->ampdu_sta[i] = 911 priv->aggr_prio_tbl[i].ampdu_user; 912 else 913 sta_ptr->ampdu_sta[i] = BA_STREAM_NOT_ALLOWED; 914 } 915 916 memset(sta_ptr->rx_seq, 0xff, sizeof(sta_ptr->rx_seq)); 917 cmd->size = cpu_to_le16(size); 918 919 return 0; 920 } 921 922 /* This function prepares the AP specific commands before sending them 923 * to the firmware. 924 * This is a generic function which calls specific command preparation 925 * routines based upon the command number. 926 */ 927 int mwifiex_uap_prepare_cmd(struct mwifiex_private *priv, u16 cmd_no, 928 u16 cmd_action, u32 type, 929 void *data_buf, void *cmd_buf) 930 { 931 struct host_cmd_ds_command *cmd = cmd_buf; 932 933 switch (cmd_no) { 934 case HostCmd_CMD_UAP_SYS_CONFIG: 935 if (mwifiex_cmd_uap_sys_config(cmd, cmd_action, type, data_buf)) 936 return -1; 937 break; 938 case HostCmd_CMD_UAP_BSS_START: 939 mwifiex_cmd_uap_bss_start(priv, cmd); 940 break; 941 case HostCmd_CMD_UAP_BSS_STOP: 942 case HOST_CMD_APCMD_SYS_RESET: 943 case HOST_CMD_APCMD_STA_LIST: 944 cmd->command = cpu_to_le16(cmd_no); 945 cmd->size = cpu_to_le16(S_DS_GEN); 946 break; 947 case HostCmd_CMD_UAP_STA_DEAUTH: 948 if (mwifiex_cmd_uap_sta_deauth(priv, cmd, data_buf)) 949 return -1; 950 break; 951 case HostCmd_CMD_CHAN_REPORT_REQUEST: 952 if (mwifiex_cmd_issue_chan_report_request(priv, cmd_buf, 953 data_buf)) 954 return -1; 955 break; 956 case HostCmd_CMD_ADD_NEW_STATION: 957 if (mwifiex_cmd_uap_add_station(priv, cmd, cmd_action, 958 data_buf)) 959 return -1; 960 break; 961 default: 962 mwifiex_dbg(priv->adapter, ERROR, 963 "PREP_CMD: unknown cmd %#x\n", cmd_no); 964 return -1; 965 } 966 967 return 0; 968 } 969 970 void mwifiex_uap_set_channel(struct mwifiex_private *priv, 971 struct mwifiex_uap_bss_param *bss_cfg, 972 struct cfg80211_chan_def chandef) 973 { 974 u8 config_bands = 0, old_bands = priv->adapter->config_bands; 975 976 priv->bss_chandef = chandef; 977 978 bss_cfg->channel = ieee80211_frequency_to_channel( 979 chandef.chan->center_freq); 980 981 /* Set appropriate bands */ 982 if (chandef.chan->band == NL80211_BAND_2GHZ) { 983 bss_cfg->band_cfg = BAND_CONFIG_BG; 984 config_bands = BAND_B | BAND_G; 985 986 if (chandef.width > NL80211_CHAN_WIDTH_20_NOHT) 987 config_bands |= BAND_GN; 988 } else { 989 bss_cfg->band_cfg = BAND_CONFIG_A; 990 config_bands = BAND_A; 991 992 if (chandef.width > NL80211_CHAN_WIDTH_20_NOHT) 993 config_bands |= BAND_AN; 994 995 if (chandef.width > NL80211_CHAN_WIDTH_40) 996 config_bands |= BAND_AAC; 997 } 998 999 switch (chandef.width) { 1000 case NL80211_CHAN_WIDTH_5: 1001 case NL80211_CHAN_WIDTH_10: 1002 case NL80211_CHAN_WIDTH_20_NOHT: 1003 case NL80211_CHAN_WIDTH_20: 1004 break; 1005 case NL80211_CHAN_WIDTH_40: 1006 if (chandef.center_freq1 < chandef.chan->center_freq) 1007 bss_cfg->band_cfg |= MWIFIEX_SEC_CHAN_BELOW; 1008 else 1009 bss_cfg->band_cfg |= MWIFIEX_SEC_CHAN_ABOVE; 1010 break; 1011 case NL80211_CHAN_WIDTH_80: 1012 case NL80211_CHAN_WIDTH_80P80: 1013 case NL80211_CHAN_WIDTH_160: 1014 bss_cfg->band_cfg |= 1015 mwifiex_get_sec_chan_offset(bss_cfg->channel) << 4; 1016 break; 1017 default: 1018 mwifiex_dbg(priv->adapter, 1019 WARN, "Unknown channel width: %d\n", 1020 chandef.width); 1021 break; 1022 } 1023 1024 priv->adapter->config_bands = config_bands; 1025 1026 if (old_bands != config_bands) { 1027 mwifiex_send_domain_info_cmd_fw(priv->adapter->wiphy); 1028 mwifiex_dnld_txpwr_table(priv); 1029 } 1030 } 1031 1032 int mwifiex_config_start_uap(struct mwifiex_private *priv, 1033 struct mwifiex_uap_bss_param *bss_cfg) 1034 { 1035 if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_SYS_CONFIG, 1036 HostCmd_ACT_GEN_SET, 1037 UAP_BSS_PARAMS_I, bss_cfg, true)) { 1038 mwifiex_dbg(priv->adapter, ERROR, 1039 "Failed to set AP configuration\n"); 1040 return -1; 1041 } 1042 1043 if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_START, 1044 HostCmd_ACT_GEN_SET, 0, NULL, true)) { 1045 mwifiex_dbg(priv->adapter, ERROR, 1046 "Failed to start the BSS\n"); 1047 return -1; 1048 } 1049 1050 if (priv->sec_info.wep_enabled) 1051 priv->curr_pkt_filter |= HostCmd_ACT_MAC_WEP_ENABLE; 1052 else 1053 priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_WEP_ENABLE; 1054 1055 if (mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL, 1056 HostCmd_ACT_GEN_SET, 0, 1057 &priv->curr_pkt_filter, true)) 1058 return -1; 1059 1060 return 0; 1061 } 1062