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