aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/wcn36xx
diff options
context:
space:
mode:
authorKalle Valo <kvalo@codeaurora.org>2016-04-26 07:13:59 -0400
committerKalle Valo <kvalo@codeaurora.org>2016-04-26 07:13:59 -0400
commitefd7cef3100b2683ba4ff48943215b9537e9a37c (patch)
tree73a617e1b1cd7212b4c13d36f64e03ed4a9057fc /drivers/net/wireless/ath/wcn36xx
parentf0d8f38cd909e072833a06b79939256c4aebe3a0 (diff)
parentffc03c331a1e7cafac3beb4f89c40fa7d6213d6e (diff)
Merge ath-next from ath.git
ath.git patches for 4.7. Major changes: ath10k * implement set_tsf() for 10.2.4 branch * remove rare MSI range support * remove deprecated firmware API 1 support ath9k * add module parameter to invert LED polarity wcn36xx * fixes to get the driver properly working on Dragonboard 410c
Diffstat (limited to 'drivers/net/wireless/ath/wcn36xx')
-rw-r--r--drivers/net/wireless/ath/wcn36xx/debug.c12
-rw-r--r--drivers/net/wireless/ath/wcn36xx/hal.h55
-rw-r--r--drivers/net/wireless/ath/wcn36xx/main.c133
-rw-r--r--drivers/net/wireless/ath/wcn36xx/pmc.c4
-rw-r--r--drivers/net/wireless/ath/wcn36xx/smd.c224
-rw-r--r--drivers/net/wireless/ath/wcn36xx/smd.h12
-rw-r--r--drivers/net/wireless/ath/wcn36xx/txrx.c8
-rw-r--r--drivers/net/wireless/ath/wcn36xx/wcn36xx.h20
8 files changed, 336 insertions, 132 deletions
diff --git a/drivers/net/wireless/ath/wcn36xx/debug.c b/drivers/net/wireless/ath/wcn36xx/debug.c
index ef44a2da644d..2a6bb62e785c 100644
--- a/drivers/net/wireless/ath/wcn36xx/debug.c
+++ b/drivers/net/wireless/ath/wcn36xx/debug.c
@@ -33,9 +33,7 @@ static ssize_t read_file_bool_bmps(struct file *file, char __user *user_buf,
33 char buf[3]; 33 char buf[3];
34 34
35 list_for_each_entry(vif_priv, &wcn->vif_list, list) { 35 list_for_each_entry(vif_priv, &wcn->vif_list, list) {
36 vif = container_of((void *)vif_priv, 36 vif = wcn36xx_priv_to_vif(vif_priv);
37 struct ieee80211_vif,
38 drv_priv);
39 if (NL80211_IFTYPE_STATION == vif->type) { 37 if (NL80211_IFTYPE_STATION == vif->type) {
40 if (vif_priv->pw_state == WCN36XX_BMPS) 38 if (vif_priv->pw_state == WCN36XX_BMPS)
41 buf[0] = '1'; 39 buf[0] = '1';
@@ -70,9 +68,7 @@ static ssize_t write_file_bool_bmps(struct file *file,
70 case 'Y': 68 case 'Y':
71 case '1': 69 case '1':
72 list_for_each_entry(vif_priv, &wcn->vif_list, list) { 70 list_for_each_entry(vif_priv, &wcn->vif_list, list) {
73 vif = container_of((void *)vif_priv, 71 vif = wcn36xx_priv_to_vif(vif_priv);
74 struct ieee80211_vif,
75 drv_priv);
76 if (NL80211_IFTYPE_STATION == vif->type) { 72 if (NL80211_IFTYPE_STATION == vif->type) {
77 wcn36xx_enable_keep_alive_null_packet(wcn, vif); 73 wcn36xx_enable_keep_alive_null_packet(wcn, vif);
78 wcn36xx_pmc_enter_bmps_state(wcn, vif); 74 wcn36xx_pmc_enter_bmps_state(wcn, vif);
@@ -83,9 +79,7 @@ static ssize_t write_file_bool_bmps(struct file *file,
83 case 'N': 79 case 'N':
84 case '0': 80 case '0':
85 list_for_each_entry(vif_priv, &wcn->vif_list, list) { 81 list_for_each_entry(vif_priv, &wcn->vif_list, list) {
86 vif = container_of((void *)vif_priv, 82 vif = wcn36xx_priv_to_vif(vif_priv);
87 struct ieee80211_vif,
88 drv_priv);
89 if (NL80211_IFTYPE_STATION == vif->type) 83 if (NL80211_IFTYPE_STATION == vif->type)
90 wcn36xx_pmc_exit_bmps_state(wcn, vif); 84 wcn36xx_pmc_exit_bmps_state(wcn, vif);
91 } 85 }
diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h b/drivers/net/wireless/ath/wcn36xx/hal.h
index b947de0fb2e5..658bfb8baabe 100644
--- a/drivers/net/wireless/ath/wcn36xx/hal.h
+++ b/drivers/net/wireless/ath/wcn36xx/hal.h
@@ -48,12 +48,15 @@
48 48
49#define WCN36XX_HAL_IPV4_ADDR_LEN 4 49#define WCN36XX_HAL_IPV4_ADDR_LEN 4
50 50
51#define WALN_HAL_STA_INVALID_IDX 0xFF 51#define WCN36XX_HAL_STA_INVALID_IDX 0xFF
52#define WCN36XX_HAL_BSS_INVALID_IDX 0xFF 52#define WCN36XX_HAL_BSS_INVALID_IDX 0xFF
53 53
54/* Default Beacon template size */ 54/* Default Beacon template size */
55#define BEACON_TEMPLATE_SIZE 0x180 55#define BEACON_TEMPLATE_SIZE 0x180
56 56
57/* Minimum PVM size that the FW expects. See comment in smd.c for details. */
58#define TIM_MIN_PVM_SIZE 6
59
57/* Param Change Bitmap sent to HAL */ 60/* Param Change Bitmap sent to HAL */
58#define PARAM_BCN_INTERVAL_CHANGED (1 << 0) 61#define PARAM_BCN_INTERVAL_CHANGED (1 << 0)
59#define PARAM_SHORT_PREAMBLE_CHANGED (1 << 1) 62#define PARAM_SHORT_PREAMBLE_CHANGED (1 << 1)
@@ -2884,11 +2887,14 @@ struct update_beacon_rsp_msg {
2884struct wcn36xx_hal_send_beacon_req_msg { 2887struct wcn36xx_hal_send_beacon_req_msg {
2885 struct wcn36xx_hal_msg_header header; 2888 struct wcn36xx_hal_msg_header header;
2886 2889
2890 /* length of the template + 6. Only qcom knows why */
2891 u32 beacon_length6;
2892
2887 /* length of the template. */ 2893 /* length of the template. */
2888 u32 beacon_length; 2894 u32 beacon_length;
2889 2895
2890 /* Beacon data. */ 2896 /* Beacon data. */
2891 u8 beacon[BEACON_TEMPLATE_SIZE]; 2897 u8 beacon[BEACON_TEMPLATE_SIZE - sizeof(u32)];
2892 2898
2893 u8 bssid[ETH_ALEN]; 2899 u8 bssid[ETH_ALEN];
2894 2900
@@ -4261,9 +4267,9 @@ struct wcn36xx_hal_rcv_flt_mc_addr_list_type {
4261 u8 data_offset; 4267 u8 data_offset;
4262 4268
4263 u32 mc_addr_count; 4269 u32 mc_addr_count;
4264 u8 mc_addr[ETH_ALEN][WCN36XX_HAL_MAX_NUM_MULTICAST_ADDRESS]; 4270 u8 mc_addr[WCN36XX_HAL_MAX_NUM_MULTICAST_ADDRESS][ETH_ALEN];
4265 u8 bss_index; 4271 u8 bss_index;
4266}; 4272} __packed;
4267 4273
4268struct wcn36xx_hal_set_pkt_filter_rsp_msg { 4274struct wcn36xx_hal_set_pkt_filter_rsp_msg {
4269 struct wcn36xx_hal_msg_header header; 4275 struct wcn36xx_hal_msg_header header;
@@ -4317,7 +4323,7 @@ struct wcn36xx_hal_rcv_flt_pkt_clear_rsp_msg {
4317struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_req_msg { 4323struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_req_msg {
4318 struct wcn36xx_hal_msg_header header; 4324 struct wcn36xx_hal_msg_header header;
4319 struct wcn36xx_hal_rcv_flt_mc_addr_list_type mc_addr_list; 4325 struct wcn36xx_hal_rcv_flt_mc_addr_list_type mc_addr_list;
4320}; 4326} __packed;
4321 4327
4322struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_rsp_msg { 4328struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_rsp_msg {
4323 struct wcn36xx_hal_msg_header header; 4329 struct wcn36xx_hal_msg_header header;
@@ -4383,6 +4389,45 @@ enum place_holder_in_cap_bitmap {
4383 RTT = 20, 4389 RTT = 20,
4384 RATECTRL = 21, 4390 RATECTRL = 21,
4385 WOW = 22, 4391 WOW = 22,
4392 WLAN_ROAM_SCAN_OFFLOAD = 23,
4393 SPECULATIVE_PS_POLL = 24,
4394 SCAN_SCH = 25,
4395 IBSS_HEARTBEAT_OFFLOAD = 26,
4396 WLAN_SCAN_OFFLOAD = 27,
4397 WLAN_PERIODIC_TX_PTRN = 28,
4398 ADVANCE_TDLS = 29,
4399 BATCH_SCAN = 30,
4400 FW_IN_TX_PATH = 31,
4401 EXTENDED_NSOFFLOAD_SLOT = 32,
4402 CH_SWITCH_V1 = 33,
4403 HT40_OBSS_SCAN = 34,
4404 UPDATE_CHANNEL_LIST = 35,
4405 WLAN_MCADDR_FLT = 36,
4406 WLAN_CH144 = 37,
4407 NAN = 38,
4408 TDLS_SCAN_COEXISTENCE = 39,
4409 LINK_LAYER_STATS_MEAS = 40,
4410 MU_MIMO = 41,
4411 EXTENDED_SCAN = 42,
4412 DYNAMIC_WMM_PS = 43,
4413 MAC_SPOOFED_SCAN = 44,
4414 BMU_ERROR_GENERIC_RECOVERY = 45,
4415 DISA = 46,
4416 FW_STATS = 47,
4417 WPS_PRBRSP_TMPL = 48,
4418 BCN_IE_FLT_DELTA = 49,
4419 TDLS_OFF_CHANNEL = 51,
4420 RTT3 = 52,
4421 MGMT_FRAME_LOGGING = 53,
4422 ENHANCED_TXBD_COMPLETION = 54,
4423 LOGGING_ENHANCEMENT = 55,
4424 EXT_SCAN_ENHANCED = 56,
4425 MEMORY_DUMP_SUPPORTED = 57,
4426 PER_PKT_STATS_SUPPORTED = 58,
4427 EXT_LL_STAT = 60,
4428 WIFI_CONFIG = 61,
4429 ANTENNA_DIVERSITY_SELECTION = 62,
4430
4386 MAX_FEATURE_SUPPORTED = 128, 4431 MAX_FEATURE_SUPPORTED = 128,
4387}; 4432};
4388 4433
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c
index 9a1db3bbec4e..a920d7020148 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -201,7 +201,45 @@ static const char * const wcn36xx_caps_names[] = {
201 "BCN_FILTER", /* 19 */ 201 "BCN_FILTER", /* 19 */
202 "RTT", /* 20 */ 202 "RTT", /* 20 */
203 "RATECTRL", /* 21 */ 203 "RATECTRL", /* 21 */
204 "WOW" /* 22 */ 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 */
205}; 243};
206 244
207static const char *wcn36xx_get_cap_name(enum place_holder_in_cap_bitmap x) 245static const char *wcn36xx_get_cap_name(enum place_holder_in_cap_bitmap x)
@@ -287,6 +325,7 @@ static int wcn36xx_start(struct ieee80211_hw *hw)
287 } 325 }
288 326
289 wcn36xx_detect_chip_version(wcn); 327 wcn36xx_detect_chip_version(wcn);
328 wcn36xx_smd_update_cfg(wcn, WCN36XX_HAL_CFG_ENABLE_MC_ADDR_LIST, 1);
290 329
291 /* DMA channel initialization */ 330 /* DMA channel initialization */
292 ret = wcn36xx_dxe_init(wcn); 331 ret = wcn36xx_dxe_init(wcn);
@@ -346,9 +385,7 @@ static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed)
346 wcn36xx_dbg(WCN36XX_DBG_MAC, "wcn36xx_config channel switch=%d\n", 385 wcn36xx_dbg(WCN36XX_DBG_MAC, "wcn36xx_config channel switch=%d\n",
347 ch); 386 ch);
348 list_for_each_entry(tmp, &wcn->vif_list, list) { 387 list_for_each_entry(tmp, &wcn->vif_list, list) {
349 vif = container_of((void *)tmp, 388 vif = wcn36xx_priv_to_vif(tmp);
350 struct ieee80211_vif,
351 drv_priv);
352 wcn36xx_smd_switch_channel(wcn, vif, ch); 389 wcn36xx_smd_switch_channel(wcn, vif, ch);
353 } 390 }
354 } 391 }
@@ -356,15 +393,57 @@ static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed)
356 return 0; 393 return 0;
357} 394}
358 395
359#define WCN36XX_SUPPORTED_FILTERS (0)
360
361static void wcn36xx_configure_filter(struct ieee80211_hw *hw, 396static void wcn36xx_configure_filter(struct ieee80211_hw *hw,
362 unsigned int changed, 397 unsigned int changed,
363 unsigned int *total, u64 multicast) 398 unsigned int *total, u64 multicast)
364{ 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
365 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac configure filter\n"); 405 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac configure filter\n");
366 406
367 *total &= WCN36XX_SUPPORTED_FILTERS; 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
422static 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;
368} 447}
369 448
370static void wcn36xx_tx(struct ieee80211_hw *hw, 449static void wcn36xx_tx(struct ieee80211_hw *hw,
@@ -375,7 +454,7 @@ static void wcn36xx_tx(struct ieee80211_hw *hw,
375 struct wcn36xx_sta *sta_priv = NULL; 454 struct wcn36xx_sta *sta_priv = NULL;
376 455
377 if (control->sta) 456 if (control->sta)
378 sta_priv = (struct wcn36xx_sta *)control->sta->drv_priv; 457 sta_priv = wcn36xx_sta_to_priv(control->sta);
379 458
380 if (wcn36xx_start_tx(wcn, sta_priv, skb)) 459 if (wcn36xx_start_tx(wcn, sta_priv, skb))
381 ieee80211_free_txskb(wcn->hw, skb); 460 ieee80211_free_txskb(wcn->hw, skb);
@@ -387,8 +466,8 @@ static int wcn36xx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
387 struct ieee80211_key_conf *key_conf) 466 struct ieee80211_key_conf *key_conf)
388{ 467{
389 struct wcn36xx *wcn = hw->priv; 468 struct wcn36xx *wcn = hw->priv;
390 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 469 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
391 struct wcn36xx_sta *sta_priv = vif_priv->sta; 470 struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
392 int ret = 0; 471 int ret = 0;
393 u8 key[WLAN_MAX_KEY_LEN]; 472 u8 key[WLAN_MAX_KEY_LEN];
394 473
@@ -473,6 +552,7 @@ static int wcn36xx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
473 break; 552 break;
474 case DISABLE_KEY: 553 case DISABLE_KEY:
475 if (!(IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags)) { 554 if (!(IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags)) {
555 vif_priv->encrypt_type = WCN36XX_HAL_ED_NONE;
476 wcn36xx_smd_remove_bsskey(wcn, 556 wcn36xx_smd_remove_bsskey(wcn,
477 vif_priv->encrypt_type, 557 vif_priv->encrypt_type,
478 key_conf->keyidx); 558 key_conf->keyidx);
@@ -520,7 +600,7 @@ static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta,
520{ 600{
521 int i, size; 601 int i, size;
522 u16 *rates_table; 602 u16 *rates_table;
523 struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv; 603 struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
524 u32 rates = sta->supp_rates[band]; 604 u32 rates = sta->supp_rates[band];
525 605
526 memset(&sta_priv->supported_rates, 0, 606 memset(&sta_priv->supported_rates, 0,
@@ -590,7 +670,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
590 struct sk_buff *skb = NULL; 670 struct sk_buff *skb = NULL;
591 u16 tim_off, tim_len; 671 u16 tim_off, tim_len;
592 enum wcn36xx_hal_link_state link_state; 672 enum wcn36xx_hal_link_state link_state;
593 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 673 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
594 674
595 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss info changed vif %p changed 0x%08x\n", 675 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss info changed vif %p changed 0x%08x\n",
596 vif, changed); 676 vif, changed);
@@ -620,7 +700,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
620 700
621 if (!is_zero_ether_addr(bss_conf->bssid)) { 701 if (!is_zero_ether_addr(bss_conf->bssid)) {
622 vif_priv->is_joining = true; 702 vif_priv->is_joining = true;
623 vif_priv->bss_index = 0xff; 703 vif_priv->bss_index = WCN36XX_HAL_BSS_INVALID_IDX;
624 wcn36xx_smd_join(wcn, bss_conf->bssid, 704 wcn36xx_smd_join(wcn, bss_conf->bssid,
625 vif->addr, WCN36XX_HW_CHANNEL(wcn)); 705 vif->addr, WCN36XX_HW_CHANNEL(wcn));
626 wcn36xx_smd_config_bss(wcn, vif, NULL, 706 wcn36xx_smd_config_bss(wcn, vif, NULL,
@@ -628,6 +708,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
628 } else { 708 } else {
629 vif_priv->is_joining = false; 709 vif_priv->is_joining = false;
630 wcn36xx_smd_delete_bss(wcn, vif); 710 wcn36xx_smd_delete_bss(wcn, vif);
711 vif_priv->encrypt_type = WCN36XX_HAL_ED_NONE;
631 } 712 }
632 } 713 }
633 714
@@ -655,6 +736,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
655 vif->addr, 736 vif->addr,
656 bss_conf->aid); 737 bss_conf->aid);
657 738
739 vif_priv->sta_assoc = true;
658 rcu_read_lock(); 740 rcu_read_lock();
659 sta = ieee80211_find_sta(vif, bss_conf->bssid); 741 sta = ieee80211_find_sta(vif, bss_conf->bssid);
660 if (!sta) { 742 if (!sta) {
@@ -663,7 +745,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
663 rcu_read_unlock(); 745 rcu_read_unlock();
664 goto out; 746 goto out;
665 } 747 }
666 sta_priv = (struct wcn36xx_sta *)sta->drv_priv; 748 sta_priv = wcn36xx_sta_to_priv(sta);
667 749
668 wcn36xx_update_allowed_rates(sta, WCN36XX_BAND(wcn)); 750 wcn36xx_update_allowed_rates(sta, WCN36XX_BAND(wcn));
669 751
@@ -686,6 +768,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
686 bss_conf->bssid, 768 bss_conf->bssid,
687 vif->addr, 769 vif->addr,
688 bss_conf->aid); 770 bss_conf->aid);
771 vif_priv->sta_assoc = false;
689 wcn36xx_smd_set_link_st(wcn, 772 wcn36xx_smd_set_link_st(wcn,
690 bss_conf->bssid, 773 bss_conf->bssid,
691 vif->addr, 774 vif->addr,
@@ -713,7 +796,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
713 796
714 if (bss_conf->enable_beacon) { 797 if (bss_conf->enable_beacon) {
715 vif_priv->dtim_period = bss_conf->dtim_period; 798 vif_priv->dtim_period = bss_conf->dtim_period;
716 vif_priv->bss_index = 0xff; 799 vif_priv->bss_index = WCN36XX_HAL_BSS_INVALID_IDX;
717 wcn36xx_smd_config_bss(wcn, vif, NULL, 800 wcn36xx_smd_config_bss(wcn, vif, NULL,
718 vif->addr, false); 801 vif->addr, false);
719 skb = ieee80211_beacon_get_tim(hw, vif, &tim_off, 802 skb = ieee80211_beacon_get_tim(hw, vif, &tim_off,
@@ -734,9 +817,9 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
734 wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr, 817 wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr,
735 link_state); 818 link_state);
736 } else { 819 } else {
820 wcn36xx_smd_delete_bss(wcn, vif);
737 wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr, 821 wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr,
738 WCN36XX_HAL_LINK_IDLE_STATE); 822 WCN36XX_HAL_LINK_IDLE_STATE);
739 wcn36xx_smd_delete_bss(wcn, vif);
740 } 823 }
741 } 824 }
742out: 825out:
@@ -757,7 +840,7 @@ static void wcn36xx_remove_interface(struct ieee80211_hw *hw,
757 struct ieee80211_vif *vif) 840 struct ieee80211_vif *vif)
758{ 841{
759 struct wcn36xx *wcn = hw->priv; 842 struct wcn36xx *wcn = hw->priv;
760 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 843 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
761 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac remove interface vif %p\n", vif); 844 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac remove interface vif %p\n", vif);
762 845
763 list_del(&vif_priv->list); 846 list_del(&vif_priv->list);
@@ -768,7 +851,7 @@ static int wcn36xx_add_interface(struct ieee80211_hw *hw,
768 struct ieee80211_vif *vif) 851 struct ieee80211_vif *vif)
769{ 852{
770 struct wcn36xx *wcn = hw->priv; 853 struct wcn36xx *wcn = hw->priv;
771 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 854 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
772 855
773 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac add interface vif %p type %d\n", 856 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac add interface vif %p type %d\n",
774 vif, vif->type); 857 vif, vif->type);
@@ -792,13 +875,12 @@ static int wcn36xx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
792 struct ieee80211_sta *sta) 875 struct ieee80211_sta *sta)
793{ 876{
794 struct wcn36xx *wcn = hw->priv; 877 struct wcn36xx *wcn = hw->priv;
795 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 878 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
796 struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv; 879 struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
797 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta add vif %p sta %pM\n", 880 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta add vif %p sta %pM\n",
798 vif, sta->addr); 881 vif, sta->addr);
799 882
800 spin_lock_init(&sta_priv->ampdu_lock); 883 spin_lock_init(&sta_priv->ampdu_lock);
801 vif_priv->sta = sta_priv;
802 sta_priv->vif = vif_priv; 884 sta_priv->vif = vif_priv;
803 /* 885 /*
804 * For STA mode HW will be configured on BSS_CHANGED_ASSOC because 886 * For STA mode HW will be configured on BSS_CHANGED_ASSOC because
@@ -817,14 +899,12 @@ static int wcn36xx_sta_remove(struct ieee80211_hw *hw,
817 struct ieee80211_sta *sta) 899 struct ieee80211_sta *sta)
818{ 900{
819 struct wcn36xx *wcn = hw->priv; 901 struct wcn36xx *wcn = hw->priv;
820 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 902 struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
821 struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv;
822 903
823 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta remove vif %p sta %pM index %d\n", 904 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta remove vif %p sta %pM index %d\n",
824 vif, sta->addr, sta_priv->sta_index); 905 vif, sta->addr, sta_priv->sta_index);
825 906
826 wcn36xx_smd_delete_sta(wcn, sta_priv->sta_index); 907 wcn36xx_smd_delete_sta(wcn, sta_priv->sta_index);
827 vif_priv->sta = NULL;
828 sta_priv->vif = NULL; 908 sta_priv->vif = NULL;
829 return 0; 909 return 0;
830} 910}
@@ -860,7 +940,7 @@ static int wcn36xx_ampdu_action(struct ieee80211_hw *hw,
860 struct ieee80211_ampdu_params *params) 940 struct ieee80211_ampdu_params *params)
861{ 941{
862 struct wcn36xx *wcn = hw->priv; 942 struct wcn36xx *wcn = hw->priv;
863 struct wcn36xx_sta *sta_priv = NULL; 943 struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(params->sta);
864 struct ieee80211_sta *sta = params->sta; 944 struct ieee80211_sta *sta = params->sta;
865 enum ieee80211_ampdu_mlme_action action = params->action; 945 enum ieee80211_ampdu_mlme_action action = params->action;
866 u16 tid = params->tid; 946 u16 tid = params->tid;
@@ -869,8 +949,6 @@ static int wcn36xx_ampdu_action(struct ieee80211_hw *hw,
869 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu action action %d tid %d\n", 949 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu action action %d tid %d\n",
870 action, tid); 950 action, tid);
871 951
872 sta_priv = (struct wcn36xx_sta *)sta->drv_priv;
873
874 switch (action) { 952 switch (action) {
875 case IEEE80211_AMPDU_RX_START: 953 case IEEE80211_AMPDU_RX_START:
876 sta_priv->tid = tid; 954 sta_priv->tid = tid;
@@ -923,6 +1001,7 @@ static const struct ieee80211_ops wcn36xx_ops = {
923 .resume = wcn36xx_resume, 1001 .resume = wcn36xx_resume,
924#endif 1002#endif
925 .config = wcn36xx_config, 1003 .config = wcn36xx_config,
1004 .prepare_multicast = wcn36xx_prepare_multicast,
926 .configure_filter = wcn36xx_configure_filter, 1005 .configure_filter = wcn36xx_configure_filter,
927 .tx = wcn36xx_tx, 1006 .tx = wcn36xx_tx,
928 .set_key = wcn36xx_set_key, 1007 .set_key = wcn36xx_set_key,
diff --git a/drivers/net/wireless/ath/wcn36xx/pmc.c b/drivers/net/wireless/ath/wcn36xx/pmc.c
index 28b515c81b0e..589fe5f70971 100644
--- a/drivers/net/wireless/ath/wcn36xx/pmc.c
+++ b/drivers/net/wireless/ath/wcn36xx/pmc.c
@@ -22,7 +22,7 @@ int wcn36xx_pmc_enter_bmps_state(struct wcn36xx *wcn,
22 struct ieee80211_vif *vif) 22 struct ieee80211_vif *vif)
23{ 23{
24 int ret = 0; 24 int ret = 0;
25 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 25 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
26 /* TODO: Make sure the TX chain clean */ 26 /* TODO: Make sure the TX chain clean */
27 ret = wcn36xx_smd_enter_bmps(wcn, vif); 27 ret = wcn36xx_smd_enter_bmps(wcn, vif);
28 if (!ret) { 28 if (!ret) {
@@ -42,7 +42,7 @@ int wcn36xx_pmc_enter_bmps_state(struct wcn36xx *wcn,
42int wcn36xx_pmc_exit_bmps_state(struct wcn36xx *wcn, 42int wcn36xx_pmc_exit_bmps_state(struct wcn36xx *wcn,
43 struct ieee80211_vif *vif) 43 struct ieee80211_vif *vif)
44{ 44{
45 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 45 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
46 46
47 if (WCN36XX_BMPS != vif_priv->pw_state) { 47 if (WCN36XX_BMPS != vif_priv->pw_state) {
48 wcn36xx_err("Not in BMPS mode, no need to exit from BMPS mode!\n"); 48 wcn36xx_err("Not in BMPS mode, no need to exit from BMPS mode!\n");
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c
index 96992a2c4b42..e8b630c4f11e 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -191,16 +191,16 @@ static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn,
191 struct ieee80211_sta *sta, 191 struct ieee80211_sta *sta,
192 struct wcn36xx_hal_config_sta_params *sta_params) 192 struct wcn36xx_hal_config_sta_params *sta_params)
193{ 193{
194 struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv; 194 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
195 struct wcn36xx_sta *priv_sta = NULL; 195 struct wcn36xx_sta *sta_priv = NULL;
196 if (vif->type == NL80211_IFTYPE_ADHOC || 196 if (vif->type == NL80211_IFTYPE_ADHOC ||
197 vif->type == NL80211_IFTYPE_AP || 197 vif->type == NL80211_IFTYPE_AP ||
198 vif->type == NL80211_IFTYPE_MESH_POINT) { 198 vif->type == NL80211_IFTYPE_MESH_POINT) {
199 sta_params->type = 1; 199 sta_params->type = 1;
200 sta_params->sta_index = 0xFF; 200 sta_params->sta_index = WCN36XX_HAL_STA_INVALID_IDX;
201 } else { 201 } else {
202 sta_params->type = 0; 202 sta_params->type = 0;
203 sta_params->sta_index = 1; 203 sta_params->sta_index = vif_priv->self_sta_index;
204 } 204 }
205 205
206 sta_params->listen_interval = WCN36XX_LISTEN_INTERVAL(wcn); 206 sta_params->listen_interval = WCN36XX_LISTEN_INTERVAL(wcn);
@@ -215,7 +215,7 @@ static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn,
215 else 215 else
216 memcpy(&sta_params->bssid, vif->addr, ETH_ALEN); 216 memcpy(&sta_params->bssid, vif->addr, ETH_ALEN);
217 217
218 sta_params->encrypt_type = priv_vif->encrypt_type; 218 sta_params->encrypt_type = vif_priv->encrypt_type;
219 sta_params->short_preamble_supported = true; 219 sta_params->short_preamble_supported = true;
220 220
221 sta_params->rifs_mode = 0; 221 sta_params->rifs_mode = 0;
@@ -224,21 +224,21 @@ static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn,
224 sta_params->uapsd = 0; 224 sta_params->uapsd = 0;
225 sta_params->mimo_ps = WCN36XX_HAL_HT_MIMO_PS_STATIC; 225 sta_params->mimo_ps = WCN36XX_HAL_HT_MIMO_PS_STATIC;
226 sta_params->max_ampdu_duration = 0; 226 sta_params->max_ampdu_duration = 0;
227 sta_params->bssid_index = priv_vif->bss_index; 227 sta_params->bssid_index = vif_priv->bss_index;
228 sta_params->p2p = 0; 228 sta_params->p2p = 0;
229 229
230 if (sta) { 230 if (sta) {
231 priv_sta = (struct wcn36xx_sta *)sta->drv_priv; 231 sta_priv = wcn36xx_sta_to_priv(sta);
232 if (NL80211_IFTYPE_STATION == vif->type) 232 if (NL80211_IFTYPE_STATION == vif->type)
233 memcpy(&sta_params->bssid, sta->addr, ETH_ALEN); 233 memcpy(&sta_params->bssid, sta->addr, ETH_ALEN);
234 else 234 else
235 memcpy(&sta_params->mac, sta->addr, ETH_ALEN); 235 memcpy(&sta_params->mac, sta->addr, ETH_ALEN);
236 sta_params->wmm_enabled = sta->wme; 236 sta_params->wmm_enabled = sta->wme;
237 sta_params->max_sp_len = sta->max_sp; 237 sta_params->max_sp_len = sta->max_sp;
238 sta_params->aid = priv_sta->aid; 238 sta_params->aid = sta_priv->aid;
239 wcn36xx_smd_set_sta_ht_params(sta, sta_params); 239 wcn36xx_smd_set_sta_ht_params(sta, sta_params);
240 memcpy(&sta_params->supported_rates, &priv_sta->supported_rates, 240 memcpy(&sta_params->supported_rates, &sta_priv->supported_rates,
241 sizeof(priv_sta->supported_rates)); 241 sizeof(sta_priv->supported_rates));
242 } else { 242 } else {
243 wcn36xx_set_default_rates(&sta_params->supported_rates); 243 wcn36xx_set_default_rates(&sta_params->supported_rates);
244 wcn36xx_smd_set_sta_default_ht_params(sta_params); 244 wcn36xx_smd_set_sta_default_ht_params(sta_params);
@@ -271,6 +271,16 @@ out:
271 return ret; 271 return ret;
272} 272}
273 273
274static void init_hal_msg(struct wcn36xx_hal_msg_header *hdr,
275 enum wcn36xx_hal_host_msg_type msg_type,
276 size_t msg_size)
277{
278 memset(hdr, 0, msg_size + sizeof(*hdr));
279 hdr->msg_type = msg_type;
280 hdr->msg_version = WCN36XX_HAL_MSG_VERSION0;
281 hdr->len = msg_size + sizeof(*hdr);
282}
283
274#define INIT_HAL_MSG(msg_body, type) \ 284#define INIT_HAL_MSG(msg_body, type) \
275 do { \ 285 do { \
276 memset(&msg_body, 0, sizeof(msg_body)); \ 286 memset(&msg_body, 0, sizeof(msg_body)); \
@@ -302,22 +312,6 @@ static int wcn36xx_smd_rsp_status_check(void *buf, size_t len)
302 return 0; 312 return 0;
303} 313}
304 314
305static int wcn36xx_smd_rsp_status_check_v2(struct wcn36xx *wcn, void *buf,
306 size_t len)
307{
308 struct wcn36xx_fw_msg_status_rsp_v2 *rsp;
309
310 if (len < sizeof(struct wcn36xx_hal_msg_header) + sizeof(*rsp))
311 return wcn36xx_smd_rsp_status_check(buf, len);
312
313 rsp = buf + sizeof(struct wcn36xx_hal_msg_header);
314
315 if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->status)
316 return rsp->status;
317
318 return 0;
319}
320
321int wcn36xx_smd_load_nv(struct wcn36xx *wcn) 315int wcn36xx_smd_load_nv(struct wcn36xx *wcn)
322{ 316{
323 struct nv_data *nv_d; 317 struct nv_data *nv_d;
@@ -726,7 +720,7 @@ static int wcn36xx_smd_add_sta_self_rsp(struct wcn36xx *wcn,
726 size_t len) 720 size_t len)
727{ 721{
728 struct wcn36xx_hal_add_sta_self_rsp_msg *rsp; 722 struct wcn36xx_hal_add_sta_self_rsp_msg *rsp;
729 struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv; 723 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
730 724
731 if (len < sizeof(*rsp)) 725 if (len < sizeof(*rsp))
732 return -EINVAL; 726 return -EINVAL;
@@ -743,8 +737,8 @@ static int wcn36xx_smd_add_sta_self_rsp(struct wcn36xx *wcn,
743 "hal add sta self status %d self_sta_index %d dpu_index %d\n", 737 "hal add sta self status %d self_sta_index %d dpu_index %d\n",
744 rsp->status, rsp->self_sta_index, rsp->dpu_index); 738 rsp->status, rsp->self_sta_index, rsp->dpu_index);
745 739
746 priv_vif->self_sta_index = rsp->self_sta_index; 740 vif_priv->self_sta_index = rsp->self_sta_index;
747 priv_vif->self_dpu_desc_index = rsp->dpu_index; 741 vif_priv->self_dpu_desc_index = rsp->dpu_index;
748 742
749 return 0; 743 return 0;
750} 744}
@@ -949,17 +943,32 @@ static void wcn36xx_smd_convert_sta_to_v1(struct wcn36xx *wcn,
949 memcpy(&v1->mac, orig->mac, ETH_ALEN); 943 memcpy(&v1->mac, orig->mac, ETH_ALEN);
950 v1->aid = orig->aid; 944 v1->aid = orig->aid;
951 v1->type = orig->type; 945 v1->type = orig->type;
946 v1->short_preamble_supported = orig->short_preamble_supported;
952 v1->listen_interval = orig->listen_interval; 947 v1->listen_interval = orig->listen_interval;
948 v1->wmm_enabled = orig->wmm_enabled;
953 v1->ht_capable = orig->ht_capable; 949 v1->ht_capable = orig->ht_capable;
954 950 v1->tx_channel_width_set = orig->tx_channel_width_set;
951 v1->rifs_mode = orig->rifs_mode;
952 v1->lsig_txop_protection = orig->lsig_txop_protection;
955 v1->max_ampdu_size = orig->max_ampdu_size; 953 v1->max_ampdu_size = orig->max_ampdu_size;
956 v1->max_ampdu_density = orig->max_ampdu_density; 954 v1->max_ampdu_density = orig->max_ampdu_density;
957 v1->sgi_40mhz = orig->sgi_40mhz; 955 v1->sgi_40mhz = orig->sgi_40mhz;
958 v1->sgi_20Mhz = orig->sgi_20Mhz; 956 v1->sgi_20Mhz = orig->sgi_20Mhz;
959 957 v1->rmf = orig->rmf;
958 v1->encrypt_type = orig->encrypt_type;
959 v1->action = orig->action;
960 v1->uapsd = orig->uapsd;
961 v1->max_sp_len = orig->max_sp_len;
962 v1->green_field_capable = orig->green_field_capable;
963 v1->mimo_ps = orig->mimo_ps;
964 v1->delayed_ba_support = orig->delayed_ba_support;
965 v1->max_ampdu_duration = orig->max_ampdu_duration;
966 v1->dsss_cck_mode_40mhz = orig->dsss_cck_mode_40mhz;
960 memcpy(&v1->supported_rates, &orig->supported_rates, 967 memcpy(&v1->supported_rates, &orig->supported_rates,
961 sizeof(orig->supported_rates)); 968 sizeof(orig->supported_rates));
962 v1->sta_index = orig->sta_index; 969 v1->sta_index = orig->sta_index;
970 v1->bssid_index = orig->bssid_index;
971 v1->p2p = orig->p2p;
963} 972}
964 973
965static int wcn36xx_smd_config_sta_rsp(struct wcn36xx *wcn, 974static int wcn36xx_smd_config_sta_rsp(struct wcn36xx *wcn,
@@ -969,7 +978,7 @@ static int wcn36xx_smd_config_sta_rsp(struct wcn36xx *wcn,
969{ 978{
970 struct wcn36xx_hal_config_sta_rsp_msg *rsp; 979 struct wcn36xx_hal_config_sta_rsp_msg *rsp;
971 struct config_sta_rsp_params *params; 980 struct config_sta_rsp_params *params;
972 struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv; 981 struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
973 982
974 if (len < sizeof(*rsp)) 983 if (len < sizeof(*rsp))
975 return -EINVAL; 984 return -EINVAL;
@@ -1170,12 +1179,13 @@ static int wcn36xx_smd_config_bss_v1(struct wcn36xx *wcn,
1170 1179
1171static int wcn36xx_smd_config_bss_rsp(struct wcn36xx *wcn, 1180static int wcn36xx_smd_config_bss_rsp(struct wcn36xx *wcn,
1172 struct ieee80211_vif *vif, 1181 struct ieee80211_vif *vif,
1182 struct ieee80211_sta *sta,
1173 void *buf, 1183 void *buf,
1174 size_t len) 1184 size_t len)
1175{ 1185{
1176 struct wcn36xx_hal_config_bss_rsp_msg *rsp; 1186 struct wcn36xx_hal_config_bss_rsp_msg *rsp;
1177 struct wcn36xx_hal_config_bss_rsp_params *params; 1187 struct wcn36xx_hal_config_bss_rsp_params *params;
1178 struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv; 1188 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
1179 1189
1180 if (len < sizeof(*rsp)) 1190 if (len < sizeof(*rsp))
1181 return -EINVAL; 1191 return -EINVAL;
@@ -1198,14 +1208,15 @@ static int wcn36xx_smd_config_bss_rsp(struct wcn36xx *wcn,
1198 params->bss_bcast_sta_idx, params->mac, 1208 params->bss_bcast_sta_idx, params->mac,
1199 params->tx_mgmt_power, params->ucast_dpu_signature); 1209 params->tx_mgmt_power, params->ucast_dpu_signature);
1200 1210
1201 priv_vif->bss_index = params->bss_index; 1211 vif_priv->bss_index = params->bss_index;
1202 1212
1203 if (priv_vif->sta) { 1213 if (sta) {
1204 priv_vif->sta->bss_sta_index = params->bss_sta_index; 1214 struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
1205 priv_vif->sta->bss_dpu_desc_index = params->dpu_desc_index; 1215 sta_priv->bss_sta_index = params->bss_sta_index;
1216 sta_priv->bss_dpu_desc_index = params->dpu_desc_index;
1206 } 1217 }
1207 1218
1208 priv_vif->self_ucast_dpu_sign = params->ucast_dpu_signature; 1219 vif_priv->self_ucast_dpu_sign = params->ucast_dpu_signature;
1209 1220
1210 return 0; 1221 return 0;
1211} 1222}
@@ -1217,7 +1228,7 @@ int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif,
1217 struct wcn36xx_hal_config_bss_req_msg msg; 1228 struct wcn36xx_hal_config_bss_req_msg msg;
1218 struct wcn36xx_hal_config_bss_params *bss; 1229 struct wcn36xx_hal_config_bss_params *bss;
1219 struct wcn36xx_hal_config_sta_params *sta_params; 1230 struct wcn36xx_hal_config_sta_params *sta_params;
1220 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 1231 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
1221 int ret = 0; 1232 int ret = 0;
1222 1233
1223 mutex_lock(&wcn->hal_mutex); 1234 mutex_lock(&wcn->hal_mutex);
@@ -1329,6 +1340,7 @@ int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif,
1329 } 1340 }
1330 ret = wcn36xx_smd_config_bss_rsp(wcn, 1341 ret = wcn36xx_smd_config_bss_rsp(wcn,
1331 vif, 1342 vif,
1343 sta,
1332 wcn->hal_buf, 1344 wcn->hal_buf,
1333 wcn->hal_rsp_len); 1345 wcn->hal_rsp_len);
1334 if (ret) { 1346 if (ret) {
@@ -1343,13 +1355,13 @@ out:
1343int wcn36xx_smd_delete_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif) 1355int wcn36xx_smd_delete_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif)
1344{ 1356{
1345 struct wcn36xx_hal_delete_bss_req_msg msg_body; 1357 struct wcn36xx_hal_delete_bss_req_msg msg_body;
1346 struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv; 1358 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
1347 int ret = 0; 1359 int ret = 0;
1348 1360
1349 mutex_lock(&wcn->hal_mutex); 1361 mutex_lock(&wcn->hal_mutex);
1350 INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_BSS_REQ); 1362 INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_BSS_REQ);
1351 1363
1352 msg_body.bss_index = priv_vif->bss_index; 1364 msg_body.bss_index = vif_priv->bss_index;
1353 1365
1354 PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1366 PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1355 1367
@@ -1375,26 +1387,47 @@ int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, struct ieee80211_vif *vif,
1375 u16 p2p_off) 1387 u16 p2p_off)
1376{ 1388{
1377 struct wcn36xx_hal_send_beacon_req_msg msg_body; 1389 struct wcn36xx_hal_send_beacon_req_msg msg_body;
1378 int ret = 0; 1390 int ret = 0, pad, pvm_len;
1379 1391
1380 mutex_lock(&wcn->hal_mutex); 1392 mutex_lock(&wcn->hal_mutex);
1381 INIT_HAL_MSG(msg_body, WCN36XX_HAL_SEND_BEACON_REQ); 1393 INIT_HAL_MSG(msg_body, WCN36XX_HAL_SEND_BEACON_REQ);
1382 1394
1383 /* TODO need to find out why this is needed? */ 1395 pvm_len = skb_beacon->data[tim_off + 1] - 3;
1384 msg_body.beacon_length = skb_beacon->len + 6; 1396 pad = TIM_MIN_PVM_SIZE - pvm_len;
1385 1397
1386 if (BEACON_TEMPLATE_SIZE > msg_body.beacon_length) { 1398 /* Padding is irrelevant to mesh mode since tim_off is always 0. */
1387 memcpy(&msg_body.beacon, &skb_beacon->len, sizeof(u32)); 1399 if (vif->type == NL80211_IFTYPE_MESH_POINT)
1388 memcpy(&(msg_body.beacon[4]), skb_beacon->data, 1400 pad = 0;
1389 skb_beacon->len); 1401
1390 } else { 1402 msg_body.beacon_length = skb_beacon->len + pad;
1403 /* TODO need to find out why + 6 is needed */
1404 msg_body.beacon_length6 = msg_body.beacon_length + 6;
1405
1406 if (msg_body.beacon_length > BEACON_TEMPLATE_SIZE) {
1391 wcn36xx_err("Beacon is to big: beacon size=%d\n", 1407 wcn36xx_err("Beacon is to big: beacon size=%d\n",
1392 msg_body.beacon_length); 1408 msg_body.beacon_length);
1393 ret = -ENOMEM; 1409 ret = -ENOMEM;
1394 goto out; 1410 goto out;
1395 } 1411 }
1412 memcpy(msg_body.beacon, skb_beacon->data, skb_beacon->len);
1396 memcpy(msg_body.bssid, vif->addr, ETH_ALEN); 1413 memcpy(msg_body.bssid, vif->addr, ETH_ALEN);
1397 1414
1415 if (pad > 0) {
1416 /*
1417 * The wcn36xx FW has a fixed size for the PVM in the TIM. If
1418 * given the beacon template from mac80211 with a PVM shorter
1419 * than the FW expectes it will overwrite the data after the
1420 * TIM.
1421 */
1422 wcn36xx_dbg(WCN36XX_DBG_HAL, "Pad TIM PVM. %d bytes at %d\n",
1423 pad, pvm_len);
1424 memmove(&msg_body.beacon[tim_off + 5 + pvm_len + pad],
1425 &msg_body.beacon[tim_off + 5 + pvm_len],
1426 skb_beacon->len - (tim_off + 5 + pvm_len));
1427 memset(&msg_body.beacon[tim_off + 5 + pvm_len], 0, pad);
1428 msg_body.beacon[tim_off + 1] += pad;
1429 }
1430
1398 /* TODO need to find out why this is needed? */ 1431 /* TODO need to find out why this is needed? */
1399 if (vif->type == NL80211_IFTYPE_MESH_POINT) 1432 if (vif->type == NL80211_IFTYPE_MESH_POINT)
1400 /* mesh beacon don't need this, so push further down */ 1433 /* mesh beacon don't need this, so push further down */
@@ -1598,8 +1631,7 @@ int wcn36xx_smd_remove_bsskey(struct wcn36xx *wcn,
1598 wcn36xx_err("Sending hal_remove_bsskey failed\n"); 1631 wcn36xx_err("Sending hal_remove_bsskey failed\n");
1599 goto out; 1632 goto out;
1600 } 1633 }
1601 ret = wcn36xx_smd_rsp_status_check_v2(wcn, wcn->hal_buf, 1634 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1602 wcn->hal_rsp_len);
1603 if (ret) { 1635 if (ret) {
1604 wcn36xx_err("hal_remove_bsskey response failed err=%d\n", ret); 1636 wcn36xx_err("hal_remove_bsskey response failed err=%d\n", ret);
1605 goto out; 1637 goto out;
@@ -1612,7 +1644,7 @@ out:
1612int wcn36xx_smd_enter_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif) 1644int wcn36xx_smd_enter_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif)
1613{ 1645{
1614 struct wcn36xx_hal_enter_bmps_req_msg msg_body; 1646 struct wcn36xx_hal_enter_bmps_req_msg msg_body;
1615 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 1647 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
1616 int ret = 0; 1648 int ret = 0;
1617 1649
1618 mutex_lock(&wcn->hal_mutex); 1650 mutex_lock(&wcn->hal_mutex);
@@ -1641,8 +1673,8 @@ out:
1641 1673
1642int wcn36xx_smd_exit_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif) 1674int wcn36xx_smd_exit_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif)
1643{ 1675{
1644 struct wcn36xx_hal_enter_bmps_req_msg msg_body; 1676 struct wcn36xx_hal_exit_bmps_req_msg msg_body;
1645 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 1677 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
1646 int ret = 0; 1678 int ret = 0;
1647 1679
1648 mutex_lock(&wcn->hal_mutex); 1680 mutex_lock(&wcn->hal_mutex);
@@ -1703,7 +1735,7 @@ int wcn36xx_smd_keep_alive_req(struct wcn36xx *wcn,
1703 int packet_type) 1735 int packet_type)
1704{ 1736{
1705 struct wcn36xx_hal_keep_alive_req_msg msg_body; 1737 struct wcn36xx_hal_keep_alive_req_msg msg_body;
1706 struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 1738 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
1707 int ret = 0; 1739 int ret = 0;
1708 1740
1709 mutex_lock(&wcn->hal_mutex); 1741 mutex_lock(&wcn->hal_mutex);
@@ -1944,6 +1976,17 @@ out:
1944 return ret; 1976 return ret;
1945} 1977}
1946 1978
1979static int wcn36xx_smd_trigger_ba_rsp(void *buf, int len)
1980{
1981 struct wcn36xx_hal_trigger_ba_rsp_msg *rsp;
1982
1983 if (len < sizeof(*rsp))
1984 return -EINVAL;
1985
1986 rsp = (struct wcn36xx_hal_trigger_ba_rsp_msg *) buf;
1987 return rsp->status;
1988}
1989
1947int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index) 1990int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index)
1948{ 1991{
1949 struct wcn36xx_hal_trigger_ba_req_msg msg_body; 1992 struct wcn36xx_hal_trigger_ba_req_msg msg_body;
@@ -1968,8 +2011,7 @@ int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index)
1968 wcn36xx_err("Sending hal_trigger_ba failed\n"); 2011 wcn36xx_err("Sending hal_trigger_ba failed\n");
1969 goto out; 2012 goto out;
1970 } 2013 }
1971 ret = wcn36xx_smd_rsp_status_check_v2(wcn, wcn->hal_buf, 2014 ret = wcn36xx_smd_trigger_ba_rsp(wcn->hal_buf, wcn->hal_rsp_len);
1972 wcn->hal_rsp_len);
1973 if (ret) { 2015 if (ret) {
1974 wcn36xx_err("hal_trigger_ba response failed err=%d\n", ret); 2016 wcn36xx_err("hal_trigger_ba response failed err=%d\n", ret);
1975 goto out; 2017 goto out;
@@ -2006,9 +2048,7 @@ static int wcn36xx_smd_missed_beacon_ind(struct wcn36xx *wcn,
2006 list_for_each_entry(tmp, &wcn->vif_list, list) { 2048 list_for_each_entry(tmp, &wcn->vif_list, list) {
2007 wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n", 2049 wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n",
2008 tmp->bss_index); 2050 tmp->bss_index);
2009 vif = container_of((void *)tmp, 2051 vif = wcn36xx_priv_to_vif(tmp);
2010 struct ieee80211_vif,
2011 drv_priv);
2012 ieee80211_connection_loss(vif); 2052 ieee80211_connection_loss(vif);
2013 } 2053 }
2014 return 0; 2054 return 0;
@@ -2023,9 +2063,7 @@ static int wcn36xx_smd_missed_beacon_ind(struct wcn36xx *wcn,
2023 if (tmp->bss_index == rsp->bss_index) { 2063 if (tmp->bss_index == rsp->bss_index) {
2024 wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n", 2064 wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n",
2025 rsp->bss_index); 2065 rsp->bss_index);
2026 vif = container_of((void *)tmp, 2066 vif = wcn36xx_priv_to_vif(tmp);
2027 struct ieee80211_vif,
2028 drv_priv);
2029 ieee80211_connection_loss(vif); 2067 ieee80211_connection_loss(vif);
2030 return 0; 2068 return 0;
2031 } 2069 }
@@ -2041,25 +2079,24 @@ static int wcn36xx_smd_delete_sta_context_ind(struct wcn36xx *wcn,
2041{ 2079{
2042 struct wcn36xx_hal_delete_sta_context_ind_msg *rsp = buf; 2080 struct wcn36xx_hal_delete_sta_context_ind_msg *rsp = buf;
2043 struct wcn36xx_vif *tmp; 2081 struct wcn36xx_vif *tmp;
2044 struct ieee80211_sta *sta = NULL; 2082 struct ieee80211_sta *sta;
2045 2083
2046 if (len != sizeof(*rsp)) { 2084 if (len != sizeof(*rsp)) {
2047 wcn36xx_warn("Corrupted delete sta indication\n"); 2085 wcn36xx_warn("Corrupted delete sta indication\n");
2048 return -EIO; 2086 return -EIO;
2049 } 2087 }
2050 2088
2089 wcn36xx_dbg(WCN36XX_DBG_HAL, "delete station indication %pM index %d\n",
2090 rsp->addr2, rsp->sta_id);
2091
2051 list_for_each_entry(tmp, &wcn->vif_list, list) { 2092 list_for_each_entry(tmp, &wcn->vif_list, list) {
2052 if (sta && (tmp->sta->sta_index == rsp->sta_id)) { 2093 rcu_read_lock();
2053 sta = container_of((void *)tmp->sta, 2094 sta = ieee80211_find_sta(wcn36xx_priv_to_vif(tmp), rsp->addr2);
2054 struct ieee80211_sta, 2095 if (sta)
2055 drv_priv);
2056 wcn36xx_dbg(WCN36XX_DBG_HAL,
2057 "delete station indication %pM index %d\n",
2058 rsp->addr2,
2059 rsp->sta_id);
2060 ieee80211_report_low_ack(sta, 0); 2096 ieee80211_report_low_ack(sta, 0);
2097 rcu_read_unlock();
2098 if (sta)
2061 return 0; 2099 return 0;
2062 }
2063 } 2100 }
2064 2101
2065 wcn36xx_warn("STA with addr %pM and index %d not found\n", 2102 wcn36xx_warn("STA with addr %pM and index %d not found\n",
@@ -2100,6 +2137,46 @@ out:
2100 mutex_unlock(&wcn->hal_mutex); 2137 mutex_unlock(&wcn->hal_mutex);
2101 return ret; 2138 return ret;
2102} 2139}
2140
2141int wcn36xx_smd_set_mc_list(struct wcn36xx *wcn,
2142 struct ieee80211_vif *vif,
2143 struct wcn36xx_hal_rcv_flt_mc_addr_list_type *fp)
2144{
2145 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
2146 struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_req_msg *msg_body = NULL;
2147 int ret = 0;
2148
2149 mutex_lock(&wcn->hal_mutex);
2150
2151 msg_body = (struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_req_msg *)
2152 wcn->hal_buf;
2153 init_hal_msg(&msg_body->header, WCN36XX_HAL_8023_MULTICAST_LIST_REQ,
2154 sizeof(msg_body->mc_addr_list));
2155
2156 /* An empty list means all mc traffic will be received */
2157 if (fp)
2158 memcpy(&msg_body->mc_addr_list, fp,
2159 sizeof(msg_body->mc_addr_list));
2160 else
2161 msg_body->mc_addr_list.mc_addr_count = 0;
2162
2163 msg_body->mc_addr_list.bss_index = vif_priv->bss_index;
2164
2165 ret = wcn36xx_smd_send_and_wait(wcn, msg_body->header.len);
2166 if (ret) {
2167 wcn36xx_err("Sending HAL_8023_MULTICAST_LIST failed\n");
2168 goto out;
2169 }
2170 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2171 if (ret) {
2172 wcn36xx_err("HAL_8023_MULTICAST_LIST rsp failed err=%d\n", ret);
2173 goto out;
2174 }
2175out:
2176 mutex_unlock(&wcn->hal_mutex);
2177 return ret;
2178}
2179
2103static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len) 2180static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len)
2104{ 2181{
2105 struct wcn36xx_hal_msg_header *msg_header = buf; 2182 struct wcn36xx_hal_msg_header *msg_header = buf;
@@ -2141,6 +2218,7 @@ static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len)
2141 case WCN36XX_HAL_UPDATE_SCAN_PARAM_RSP: 2218 case WCN36XX_HAL_UPDATE_SCAN_PARAM_RSP:
2142 case WCN36XX_HAL_CH_SWITCH_RSP: 2219 case WCN36XX_HAL_CH_SWITCH_RSP:
2143 case WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_RSP: 2220 case WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_RSP:
2221 case WCN36XX_HAL_8023_MULTICAST_LIST_RSP:
2144 memcpy(wcn->hal_buf, buf, len); 2222 memcpy(wcn->hal_buf, buf, len);
2145 wcn->hal_rsp_len = len; 2223 wcn->hal_rsp_len = len;
2146 complete(&wcn->hal_rsp_compl); 2224 complete(&wcn->hal_rsp_compl);
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.h b/drivers/net/wireless/ath/wcn36xx/smd.h
index 8361f9e3995b..d74d781f4c8d 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.h
+++ b/drivers/net/wireless/ath/wcn36xx/smd.h
@@ -44,15 +44,6 @@ struct wcn36xx_fw_msg_status_rsp {
44 u32 status; 44 u32 status;
45} __packed; 45} __packed;
46 46
47/* wcn3620 returns this for tigger_ba */
48
49struct wcn36xx_fw_msg_status_rsp_v2 {
50 u8 bss_id[6];
51 u32 status __packed;
52 u16 count_following_candidates __packed;
53 /* candidate list follows */
54};
55
56struct wcn36xx_hal_ind_msg { 47struct wcn36xx_hal_ind_msg {
57 struct list_head list; 48 struct list_head list;
58 u8 *msg; 49 u8 *msg;
@@ -136,4 +127,7 @@ int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 sta_index);
136int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index); 127int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index);
137 128
138int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value); 129int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value);
130int wcn36xx_smd_set_mc_list(struct wcn36xx *wcn,
131 struct ieee80211_vif *vif,
132 struct wcn36xx_hal_rcv_flt_mc_addr_list_type *fp);
139#endif /* _SMD_H_ */ 133#endif /* _SMD_H_ */
diff --git a/drivers/net/wireless/ath/wcn36xx/txrx.c b/drivers/net/wireless/ath/wcn36xx/txrx.c
index 6c47a7336c38..1f34c2e912d7 100644
--- a/drivers/net/wireless/ath/wcn36xx/txrx.c
+++ b/drivers/net/wireless/ath/wcn36xx/txrx.c
@@ -102,9 +102,7 @@ static inline struct wcn36xx_vif *get_vif_by_addr(struct wcn36xx *wcn,
102 struct wcn36xx_vif *vif_priv = NULL; 102 struct wcn36xx_vif *vif_priv = NULL;
103 struct ieee80211_vif *vif = NULL; 103 struct ieee80211_vif *vif = NULL;
104 list_for_each_entry(vif_priv, &wcn->vif_list, list) { 104 list_for_each_entry(vif_priv, &wcn->vif_list, list) {
105 vif = container_of((void *)vif_priv, 105 vif = wcn36xx_priv_to_vif(vif_priv);
106 struct ieee80211_vif,
107 drv_priv);
108 if (memcmp(vif->addr, addr, ETH_ALEN) == 0) 106 if (memcmp(vif->addr, addr, ETH_ALEN) == 0)
109 return vif_priv; 107 return vif_priv;
110 } 108 }
@@ -167,9 +165,7 @@ static void wcn36xx_set_tx_data(struct wcn36xx_tx_bd *bd,
167 */ 165 */
168 if (sta_priv) { 166 if (sta_priv) {
169 __vif_priv = sta_priv->vif; 167 __vif_priv = sta_priv->vif;
170 vif = container_of((void *)__vif_priv, 168 vif = wcn36xx_priv_to_vif(__vif_priv);
171 struct ieee80211_vif,
172 drv_priv);
173 169
174 bd->dpu_sign = sta_priv->ucast_dpu_sign; 170 bd->dpu_sign = sta_priv->ucast_dpu_sign;
175 if (vif->type == NL80211_IFTYPE_STATION) { 171 if (vif->type == NL80211_IFTYPE_STATION) {
diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
index 7b41e833e18c..7433d67a5929 100644
--- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
+++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
@@ -125,10 +125,10 @@ struct wcn36xx_platform_ctrl_ops {
125 */ 125 */
126struct wcn36xx_vif { 126struct wcn36xx_vif {
127 struct list_head list; 127 struct list_head list;
128 struct wcn36xx_sta *sta;
129 u8 dtim_period; 128 u8 dtim_period;
130 enum ani_ed_type encrypt_type; 129 enum ani_ed_type encrypt_type;
131 bool is_joining; 130 bool is_joining;
131 bool sta_assoc;
132 struct wcn36xx_hal_mac_ssid ssid; 132 struct wcn36xx_hal_mac_ssid ssid;
133 133
134 /* Power management */ 134 /* Power management */
@@ -263,4 +263,22 @@ struct ieee80211_sta *wcn36xx_priv_to_sta(struct wcn36xx_sta *sta_priv)
263 return container_of((void *)sta_priv, struct ieee80211_sta, drv_priv); 263 return container_of((void *)sta_priv, struct ieee80211_sta, drv_priv);
264} 264}
265 265
266static inline
267struct wcn36xx_vif *wcn36xx_vif_to_priv(struct ieee80211_vif *vif)
268{
269 return (struct wcn36xx_vif *) vif->drv_priv;
270}
271
272static inline
273struct ieee80211_vif *wcn36xx_priv_to_vif(struct wcn36xx_vif *vif_priv)
274{
275 return container_of((void *) vif_priv, struct ieee80211_vif, drv_priv);
276}
277
278static inline
279struct wcn36xx_sta *wcn36xx_sta_to_priv(struct ieee80211_sta *sta)
280{
281 return (struct wcn36xx_sta *)sta->drv_priv;
282}
283
266#endif /* _WCN36XX_H_ */ 284#endif /* _WCN36XX_H_ */