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 = NL80211_BAND_2GHZ, \ 30 .center_freq = (_freq), \ 31 .hw_value = (_idx), \ 32 .max_power = 25, \ 33 } 34 35 #define CHAN5G(_freq, _idx) { \ 36 .band = NL80211_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 "WLAN_ROAM_SCAN_OFFLOAD", /* 23 */ 206 "SPECULATIVE_PS_POLL", /* 24 */ 207 "SCAN_SCH", /* 25 */ 208 "IBSS_HEARTBEAT_OFFLOAD", /* 26 */ 209 "WLAN_SCAN_OFFLOAD", /* 27 */ 210 "WLAN_PERIODIC_TX_PTRN", /* 28 */ 211 "ADVANCE_TDLS", /* 29 */ 212 "BATCH_SCAN", /* 30 */ 213 "FW_IN_TX_PATH", /* 31 */ 214 "EXTENDED_NSOFFLOAD_SLOT", /* 32 */ 215 "CH_SWITCH_V1", /* 33 */ 216 "HT40_OBSS_SCAN", /* 34 */ 217 "UPDATE_CHANNEL_LIST", /* 35 */ 218 "WLAN_MCADDR_FLT", /* 36 */ 219 "WLAN_CH144", /* 37 */ 220 "NAN", /* 38 */ 221 "TDLS_SCAN_COEXISTENCE", /* 39 */ 222 "LINK_LAYER_STATS_MEAS", /* 40 */ 223 "MU_MIMO", /* 41 */ 224 "EXTENDED_SCAN", /* 42 */ 225 "DYNAMIC_WMM_PS", /* 43 */ 226 "MAC_SPOOFED_SCAN", /* 44 */ 227 "BMU_ERROR_GENERIC_RECOVERY", /* 45 */ 228 "DISA", /* 46 */ 229 "FW_STATS", /* 47 */ 230 "WPS_PRBRSP_TMPL", /* 48 */ 231 "BCN_IE_FLT_DELTA", /* 49 */ 232 "TDLS_OFF_CHANNEL", /* 51 */ 233 "RTT3", /* 52 */ 234 "MGMT_FRAME_LOGGING", /* 53 */ 235 "ENHANCED_TXBD_COMPLETION", /* 54 */ 236 "LOGGING_ENHANCEMENT", /* 55 */ 237 "EXT_SCAN_ENHANCED", /* 56 */ 238 "MEMORY_DUMP_SUPPORTED", /* 57 */ 239 "PER_PKT_STATS_SUPPORTED", /* 58 */ 240 "EXT_LL_STAT", /* 60 */ 241 "WIFI_CONFIG", /* 61 */ 242 "ANTENNA_DIVERSITY_SELECTION", /* 62 */ 243 }; 244 245 static const char *wcn36xx_get_cap_name(enum place_holder_in_cap_bitmap x) 246 { 247 if (x >= ARRAY_SIZE(wcn36xx_caps_names)) 248 return "UNKNOWN"; 249 return wcn36xx_caps_names[x]; 250 } 251 252 static void wcn36xx_feat_caps_info(struct wcn36xx *wcn) 253 { 254 int i; 255 256 for (i = 0; i < MAX_FEATURE_SUPPORTED; i++) { 257 if (get_feat_caps(wcn->fw_feat_caps, i)) 258 wcn36xx_info("FW Cap %s\n", wcn36xx_get_cap_name(i)); 259 } 260 } 261 262 static void wcn36xx_detect_chip_version(struct wcn36xx *wcn) 263 { 264 if (get_feat_caps(wcn->fw_feat_caps, DOT11AC)) { 265 wcn36xx_info("Chip is 3680\n"); 266 wcn->chip_version = WCN36XX_CHIP_3680; 267 } else { 268 wcn36xx_info("Chip is 3660\n"); 269 wcn->chip_version = WCN36XX_CHIP_3660; 270 } 271 } 272 273 static int wcn36xx_start(struct ieee80211_hw *hw) 274 { 275 struct wcn36xx *wcn = hw->priv; 276 int ret; 277 278 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac start\n"); 279 280 /* SMD initialization */ 281 ret = wcn36xx_smd_open(wcn); 282 if (ret) { 283 wcn36xx_err("Failed to open smd channel: %d\n", ret); 284 goto out_err; 285 } 286 287 /* Allocate memory pools for Mgmt BD headers and Data BD headers */ 288 ret = wcn36xx_dxe_allocate_mem_pools(wcn); 289 if (ret) { 290 wcn36xx_err("Failed to alloc DXE mempool: %d\n", ret); 291 goto out_smd_close; 292 } 293 294 ret = wcn36xx_dxe_alloc_ctl_blks(wcn); 295 if (ret) { 296 wcn36xx_err("Failed to alloc DXE ctl blocks: %d\n", ret); 297 goto out_free_dxe_pool; 298 } 299 300 wcn->hal_buf = kmalloc(WCN36XX_HAL_BUF_SIZE, GFP_KERNEL); 301 if (!wcn->hal_buf) { 302 wcn36xx_err("Failed to allocate smd buf\n"); 303 ret = -ENOMEM; 304 goto out_free_dxe_ctl; 305 } 306 307 ret = wcn36xx_smd_load_nv(wcn); 308 if (ret) { 309 wcn36xx_err("Failed to push NV to chip\n"); 310 goto out_free_smd_buf; 311 } 312 313 ret = wcn36xx_smd_start(wcn); 314 if (ret) { 315 wcn36xx_err("Failed to start chip\n"); 316 goto out_free_smd_buf; 317 } 318 319 if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) { 320 ret = wcn36xx_smd_feature_caps_exchange(wcn); 321 if (ret) 322 wcn36xx_warn("Exchange feature caps failed\n"); 323 else 324 wcn36xx_feat_caps_info(wcn); 325 } 326 327 wcn36xx_detect_chip_version(wcn); 328 wcn36xx_smd_update_cfg(wcn, WCN36XX_HAL_CFG_ENABLE_MC_ADDR_LIST, 1); 329 330 /* DMA channel initialization */ 331 ret = wcn36xx_dxe_init(wcn); 332 if (ret) { 333 wcn36xx_err("DXE init failed\n"); 334 goto out_smd_stop; 335 } 336 337 wcn36xx_debugfs_init(wcn); 338 339 INIT_LIST_HEAD(&wcn->vif_list); 340 spin_lock_init(&wcn->dxe_lock); 341 342 return 0; 343 344 out_smd_stop: 345 wcn36xx_smd_stop(wcn); 346 out_free_smd_buf: 347 kfree(wcn->hal_buf); 348 out_free_dxe_pool: 349 wcn36xx_dxe_free_mem_pools(wcn); 350 out_free_dxe_ctl: 351 wcn36xx_dxe_free_ctl_blks(wcn); 352 out_smd_close: 353 wcn36xx_smd_close(wcn); 354 out_err: 355 return ret; 356 } 357 358 static void wcn36xx_stop(struct ieee80211_hw *hw) 359 { 360 struct wcn36xx *wcn = hw->priv; 361 362 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac stop\n"); 363 364 wcn36xx_debugfs_exit(wcn); 365 wcn36xx_smd_stop(wcn); 366 wcn36xx_dxe_deinit(wcn); 367 wcn36xx_smd_close(wcn); 368 369 wcn36xx_dxe_free_mem_pools(wcn); 370 wcn36xx_dxe_free_ctl_blks(wcn); 371 372 kfree(wcn->hal_buf); 373 } 374 375 static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed) 376 { 377 struct wcn36xx *wcn = hw->priv; 378 struct ieee80211_vif *vif = NULL; 379 struct wcn36xx_vif *tmp; 380 381 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac config changed 0x%08x\n", changed); 382 383 if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { 384 int ch = WCN36XX_HW_CHANNEL(wcn); 385 wcn36xx_dbg(WCN36XX_DBG_MAC, "wcn36xx_config channel switch=%d\n", 386 ch); 387 list_for_each_entry(tmp, &wcn->vif_list, list) { 388 vif = wcn36xx_priv_to_vif(tmp); 389 wcn36xx_smd_switch_channel(wcn, vif, ch); 390 } 391 } 392 393 return 0; 394 } 395 396 static void wcn36xx_configure_filter(struct ieee80211_hw *hw, 397 unsigned int changed, 398 unsigned int *total, u64 multicast) 399 { 400 struct wcn36xx_hal_rcv_flt_mc_addr_list_type *fp; 401 struct wcn36xx *wcn = hw->priv; 402 struct wcn36xx_vif *tmp; 403 struct ieee80211_vif *vif = NULL; 404 405 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac configure filter\n"); 406 407 *total &= FIF_ALLMULTI; 408 409 fp = (void *)(unsigned long)multicast; 410 list_for_each_entry(tmp, &wcn->vif_list, list) { 411 vif = wcn36xx_priv_to_vif(tmp); 412 413 /* FW handles MC filtering only when connected as STA */ 414 if (*total & FIF_ALLMULTI) 415 wcn36xx_smd_set_mc_list(wcn, vif, NULL); 416 else if (NL80211_IFTYPE_STATION == vif->type && tmp->sta_assoc) 417 wcn36xx_smd_set_mc_list(wcn, vif, fp); 418 } 419 kfree(fp); 420 } 421 422 static u64 wcn36xx_prepare_multicast(struct ieee80211_hw *hw, 423 struct netdev_hw_addr_list *mc_list) 424 { 425 struct wcn36xx_hal_rcv_flt_mc_addr_list_type *fp; 426 struct netdev_hw_addr *ha; 427 428 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac prepare multicast list\n"); 429 fp = kzalloc(sizeof(*fp), GFP_ATOMIC); 430 if (!fp) { 431 wcn36xx_err("Out of memory setting filters.\n"); 432 return 0; 433 } 434 435 fp->mc_addr_count = 0; 436 /* update multicast filtering parameters */ 437 if (netdev_hw_addr_list_count(mc_list) <= 438 WCN36XX_HAL_MAX_NUM_MULTICAST_ADDRESS) { 439 netdev_hw_addr_list_for_each(ha, mc_list) { 440 memcpy(fp->mc_addr[fp->mc_addr_count], 441 ha->addr, ETH_ALEN); 442 fp->mc_addr_count++; 443 } 444 } 445 446 return (u64)(unsigned long)fp; 447 } 448 449 static void wcn36xx_tx(struct ieee80211_hw *hw, 450 struct ieee80211_tx_control *control, 451 struct sk_buff *skb) 452 { 453 struct wcn36xx *wcn = hw->priv; 454 struct wcn36xx_sta *sta_priv = NULL; 455 456 if (control->sta) 457 sta_priv = wcn36xx_sta_to_priv(control->sta); 458 459 if (wcn36xx_start_tx(wcn, sta_priv, skb)) 460 ieee80211_free_txskb(wcn->hw, skb); 461 } 462 463 static int wcn36xx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, 464 struct ieee80211_vif *vif, 465 struct ieee80211_sta *sta, 466 struct ieee80211_key_conf *key_conf) 467 { 468 struct wcn36xx *wcn = hw->priv; 469 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); 470 struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta); 471 int ret = 0; 472 u8 key[WLAN_MAX_KEY_LEN]; 473 474 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac80211 set key\n"); 475 wcn36xx_dbg(WCN36XX_DBG_MAC, "Key: cmd=0x%x algo:0x%x, id:%d, len:%d flags 0x%x\n", 476 cmd, key_conf->cipher, key_conf->keyidx, 477 key_conf->keylen, key_conf->flags); 478 wcn36xx_dbg_dump(WCN36XX_DBG_MAC, "KEY: ", 479 key_conf->key, 480 key_conf->keylen); 481 482 switch (key_conf->cipher) { 483 case WLAN_CIPHER_SUITE_WEP40: 484 vif_priv->encrypt_type = WCN36XX_HAL_ED_WEP40; 485 break; 486 case WLAN_CIPHER_SUITE_WEP104: 487 vif_priv->encrypt_type = WCN36XX_HAL_ED_WEP40; 488 break; 489 case WLAN_CIPHER_SUITE_CCMP: 490 vif_priv->encrypt_type = WCN36XX_HAL_ED_CCMP; 491 break; 492 case WLAN_CIPHER_SUITE_TKIP: 493 vif_priv->encrypt_type = WCN36XX_HAL_ED_TKIP; 494 break; 495 default: 496 wcn36xx_err("Unsupported key type 0x%x\n", 497 key_conf->cipher); 498 ret = -EOPNOTSUPP; 499 goto out; 500 } 501 502 switch (cmd) { 503 case SET_KEY: 504 if (WCN36XX_HAL_ED_TKIP == vif_priv->encrypt_type) { 505 /* 506 * Supplicant is sending key in the wrong order: 507 * Temporal Key (16 b) - TX MIC (8 b) - RX MIC (8 b) 508 * but HW expects it to be in the order as described in 509 * IEEE 802.11 spec (see chapter 11.7) like this: 510 * Temporal Key (16 b) - RX MIC (8 b) - TX MIC (8 b) 511 */ 512 memcpy(key, key_conf->key, 16); 513 memcpy(key + 16, key_conf->key + 24, 8); 514 memcpy(key + 24, key_conf->key + 16, 8); 515 } else { 516 memcpy(key, key_conf->key, key_conf->keylen); 517 } 518 519 if (IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags) { 520 sta_priv->is_data_encrypted = true; 521 /* Reconfigure bss with encrypt_type */ 522 if (NL80211_IFTYPE_STATION == vif->type) 523 wcn36xx_smd_config_bss(wcn, 524 vif, 525 sta, 526 sta->addr, 527 true); 528 529 wcn36xx_smd_set_stakey(wcn, 530 vif_priv->encrypt_type, 531 key_conf->keyidx, 532 key_conf->keylen, 533 key, 534 get_sta_index(vif, sta_priv)); 535 } else { 536 wcn36xx_smd_set_bsskey(wcn, 537 vif_priv->encrypt_type, 538 key_conf->keyidx, 539 key_conf->keylen, 540 key); 541 if ((WLAN_CIPHER_SUITE_WEP40 == key_conf->cipher) || 542 (WLAN_CIPHER_SUITE_WEP104 == key_conf->cipher)) { 543 sta_priv->is_data_encrypted = true; 544 wcn36xx_smd_set_stakey(wcn, 545 vif_priv->encrypt_type, 546 key_conf->keyidx, 547 key_conf->keylen, 548 key, 549 get_sta_index(vif, sta_priv)); 550 } 551 } 552 break; 553 case DISABLE_KEY: 554 if (!(IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags)) { 555 vif_priv->encrypt_type = WCN36XX_HAL_ED_NONE; 556 wcn36xx_smd_remove_bsskey(wcn, 557 vif_priv->encrypt_type, 558 key_conf->keyidx); 559 } else { 560 sta_priv->is_data_encrypted = false; 561 /* do not remove key if disassociated */ 562 if (sta_priv->aid) 563 wcn36xx_smd_remove_stakey(wcn, 564 vif_priv->encrypt_type, 565 key_conf->keyidx, 566 get_sta_index(vif, sta_priv)); 567 } 568 break; 569 default: 570 wcn36xx_err("Unsupported key cmd 0x%x\n", cmd); 571 ret = -EOPNOTSUPP; 572 goto out; 573 } 574 575 out: 576 return ret; 577 } 578 579 static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw, 580 struct ieee80211_vif *vif, 581 const u8 *mac_addr) 582 { 583 struct wcn36xx *wcn = hw->priv; 584 585 wcn36xx_smd_init_scan(wcn, HAL_SYS_MODE_SCAN); 586 wcn36xx_smd_start_scan(wcn); 587 } 588 589 static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw, 590 struct ieee80211_vif *vif) 591 { 592 struct wcn36xx *wcn = hw->priv; 593 594 wcn36xx_smd_end_scan(wcn); 595 wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN); 596 } 597 598 static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta, 599 enum nl80211_band band) 600 { 601 int i, size; 602 u16 *rates_table; 603 struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta); 604 u32 rates = sta->supp_rates[band]; 605 606 memset(&sta_priv->supported_rates, 0, 607 sizeof(sta_priv->supported_rates)); 608 sta_priv->supported_rates.op_rate_mode = STA_11n; 609 610 size = ARRAY_SIZE(sta_priv->supported_rates.dsss_rates); 611 rates_table = sta_priv->supported_rates.dsss_rates; 612 if (band == NL80211_BAND_2GHZ) { 613 for (i = 0; i < size; i++) { 614 if (rates & 0x01) { 615 rates_table[i] = wcn_2ghz_rates[i].hw_value; 616 rates = rates >> 1; 617 } 618 } 619 } 620 621 size = ARRAY_SIZE(sta_priv->supported_rates.ofdm_rates); 622 rates_table = sta_priv->supported_rates.ofdm_rates; 623 for (i = 0; i < size; i++) { 624 if (rates & 0x01) { 625 rates_table[i] = wcn_5ghz_rates[i].hw_value; 626 rates = rates >> 1; 627 } 628 } 629 630 if (sta->ht_cap.ht_supported) { 631 BUILD_BUG_ON(sizeof(sta->ht_cap.mcs.rx_mask) > 632 sizeof(sta_priv->supported_rates.supported_mcs_set)); 633 memcpy(sta_priv->supported_rates.supported_mcs_set, 634 sta->ht_cap.mcs.rx_mask, 635 sizeof(sta->ht_cap.mcs.rx_mask)); 636 } 637 } 638 void wcn36xx_set_default_rates(struct wcn36xx_hal_supported_rates *rates) 639 { 640 u16 ofdm_rates[WCN36XX_HAL_NUM_OFDM_RATES] = { 641 HW_RATE_INDEX_6MBPS, 642 HW_RATE_INDEX_9MBPS, 643 HW_RATE_INDEX_12MBPS, 644 HW_RATE_INDEX_18MBPS, 645 HW_RATE_INDEX_24MBPS, 646 HW_RATE_INDEX_36MBPS, 647 HW_RATE_INDEX_48MBPS, 648 HW_RATE_INDEX_54MBPS 649 }; 650 u16 dsss_rates[WCN36XX_HAL_NUM_DSSS_RATES] = { 651 HW_RATE_INDEX_1MBPS, 652 HW_RATE_INDEX_2MBPS, 653 HW_RATE_INDEX_5_5MBPS, 654 HW_RATE_INDEX_11MBPS 655 }; 656 657 rates->op_rate_mode = STA_11n; 658 memcpy(rates->dsss_rates, dsss_rates, 659 sizeof(*dsss_rates) * WCN36XX_HAL_NUM_DSSS_RATES); 660 memcpy(rates->ofdm_rates, ofdm_rates, 661 sizeof(*ofdm_rates) * WCN36XX_HAL_NUM_OFDM_RATES); 662 rates->supported_mcs_set[0] = 0xFF; 663 } 664 static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw, 665 struct ieee80211_vif *vif, 666 struct ieee80211_bss_conf *bss_conf, 667 u32 changed) 668 { 669 struct wcn36xx *wcn = hw->priv; 670 struct sk_buff *skb = NULL; 671 u16 tim_off, tim_len; 672 enum wcn36xx_hal_link_state link_state; 673 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); 674 675 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss info changed vif %p changed 0x%08x\n", 676 vif, changed); 677 678 if (changed & BSS_CHANGED_BEACON_INFO) { 679 wcn36xx_dbg(WCN36XX_DBG_MAC, 680 "mac bss changed dtim period %d\n", 681 bss_conf->dtim_period); 682 683 vif_priv->dtim_period = bss_conf->dtim_period; 684 } 685 686 if (changed & BSS_CHANGED_PS) { 687 wcn36xx_dbg(WCN36XX_DBG_MAC, 688 "mac bss PS set %d\n", 689 bss_conf->ps); 690 if (bss_conf->ps) { 691 wcn36xx_pmc_enter_bmps_state(wcn, vif); 692 } else { 693 wcn36xx_pmc_exit_bmps_state(wcn, vif); 694 } 695 } 696 697 if (changed & BSS_CHANGED_BSSID) { 698 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss changed_bssid %pM\n", 699 bss_conf->bssid); 700 701 if (!is_zero_ether_addr(bss_conf->bssid)) { 702 vif_priv->is_joining = true; 703 vif_priv->bss_index = WCN36XX_HAL_BSS_INVALID_IDX; 704 wcn36xx_smd_join(wcn, bss_conf->bssid, 705 vif->addr, WCN36XX_HW_CHANNEL(wcn)); 706 wcn36xx_smd_config_bss(wcn, vif, NULL, 707 bss_conf->bssid, false); 708 } else { 709 vif_priv->is_joining = false; 710 wcn36xx_smd_delete_bss(wcn, vif); 711 vif_priv->encrypt_type = WCN36XX_HAL_ED_NONE; 712 } 713 } 714 715 if (changed & BSS_CHANGED_SSID) { 716 wcn36xx_dbg(WCN36XX_DBG_MAC, 717 "mac bss changed ssid\n"); 718 wcn36xx_dbg_dump(WCN36XX_DBG_MAC, "ssid ", 719 bss_conf->ssid, bss_conf->ssid_len); 720 721 vif_priv->ssid.length = bss_conf->ssid_len; 722 memcpy(&vif_priv->ssid.ssid, 723 bss_conf->ssid, 724 bss_conf->ssid_len); 725 } 726 727 if (changed & BSS_CHANGED_ASSOC) { 728 vif_priv->is_joining = false; 729 if (bss_conf->assoc) { 730 struct ieee80211_sta *sta; 731 struct wcn36xx_sta *sta_priv; 732 733 wcn36xx_dbg(WCN36XX_DBG_MAC, 734 "mac assoc bss %pM vif %pM AID=%d\n", 735 bss_conf->bssid, 736 vif->addr, 737 bss_conf->aid); 738 739 vif_priv->sta_assoc = true; 740 rcu_read_lock(); 741 sta = ieee80211_find_sta(vif, bss_conf->bssid); 742 if (!sta) { 743 wcn36xx_err("sta %pM is not found\n", 744 bss_conf->bssid); 745 rcu_read_unlock(); 746 goto out; 747 } 748 sta_priv = wcn36xx_sta_to_priv(sta); 749 750 wcn36xx_update_allowed_rates(sta, WCN36XX_BAND(wcn)); 751 752 wcn36xx_smd_set_link_st(wcn, bss_conf->bssid, 753 vif->addr, 754 WCN36XX_HAL_LINK_POSTASSOC_STATE); 755 wcn36xx_smd_config_bss(wcn, vif, sta, 756 bss_conf->bssid, 757 true); 758 sta_priv->aid = bss_conf->aid; 759 /* 760 * config_sta must be called from because this is the 761 * place where AID is available. 762 */ 763 wcn36xx_smd_config_sta(wcn, vif, sta); 764 rcu_read_unlock(); 765 } else { 766 wcn36xx_dbg(WCN36XX_DBG_MAC, 767 "disassociated bss %pM vif %pM AID=%d\n", 768 bss_conf->bssid, 769 vif->addr, 770 bss_conf->aid); 771 vif_priv->sta_assoc = false; 772 wcn36xx_smd_set_link_st(wcn, 773 bss_conf->bssid, 774 vif->addr, 775 WCN36XX_HAL_LINK_IDLE_STATE); 776 } 777 } 778 779 if (changed & BSS_CHANGED_AP_PROBE_RESP) { 780 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss changed ap probe resp\n"); 781 skb = ieee80211_proberesp_get(hw, vif); 782 if (!skb) { 783 wcn36xx_err("failed to alloc probereq skb\n"); 784 goto out; 785 } 786 787 wcn36xx_smd_update_proberesp_tmpl(wcn, vif, skb); 788 dev_kfree_skb(skb); 789 } 790 791 if (changed & BSS_CHANGED_BEACON_ENABLED || 792 changed & BSS_CHANGED_BEACON) { 793 wcn36xx_dbg(WCN36XX_DBG_MAC, 794 "mac bss changed beacon enabled %d\n", 795 bss_conf->enable_beacon); 796 797 if (bss_conf->enable_beacon) { 798 vif_priv->dtim_period = bss_conf->dtim_period; 799 vif_priv->bss_index = WCN36XX_HAL_BSS_INVALID_IDX; 800 wcn36xx_smd_config_bss(wcn, vif, NULL, 801 vif->addr, false); 802 skb = ieee80211_beacon_get_tim(hw, vif, &tim_off, 803 &tim_len); 804 if (!skb) { 805 wcn36xx_err("failed to alloc beacon skb\n"); 806 goto out; 807 } 808 wcn36xx_smd_send_beacon(wcn, vif, skb, tim_off, 0); 809 dev_kfree_skb(skb); 810 811 if (vif->type == NL80211_IFTYPE_ADHOC || 812 vif->type == NL80211_IFTYPE_MESH_POINT) 813 link_state = WCN36XX_HAL_LINK_IBSS_STATE; 814 else 815 link_state = WCN36XX_HAL_LINK_AP_STATE; 816 817 wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr, 818 link_state); 819 } else { 820 wcn36xx_smd_delete_bss(wcn, vif); 821 wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr, 822 WCN36XX_HAL_LINK_IDLE_STATE); 823 } 824 } 825 out: 826 return; 827 } 828 829 /* this is required when using IEEE80211_HW_HAS_RATE_CONTROL */ 830 static int wcn36xx_set_rts_threshold(struct ieee80211_hw *hw, u32 value) 831 { 832 struct wcn36xx *wcn = hw->priv; 833 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac set RTS threshold %d\n", value); 834 835 wcn36xx_smd_update_cfg(wcn, WCN36XX_HAL_CFG_RTS_THRESHOLD, value); 836 return 0; 837 } 838 839 static void wcn36xx_remove_interface(struct ieee80211_hw *hw, 840 struct ieee80211_vif *vif) 841 { 842 struct wcn36xx *wcn = hw->priv; 843 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); 844 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac remove interface vif %p\n", vif); 845 846 list_del(&vif_priv->list); 847 wcn36xx_smd_delete_sta_self(wcn, vif->addr); 848 } 849 850 static int wcn36xx_add_interface(struct ieee80211_hw *hw, 851 struct ieee80211_vif *vif) 852 { 853 struct wcn36xx *wcn = hw->priv; 854 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); 855 856 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac add interface vif %p type %d\n", 857 vif, vif->type); 858 859 if (!(NL80211_IFTYPE_STATION == vif->type || 860 NL80211_IFTYPE_AP == vif->type || 861 NL80211_IFTYPE_ADHOC == vif->type || 862 NL80211_IFTYPE_MESH_POINT == vif->type)) { 863 wcn36xx_warn("Unsupported interface type requested: %d\n", 864 vif->type); 865 return -EOPNOTSUPP; 866 } 867 868 list_add(&vif_priv->list, &wcn->vif_list); 869 wcn36xx_smd_add_sta_self(wcn, vif); 870 871 return 0; 872 } 873 874 static int wcn36xx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 875 struct ieee80211_sta *sta) 876 { 877 struct wcn36xx *wcn = hw->priv; 878 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); 879 struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta); 880 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta add vif %p sta %pM\n", 881 vif, sta->addr); 882 883 spin_lock_init(&sta_priv->ampdu_lock); 884 sta_priv->vif = vif_priv; 885 /* 886 * For STA mode HW will be configured on BSS_CHANGED_ASSOC because 887 * at this stage AID is not available yet. 888 */ 889 if (NL80211_IFTYPE_STATION != vif->type) { 890 wcn36xx_update_allowed_rates(sta, WCN36XX_BAND(wcn)); 891 sta_priv->aid = sta->aid; 892 wcn36xx_smd_config_sta(wcn, vif, sta); 893 } 894 return 0; 895 } 896 897 static int wcn36xx_sta_remove(struct ieee80211_hw *hw, 898 struct ieee80211_vif *vif, 899 struct ieee80211_sta *sta) 900 { 901 struct wcn36xx *wcn = hw->priv; 902 struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta); 903 904 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta remove vif %p sta %pM index %d\n", 905 vif, sta->addr, sta_priv->sta_index); 906 907 wcn36xx_smd_delete_sta(wcn, sta_priv->sta_index); 908 sta_priv->vif = NULL; 909 return 0; 910 } 911 912 #ifdef CONFIG_PM 913 914 static int wcn36xx_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wow) 915 { 916 struct wcn36xx *wcn = hw->priv; 917 918 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac suspend\n"); 919 920 flush_workqueue(wcn->hal_ind_wq); 921 wcn36xx_smd_set_power_params(wcn, true); 922 return 0; 923 } 924 925 static int wcn36xx_resume(struct ieee80211_hw *hw) 926 { 927 struct wcn36xx *wcn = hw->priv; 928 929 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac resume\n"); 930 931 flush_workqueue(wcn->hal_ind_wq); 932 wcn36xx_smd_set_power_params(wcn, false); 933 return 0; 934 } 935 936 #endif 937 938 static int wcn36xx_ampdu_action(struct ieee80211_hw *hw, 939 struct ieee80211_vif *vif, 940 struct ieee80211_ampdu_params *params) 941 { 942 struct wcn36xx *wcn = hw->priv; 943 struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(params->sta); 944 struct ieee80211_sta *sta = params->sta; 945 enum ieee80211_ampdu_mlme_action action = params->action; 946 u16 tid = params->tid; 947 u16 *ssn = ¶ms->ssn; 948 949 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu action action %d tid %d\n", 950 action, tid); 951 952 switch (action) { 953 case IEEE80211_AMPDU_RX_START: 954 sta_priv->tid = tid; 955 wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 0, 956 get_sta_index(vif, sta_priv)); 957 wcn36xx_smd_add_ba(wcn); 958 wcn36xx_smd_trigger_ba(wcn, get_sta_index(vif, sta_priv)); 959 break; 960 case IEEE80211_AMPDU_RX_STOP: 961 wcn36xx_smd_del_ba(wcn, tid, get_sta_index(vif, sta_priv)); 962 break; 963 case IEEE80211_AMPDU_TX_START: 964 spin_lock_bh(&sta_priv->ampdu_lock); 965 sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_START; 966 spin_unlock_bh(&sta_priv->ampdu_lock); 967 968 ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); 969 break; 970 case IEEE80211_AMPDU_TX_OPERATIONAL: 971 spin_lock_bh(&sta_priv->ampdu_lock); 972 sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_OPERATIONAL; 973 spin_unlock_bh(&sta_priv->ampdu_lock); 974 975 wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 1, 976 get_sta_index(vif, sta_priv)); 977 break; 978 case IEEE80211_AMPDU_TX_STOP_FLUSH: 979 case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: 980 case IEEE80211_AMPDU_TX_STOP_CONT: 981 spin_lock_bh(&sta_priv->ampdu_lock); 982 sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_NONE; 983 spin_unlock_bh(&sta_priv->ampdu_lock); 984 985 ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); 986 break; 987 default: 988 wcn36xx_err("Unknown AMPDU action\n"); 989 } 990 991 return 0; 992 } 993 994 static const struct ieee80211_ops wcn36xx_ops = { 995 .start = wcn36xx_start, 996 .stop = wcn36xx_stop, 997 .add_interface = wcn36xx_add_interface, 998 .remove_interface = wcn36xx_remove_interface, 999 #ifdef CONFIG_PM 1000 .suspend = wcn36xx_suspend, 1001 .resume = wcn36xx_resume, 1002 #endif 1003 .config = wcn36xx_config, 1004 .prepare_multicast = wcn36xx_prepare_multicast, 1005 .configure_filter = wcn36xx_configure_filter, 1006 .tx = wcn36xx_tx, 1007 .set_key = wcn36xx_set_key, 1008 .sw_scan_start = wcn36xx_sw_scan_start, 1009 .sw_scan_complete = wcn36xx_sw_scan_complete, 1010 .bss_info_changed = wcn36xx_bss_info_changed, 1011 .set_rts_threshold = wcn36xx_set_rts_threshold, 1012 .sta_add = wcn36xx_sta_add, 1013 .sta_remove = wcn36xx_sta_remove, 1014 .ampdu_action = wcn36xx_ampdu_action, 1015 }; 1016 1017 static int wcn36xx_init_ieee80211(struct wcn36xx *wcn) 1018 { 1019 int ret = 0; 1020 1021 static const u32 cipher_suites[] = { 1022 WLAN_CIPHER_SUITE_WEP40, 1023 WLAN_CIPHER_SUITE_WEP104, 1024 WLAN_CIPHER_SUITE_TKIP, 1025 WLAN_CIPHER_SUITE_CCMP, 1026 }; 1027 1028 ieee80211_hw_set(wcn->hw, TIMING_BEACON_ONLY); 1029 ieee80211_hw_set(wcn->hw, AMPDU_AGGREGATION); 1030 ieee80211_hw_set(wcn->hw, CONNECTION_MONITOR); 1031 ieee80211_hw_set(wcn->hw, SUPPORTS_PS); 1032 ieee80211_hw_set(wcn->hw, SIGNAL_DBM); 1033 ieee80211_hw_set(wcn->hw, HAS_RATE_CONTROL); 1034 1035 wcn->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | 1036 BIT(NL80211_IFTYPE_AP) | 1037 BIT(NL80211_IFTYPE_ADHOC) | 1038 BIT(NL80211_IFTYPE_MESH_POINT); 1039 1040 wcn->hw->wiphy->bands[NL80211_BAND_2GHZ] = &wcn_band_2ghz; 1041 wcn->hw->wiphy->bands[NL80211_BAND_5GHZ] = &wcn_band_5ghz; 1042 1043 wcn->hw->wiphy->cipher_suites = cipher_suites; 1044 wcn->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); 1045 1046 wcn->hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; 1047 1048 #ifdef CONFIG_PM 1049 wcn->hw->wiphy->wowlan = &wowlan_support; 1050 #endif 1051 1052 wcn->hw->max_listen_interval = 200; 1053 1054 wcn->hw->queues = 4; 1055 1056 SET_IEEE80211_DEV(wcn->hw, wcn->dev); 1057 1058 wcn->hw->sta_data_size = sizeof(struct wcn36xx_sta); 1059 wcn->hw->vif_data_size = sizeof(struct wcn36xx_vif); 1060 1061 return ret; 1062 } 1063 1064 static int wcn36xx_platform_get_resources(struct wcn36xx *wcn, 1065 struct platform_device *pdev) 1066 { 1067 struct resource *res; 1068 /* Set TX IRQ */ 1069 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, 1070 "wcnss_wlantx_irq"); 1071 if (!res) { 1072 wcn36xx_err("failed to get tx_irq\n"); 1073 return -ENOENT; 1074 } 1075 wcn->tx_irq = res->start; 1076 1077 /* Set RX IRQ */ 1078 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, 1079 "wcnss_wlanrx_irq"); 1080 if (!res) { 1081 wcn36xx_err("failed to get rx_irq\n"); 1082 return -ENOENT; 1083 } 1084 wcn->rx_irq = res->start; 1085 1086 /* Map the memory */ 1087 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, 1088 "wcnss_mmio"); 1089 if (!res) { 1090 wcn36xx_err("failed to get mmio\n"); 1091 return -ENOENT; 1092 } 1093 wcn->mmio = ioremap(res->start, resource_size(res)); 1094 if (!wcn->mmio) { 1095 wcn36xx_err("failed to map io memory\n"); 1096 return -ENOMEM; 1097 } 1098 return 0; 1099 } 1100 1101 static int wcn36xx_probe(struct platform_device *pdev) 1102 { 1103 struct ieee80211_hw *hw; 1104 struct wcn36xx *wcn; 1105 int ret; 1106 u8 addr[ETH_ALEN]; 1107 1108 wcn36xx_dbg(WCN36XX_DBG_MAC, "platform probe\n"); 1109 1110 hw = ieee80211_alloc_hw(sizeof(struct wcn36xx), &wcn36xx_ops); 1111 if (!hw) { 1112 wcn36xx_err("failed to alloc hw\n"); 1113 ret = -ENOMEM; 1114 goto out_err; 1115 } 1116 platform_set_drvdata(pdev, hw); 1117 wcn = hw->priv; 1118 wcn->hw = hw; 1119 wcn->dev = &pdev->dev; 1120 wcn->ctrl_ops = pdev->dev.platform_data; 1121 1122 mutex_init(&wcn->hal_mutex); 1123 1124 if (!wcn->ctrl_ops->get_hw_mac(addr)) { 1125 wcn36xx_info("mac address: %pM\n", addr); 1126 SET_IEEE80211_PERM_ADDR(wcn->hw, addr); 1127 } 1128 1129 ret = wcn36xx_platform_get_resources(wcn, pdev); 1130 if (ret) 1131 goto out_wq; 1132 1133 wcn36xx_init_ieee80211(wcn); 1134 ret = ieee80211_register_hw(wcn->hw); 1135 if (ret) 1136 goto out_unmap; 1137 1138 return 0; 1139 1140 out_unmap: 1141 iounmap(wcn->mmio); 1142 out_wq: 1143 ieee80211_free_hw(hw); 1144 out_err: 1145 return ret; 1146 } 1147 static int wcn36xx_remove(struct platform_device *pdev) 1148 { 1149 struct ieee80211_hw *hw = platform_get_drvdata(pdev); 1150 struct wcn36xx *wcn = hw->priv; 1151 wcn36xx_dbg(WCN36XX_DBG_MAC, "platform remove\n"); 1152 1153 release_firmware(wcn->nv); 1154 mutex_destroy(&wcn->hal_mutex); 1155 1156 ieee80211_unregister_hw(hw); 1157 iounmap(wcn->mmio); 1158 ieee80211_free_hw(hw); 1159 1160 return 0; 1161 } 1162 static const struct platform_device_id wcn36xx_platform_id_table[] = { 1163 { 1164 .name = "wcn36xx", 1165 .driver_data = 0 1166 }, 1167 {} 1168 }; 1169 MODULE_DEVICE_TABLE(platform, wcn36xx_platform_id_table); 1170 1171 static struct platform_driver wcn36xx_driver = { 1172 .probe = wcn36xx_probe, 1173 .remove = wcn36xx_remove, 1174 .driver = { 1175 .name = "wcn36xx", 1176 }, 1177 .id_table = wcn36xx_platform_id_table, 1178 }; 1179 1180 static int __init wcn36xx_init(void) 1181 { 1182 platform_driver_register(&wcn36xx_driver); 1183 return 0; 1184 } 1185 module_init(wcn36xx_init); 1186 1187 static void __exit wcn36xx_exit(void) 1188 { 1189 platform_driver_unregister(&wcn36xx_driver); 1190 } 1191 module_exit(wcn36xx_exit); 1192 1193 MODULE_LICENSE("Dual BSD/GPL"); 1194 MODULE_AUTHOR("Eugene Krasnikov k.eugene.e@gmail.com"); 1195 MODULE_FIRMWARE(WLAN_NV_FILE); 1196