diff options
-rw-r--r-- | drivers/net/wireless/rtlwifi/base.c | 361 | ||||
-rw-r--r-- | drivers/net/wireless/rtlwifi/base.h | 14 | ||||
-rw-r--r-- | drivers/net/wireless/rtlwifi/core.c | 208 | ||||
-rw-r--r-- | drivers/net/wireless/rtlwifi/debug.c | 5 | ||||
-rw-r--r-- | drivers/net/wireless/rtlwifi/debug.h | 7 | ||||
-rw-r--r-- | drivers/net/wireless/rtlwifi/efuse.c | 42 | ||||
-rw-r--r-- | drivers/net/wireless/rtlwifi/pci.c | 117 | ||||
-rw-r--r-- | drivers/net/wireless/rtlwifi/pci.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/rtlwifi/ps.c | 330 | ||||
-rw-r--r-- | drivers/net/wireless/rtlwifi/ps.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/rtlwifi/wifi.h | 116 |
11 files changed, 1055 insertions, 148 deletions
diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c index 99c5cea3fe21..270b27a06905 100644 --- a/drivers/net/wireless/rtlwifi/base.c +++ b/drivers/net/wireless/rtlwifi/base.c | |||
@@ -54,7 +54,8 @@ | |||
54 | *5) frame process functions | 54 | *5) frame process functions |
55 | *6) IOT functions | 55 | *6) IOT functions |
56 | *7) sysfs functions | 56 | *7) sysfs functions |
57 | *8) ... | 57 | *8) vif functions |
58 | *9) ... | ||
58 | */ | 59 | */ |
59 | 60 | ||
60 | /********************************************************* | 61 | /********************************************************* |
@@ -198,34 +199,46 @@ static void _rtl_init_hw_ht_capab(struct ieee80211_hw *hw, | |||
198 | 199 | ||
199 | ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; | 200 | ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; |
200 | 201 | ||
201 | /* | 202 | /*hw->wiphy->bands[IEEE80211_BAND_2GHZ] |
202 | *hw->wiphy->bands[IEEE80211_BAND_2GHZ] | ||
203 | *base on ant_num | 203 | *base on ant_num |
204 | *rx_mask: RX mask | 204 | *rx_mask: RX mask |
205 | *if rx_ant =1 rx_mask[0]=0xff;==>MCS0-MCS7 | 205 | *if rx_ant = 1 rx_mask[0]= 0xff;==>MCS0-MCS7 |
206 | *if rx_ant =2 rx_mask[1]=0xff;==>MCS8-MCS15 | 206 | *if rx_ant = 2 rx_mask[1]= 0xff;==>MCS8-MCS15 |
207 | *if rx_ant >=3 rx_mask[2]=0xff; | 207 | *if rx_ant >= 3 rx_mask[2]= 0xff; |
208 | *if BW_40 rx_mask[4]=0x01; | 208 | *if BW_40 rx_mask[4]= 0x01; |
209 | *highest supported RX rate | 209 | *highest supported RX rate |
210 | */ | 210 | */ |
211 | if (get_rf_type(rtlphy) == RF_1T2R || get_rf_type(rtlphy) == RF_2T2R) { | 211 | if (rtlpriv->dm.supp_phymode_switch) { |
212 | 212 | ||
213 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "1T2R or 2T2R\n"); | 213 | RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, |
214 | "Support phy mode switch\n"); | ||
214 | 215 | ||
215 | ht_cap->mcs.rx_mask[0] = 0xFF; | 216 | ht_cap->mcs.rx_mask[0] = 0xFF; |
216 | ht_cap->mcs.rx_mask[1] = 0xFF; | 217 | ht_cap->mcs.rx_mask[1] = 0xFF; |
217 | ht_cap->mcs.rx_mask[4] = 0x01; | 218 | ht_cap->mcs.rx_mask[4] = 0x01; |
218 | 219 | ||
219 | ht_cap->mcs.rx_highest = cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS15); | 220 | ht_cap->mcs.rx_highest = cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS15); |
220 | } else if (get_rf_type(rtlphy) == RF_1T1R) { | 221 | } else { |
221 | 222 | if (get_rf_type(rtlphy) == RF_1T2R || | |
222 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "1T1R\n"); | 223 | get_rf_type(rtlphy) == RF_2T2R) { |
223 | 224 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, | |
224 | ht_cap->mcs.rx_mask[0] = 0xFF; | 225 | "1T2R or 2T2R\n"); |
225 | ht_cap->mcs.rx_mask[1] = 0x00; | 226 | ht_cap->mcs.rx_mask[0] = 0xFF; |
226 | ht_cap->mcs.rx_mask[4] = 0x01; | 227 | ht_cap->mcs.rx_mask[1] = 0xFF; |
227 | 228 | ht_cap->mcs.rx_mask[4] = 0x01; | |
228 | ht_cap->mcs.rx_highest = cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS7); | 229 | |
230 | ht_cap->mcs.rx_highest = | ||
231 | cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS15); | ||
232 | } else if (get_rf_type(rtlphy) == RF_1T1R) { | ||
233 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "1T1R\n"); | ||
234 | |||
235 | ht_cap->mcs.rx_mask[0] = 0xFF; | ||
236 | ht_cap->mcs.rx_mask[1] = 0x00; | ||
237 | ht_cap->mcs.rx_mask[4] = 0x01; | ||
238 | |||
239 | ht_cap->mcs.rx_highest = | ||
240 | cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS7); | ||
241 | } | ||
229 | } | 242 | } |
230 | } | 243 | } |
231 | 244 | ||
@@ -311,6 +324,8 @@ static void _rtl_init_mac80211(struct ieee80211_hw *hw) | |||
311 | IEEE80211_HW_AMPDU_AGGREGATION | | 324 | IEEE80211_HW_AMPDU_AGGREGATION | |
312 | IEEE80211_HW_CONNECTION_MONITOR | | 325 | IEEE80211_HW_CONNECTION_MONITOR | |
313 | /* IEEE80211_HW_SUPPORTS_CQM_RSSI | */ | 326 | /* IEEE80211_HW_SUPPORTS_CQM_RSSI | */ |
327 | IEEE80211_HW_CONNECTION_MONITOR | | ||
328 | IEEE80211_HW_MFP_CAPABLE | | ||
314 | IEEE80211_HW_REPORTS_TX_ACK_STATUS | 0; | 329 | IEEE80211_HW_REPORTS_TX_ACK_STATUS | 0; |
315 | 330 | ||
316 | /* swlps or hwlps has been set in diff chip in init_sw_vars */ | 331 | /* swlps or hwlps has been set in diff chip in init_sw_vars */ |
@@ -323,8 +338,12 @@ static void _rtl_init_mac80211(struct ieee80211_hw *hw) | |||
323 | hw->wiphy->interface_modes = | 338 | hw->wiphy->interface_modes = |
324 | BIT(NL80211_IFTYPE_AP) | | 339 | BIT(NL80211_IFTYPE_AP) | |
325 | BIT(NL80211_IFTYPE_STATION) | | 340 | BIT(NL80211_IFTYPE_STATION) | |
326 | BIT(NL80211_IFTYPE_ADHOC); | 341 | BIT(NL80211_IFTYPE_ADHOC) | |
342 | BIT(NL80211_IFTYPE_MESH_POINT) | | ||
343 | BIT(NL80211_IFTYPE_P2P_CLIENT) | | ||
344 | BIT(NL80211_IFTYPE_P2P_GO); | ||
327 | 345 | ||
346 | hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; | ||
328 | hw->wiphy->rts_threshold = 2347; | 347 | hw->wiphy->rts_threshold = 2347; |
329 | 348 | ||
330 | hw->queues = AC_MAX; | 349 | hw->queues = AC_MAX; |
@@ -354,9 +373,10 @@ static void _rtl_init_deferred_work(struct ieee80211_hw *hw) | |||
354 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 373 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
355 | 374 | ||
356 | /* <1> timer */ | 375 | /* <1> timer */ |
357 | init_timer(&rtlpriv->works.watchdog_timer); | ||
358 | setup_timer(&rtlpriv->works.watchdog_timer, | 376 | setup_timer(&rtlpriv->works.watchdog_timer, |
359 | rtl_watch_dog_timer_callback, (unsigned long)hw); | 377 | rtl_watch_dog_timer_callback, (unsigned long)hw); |
378 | setup_timer(&rtlpriv->works.dualmac_easyconcurrent_retrytimer, | ||
379 | rtl_easy_concurrent_retrytimer_callback, (unsigned long)hw); | ||
360 | 380 | ||
361 | /* <2> work queue */ | 381 | /* <2> work queue */ |
362 | rtlpriv->works.hw = hw; | 382 | rtlpriv->works.hw = hw; |
@@ -369,6 +389,8 @@ static void _rtl_init_deferred_work(struct ieee80211_hw *hw) | |||
369 | (void *)rtl_swlps_wq_callback); | 389 | (void *)rtl_swlps_wq_callback); |
370 | INIT_DELAYED_WORK(&rtlpriv->works.ps_rfon_wq, | 390 | INIT_DELAYED_WORK(&rtlpriv->works.ps_rfon_wq, |
371 | (void *)rtl_swlps_rfon_wq_callback); | 391 | (void *)rtl_swlps_rfon_wq_callback); |
392 | INIT_DELAYED_WORK(&rtlpriv->works.fwevt_wq, | ||
393 | (void *)rtl_fwevt_wq_callback); | ||
372 | 394 | ||
373 | } | 395 | } |
374 | 396 | ||
@@ -382,6 +404,7 @@ void rtl_deinit_deferred_work(struct ieee80211_hw *hw) | |||
382 | cancel_delayed_work(&rtlpriv->works.ips_nic_off_wq); | 404 | cancel_delayed_work(&rtlpriv->works.ips_nic_off_wq); |
383 | cancel_delayed_work(&rtlpriv->works.ps_work); | 405 | cancel_delayed_work(&rtlpriv->works.ps_work); |
384 | cancel_delayed_work(&rtlpriv->works.ps_rfon_wq); | 406 | cancel_delayed_work(&rtlpriv->works.ps_rfon_wq); |
407 | cancel_delayed_work(&rtlpriv->works.fwevt_wq); | ||
385 | } | 408 | } |
386 | 409 | ||
387 | void rtl_init_rfkill(struct ieee80211_hw *hw) | 410 | void rtl_init_rfkill(struct ieee80211_hw *hw) |
@@ -436,12 +459,6 @@ int rtl_init_core(struct ieee80211_hw *hw) | |||
436 | if (rtl_regd_init(hw, rtl_reg_notifier)) { | 459 | if (rtl_regd_init(hw, rtl_reg_notifier)) { |
437 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "REGD init failed\n"); | 460 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "REGD init failed\n"); |
438 | return 1; | 461 | return 1; |
439 | } else { | ||
440 | /* CRDA regd hint must after init CRDA */ | ||
441 | if (regulatory_hint(hw->wiphy, rtlpriv->regd.alpha2)) { | ||
442 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | ||
443 | "regulatory_hint fail\n"); | ||
444 | } | ||
445 | } | 462 | } |
446 | 463 | ||
447 | /* <4> locks */ | 464 | /* <4> locks */ |
@@ -449,15 +466,24 @@ int rtl_init_core(struct ieee80211_hw *hw) | |||
449 | mutex_init(&rtlpriv->locks.ps_mutex); | 466 | mutex_init(&rtlpriv->locks.ps_mutex); |
450 | spin_lock_init(&rtlpriv->locks.ips_lock); | 467 | spin_lock_init(&rtlpriv->locks.ips_lock); |
451 | spin_lock_init(&rtlpriv->locks.irq_th_lock); | 468 | spin_lock_init(&rtlpriv->locks.irq_th_lock); |
469 | spin_lock_init(&rtlpriv->locks.irq_pci_lock); | ||
470 | spin_lock_init(&rtlpriv->locks.tx_lock); | ||
452 | spin_lock_init(&rtlpriv->locks.h2c_lock); | 471 | spin_lock_init(&rtlpriv->locks.h2c_lock); |
453 | spin_lock_init(&rtlpriv->locks.rf_ps_lock); | 472 | spin_lock_init(&rtlpriv->locks.rf_ps_lock); |
454 | spin_lock_init(&rtlpriv->locks.rf_lock); | 473 | spin_lock_init(&rtlpriv->locks.rf_lock); |
455 | spin_lock_init(&rtlpriv->locks.waitq_lock); | 474 | spin_lock_init(&rtlpriv->locks.waitq_lock); |
475 | spin_lock_init(&rtlpriv->locks.entry_list_lock); | ||
456 | spin_lock_init(&rtlpriv->locks.cck_and_rw_pagea_lock); | 476 | spin_lock_init(&rtlpriv->locks.cck_and_rw_pagea_lock); |
477 | spin_lock_init(&rtlpriv->locks.check_sendpkt_lock); | ||
478 | spin_lock_init(&rtlpriv->locks.fw_ps_lock); | ||
479 | spin_lock_init(&rtlpriv->locks.lps_lock); | ||
480 | |||
481 | /* <5> init list */ | ||
482 | INIT_LIST_HEAD(&rtlpriv->entry_list); | ||
457 | 483 | ||
458 | rtlmac->link_state = MAC80211_NOLINK; | 484 | rtlmac->link_state = MAC80211_NOLINK; |
459 | 485 | ||
460 | /* <5> init deferred work */ | 486 | /* <6> init deferred work */ |
461 | _rtl_init_deferred_work(hw); | 487 | _rtl_init_deferred_work(hw); |
462 | 488 | ||
463 | return 0; | 489 | return 0; |
@@ -523,7 +549,8 @@ static void _rtl_query_shortgi(struct ieee80211_hw *hw, | |||
523 | if (mac->opmode == NL80211_IFTYPE_STATION) | 549 | if (mac->opmode == NL80211_IFTYPE_STATION) |
524 | bw_40 = mac->bw_40; | 550 | bw_40 = mac->bw_40; |
525 | else if (mac->opmode == NL80211_IFTYPE_AP || | 551 | else if (mac->opmode == NL80211_IFTYPE_AP || |
526 | mac->opmode == NL80211_IFTYPE_ADHOC) | 552 | mac->opmode == NL80211_IFTYPE_ADHOC || |
553 | mac->opmode == NL80211_IFTYPE_MESH_POINT) | ||
527 | bw_40 = sta->bandwidth >= IEEE80211_STA_RX_BW_40; | 554 | bw_40 = sta->bandwidth >= IEEE80211_STA_RX_BW_40; |
528 | 555 | ||
529 | if (bw_40 && sgi_40) | 556 | if (bw_40 && sgi_40) |
@@ -578,23 +605,26 @@ static void _rtl_txrate_selectmode(struct ieee80211_hw *hw, | |||
578 | if (!tcb_desc->disable_ratefallback || !tcb_desc->use_driver_rate) { | 605 | if (!tcb_desc->disable_ratefallback || !tcb_desc->use_driver_rate) { |
579 | if (mac->opmode == NL80211_IFTYPE_STATION) { | 606 | if (mac->opmode == NL80211_IFTYPE_STATION) { |
580 | tcb_desc->ratr_index = 0; | 607 | tcb_desc->ratr_index = 0; |
581 | } else if (mac->opmode == NL80211_IFTYPE_ADHOC) { | 608 | } else if (mac->opmode == NL80211_IFTYPE_ADHOC || |
609 | mac->opmode == NL80211_IFTYPE_MESH_POINT) { | ||
582 | if (tcb_desc->multicast || tcb_desc->broadcast) { | 610 | if (tcb_desc->multicast || tcb_desc->broadcast) { |
583 | tcb_desc->hw_rate = | 611 | tcb_desc->hw_rate = |
584 | rtlpriv->cfg->maps[RTL_RC_CCK_RATE2M]; | 612 | rtlpriv->cfg->maps[RTL_RC_CCK_RATE2M]; |
585 | tcb_desc->use_driver_rate = 1; | 613 | tcb_desc->use_driver_rate = 1; |
614 | tcb_desc->ratr_index = RATR_INX_WIRELESS_MC; | ||
586 | } else { | 615 | } else { |
587 | /* TODO */ | 616 | tcb_desc->ratr_index = ratr_index; |
588 | } | 617 | } |
589 | tcb_desc->ratr_index = ratr_index; | ||
590 | } else if (mac->opmode == NL80211_IFTYPE_AP) { | 618 | } else if (mac->opmode == NL80211_IFTYPE_AP) { |
591 | tcb_desc->ratr_index = ratr_index; | 619 | tcb_desc->ratr_index = ratr_index; |
592 | } | 620 | } |
593 | } | 621 | } |
594 | 622 | ||
595 | if (rtlpriv->dm.useramask) { | 623 | if (rtlpriv->dm.useramask) { |
596 | /* TODO we will differentiate adhoc and station futrue */ | 624 | tcb_desc->ratr_index = ratr_index; |
597 | if (mac->opmode == NL80211_IFTYPE_STATION) { | 625 | /* TODO we will differentiate adhoc and station future */ |
626 | if (mac->opmode == NL80211_IFTYPE_STATION || | ||
627 | mac->opmode == NL80211_IFTYPE_MESH_POINT) { | ||
598 | tcb_desc->mac_id = 0; | 628 | tcb_desc->mac_id = 0; |
599 | 629 | ||
600 | if (mac->mode == WIRELESS_MODE_N_24G) | 630 | if (mac->mode == WIRELESS_MODE_N_24G) |
@@ -608,7 +638,7 @@ static void _rtl_txrate_selectmode(struct ieee80211_hw *hw, | |||
608 | else if (mac->mode & WIRELESS_MODE_A) | 638 | else if (mac->mode & WIRELESS_MODE_A) |
609 | tcb_desc->ratr_index = RATR_INX_WIRELESS_G; | 639 | tcb_desc->ratr_index = RATR_INX_WIRELESS_G; |
610 | } else if (mac->opmode == NL80211_IFTYPE_AP || | 640 | } else if (mac->opmode == NL80211_IFTYPE_AP || |
611 | mac->opmode == NL80211_IFTYPE_ADHOC) { | 641 | mac->opmode == NL80211_IFTYPE_ADHOC) { |
612 | if (NULL != sta) { | 642 | if (NULL != sta) { |
613 | if (sta->aid > 0) | 643 | if (sta->aid > 0) |
614 | tcb_desc->mac_id = sta->aid + 1; | 644 | tcb_desc->mac_id = sta->aid + 1; |
@@ -619,7 +649,6 @@ static void _rtl_txrate_selectmode(struct ieee80211_hw *hw, | |||
619 | } | 649 | } |
620 | } | 650 | } |
621 | } | 651 | } |
622 | |||
623 | } | 652 | } |
624 | 653 | ||
625 | static void _rtl_query_bandwidth_mode(struct ieee80211_hw *hw, | 654 | static void _rtl_query_bandwidth_mode(struct ieee80211_hw *hw, |
@@ -633,7 +662,8 @@ static void _rtl_query_bandwidth_mode(struct ieee80211_hw *hw, | |||
633 | if (!sta) | 662 | if (!sta) |
634 | return; | 663 | return; |
635 | if (mac->opmode == NL80211_IFTYPE_AP || | 664 | if (mac->opmode == NL80211_IFTYPE_AP || |
636 | mac->opmode == NL80211_IFTYPE_ADHOC) { | 665 | mac->opmode == NL80211_IFTYPE_ADHOC || |
666 | mac->opmode == NL80211_IFTYPE_MESH_POINT) { | ||
637 | if (sta->bandwidth == IEEE80211_STA_RX_BW_20) | 667 | if (sta->bandwidth == IEEE80211_STA_RX_BW_20) |
638 | return; | 668 | return; |
639 | } else if (mac->opmode == NL80211_IFTYPE_STATION) { | 669 | } else if (mac->opmode == NL80211_IFTYPE_STATION) { |
@@ -834,8 +864,8 @@ bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
834 | if (rtlpriv->dm.supp_phymode_switch && | 864 | if (rtlpriv->dm.supp_phymode_switch && |
835 | mac->link_state < MAC80211_LINKED && | 865 | mac->link_state < MAC80211_LINKED && |
836 | (ieee80211_is_auth(fc) || ieee80211_is_probe_req(fc))) { | 866 | (ieee80211_is_auth(fc) || ieee80211_is_probe_req(fc))) { |
837 | if (rtlpriv->cfg->ops->check_switch_to_dmdp) | 867 | if (rtlpriv->cfg->ops->chk_switch_dmdp) |
838 | rtlpriv->cfg->ops->check_switch_to_dmdp(hw); | 868 | rtlpriv->cfg->ops->chk_switch_dmdp(hw); |
839 | } | 869 | } |
840 | if (ieee80211_is_auth(fc)) { | 870 | if (ieee80211_is_auth(fc)) { |
841 | RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, "MAC80211_LINKING\n"); | 871 | RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, "MAC80211_LINKING\n"); |
@@ -924,6 +954,56 @@ void rtl_get_tcb_desc(struct ieee80211_hw *hw, | |||
924 | } | 954 | } |
925 | EXPORT_SYMBOL(rtl_get_tcb_desc); | 955 | EXPORT_SYMBOL(rtl_get_tcb_desc); |
926 | 956 | ||
957 | static bool addbareq_rx(struct ieee80211_hw *hw, struct sk_buff *skb) | ||
958 | { | ||
959 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
960 | struct ieee80211_sta *sta = NULL; | ||
961 | struct ieee80211_hdr *hdr = rtl_get_hdr(skb); | ||
962 | struct rtl_sta_info *sta_entry = NULL; | ||
963 | struct ieee80211_mgmt *mgmt = (void *)skb->data; | ||
964 | u16 capab = 0, tid = 0; | ||
965 | struct rtl_tid_data *tid_data; | ||
966 | struct sk_buff *skb_delba = NULL; | ||
967 | struct ieee80211_rx_status rx_status = { 0 }; | ||
968 | |||
969 | rcu_read_lock(); | ||
970 | sta = rtl_find_sta(hw, hdr->addr3); | ||
971 | if (sta == NULL) { | ||
972 | RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_EMERG, | ||
973 | "sta is NULL\n"); | ||
974 | rcu_read_unlock(); | ||
975 | return true; | ||
976 | } | ||
977 | |||
978 | sta_entry = (struct rtl_sta_info *)sta->drv_priv; | ||
979 | if (!sta_entry) { | ||
980 | rcu_read_unlock(); | ||
981 | return true; | ||
982 | } | ||
983 | capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab); | ||
984 | tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; | ||
985 | tid_data = &sta_entry->tids[tid]; | ||
986 | if (tid_data->agg.rx_agg_state == RTL_RX_AGG_START) { | ||
987 | skb_delba = rtl_make_del_ba(hw, hdr->addr2, hdr->addr3, tid); | ||
988 | if (skb_delba) { | ||
989 | rx_status.freq = hw->conf.channel->center_freq; | ||
990 | rx_status.band = hw->conf.channel->band; | ||
991 | rx_status.flag |= RX_FLAG_DECRYPTED; | ||
992 | rx_status.flag |= RX_FLAG_MACTIME_END; | ||
993 | rx_status.rate_idx = 0; | ||
994 | rx_status.signal = 50 + 10; | ||
995 | memcpy(IEEE80211_SKB_RXCB(skb_delba), &rx_status, | ||
996 | sizeof(rx_status)); | ||
997 | RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, | ||
998 | "fake del\n", skb_delba->data, | ||
999 | skb_delba->len); | ||
1000 | ieee80211_rx_irqsafe(hw, skb_delba); | ||
1001 | } | ||
1002 | } | ||
1003 | rcu_read_unlock(); | ||
1004 | return false; | ||
1005 | } | ||
1006 | |||
927 | bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) | 1007 | bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) |
928 | { | 1008 | { |
929 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | 1009 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
@@ -948,6 +1028,11 @@ bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) | |||
948 | RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, | 1028 | RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, |
949 | "%s ACT_ADDBAREQ From :%pM\n", | 1029 | "%s ACT_ADDBAREQ From :%pM\n", |
950 | is_tx ? "Tx" : "Rx", hdr->addr2); | 1030 | is_tx ? "Tx" : "Rx", hdr->addr2); |
1031 | RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, "req\n", | ||
1032 | skb->data, skb->len); | ||
1033 | if (!is_tx) | ||
1034 | if (addbareq_rx(hw, skb)) | ||
1035 | return true; | ||
951 | break; | 1036 | break; |
952 | case ACT_ADDBARSP: | 1037 | case ACT_ADDBARSP: |
953 | RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, | 1038 | RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, |
@@ -1101,6 +1186,58 @@ int rtl_tx_agg_stop(struct ieee80211_hw *hw, | |||
1101 | return 0; | 1186 | return 0; |
1102 | } | 1187 | } |
1103 | 1188 | ||
1189 | int rtl_rx_agg_start(struct ieee80211_hw *hw, | ||
1190 | struct ieee80211_sta *sta, u16 tid) | ||
1191 | { | ||
1192 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1193 | struct rtl_tid_data *tid_data; | ||
1194 | struct rtl_sta_info *sta_entry = NULL; | ||
1195 | |||
1196 | if (sta == NULL) | ||
1197 | return -EINVAL; | ||
1198 | |||
1199 | if (unlikely(tid >= MAX_TID_COUNT)) | ||
1200 | return -EINVAL; | ||
1201 | |||
1202 | sta_entry = (struct rtl_sta_info *)sta->drv_priv; | ||
1203 | if (!sta_entry) | ||
1204 | return -ENXIO; | ||
1205 | tid_data = &sta_entry->tids[tid]; | ||
1206 | |||
1207 | RT_TRACE(rtlpriv, COMP_RECV, DBG_DMESG, | ||
1208 | "on ra = %pM tid = %d seq:%d\n", sta->addr, tid, | ||
1209 | tid_data->seq_number); | ||
1210 | |||
1211 | tid_data->agg.rx_agg_state = RTL_RX_AGG_START; | ||
1212 | return 0; | ||
1213 | } | ||
1214 | |||
1215 | int rtl_rx_agg_stop(struct ieee80211_hw *hw, | ||
1216 | struct ieee80211_sta *sta, u16 tid) | ||
1217 | { | ||
1218 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1219 | struct rtl_sta_info *sta_entry = NULL; | ||
1220 | |||
1221 | if (sta == NULL) | ||
1222 | return -EINVAL; | ||
1223 | |||
1224 | if (!sta->addr) { | ||
1225 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "ra = NULL\n"); | ||
1226 | return -EINVAL; | ||
1227 | } | ||
1228 | |||
1229 | RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, | ||
1230 | "on ra = %pM tid = %d\n", sta->addr, tid); | ||
1231 | |||
1232 | if (unlikely(tid >= MAX_TID_COUNT)) | ||
1233 | return -EINVAL; | ||
1234 | |||
1235 | sta_entry = (struct rtl_sta_info *)sta->drv_priv; | ||
1236 | sta_entry->tids[tid].agg.rx_agg_state = RTL_RX_AGG_STOP; | ||
1237 | |||
1238 | return 0; | ||
1239 | } | ||
1240 | |||
1104 | int rtl_tx_agg_oper(struct ieee80211_hw *hw, | 1241 | int rtl_tx_agg_oper(struct ieee80211_hw *hw, |
1105 | struct ieee80211_sta *sta, u16 tid) | 1242 | struct ieee80211_sta *sta, u16 tid) |
1106 | { | 1243 | { |
@@ -1132,6 +1269,34 @@ int rtl_tx_agg_oper(struct ieee80211_hw *hw, | |||
1132 | * wq & timer callback functions | 1269 | * wq & timer callback functions |
1133 | * | 1270 | * |
1134 | *********************************************************/ | 1271 | *********************************************************/ |
1272 | /* this function is used for roaming */ | ||
1273 | void rtl_beacon_statistic(struct ieee80211_hw *hw, struct sk_buff *skb) | ||
1274 | { | ||
1275 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1276 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
1277 | |||
1278 | if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION) | ||
1279 | return; | ||
1280 | |||
1281 | if (rtlpriv->mac80211.link_state < MAC80211_LINKED) | ||
1282 | return; | ||
1283 | |||
1284 | /* check if this really is a beacon */ | ||
1285 | if (!ieee80211_is_beacon(hdr->frame_control) && | ||
1286 | !ieee80211_is_probe_resp(hdr->frame_control)) | ||
1287 | return; | ||
1288 | |||
1289 | /* min. beacon length + FCS_LEN */ | ||
1290 | if (skb->len <= 40 + FCS_LEN) | ||
1291 | return; | ||
1292 | |||
1293 | /* and only beacons from the associated BSSID, please */ | ||
1294 | if (compare_ether_addr(hdr->addr3, rtlpriv->mac80211.bssid)) | ||
1295 | return; | ||
1296 | |||
1297 | rtlpriv->link_info.bcn_rx_inperiod++; | ||
1298 | } | ||
1299 | |||
1135 | void rtl_watchdog_wq_callback(void *data) | 1300 | void rtl_watchdog_wq_callback(void *data) |
1136 | { | 1301 | { |
1137 | struct rtl_works *rtlworks = container_of_dwork_rtl(data, | 1302 | struct rtl_works *rtlworks = container_of_dwork_rtl(data, |
@@ -1142,6 +1307,8 @@ void rtl_watchdog_wq_callback(void *data) | |||
1142 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | 1307 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
1143 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | 1308 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
1144 | bool busytraffic = false; | 1309 | bool busytraffic = false; |
1310 | bool tx_busy_traffic = false; | ||
1311 | bool rx_busy_traffic = false; | ||
1145 | bool higher_busytraffic = false; | 1312 | bool higher_busytraffic = false; |
1146 | bool higher_busyrxtraffic = false; | 1313 | bool higher_busyrxtraffic = false; |
1147 | u8 idx, tid; | 1314 | u8 idx, tid; |
@@ -1191,8 +1358,13 @@ void rtl_watchdog_wq_callback(void *data) | |||
1191 | aver_tx_cnt_inperiod = tx_cnt_inp4eriod / 4; | 1358 | aver_tx_cnt_inperiod = tx_cnt_inp4eriod / 4; |
1192 | 1359 | ||
1193 | /* (2) check traffic busy */ | 1360 | /* (2) check traffic busy */ |
1194 | if (aver_rx_cnt_inperiod > 100 || aver_tx_cnt_inperiod > 100) | 1361 | if (aver_rx_cnt_inperiod > 100 || aver_tx_cnt_inperiod > 100) { |
1195 | busytraffic = true; | 1362 | busytraffic = true; |
1363 | if (aver_rx_cnt_inperiod > aver_tx_cnt_inperiod) | ||
1364 | rx_busy_traffic = true; | ||
1365 | else | ||
1366 | tx_busy_traffic = false; | ||
1367 | } | ||
1196 | 1368 | ||
1197 | /* Higher Tx/Rx data. */ | 1369 | /* Higher Tx/Rx data. */ |
1198 | if (aver_rx_cnt_inperiod > 4000 || | 1370 | if (aver_rx_cnt_inperiod > 4000 || |
@@ -1236,7 +1408,7 @@ void rtl_watchdog_wq_callback(void *data) | |||
1236 | if (enter_ps) | 1408 | if (enter_ps) |
1237 | rtl_lps_enter(hw); | 1409 | rtl_lps_enter(hw); |
1238 | else | 1410 | else |
1239 | rtl_lps_leave(hw); | 1411 | schedule_work(&rtlpriv->works.lps_leave_work); |
1240 | } | 1412 | } |
1241 | 1413 | ||
1242 | rtlpriv->link_info.num_rx_inperiod = 0; | 1414 | rtlpriv->link_info.num_rx_inperiod = 0; |
@@ -1246,10 +1418,37 @@ void rtl_watchdog_wq_callback(void *data) | |||
1246 | 1418 | ||
1247 | rtlpriv->link_info.busytraffic = busytraffic; | 1419 | rtlpriv->link_info.busytraffic = busytraffic; |
1248 | rtlpriv->link_info.higher_busytraffic = higher_busytraffic; | 1420 | rtlpriv->link_info.higher_busytraffic = higher_busytraffic; |
1421 | rtlpriv->link_info.rx_busy_traffic = rx_busy_traffic; | ||
1422 | rtlpriv->link_info.tx_busy_traffic = tx_busy_traffic; | ||
1249 | rtlpriv->link_info.higher_busyrxtraffic = higher_busyrxtraffic; | 1423 | rtlpriv->link_info.higher_busyrxtraffic = higher_busyrxtraffic; |
1250 | 1424 | ||
1251 | /* <3> DM */ | 1425 | /* <3> DM */ |
1252 | rtlpriv->cfg->ops->dm_watchdog(hw); | 1426 | rtlpriv->cfg->ops->dm_watchdog(hw); |
1427 | |||
1428 | /* <4> roaming */ | ||
1429 | if (mac->link_state == MAC80211_LINKED && | ||
1430 | mac->opmode == NL80211_IFTYPE_STATION) { | ||
1431 | if ((rtlpriv->link_info.bcn_rx_inperiod + | ||
1432 | rtlpriv->link_info.num_rx_inperiod) == 0) { | ||
1433 | rtlpriv->link_info.roam_times++; | ||
1434 | RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG, | ||
1435 | "AP off for %d s\n", | ||
1436 | (rtlpriv->link_info.roam_times * 2)); | ||
1437 | |||
1438 | /* if we can't recv beacon for 6s, we should | ||
1439 | * reconnect this AP | ||
1440 | */ | ||
1441 | if (rtlpriv->link_info.roam_times >= 3) { | ||
1442 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
1443 | "AP off, try to reconnect now\n"); | ||
1444 | rtlpriv->link_info.roam_times = 0; | ||
1445 | ieee80211_connection_loss(rtlpriv->mac80211.vif); | ||
1446 | } | ||
1447 | } else { | ||
1448 | rtlpriv->link_info.roam_times = 0; | ||
1449 | } | ||
1450 | } | ||
1451 | rtlpriv->link_info.bcn_rx_inperiod = 0; | ||
1253 | } | 1452 | } |
1254 | 1453 | ||
1255 | void rtl_watch_dog_timer_callback(unsigned long data) | 1454 | void rtl_watch_dog_timer_callback(unsigned long data) |
@@ -1264,6 +1463,28 @@ void rtl_watch_dog_timer_callback(unsigned long data) | |||
1264 | jiffies + MSECS(RTL_WATCH_DOG_TIME)); | 1463 | jiffies + MSECS(RTL_WATCH_DOG_TIME)); |
1265 | } | 1464 | } |
1266 | 1465 | ||
1466 | void rtl_fwevt_wq_callback(void *data) | ||
1467 | { | ||
1468 | struct rtl_works *rtlworks = | ||
1469 | container_of_dwork_rtl(data, struct rtl_works, fwevt_wq); | ||
1470 | struct ieee80211_hw *hw = rtlworks->hw; | ||
1471 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1472 | |||
1473 | rtlpriv->cfg->ops->c2h_command_handle(hw); | ||
1474 | } | ||
1475 | |||
1476 | void rtl_easy_concurrent_retrytimer_callback(unsigned long data) | ||
1477 | { | ||
1478 | struct ieee80211_hw *hw = (struct ieee80211_hw *)data; | ||
1479 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1480 | struct rtl_priv *buddy_priv = rtlpriv->buddy_priv; | ||
1481 | |||
1482 | if (buddy_priv == NULL) | ||
1483 | return; | ||
1484 | |||
1485 | rtlpriv->cfg->ops->dualmac_easy_concurrent(hw); | ||
1486 | } | ||
1487 | |||
1267 | /********************************************************* | 1488 | /********************************************************* |
1268 | * | 1489 | * |
1269 | * frame process functions | 1490 | * frame process functions |
@@ -1334,14 +1555,16 @@ static struct sk_buff *rtl_make_smps_action(struct ieee80211_hw *hw, | |||
1334 | } | 1555 | } |
1335 | 1556 | ||
1336 | int rtl_send_smps_action(struct ieee80211_hw *hw, | 1557 | int rtl_send_smps_action(struct ieee80211_hw *hw, |
1337 | struct ieee80211_sta *sta, u8 *da, u8 *bssid, | 1558 | struct ieee80211_sta *sta, |
1338 | enum ieee80211_smps_mode smps) | 1559 | enum ieee80211_smps_mode smps) |
1339 | { | 1560 | { |
1340 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1561 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1341 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | 1562 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
1342 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | 1563 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); |
1343 | struct sk_buff *skb = rtl_make_smps_action(hw, smps, da, bssid); | 1564 | struct sk_buff *skb = NULL; |
1344 | struct rtl_tcb_desc tcb_desc; | 1565 | struct rtl_tcb_desc tcb_desc; |
1566 | u8 bssid[ETH_ALEN] = {0}; | ||
1567 | |||
1345 | memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); | 1568 | memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); |
1346 | 1569 | ||
1347 | if (rtlpriv->mac80211.act_scanning) | 1570 | if (rtlpriv->mac80211.act_scanning) |
@@ -1356,21 +1579,67 @@ int rtl_send_smps_action(struct ieee80211_hw *hw, | |||
1356 | if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status)) | 1579 | if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status)) |
1357 | goto err_free; | 1580 | goto err_free; |
1358 | 1581 | ||
1582 | if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP) | ||
1583 | memcpy(bssid, rtlpriv->efuse.dev_addr, ETH_ALEN); | ||
1584 | else | ||
1585 | memcpy(bssid, rtlpriv->mac80211.bssid, ETH_ALEN); | ||
1586 | |||
1587 | skb = rtl_make_smps_action(hw, smps, sta->addr, bssid); | ||
1359 | /* this is a type = mgmt * stype = action frame */ | 1588 | /* this is a type = mgmt * stype = action frame */ |
1360 | if (skb) { | 1589 | if (skb) { |
1361 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1590 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1362 | struct rtl_sta_info *sta_entry = | 1591 | struct rtl_sta_info *sta_entry = |
1363 | (struct rtl_sta_info *) sta->drv_priv; | 1592 | (struct rtl_sta_info *) sta->drv_priv; |
1364 | sta_entry->mimo_ps = smps; | 1593 | sta_entry->mimo_ps = smps; |
1365 | rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); | ||
1366 | 1594 | ||
1367 | info->control.rates[0].idx = 0; | 1595 | info->control.rates[0].idx = 0; |
1368 | info->band = hw->conf.channel->band; | 1596 | info->band = hw->conf.channel->band; |
1369 | rtlpriv->intf_ops->adapter_tx(hw, sta, skb, &tcb_desc); | 1597 | rtlpriv->intf_ops->adapter_tx(hw, sta, skb, &tcb_desc); |
1370 | } | 1598 | } |
1599 | return 1; | ||
1600 | |||
1371 | err_free: | 1601 | err_free: |
1372 | return 0; | 1602 | return 0; |
1373 | } | 1603 | } |
1604 | EXPORT_SYMBOL(rtl_send_smps_action); | ||
1605 | |||
1606 | /* There seem to be issues in mac80211 regarding when del ba frames can be | ||
1607 | * received. As a work around, we make a fake del_ba if we receive a ba_req; | ||
1608 | * however, rx_agg was opened to let mac80211 release some ba related | ||
1609 | * resources. This del_ba is for tx only. | ||
1610 | */ | ||
1611 | struct sk_buff *rtl_make_del_ba(struct ieee80211_hw *hw, | ||
1612 | u8 *sa, u8 *bssid, u16 tid) | ||
1613 | { | ||
1614 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
1615 | struct sk_buff *skb; | ||
1616 | struct ieee80211_mgmt *action_frame; | ||
1617 | u16 params; | ||
1618 | |||
1619 | /* 27 = header + category + action + smps mode */ | ||
1620 | skb = dev_alloc_skb(34 + hw->extra_tx_headroom); | ||
1621 | if (!skb) | ||
1622 | return NULL; | ||
1623 | |||
1624 | skb_reserve(skb, hw->extra_tx_headroom); | ||
1625 | action_frame = (void *)skb_put(skb, 34); | ||
1626 | memset(action_frame, 0, 34); | ||
1627 | memcpy(action_frame->sa, sa, ETH_ALEN); | ||
1628 | memcpy(action_frame->da, rtlefuse->dev_addr, ETH_ALEN); | ||
1629 | memcpy(action_frame->bssid, bssid, ETH_ALEN); | ||
1630 | action_frame->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
1631 | IEEE80211_STYPE_ACTION); | ||
1632 | action_frame->u.action.category = WLAN_CATEGORY_BACK; | ||
1633 | action_frame->u.action.u.delba.action_code = WLAN_ACTION_DELBA; | ||
1634 | params = (u16)(1 << 11); /* bit 11 initiator */ | ||
1635 | params |= (u16)(tid << 12); /* bit 15:12 TID number */ | ||
1636 | |||
1637 | action_frame->u.action.u.delba.params = cpu_to_le16(params); | ||
1638 | action_frame->u.action.u.delba.reason_code = | ||
1639 | cpu_to_le16(WLAN_REASON_QSTA_TIMEOUT); | ||
1640 | |||
1641 | return skb; | ||
1642 | } | ||
1374 | 1643 | ||
1375 | /********************************************************* | 1644 | /********************************************************* |
1376 | * | 1645 | * |
@@ -1587,11 +1856,17 @@ MODULE_AUTHOR("Larry Finger <Larry.FInger@lwfinger.net>"); | |||
1587 | MODULE_LICENSE("GPL"); | 1856 | MODULE_LICENSE("GPL"); |
1588 | MODULE_DESCRIPTION("Realtek 802.11n PCI wireless core"); | 1857 | MODULE_DESCRIPTION("Realtek 802.11n PCI wireless core"); |
1589 | 1858 | ||
1859 | struct rtl_global_var global_var = {}; | ||
1860 | |||
1590 | static int __init rtl_core_module_init(void) | 1861 | static int __init rtl_core_module_init(void) |
1591 | { | 1862 | { |
1592 | if (rtl_rate_control_register()) | 1863 | if (rtl_rate_control_register()) |
1593 | pr_err("Unable to register rtl_rc, use default RC !!\n"); | 1864 | pr_err("Unable to register rtl_rc, use default RC !!\n"); |
1594 | 1865 | ||
1866 | /* init some global vars */ | ||
1867 | INIT_LIST_HEAD(&global_var.glb_priv_list); | ||
1868 | spin_lock_init(&global_var.glb_list_lock); | ||
1869 | |||
1595 | return 0; | 1870 | return 0; |
1596 | } | 1871 | } |
1597 | 1872 | ||
diff --git a/drivers/net/wireless/rtlwifi/base.h b/drivers/net/wireless/rtlwifi/base.h index 5a8c80e259f7..8576bc34b032 100644 --- a/drivers/net/wireless/rtlwifi/base.h +++ b/drivers/net/wireless/rtlwifi/base.h | |||
@@ -113,6 +113,7 @@ void rtl_init_rx_config(struct ieee80211_hw *hw); | |||
113 | void rtl_init_rfkill(struct ieee80211_hw *hw); | 113 | void rtl_init_rfkill(struct ieee80211_hw *hw); |
114 | void rtl_deinit_rfkill(struct ieee80211_hw *hw); | 114 | void rtl_deinit_rfkill(struct ieee80211_hw *hw); |
115 | 115 | ||
116 | void rtl_beacon_statistic(struct ieee80211_hw *hw, struct sk_buff *skb); | ||
116 | void rtl_watch_dog_timer_callback(unsigned long data); | 117 | void rtl_watch_dog_timer_callback(unsigned long data); |
117 | void rtl_deinit_deferred_work(struct ieee80211_hw *hw); | 118 | void rtl_deinit_deferred_work(struct ieee80211_hw *hw); |
118 | 119 | ||
@@ -126,7 +127,12 @@ int rtl_tx_agg_stop(struct ieee80211_hw *hw, struct ieee80211_sta *sta, | |||
126 | u16 tid); | 127 | u16 tid); |
127 | int rtl_tx_agg_oper(struct ieee80211_hw *hw, struct ieee80211_sta *sta, | 128 | int rtl_tx_agg_oper(struct ieee80211_hw *hw, struct ieee80211_sta *sta, |
128 | u16 tid); | 129 | u16 tid); |
130 | int rtl_rx_agg_start(struct ieee80211_hw *hw, struct ieee80211_sta *sta, | ||
131 | u16 tid); | ||
132 | int rtl_rx_agg_stop(struct ieee80211_hw *hw, struct ieee80211_sta *sta, | ||
133 | u16 tid); | ||
129 | void rtl_watchdog_wq_callback(void *data); | 134 | void rtl_watchdog_wq_callback(void *data); |
135 | void rtl_fwevt_wq_callback(void *data); | ||
130 | 136 | ||
131 | void rtl_get_tcb_desc(struct ieee80211_hw *hw, | 137 | void rtl_get_tcb_desc(struct ieee80211_hw *hw, |
132 | struct ieee80211_tx_info *info, | 138 | struct ieee80211_tx_info *info, |
@@ -134,14 +140,18 @@ void rtl_get_tcb_desc(struct ieee80211_hw *hw, | |||
134 | struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc); | 140 | struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc); |
135 | 141 | ||
136 | int rtl_send_smps_action(struct ieee80211_hw *hw, | 142 | int rtl_send_smps_action(struct ieee80211_hw *hw, |
137 | struct ieee80211_sta *sta, u8 *da, u8 *bssid, | 143 | struct ieee80211_sta *sta, |
138 | enum ieee80211_smps_mode smps); | 144 | enum ieee80211_smps_mode smps); |
139 | u8 *rtl_find_ie(u8 *data, unsigned int len, u8 ie); | 145 | u8 *rtl_find_ie(u8 *data, unsigned int len, u8 ie); |
140 | void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len); | 146 | void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len); |
141 | u8 rtl_tid_to_ac(u8 tid); | 147 | u8 rtl_tid_to_ac(u8 tid); |
142 | extern struct attribute_group rtl_attribute_group; | 148 | extern struct attribute_group rtl_attribute_group; |
149 | void rtl_easy_concurrent_retrytimer_callback(unsigned long data); | ||
150 | extern struct rtl_global_var global_var; | ||
143 | int rtlwifi_rate_mapping(struct ieee80211_hw *hw, | 151 | int rtlwifi_rate_mapping(struct ieee80211_hw *hw, |
144 | bool isht, u8 desc_rate, bool first_ampdu); | 152 | bool isht, u8 desc_rate, bool first_ampdu); |
145 | bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb); | 153 | bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb); |
154 | struct sk_buff *rtl_make_del_ba(struct ieee80211_hw *hw, | ||
155 | u8 *sa, u8 *bssid, u16 tid); | ||
146 | 156 | ||
147 | #endif | 157 | #endif |
diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c index b5a7a260bf63..3338cf311062 100644 --- a/drivers/net/wireless/rtlwifi/core.c +++ b/drivers/net/wireless/rtlwifi/core.c | |||
@@ -104,9 +104,12 @@ static void rtl_op_stop(struct ieee80211_hw *hw) | |||
104 | if (is_hal_stop(rtlhal)) | 104 | if (is_hal_stop(rtlhal)) |
105 | return; | 105 | return; |
106 | 106 | ||
107 | /* here is must, because adhoc do stop and start, | ||
108 | * but stop with RFOFF may cause something wrong, | ||
109 | * like adhoc TP | ||
110 | */ | ||
107 | if (unlikely(ppsc->rfpwr_state == ERFOFF)) { | 111 | if (unlikely(ppsc->rfpwr_state == ERFOFF)) { |
108 | rtl_ips_nic_on(hw); | 112 | rtl_ips_nic_on(hw); |
109 | mdelay(1); | ||
110 | } | 113 | } |
111 | 114 | ||
112 | mutex_lock(&rtlpriv->locks.conf_mutex); | 115 | mutex_lock(&rtlpriv->locks.conf_mutex); |
@@ -167,7 +170,11 @@ static int rtl_op_add_interface(struct ieee80211_hw *hw, | |||
167 | rtl_ips_nic_on(hw); | 170 | rtl_ips_nic_on(hw); |
168 | 171 | ||
169 | mutex_lock(&rtlpriv->locks.conf_mutex); | 172 | mutex_lock(&rtlpriv->locks.conf_mutex); |
170 | switch (vif->type) { | 173 | |
174 | switch (ieee80211_vif_type_p2p(vif)) { | ||
175 | case NL80211_IFTYPE_P2P_CLIENT: | ||
176 | mac->p2p = P2P_ROLE_CLIENT; | ||
177 | /*fall through*/ | ||
171 | case NL80211_IFTYPE_STATION: | 178 | case NL80211_IFTYPE_STATION: |
172 | if (mac->beacon_enabled == 1) { | 179 | if (mac->beacon_enabled == 1) { |
173 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, | 180 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, |
@@ -192,6 +199,9 @@ static int rtl_op_add_interface(struct ieee80211_hw *hw, | |||
192 | (u8 *) (&mac->basic_rates)); | 199 | (u8 *) (&mac->basic_rates)); |
193 | 200 | ||
194 | break; | 201 | break; |
202 | case NL80211_IFTYPE_P2P_GO: | ||
203 | mac->p2p = P2P_ROLE_GO; | ||
204 | /*fall through*/ | ||
195 | case NL80211_IFTYPE_AP: | 205 | case NL80211_IFTYPE_AP: |
196 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, | 206 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, |
197 | "NL80211_IFTYPE_AP\n"); | 207 | "NL80211_IFTYPE_AP\n"); |
@@ -205,6 +215,19 @@ static int rtl_op_add_interface(struct ieee80211_hw *hw, | |||
205 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, | 215 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, |
206 | (u8 *) (&mac->basic_rates)); | 216 | (u8 *) (&mac->basic_rates)); |
207 | break; | 217 | break; |
218 | case NL80211_IFTYPE_MESH_POINT: | ||
219 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, | ||
220 | "NL80211_IFTYPE_MESH_POINT\n"); | ||
221 | |||
222 | mac->link_state = MAC80211_LINKED; | ||
223 | rtlpriv->cfg->ops->set_bcn_reg(hw); | ||
224 | if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G) | ||
225 | mac->basic_rates = 0xfff; | ||
226 | else | ||
227 | mac->basic_rates = 0xff0; | ||
228 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, | ||
229 | (u8 *)(&mac->basic_rates)); | ||
230 | break; | ||
208 | default: | 231 | default: |
209 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | 232 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, |
210 | "operation mode %d is not supported!\n", vif->type); | 233 | "operation mode %d is not supported!\n", vif->type); |
@@ -212,6 +235,13 @@ static int rtl_op_add_interface(struct ieee80211_hw *hw, | |||
212 | goto out; | 235 | goto out; |
213 | } | 236 | } |
214 | 237 | ||
238 | if (mac->p2p) { | ||
239 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, | ||
240 | "p2p role %x\n", vif->type); | ||
241 | mac->basic_rates = 0xff0;/*disable cck rate for p2p*/ | ||
242 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, | ||
243 | (u8 *)(&mac->basic_rates)); | ||
244 | } | ||
215 | mac->vif = vif; | 245 | mac->vif = vif; |
216 | mac->opmode = vif->type; | 246 | mac->opmode = vif->type; |
217 | rtlpriv->cfg->ops->set_network_type(hw, vif->type); | 247 | rtlpriv->cfg->ops->set_network_type(hw, vif->type); |
@@ -232,9 +262,9 @@ static void rtl_op_remove_interface(struct ieee80211_hw *hw, | |||
232 | mutex_lock(&rtlpriv->locks.conf_mutex); | 262 | mutex_lock(&rtlpriv->locks.conf_mutex); |
233 | 263 | ||
234 | /* Free beacon resources */ | 264 | /* Free beacon resources */ |
235 | if ((mac->opmode == NL80211_IFTYPE_AP) || | 265 | if ((vif->type == NL80211_IFTYPE_AP) || |
236 | (mac->opmode == NL80211_IFTYPE_ADHOC) || | 266 | (vif->type == NL80211_IFTYPE_ADHOC) || |
237 | (mac->opmode == NL80211_IFTYPE_MESH_POINT)) { | 267 | (vif->type == NL80211_IFTYPE_MESH_POINT)) { |
238 | if (mac->beacon_enabled == 1) { | 268 | if (mac->beacon_enabled == 1) { |
239 | mac->beacon_enabled = 0; | 269 | mac->beacon_enabled = 0; |
240 | rtlpriv->cfg->ops->update_interrupt_mask(hw, 0, | 270 | rtlpriv->cfg->ops->update_interrupt_mask(hw, 0, |
@@ -247,6 +277,7 @@ static void rtl_op_remove_interface(struct ieee80211_hw *hw, | |||
247 | *Note: We assume NL80211_IFTYPE_UNSPECIFIED as | 277 | *Note: We assume NL80211_IFTYPE_UNSPECIFIED as |
248 | *NO LINK for our hardware. | 278 | *NO LINK for our hardware. |
249 | */ | 279 | */ |
280 | mac->p2p = 0; | ||
250 | mac->vif = NULL; | 281 | mac->vif = NULL; |
251 | mac->link_state = MAC80211_NOLINK; | 282 | mac->link_state = MAC80211_NOLINK; |
252 | memset(mac->bssid, 0, 6); | 283 | memset(mac->bssid, 0, 6); |
@@ -256,6 +287,22 @@ static void rtl_op_remove_interface(struct ieee80211_hw *hw, | |||
256 | mutex_unlock(&rtlpriv->locks.conf_mutex); | 287 | mutex_unlock(&rtlpriv->locks.conf_mutex); |
257 | } | 288 | } |
258 | 289 | ||
290 | static int rtl_op_change_interface(struct ieee80211_hw *hw, | ||
291 | struct ieee80211_vif *vif, | ||
292 | enum nl80211_iftype new_type, bool p2p) | ||
293 | { | ||
294 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
295 | int ret; | ||
296 | rtl_op_remove_interface(hw, vif); | ||
297 | |||
298 | vif->type = new_type; | ||
299 | vif->p2p = p2p; | ||
300 | ret = rtl_op_add_interface(hw, vif); | ||
301 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, | ||
302 | "p2p %x\n", p2p); | ||
303 | return ret; | ||
304 | } | ||
305 | |||
259 | static int rtl_op_config(struct ieee80211_hw *hw, u32 changed) | 306 | static int rtl_op_config(struct ieee80211_hw *hw, u32 changed) |
260 | { | 307 | { |
261 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 308 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
@@ -264,6 +311,9 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed) | |||
264 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | 311 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); |
265 | struct ieee80211_conf *conf = &hw->conf; | 312 | struct ieee80211_conf *conf = &hw->conf; |
266 | 313 | ||
314 | if (mac->skip_scan) | ||
315 | return 1; | ||
316 | |||
267 | mutex_lock(&rtlpriv->locks.conf_mutex); | 317 | mutex_lock(&rtlpriv->locks.conf_mutex); |
268 | if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) { /*BIT(2)*/ | 318 | if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) { /*BIT(2)*/ |
269 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, | 319 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, |
@@ -323,6 +373,16 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed) | |||
323 | struct ieee80211_channel *channel = hw->conf.channel; | 373 | struct ieee80211_channel *channel = hw->conf.channel; |
324 | u8 wide_chan = (u8) channel->hw_value; | 374 | u8 wide_chan = (u8) channel->hw_value; |
325 | 375 | ||
376 | if (mac->act_scanning) | ||
377 | mac->n_channels++; | ||
378 | |||
379 | if (rtlpriv->dm.supp_phymode_switch && | ||
380 | mac->link_state < MAC80211_LINKED && | ||
381 | !mac->act_scanning) { | ||
382 | if (rtlpriv->cfg->ops->chk_switch_dmdp) | ||
383 | rtlpriv->cfg->ops->chk_switch_dmdp(hw); | ||
384 | } | ||
385 | |||
326 | /* | 386 | /* |
327 | *because we should back channel to | 387 | *because we should back channel to |
328 | *current_network.chan in in scanning, | 388 | *current_network.chan in in scanning, |
@@ -373,13 +433,13 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed) | |||
373 | if (wide_chan <= 0) | 433 | if (wide_chan <= 0) |
374 | wide_chan = 1; | 434 | wide_chan = 1; |
375 | 435 | ||
376 | /* In scanning, before we go offchannel we may send a ps=1 null | 436 | /* In scanning, before we go offchannel we may send a ps = 1 |
377 | * to AP, and then we may send a ps = 0 null to AP quickly, but | 437 | * null to AP, and then we may send a ps = 0 null to AP quickly, |
378 | * first null may have caused AP to put lots of packet to hw tx | 438 | * but first null may have caused AP to put lots of packet to |
379 | * buffer. These packets must be tx'd before we go off channel | 439 | * hw tx buffer. These packets must be tx'd before we go off |
380 | * so we must delay more time to let AP flush these packets | 440 | * channel so we must delay more time to let AP flush these |
381 | * before going offchannel, or dis-association or delete BA will | 441 | * packets before going offchannel, or dis-association or |
382 | * happen by AP | 442 | * delete BA will be caused by AP |
383 | */ | 443 | */ |
384 | if (rtlpriv->mac80211.offchan_delay) { | 444 | if (rtlpriv->mac80211.offchan_delay) { |
385 | rtlpriv->mac80211.offchan_delay = false; | 445 | rtlpriv->mac80211.offchan_delay = false; |
@@ -441,7 +501,8 @@ static void rtl_op_configure_filter(struct ieee80211_hw *hw, | |||
441 | * and nolink check bssid is set in set network_type */ | 501 | * and nolink check bssid is set in set network_type */ |
442 | if ((changed_flags & FIF_BCN_PRBRESP_PROMISC) && | 502 | if ((changed_flags & FIF_BCN_PRBRESP_PROMISC) && |
443 | (mac->link_state >= MAC80211_LINKED)) { | 503 | (mac->link_state >= MAC80211_LINKED)) { |
444 | if (mac->opmode != NL80211_IFTYPE_AP) { | 504 | if (mac->opmode != NL80211_IFTYPE_AP && |
505 | mac->opmode != NL80211_IFTYPE_MESH_POINT) { | ||
445 | if (*new_flags & FIF_BCN_PRBRESP_PROMISC) { | 506 | if (*new_flags & FIF_BCN_PRBRESP_PROMISC) { |
446 | rtlpriv->cfg->ops->set_chk_bssid(hw, false); | 507 | rtlpriv->cfg->ops->set_chk_bssid(hw, false); |
447 | } else { | 508 | } else { |
@@ -481,32 +542,43 @@ static int rtl_op_sta_add(struct ieee80211_hw *hw, | |||
481 | { | 542 | { |
482 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 543 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
483 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | 544 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
545 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
484 | struct rtl_sta_info *sta_entry; | 546 | struct rtl_sta_info *sta_entry; |
485 | 547 | ||
486 | if (sta) { | 548 | if (sta) { |
487 | sta_entry = (struct rtl_sta_info *) sta->drv_priv; | 549 | sta_entry = (struct rtl_sta_info *) sta->drv_priv; |
550 | spin_lock_bh(&rtlpriv->locks.entry_list_lock); | ||
551 | list_add_tail(&sta_entry->list, &rtlpriv->entry_list); | ||
552 | spin_unlock_bh(&rtlpriv->locks.entry_list_lock); | ||
488 | if (rtlhal->current_bandtype == BAND_ON_2_4G) { | 553 | if (rtlhal->current_bandtype == BAND_ON_2_4G) { |
489 | sta_entry->wireless_mode = WIRELESS_MODE_G; | 554 | sta_entry->wireless_mode = WIRELESS_MODE_G; |
490 | if (sta->supp_rates[0] <= 0xf) | 555 | if (sta->supp_rates[0] <= 0xf) |
491 | sta_entry->wireless_mode = WIRELESS_MODE_B; | 556 | sta_entry->wireless_mode = WIRELESS_MODE_B; |
492 | if (sta->ht_cap.ht_supported) | 557 | if (sta->ht_cap.ht_supported == true) |
493 | sta_entry->wireless_mode = WIRELESS_MODE_N_24G; | 558 | sta_entry->wireless_mode = WIRELESS_MODE_N_24G; |
559 | |||
560 | if (vif->type == NL80211_IFTYPE_ADHOC) | ||
561 | sta_entry->wireless_mode = WIRELESS_MODE_G; | ||
494 | } else if (rtlhal->current_bandtype == BAND_ON_5G) { | 562 | } else if (rtlhal->current_bandtype == BAND_ON_5G) { |
495 | sta_entry->wireless_mode = WIRELESS_MODE_A; | 563 | sta_entry->wireless_mode = WIRELESS_MODE_A; |
496 | if (sta->ht_cap.ht_supported) | 564 | if (sta->ht_cap.ht_supported == true) |
497 | sta_entry->wireless_mode = WIRELESS_MODE_N_24G; | 565 | sta_entry->wireless_mode = WIRELESS_MODE_N_24G; |
498 | } | ||
499 | 566 | ||
500 | /* I found some times mac80211 give wrong supp_rates for adhoc*/ | 567 | if (vif->type == NL80211_IFTYPE_ADHOC) |
501 | if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC) | 568 | sta_entry->wireless_mode = WIRELESS_MODE_A; |
502 | sta_entry->wireless_mode = WIRELESS_MODE_G; | 569 | } |
570 | /*disable cck rate for p2p*/ | ||
571 | if (mac->p2p) | ||
572 | sta->supp_rates[0] &= 0xfffffff0; | ||
503 | 573 | ||
574 | memcpy(sta_entry->mac_addr, sta->addr, ETH_ALEN); | ||
504 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, | 575 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, |
505 | "Add sta addr is %pM\n", sta->addr); | 576 | "Add sta addr is %pM\n", sta->addr); |
506 | rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); | 577 | rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); |
507 | } | 578 | } |
508 | return 0; | 579 | return 0; |
509 | } | 580 | } |
581 | |||
510 | static int rtl_op_sta_remove(struct ieee80211_hw *hw, | 582 | static int rtl_op_sta_remove(struct ieee80211_hw *hw, |
511 | struct ieee80211_vif *vif, | 583 | struct ieee80211_vif *vif, |
512 | struct ieee80211_sta *sta) | 584 | struct ieee80211_sta *sta) |
@@ -519,9 +591,14 @@ static int rtl_op_sta_remove(struct ieee80211_hw *hw, | |||
519 | sta_entry = (struct rtl_sta_info *) sta->drv_priv; | 591 | sta_entry = (struct rtl_sta_info *) sta->drv_priv; |
520 | sta_entry->wireless_mode = 0; | 592 | sta_entry->wireless_mode = 0; |
521 | sta_entry->ratr_index = 0; | 593 | sta_entry->ratr_index = 0; |
594 | |||
595 | spin_lock_bh(&rtlpriv->locks.entry_list_lock); | ||
596 | list_del(&sta_entry->list); | ||
597 | spin_unlock_bh(&rtlpriv->locks.entry_list_lock); | ||
522 | } | 598 | } |
523 | return 0; | 599 | return 0; |
524 | } | 600 | } |
601 | |||
525 | static int _rtl_get_hal_qnum(u16 queue) | 602 | static int _rtl_get_hal_qnum(u16 queue) |
526 | { | 603 | { |
527 | int qnum; | 604 | int qnum; |
@@ -547,8 +624,8 @@ static int _rtl_get_hal_qnum(u16 queue) | |||
547 | } | 624 | } |
548 | 625 | ||
549 | /* | 626 | /* |
550 | *for mac80211 VO=0, VI=1, BE=2, BK=3 | 627 | *for mac80211 VO = 0, VI = 1, BE = 2, BK = 3 |
551 | *for rtl819x BE=0, BK=1, VI=2, VO=3 | 628 | *for rtl819x BE = 0, BK = 1, VI = 2, VO = 3 |
552 | */ | 629 | */ |
553 | static int rtl_op_conf_tx(struct ieee80211_hw *hw, | 630 | static int rtl_op_conf_tx(struct ieee80211_hw *hw, |
554 | struct ieee80211_vif *vif, u16 queue, | 631 | struct ieee80211_vif *vif, u16 queue, |
@@ -630,6 +707,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, | |||
630 | /*TODO: reference to enum ieee80211_bss_change */ | 707 | /*TODO: reference to enum ieee80211_bss_change */ |
631 | if (changed & BSS_CHANGED_ASSOC) { | 708 | if (changed & BSS_CHANGED_ASSOC) { |
632 | if (bss_conf->assoc) { | 709 | if (bss_conf->assoc) { |
710 | struct ieee80211_sta *sta = NULL; | ||
633 | /* we should reset all sec info & cam | 711 | /* we should reset all sec info & cam |
634 | * before set cam after linked, we should not | 712 | * before set cam after linked, we should not |
635 | * reset in disassoc, that will cause tkip->wep | 713 | * reset in disassoc, that will cause tkip->wep |
@@ -647,23 +725,37 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, | |||
647 | 725 | ||
648 | if (rtlpriv->cfg->ops->linked_set_reg) | 726 | if (rtlpriv->cfg->ops->linked_set_reg) |
649 | rtlpriv->cfg->ops->linked_set_reg(hw); | 727 | rtlpriv->cfg->ops->linked_set_reg(hw); |
650 | if (mac->opmode == NL80211_IFTYPE_STATION && sta) | 728 | rcu_read_lock(); |
729 | sta = ieee80211_find_sta(vif, (u8 *)bss_conf->bssid); | ||
730 | |||
731 | if (vif->type == NL80211_IFTYPE_STATION && sta) | ||
651 | rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); | 732 | rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); |
733 | RT_TRACE(rtlpriv, COMP_EASY_CONCURRENT, DBG_LOUD, | ||
734 | "send PS STATIC frame\n"); | ||
735 | if (rtlpriv->dm.supp_phymode_switch) { | ||
736 | if (sta->ht_cap.ht_supported) | ||
737 | rtl_send_smps_action(hw, sta, | ||
738 | IEEE80211_SMPS_STATIC); | ||
739 | } | ||
740 | rcu_read_unlock(); | ||
741 | |||
652 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, | 742 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, |
653 | "BSS_CHANGED_ASSOC\n"); | 743 | "BSS_CHANGED_ASSOC\n"); |
654 | } else { | 744 | } else { |
655 | if (mac->link_state == MAC80211_LINKED) | 745 | if (mac->link_state == MAC80211_LINKED) |
656 | rtl_lps_leave(hw); | 746 | schedule_work(&rtlpriv->works.lps_leave_work); |
657 | 747 | ||
748 | if (ppsc->p2p_ps_info.p2p_ps_mode > P2P_PS_NONE) | ||
749 | rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE); | ||
658 | mac->link_state = MAC80211_NOLINK; | 750 | mac->link_state = MAC80211_NOLINK; |
659 | memset(mac->bssid, 0, 6); | 751 | memset(mac->bssid, 0, 6); |
660 | |||
661 | /* reset sec info */ | ||
662 | rtl_cam_reset_sec_info(hw); | ||
663 | |||
664 | rtl_cam_reset_all_entry(hw); | ||
665 | mac->vendor = PEER_UNKNOWN; | 752 | mac->vendor = PEER_UNKNOWN; |
666 | 753 | ||
754 | if (rtlpriv->dm.supp_phymode_switch) { | ||
755 | if (rtlpriv->cfg->ops->chk_switch_dmdp) | ||
756 | rtlpriv->cfg->ops->chk_switch_dmdp(hw); | ||
757 | } | ||
758 | |||
667 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, | 759 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, |
668 | "BSS_CHANGED_UN_ASSOC\n"); | 760 | "BSS_CHANGED_UN_ASSOC\n"); |
669 | } | 761 | } |
@@ -778,7 +870,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, | |||
778 | } | 870 | } |
779 | 871 | ||
780 | if (changed & BSS_CHANGED_BASIC_RATES) { | 872 | if (changed & BSS_CHANGED_BASIC_RATES) { |
781 | /* for 5G must << RATE_6M_INDEX=4, | 873 | /* for 5G must << RATE_6M_INDEX = 4, |
782 | * because 5G have no cck rate*/ | 874 | * because 5G have no cck rate*/ |
783 | if (rtlhal->current_bandtype == BAND_ON_5G) | 875 | if (rtlhal->current_bandtype == BAND_ON_5G) |
784 | basic_rates = sta->supp_rates[1] << 4; | 876 | basic_rates = sta->supp_rates[1] << 4; |
@@ -815,6 +907,9 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, | |||
815 | ppsc->report_linked = false; | 907 | ppsc->report_linked = false; |
816 | } | 908 | } |
817 | } | 909 | } |
910 | if (rtlpriv->cfg->ops->bt_wifi_media_status_notify) | ||
911 | rtlpriv->cfg->ops->bt_wifi_media_status_notify(hw, | ||
912 | ppsc->report_linked); | ||
818 | } | 913 | } |
819 | 914 | ||
820 | out: | 915 | out: |
@@ -885,7 +980,6 @@ static int rtl_op_ampdu_action(struct ieee80211_hw *hw, | |||
885 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, | 980 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, |
886 | "IEEE80211_AMPDU_TX_STOP: TID:%d\n", tid); | 981 | "IEEE80211_AMPDU_TX_STOP: TID:%d\n", tid); |
887 | return rtl_tx_agg_stop(hw, sta, tid); | 982 | return rtl_tx_agg_stop(hw, sta, tid); |
888 | break; | ||
889 | case IEEE80211_AMPDU_TX_OPERATIONAL: | 983 | case IEEE80211_AMPDU_TX_OPERATIONAL: |
890 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, | 984 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, |
891 | "IEEE80211_AMPDU_TX_OPERATIONAL:TID:%d\n", tid); | 985 | "IEEE80211_AMPDU_TX_OPERATIONAL:TID:%d\n", tid); |
@@ -894,11 +988,11 @@ static int rtl_op_ampdu_action(struct ieee80211_hw *hw, | |||
894 | case IEEE80211_AMPDU_RX_START: | 988 | case IEEE80211_AMPDU_RX_START: |
895 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, | 989 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, |
896 | "IEEE80211_AMPDU_RX_START:TID:%d\n", tid); | 990 | "IEEE80211_AMPDU_RX_START:TID:%d\n", tid); |
897 | break; | 991 | return rtl_rx_agg_start(hw, sta, tid); |
898 | case IEEE80211_AMPDU_RX_STOP: | 992 | case IEEE80211_AMPDU_RX_STOP: |
899 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, | 993 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, |
900 | "IEEE80211_AMPDU_RX_STOP:TID:%d\n", tid); | 994 | "IEEE80211_AMPDU_RX_STOP:TID:%d\n", tid); |
901 | break; | 995 | return rtl_rx_agg_stop(hw, sta, tid); |
902 | default: | 996 | default: |
903 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | 997 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, |
904 | "IEEE80211_AMPDU_ERR!!!!:\n"); | 998 | "IEEE80211_AMPDU_ERR!!!!:\n"); |
@@ -912,12 +1006,19 @@ static void rtl_op_sw_scan_start(struct ieee80211_hw *hw) | |||
912 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1006 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
913 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | 1007 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
914 | 1008 | ||
915 | mac->act_scanning = true; | ||
916 | |||
917 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "\n"); | 1009 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "\n"); |
1010 | mac->act_scanning = true; | ||
1011 | if (rtlpriv->link_info.higher_busytraffic) { | ||
1012 | mac->skip_scan = true; | ||
1013 | return; | ||
1014 | } | ||
918 | 1015 | ||
1016 | if (rtlpriv->dm.supp_phymode_switch) { | ||
1017 | if (rtlpriv->cfg->ops->chk_switch_dmdp) | ||
1018 | rtlpriv->cfg->ops->chk_switch_dmdp(hw); | ||
1019 | } | ||
919 | if (mac->link_state == MAC80211_LINKED) { | 1020 | if (mac->link_state == MAC80211_LINKED) { |
920 | rtl_lps_leave(hw); | 1021 | schedule_work(&rtlpriv->works.lps_leave_work); |
921 | mac->link_state = MAC80211_LINKED_SCANNING; | 1022 | mac->link_state = MAC80211_LINKED_SCANNING; |
922 | } else { | 1023 | } else { |
923 | rtl_ips_nic_on(hw); | 1024 | rtl_ips_nic_on(hw); |
@@ -937,6 +1038,16 @@ static void rtl_op_sw_scan_complete(struct ieee80211_hw *hw) | |||
937 | 1038 | ||
938 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "\n"); | 1039 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "\n"); |
939 | mac->act_scanning = false; | 1040 | mac->act_scanning = false; |
1041 | mac->skip_scan = false; | ||
1042 | if (rtlpriv->link_info.higher_busytraffic) | ||
1043 | return; | ||
1044 | |||
1045 | /*p2p will use 1/6/11 to scan */ | ||
1046 | if (mac->n_channels == 3) | ||
1047 | mac->p2p_in_use = true; | ||
1048 | else | ||
1049 | mac->p2p_in_use = false; | ||
1050 | mac->n_channels = 0; | ||
940 | /* Dual mac */ | 1051 | /* Dual mac */ |
941 | rtlpriv->rtlhal.load_imrandiqk_setting_for2g = false; | 1052 | rtlpriv->rtlhal.load_imrandiqk_setting_for2g = false; |
942 | 1053 | ||
@@ -970,6 +1081,11 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
970 | "not open hw encryption\n"); | 1081 | "not open hw encryption\n"); |
971 | return -ENOSPC; /*User disabled HW-crypto */ | 1082 | return -ENOSPC; /*User disabled HW-crypto */ |
972 | } | 1083 | } |
1084 | /* To support IBSS, use sw-crypto for GTK */ | ||
1085 | if (((vif->type == NL80211_IFTYPE_ADHOC) || | ||
1086 | (vif->type == NL80211_IFTYPE_MESH_POINT)) && | ||
1087 | !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) | ||
1088 | return -ENOSPC; | ||
973 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, | 1089 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, |
974 | "%s hardware based encryption for keyidx: %d, mac: %pM\n", | 1090 | "%s hardware based encryption for keyidx: %d, mac: %pM\n", |
975 | cmd == SET_KEY ? "Using" : "Disabling", key->keyidx, | 1091 | cmd == SET_KEY ? "Using" : "Disabling", key->keyidx, |
@@ -996,6 +1112,14 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
996 | key_type = AESCCMP_ENCRYPTION; | 1112 | key_type = AESCCMP_ENCRYPTION; |
997 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:CCMP\n"); | 1113 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:CCMP\n"); |
998 | break; | 1114 | break; |
1115 | case WLAN_CIPHER_SUITE_AES_CMAC: | ||
1116 | /*HW doesn't support CMAC encryption, use software CMAC */ | ||
1117 | key_type = AESCMAC_ENCRYPTION; | ||
1118 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:CMAC\n"); | ||
1119 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, | ||
1120 | "HW don't support CMAC encryption, use software CMAC\n"); | ||
1121 | err = -EOPNOTSUPP; | ||
1122 | goto out_unlock; | ||
999 | default: | 1123 | default: |
1000 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "alg_err:%x!!!!\n", | 1124 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "alg_err:%x!!!!\n", |
1001 | key->cipher); | 1125 | key->cipher); |
@@ -1017,13 +1141,14 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
1017 | * 1) wep only: is just for wep enc, in this condition | 1141 | * 1) wep only: is just for wep enc, in this condition |
1018 | * rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION | 1142 | * rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION |
1019 | * will be true & enable_hw_sec will be set when wep | 1143 | * will be true & enable_hw_sec will be set when wep |
1020 | * ke setting. | 1144 | * key setting. |
1021 | * 2) wep(group) + AES(pairwise): some AP like cisco | 1145 | * 2) wep(group) + AES(pairwise): some AP like cisco |
1022 | * may use it, in this condition enable_hw_sec will not | 1146 | * may use it, in this condition enable_hw_sec will not |
1023 | * be set when wep key setting */ | 1147 | * be set when wep key setting */ |
1024 | /* we must reset sec_info after lingked before set key, | 1148 | /* we must reset sec_info after lingked before set key, |
1025 | * or some flag will be wrong*/ | 1149 | * or some flag will be wrong*/ |
1026 | if (mac->opmode == NL80211_IFTYPE_AP) { | 1150 | if (vif->type == NL80211_IFTYPE_AP || |
1151 | vif->type == NL80211_IFTYPE_MESH_POINT) { | ||
1027 | if (!group_key || key_type == WEP40_ENCRYPTION || | 1152 | if (!group_key || key_type == WEP40_ENCRYPTION || |
1028 | key_type == WEP104_ENCRYPTION) { | 1153 | key_type == WEP104_ENCRYPTION) { |
1029 | if (group_key) | 1154 | if (group_key) |
@@ -1098,12 +1223,16 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
1098 | key->hw_key_idx = key_idx; | 1223 | key->hw_key_idx = key_idx; |
1099 | if (key_type == TKIP_ENCRYPTION) | 1224 | if (key_type == TKIP_ENCRYPTION) |
1100 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; | 1225 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; |
1226 | /*use software CCMP encryption for management frames (MFP) */ | ||
1227 | if (key_type == AESCCMP_ENCRYPTION) | ||
1228 | key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; | ||
1101 | break; | 1229 | break; |
1102 | case DISABLE_KEY: | 1230 | case DISABLE_KEY: |
1103 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, | 1231 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, |
1104 | "disable key delete one entry\n"); | 1232 | "disable key delete one entry\n"); |
1105 | /*set local buf about wep key. */ | 1233 | /*set local buf about wep key. */ |
1106 | if (mac->opmode == NL80211_IFTYPE_AP) { | 1234 | if (vif->type == NL80211_IFTYPE_AP || |
1235 | vif->type == NL80211_IFTYPE_MESH_POINT) { | ||
1107 | if (sta) | 1236 | if (sta) |
1108 | rtl_cam_del_entry(hw, sta->addr); | 1237 | rtl_cam_del_entry(hw, sta->addr); |
1109 | } | 1238 | } |
@@ -1163,7 +1292,7 @@ static void rtl_op_rfkill_poll(struct ieee80211_hw *hw) | |||
1163 | } | 1292 | } |
1164 | 1293 | ||
1165 | /* this function is called by mac80211 to flush tx buffer | 1294 | /* this function is called by mac80211 to flush tx buffer |
1166 | * before switch channle or power save, or tx buffer packet | 1295 | * before switch channel or power save, or tx buffer packet |
1167 | * maybe send after offchannel or rf sleep, this may cause | 1296 | * maybe send after offchannel or rf sleep, this may cause |
1168 | * dis-association by AP */ | 1297 | * dis-association by AP */ |
1169 | static void rtl_op_flush(struct ieee80211_hw *hw, u32 queues, bool drop) | 1298 | static void rtl_op_flush(struct ieee80211_hw *hw, u32 queues, bool drop) |
@@ -1180,6 +1309,7 @@ const struct ieee80211_ops rtl_ops = { | |||
1180 | .tx = rtl_op_tx, | 1309 | .tx = rtl_op_tx, |
1181 | .add_interface = rtl_op_add_interface, | 1310 | .add_interface = rtl_op_add_interface, |
1182 | .remove_interface = rtl_op_remove_interface, | 1311 | .remove_interface = rtl_op_remove_interface, |
1312 | .change_interface = rtl_op_change_interface, | ||
1183 | .config = rtl_op_config, | 1313 | .config = rtl_op_config, |
1184 | .configure_filter = rtl_op_configure_filter, | 1314 | .configure_filter = rtl_op_configure_filter, |
1185 | .sta_add = rtl_op_sta_add, | 1315 | .sta_add = rtl_op_sta_add, |
diff --git a/drivers/net/wireless/rtlwifi/debug.c b/drivers/net/wireless/rtlwifi/debug.c index bdda9b2fffe1..7d52d3d7769f 100644 --- a/drivers/net/wireless/rtlwifi/debug.c +++ b/drivers/net/wireless/rtlwifi/debug.c | |||
@@ -41,7 +41,10 @@ void rtl_dbgp_flag_init(struct ieee80211_hw *hw) | |||
41 | COMP_BEACON | COMP_RATE | COMP_RXDESC | COMP_DIG | COMP_TXAGC | | 41 | COMP_BEACON | COMP_RATE | COMP_RXDESC | COMP_DIG | COMP_TXAGC | |
42 | COMP_POWER | COMP_POWER_TRACKING | COMP_BB_POWERSAVING | COMP_SWAS | | 42 | COMP_POWER | COMP_POWER_TRACKING | COMP_BB_POWERSAVING | COMP_SWAS | |
43 | COMP_RF | COMP_TURBO | COMP_RATR | COMP_CMD | | 43 | COMP_RF | COMP_TURBO | COMP_RATR | COMP_CMD | |
44 | COMP_EFUSE | COMP_QOS | COMP_MAC80211 | COMP_REGD | COMP_CHAN; | 44 | COMP_EFUSE | COMP_QOS | COMP_MAC80211 | COMP_REGD | COMP_CHAN | |
45 | COMP_EASY_CONCURRENT | COMP_EFUSE | COMP_QOS | COMP_MAC80211 | | ||
46 | COMP_REGD | COMP_CHAN | COMP_BT_COEXIST; | ||
47 | |||
45 | 48 | ||
46 | for (i = 0; i < DBGP_TYPE_MAX; i++) | 49 | for (i = 0; i < DBGP_TYPE_MAX; i++) |
47 | rtlpriv->dbg.dbgp_type[i] = 0; | 50 | rtlpriv->dbg.dbgp_type[i] = 0; |
diff --git a/drivers/net/wireless/rtlwifi/debug.h b/drivers/net/wireless/rtlwifi/debug.h index fd3269f47685..60119a666da7 100644 --- a/drivers/net/wireless/rtlwifi/debug.h +++ b/drivers/net/wireless/rtlwifi/debug.h | |||
@@ -135,6 +135,13 @@ | |||
135 | #define PHY_TXPWR BIT(8) | 135 | #define PHY_TXPWR BIT(8) |
136 | #define PHY_PWRDIFF BIT(9) | 136 | #define PHY_PWRDIFF BIT(9) |
137 | 137 | ||
138 | /* Define Dynamic Mechanism check module bit --> FDM */ | ||
139 | #define WA_IOT BIT(0) | ||
140 | #define DM_PWDB BIT(1) | ||
141 | #define DM_MONITOR BIT(2) | ||
142 | #define DM_DIG BIT(3) | ||
143 | #define DM_EDCA_TURBO BIT(4) | ||
144 | |||
138 | enum dbgp_flag_e { | 145 | enum dbgp_flag_e { |
139 | FQOS = 0, | 146 | FQOS = 0, |
140 | FTX = 1, | 147 | FTX = 1, |
diff --git a/drivers/net/wireless/rtlwifi/efuse.c b/drivers/net/wireless/rtlwifi/efuse.c index 8e2f9afb125a..41a03b12463b 100644 --- a/drivers/net/wireless/rtlwifi/efuse.c +++ b/drivers/net/wireless/rtlwifi/efuse.c | |||
@@ -35,8 +35,6 @@ static const u8 MAX_PGPKT_SIZE = 9; | |||
35 | static const u8 PGPKT_DATA_SIZE = 8; | 35 | static const u8 PGPKT_DATA_SIZE = 8; |
36 | static const int EFUSE_MAX_SIZE = 512; | 36 | static const int EFUSE_MAX_SIZE = 512; |
37 | 37 | ||
38 | static const u8 EFUSE_OOB_PROTECT_BYTES = 15; | ||
39 | |||
40 | static const struct efuse_map RTL8712_SDIO_EFUSE_TABLE[] = { | 38 | static const struct efuse_map RTL8712_SDIO_EFUSE_TABLE[] = { |
41 | {0, 0, 0, 2}, | 39 | {0, 0, 0, 2}, |
42 | {0, 1, 0, 2}, | 40 | {0, 1, 0, 2}, |
@@ -240,6 +238,7 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) | |||
240 | u8 rtemp8[1]; | 238 | u8 rtemp8[1]; |
241 | u16 efuse_addr = 0; | 239 | u16 efuse_addr = 0; |
242 | u8 offset, wren; | 240 | u8 offset, wren; |
241 | u8 u1temp = 0; | ||
243 | u16 i; | 242 | u16 i; |
244 | u16 j; | 243 | u16 j; |
245 | const u16 efuse_max_section = | 244 | const u16 efuse_max_section = |
@@ -285,10 +284,31 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) | |||
285 | } | 284 | } |
286 | 285 | ||
287 | while ((*rtemp8 != 0xFF) && (efuse_addr < efuse_len)) { | 286 | while ((*rtemp8 != 0xFF) && (efuse_addr < efuse_len)) { |
288 | offset = ((*rtemp8 >> 4) & 0x0f); | 287 | /* Check PG header for section num. */ |
288 | if ((*rtemp8 & 0x1F) == 0x0F) {/* extended header */ | ||
289 | u1temp = ((*rtemp8 & 0xE0) >> 5); | ||
290 | read_efuse_byte(hw, efuse_addr, rtemp8); | ||
289 | 291 | ||
290 | if (offset < efuse_max_section) { | 292 | if ((*rtemp8 & 0x0F) == 0x0F) { |
293 | efuse_addr++; | ||
294 | read_efuse_byte(hw, efuse_addr, rtemp8); | ||
295 | |||
296 | if (*rtemp8 != 0xFF && | ||
297 | (efuse_addr < efuse_len)) { | ||
298 | efuse_addr++; | ||
299 | } | ||
300 | continue; | ||
301 | } else { | ||
302 | offset = ((*rtemp8 & 0xF0) >> 1) | u1temp; | ||
303 | wren = (*rtemp8 & 0x0F); | ||
304 | efuse_addr++; | ||
305 | } | ||
306 | } else { | ||
307 | offset = ((*rtemp8 >> 4) & 0x0f); | ||
291 | wren = (*rtemp8 & 0x0f); | 308 | wren = (*rtemp8 & 0x0f); |
309 | } | ||
310 | |||
311 | if (offset < efuse_max_section) { | ||
292 | RTPRINT(rtlpriv, FEEPROM, EFUSE_READ_ALL, | 312 | RTPRINT(rtlpriv, FEEPROM, EFUSE_READ_ALL, |
293 | "offset-%d Worden=%x\n", offset, wren); | 313 | "offset-%d Worden=%x\n", offset, wren); |
294 | 314 | ||
@@ -391,7 +411,8 @@ bool efuse_shadow_update_chk(struct ieee80211_hw *hw) | |||
391 | efuse_used = rtlefuse->efuse_usedbytes; | 411 | efuse_used = rtlefuse->efuse_usedbytes; |
392 | 412 | ||
393 | if ((totalbytes + efuse_used) >= | 413 | if ((totalbytes + efuse_used) >= |
394 | (EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES)) | 414 | (EFUSE_MAX_SIZE - |
415 | rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN])) | ||
395 | result = false; | 416 | result = false; |
396 | 417 | ||
397 | RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, | 418 | RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, |
@@ -932,8 +953,8 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw, | |||
932 | u8 badworden = 0x0F; | 953 | u8 badworden = 0x0F; |
933 | static int repeat_times; | 954 | static int repeat_times; |
934 | 955 | ||
935 | if (efuse_get_current_size(hw) >= | 956 | if (efuse_get_current_size(hw) >= (EFUSE_MAX_SIZE - |
936 | (EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES)) { | 957 | rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN])) { |
937 | RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, | 958 | RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, |
938 | "efuse_pg_packet_write error\n"); | 959 | "efuse_pg_packet_write error\n"); |
939 | return false; | 960 | return false; |
@@ -949,8 +970,8 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw, | |||
949 | 970 | ||
950 | RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, "efuse Power ON\n"); | 971 | RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, "efuse Power ON\n"); |
951 | 972 | ||
952 | while (continual && (efuse_addr < | 973 | while (continual && (efuse_addr < (EFUSE_MAX_SIZE - |
953 | (EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES))) { | 974 | rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN]))) { |
954 | 975 | ||
955 | if (write_state == PG_STATE_HEADER) { | 976 | if (write_state == PG_STATE_HEADER) { |
956 | badworden = 0x0F; | 977 | badworden = 0x0F; |
@@ -1003,7 +1024,8 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw, | |||
1003 | } | 1024 | } |
1004 | } | 1025 | } |
1005 | 1026 | ||
1006 | if (efuse_addr >= (EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES)) { | 1027 | if (efuse_addr >= (EFUSE_MAX_SIZE - |
1028 | rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN])) { | ||
1007 | RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, | 1029 | RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, |
1008 | "efuse_addr(%#x) Out of size!!\n", efuse_addr); | 1030 | "efuse_addr(%#x) Out of size!!\n", efuse_addr); |
1009 | } | 1031 | } |
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index 4261e8ecc4c3..4af6abd1491c 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c | |||
@@ -59,7 +59,7 @@ static u8 _rtl_mac_to_hwqueue(struct ieee80211_hw *hw, | |||
59 | 59 | ||
60 | if (unlikely(ieee80211_is_beacon(fc))) | 60 | if (unlikely(ieee80211_is_beacon(fc))) |
61 | return BEACON_QUEUE; | 61 | return BEACON_QUEUE; |
62 | if (ieee80211_is_mgmt(fc)) | 62 | if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) |
63 | return MGNT_QUEUE; | 63 | return MGNT_QUEUE; |
64 | if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) | 64 | if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) |
65 | if (ieee80211_is_nullfunc(fc)) | 65 | if (ieee80211_is_nullfunc(fc)) |
@@ -271,9 +271,6 @@ static void rtl_pci_enable_aspm(struct ieee80211_hw *hw) | |||
271 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); | 271 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); |
272 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | 272 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); |
273 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | 273 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); |
274 | u8 pcibridge_busnum = pcipriv->ndis_adapter.pcibridge_busnum; | ||
275 | u8 pcibridge_devnum = pcipriv->ndis_adapter.pcibridge_devnum; | ||
276 | u8 pcibridge_funcnum = pcipriv->ndis_adapter.pcibridge_funcnum; | ||
277 | u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor; | 274 | u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor; |
278 | u8 num4bytes = pcipriv->ndis_adapter.num4bytes; | 275 | u8 num4bytes = pcipriv->ndis_adapter.num4bytes; |
279 | u16 aspmlevel; | 276 | u16 aspmlevel; |
@@ -302,8 +299,7 @@ static void rtl_pci_enable_aspm(struct ieee80211_hw *hw) | |||
302 | u_pcibridge_aspmsetting); | 299 | u_pcibridge_aspmsetting); |
303 | 300 | ||
304 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | 301 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, |
305 | "PlatformEnableASPM():PciBridge busnumber[%x], DevNumbe[%x], funcnumber[%x], Write reg[%x] = %x\n", | 302 | "PlatformEnableASPM(): Write reg[%x] = %x\n", |
306 | pcibridge_busnum, pcibridge_devnum, pcibridge_funcnum, | ||
307 | (pcipriv->ndis_adapter.pcibridge_pciehdr_offset + 0x10), | 303 | (pcipriv->ndis_adapter.pcibridge_pciehdr_offset + 0x10), |
308 | u_pcibridge_aspmsetting); | 304 | u_pcibridge_aspmsetting); |
309 | 305 | ||
@@ -349,6 +345,49 @@ static bool rtl_pci_get_amd_l1_patch(struct ieee80211_hw *hw) | |||
349 | return status; | 345 | return status; |
350 | } | 346 | } |
351 | 347 | ||
348 | static bool rtl_pci_check_buddy_priv(struct ieee80211_hw *hw, | ||
349 | struct rtl_priv **buddy_priv) | ||
350 | { | ||
351 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
352 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); | ||
353 | bool find_buddy_priv = false; | ||
354 | struct rtl_priv *tpriv = NULL; | ||
355 | struct rtl_pci_priv *tpcipriv = NULL; | ||
356 | |||
357 | if (!list_empty(&rtlpriv->glb_var->glb_priv_list)) { | ||
358 | list_for_each_entry(tpriv, &rtlpriv->glb_var->glb_priv_list, | ||
359 | list) { | ||
360 | if (tpriv) { | ||
361 | tpcipriv = (struct rtl_pci_priv *)tpriv->priv; | ||
362 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
363 | "pcipriv->ndis_adapter.funcnumber %x\n", | ||
364 | pcipriv->ndis_adapter.funcnumber); | ||
365 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
366 | "tpcipriv->ndis_adapter.funcnumber %x\n", | ||
367 | tpcipriv->ndis_adapter.funcnumber); | ||
368 | |||
369 | if ((pcipriv->ndis_adapter.busnumber == | ||
370 | tpcipriv->ndis_adapter.busnumber) && | ||
371 | (pcipriv->ndis_adapter.devnumber == | ||
372 | tpcipriv->ndis_adapter.devnumber) && | ||
373 | (pcipriv->ndis_adapter.funcnumber != | ||
374 | tpcipriv->ndis_adapter.funcnumber)) { | ||
375 | find_buddy_priv = true; | ||
376 | break; | ||
377 | } | ||
378 | } | ||
379 | } | ||
380 | } | ||
381 | |||
382 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
383 | "find_buddy_priv %d\n", find_buddy_priv); | ||
384 | |||
385 | if (find_buddy_priv) | ||
386 | *buddy_priv = tpriv; | ||
387 | |||
388 | return find_buddy_priv; | ||
389 | } | ||
390 | |||
352 | static void rtl_pci_get_linkcontrol_field(struct ieee80211_hw *hw) | 391 | static void rtl_pci_get_linkcontrol_field(struct ieee80211_hw *hw) |
353 | { | 392 | { |
354 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); | 393 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); |
@@ -420,17 +459,14 @@ static void _rtl_pci_io_handler_init(struct device *dev, | |||
420 | 459 | ||
421 | } | 460 | } |
422 | 461 | ||
423 | static void _rtl_pci_io_handler_release(struct ieee80211_hw *hw) | ||
424 | { | ||
425 | } | ||
426 | |||
427 | static bool _rtl_update_earlymode_info(struct ieee80211_hw *hw, | 462 | static bool _rtl_update_earlymode_info(struct ieee80211_hw *hw, |
428 | struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc, u8 tid) | 463 | struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc, u8 tid) |
429 | { | 464 | { |
430 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 465 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
431 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 466 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
432 | u8 additionlen = FCS_LEN; | 467 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
433 | struct sk_buff *next_skb; | 468 | struct sk_buff *next_skb; |
469 | u8 additionlen = FCS_LEN; | ||
434 | 470 | ||
435 | /* here open is 4, wep/tkip is 8, aes is 12*/ | 471 | /* here open is 4, wep/tkip is 8, aes is 12*/ |
436 | if (info->control.hw_key) | 472 | if (info->control.hw_key) |
@@ -455,7 +491,7 @@ static bool _rtl_update_earlymode_info(struct ieee80211_hw *hw, | |||
455 | next_skb)) | 491 | next_skb)) |
456 | break; | 492 | break; |
457 | 493 | ||
458 | if (tcb_desc->empkt_num >= 5) | 494 | if (tcb_desc->empkt_num >= rtlhal->max_earlymode_num) |
459 | break; | 495 | break; |
460 | } | 496 | } |
461 | spin_unlock_bh(&rtlpriv->locks.waitq_lock); | 497 | spin_unlock_bh(&rtlpriv->locks.waitq_lock); |
@@ -471,11 +507,17 @@ static void _rtl_pci_tx_chk_waitq(struct ieee80211_hw *hw) | |||
471 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | 507 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); |
472 | struct sk_buff *skb = NULL; | 508 | struct sk_buff *skb = NULL; |
473 | struct ieee80211_tx_info *info = NULL; | 509 | struct ieee80211_tx_info *info = NULL; |
510 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
474 | int tid; | 511 | int tid; |
475 | 512 | ||
476 | if (!rtlpriv->rtlhal.earlymode_enable) | 513 | if (!rtlpriv->rtlhal.earlymode_enable) |
477 | return; | 514 | return; |
478 | 515 | ||
516 | if (rtlpriv->dm.supp_phymode_switch && | ||
517 | (rtlpriv->easy_concurrent_ctl.switch_in_process || | ||
518 | (rtlpriv->buddy_priv && | ||
519 | rtlpriv->buddy_priv->easy_concurrent_ctl.switch_in_process))) | ||
520 | return; | ||
479 | /* we juse use em for BE/BK/VI/VO */ | 521 | /* we juse use em for BE/BK/VI/VO */ |
480 | for (tid = 7; tid >= 0; tid--) { | 522 | for (tid = 7; tid >= 0; tid--) { |
481 | u8 hw_queue = ac_to_hwq[rtl_tid_to_ac(tid)]; | 523 | u8 hw_queue = ac_to_hwq[rtl_tid_to_ac(tid)]; |
@@ -487,7 +529,8 @@ static void _rtl_pci_tx_chk_waitq(struct ieee80211_hw *hw) | |||
487 | 529 | ||
488 | spin_lock_bh(&rtlpriv->locks.waitq_lock); | 530 | spin_lock_bh(&rtlpriv->locks.waitq_lock); |
489 | if (!skb_queue_empty(&mac->skb_waitq[tid]) && | 531 | if (!skb_queue_empty(&mac->skb_waitq[tid]) && |
490 | (ring->entries - skb_queue_len(&ring->queue) > 5)) { | 532 | (ring->entries - skb_queue_len(&ring->queue) > |
533 | rtlhal->max_earlymode_num)) { | ||
491 | skb = skb_dequeue(&mac->skb_waitq[tid]); | 534 | skb = skb_dequeue(&mac->skb_waitq[tid]); |
492 | } else { | 535 | } else { |
493 | spin_unlock_bh(&rtlpriv->locks.waitq_lock); | 536 | spin_unlock_bh(&rtlpriv->locks.waitq_lock); |
@@ -525,9 +568,8 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio) | |||
525 | u8 own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) entry, true, | 568 | u8 own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) entry, true, |
526 | HW_DESC_OWN); | 569 | HW_DESC_OWN); |
527 | 570 | ||
528 | /* | 571 | /*beacon packet will only use the first |
529 | *beacon packet will only use the first | 572 | *descriptor by defaut, and the own may not |
530 | *descriptor defautly,and the own may not | ||
531 | *be cleared by the hardware | 573 | *be cleared by the hardware |
532 | */ | 574 | */ |
533 | if (own) | 575 | if (own) |
@@ -558,8 +600,9 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio) | |||
558 | } | 600 | } |
559 | 601 | ||
560 | /* for sw LPS, just after NULL skb send out, we can | 602 | /* for sw LPS, just after NULL skb send out, we can |
561 | * sure AP kown we are sleeped, our we should not let | 603 | * sure AP knows we are sleeping, we should not let |
562 | * rf to sleep*/ | 604 | * rf sleep |
605 | */ | ||
563 | fc = rtl_get_fc(skb); | 606 | fc = rtl_get_fc(skb); |
564 | if (ieee80211_is_nullfunc(fc)) { | 607 | if (ieee80211_is_nullfunc(fc)) { |
565 | if (ieee80211_has_pm(fc)) { | 608 | if (ieee80211_has_pm(fc)) { |
@@ -569,6 +612,15 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio) | |||
569 | rtlpriv->psc.state_inap = false; | 612 | rtlpriv->psc.state_inap = false; |
570 | } | 613 | } |
571 | } | 614 | } |
615 | if (ieee80211_is_action(fc)) { | ||
616 | struct ieee80211_mgmt *action_frame = | ||
617 | (struct ieee80211_mgmt *)skb->data; | ||
618 | if (action_frame->u.action.u.ht_smps.action == | ||
619 | WLAN_HT_ACTION_SMPS) { | ||
620 | dev_kfree_skb(skb); | ||
621 | goto tx_status_ok; | ||
622 | } | ||
623 | } | ||
572 | 624 | ||
573 | /* update tid tx pkt num */ | 625 | /* update tid tx pkt num */ |
574 | tid = rtl_get_tid(skb); | 626 | tid = rtl_get_tid(skb); |
@@ -637,6 +689,10 @@ static void _rtl_receive_one(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
637 | rtlpriv->link_info.num_rx_inperiod++; | 689 | rtlpriv->link_info.num_rx_inperiod++; |
638 | } | 690 | } |
639 | 691 | ||
692 | /* static bcn for roaming */ | ||
693 | rtl_beacon_statistic(hw, skb); | ||
694 | rtl_p2p_info(hw, (void *)skb->data, skb->len); | ||
695 | |||
640 | /* for sw lps */ | 696 | /* for sw lps */ |
641 | rtl_swlps_beacon(hw, (void *)skb->data, skb->len); | 697 | rtl_swlps_beacon(hw, (void *)skb->data, skb->len); |
642 | rtl_recognize_peer(hw, (void *)skb->data, skb->len); | 698 | rtl_recognize_peer(hw, (void *)skb->data, skb->len); |
@@ -884,6 +940,16 @@ static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id) | |||
884 | _rtl_pci_rx_interrupt(hw); | 940 | _rtl_pci_rx_interrupt(hw); |
885 | } | 941 | } |
886 | 942 | ||
943 | /*fw related*/ | ||
944 | if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723AE) { | ||
945 | if (inta & rtlpriv->cfg->maps[RTL_IMR_C2HCMD]) { | ||
946 | RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, | ||
947 | "firmware interrupt!\n"); | ||
948 | queue_delayed_work(rtlpriv->works.rtl_wq, | ||
949 | &rtlpriv->works.fwevt_wq, 0); | ||
950 | } | ||
951 | } | ||
952 | |||
887 | if (rtlpriv->rtlhal.earlymode_enable) | 953 | if (rtlpriv->rtlhal.earlymode_enable) |
888 | tasklet_schedule(&rtlpriv->works.irq_tasklet); | 954 | tasklet_schedule(&rtlpriv->works.irq_tasklet); |
889 | 955 | ||
@@ -1458,10 +1524,14 @@ static void rtl_pci_flush(struct ieee80211_hw *hw, bool drop) | |||
1458 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1524 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1459 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); | 1525 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); |
1460 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | 1526 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
1527 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
1461 | u16 i = 0; | 1528 | u16 i = 0; |
1462 | int queue_id; | 1529 | int queue_id; |
1463 | struct rtl8192_tx_ring *ring; | 1530 | struct rtl8192_tx_ring *ring; |
1464 | 1531 | ||
1532 | if (mac->skip_scan) | ||
1533 | return; | ||
1534 | |||
1465 | for (queue_id = RTL_PCI_MAX_TX_QUEUE_COUNT - 1; queue_id >= 0;) { | 1535 | for (queue_id = RTL_PCI_MAX_TX_QUEUE_COUNT - 1; queue_id >= 0;) { |
1466 | u32 queue_len; | 1536 | u32 queue_len; |
1467 | ring = &pcipriv->dev.tx_ring[queue_id]; | 1537 | ring = &pcipriv->dev.tx_ring[queue_id]; |
@@ -1704,6 +1774,9 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev, | |||
1704 | pcipriv->ndis_adapter.devnumber = PCI_SLOT(pdev->devfn); | 1774 | pcipriv->ndis_adapter.devnumber = PCI_SLOT(pdev->devfn); |
1705 | pcipriv->ndis_adapter.funcnumber = PCI_FUNC(pdev->devfn); | 1775 | pcipriv->ndis_adapter.funcnumber = PCI_FUNC(pdev->devfn); |
1706 | 1776 | ||
1777 | /* some ARM have no bridge_pdev and will crash here | ||
1778 | * so we should check if bridge_pdev is NULL | ||
1779 | */ | ||
1707 | if (bridge_pdev) { | 1780 | if (bridge_pdev) { |
1708 | /*find bridge info if available */ | 1781 | /*find bridge info if available */ |
1709 | pcipriv->ndis_adapter.pcibridge_vendorid = bridge_pdev->vendor; | 1782 | pcipriv->ndis_adapter.pcibridge_vendorid = bridge_pdev->vendor; |
@@ -1758,6 +1831,7 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev, | |||
1758 | pcipriv->ndis_adapter.amd_l1_patch); | 1831 | pcipriv->ndis_adapter.amd_l1_patch); |
1759 | 1832 | ||
1760 | rtl_pci_parse_configuration(pdev, hw); | 1833 | rtl_pci_parse_configuration(pdev, hw); |
1834 | list_add_tail(&rtlpriv->list, &rtlpriv->glb_var->glb_priv_list); | ||
1761 | 1835 | ||
1762 | return true; | 1836 | return true; |
1763 | } | 1837 | } |
@@ -1804,6 +1878,7 @@ int rtl_pci_probe(struct pci_dev *pdev, | |||
1804 | pci_set_drvdata(pdev, hw); | 1878 | pci_set_drvdata(pdev, hw); |
1805 | 1879 | ||
1806 | rtlpriv = hw->priv; | 1880 | rtlpriv = hw->priv; |
1881 | rtlpriv->hw = hw; | ||
1807 | pcipriv = (void *)rtlpriv->priv; | 1882 | pcipriv = (void *)rtlpriv->priv; |
1808 | pcipriv->dev.pdev = pdev; | 1883 | pcipriv->dev.pdev = pdev; |
1809 | init_completion(&rtlpriv->firmware_loading_complete); | 1884 | init_completion(&rtlpriv->firmware_loading_complete); |
@@ -1812,6 +1887,7 @@ int rtl_pci_probe(struct pci_dev *pdev, | |||
1812 | rtlpriv->rtlhal.interface = INTF_PCI; | 1887 | rtlpriv->rtlhal.interface = INTF_PCI; |
1813 | rtlpriv->cfg = (struct rtl_hal_cfg *)(id->driver_data); | 1888 | rtlpriv->cfg = (struct rtl_hal_cfg *)(id->driver_data); |
1814 | rtlpriv->intf_ops = &rtl_pci_ops; | 1889 | rtlpriv->intf_ops = &rtl_pci_ops; |
1890 | rtlpriv->glb_var = &global_var; | ||
1815 | 1891 | ||
1816 | /* | 1892 | /* |
1817 | *init dbgp flags before all | 1893 | *init dbgp flags before all |
@@ -1916,7 +1992,6 @@ int rtl_pci_probe(struct pci_dev *pdev, | |||
1916 | 1992 | ||
1917 | fail3: | 1993 | fail3: |
1918 | rtl_deinit_core(hw); | 1994 | rtl_deinit_core(hw); |
1919 | _rtl_pci_io_handler_release(hw); | ||
1920 | 1995 | ||
1921 | if (rtlpriv->io.pci_mem_start != 0) | 1996 | if (rtlpriv->io.pci_mem_start != 0) |
1922 | pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start); | 1997 | pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start); |
@@ -1965,14 +2040,15 @@ void rtl_pci_disconnect(struct pci_dev *pdev) | |||
1965 | 2040 | ||
1966 | rtl_pci_deinit(hw); | 2041 | rtl_pci_deinit(hw); |
1967 | rtl_deinit_core(hw); | 2042 | rtl_deinit_core(hw); |
1968 | _rtl_pci_io_handler_release(hw); | ||
1969 | rtlpriv->cfg->ops->deinit_sw_vars(hw); | 2043 | rtlpriv->cfg->ops->deinit_sw_vars(hw); |
1970 | 2044 | ||
1971 | if (rtlpci->irq_alloc) { | 2045 | if (rtlpci->irq_alloc) { |
2046 | synchronize_irq(rtlpci->pdev->irq); | ||
1972 | free_irq(rtlpci->pdev->irq, hw); | 2047 | free_irq(rtlpci->pdev->irq, hw); |
1973 | rtlpci->irq_alloc = 0; | 2048 | rtlpci->irq_alloc = 0; |
1974 | } | 2049 | } |
1975 | 2050 | ||
2051 | list_del(&rtlpriv->list); | ||
1976 | if (rtlpriv->io.pci_mem_start != 0) { | 2052 | if (rtlpriv->io.pci_mem_start != 0) { |
1977 | pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start); | 2053 | pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start); |
1978 | pci_release_regions(pdev); | 2054 | pci_release_regions(pdev); |
@@ -2034,6 +2110,7 @@ struct rtl_intf_ops rtl_pci_ops = { | |||
2034 | .read_efuse_byte = read_efuse_byte, | 2110 | .read_efuse_byte = read_efuse_byte, |
2035 | .adapter_start = rtl_pci_start, | 2111 | .adapter_start = rtl_pci_start, |
2036 | .adapter_stop = rtl_pci_stop, | 2112 | .adapter_stop = rtl_pci_stop, |
2113 | .check_buddy_priv = rtl_pci_check_buddy_priv, | ||
2037 | .adapter_tx = rtl_pci_tx, | 2114 | .adapter_tx = rtl_pci_tx, |
2038 | .flush = rtl_pci_flush, | 2115 | .flush = rtl_pci_flush, |
2039 | .reset_trx_ring = rtl_pci_reset_trx_ring, | 2116 | .reset_trx_ring = rtl_pci_reset_trx_ring, |
diff --git a/drivers/net/wireless/rtlwifi/pci.h b/drivers/net/wireless/rtlwifi/pci.h index 65b08f50022e..bd368d9c67fc 100644 --- a/drivers/net/wireless/rtlwifi/pci.h +++ b/drivers/net/wireless/rtlwifi/pci.h | |||
@@ -175,6 +175,7 @@ struct rtl_pci { | |||
175 | /*irq */ | 175 | /*irq */ |
176 | u8 irq_alloc; | 176 | u8 irq_alloc; |
177 | u32 irq_mask[2]; | 177 | u32 irq_mask[2]; |
178 | u32 sys_irq_mask; | ||
178 | 179 | ||
179 | /*Bcn control register setting */ | 180 | /*Bcn control register setting */ |
180 | u32 reg_bcn_ctrl_val; | 181 | u32 reg_bcn_ctrl_val; |
diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/rtlwifi/ps.c index 13ad33e85577..884bceae38a9 100644 --- a/drivers/net/wireless/rtlwifi/ps.c +++ b/drivers/net/wireless/rtlwifi/ps.c | |||
@@ -180,6 +180,9 @@ void rtl_ips_nic_off_wq_callback(void *data) | |||
180 | return; | 180 | return; |
181 | } | 181 | } |
182 | 182 | ||
183 | if (mac->p2p_in_use) | ||
184 | return; | ||
185 | |||
183 | if (mac->link_state > MAC80211_NOLINK) | 186 | if (mac->link_state > MAC80211_NOLINK) |
184 | return; | 187 | return; |
185 | 188 | ||
@@ -189,6 +192,9 @@ void rtl_ips_nic_off_wq_callback(void *data) | |||
189 | if (rtlpriv->sec.being_setkey) | 192 | if (rtlpriv->sec.being_setkey) |
190 | return; | 193 | return; |
191 | 194 | ||
195 | if (rtlpriv->cfg->ops->bt_coex_off_before_lps) | ||
196 | rtlpriv->cfg->ops->bt_coex_off_before_lps(hw); | ||
197 | |||
192 | if (ppsc->inactiveps) { | 198 | if (ppsc->inactiveps) { |
193 | rtstate = ppsc->rfpwr_state; | 199 | rtstate = ppsc->rfpwr_state; |
194 | 200 | ||
@@ -231,6 +237,9 @@ void rtl_ips_nic_off(struct ieee80211_hw *hw) | |||
231 | &rtlpriv->works.ips_nic_off_wq, MSECS(100)); | 237 | &rtlpriv->works.ips_nic_off_wq, MSECS(100)); |
232 | } | 238 | } |
233 | 239 | ||
240 | /* NOTICE: any opmode should exc nic_on, or disable without | ||
241 | * nic_on may something wrong, like adhoc TP | ||
242 | */ | ||
234 | void rtl_ips_nic_on(struct ieee80211_hw *hw) | 243 | void rtl_ips_nic_on(struct ieee80211_hw *hw) |
235 | { | 244 | { |
236 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 245 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
@@ -299,7 +308,7 @@ static void rtl_lps_set_psmode(struct ieee80211_hw *hw, u8 rt_psmode) | |||
299 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 308 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
300 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | 309 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
301 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | 310 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); |
302 | u8 rpwm_val, fw_pwrmode; | 311 | bool enter_fwlps; |
303 | 312 | ||
304 | if (mac->opmode == NL80211_IFTYPE_ADHOC) | 313 | if (mac->opmode == NL80211_IFTYPE_ADHOC) |
305 | return; | 314 | return; |
@@ -324,43 +333,31 @@ static void rtl_lps_set_psmode(struct ieee80211_hw *hw, u8 rt_psmode) | |||
324 | */ | 333 | */ |
325 | 334 | ||
326 | if ((ppsc->fwctrl_lps) && ppsc->report_linked) { | 335 | if ((ppsc->fwctrl_lps) && ppsc->report_linked) { |
327 | bool fw_current_inps; | ||
328 | if (ppsc->dot11_psmode == EACTIVE) { | 336 | if (ppsc->dot11_psmode == EACTIVE) { |
329 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, | 337 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, |
330 | "FW LPS leave ps_mode:%x\n", | 338 | "FW LPS leave ps_mode:%x\n", |
331 | FW_PS_ACTIVE_MODE); | 339 | FW_PS_ACTIVE_MODE); |
332 | 340 | enter_fwlps = false; | |
333 | rpwm_val = 0x0C; /* RF on */ | 341 | ppsc->pwr_mode = FW_PS_ACTIVE_MODE; |
334 | fw_pwrmode = FW_PS_ACTIVE_MODE; | 342 | ppsc->smart_ps = 0; |
335 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, | ||
336 | &rpwm_val); | ||
337 | rtlpriv->cfg->ops->set_hw_reg(hw, | 343 | rtlpriv->cfg->ops->set_hw_reg(hw, |
338 | HW_VAR_H2C_FW_PWRMODE, | 344 | HW_VAR_FW_LPS_ACTION, |
339 | &fw_pwrmode); | 345 | (u8 *)(&enter_fwlps)); |
340 | fw_current_inps = false; | 346 | if (ppsc->p2p_ps_info.opp_ps) |
341 | 347 | rtl_p2p_ps_cmd(hw, P2P_PS_ENABLE); | |
342 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
343 | HW_VAR_FW_PSMODE_STATUS, | ||
344 | (u8 *) (&fw_current_inps)); | ||
345 | 348 | ||
346 | } else { | 349 | } else { |
347 | if (rtl_get_fwlps_doze(hw)) { | 350 | if (rtl_get_fwlps_doze(hw)) { |
348 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, | 351 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, |
349 | "FW LPS enter ps_mode:%x\n", | 352 | "FW LPS enter ps_mode:%x\n", |
350 | ppsc->fwctrl_psmode); | 353 | ppsc->fwctrl_psmode); |
351 | 354 | enter_fwlps = true; | |
352 | rpwm_val = 0x02; /* RF off */ | 355 | ppsc->pwr_mode = ppsc->fwctrl_psmode; |
353 | fw_current_inps = true; | 356 | ppsc->smart_ps = 2; |
354 | rtlpriv->cfg->ops->set_hw_reg(hw, | 357 | rtlpriv->cfg->ops->set_hw_reg(hw, |
355 | HW_VAR_FW_PSMODE_STATUS, | 358 | HW_VAR_FW_LPS_ACTION, |
356 | (u8 *) (&fw_current_inps)); | 359 | (u8 *)(&enter_fwlps)); |
357 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
358 | HW_VAR_H2C_FW_PWRMODE, | ||
359 | &ppsc->fwctrl_psmode); | ||
360 | 360 | ||
361 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
362 | HW_VAR_SET_RPWM, | ||
363 | &rpwm_val); | ||
364 | } else { | 361 | } else { |
365 | /* Reset the power save related parameters. */ | 362 | /* Reset the power save related parameters. */ |
366 | ppsc->dot11_psmode = EACTIVE; | 363 | ppsc->dot11_psmode = EACTIVE; |
@@ -642,3 +639,286 @@ void rtl_swlps_wq_callback(void *data) | |||
642 | rtlpriv->psc.state = ps; | 639 | rtlpriv->psc.state = ps; |
643 | } | 640 | } |
644 | } | 641 | } |
642 | |||
643 | static void rtl_p2p_noa_ie(struct ieee80211_hw *hw, void *data, | ||
644 | unsigned int len) | ||
645 | { | ||
646 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
647 | struct ieee80211_mgmt *mgmt = (void *)data; | ||
648 | struct rtl_p2p_ps_info *p2pinfo = &(rtlpriv->psc.p2p_ps_info); | ||
649 | u8 *pos, *end, *ie; | ||
650 | u16 noa_len; | ||
651 | static u8 p2p_oui_ie_type[4] = {0x50, 0x6f, 0x9a, 0x09}; | ||
652 | u8 noa_num, index, i, noa_index = 0; | ||
653 | bool find_p2p_ie = false , find_p2p_ps_ie = false; | ||
654 | pos = (u8 *)mgmt->u.beacon.variable; | ||
655 | end = data + len; | ||
656 | ie = NULL; | ||
657 | |||
658 | while (pos + 1 < end) { | ||
659 | if (pos + 2 + pos[1] > end) | ||
660 | return; | ||
661 | |||
662 | if (pos[0] == 221 && pos[1] > 4) { | ||
663 | if (memcmp(&pos[2], p2p_oui_ie_type, 4) == 0) { | ||
664 | ie = pos + 2+4; | ||
665 | break; | ||
666 | } | ||
667 | } | ||
668 | pos += 2 + pos[1]; | ||
669 | } | ||
670 | |||
671 | if (ie == NULL) | ||
672 | return; | ||
673 | find_p2p_ie = true; | ||
674 | /*to find noa ie*/ | ||
675 | while (ie + 1 < end) { | ||
676 | noa_len = READEF2BYTE(&ie[1]); | ||
677 | if (ie + 3 + ie[1] > end) | ||
678 | return; | ||
679 | |||
680 | if (ie[0] == 12) { | ||
681 | find_p2p_ps_ie = true; | ||
682 | if ((noa_len - 2) % 13 != 0) { | ||
683 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
684 | "P2P notice of absence: invalid length.%d\n", | ||
685 | noa_len); | ||
686 | return; | ||
687 | } else { | ||
688 | noa_num = (noa_len - 2) / 13; | ||
689 | } | ||
690 | noa_index = ie[3]; | ||
691 | if (rtlpriv->psc.p2p_ps_info.p2p_ps_mode == | ||
692 | P2P_PS_NONE || noa_index != p2pinfo->noa_index) { | ||
693 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, | ||
694 | "update NOA ie.\n"); | ||
695 | p2pinfo->noa_index = noa_index; | ||
696 | p2pinfo->opp_ps = (ie[4] >> 7); | ||
697 | p2pinfo->ctwindow = ie[4] & 0x7F; | ||
698 | p2pinfo->noa_num = noa_num; | ||
699 | index = 5; | ||
700 | for (i = 0; i < noa_num; i++) { | ||
701 | p2pinfo->noa_count_type[i] = | ||
702 | READEF1BYTE(ie+index); | ||
703 | index += 1; | ||
704 | p2pinfo->noa_duration[i] = | ||
705 | READEF4BYTE(ie+index); | ||
706 | index += 4; | ||
707 | p2pinfo->noa_interval[i] = | ||
708 | READEF4BYTE(ie+index); | ||
709 | index += 4; | ||
710 | p2pinfo->noa_start_time[i] = | ||
711 | READEF4BYTE(ie+index); | ||
712 | index += 4; | ||
713 | } | ||
714 | |||
715 | if (p2pinfo->opp_ps == 1) { | ||
716 | p2pinfo->p2p_ps_mode = P2P_PS_CTWINDOW; | ||
717 | /* Driver should wait LPS entering | ||
718 | * CTWindow | ||
719 | */ | ||
720 | if (rtlpriv->psc.fw_current_inpsmode) | ||
721 | rtl_p2p_ps_cmd(hw, | ||
722 | P2P_PS_ENABLE); | ||
723 | } else if (p2pinfo->noa_num > 0) { | ||
724 | p2pinfo->p2p_ps_mode = P2P_PS_NOA; | ||
725 | rtl_p2p_ps_cmd(hw, P2P_PS_ENABLE); | ||
726 | } else if (p2pinfo->p2p_ps_mode > P2P_PS_NONE) { | ||
727 | rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE); | ||
728 | } | ||
729 | } | ||
730 | break; | ||
731 | } | ||
732 | ie += 3 + noa_len; | ||
733 | } | ||
734 | |||
735 | if (find_p2p_ie == true) { | ||
736 | if ((p2pinfo->p2p_ps_mode > P2P_PS_NONE) && | ||
737 | (find_p2p_ps_ie == false)) | ||
738 | rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE); | ||
739 | } | ||
740 | } | ||
741 | |||
742 | static void rtl_p2p_action_ie(struct ieee80211_hw *hw, void *data, | ||
743 | unsigned int len) | ||
744 | { | ||
745 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
746 | struct ieee80211_mgmt *mgmt = (void *)data; | ||
747 | struct rtl_p2p_ps_info *p2pinfo = &(rtlpriv->psc.p2p_ps_info); | ||
748 | u8 noa_num, index, i, noa_index = 0; | ||
749 | u8 *pos, *end, *ie; | ||
750 | u16 noa_len; | ||
751 | static u8 p2p_oui_ie_type[4] = {0x50, 0x6f, 0x9a, 0x09}; | ||
752 | |||
753 | pos = (u8 *)&mgmt->u.action.category; | ||
754 | end = data + len; | ||
755 | ie = NULL; | ||
756 | |||
757 | if (pos[0] == 0x7f) { | ||
758 | if (memcmp(&pos[1], p2p_oui_ie_type, 4) == 0) | ||
759 | ie = pos + 3+4; | ||
760 | } | ||
761 | |||
762 | if (ie == NULL) | ||
763 | return; | ||
764 | |||
765 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "action frame find P2P IE.\n"); | ||
766 | /*to find noa ie*/ | ||
767 | while (ie + 1 < end) { | ||
768 | noa_len = READEF2BYTE(&ie[1]); | ||
769 | if (ie + 3 + ie[1] > end) | ||
770 | return; | ||
771 | |||
772 | if (ie[0] == 12) { | ||
773 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "find NOA IE.\n"); | ||
774 | RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_LOUD, "noa ie ", | ||
775 | ie, noa_len); | ||
776 | if ((noa_len - 2) % 13 != 0) { | ||
777 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, | ||
778 | "P2P notice of absence: invalid length.%d\n", | ||
779 | noa_len); | ||
780 | return; | ||
781 | } else { | ||
782 | noa_num = (noa_len - 2) / 13; | ||
783 | } | ||
784 | noa_index = ie[3]; | ||
785 | if (rtlpriv->psc.p2p_ps_info.p2p_ps_mode == | ||
786 | P2P_PS_NONE || noa_index != p2pinfo->noa_index) { | ||
787 | p2pinfo->noa_index = noa_index; | ||
788 | p2pinfo->opp_ps = (ie[4] >> 7); | ||
789 | p2pinfo->ctwindow = ie[4] & 0x7F; | ||
790 | p2pinfo->noa_num = noa_num; | ||
791 | index = 5; | ||
792 | for (i = 0; i < noa_num; i++) { | ||
793 | p2pinfo->noa_count_type[i] = | ||
794 | READEF1BYTE(ie+index); | ||
795 | index += 1; | ||
796 | p2pinfo->noa_duration[i] = | ||
797 | READEF4BYTE(ie+index); | ||
798 | index += 4; | ||
799 | p2pinfo->noa_interval[i] = | ||
800 | READEF4BYTE(ie+index); | ||
801 | index += 4; | ||
802 | p2pinfo->noa_start_time[i] = | ||
803 | READEF4BYTE(ie+index); | ||
804 | index += 4; | ||
805 | } | ||
806 | |||
807 | if (p2pinfo->opp_ps == 1) { | ||
808 | p2pinfo->p2p_ps_mode = P2P_PS_CTWINDOW; | ||
809 | /* Driver should wait LPS entering | ||
810 | * CTWindow | ||
811 | */ | ||
812 | if (rtlpriv->psc.fw_current_inpsmode) | ||
813 | rtl_p2p_ps_cmd(hw, | ||
814 | P2P_PS_ENABLE); | ||
815 | } else if (p2pinfo->noa_num > 0) { | ||
816 | p2pinfo->p2p_ps_mode = P2P_PS_NOA; | ||
817 | rtl_p2p_ps_cmd(hw, P2P_PS_ENABLE); | ||
818 | } else if (p2pinfo->p2p_ps_mode > P2P_PS_NONE) { | ||
819 | rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE); | ||
820 | } | ||
821 | } | ||
822 | break; | ||
823 | } | ||
824 | ie += 3 + noa_len; | ||
825 | } | ||
826 | } | ||
827 | |||
828 | void rtl_p2p_ps_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state) | ||
829 | { | ||
830 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
831 | struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw)); | ||
832 | struct rtl_p2p_ps_info *p2pinfo = &(rtlpriv->psc.p2p_ps_info); | ||
833 | |||
834 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, " p2p state %x\n", p2p_ps_state); | ||
835 | switch (p2p_ps_state) { | ||
836 | case P2P_PS_DISABLE: | ||
837 | p2pinfo->p2p_ps_state = p2p_ps_state; | ||
838 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
839 | HW_VAR_H2C_FW_P2P_PS_OFFLOAD, | ||
840 | (u8 *)(&p2p_ps_state)); | ||
841 | |||
842 | p2pinfo->noa_index = 0; | ||
843 | p2pinfo->ctwindow = 0; | ||
844 | p2pinfo->opp_ps = 0; | ||
845 | p2pinfo->noa_num = 0; | ||
846 | p2pinfo->p2p_ps_mode = P2P_PS_NONE; | ||
847 | if (rtlps->fw_current_inpsmode == true) { | ||
848 | if (rtlps->smart_ps == 0) { | ||
849 | rtlps->smart_ps = 2; | ||
850 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
851 | HW_VAR_H2C_FW_PWRMODE, | ||
852 | (u8 *)(&rtlps->pwr_mode)); | ||
853 | } | ||
854 | } | ||
855 | break; | ||
856 | case P2P_PS_ENABLE: | ||
857 | if (p2pinfo->p2p_ps_mode > P2P_PS_NONE) { | ||
858 | p2pinfo->p2p_ps_state = p2p_ps_state; | ||
859 | |||
860 | if (p2pinfo->ctwindow > 0) { | ||
861 | if (rtlps->smart_ps != 0) { | ||
862 | rtlps->smart_ps = 0; | ||
863 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
864 | HW_VAR_H2C_FW_PWRMODE, | ||
865 | (u8 *)(&rtlps->pwr_mode)); | ||
866 | } | ||
867 | } | ||
868 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
869 | HW_VAR_H2C_FW_P2P_PS_OFFLOAD, | ||
870 | (u8 *)(&p2p_ps_state)); | ||
871 | } | ||
872 | break; | ||
873 | case P2P_PS_SCAN: | ||
874 | case P2P_PS_SCAN_DONE: | ||
875 | case P2P_PS_ALLSTASLEEP: | ||
876 | if (p2pinfo->p2p_ps_mode > P2P_PS_NONE) { | ||
877 | p2pinfo->p2p_ps_state = p2p_ps_state; | ||
878 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
879 | HW_VAR_H2C_FW_P2P_PS_OFFLOAD, | ||
880 | (u8 *)(&p2p_ps_state)); | ||
881 | } | ||
882 | break; | ||
883 | default: | ||
884 | break; | ||
885 | } | ||
886 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, | ||
887 | "ctwindow %x oppps %x\n", p2pinfo->ctwindow, p2pinfo->opp_ps); | ||
888 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, | ||
889 | "count %x duration %x index %x interval %x start time %x noa num %x\n", | ||
890 | p2pinfo->noa_count_type[0], p2pinfo->noa_duration[0], | ||
891 | p2pinfo->noa_index, p2pinfo->noa_interval[0], | ||
892 | p2pinfo->noa_start_time[0], p2pinfo->noa_num); | ||
893 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "end\n"); | ||
894 | } | ||
895 | |||
896 | void rtl_p2p_info(struct ieee80211_hw *hw, void *data, unsigned int len) | ||
897 | { | ||
898 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
899 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
900 | struct ieee80211_hdr *hdr = (void *)data; | ||
901 | |||
902 | if (!mac->p2p) | ||
903 | return; | ||
904 | if (mac->link_state != MAC80211_LINKED) | ||
905 | return; | ||
906 | /* min. beacon length + FCS_LEN */ | ||
907 | if (len <= 40 + FCS_LEN) | ||
908 | return; | ||
909 | |||
910 | /* and only beacons from the associated BSSID, please */ | ||
911 | if (compare_ether_addr(hdr->addr3, rtlpriv->mac80211.bssid)) | ||
912 | return; | ||
913 | |||
914 | /* check if this really is a beacon */ | ||
915 | if (!(ieee80211_is_beacon(hdr->frame_control) || | ||
916 | ieee80211_is_probe_resp(hdr->frame_control) || | ||
917 | ieee80211_is_action(hdr->frame_control))) | ||
918 | return; | ||
919 | |||
920 | if (ieee80211_is_action(hdr->frame_control)) | ||
921 | rtl_p2p_action_ie(hw, data, len - FCS_LEN); | ||
922 | else | ||
923 | rtl_p2p_noa_ie(hw, data, len - FCS_LEN); | ||
924 | } | ||
diff --git a/drivers/net/wireless/rtlwifi/ps.h b/drivers/net/wireless/rtlwifi/ps.h index 1357856998c2..4d682b753f50 100644 --- a/drivers/net/wireless/rtlwifi/ps.h +++ b/drivers/net/wireless/rtlwifi/ps.h | |||
@@ -47,5 +47,7 @@ void rtl_swlps_wq_callback(void *data); | |||
47 | void rtl_swlps_rfon_wq_callback(void *data); | 47 | void rtl_swlps_rfon_wq_callback(void *data); |
48 | void rtl_swlps_rf_awake(struct ieee80211_hw *hw); | 48 | void rtl_swlps_rf_awake(struct ieee80211_hw *hw); |
49 | void rtl_swlps_rf_sleep(struct ieee80211_hw *hw); | 49 | void rtl_swlps_rf_sleep(struct ieee80211_hw *hw); |
50 | void rtl_p2p_ps_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state); | ||
51 | void rtl_p2p_info(struct ieee80211_hw *hw, void *data, unsigned int len); | ||
50 | 52 | ||
51 | #endif | 53 | #endif |
diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index c3eff32acf6c..528888d69d2f 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h | |||
@@ -104,6 +104,7 @@ | |||
104 | /* for early mode */ | 104 | /* for early mode */ |
105 | #define FCS_LEN 4 | 105 | #define FCS_LEN 4 |
106 | #define EM_HDR_LEN 8 | 106 | #define EM_HDR_LEN 8 |
107 | |||
107 | enum intf_type { | 108 | enum intf_type { |
108 | INTF_PCI = 0, | 109 | INTF_PCI = 0, |
109 | INTF_USB = 1, | 110 | INTF_USB = 1, |
@@ -263,7 +264,7 @@ enum hw_variables { | |||
263 | HW_VAR_RATR_0, | 264 | HW_VAR_RATR_0, |
264 | HW_VAR_RRSR, | 265 | HW_VAR_RRSR, |
265 | HW_VAR_CPU_RST, | 266 | HW_VAR_CPU_RST, |
266 | HW_VAR_CECHK_BSSID, | 267 | HW_VAR_CHECK_BSSID, |
267 | HW_VAR_LBK_MODE, | 268 | HW_VAR_LBK_MODE, |
268 | HW_VAR_AES_11N_FIX, | 269 | HW_VAR_AES_11N_FIX, |
269 | HW_VAR_USB_RX_AGGR, | 270 | HW_VAR_USB_RX_AGGR, |
@@ -278,7 +279,10 @@ enum hw_variables { | |||
278 | HW_VAR_SET_RPWM, | 279 | HW_VAR_SET_RPWM, |
279 | HW_VAR_H2C_FW_PWRMODE, | 280 | HW_VAR_H2C_FW_PWRMODE, |
280 | HW_VAR_H2C_FW_JOINBSSRPT, | 281 | HW_VAR_H2C_FW_JOINBSSRPT, |
282 | HW_VAR_H2C_FW_P2P_PS_OFFLOAD, | ||
281 | HW_VAR_FW_PSMODE_STATUS, | 283 | HW_VAR_FW_PSMODE_STATUS, |
284 | HW_VAR_RESUME_CLK_ON, | ||
285 | HW_VAR_FW_LPS_ACTION, | ||
282 | HW_VAR_1X1_RECV_COMBINE, | 286 | HW_VAR_1X1_RECV_COMBINE, |
283 | HW_VAR_STOP_SEND_BEACON, | 287 | HW_VAR_STOP_SEND_BEACON, |
284 | HW_VAR_TSF_TIMER, | 288 | HW_VAR_TSF_TIMER, |
@@ -305,6 +309,7 @@ enum hw_variables { | |||
305 | HW_VAR_INT_AC, | 309 | HW_VAR_INT_AC, |
306 | HW_VAR_RF_TIMING, | 310 | HW_VAR_RF_TIMING, |
307 | 311 | ||
312 | HAL_DEF_WOWLAN, | ||
308 | HW_VAR_MRC, | 313 | HW_VAR_MRC, |
309 | 314 | ||
310 | HW_VAR_MGT_FILTER, | 315 | HW_VAR_MGT_FILTER, |
@@ -461,6 +466,7 @@ enum rtl_var_map { | |||
461 | EFUSE_MAX_SECTION_MAP, | 466 | EFUSE_MAX_SECTION_MAP, |
462 | EFUSE_REAL_CONTENT_SIZE, | 467 | EFUSE_REAL_CONTENT_SIZE, |
463 | EFUSE_OOB_PROTECT_BYTES_LEN, | 468 | EFUSE_OOB_PROTECT_BYTES_LEN, |
469 | EFUSE_ACCESS, | ||
464 | 470 | ||
465 | /*CAM map */ | 471 | /*CAM map */ |
466 | RWCAM, | 472 | RWCAM, |
@@ -742,6 +748,11 @@ struct false_alarm_statistics { | |||
742 | u32 cnt_ofdm_fail; | 748 | u32 cnt_ofdm_fail; |
743 | u32 cnt_cck_fail; | 749 | u32 cnt_cck_fail; |
744 | u32 cnt_all; | 750 | u32 cnt_all; |
751 | u32 cnt_ofdm_cca; | ||
752 | u32 cnt_cck_cca; | ||
753 | u32 cnt_cca_all; | ||
754 | u32 cnt_bw_usc; | ||
755 | u32 cnt_bw_lsc; | ||
745 | }; | 756 | }; |
746 | 757 | ||
747 | struct init_gain { | 758 | struct init_gain { |
@@ -826,8 +837,67 @@ struct rtl_rfkill { | |||
826 | bool rfkill_state; /*0 is off, 1 is on */ | 837 | bool rfkill_state; /*0 is off, 1 is on */ |
827 | }; | 838 | }; |
828 | 839 | ||
840 | /*for P2P PS**/ | ||
841 | #define P2P_MAX_NOA_NUM 2 | ||
842 | |||
843 | enum p2p_role { | ||
844 | P2P_ROLE_DISABLE = 0, | ||
845 | P2P_ROLE_DEVICE = 1, | ||
846 | P2P_ROLE_CLIENT = 2, | ||
847 | P2P_ROLE_GO = 3 | ||
848 | }; | ||
849 | |||
850 | enum p2p_ps_state { | ||
851 | P2P_PS_DISABLE = 0, | ||
852 | P2P_PS_ENABLE = 1, | ||
853 | P2P_PS_SCAN = 2, | ||
854 | P2P_PS_SCAN_DONE = 3, | ||
855 | P2P_PS_ALLSTASLEEP = 4, /* for P2P GO */ | ||
856 | }; | ||
857 | |||
858 | enum p2p_ps_mode { | ||
859 | P2P_PS_NONE = 0, | ||
860 | P2P_PS_CTWINDOW = 1, | ||
861 | P2P_PS_NOA = 2, | ||
862 | P2P_PS_MIX = 3, /* CTWindow and NoA */ | ||
863 | }; | ||
864 | |||
865 | struct rtl_p2p_ps_info { | ||
866 | enum p2p_ps_mode p2p_ps_mode; /* indicate p2p ps mode */ | ||
867 | enum p2p_ps_state p2p_ps_state; /* indicate p2p ps state */ | ||
868 | u8 noa_index; /* Identifies instance of Notice of Absence timing. */ | ||
869 | /* Client traffic window. A period of time in TU after TBTT. */ | ||
870 | u8 ctwindow; | ||
871 | u8 opp_ps; /* opportunistic power save. */ | ||
872 | u8 noa_num; /* number of NoA descriptor in P2P IE. */ | ||
873 | /* Count for owner, Type of client. */ | ||
874 | u8 noa_count_type[P2P_MAX_NOA_NUM]; | ||
875 | /* Max duration for owner, preferred or min acceptable duration | ||
876 | * for client. | ||
877 | */ | ||
878 | u32 noa_duration[P2P_MAX_NOA_NUM]; | ||
879 | /* Length of interval for owner, preferred or max acceptable intervali | ||
880 | * of client. | ||
881 | */ | ||
882 | u32 noa_interval[P2P_MAX_NOA_NUM]; | ||
883 | /* schedule in terms of the lower 4 bytes of the TSF timer. */ | ||
884 | u32 noa_start_time[P2P_MAX_NOA_NUM]; | ||
885 | }; | ||
886 | |||
887 | struct p2p_ps_offload_t { | ||
888 | u8 offload_en:1; | ||
889 | u8 role:1; /* 1: Owner, 0: Client */ | ||
890 | u8 ctwindow_en:1; | ||
891 | u8 noa0_en:1; | ||
892 | u8 noa1_en:1; | ||
893 | u8 allstasleep:1; | ||
894 | u8 discovery:1; | ||
895 | u8 reserved:1; | ||
896 | }; | ||
897 | |||
829 | #define IQK_MATRIX_REG_NUM 8 | 898 | #define IQK_MATRIX_REG_NUM 8 |
830 | #define IQK_MATRIX_SETTINGS_NUM (1 + 24 + 21) | 899 | #define IQK_MATRIX_SETTINGS_NUM (1 + 24 + 21) |
900 | |||
831 | struct iqk_matrix_regs { | 901 | struct iqk_matrix_regs { |
832 | bool iqk_done; | 902 | bool iqk_done; |
833 | long value[1][IQK_MATRIX_REG_NUM]; | 903 | long value[1][IQK_MATRIX_REG_NUM]; |
@@ -902,6 +972,8 @@ struct rtl_phy { | |||
902 | /* the current Tx power level */ | 972 | /* the current Tx power level */ |
903 | u8 cur_cck_txpwridx; | 973 | u8 cur_cck_txpwridx; |
904 | u8 cur_ofdm24g_txpwridx; | 974 | u8 cur_ofdm24g_txpwridx; |
975 | u8 cur_bw20_txpwridx; | ||
976 | u8 cur_bw40_txpwridx; | ||
905 | 977 | ||
906 | u32 rfreg_chnlval[2]; | 978 | u32 rfreg_chnlval[2]; |
907 | bool apk_done; | 979 | bool apk_done; |
@@ -940,20 +1012,21 @@ struct rtl_ht_agg { | |||
940 | u8 rx_agg_state; | 1012 | u8 rx_agg_state; |
941 | }; | 1013 | }; |
942 | 1014 | ||
1015 | struct rssi_sta { | ||
1016 | long undec_sm_pwdb; | ||
1017 | }; | ||
1018 | |||
943 | struct rtl_tid_data { | 1019 | struct rtl_tid_data { |
944 | u16 seq_number; | 1020 | u16 seq_number; |
945 | struct rtl_ht_agg agg; | 1021 | struct rtl_ht_agg agg; |
946 | }; | 1022 | }; |
947 | 1023 | ||
948 | struct rssi_sta { | ||
949 | long undec_sm_pwdb; | ||
950 | }; | ||
951 | |||
952 | struct rtl_sta_info { | 1024 | struct rtl_sta_info { |
953 | struct list_head list; | 1025 | struct list_head list; |
954 | u8 ratr_index; | 1026 | u8 ratr_index; |
955 | u8 wireless_mode; | 1027 | u8 wireless_mode; |
956 | u8 mimo_ps; | 1028 | u8 mimo_ps; |
1029 | u8 mac_addr[ETH_ALEN]; | ||
957 | struct rtl_tid_data tids[MAX_TID_COUNT]; | 1030 | struct rtl_tid_data tids[MAX_TID_COUNT]; |
958 | 1031 | ||
959 | /* just used for ap adhoc or mesh*/ | 1032 | /* just used for ap adhoc or mesh*/ |
@@ -1005,6 +1078,8 @@ struct rtl_mac { | |||
1005 | int n_bitrates; | 1078 | int n_bitrates; |
1006 | 1079 | ||
1007 | bool offchan_delay; | 1080 | bool offchan_delay; |
1081 | u8 p2p; /*using p2p role*/ | ||
1082 | bool p2p_in_use; | ||
1008 | 1083 | ||
1009 | /*filters */ | 1084 | /*filters */ |
1010 | u32 rx_conf; | 1085 | u32 rx_conf; |
@@ -1014,11 +1089,11 @@ struct rtl_mac { | |||
1014 | 1089 | ||
1015 | bool act_scanning; | 1090 | bool act_scanning; |
1016 | u8 cnt_after_linked; | 1091 | u8 cnt_after_linked; |
1092 | bool skip_scan; | ||
1017 | 1093 | ||
1018 | /* early mode */ | 1094 | /* early mode */ |
1019 | /* skb wait queue */ | 1095 | /* skb wait queue */ |
1020 | struct sk_buff_head skb_waitq[MAX_TID_COUNT]; | 1096 | struct sk_buff_head skb_waitq[MAX_TID_COUNT]; |
1021 | u8 earlymode_threshold; | ||
1022 | 1097 | ||
1023 | /*RDG*/ | 1098 | /*RDG*/ |
1024 | bool rdg_en; | 1099 | bool rdg_en; |
@@ -1042,6 +1117,7 @@ struct rtl_mac { | |||
1042 | u8 retry_short; | 1117 | u8 retry_short; |
1043 | u8 retry_long; | 1118 | u8 retry_long; |
1044 | u16 assoc_id; | 1119 | u16 assoc_id; |
1120 | bool hiddenssid; | ||
1045 | 1121 | ||
1046 | /*IBSS*/ | 1122 | /*IBSS*/ |
1047 | int beacon_interval; | 1123 | int beacon_interval; |
@@ -1111,10 +1187,13 @@ struct bt_coexist_8723 { | |||
1111 | 1187 | ||
1112 | struct rtl_hal { | 1188 | struct rtl_hal { |
1113 | struct ieee80211_hw *hw; | 1189 | struct ieee80211_hw *hw; |
1114 | struct bt_coexist_8723 hal_coex_8723; | 1190 | bool driver_is_goingto_unload; |
1115 | bool up_first_time; | 1191 | bool up_first_time; |
1192 | bool first_init; | ||
1116 | bool being_init_adapter; | 1193 | bool being_init_adapter; |
1117 | bool bbrf_ready; | 1194 | bool bbrf_ready; |
1195 | bool mac_func_enable; | ||
1196 | struct bt_coexist_8723 hal_coex_8723; | ||
1118 | 1197 | ||
1119 | enum intf_type interface; | 1198 | enum intf_type interface; |
1120 | u16 hw_type; /*92c or 92d or 92s and so on */ | 1199 | u16 hw_type; /*92c or 92d or 92s and so on */ |
@@ -1122,6 +1201,7 @@ struct rtl_hal { | |||
1122 | u8 oem_id; | 1201 | u8 oem_id; |
1123 | u32 version; /*version of chip */ | 1202 | u32 version; /*version of chip */ |
1124 | u8 state; /*stop 0, start 1 */ | 1203 | u8 state; /*stop 0, start 1 */ |
1204 | u8 board_type; | ||
1125 | 1205 | ||
1126 | /*firmware */ | 1206 | /*firmware */ |
1127 | u32 fwsize; | 1207 | u32 fwsize; |
@@ -1141,6 +1221,10 @@ struct rtl_hal { | |||
1141 | bool set_fwcmd_inprogress; | 1221 | bool set_fwcmd_inprogress; |
1142 | u8 current_fwcmd_io; | 1222 | u8 current_fwcmd_io; |
1143 | 1223 | ||
1224 | bool fw_clk_change_in_progress; | ||
1225 | bool allow_sw_to_change_hwclc; | ||
1226 | u8 fw_ps_state; | ||
1227 | struct p2p_ps_offload_t p2p_ps_offload; | ||
1144 | /**/ | 1228 | /**/ |
1145 | bool driver_going2unload; | 1229 | bool driver_going2unload; |
1146 | 1230 | ||
@@ -1157,6 +1241,7 @@ struct rtl_hal { | |||
1157 | /* just for DualMac S3S4 */ | 1241 | /* just for DualMac S3S4 */ |
1158 | u8 macphyctl_reg; | 1242 | u8 macphyctl_reg; |
1159 | bool earlymode_enable; | 1243 | bool earlymode_enable; |
1244 | u8 max_earlymode_num; | ||
1160 | /* Dual mac*/ | 1245 | /* Dual mac*/ |
1161 | bool during_mac0init_radiob; | 1246 | bool during_mac0init_radiob; |
1162 | bool during_mac1init_radioa; | 1247 | bool during_mac1init_radioa; |
@@ -1341,6 +1426,7 @@ struct rtl_ps_ctl { | |||
1341 | bool fw_current_inpsmode; | 1426 | bool fw_current_inpsmode; |
1342 | u8 reg_max_lps_awakeintvl; | 1427 | u8 reg_max_lps_awakeintvl; |
1343 | bool report_linked; | 1428 | bool report_linked; |
1429 | bool low_power_enable;/*for 32k*/ | ||
1344 | 1430 | ||
1345 | /*for IPS */ | 1431 | /*for IPS */ |
1346 | bool inactiveps; | 1432 | bool inactiveps; |
@@ -1373,6 +1459,11 @@ struct rtl_ps_ctl { | |||
1373 | unsigned long last_beacon; | 1459 | unsigned long last_beacon; |
1374 | unsigned long last_action; | 1460 | unsigned long last_action; |
1375 | unsigned long last_slept; | 1461 | unsigned long last_slept; |
1462 | |||
1463 | /*For P2P PS */ | ||
1464 | struct rtl_p2p_ps_info p2p_ps_info; | ||
1465 | u8 pwr_mode; | ||
1466 | u8 smart_ps; | ||
1376 | }; | 1467 | }; |
1377 | 1468 | ||
1378 | struct rtl_stats { | 1469 | struct rtl_stats { |
@@ -1553,7 +1644,7 @@ struct rtl_hal_ops { | |||
1553 | void (*allow_all_destaddr)(struct ieee80211_hw *hw, | 1644 | void (*allow_all_destaddr)(struct ieee80211_hw *hw, |
1554 | bool allow_all_da, bool write_into_reg); | 1645 | bool allow_all_da, bool write_into_reg); |
1555 | void (*linked_set_reg) (struct ieee80211_hw *hw); | 1646 | void (*linked_set_reg) (struct ieee80211_hw *hw); |
1556 | void (*check_switch_to_dmdp) (struct ieee80211_hw *hw); | 1647 | void (*chk_switch_dmdp) (struct ieee80211_hw *hw); |
1557 | void (*dualmac_easy_concurrent) (struct ieee80211_hw *hw); | 1648 | void (*dualmac_easy_concurrent) (struct ieee80211_hw *hw); |
1558 | void (*dualmac_switch_to_dmdp) (struct ieee80211_hw *hw); | 1649 | void (*dualmac_switch_to_dmdp) (struct ieee80211_hw *hw); |
1559 | bool (*phy_rf6052_config) (struct ieee80211_hw *hw); | 1650 | bool (*phy_rf6052_config) (struct ieee80211_hw *hw); |
@@ -1662,6 +1753,8 @@ struct rtl_locks { | |||
1662 | /*spin lock */ | 1753 | /*spin lock */ |
1663 | spinlock_t ips_lock; | 1754 | spinlock_t ips_lock; |
1664 | spinlock_t irq_th_lock; | 1755 | spinlock_t irq_th_lock; |
1756 | spinlock_t irq_pci_lock; | ||
1757 | spinlock_t tx_lock; | ||
1665 | spinlock_t h2c_lock; | 1758 | spinlock_t h2c_lock; |
1666 | spinlock_t rf_ps_lock; | 1759 | spinlock_t rf_ps_lock; |
1667 | spinlock_t rf_lock; | 1760 | spinlock_t rf_lock; |
@@ -1670,6 +1763,9 @@ struct rtl_locks { | |||
1670 | spinlock_t entry_list_lock; | 1763 | spinlock_t entry_list_lock; |
1671 | spinlock_t usb_lock; | 1764 | spinlock_t usb_lock; |
1672 | 1765 | ||
1766 | /*FW clock change */ | ||
1767 | spinlock_t fw_ps_lock; | ||
1768 | |||
1673 | /*Dual mac*/ | 1769 | /*Dual mac*/ |
1674 | spinlock_t cck_and_rw_pagea_lock; | 1770 | spinlock_t cck_and_rw_pagea_lock; |
1675 | 1771 | ||
@@ -1683,6 +1779,8 @@ struct rtl_works { | |||
1683 | /*timer */ | 1779 | /*timer */ |
1684 | struct timer_list watchdog_timer; | 1780 | struct timer_list watchdog_timer; |
1685 | struct timer_list dualmac_easyconcurrent_retrytimer; | 1781 | struct timer_list dualmac_easyconcurrent_retrytimer; |
1782 | struct timer_list fw_clockoff_timer; | ||
1783 | struct timer_list fast_antenna_training_timer; | ||
1686 | 1784 | ||
1687 | /*task */ | 1785 | /*task */ |
1688 | struct tasklet_struct irq_tasklet; | 1786 | struct tasklet_struct irq_tasklet; |
@@ -1696,6 +1794,7 @@ struct rtl_works { | |||
1696 | /* For SW LPS */ | 1794 | /* For SW LPS */ |
1697 | struct delayed_work ps_work; | 1795 | struct delayed_work ps_work; |
1698 | struct delayed_work ps_rfon_wq; | 1796 | struct delayed_work ps_rfon_wq; |
1797 | struct delayed_work fwevt_wq; | ||
1699 | 1798 | ||
1700 | struct work_struct lps_leave_work; | 1799 | struct work_struct lps_leave_work; |
1701 | }; | 1800 | }; |
@@ -1802,6 +1901,7 @@ struct rtl_global_var { | |||
1802 | }; | 1901 | }; |
1803 | 1902 | ||
1804 | struct rtl_priv { | 1903 | struct rtl_priv { |
1904 | struct ieee80211_hw *hw; | ||
1805 | struct completion firmware_loading_complete; | 1905 | struct completion firmware_loading_complete; |
1806 | struct list_head list; | 1906 | struct list_head list; |
1807 | struct rtl_priv *buddy_priv; | 1907 | struct rtl_priv *buddy_priv; |