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