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 break; 492 } 493 494 out: 495 return ret; 496 } 497 498 static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw) 499 { 500 struct wcn36xx *wcn = hw->priv; 501 502 wcn36xx_smd_init_scan(wcn, HAL_SYS_MODE_SCAN); 503 wcn36xx_smd_start_scan(wcn); 504 } 505 506 static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw) 507 { 508 struct wcn36xx *wcn = hw->priv; 509 510 wcn36xx_smd_end_scan(wcn); 511 wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN); 512 } 513 514 static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta, 515 enum ieee80211_band band) 516 { 517 int i, size; 518 u16 *rates_table; 519 struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv; 520 u32 rates = sta->supp_rates[band]; 521 522 memset(&sta_priv->supported_rates, 0, 523 sizeof(sta_priv->supported_rates)); 524 sta_priv->supported_rates.op_rate_mode = STA_11n; 525 526 size = ARRAY_SIZE(sta_priv->supported_rates.dsss_rates); 527 rates_table = sta_priv->supported_rates.dsss_rates; 528 if (band == IEEE80211_BAND_2GHZ) { 529 for (i = 0; i < size; i++) { 530 if (rates & 0x01) { 531 rates_table[i] = wcn_2ghz_rates[i].hw_value; 532 rates = rates >> 1; 533 } 534 } 535 } 536 537 size = ARRAY_SIZE(sta_priv->supported_rates.ofdm_rates); 538 rates_table = sta_priv->supported_rates.ofdm_rates; 539 for (i = 0; i < size; i++) { 540 if (rates & 0x01) { 541 rates_table[i] = wcn_5ghz_rates[i].hw_value; 542 rates = rates >> 1; 543 } 544 } 545 546 if (sta->ht_cap.ht_supported) { 547 BUILD_BUG_ON(sizeof(sta->ht_cap.mcs.rx_mask) > 548 sizeof(sta_priv->supported_rates.supported_mcs_set)); 549 memcpy(sta_priv->supported_rates.supported_mcs_set, 550 sta->ht_cap.mcs.rx_mask, 551 sizeof(sta->ht_cap.mcs.rx_mask)); 552 } 553 } 554 void wcn36xx_set_default_rates(struct wcn36xx_hal_supported_rates *rates) 555 { 556 u16 ofdm_rates[WCN36XX_HAL_NUM_OFDM_RATES] = { 557 HW_RATE_INDEX_6MBPS, 558 HW_RATE_INDEX_9MBPS, 559 HW_RATE_INDEX_12MBPS, 560 HW_RATE_INDEX_18MBPS, 561 HW_RATE_INDEX_24MBPS, 562 HW_RATE_INDEX_36MBPS, 563 HW_RATE_INDEX_48MBPS, 564 HW_RATE_INDEX_54MBPS 565 }; 566 u16 dsss_rates[WCN36XX_HAL_NUM_DSSS_RATES] = { 567 HW_RATE_INDEX_1MBPS, 568 HW_RATE_INDEX_2MBPS, 569 HW_RATE_INDEX_5_5MBPS, 570 HW_RATE_INDEX_11MBPS 571 }; 572 573 rates->op_rate_mode = STA_11n; 574 memcpy(rates->dsss_rates, dsss_rates, 575 sizeof(*dsss_rates) * WCN36XX_HAL_NUM_DSSS_RATES); 576 memcpy(rates->ofdm_rates, ofdm_rates, 577 sizeof(*ofdm_rates) * WCN36XX_HAL_NUM_OFDM_RATES); 578 rates->supported_mcs_set[0] = 0xFF; 579 } 580 static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw, 581 struct ieee80211_vif *vif, 582 struct ieee80211_bss_conf *bss_conf, 583 u32 changed) 584 { 585 struct wcn36xx *wcn = hw->priv; 586 struct sk_buff *skb = NULL; 587 u16 tim_off, tim_len; 588 enum wcn36xx_hal_link_state link_state; 589 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 590 591 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss info changed vif %p changed 0x%08x\n", 592 vif, changed); 593 594 if (changed & BSS_CHANGED_BEACON_INFO) { 595 wcn36xx_dbg(WCN36XX_DBG_MAC, 596 "mac bss changed dtim period %d\n", 597 bss_conf->dtim_period); 598 599 vif_priv->dtim_period = bss_conf->dtim_period; 600 } 601 602 if (changed & BSS_CHANGED_PS) { 603 wcn36xx_dbg(WCN36XX_DBG_MAC, 604 "mac bss PS set %d\n", 605 bss_conf->ps); 606 if (bss_conf->ps) { 607 wcn36xx_pmc_enter_bmps_state(wcn, vif); 608 } else { 609 wcn36xx_pmc_exit_bmps_state(wcn, vif); 610 } 611 } 612 613 if (changed & BSS_CHANGED_BSSID) { 614 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss changed_bssid %pM\n", 615 bss_conf->bssid); 616 617 if (!is_zero_ether_addr(bss_conf->bssid)) { 618 vif_priv->is_joining = true; 619 vif_priv->bss_index = 0xff; 620 wcn36xx_smd_join(wcn, bss_conf->bssid, 621 vif->addr, WCN36XX_HW_CHANNEL(wcn)); 622 wcn36xx_smd_config_bss(wcn, vif, NULL, 623 bss_conf->bssid, false); 624 } else { 625 vif_priv->is_joining = false; 626 wcn36xx_smd_delete_bss(wcn, vif); 627 } 628 } 629 630 if (changed & BSS_CHANGED_SSID) { 631 wcn36xx_dbg(WCN36XX_DBG_MAC, 632 "mac bss changed ssid\n"); 633 wcn36xx_dbg_dump(WCN36XX_DBG_MAC, "ssid ", 634 bss_conf->ssid, bss_conf->ssid_len); 635 636 vif_priv->ssid.length = bss_conf->ssid_len; 637 memcpy(&vif_priv->ssid.ssid, 638 bss_conf->ssid, 639 bss_conf->ssid_len); 640 } 641 642 if (changed & BSS_CHANGED_ASSOC) { 643 vif_priv->is_joining = false; 644 if (bss_conf->assoc) { 645 struct ieee80211_sta *sta; 646 struct wcn36xx_sta *sta_priv; 647 648 wcn36xx_dbg(WCN36XX_DBG_MAC, 649 "mac assoc bss %pM vif %pM AID=%d\n", 650 bss_conf->bssid, 651 vif->addr, 652 bss_conf->aid); 653 654 rcu_read_lock(); 655 sta = ieee80211_find_sta(vif, bss_conf->bssid); 656 if (!sta) { 657 wcn36xx_err("sta %pM is not found\n", 658 bss_conf->bssid); 659 rcu_read_unlock(); 660 goto out; 661 } 662 sta_priv = (struct wcn36xx_sta *)sta->drv_priv; 663 664 wcn36xx_update_allowed_rates(sta, WCN36XX_BAND(wcn)); 665 666 wcn36xx_smd_set_link_st(wcn, bss_conf->bssid, 667 vif->addr, 668 WCN36XX_HAL_LINK_POSTASSOC_STATE); 669 wcn36xx_smd_config_bss(wcn, vif, sta, 670 bss_conf->bssid, 671 true); 672 sta_priv->aid = bss_conf->aid; 673 /* 674 * config_sta must be called from because this is the 675 * place where AID is available. 676 */ 677 wcn36xx_smd_config_sta(wcn, vif, sta); 678 rcu_read_unlock(); 679 } else { 680 wcn36xx_dbg(WCN36XX_DBG_MAC, 681 "disassociated bss %pM vif %pM AID=%d\n", 682 bss_conf->bssid, 683 vif->addr, 684 bss_conf->aid); 685 wcn36xx_smd_set_link_st(wcn, 686 bss_conf->bssid, 687 vif->addr, 688 WCN36XX_HAL_LINK_IDLE_STATE); 689 } 690 } 691 692 if (changed & BSS_CHANGED_AP_PROBE_RESP) { 693 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss changed ap probe resp\n"); 694 skb = ieee80211_proberesp_get(hw, vif); 695 if (!skb) { 696 wcn36xx_err("failed to alloc probereq skb\n"); 697 goto out; 698 } 699 700 wcn36xx_smd_update_proberesp_tmpl(wcn, vif, skb); 701 dev_kfree_skb(skb); 702 } 703 704 if (changed & BSS_CHANGED_BEACON_ENABLED || 705 changed & BSS_CHANGED_BEACON) { 706 wcn36xx_dbg(WCN36XX_DBG_MAC, 707 "mac bss changed beacon enabled %d\n", 708 bss_conf->enable_beacon); 709 710 if (bss_conf->enable_beacon) { 711 vif_priv->dtim_period = bss_conf->dtim_period; 712 vif_priv->bss_index = 0xff; 713 wcn36xx_smd_config_bss(wcn, vif, NULL, 714 vif->addr, false); 715 skb = ieee80211_beacon_get_tim(hw, vif, &tim_off, 716 &tim_len); 717 if (!skb) { 718 wcn36xx_err("failed to alloc beacon skb\n"); 719 goto out; 720 } 721 wcn36xx_smd_send_beacon(wcn, vif, skb, tim_off, 0); 722 dev_kfree_skb(skb); 723 724 if (vif->type == NL80211_IFTYPE_ADHOC || 725 vif->type == NL80211_IFTYPE_MESH_POINT) 726 link_state = WCN36XX_HAL_LINK_IBSS_STATE; 727 else 728 link_state = WCN36XX_HAL_LINK_AP_STATE; 729 730 wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr, 731 link_state); 732 } else { 733 wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr, 734 WCN36XX_HAL_LINK_IDLE_STATE); 735 wcn36xx_smd_delete_bss(wcn, vif); 736 } 737 } 738 out: 739 return; 740 } 741 742 /* this is required when using IEEE80211_HW_HAS_RATE_CONTROL */ 743 static int wcn36xx_set_rts_threshold(struct ieee80211_hw *hw, u32 value) 744 { 745 struct wcn36xx *wcn = hw->priv; 746 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac set RTS threshold %d\n", value); 747 748 wcn36xx_smd_update_cfg(wcn, WCN36XX_HAL_CFG_RTS_THRESHOLD, value); 749 return 0; 750 } 751 752 static void wcn36xx_remove_interface(struct ieee80211_hw *hw, 753 struct ieee80211_vif *vif) 754 { 755 struct wcn36xx *wcn = hw->priv; 756 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 757 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac remove interface vif %p\n", vif); 758 759 list_del(&vif_priv->list); 760 wcn36xx_smd_delete_sta_self(wcn, vif->addr); 761 } 762 763 static int wcn36xx_add_interface(struct ieee80211_hw *hw, 764 struct ieee80211_vif *vif) 765 { 766 struct wcn36xx *wcn = hw->priv; 767 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 768 769 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac add interface vif %p type %d\n", 770 vif, vif->type); 771 772 if (!(NL80211_IFTYPE_STATION == vif->type || 773 NL80211_IFTYPE_AP == vif->type || 774 NL80211_IFTYPE_ADHOC == vif->type || 775 NL80211_IFTYPE_MESH_POINT == vif->type)) { 776 wcn36xx_warn("Unsupported interface type requested: %d\n", 777 vif->type); 778 return -EOPNOTSUPP; 779 } 780 781 list_add(&vif_priv->list, &wcn->vif_list); 782 wcn36xx_smd_add_sta_self(wcn, vif); 783 784 return 0; 785 } 786 787 static int wcn36xx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 788 struct ieee80211_sta *sta) 789 { 790 struct wcn36xx *wcn = hw->priv; 791 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 792 struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv; 793 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta add vif %p sta %pM\n", 794 vif, sta->addr); 795 796 vif_priv->sta = sta_priv; 797 sta_priv->vif = vif_priv; 798 /* 799 * For STA mode HW will be configured on BSS_CHANGED_ASSOC because 800 * at this stage AID is not available yet. 801 */ 802 if (NL80211_IFTYPE_STATION != vif->type) { 803 wcn36xx_update_allowed_rates(sta, WCN36XX_BAND(wcn)); 804 sta_priv->aid = sta->aid; 805 wcn36xx_smd_config_sta(wcn, vif, sta); 806 } 807 return 0; 808 } 809 810 static int wcn36xx_sta_remove(struct ieee80211_hw *hw, 811 struct ieee80211_vif *vif, 812 struct ieee80211_sta *sta) 813 { 814 struct wcn36xx *wcn = hw->priv; 815 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 816 struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv; 817 818 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta remove vif %p sta %pM index %d\n", 819 vif, sta->addr, sta_priv->sta_index); 820 821 wcn36xx_smd_delete_sta(wcn, sta_priv->sta_index); 822 vif_priv->sta = NULL; 823 sta_priv->vif = NULL; 824 return 0; 825 } 826 827 #ifdef CONFIG_PM 828 829 static int wcn36xx_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wow) 830 { 831 struct wcn36xx *wcn = hw->priv; 832 833 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac suspend\n"); 834 835 flush_workqueue(wcn->hal_ind_wq); 836 wcn36xx_smd_set_power_params(wcn, true); 837 return 0; 838 } 839 840 static int wcn36xx_resume(struct ieee80211_hw *hw) 841 { 842 struct wcn36xx *wcn = hw->priv; 843 844 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac resume\n"); 845 846 flush_workqueue(wcn->hal_ind_wq); 847 wcn36xx_smd_set_power_params(wcn, false); 848 return 0; 849 } 850 851 #endif 852 853 static int wcn36xx_ampdu_action(struct ieee80211_hw *hw, 854 struct ieee80211_vif *vif, 855 enum ieee80211_ampdu_mlme_action action, 856 struct ieee80211_sta *sta, u16 tid, u16 *ssn, 857 u8 buf_size) 858 { 859 struct wcn36xx *wcn = hw->priv; 860 struct wcn36xx_sta *sta_priv = NULL; 861 862 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu action action %d tid %d\n", 863 action, tid); 864 865 sta_priv = (struct wcn36xx_sta *)sta->drv_priv; 866 867 switch (action) { 868 case IEEE80211_AMPDU_RX_START: 869 sta_priv->tid = tid; 870 wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 0, 871 get_sta_index(vif, sta_priv)); 872 wcn36xx_smd_add_ba(wcn); 873 wcn36xx_smd_trigger_ba(wcn, get_sta_index(vif, sta_priv)); 874 ieee80211_start_tx_ba_session(sta, tid, 0); 875 break; 876 case IEEE80211_AMPDU_RX_STOP: 877 wcn36xx_smd_del_ba(wcn, tid, get_sta_index(vif, sta_priv)); 878 break; 879 case IEEE80211_AMPDU_TX_START: 880 ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); 881 break; 882 case IEEE80211_AMPDU_TX_OPERATIONAL: 883 wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 1, 884 get_sta_index(vif, sta_priv)); 885 break; 886 case IEEE80211_AMPDU_TX_STOP_FLUSH: 887 case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: 888 case IEEE80211_AMPDU_TX_STOP_CONT: 889 ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); 890 break; 891 default: 892 wcn36xx_err("Unknown AMPDU action\n"); 893 } 894 895 return 0; 896 } 897 898 static const struct ieee80211_ops wcn36xx_ops = { 899 .start = wcn36xx_start, 900 .stop = wcn36xx_stop, 901 .add_interface = wcn36xx_add_interface, 902 .remove_interface = wcn36xx_remove_interface, 903 #ifdef CONFIG_PM 904 .suspend = wcn36xx_suspend, 905 .resume = wcn36xx_resume, 906 #endif 907 .config = wcn36xx_config, 908 .configure_filter = wcn36xx_configure_filter, 909 .tx = wcn36xx_tx, 910 .set_key = wcn36xx_set_key, 911 .sw_scan_start = wcn36xx_sw_scan_start, 912 .sw_scan_complete = wcn36xx_sw_scan_complete, 913 .bss_info_changed = wcn36xx_bss_info_changed, 914 .set_rts_threshold = wcn36xx_set_rts_threshold, 915 .sta_add = wcn36xx_sta_add, 916 .sta_remove = wcn36xx_sta_remove, 917 .ampdu_action = wcn36xx_ampdu_action, 918 }; 919 920 static int wcn36xx_init_ieee80211(struct wcn36xx *wcn) 921 { 922 int ret = 0; 923 924 static const u32 cipher_suites[] = { 925 WLAN_CIPHER_SUITE_WEP40, 926 WLAN_CIPHER_SUITE_WEP104, 927 WLAN_CIPHER_SUITE_TKIP, 928 WLAN_CIPHER_SUITE_CCMP, 929 }; 930 931 wcn->hw->flags = IEEE80211_HW_SIGNAL_DBM | 932 IEEE80211_HW_HAS_RATE_CONTROL | 933 IEEE80211_HW_SUPPORTS_PS | 934 IEEE80211_HW_CONNECTION_MONITOR | 935 IEEE80211_HW_AMPDU_AGGREGATION | 936 IEEE80211_HW_TIMING_BEACON_ONLY; 937 938 wcn->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | 939 BIT(NL80211_IFTYPE_AP) | 940 BIT(NL80211_IFTYPE_ADHOC) | 941 BIT(NL80211_IFTYPE_MESH_POINT); 942 943 wcn->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wcn_band_2ghz; 944 wcn->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wcn_band_5ghz; 945 946 wcn->hw->wiphy->cipher_suites = cipher_suites; 947 wcn->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); 948 949 wcn->hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; 950 951 #ifdef CONFIG_PM 952 wcn->hw->wiphy->wowlan = &wowlan_support; 953 #endif 954 955 wcn->hw->max_listen_interval = 200; 956 957 wcn->hw->queues = 4; 958 959 SET_IEEE80211_DEV(wcn->hw, wcn->dev); 960 961 wcn->hw->sta_data_size = sizeof(struct wcn36xx_sta); 962 wcn->hw->vif_data_size = sizeof(struct wcn36xx_vif); 963 964 return ret; 965 } 966 967 static int wcn36xx_platform_get_resources(struct wcn36xx *wcn, 968 struct platform_device *pdev) 969 { 970 struct resource *res; 971 /* Set TX IRQ */ 972 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, 973 "wcnss_wlantx_irq"); 974 if (!res) { 975 wcn36xx_err("failed to get tx_irq\n"); 976 return -ENOENT; 977 } 978 wcn->tx_irq = res->start; 979 980 /* Set RX IRQ */ 981 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, 982 "wcnss_wlanrx_irq"); 983 if (!res) { 984 wcn36xx_err("failed to get rx_irq\n"); 985 return -ENOENT; 986 } 987 wcn->rx_irq = res->start; 988 989 /* Map the memory */ 990 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, 991 "wcnss_mmio"); 992 if (!res) { 993 wcn36xx_err("failed to get mmio\n"); 994 return -ENOENT; 995 } 996 wcn->mmio = ioremap(res->start, resource_size(res)); 997 if (!wcn->mmio) { 998 wcn36xx_err("failed to map io memory\n"); 999 return -ENOMEM; 1000 } 1001 return 0; 1002 } 1003 1004 static int wcn36xx_probe(struct platform_device *pdev) 1005 { 1006 struct ieee80211_hw *hw; 1007 struct wcn36xx *wcn; 1008 int ret; 1009 u8 addr[ETH_ALEN]; 1010 1011 wcn36xx_dbg(WCN36XX_DBG_MAC, "platform probe\n"); 1012 1013 hw = ieee80211_alloc_hw(sizeof(struct wcn36xx), &wcn36xx_ops); 1014 if (!hw) { 1015 wcn36xx_err("failed to alloc hw\n"); 1016 ret = -ENOMEM; 1017 goto out_err; 1018 } 1019 platform_set_drvdata(pdev, hw); 1020 wcn = hw->priv; 1021 wcn->hw = hw; 1022 wcn->dev = &pdev->dev; 1023 wcn->ctrl_ops = pdev->dev.platform_data; 1024 1025 mutex_init(&wcn->hal_mutex); 1026 1027 if (!wcn->ctrl_ops->get_hw_mac(addr)) { 1028 wcn36xx_info("mac address: %pM\n", addr); 1029 SET_IEEE80211_PERM_ADDR(wcn->hw, addr); 1030 } 1031 1032 ret = wcn36xx_platform_get_resources(wcn, pdev); 1033 if (ret) 1034 goto out_wq; 1035 1036 wcn36xx_init_ieee80211(wcn); 1037 ret = ieee80211_register_hw(wcn->hw); 1038 if (ret) 1039 goto out_unmap; 1040 1041 return 0; 1042 1043 out_unmap: 1044 iounmap(wcn->mmio); 1045 out_wq: 1046 ieee80211_free_hw(hw); 1047 out_err: 1048 return ret; 1049 } 1050 static int wcn36xx_remove(struct platform_device *pdev) 1051 { 1052 struct ieee80211_hw *hw = platform_get_drvdata(pdev); 1053 struct wcn36xx *wcn = hw->priv; 1054 wcn36xx_dbg(WCN36XX_DBG_MAC, "platform remove\n"); 1055 1056 release_firmware(wcn->nv); 1057 mutex_destroy(&wcn->hal_mutex); 1058 1059 ieee80211_unregister_hw(hw); 1060 iounmap(wcn->mmio); 1061 ieee80211_free_hw(hw); 1062 1063 return 0; 1064 } 1065 static const struct platform_device_id wcn36xx_platform_id_table[] = { 1066 { 1067 .name = "wcn36xx", 1068 .driver_data = 0 1069 }, 1070 {} 1071 }; 1072 MODULE_DEVICE_TABLE(platform, wcn36xx_platform_id_table); 1073 1074 static struct platform_driver wcn36xx_driver = { 1075 .probe = wcn36xx_probe, 1076 .remove = wcn36xx_remove, 1077 .driver = { 1078 .name = "wcn36xx", 1079 .owner = THIS_MODULE, 1080 }, 1081 .id_table = wcn36xx_platform_id_table, 1082 }; 1083 1084 static int __init wcn36xx_init(void) 1085 { 1086 platform_driver_register(&wcn36xx_driver); 1087 return 0; 1088 } 1089 module_init(wcn36xx_init); 1090 1091 static void __exit wcn36xx_exit(void) 1092 { 1093 platform_driver_unregister(&wcn36xx_driver); 1094 } 1095 module_exit(wcn36xx_exit); 1096 1097 MODULE_LICENSE("Dual BSD/GPL"); 1098 MODULE_AUTHOR("Eugene Krasnikov k.eugene.e@gmail.com"); 1099 MODULE_FIRMWARE(WLAN_NV_FILE); 1100