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 spin_lock_init(&wcn->dxe_lock); 302 303 return 0; 304 305 out_smd_stop: 306 wcn36xx_smd_stop(wcn); 307 out_free_smd_buf: 308 kfree(wcn->hal_buf); 309 out_free_dxe_pool: 310 wcn36xx_dxe_free_mem_pools(wcn); 311 out_free_dxe_ctl: 312 wcn36xx_dxe_free_ctl_blks(wcn); 313 out_smd_close: 314 wcn36xx_smd_close(wcn); 315 out_err: 316 return ret; 317 } 318 319 static void wcn36xx_stop(struct ieee80211_hw *hw) 320 { 321 struct wcn36xx *wcn = hw->priv; 322 323 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac stop\n"); 324 325 wcn36xx_debugfs_exit(wcn); 326 wcn36xx_smd_stop(wcn); 327 wcn36xx_dxe_deinit(wcn); 328 wcn36xx_smd_close(wcn); 329 330 wcn36xx_dxe_free_mem_pools(wcn); 331 wcn36xx_dxe_free_ctl_blks(wcn); 332 333 kfree(wcn->hal_buf); 334 } 335 336 static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed) 337 { 338 struct wcn36xx *wcn = hw->priv; 339 struct ieee80211_vif *vif = NULL; 340 struct wcn36xx_vif *tmp; 341 342 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac config changed 0x%08x\n", changed); 343 344 if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { 345 int ch = WCN36XX_HW_CHANNEL(wcn); 346 wcn36xx_dbg(WCN36XX_DBG_MAC, "wcn36xx_config channel switch=%d\n", 347 ch); 348 list_for_each_entry(tmp, &wcn->vif_list, list) { 349 vif = container_of((void *)tmp, 350 struct ieee80211_vif, 351 drv_priv); 352 wcn36xx_smd_switch_channel(wcn, vif, ch); 353 } 354 } 355 356 return 0; 357 } 358 359 #define WCN36XX_SUPPORTED_FILTERS (0) 360 361 static void wcn36xx_configure_filter(struct ieee80211_hw *hw, 362 unsigned int changed, 363 unsigned int *total, u64 multicast) 364 { 365 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac configure filter\n"); 366 367 *total &= WCN36XX_SUPPORTED_FILTERS; 368 } 369 370 static void wcn36xx_tx(struct ieee80211_hw *hw, 371 struct ieee80211_tx_control *control, 372 struct sk_buff *skb) 373 { 374 struct wcn36xx *wcn = hw->priv; 375 struct wcn36xx_sta *sta_priv = NULL; 376 377 if (control->sta) 378 sta_priv = (struct wcn36xx_sta *)control->sta->drv_priv; 379 380 if (wcn36xx_start_tx(wcn, sta_priv, skb)) 381 ieee80211_free_txskb(wcn->hw, skb); 382 } 383 384 static int wcn36xx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, 385 struct ieee80211_vif *vif, 386 struct ieee80211_sta *sta, 387 struct ieee80211_key_conf *key_conf) 388 { 389 struct wcn36xx *wcn = hw->priv; 390 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 391 struct wcn36xx_sta *sta_priv = vif_priv->sta; 392 int ret = 0; 393 u8 key[WLAN_MAX_KEY_LEN]; 394 395 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac80211 set key\n"); 396 wcn36xx_dbg(WCN36XX_DBG_MAC, "Key: cmd=0x%x algo:0x%x, id:%d, len:%d flags 0x%x\n", 397 cmd, key_conf->cipher, key_conf->keyidx, 398 key_conf->keylen, key_conf->flags); 399 wcn36xx_dbg_dump(WCN36XX_DBG_MAC, "KEY: ", 400 key_conf->key, 401 key_conf->keylen); 402 403 switch (key_conf->cipher) { 404 case WLAN_CIPHER_SUITE_WEP40: 405 vif_priv->encrypt_type = WCN36XX_HAL_ED_WEP40; 406 break; 407 case WLAN_CIPHER_SUITE_WEP104: 408 vif_priv->encrypt_type = WCN36XX_HAL_ED_WEP40; 409 break; 410 case WLAN_CIPHER_SUITE_CCMP: 411 vif_priv->encrypt_type = WCN36XX_HAL_ED_CCMP; 412 break; 413 case WLAN_CIPHER_SUITE_TKIP: 414 vif_priv->encrypt_type = WCN36XX_HAL_ED_TKIP; 415 break; 416 default: 417 wcn36xx_err("Unsupported key type 0x%x\n", 418 key_conf->cipher); 419 ret = -EOPNOTSUPP; 420 goto out; 421 } 422 423 switch (cmd) { 424 case SET_KEY: 425 if (WCN36XX_HAL_ED_TKIP == vif_priv->encrypt_type) { 426 /* 427 * Supplicant is sending key in the wrong order: 428 * Temporal Key (16 b) - TX MIC (8 b) - RX MIC (8 b) 429 * but HW expects it to be in the order as described in 430 * IEEE 802.11 spec (see chapter 11.7) like this: 431 * Temporal Key (16 b) - RX MIC (8 b) - TX MIC (8 b) 432 */ 433 memcpy(key, key_conf->key, 16); 434 memcpy(key + 16, key_conf->key + 24, 8); 435 memcpy(key + 24, key_conf->key + 16, 8); 436 } else { 437 memcpy(key, key_conf->key, key_conf->keylen); 438 } 439 440 if (IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags) { 441 sta_priv->is_data_encrypted = true; 442 /* Reconfigure bss with encrypt_type */ 443 if (NL80211_IFTYPE_STATION == vif->type) 444 wcn36xx_smd_config_bss(wcn, 445 vif, 446 sta, 447 sta->addr, 448 true); 449 450 wcn36xx_smd_set_stakey(wcn, 451 vif_priv->encrypt_type, 452 key_conf->keyidx, 453 key_conf->keylen, 454 key, 455 get_sta_index(vif, sta_priv)); 456 } else { 457 wcn36xx_smd_set_bsskey(wcn, 458 vif_priv->encrypt_type, 459 key_conf->keyidx, 460 key_conf->keylen, 461 key); 462 if ((WLAN_CIPHER_SUITE_WEP40 == key_conf->cipher) || 463 (WLAN_CIPHER_SUITE_WEP104 == key_conf->cipher)) { 464 sta_priv->is_data_encrypted = true; 465 wcn36xx_smd_set_stakey(wcn, 466 vif_priv->encrypt_type, 467 key_conf->keyidx, 468 key_conf->keylen, 469 key, 470 get_sta_index(vif, sta_priv)); 471 } 472 } 473 break; 474 case DISABLE_KEY: 475 if (!(IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags)) { 476 wcn36xx_smd_remove_bsskey(wcn, 477 vif_priv->encrypt_type, 478 key_conf->keyidx); 479 } else { 480 sta_priv->is_data_encrypted = false; 481 /* do not remove key if disassociated */ 482 if (sta_priv->aid) 483 wcn36xx_smd_remove_stakey(wcn, 484 vif_priv->encrypt_type, 485 key_conf->keyidx, 486 get_sta_index(vif, sta_priv)); 487 } 488 break; 489 default: 490 wcn36xx_err("Unsupported key cmd 0x%x\n", cmd); 491 ret = -EOPNOTSUPP; 492 goto out; 493 } 494 495 out: 496 return ret; 497 } 498 499 static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw, 500 struct ieee80211_vif *vif, 501 const u8 *mac_addr) 502 { 503 struct wcn36xx *wcn = hw->priv; 504 505 wcn36xx_smd_init_scan(wcn, HAL_SYS_MODE_SCAN); 506 wcn36xx_smd_start_scan(wcn); 507 } 508 509 static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw, 510 struct ieee80211_vif *vif) 511 { 512 struct wcn36xx *wcn = hw->priv; 513 514 wcn36xx_smd_end_scan(wcn); 515 wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN); 516 } 517 518 static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta, 519 enum ieee80211_band band) 520 { 521 int i, size; 522 u16 *rates_table; 523 struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv; 524 u32 rates = sta->supp_rates[band]; 525 526 memset(&sta_priv->supported_rates, 0, 527 sizeof(sta_priv->supported_rates)); 528 sta_priv->supported_rates.op_rate_mode = STA_11n; 529 530 size = ARRAY_SIZE(sta_priv->supported_rates.dsss_rates); 531 rates_table = sta_priv->supported_rates.dsss_rates; 532 if (band == IEEE80211_BAND_2GHZ) { 533 for (i = 0; i < size; i++) { 534 if (rates & 0x01) { 535 rates_table[i] = wcn_2ghz_rates[i].hw_value; 536 rates = rates >> 1; 537 } 538 } 539 } 540 541 size = ARRAY_SIZE(sta_priv->supported_rates.ofdm_rates); 542 rates_table = sta_priv->supported_rates.ofdm_rates; 543 for (i = 0; i < size; i++) { 544 if (rates & 0x01) { 545 rates_table[i] = wcn_5ghz_rates[i].hw_value; 546 rates = rates >> 1; 547 } 548 } 549 550 if (sta->ht_cap.ht_supported) { 551 BUILD_BUG_ON(sizeof(sta->ht_cap.mcs.rx_mask) > 552 sizeof(sta_priv->supported_rates.supported_mcs_set)); 553 memcpy(sta_priv->supported_rates.supported_mcs_set, 554 sta->ht_cap.mcs.rx_mask, 555 sizeof(sta->ht_cap.mcs.rx_mask)); 556 } 557 } 558 void wcn36xx_set_default_rates(struct wcn36xx_hal_supported_rates *rates) 559 { 560 u16 ofdm_rates[WCN36XX_HAL_NUM_OFDM_RATES] = { 561 HW_RATE_INDEX_6MBPS, 562 HW_RATE_INDEX_9MBPS, 563 HW_RATE_INDEX_12MBPS, 564 HW_RATE_INDEX_18MBPS, 565 HW_RATE_INDEX_24MBPS, 566 HW_RATE_INDEX_36MBPS, 567 HW_RATE_INDEX_48MBPS, 568 HW_RATE_INDEX_54MBPS 569 }; 570 u16 dsss_rates[WCN36XX_HAL_NUM_DSSS_RATES] = { 571 HW_RATE_INDEX_1MBPS, 572 HW_RATE_INDEX_2MBPS, 573 HW_RATE_INDEX_5_5MBPS, 574 HW_RATE_INDEX_11MBPS 575 }; 576 577 rates->op_rate_mode = STA_11n; 578 memcpy(rates->dsss_rates, dsss_rates, 579 sizeof(*dsss_rates) * WCN36XX_HAL_NUM_DSSS_RATES); 580 memcpy(rates->ofdm_rates, ofdm_rates, 581 sizeof(*ofdm_rates) * WCN36XX_HAL_NUM_OFDM_RATES); 582 rates->supported_mcs_set[0] = 0xFF; 583 } 584 static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw, 585 struct ieee80211_vif *vif, 586 struct ieee80211_bss_conf *bss_conf, 587 u32 changed) 588 { 589 struct wcn36xx *wcn = hw->priv; 590 struct sk_buff *skb = NULL; 591 u16 tim_off, tim_len; 592 enum wcn36xx_hal_link_state link_state; 593 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 594 595 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss info changed vif %p changed 0x%08x\n", 596 vif, changed); 597 598 if (changed & BSS_CHANGED_BEACON_INFO) { 599 wcn36xx_dbg(WCN36XX_DBG_MAC, 600 "mac bss changed dtim period %d\n", 601 bss_conf->dtim_period); 602 603 vif_priv->dtim_period = bss_conf->dtim_period; 604 } 605 606 if (changed & BSS_CHANGED_PS) { 607 wcn36xx_dbg(WCN36XX_DBG_MAC, 608 "mac bss PS set %d\n", 609 bss_conf->ps); 610 if (bss_conf->ps) { 611 wcn36xx_pmc_enter_bmps_state(wcn, vif); 612 } else { 613 wcn36xx_pmc_exit_bmps_state(wcn, vif); 614 } 615 } 616 617 if (changed & BSS_CHANGED_BSSID) { 618 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss changed_bssid %pM\n", 619 bss_conf->bssid); 620 621 if (!is_zero_ether_addr(bss_conf->bssid)) { 622 vif_priv->is_joining = true; 623 vif_priv->bss_index = 0xff; 624 wcn36xx_smd_join(wcn, bss_conf->bssid, 625 vif->addr, WCN36XX_HW_CHANNEL(wcn)); 626 wcn36xx_smd_config_bss(wcn, vif, NULL, 627 bss_conf->bssid, false); 628 } else { 629 vif_priv->is_joining = false; 630 wcn36xx_smd_delete_bss(wcn, vif); 631 } 632 } 633 634 if (changed & BSS_CHANGED_SSID) { 635 wcn36xx_dbg(WCN36XX_DBG_MAC, 636 "mac bss changed ssid\n"); 637 wcn36xx_dbg_dump(WCN36XX_DBG_MAC, "ssid ", 638 bss_conf->ssid, bss_conf->ssid_len); 639 640 vif_priv->ssid.length = bss_conf->ssid_len; 641 memcpy(&vif_priv->ssid.ssid, 642 bss_conf->ssid, 643 bss_conf->ssid_len); 644 } 645 646 if (changed & BSS_CHANGED_ASSOC) { 647 vif_priv->is_joining = false; 648 if (bss_conf->assoc) { 649 struct ieee80211_sta *sta; 650 struct wcn36xx_sta *sta_priv; 651 652 wcn36xx_dbg(WCN36XX_DBG_MAC, 653 "mac assoc bss %pM vif %pM AID=%d\n", 654 bss_conf->bssid, 655 vif->addr, 656 bss_conf->aid); 657 658 rcu_read_lock(); 659 sta = ieee80211_find_sta(vif, bss_conf->bssid); 660 if (!sta) { 661 wcn36xx_err("sta %pM is not found\n", 662 bss_conf->bssid); 663 rcu_read_unlock(); 664 goto out; 665 } 666 sta_priv = (struct wcn36xx_sta *)sta->drv_priv; 667 668 wcn36xx_update_allowed_rates(sta, WCN36XX_BAND(wcn)); 669 670 wcn36xx_smd_set_link_st(wcn, bss_conf->bssid, 671 vif->addr, 672 WCN36XX_HAL_LINK_POSTASSOC_STATE); 673 wcn36xx_smd_config_bss(wcn, vif, sta, 674 bss_conf->bssid, 675 true); 676 sta_priv->aid = bss_conf->aid; 677 /* 678 * config_sta must be called from because this is the 679 * place where AID is available. 680 */ 681 wcn36xx_smd_config_sta(wcn, vif, sta); 682 rcu_read_unlock(); 683 } else { 684 wcn36xx_dbg(WCN36XX_DBG_MAC, 685 "disassociated bss %pM vif %pM AID=%d\n", 686 bss_conf->bssid, 687 vif->addr, 688 bss_conf->aid); 689 wcn36xx_smd_set_link_st(wcn, 690 bss_conf->bssid, 691 vif->addr, 692 WCN36XX_HAL_LINK_IDLE_STATE); 693 } 694 } 695 696 if (changed & BSS_CHANGED_AP_PROBE_RESP) { 697 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss changed ap probe resp\n"); 698 skb = ieee80211_proberesp_get(hw, vif); 699 if (!skb) { 700 wcn36xx_err("failed to alloc probereq skb\n"); 701 goto out; 702 } 703 704 wcn36xx_smd_update_proberesp_tmpl(wcn, vif, skb); 705 dev_kfree_skb(skb); 706 } 707 708 if (changed & BSS_CHANGED_BEACON_ENABLED || 709 changed & BSS_CHANGED_BEACON) { 710 wcn36xx_dbg(WCN36XX_DBG_MAC, 711 "mac bss changed beacon enabled %d\n", 712 bss_conf->enable_beacon); 713 714 if (bss_conf->enable_beacon) { 715 vif_priv->dtim_period = bss_conf->dtim_period; 716 vif_priv->bss_index = 0xff; 717 wcn36xx_smd_config_bss(wcn, vif, NULL, 718 vif->addr, false); 719 skb = ieee80211_beacon_get_tim(hw, vif, &tim_off, 720 &tim_len); 721 if (!skb) { 722 wcn36xx_err("failed to alloc beacon skb\n"); 723 goto out; 724 } 725 wcn36xx_smd_send_beacon(wcn, vif, skb, tim_off, 0); 726 dev_kfree_skb(skb); 727 728 if (vif->type == NL80211_IFTYPE_ADHOC || 729 vif->type == NL80211_IFTYPE_MESH_POINT) 730 link_state = WCN36XX_HAL_LINK_IBSS_STATE; 731 else 732 link_state = WCN36XX_HAL_LINK_AP_STATE; 733 734 wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr, 735 link_state); 736 } else { 737 wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr, 738 WCN36XX_HAL_LINK_IDLE_STATE); 739 wcn36xx_smd_delete_bss(wcn, vif); 740 } 741 } 742 out: 743 return; 744 } 745 746 /* this is required when using IEEE80211_HW_HAS_RATE_CONTROL */ 747 static int wcn36xx_set_rts_threshold(struct ieee80211_hw *hw, u32 value) 748 { 749 struct wcn36xx *wcn = hw->priv; 750 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac set RTS threshold %d\n", value); 751 752 wcn36xx_smd_update_cfg(wcn, WCN36XX_HAL_CFG_RTS_THRESHOLD, value); 753 return 0; 754 } 755 756 static void wcn36xx_remove_interface(struct ieee80211_hw *hw, 757 struct ieee80211_vif *vif) 758 { 759 struct wcn36xx *wcn = hw->priv; 760 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 761 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac remove interface vif %p\n", vif); 762 763 list_del(&vif_priv->list); 764 wcn36xx_smd_delete_sta_self(wcn, vif->addr); 765 } 766 767 static int wcn36xx_add_interface(struct ieee80211_hw *hw, 768 struct ieee80211_vif *vif) 769 { 770 struct wcn36xx *wcn = hw->priv; 771 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 772 773 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac add interface vif %p type %d\n", 774 vif, vif->type); 775 776 if (!(NL80211_IFTYPE_STATION == vif->type || 777 NL80211_IFTYPE_AP == vif->type || 778 NL80211_IFTYPE_ADHOC == vif->type || 779 NL80211_IFTYPE_MESH_POINT == vif->type)) { 780 wcn36xx_warn("Unsupported interface type requested: %d\n", 781 vif->type); 782 return -EOPNOTSUPP; 783 } 784 785 list_add(&vif_priv->list, &wcn->vif_list); 786 wcn36xx_smd_add_sta_self(wcn, vif); 787 788 return 0; 789 } 790 791 static int wcn36xx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 792 struct ieee80211_sta *sta) 793 { 794 struct wcn36xx *wcn = hw->priv; 795 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 796 struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv; 797 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta add vif %p sta %pM\n", 798 vif, sta->addr); 799 800 spin_lock_init(&sta_priv->ampdu_lock); 801 vif_priv->sta = sta_priv; 802 sta_priv->vif = vif_priv; 803 /* 804 * For STA mode HW will be configured on BSS_CHANGED_ASSOC because 805 * at this stage AID is not available yet. 806 */ 807 if (NL80211_IFTYPE_STATION != vif->type) { 808 wcn36xx_update_allowed_rates(sta, WCN36XX_BAND(wcn)); 809 sta_priv->aid = sta->aid; 810 wcn36xx_smd_config_sta(wcn, vif, sta); 811 } 812 return 0; 813 } 814 815 static int wcn36xx_sta_remove(struct ieee80211_hw *hw, 816 struct ieee80211_vif *vif, 817 struct ieee80211_sta *sta) 818 { 819 struct wcn36xx *wcn = hw->priv; 820 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 821 struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv; 822 823 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta remove vif %p sta %pM index %d\n", 824 vif, sta->addr, sta_priv->sta_index); 825 826 wcn36xx_smd_delete_sta(wcn, sta_priv->sta_index); 827 vif_priv->sta = NULL; 828 sta_priv->vif = NULL; 829 return 0; 830 } 831 832 #ifdef CONFIG_PM 833 834 static int wcn36xx_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wow) 835 { 836 struct wcn36xx *wcn = hw->priv; 837 838 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac suspend\n"); 839 840 flush_workqueue(wcn->hal_ind_wq); 841 wcn36xx_smd_set_power_params(wcn, true); 842 return 0; 843 } 844 845 static int wcn36xx_resume(struct ieee80211_hw *hw) 846 { 847 struct wcn36xx *wcn = hw->priv; 848 849 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac resume\n"); 850 851 flush_workqueue(wcn->hal_ind_wq); 852 wcn36xx_smd_set_power_params(wcn, false); 853 return 0; 854 } 855 856 #endif 857 858 static int wcn36xx_ampdu_action(struct ieee80211_hw *hw, 859 struct ieee80211_vif *vif, 860 enum ieee80211_ampdu_mlme_action action, 861 struct ieee80211_sta *sta, u16 tid, u16 *ssn, 862 u8 buf_size) 863 { 864 struct wcn36xx *wcn = hw->priv; 865 struct wcn36xx_sta *sta_priv = NULL; 866 867 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu action action %d tid %d\n", 868 action, tid); 869 870 sta_priv = (struct wcn36xx_sta *)sta->drv_priv; 871 872 switch (action) { 873 case IEEE80211_AMPDU_RX_START: 874 sta_priv->tid = tid; 875 wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 0, 876 get_sta_index(vif, sta_priv)); 877 wcn36xx_smd_add_ba(wcn); 878 wcn36xx_smd_trigger_ba(wcn, get_sta_index(vif, sta_priv)); 879 break; 880 case IEEE80211_AMPDU_RX_STOP: 881 wcn36xx_smd_del_ba(wcn, tid, get_sta_index(vif, sta_priv)); 882 break; 883 case IEEE80211_AMPDU_TX_START: 884 spin_lock_bh(&sta_priv->ampdu_lock); 885 sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_START; 886 spin_unlock_bh(&sta_priv->ampdu_lock); 887 888 ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); 889 break; 890 case IEEE80211_AMPDU_TX_OPERATIONAL: 891 spin_lock_bh(&sta_priv->ampdu_lock); 892 sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_OPERATIONAL; 893 spin_unlock_bh(&sta_priv->ampdu_lock); 894 895 wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 1, 896 get_sta_index(vif, sta_priv)); 897 break; 898 case IEEE80211_AMPDU_TX_STOP_FLUSH: 899 case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: 900 case IEEE80211_AMPDU_TX_STOP_CONT: 901 spin_lock_bh(&sta_priv->ampdu_lock); 902 sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_NONE; 903 spin_unlock_bh(&sta_priv->ampdu_lock); 904 905 ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); 906 break; 907 default: 908 wcn36xx_err("Unknown AMPDU action\n"); 909 } 910 911 return 0; 912 } 913 914 static const struct ieee80211_ops wcn36xx_ops = { 915 .start = wcn36xx_start, 916 .stop = wcn36xx_stop, 917 .add_interface = wcn36xx_add_interface, 918 .remove_interface = wcn36xx_remove_interface, 919 #ifdef CONFIG_PM 920 .suspend = wcn36xx_suspend, 921 .resume = wcn36xx_resume, 922 #endif 923 .config = wcn36xx_config, 924 .configure_filter = wcn36xx_configure_filter, 925 .tx = wcn36xx_tx, 926 .set_key = wcn36xx_set_key, 927 .sw_scan_start = wcn36xx_sw_scan_start, 928 .sw_scan_complete = wcn36xx_sw_scan_complete, 929 .bss_info_changed = wcn36xx_bss_info_changed, 930 .set_rts_threshold = wcn36xx_set_rts_threshold, 931 .sta_add = wcn36xx_sta_add, 932 .sta_remove = wcn36xx_sta_remove, 933 .ampdu_action = wcn36xx_ampdu_action, 934 }; 935 936 static int wcn36xx_init_ieee80211(struct wcn36xx *wcn) 937 { 938 int ret = 0; 939 940 static const u32 cipher_suites[] = { 941 WLAN_CIPHER_SUITE_WEP40, 942 WLAN_CIPHER_SUITE_WEP104, 943 WLAN_CIPHER_SUITE_TKIP, 944 WLAN_CIPHER_SUITE_CCMP, 945 }; 946 947 wcn->hw->flags = IEEE80211_HW_SIGNAL_DBM | 948 IEEE80211_HW_HAS_RATE_CONTROL | 949 IEEE80211_HW_SUPPORTS_PS | 950 IEEE80211_HW_CONNECTION_MONITOR | 951 IEEE80211_HW_AMPDU_AGGREGATION | 952 IEEE80211_HW_TIMING_BEACON_ONLY; 953 954 wcn->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | 955 BIT(NL80211_IFTYPE_AP) | 956 BIT(NL80211_IFTYPE_ADHOC) | 957 BIT(NL80211_IFTYPE_MESH_POINT); 958 959 wcn->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wcn_band_2ghz; 960 wcn->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wcn_band_5ghz; 961 962 wcn->hw->wiphy->cipher_suites = cipher_suites; 963 wcn->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); 964 965 wcn->hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; 966 967 #ifdef CONFIG_PM 968 wcn->hw->wiphy->wowlan = &wowlan_support; 969 #endif 970 971 wcn->hw->max_listen_interval = 200; 972 973 wcn->hw->queues = 4; 974 975 SET_IEEE80211_DEV(wcn->hw, wcn->dev); 976 977 wcn->hw->sta_data_size = sizeof(struct wcn36xx_sta); 978 wcn->hw->vif_data_size = sizeof(struct wcn36xx_vif); 979 980 return ret; 981 } 982 983 static int wcn36xx_platform_get_resources(struct wcn36xx *wcn, 984 struct platform_device *pdev) 985 { 986 struct resource *res; 987 /* Set TX IRQ */ 988 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, 989 "wcnss_wlantx_irq"); 990 if (!res) { 991 wcn36xx_err("failed to get tx_irq\n"); 992 return -ENOENT; 993 } 994 wcn->tx_irq = res->start; 995 996 /* Set RX IRQ */ 997 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, 998 "wcnss_wlanrx_irq"); 999 if (!res) { 1000 wcn36xx_err("failed to get rx_irq\n"); 1001 return -ENOENT; 1002 } 1003 wcn->rx_irq = res->start; 1004 1005 /* Map the memory */ 1006 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, 1007 "wcnss_mmio"); 1008 if (!res) { 1009 wcn36xx_err("failed to get mmio\n"); 1010 return -ENOENT; 1011 } 1012 wcn->mmio = ioremap(res->start, resource_size(res)); 1013 if (!wcn->mmio) { 1014 wcn36xx_err("failed to map io memory\n"); 1015 return -ENOMEM; 1016 } 1017 return 0; 1018 } 1019 1020 static int wcn36xx_probe(struct platform_device *pdev) 1021 { 1022 struct ieee80211_hw *hw; 1023 struct wcn36xx *wcn; 1024 int ret; 1025 u8 addr[ETH_ALEN]; 1026 1027 wcn36xx_dbg(WCN36XX_DBG_MAC, "platform probe\n"); 1028 1029 hw = ieee80211_alloc_hw(sizeof(struct wcn36xx), &wcn36xx_ops); 1030 if (!hw) { 1031 wcn36xx_err("failed to alloc hw\n"); 1032 ret = -ENOMEM; 1033 goto out_err; 1034 } 1035 platform_set_drvdata(pdev, hw); 1036 wcn = hw->priv; 1037 wcn->hw = hw; 1038 wcn->dev = &pdev->dev; 1039 wcn->ctrl_ops = pdev->dev.platform_data; 1040 1041 mutex_init(&wcn->hal_mutex); 1042 1043 if (!wcn->ctrl_ops->get_hw_mac(addr)) { 1044 wcn36xx_info("mac address: %pM\n", addr); 1045 SET_IEEE80211_PERM_ADDR(wcn->hw, addr); 1046 } 1047 1048 ret = wcn36xx_platform_get_resources(wcn, pdev); 1049 if (ret) 1050 goto out_wq; 1051 1052 wcn36xx_init_ieee80211(wcn); 1053 ret = ieee80211_register_hw(wcn->hw); 1054 if (ret) 1055 goto out_unmap; 1056 1057 return 0; 1058 1059 out_unmap: 1060 iounmap(wcn->mmio); 1061 out_wq: 1062 ieee80211_free_hw(hw); 1063 out_err: 1064 return ret; 1065 } 1066 static int wcn36xx_remove(struct platform_device *pdev) 1067 { 1068 struct ieee80211_hw *hw = platform_get_drvdata(pdev); 1069 struct wcn36xx *wcn = hw->priv; 1070 wcn36xx_dbg(WCN36XX_DBG_MAC, "platform remove\n"); 1071 1072 release_firmware(wcn->nv); 1073 mutex_destroy(&wcn->hal_mutex); 1074 1075 ieee80211_unregister_hw(hw); 1076 iounmap(wcn->mmio); 1077 ieee80211_free_hw(hw); 1078 1079 return 0; 1080 } 1081 static const struct platform_device_id wcn36xx_platform_id_table[] = { 1082 { 1083 .name = "wcn36xx", 1084 .driver_data = 0 1085 }, 1086 {} 1087 }; 1088 MODULE_DEVICE_TABLE(platform, wcn36xx_platform_id_table); 1089 1090 static struct platform_driver wcn36xx_driver = { 1091 .probe = wcn36xx_probe, 1092 .remove = wcn36xx_remove, 1093 .driver = { 1094 .name = "wcn36xx", 1095 }, 1096 .id_table = wcn36xx_platform_id_table, 1097 }; 1098 1099 static int __init wcn36xx_init(void) 1100 { 1101 platform_driver_register(&wcn36xx_driver); 1102 return 0; 1103 } 1104 module_init(wcn36xx_init); 1105 1106 static void __exit wcn36xx_exit(void) 1107 { 1108 platform_driver_unregister(&wcn36xx_driver); 1109 } 1110 module_exit(wcn36xx_exit); 1111 1112 MODULE_LICENSE("Dual BSD/GPL"); 1113 MODULE_AUTHOR("Eugene Krasnikov k.eugene.e@gmail.com"); 1114 MODULE_FIRMWARE(WLAN_NV_FILE); 1115