1 /* 2 * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 18 19 #include <linux/module.h> 20 #include <linux/firmware.h> 21 #include <linux/platform_device.h> 22 #include "wcn36xx.h" 23 24 unsigned int wcn36xx_dbg_mask; 25 module_param_named(debug_mask, wcn36xx_dbg_mask, uint, 0644); 26 MODULE_PARM_DESC(debug_mask, "Debugging mask"); 27 28 #define CHAN2G(_freq, _idx) { \ 29 .band = IEEE80211_BAND_2GHZ, \ 30 .center_freq = (_freq), \ 31 .hw_value = (_idx), \ 32 .max_power = 25, \ 33 } 34 35 #define CHAN5G(_freq, _idx) { \ 36 .band = IEEE80211_BAND_5GHZ, \ 37 .center_freq = (_freq), \ 38 .hw_value = (_idx), \ 39 .max_power = 25, \ 40 } 41 42 /* The wcn firmware expects channel values to matching 43 * their mnemonic values. So use these for .hw_value. */ 44 static struct ieee80211_channel wcn_2ghz_channels[] = { 45 CHAN2G(2412, 1), /* Channel 1 */ 46 CHAN2G(2417, 2), /* Channel 2 */ 47 CHAN2G(2422, 3), /* Channel 3 */ 48 CHAN2G(2427, 4), /* Channel 4 */ 49 CHAN2G(2432, 5), /* Channel 5 */ 50 CHAN2G(2437, 6), /* Channel 6 */ 51 CHAN2G(2442, 7), /* Channel 7 */ 52 CHAN2G(2447, 8), /* Channel 8 */ 53 CHAN2G(2452, 9), /* Channel 9 */ 54 CHAN2G(2457, 10), /* Channel 10 */ 55 CHAN2G(2462, 11), /* Channel 11 */ 56 CHAN2G(2467, 12), /* Channel 12 */ 57 CHAN2G(2472, 13), /* Channel 13 */ 58 CHAN2G(2484, 14) /* Channel 14 */ 59 60 }; 61 62 static struct ieee80211_channel wcn_5ghz_channels[] = { 63 CHAN5G(5180, 36), 64 CHAN5G(5200, 40), 65 CHAN5G(5220, 44), 66 CHAN5G(5240, 48), 67 CHAN5G(5260, 52), 68 CHAN5G(5280, 56), 69 CHAN5G(5300, 60), 70 CHAN5G(5320, 64), 71 CHAN5G(5500, 100), 72 CHAN5G(5520, 104), 73 CHAN5G(5540, 108), 74 CHAN5G(5560, 112), 75 CHAN5G(5580, 116), 76 CHAN5G(5600, 120), 77 CHAN5G(5620, 124), 78 CHAN5G(5640, 128), 79 CHAN5G(5660, 132), 80 CHAN5G(5700, 140), 81 CHAN5G(5745, 149), 82 CHAN5G(5765, 153), 83 CHAN5G(5785, 157), 84 CHAN5G(5805, 161), 85 CHAN5G(5825, 165) 86 }; 87 88 #define RATE(_bitrate, _hw_rate, _flags) { \ 89 .bitrate = (_bitrate), \ 90 .flags = (_flags), \ 91 .hw_value = (_hw_rate), \ 92 .hw_value_short = (_hw_rate) \ 93 } 94 95 static struct ieee80211_rate wcn_2ghz_rates[] = { 96 RATE(10, HW_RATE_INDEX_1MBPS, 0), 97 RATE(20, HW_RATE_INDEX_2MBPS, IEEE80211_RATE_SHORT_PREAMBLE), 98 RATE(55, HW_RATE_INDEX_5_5MBPS, IEEE80211_RATE_SHORT_PREAMBLE), 99 RATE(110, HW_RATE_INDEX_11MBPS, IEEE80211_RATE_SHORT_PREAMBLE), 100 RATE(60, HW_RATE_INDEX_6MBPS, 0), 101 RATE(90, HW_RATE_INDEX_9MBPS, 0), 102 RATE(120, HW_RATE_INDEX_12MBPS, 0), 103 RATE(180, HW_RATE_INDEX_18MBPS, 0), 104 RATE(240, HW_RATE_INDEX_24MBPS, 0), 105 RATE(360, HW_RATE_INDEX_36MBPS, 0), 106 RATE(480, HW_RATE_INDEX_48MBPS, 0), 107 RATE(540, HW_RATE_INDEX_54MBPS, 0) 108 }; 109 110 static struct ieee80211_rate wcn_5ghz_rates[] = { 111 RATE(60, HW_RATE_INDEX_6MBPS, 0), 112 RATE(90, HW_RATE_INDEX_9MBPS, 0), 113 RATE(120, HW_RATE_INDEX_12MBPS, 0), 114 RATE(180, HW_RATE_INDEX_18MBPS, 0), 115 RATE(240, HW_RATE_INDEX_24MBPS, 0), 116 RATE(360, HW_RATE_INDEX_36MBPS, 0), 117 RATE(480, HW_RATE_INDEX_48MBPS, 0), 118 RATE(540, HW_RATE_INDEX_54MBPS, 0) 119 }; 120 121 static struct ieee80211_supported_band wcn_band_2ghz = { 122 .channels = wcn_2ghz_channels, 123 .n_channels = ARRAY_SIZE(wcn_2ghz_channels), 124 .bitrates = wcn_2ghz_rates, 125 .n_bitrates = ARRAY_SIZE(wcn_2ghz_rates), 126 .ht_cap = { 127 .cap = IEEE80211_HT_CAP_GRN_FLD | 128 IEEE80211_HT_CAP_SGI_20 | 129 IEEE80211_HT_CAP_DSSSCCK40 | 130 IEEE80211_HT_CAP_LSIG_TXOP_PROT, 131 .ht_supported = true, 132 .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, 133 .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, 134 .mcs = { 135 .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 136 .rx_highest = cpu_to_le16(72), 137 .tx_params = IEEE80211_HT_MCS_TX_DEFINED, 138 } 139 } 140 }; 141 142 static struct ieee80211_supported_band wcn_band_5ghz = { 143 .channels = wcn_5ghz_channels, 144 .n_channels = ARRAY_SIZE(wcn_5ghz_channels), 145 .bitrates = wcn_5ghz_rates, 146 .n_bitrates = ARRAY_SIZE(wcn_5ghz_rates), 147 .ht_cap = { 148 .cap = IEEE80211_HT_CAP_GRN_FLD | 149 IEEE80211_HT_CAP_SGI_20 | 150 IEEE80211_HT_CAP_DSSSCCK40 | 151 IEEE80211_HT_CAP_LSIG_TXOP_PROT | 152 IEEE80211_HT_CAP_SGI_40 | 153 IEEE80211_HT_CAP_SUP_WIDTH_20_40, 154 .ht_supported = true, 155 .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, 156 .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, 157 .mcs = { 158 .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 159 .rx_highest = cpu_to_le16(72), 160 .tx_params = IEEE80211_HT_MCS_TX_DEFINED, 161 } 162 } 163 }; 164 165 #ifdef CONFIG_PM 166 167 static const struct wiphy_wowlan_support wowlan_support = { 168 .flags = WIPHY_WOWLAN_ANY 169 }; 170 171 #endif 172 173 static inline u8 get_sta_index(struct ieee80211_vif *vif, 174 struct wcn36xx_sta *sta_priv) 175 { 176 return NL80211_IFTYPE_STATION == vif->type ? 177 sta_priv->bss_sta_index : 178 sta_priv->sta_index; 179 } 180 181 static const char * const wcn36xx_caps_names[] = { 182 "MCC", /* 0 */ 183 "P2P", /* 1 */ 184 "DOT11AC", /* 2 */ 185 "SLM_SESSIONIZATION", /* 3 */ 186 "DOT11AC_OPMODE", /* 4 */ 187 "SAP32STA", /* 5 */ 188 "TDLS", /* 6 */ 189 "P2P_GO_NOA_DECOUPLE_INIT_SCAN",/* 7 */ 190 "WLANACTIVE_OFFLOAD", /* 8 */ 191 "BEACON_OFFLOAD", /* 9 */ 192 "SCAN_OFFLOAD", /* 10 */ 193 "ROAM_OFFLOAD", /* 11 */ 194 "BCN_MISS_OFFLOAD", /* 12 */ 195 "STA_POWERSAVE", /* 13 */ 196 "STA_ADVANCED_PWRSAVE", /* 14 */ 197 "AP_UAPSD", /* 15 */ 198 "AP_DFS", /* 16 */ 199 "BLOCKACK", /* 17 */ 200 "PHY_ERR", /* 18 */ 201 "BCN_FILTER", /* 19 */ 202 "RTT", /* 20 */ 203 "RATECTRL", /* 21 */ 204 "WOW" /* 22 */ 205 }; 206 207 static const char *wcn36xx_get_cap_name(enum place_holder_in_cap_bitmap x) 208 { 209 if (x >= ARRAY_SIZE(wcn36xx_caps_names)) 210 return "UNKNOWN"; 211 return wcn36xx_caps_names[x]; 212 } 213 214 static void wcn36xx_feat_caps_info(struct wcn36xx *wcn) 215 { 216 int i; 217 218 for (i = 0; i < MAX_FEATURE_SUPPORTED; i++) { 219 if (get_feat_caps(wcn->fw_feat_caps, i)) 220 wcn36xx_info("FW Cap %s\n", wcn36xx_get_cap_name(i)); 221 } 222 } 223 224 static void wcn36xx_detect_chip_version(struct wcn36xx *wcn) 225 { 226 if (get_feat_caps(wcn->fw_feat_caps, DOT11AC)) { 227 wcn36xx_info("Chip is 3680\n"); 228 wcn->chip_version = WCN36XX_CHIP_3680; 229 } else { 230 wcn36xx_info("Chip is 3660\n"); 231 wcn->chip_version = WCN36XX_CHIP_3660; 232 } 233 } 234 235 static int wcn36xx_start(struct ieee80211_hw *hw) 236 { 237 struct wcn36xx *wcn = hw->priv; 238 int ret; 239 240 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac start\n"); 241 242 /* SMD initialization */ 243 ret = wcn36xx_smd_open(wcn); 244 if (ret) { 245 wcn36xx_err("Failed to open smd channel: %d\n", ret); 246 goto out_err; 247 } 248 249 /* Allocate memory pools for Mgmt BD headers and Data BD headers */ 250 ret = wcn36xx_dxe_allocate_mem_pools(wcn); 251 if (ret) { 252 wcn36xx_err("Failed to alloc DXE mempool: %d\n", ret); 253 goto out_smd_close; 254 } 255 256 ret = wcn36xx_dxe_alloc_ctl_blks(wcn); 257 if (ret) { 258 wcn36xx_err("Failed to alloc DXE ctl blocks: %d\n", ret); 259 goto out_free_dxe_pool; 260 } 261 262 wcn->hal_buf = kmalloc(WCN36XX_HAL_BUF_SIZE, GFP_KERNEL); 263 if (!wcn->hal_buf) { 264 wcn36xx_err("Failed to allocate smd buf\n"); 265 ret = -ENOMEM; 266 goto out_free_dxe_ctl; 267 } 268 269 ret = wcn36xx_smd_load_nv(wcn); 270 if (ret) { 271 wcn36xx_err("Failed to push NV to chip\n"); 272 goto out_free_smd_buf; 273 } 274 275 ret = wcn36xx_smd_start(wcn); 276 if (ret) { 277 wcn36xx_err("Failed to start chip\n"); 278 goto out_free_smd_buf; 279 } 280 281 if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) { 282 ret = wcn36xx_smd_feature_caps_exchange(wcn); 283 if (ret) 284 wcn36xx_warn("Exchange feature caps failed\n"); 285 else 286 wcn36xx_feat_caps_info(wcn); 287 } 288 289 wcn36xx_detect_chip_version(wcn); 290 291 /* DMA channel initialization */ 292 ret = wcn36xx_dxe_init(wcn); 293 if (ret) { 294 wcn36xx_err("DXE init failed\n"); 295 goto out_smd_stop; 296 } 297 298 wcn36xx_debugfs_init(wcn); 299 300 INIT_LIST_HEAD(&wcn->vif_list); 301 return 0; 302 303 out_smd_stop: 304 wcn36xx_smd_stop(wcn); 305 out_free_smd_buf: 306 kfree(wcn->hal_buf); 307 out_free_dxe_pool: 308 wcn36xx_dxe_free_mem_pools(wcn); 309 out_free_dxe_ctl: 310 wcn36xx_dxe_free_ctl_blks(wcn); 311 out_smd_close: 312 wcn36xx_smd_close(wcn); 313 out_err: 314 return ret; 315 } 316 317 static void wcn36xx_stop(struct ieee80211_hw *hw) 318 { 319 struct wcn36xx *wcn = hw->priv; 320 321 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac stop\n"); 322 323 wcn36xx_debugfs_exit(wcn); 324 wcn36xx_smd_stop(wcn); 325 wcn36xx_dxe_deinit(wcn); 326 wcn36xx_smd_close(wcn); 327 328 wcn36xx_dxe_free_mem_pools(wcn); 329 wcn36xx_dxe_free_ctl_blks(wcn); 330 331 kfree(wcn->hal_buf); 332 } 333 334 static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed) 335 { 336 struct wcn36xx *wcn = hw->priv; 337 struct ieee80211_vif *vif = NULL; 338 struct wcn36xx_vif *tmp; 339 340 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac config changed 0x%08x\n", changed); 341 342 if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { 343 int ch = WCN36XX_HW_CHANNEL(wcn); 344 wcn36xx_dbg(WCN36XX_DBG_MAC, "wcn36xx_config channel switch=%d\n", 345 ch); 346 list_for_each_entry(tmp, &wcn->vif_list, list) { 347 vif = container_of((void *)tmp, 348 struct ieee80211_vif, 349 drv_priv); 350 wcn36xx_smd_switch_channel(wcn, vif, ch); 351 } 352 } 353 354 return 0; 355 } 356 357 #define WCN36XX_SUPPORTED_FILTERS (0) 358 359 static void wcn36xx_configure_filter(struct ieee80211_hw *hw, 360 unsigned int changed, 361 unsigned int *total, u64 multicast) 362 { 363 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac configure filter\n"); 364 365 *total &= WCN36XX_SUPPORTED_FILTERS; 366 } 367 368 static void wcn36xx_tx(struct ieee80211_hw *hw, 369 struct ieee80211_tx_control *control, 370 struct sk_buff *skb) 371 { 372 struct wcn36xx *wcn = hw->priv; 373 struct wcn36xx_sta *sta_priv = NULL; 374 375 if (control->sta) 376 sta_priv = (struct wcn36xx_sta *)control->sta->drv_priv; 377 378 if (wcn36xx_start_tx(wcn, sta_priv, skb)) 379 ieee80211_free_txskb(wcn->hw, skb); 380 } 381 382 static int wcn36xx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, 383 struct ieee80211_vif *vif, 384 struct ieee80211_sta *sta, 385 struct ieee80211_key_conf *key_conf) 386 { 387 struct wcn36xx *wcn = hw->priv; 388 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 389 struct wcn36xx_sta *sta_priv = vif_priv->sta; 390 int ret = 0; 391 u8 key[WLAN_MAX_KEY_LEN]; 392 393 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac80211 set key\n"); 394 wcn36xx_dbg(WCN36XX_DBG_MAC, "Key: cmd=0x%x algo:0x%x, id:%d, len:%d flags 0x%x\n", 395 cmd, key_conf->cipher, key_conf->keyidx, 396 key_conf->keylen, key_conf->flags); 397 wcn36xx_dbg_dump(WCN36XX_DBG_MAC, "KEY: ", 398 key_conf->key, 399 key_conf->keylen); 400 401 switch (key_conf->cipher) { 402 case WLAN_CIPHER_SUITE_WEP40: 403 vif_priv->encrypt_type = WCN36XX_HAL_ED_WEP40; 404 break; 405 case WLAN_CIPHER_SUITE_WEP104: 406 vif_priv->encrypt_type = WCN36XX_HAL_ED_WEP40; 407 break; 408 case WLAN_CIPHER_SUITE_CCMP: 409 vif_priv->encrypt_type = WCN36XX_HAL_ED_CCMP; 410 break; 411 case WLAN_CIPHER_SUITE_TKIP: 412 vif_priv->encrypt_type = WCN36XX_HAL_ED_TKIP; 413 break; 414 default: 415 wcn36xx_err("Unsupported key type 0x%x\n", 416 key_conf->cipher); 417 ret = -EOPNOTSUPP; 418 goto out; 419 } 420 421 switch (cmd) { 422 case SET_KEY: 423 if (WCN36XX_HAL_ED_TKIP == vif_priv->encrypt_type) { 424 /* 425 * Supplicant is sending key in the wrong order: 426 * Temporal Key (16 b) - TX MIC (8 b) - RX MIC (8 b) 427 * but HW expects it to be in the order as described in 428 * IEEE 802.11 spec (see chapter 11.7) like this: 429 * Temporal Key (16 b) - RX MIC (8 b) - TX MIC (8 b) 430 */ 431 memcpy(key, key_conf->key, 16); 432 memcpy(key + 16, key_conf->key + 24, 8); 433 memcpy(key + 24, key_conf->key + 16, 8); 434 } else { 435 memcpy(key, key_conf->key, key_conf->keylen); 436 } 437 438 if (IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags) { 439 sta_priv->is_data_encrypted = true; 440 /* Reconfigure bss with encrypt_type */ 441 if (NL80211_IFTYPE_STATION == vif->type) 442 wcn36xx_smd_config_bss(wcn, 443 vif, 444 sta, 445 sta->addr, 446 true); 447 448 wcn36xx_smd_set_stakey(wcn, 449 vif_priv->encrypt_type, 450 key_conf->keyidx, 451 key_conf->keylen, 452 key, 453 get_sta_index(vif, sta_priv)); 454 } else { 455 wcn36xx_smd_set_bsskey(wcn, 456 vif_priv->encrypt_type, 457 key_conf->keyidx, 458 key_conf->keylen, 459 key); 460 if ((WLAN_CIPHER_SUITE_WEP40 == key_conf->cipher) || 461 (WLAN_CIPHER_SUITE_WEP104 == key_conf->cipher)) { 462 sta_priv->is_data_encrypted = true; 463 wcn36xx_smd_set_stakey(wcn, 464 vif_priv->encrypt_type, 465 key_conf->keyidx, 466 key_conf->keylen, 467 key, 468 get_sta_index(vif, sta_priv)); 469 } 470 } 471 break; 472 case DISABLE_KEY: 473 if (!(IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags)) { 474 wcn36xx_smd_remove_bsskey(wcn, 475 vif_priv->encrypt_type, 476 key_conf->keyidx); 477 } else { 478 sta_priv->is_data_encrypted = false; 479 /* do not remove key if disassociated */ 480 if (sta_priv->aid) 481 wcn36xx_smd_remove_stakey(wcn, 482 vif_priv->encrypt_type, 483 key_conf->keyidx, 484 get_sta_index(vif, sta_priv)); 485 } 486 break; 487 default: 488 wcn36xx_err("Unsupported key cmd 0x%x\n", cmd); 489 ret = -EOPNOTSUPP; 490 goto out; 491 } 492 493 out: 494 return ret; 495 } 496 497 static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw) 498 { 499 struct wcn36xx *wcn = hw->priv; 500 501 wcn36xx_smd_init_scan(wcn, HAL_SYS_MODE_SCAN); 502 wcn36xx_smd_start_scan(wcn); 503 } 504 505 static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw) 506 { 507 struct wcn36xx *wcn = hw->priv; 508 509 wcn36xx_smd_end_scan(wcn); 510 wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN); 511 } 512 513 static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta, 514 enum ieee80211_band band) 515 { 516 int i, size; 517 u16 *rates_table; 518 struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv; 519 u32 rates = sta->supp_rates[band]; 520 521 memset(&sta_priv->supported_rates, 0, 522 sizeof(sta_priv->supported_rates)); 523 sta_priv->supported_rates.op_rate_mode = STA_11n; 524 525 size = ARRAY_SIZE(sta_priv->supported_rates.dsss_rates); 526 rates_table = sta_priv->supported_rates.dsss_rates; 527 if (band == IEEE80211_BAND_2GHZ) { 528 for (i = 0; i < size; i++) { 529 if (rates & 0x01) { 530 rates_table[i] = wcn_2ghz_rates[i].hw_value; 531 rates = rates >> 1; 532 } 533 } 534 } 535 536 size = ARRAY_SIZE(sta_priv->supported_rates.ofdm_rates); 537 rates_table = sta_priv->supported_rates.ofdm_rates; 538 for (i = 0; i < size; i++) { 539 if (rates & 0x01) { 540 rates_table[i] = wcn_5ghz_rates[i].hw_value; 541 rates = rates >> 1; 542 } 543 } 544 545 if (sta->ht_cap.ht_supported) { 546 BUILD_BUG_ON(sizeof(sta->ht_cap.mcs.rx_mask) > 547 sizeof(sta_priv->supported_rates.supported_mcs_set)); 548 memcpy(sta_priv->supported_rates.supported_mcs_set, 549 sta->ht_cap.mcs.rx_mask, 550 sizeof(sta->ht_cap.mcs.rx_mask)); 551 } 552 } 553 void wcn36xx_set_default_rates(struct wcn36xx_hal_supported_rates *rates) 554 { 555 u16 ofdm_rates[WCN36XX_HAL_NUM_OFDM_RATES] = { 556 HW_RATE_INDEX_6MBPS, 557 HW_RATE_INDEX_9MBPS, 558 HW_RATE_INDEX_12MBPS, 559 HW_RATE_INDEX_18MBPS, 560 HW_RATE_INDEX_24MBPS, 561 HW_RATE_INDEX_36MBPS, 562 HW_RATE_INDEX_48MBPS, 563 HW_RATE_INDEX_54MBPS 564 }; 565 u16 dsss_rates[WCN36XX_HAL_NUM_DSSS_RATES] = { 566 HW_RATE_INDEX_1MBPS, 567 HW_RATE_INDEX_2MBPS, 568 HW_RATE_INDEX_5_5MBPS, 569 HW_RATE_INDEX_11MBPS 570 }; 571 572 rates->op_rate_mode = STA_11n; 573 memcpy(rates->dsss_rates, dsss_rates, 574 sizeof(*dsss_rates) * WCN36XX_HAL_NUM_DSSS_RATES); 575 memcpy(rates->ofdm_rates, ofdm_rates, 576 sizeof(*ofdm_rates) * WCN36XX_HAL_NUM_OFDM_RATES); 577 rates->supported_mcs_set[0] = 0xFF; 578 } 579 static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw, 580 struct ieee80211_vif *vif, 581 struct ieee80211_bss_conf *bss_conf, 582 u32 changed) 583 { 584 struct wcn36xx *wcn = hw->priv; 585 struct sk_buff *skb = NULL; 586 u16 tim_off, tim_len; 587 enum wcn36xx_hal_link_state link_state; 588 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 589 590 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss info changed vif %p changed 0x%08x\n", 591 vif, changed); 592 593 if (changed & BSS_CHANGED_BEACON_INFO) { 594 wcn36xx_dbg(WCN36XX_DBG_MAC, 595 "mac bss changed dtim period %d\n", 596 bss_conf->dtim_period); 597 598 vif_priv->dtim_period = bss_conf->dtim_period; 599 } 600 601 if (changed & BSS_CHANGED_PS) { 602 wcn36xx_dbg(WCN36XX_DBG_MAC, 603 "mac bss PS set %d\n", 604 bss_conf->ps); 605 if (bss_conf->ps) { 606 wcn36xx_pmc_enter_bmps_state(wcn, vif); 607 } else { 608 wcn36xx_pmc_exit_bmps_state(wcn, vif); 609 } 610 } 611 612 if (changed & BSS_CHANGED_BSSID) { 613 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss changed_bssid %pM\n", 614 bss_conf->bssid); 615 616 if (!is_zero_ether_addr(bss_conf->bssid)) { 617 vif_priv->is_joining = true; 618 vif_priv->bss_index = 0xff; 619 wcn36xx_smd_join(wcn, bss_conf->bssid, 620 vif->addr, WCN36XX_HW_CHANNEL(wcn)); 621 wcn36xx_smd_config_bss(wcn, vif, NULL, 622 bss_conf->bssid, false); 623 } else { 624 vif_priv->is_joining = false; 625 wcn36xx_smd_delete_bss(wcn, vif); 626 } 627 } 628 629 if (changed & BSS_CHANGED_SSID) { 630 wcn36xx_dbg(WCN36XX_DBG_MAC, 631 "mac bss changed ssid\n"); 632 wcn36xx_dbg_dump(WCN36XX_DBG_MAC, "ssid ", 633 bss_conf->ssid, bss_conf->ssid_len); 634 635 vif_priv->ssid.length = bss_conf->ssid_len; 636 memcpy(&vif_priv->ssid.ssid, 637 bss_conf->ssid, 638 bss_conf->ssid_len); 639 } 640 641 if (changed & BSS_CHANGED_ASSOC) { 642 vif_priv->is_joining = false; 643 if (bss_conf->assoc) { 644 struct ieee80211_sta *sta; 645 struct wcn36xx_sta *sta_priv; 646 647 wcn36xx_dbg(WCN36XX_DBG_MAC, 648 "mac assoc bss %pM vif %pM AID=%d\n", 649 bss_conf->bssid, 650 vif->addr, 651 bss_conf->aid); 652 653 rcu_read_lock(); 654 sta = ieee80211_find_sta(vif, bss_conf->bssid); 655 if (!sta) { 656 wcn36xx_err("sta %pM is not found\n", 657 bss_conf->bssid); 658 rcu_read_unlock(); 659 goto out; 660 } 661 sta_priv = (struct wcn36xx_sta *)sta->drv_priv; 662 663 wcn36xx_update_allowed_rates(sta, WCN36XX_BAND(wcn)); 664 665 wcn36xx_smd_set_link_st(wcn, bss_conf->bssid, 666 vif->addr, 667 WCN36XX_HAL_LINK_POSTASSOC_STATE); 668 wcn36xx_smd_config_bss(wcn, vif, sta, 669 bss_conf->bssid, 670 true); 671 sta_priv->aid = bss_conf->aid; 672 /* 673 * config_sta must be called from because this is the 674 * place where AID is available. 675 */ 676 wcn36xx_smd_config_sta(wcn, vif, sta); 677 rcu_read_unlock(); 678 } else { 679 wcn36xx_dbg(WCN36XX_DBG_MAC, 680 "disassociated bss %pM vif %pM AID=%d\n", 681 bss_conf->bssid, 682 vif->addr, 683 bss_conf->aid); 684 wcn36xx_smd_set_link_st(wcn, 685 bss_conf->bssid, 686 vif->addr, 687 WCN36XX_HAL_LINK_IDLE_STATE); 688 } 689 } 690 691 if (changed & BSS_CHANGED_AP_PROBE_RESP) { 692 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss changed ap probe resp\n"); 693 skb = ieee80211_proberesp_get(hw, vif); 694 if (!skb) { 695 wcn36xx_err("failed to alloc probereq skb\n"); 696 goto out; 697 } 698 699 wcn36xx_smd_update_proberesp_tmpl(wcn, vif, skb); 700 dev_kfree_skb(skb); 701 } 702 703 if (changed & BSS_CHANGED_BEACON_ENABLED || 704 changed & BSS_CHANGED_BEACON) { 705 wcn36xx_dbg(WCN36XX_DBG_MAC, 706 "mac bss changed beacon enabled %d\n", 707 bss_conf->enable_beacon); 708 709 if (bss_conf->enable_beacon) { 710 vif_priv->dtim_period = bss_conf->dtim_period; 711 vif_priv->bss_index = 0xff; 712 wcn36xx_smd_config_bss(wcn, vif, NULL, 713 vif->addr, false); 714 skb = ieee80211_beacon_get_tim(hw, vif, &tim_off, 715 &tim_len); 716 if (!skb) { 717 wcn36xx_err("failed to alloc beacon skb\n"); 718 goto out; 719 } 720 wcn36xx_smd_send_beacon(wcn, vif, skb, tim_off, 0); 721 dev_kfree_skb(skb); 722 723 if (vif->type == NL80211_IFTYPE_ADHOC || 724 vif->type == NL80211_IFTYPE_MESH_POINT) 725 link_state = WCN36XX_HAL_LINK_IBSS_STATE; 726 else 727 link_state = WCN36XX_HAL_LINK_AP_STATE; 728 729 wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr, 730 link_state); 731 } else { 732 wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr, 733 WCN36XX_HAL_LINK_IDLE_STATE); 734 wcn36xx_smd_delete_bss(wcn, vif); 735 } 736 } 737 out: 738 return; 739 } 740 741 /* this is required when using IEEE80211_HW_HAS_RATE_CONTROL */ 742 static int wcn36xx_set_rts_threshold(struct ieee80211_hw *hw, u32 value) 743 { 744 struct wcn36xx *wcn = hw->priv; 745 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac set RTS threshold %d\n", value); 746 747 wcn36xx_smd_update_cfg(wcn, WCN36XX_HAL_CFG_RTS_THRESHOLD, value); 748 return 0; 749 } 750 751 static void wcn36xx_remove_interface(struct ieee80211_hw *hw, 752 struct ieee80211_vif *vif) 753 { 754 struct wcn36xx *wcn = hw->priv; 755 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 756 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac remove interface vif %p\n", vif); 757 758 list_del(&vif_priv->list); 759 wcn36xx_smd_delete_sta_self(wcn, vif->addr); 760 } 761 762 static int wcn36xx_add_interface(struct ieee80211_hw *hw, 763 struct ieee80211_vif *vif) 764 { 765 struct wcn36xx *wcn = hw->priv; 766 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 767 768 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac add interface vif %p type %d\n", 769 vif, vif->type); 770 771 if (!(NL80211_IFTYPE_STATION == vif->type || 772 NL80211_IFTYPE_AP == vif->type || 773 NL80211_IFTYPE_ADHOC == vif->type || 774 NL80211_IFTYPE_MESH_POINT == vif->type)) { 775 wcn36xx_warn("Unsupported interface type requested: %d\n", 776 vif->type); 777 return -EOPNOTSUPP; 778 } 779 780 list_add(&vif_priv->list, &wcn->vif_list); 781 wcn36xx_smd_add_sta_self(wcn, vif); 782 783 return 0; 784 } 785 786 static int wcn36xx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 787 struct ieee80211_sta *sta) 788 { 789 struct wcn36xx *wcn = hw->priv; 790 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 791 struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv; 792 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta add vif %p sta %pM\n", 793 vif, sta->addr); 794 795 vif_priv->sta = sta_priv; 796 sta_priv->vif = vif_priv; 797 /* 798 * For STA mode HW will be configured on BSS_CHANGED_ASSOC because 799 * at this stage AID is not available yet. 800 */ 801 if (NL80211_IFTYPE_STATION != vif->type) { 802 wcn36xx_update_allowed_rates(sta, WCN36XX_BAND(wcn)); 803 sta_priv->aid = sta->aid; 804 wcn36xx_smd_config_sta(wcn, vif, sta); 805 } 806 return 0; 807 } 808 809 static int wcn36xx_sta_remove(struct ieee80211_hw *hw, 810 struct ieee80211_vif *vif, 811 struct ieee80211_sta *sta) 812 { 813 struct wcn36xx *wcn = hw->priv; 814 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 815 struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv; 816 817 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta remove vif %p sta %pM index %d\n", 818 vif, sta->addr, sta_priv->sta_index); 819 820 wcn36xx_smd_delete_sta(wcn, sta_priv->sta_index); 821 vif_priv->sta = NULL; 822 sta_priv->vif = NULL; 823 return 0; 824 } 825 826 #ifdef CONFIG_PM 827 828 static int wcn36xx_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wow) 829 { 830 struct wcn36xx *wcn = hw->priv; 831 832 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac suspend\n"); 833 834 flush_workqueue(wcn->hal_ind_wq); 835 wcn36xx_smd_set_power_params(wcn, true); 836 return 0; 837 } 838 839 static int wcn36xx_resume(struct ieee80211_hw *hw) 840 { 841 struct wcn36xx *wcn = hw->priv; 842 843 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac resume\n"); 844 845 flush_workqueue(wcn->hal_ind_wq); 846 wcn36xx_smd_set_power_params(wcn, false); 847 return 0; 848 } 849 850 #endif 851 852 static int wcn36xx_ampdu_action(struct ieee80211_hw *hw, 853 struct ieee80211_vif *vif, 854 enum ieee80211_ampdu_mlme_action action, 855 struct ieee80211_sta *sta, u16 tid, u16 *ssn, 856 u8 buf_size) 857 { 858 struct wcn36xx *wcn = hw->priv; 859 struct wcn36xx_sta *sta_priv = NULL; 860 861 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu action action %d tid %d\n", 862 action, tid); 863 864 sta_priv = (struct wcn36xx_sta *)sta->drv_priv; 865 866 switch (action) { 867 case IEEE80211_AMPDU_RX_START: 868 sta_priv->tid = tid; 869 wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 0, 870 get_sta_index(vif, sta_priv)); 871 wcn36xx_smd_add_ba(wcn); 872 wcn36xx_smd_trigger_ba(wcn, get_sta_index(vif, sta_priv)); 873 ieee80211_start_tx_ba_session(sta, tid, 0); 874 break; 875 case IEEE80211_AMPDU_RX_STOP: 876 wcn36xx_smd_del_ba(wcn, tid, get_sta_index(vif, sta_priv)); 877 break; 878 case IEEE80211_AMPDU_TX_START: 879 ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); 880 break; 881 case IEEE80211_AMPDU_TX_OPERATIONAL: 882 wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 1, 883 get_sta_index(vif, sta_priv)); 884 break; 885 case IEEE80211_AMPDU_TX_STOP_FLUSH: 886 case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: 887 case IEEE80211_AMPDU_TX_STOP_CONT: 888 ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); 889 break; 890 default: 891 wcn36xx_err("Unknown AMPDU action\n"); 892 } 893 894 return 0; 895 } 896 897 static const struct ieee80211_ops wcn36xx_ops = { 898 .start = wcn36xx_start, 899 .stop = wcn36xx_stop, 900 .add_interface = wcn36xx_add_interface, 901 .remove_interface = wcn36xx_remove_interface, 902 #ifdef CONFIG_PM 903 .suspend = wcn36xx_suspend, 904 .resume = wcn36xx_resume, 905 #endif 906 .config = wcn36xx_config, 907 .configure_filter = wcn36xx_configure_filter, 908 .tx = wcn36xx_tx, 909 .set_key = wcn36xx_set_key, 910 .sw_scan_start = wcn36xx_sw_scan_start, 911 .sw_scan_complete = wcn36xx_sw_scan_complete, 912 .bss_info_changed = wcn36xx_bss_info_changed, 913 .set_rts_threshold = wcn36xx_set_rts_threshold, 914 .sta_add = wcn36xx_sta_add, 915 .sta_remove = wcn36xx_sta_remove, 916 .ampdu_action = wcn36xx_ampdu_action, 917 }; 918 919 static int wcn36xx_init_ieee80211(struct wcn36xx *wcn) 920 { 921 int ret = 0; 922 923 static const u32 cipher_suites[] = { 924 WLAN_CIPHER_SUITE_WEP40, 925 WLAN_CIPHER_SUITE_WEP104, 926 WLAN_CIPHER_SUITE_TKIP, 927 WLAN_CIPHER_SUITE_CCMP, 928 }; 929 930 wcn->hw->flags = IEEE80211_HW_SIGNAL_DBM | 931 IEEE80211_HW_HAS_RATE_CONTROL | 932 IEEE80211_HW_SUPPORTS_PS | 933 IEEE80211_HW_CONNECTION_MONITOR | 934 IEEE80211_HW_AMPDU_AGGREGATION | 935 IEEE80211_HW_TIMING_BEACON_ONLY; 936 937 wcn->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | 938 BIT(NL80211_IFTYPE_AP) | 939 BIT(NL80211_IFTYPE_ADHOC) | 940 BIT(NL80211_IFTYPE_MESH_POINT); 941 942 wcn->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wcn_band_2ghz; 943 wcn->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wcn_band_5ghz; 944 945 wcn->hw->wiphy->cipher_suites = cipher_suites; 946 wcn->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); 947 948 wcn->hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; 949 950 #ifdef CONFIG_PM 951 wcn->hw->wiphy->wowlan = &wowlan_support; 952 #endif 953 954 wcn->hw->max_listen_interval = 200; 955 956 wcn->hw->queues = 4; 957 958 SET_IEEE80211_DEV(wcn->hw, wcn->dev); 959 960 wcn->hw->sta_data_size = sizeof(struct wcn36xx_sta); 961 wcn->hw->vif_data_size = sizeof(struct wcn36xx_vif); 962 963 return ret; 964 } 965 966 static int wcn36xx_platform_get_resources(struct wcn36xx *wcn, 967 struct platform_device *pdev) 968 { 969 struct resource *res; 970 /* Set TX IRQ */ 971 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, 972 "wcnss_wlantx_irq"); 973 if (!res) { 974 wcn36xx_err("failed to get tx_irq\n"); 975 return -ENOENT; 976 } 977 wcn->tx_irq = res->start; 978 979 /* Set RX IRQ */ 980 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, 981 "wcnss_wlanrx_irq"); 982 if (!res) { 983 wcn36xx_err("failed to get rx_irq\n"); 984 return -ENOENT; 985 } 986 wcn->rx_irq = res->start; 987 988 /* Map the memory */ 989 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, 990 "wcnss_mmio"); 991 if (!res) { 992 wcn36xx_err("failed to get mmio\n"); 993 return -ENOENT; 994 } 995 wcn->mmio = ioremap(res->start, resource_size(res)); 996 if (!wcn->mmio) { 997 wcn36xx_err("failed to map io memory\n"); 998 return -ENOMEM; 999 } 1000 return 0; 1001 } 1002 1003 static int wcn36xx_probe(struct platform_device *pdev) 1004 { 1005 struct ieee80211_hw *hw; 1006 struct wcn36xx *wcn; 1007 int ret; 1008 u8 addr[ETH_ALEN]; 1009 1010 wcn36xx_dbg(WCN36XX_DBG_MAC, "platform probe\n"); 1011 1012 hw = ieee80211_alloc_hw(sizeof(struct wcn36xx), &wcn36xx_ops); 1013 if (!hw) { 1014 wcn36xx_err("failed to alloc hw\n"); 1015 ret = -ENOMEM; 1016 goto out_err; 1017 } 1018 platform_set_drvdata(pdev, hw); 1019 wcn = hw->priv; 1020 wcn->hw = hw; 1021 wcn->dev = &pdev->dev; 1022 wcn->ctrl_ops = pdev->dev.platform_data; 1023 1024 mutex_init(&wcn->hal_mutex); 1025 1026 if (!wcn->ctrl_ops->get_hw_mac(addr)) { 1027 wcn36xx_info("mac address: %pM\n", addr); 1028 SET_IEEE80211_PERM_ADDR(wcn->hw, addr); 1029 } 1030 1031 ret = wcn36xx_platform_get_resources(wcn, pdev); 1032 if (ret) 1033 goto out_wq; 1034 1035 wcn36xx_init_ieee80211(wcn); 1036 ret = ieee80211_register_hw(wcn->hw); 1037 if (ret) 1038 goto out_unmap; 1039 1040 return 0; 1041 1042 out_unmap: 1043 iounmap(wcn->mmio); 1044 out_wq: 1045 ieee80211_free_hw(hw); 1046 out_err: 1047 return ret; 1048 } 1049 static int wcn36xx_remove(struct platform_device *pdev) 1050 { 1051 struct ieee80211_hw *hw = platform_get_drvdata(pdev); 1052 struct wcn36xx *wcn = hw->priv; 1053 wcn36xx_dbg(WCN36XX_DBG_MAC, "platform remove\n"); 1054 1055 release_firmware(wcn->nv); 1056 mutex_destroy(&wcn->hal_mutex); 1057 1058 ieee80211_unregister_hw(hw); 1059 iounmap(wcn->mmio); 1060 ieee80211_free_hw(hw); 1061 1062 return 0; 1063 } 1064 static const struct platform_device_id wcn36xx_platform_id_table[] = { 1065 { 1066 .name = "wcn36xx", 1067 .driver_data = 0 1068 }, 1069 {} 1070 }; 1071 MODULE_DEVICE_TABLE(platform, wcn36xx_platform_id_table); 1072 1073 static struct platform_driver wcn36xx_driver = { 1074 .probe = wcn36xx_probe, 1075 .remove = wcn36xx_remove, 1076 .driver = { 1077 .name = "wcn36xx", 1078 .owner = THIS_MODULE, 1079 }, 1080 .id_table = wcn36xx_platform_id_table, 1081 }; 1082 1083 static int __init wcn36xx_init(void) 1084 { 1085 platform_driver_register(&wcn36xx_driver); 1086 return 0; 1087 } 1088 module_init(wcn36xx_init); 1089 1090 static void __exit wcn36xx_exit(void) 1091 { 1092 platform_driver_unregister(&wcn36xx_driver); 1093 } 1094 module_exit(wcn36xx_exit); 1095 1096 MODULE_LICENSE("Dual BSD/GPL"); 1097 MODULE_AUTHOR("Eugene Krasnikov k.eugene.e@gmail.com"); 1098 MODULE_FIRMWARE(WLAN_NV_FILE); 1099