18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 28c2ecf20Sopenharmony_ci/* Copyright(c) 2018-2019 Realtek Corporation 38c2ecf20Sopenharmony_ci */ 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_ci#include "main.h" 68c2ecf20Sopenharmony_ci#include "regd.h" 78c2ecf20Sopenharmony_ci#include "fw.h" 88c2ecf20Sopenharmony_ci#include "ps.h" 98c2ecf20Sopenharmony_ci#include "sec.h" 108c2ecf20Sopenharmony_ci#include "mac.h" 118c2ecf20Sopenharmony_ci#include "coex.h" 128c2ecf20Sopenharmony_ci#include "phy.h" 138c2ecf20Sopenharmony_ci#include "reg.h" 148c2ecf20Sopenharmony_ci#include "efuse.h" 158c2ecf20Sopenharmony_ci#include "tx.h" 168c2ecf20Sopenharmony_ci#include "debug.h" 178c2ecf20Sopenharmony_ci#include "bf.h" 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ciunsigned int rtw_fw_lps_deep_mode; 208c2ecf20Sopenharmony_ciEXPORT_SYMBOL(rtw_fw_lps_deep_mode); 218c2ecf20Sopenharmony_cibool rtw_bf_support = true; 228c2ecf20Sopenharmony_ciunsigned int rtw_debug_mask; 238c2ecf20Sopenharmony_ciEXPORT_SYMBOL(rtw_debug_mask); 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_cimodule_param_named(lps_deep_mode, rtw_fw_lps_deep_mode, uint, 0644); 268c2ecf20Sopenharmony_cimodule_param_named(support_bf, rtw_bf_support, bool, 0644); 278c2ecf20Sopenharmony_cimodule_param_named(debug_mask, rtw_debug_mask, uint, 0644); 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ciMODULE_PARM_DESC(lps_deep_mode, "Deeper PS mode. If 0, deep PS is disabled"); 308c2ecf20Sopenharmony_ciMODULE_PARM_DESC(support_bf, "Set Y to enable beamformee support"); 318c2ecf20Sopenharmony_ciMODULE_PARM_DESC(debug_mask, "Debugging mask"); 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cistatic struct ieee80211_channel rtw_channeltable_2g[] = { 348c2ecf20Sopenharmony_ci {.center_freq = 2412, .hw_value = 1,}, 358c2ecf20Sopenharmony_ci {.center_freq = 2417, .hw_value = 2,}, 368c2ecf20Sopenharmony_ci {.center_freq = 2422, .hw_value = 3,}, 378c2ecf20Sopenharmony_ci {.center_freq = 2427, .hw_value = 4,}, 388c2ecf20Sopenharmony_ci {.center_freq = 2432, .hw_value = 5,}, 398c2ecf20Sopenharmony_ci {.center_freq = 2437, .hw_value = 6,}, 408c2ecf20Sopenharmony_ci {.center_freq = 2442, .hw_value = 7,}, 418c2ecf20Sopenharmony_ci {.center_freq = 2447, .hw_value = 8,}, 428c2ecf20Sopenharmony_ci {.center_freq = 2452, .hw_value = 9,}, 438c2ecf20Sopenharmony_ci {.center_freq = 2457, .hw_value = 10,}, 448c2ecf20Sopenharmony_ci {.center_freq = 2462, .hw_value = 11,}, 458c2ecf20Sopenharmony_ci {.center_freq = 2467, .hw_value = 12,}, 468c2ecf20Sopenharmony_ci {.center_freq = 2472, .hw_value = 13,}, 478c2ecf20Sopenharmony_ci {.center_freq = 2484, .hw_value = 14,}, 488c2ecf20Sopenharmony_ci}; 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_cistatic struct ieee80211_channel rtw_channeltable_5g[] = { 518c2ecf20Sopenharmony_ci {.center_freq = 5180, .hw_value = 36,}, 528c2ecf20Sopenharmony_ci {.center_freq = 5200, .hw_value = 40,}, 538c2ecf20Sopenharmony_ci {.center_freq = 5220, .hw_value = 44,}, 548c2ecf20Sopenharmony_ci {.center_freq = 5240, .hw_value = 48,}, 558c2ecf20Sopenharmony_ci {.center_freq = 5260, .hw_value = 52,}, 568c2ecf20Sopenharmony_ci {.center_freq = 5280, .hw_value = 56,}, 578c2ecf20Sopenharmony_ci {.center_freq = 5300, .hw_value = 60,}, 588c2ecf20Sopenharmony_ci {.center_freq = 5320, .hw_value = 64,}, 598c2ecf20Sopenharmony_ci {.center_freq = 5500, .hw_value = 100,}, 608c2ecf20Sopenharmony_ci {.center_freq = 5520, .hw_value = 104,}, 618c2ecf20Sopenharmony_ci {.center_freq = 5540, .hw_value = 108,}, 628c2ecf20Sopenharmony_ci {.center_freq = 5560, .hw_value = 112,}, 638c2ecf20Sopenharmony_ci {.center_freq = 5580, .hw_value = 116,}, 648c2ecf20Sopenharmony_ci {.center_freq = 5600, .hw_value = 120,}, 658c2ecf20Sopenharmony_ci {.center_freq = 5620, .hw_value = 124,}, 668c2ecf20Sopenharmony_ci {.center_freq = 5640, .hw_value = 128,}, 678c2ecf20Sopenharmony_ci {.center_freq = 5660, .hw_value = 132,}, 688c2ecf20Sopenharmony_ci {.center_freq = 5680, .hw_value = 136,}, 698c2ecf20Sopenharmony_ci {.center_freq = 5700, .hw_value = 140,}, 708c2ecf20Sopenharmony_ci {.center_freq = 5745, .hw_value = 149,}, 718c2ecf20Sopenharmony_ci {.center_freq = 5765, .hw_value = 153,}, 728c2ecf20Sopenharmony_ci {.center_freq = 5785, .hw_value = 157,}, 738c2ecf20Sopenharmony_ci {.center_freq = 5805, .hw_value = 161,}, 748c2ecf20Sopenharmony_ci {.center_freq = 5825, .hw_value = 165, 758c2ecf20Sopenharmony_ci .flags = IEEE80211_CHAN_NO_HT40MINUS}, 768c2ecf20Sopenharmony_ci}; 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_cistatic struct ieee80211_rate rtw_ratetable[] = { 798c2ecf20Sopenharmony_ci {.bitrate = 10, .hw_value = 0x00,}, 808c2ecf20Sopenharmony_ci {.bitrate = 20, .hw_value = 0x01,}, 818c2ecf20Sopenharmony_ci {.bitrate = 55, .hw_value = 0x02,}, 828c2ecf20Sopenharmony_ci {.bitrate = 110, .hw_value = 0x03,}, 838c2ecf20Sopenharmony_ci {.bitrate = 60, .hw_value = 0x04,}, 848c2ecf20Sopenharmony_ci {.bitrate = 90, .hw_value = 0x05,}, 858c2ecf20Sopenharmony_ci {.bitrate = 120, .hw_value = 0x06,}, 868c2ecf20Sopenharmony_ci {.bitrate = 180, .hw_value = 0x07,}, 878c2ecf20Sopenharmony_ci {.bitrate = 240, .hw_value = 0x08,}, 888c2ecf20Sopenharmony_ci {.bitrate = 360, .hw_value = 0x09,}, 898c2ecf20Sopenharmony_ci {.bitrate = 480, .hw_value = 0x0a,}, 908c2ecf20Sopenharmony_ci {.bitrate = 540, .hw_value = 0x0b,}, 918c2ecf20Sopenharmony_ci}; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ciu16 rtw_desc_to_bitrate(u8 desc_rate) 948c2ecf20Sopenharmony_ci{ 958c2ecf20Sopenharmony_ci struct ieee80211_rate rate; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci if (WARN(desc_rate >= ARRAY_SIZE(rtw_ratetable), "invalid desc rate\n")) 988c2ecf20Sopenharmony_ci return 0; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci rate = rtw_ratetable[desc_rate]; 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci return rate.bitrate; 1038c2ecf20Sopenharmony_ci} 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_cistatic struct ieee80211_supported_band rtw_band_2ghz = { 1068c2ecf20Sopenharmony_ci .band = NL80211_BAND_2GHZ, 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci .channels = rtw_channeltable_2g, 1098c2ecf20Sopenharmony_ci .n_channels = ARRAY_SIZE(rtw_channeltable_2g), 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci .bitrates = rtw_ratetable, 1128c2ecf20Sopenharmony_ci .n_bitrates = ARRAY_SIZE(rtw_ratetable), 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci .ht_cap = {0}, 1158c2ecf20Sopenharmony_ci .vht_cap = {0}, 1168c2ecf20Sopenharmony_ci}; 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_cistatic struct ieee80211_supported_band rtw_band_5ghz = { 1198c2ecf20Sopenharmony_ci .band = NL80211_BAND_5GHZ, 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci .channels = rtw_channeltable_5g, 1228c2ecf20Sopenharmony_ci .n_channels = ARRAY_SIZE(rtw_channeltable_5g), 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci /* 5G has no CCK rates */ 1258c2ecf20Sopenharmony_ci .bitrates = rtw_ratetable + 4, 1268c2ecf20Sopenharmony_ci .n_bitrates = ARRAY_SIZE(rtw_ratetable) - 4, 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci .ht_cap = {0}, 1298c2ecf20Sopenharmony_ci .vht_cap = {0}, 1308c2ecf20Sopenharmony_ci}; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_cistruct rtw_watch_dog_iter_data { 1338c2ecf20Sopenharmony_ci struct rtw_dev *rtwdev; 1348c2ecf20Sopenharmony_ci struct rtw_vif *rtwvif; 1358c2ecf20Sopenharmony_ci}; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_cistatic void rtw_dynamic_csi_rate(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif) 1388c2ecf20Sopenharmony_ci{ 1398c2ecf20Sopenharmony_ci struct rtw_bf_info *bf_info = &rtwdev->bf_info; 1408c2ecf20Sopenharmony_ci u8 fix_rate_enable = 0; 1418c2ecf20Sopenharmony_ci u8 new_csi_rate_idx; 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci if (rtwvif->bfee.role != RTW_BFEE_SU && 1448c2ecf20Sopenharmony_ci rtwvif->bfee.role != RTW_BFEE_MU) 1458c2ecf20Sopenharmony_ci return; 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci rtw_chip_cfg_csi_rate(rtwdev, rtwdev->dm_info.min_rssi, 1488c2ecf20Sopenharmony_ci bf_info->cur_csi_rpt_rate, 1498c2ecf20Sopenharmony_ci fix_rate_enable, &new_csi_rate_idx); 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci if (new_csi_rate_idx != bf_info->cur_csi_rpt_rate) 1528c2ecf20Sopenharmony_ci bf_info->cur_csi_rpt_rate = new_csi_rate_idx; 1538c2ecf20Sopenharmony_ci} 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_cistatic void rtw_vif_watch_dog_iter(void *data, u8 *mac, 1568c2ecf20Sopenharmony_ci struct ieee80211_vif *vif) 1578c2ecf20Sopenharmony_ci{ 1588c2ecf20Sopenharmony_ci struct rtw_watch_dog_iter_data *iter_data = data; 1598c2ecf20Sopenharmony_ci struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci if (vif->type == NL80211_IFTYPE_STATION) 1628c2ecf20Sopenharmony_ci if (vif->bss_conf.assoc) 1638c2ecf20Sopenharmony_ci iter_data->rtwvif = rtwvif; 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci rtw_dynamic_csi_rate(iter_data->rtwdev, rtwvif); 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci rtwvif->stats.tx_unicast = 0; 1688c2ecf20Sopenharmony_ci rtwvif->stats.rx_unicast = 0; 1698c2ecf20Sopenharmony_ci rtwvif->stats.tx_cnt = 0; 1708c2ecf20Sopenharmony_ci rtwvif->stats.rx_cnt = 0; 1718c2ecf20Sopenharmony_ci} 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci/* process TX/RX statistics periodically for hardware, 1748c2ecf20Sopenharmony_ci * the information helps hardware to enhance performance 1758c2ecf20Sopenharmony_ci */ 1768c2ecf20Sopenharmony_cistatic void rtw_watch_dog_work(struct work_struct *work) 1778c2ecf20Sopenharmony_ci{ 1788c2ecf20Sopenharmony_ci struct rtw_dev *rtwdev = container_of(work, struct rtw_dev, 1798c2ecf20Sopenharmony_ci watch_dog_work.work); 1808c2ecf20Sopenharmony_ci struct rtw_traffic_stats *stats = &rtwdev->stats; 1818c2ecf20Sopenharmony_ci struct rtw_watch_dog_iter_data data = {}; 1828c2ecf20Sopenharmony_ci bool busy_traffic = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags); 1838c2ecf20Sopenharmony_ci bool ps_active; 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci mutex_lock(&rtwdev->mutex); 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci if (!test_bit(RTW_FLAG_RUNNING, rtwdev->flags)) 1888c2ecf20Sopenharmony_ci goto unlock; 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->watch_dog_work, 1918c2ecf20Sopenharmony_ci RTW_WATCH_DOG_DELAY_TIME); 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci if (rtwdev->stats.tx_cnt > 100 || rtwdev->stats.rx_cnt > 100) 1948c2ecf20Sopenharmony_ci set_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags); 1958c2ecf20Sopenharmony_ci else 1968c2ecf20Sopenharmony_ci clear_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags); 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci if (busy_traffic != test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags)) 1998c2ecf20Sopenharmony_ci rtw_coex_wl_status_change_notify(rtwdev); 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci if (stats->tx_cnt > RTW_LPS_THRESHOLD || 2028c2ecf20Sopenharmony_ci stats->rx_cnt > RTW_LPS_THRESHOLD) 2038c2ecf20Sopenharmony_ci ps_active = true; 2048c2ecf20Sopenharmony_ci else 2058c2ecf20Sopenharmony_ci ps_active = false; 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci ewma_tp_add(&stats->tx_ewma_tp, 2088c2ecf20Sopenharmony_ci (u32)(stats->tx_unicast >> RTW_TP_SHIFT)); 2098c2ecf20Sopenharmony_ci ewma_tp_add(&stats->rx_ewma_tp, 2108c2ecf20Sopenharmony_ci (u32)(stats->rx_unicast >> RTW_TP_SHIFT)); 2118c2ecf20Sopenharmony_ci stats->tx_throughput = ewma_tp_read(&stats->tx_ewma_tp); 2128c2ecf20Sopenharmony_ci stats->rx_throughput = ewma_tp_read(&stats->rx_ewma_tp); 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci /* reset tx/rx statictics */ 2158c2ecf20Sopenharmony_ci stats->tx_unicast = 0; 2168c2ecf20Sopenharmony_ci stats->rx_unicast = 0; 2178c2ecf20Sopenharmony_ci stats->tx_cnt = 0; 2188c2ecf20Sopenharmony_ci stats->rx_cnt = 0; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci if (test_bit(RTW_FLAG_SCANNING, rtwdev->flags)) 2218c2ecf20Sopenharmony_ci goto unlock; 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci /* make sure BB/RF is working for dynamic mech */ 2248c2ecf20Sopenharmony_ci rtw_leave_lps(rtwdev); 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci rtw_phy_dynamic_mechanism(rtwdev); 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci data.rtwdev = rtwdev; 2298c2ecf20Sopenharmony_ci /* use atomic version to avoid taking local->iflist_mtx mutex */ 2308c2ecf20Sopenharmony_ci rtw_iterate_vifs_atomic(rtwdev, rtw_vif_watch_dog_iter, &data); 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci /* fw supports only one station associated to enter lps, if there are 2338c2ecf20Sopenharmony_ci * more than two stations associated to the AP, then we can not enter 2348c2ecf20Sopenharmony_ci * lps, because fw does not handle the overlapped beacon interval 2358c2ecf20Sopenharmony_ci * 2368c2ecf20Sopenharmony_ci * mac80211 should iterate vifs and determine if driver can enter 2378c2ecf20Sopenharmony_ci * ps by passing IEEE80211_CONF_PS to us, all we need to do is to 2388c2ecf20Sopenharmony_ci * get that vif and check if device is having traffic more than the 2398c2ecf20Sopenharmony_ci * threshold. 2408c2ecf20Sopenharmony_ci */ 2418c2ecf20Sopenharmony_ci if (rtwdev->ps_enabled && data.rtwvif && !ps_active) 2428c2ecf20Sopenharmony_ci rtw_enter_lps(rtwdev, data.rtwvif->port); 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci rtwdev->watch_dog_cnt++; 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ciunlock: 2478c2ecf20Sopenharmony_ci mutex_unlock(&rtwdev->mutex); 2488c2ecf20Sopenharmony_ci} 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_cistatic void rtw_c2h_work(struct work_struct *work) 2518c2ecf20Sopenharmony_ci{ 2528c2ecf20Sopenharmony_ci struct rtw_dev *rtwdev = container_of(work, struct rtw_dev, c2h_work); 2538c2ecf20Sopenharmony_ci struct sk_buff *skb, *tmp; 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci skb_queue_walk_safe(&rtwdev->c2h_queue, skb, tmp) { 2568c2ecf20Sopenharmony_ci skb_unlink(skb, &rtwdev->c2h_queue); 2578c2ecf20Sopenharmony_ci rtw_fw_c2h_cmd_handle(rtwdev, skb); 2588c2ecf20Sopenharmony_ci dev_kfree_skb_any(skb); 2598c2ecf20Sopenharmony_ci } 2608c2ecf20Sopenharmony_ci} 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_cistatic u8 rtw_acquire_macid(struct rtw_dev *rtwdev) 2638c2ecf20Sopenharmony_ci{ 2648c2ecf20Sopenharmony_ci unsigned long mac_id; 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci mac_id = find_first_zero_bit(rtwdev->mac_id_map, RTW_MAX_MAC_ID_NUM); 2678c2ecf20Sopenharmony_ci if (mac_id < RTW_MAX_MAC_ID_NUM) 2688c2ecf20Sopenharmony_ci set_bit(mac_id, rtwdev->mac_id_map); 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci return mac_id; 2718c2ecf20Sopenharmony_ci} 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ciint rtw_sta_add(struct rtw_dev *rtwdev, struct ieee80211_sta *sta, 2748c2ecf20Sopenharmony_ci struct ieee80211_vif *vif) 2758c2ecf20Sopenharmony_ci{ 2768c2ecf20Sopenharmony_ci struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv; 2778c2ecf20Sopenharmony_ci int i; 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci si->mac_id = rtw_acquire_macid(rtwdev); 2808c2ecf20Sopenharmony_ci if (si->mac_id >= RTW_MAX_MAC_ID_NUM) 2818c2ecf20Sopenharmony_ci return -ENOSPC; 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci si->sta = sta; 2848c2ecf20Sopenharmony_ci si->vif = vif; 2858c2ecf20Sopenharmony_ci si->init_ra_lv = 1; 2868c2ecf20Sopenharmony_ci ewma_rssi_init(&si->avg_rssi); 2878c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(sta->txq); i++) 2888c2ecf20Sopenharmony_ci rtw_txq_init(rtwdev, sta->txq[i]); 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci rtw_update_sta_info(rtwdev, si); 2918c2ecf20Sopenharmony_ci rtw_fw_media_status_report(rtwdev, si->mac_id, true); 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci rtwdev->sta_cnt++; 2948c2ecf20Sopenharmony_ci rtw_info(rtwdev, "sta %pM joined with macid %d\n", 2958c2ecf20Sopenharmony_ci sta->addr, si->mac_id); 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci return 0; 2988c2ecf20Sopenharmony_ci} 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_civoid rtw_sta_remove(struct rtw_dev *rtwdev, struct ieee80211_sta *sta, 3018c2ecf20Sopenharmony_ci bool fw_exist) 3028c2ecf20Sopenharmony_ci{ 3038c2ecf20Sopenharmony_ci struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv; 3048c2ecf20Sopenharmony_ci int i; 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci rtw_release_macid(rtwdev, si->mac_id); 3078c2ecf20Sopenharmony_ci if (fw_exist) 3088c2ecf20Sopenharmony_ci rtw_fw_media_status_report(rtwdev, si->mac_id, false); 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(sta->txq); i++) 3118c2ecf20Sopenharmony_ci rtw_txq_cleanup(rtwdev, sta->txq[i]); 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci kfree(si->mask); 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci rtwdev->sta_cnt--; 3168c2ecf20Sopenharmony_ci rtw_info(rtwdev, "sta %pM with macid %d left\n", 3178c2ecf20Sopenharmony_ci sta->addr, si->mac_id); 3188c2ecf20Sopenharmony_ci} 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_cistatic bool rtw_fw_dump_crash_log(struct rtw_dev *rtwdev) 3218c2ecf20Sopenharmony_ci{ 3228c2ecf20Sopenharmony_ci u32 size = rtwdev->chip->fw_rxff_size; 3238c2ecf20Sopenharmony_ci u32 *buf; 3248c2ecf20Sopenharmony_ci u8 seq; 3258c2ecf20Sopenharmony_ci bool ret = true; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci buf = vmalloc(size); 3288c2ecf20Sopenharmony_ci if (!buf) 3298c2ecf20Sopenharmony_ci goto exit; 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci if (rtw_fw_dump_fifo(rtwdev, RTW_FW_FIFO_SEL_RXBUF_FW, 0, size, buf)) { 3328c2ecf20Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_FW, "dump fw fifo fail\n"); 3338c2ecf20Sopenharmony_ci goto free_buf; 3348c2ecf20Sopenharmony_ci } 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci if (GET_FW_DUMP_LEN(buf) == 0) { 3378c2ecf20Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_FW, "fw crash dump's length is 0\n"); 3388c2ecf20Sopenharmony_ci goto free_buf; 3398c2ecf20Sopenharmony_ci } 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci seq = GET_FW_DUMP_SEQ(buf); 3428c2ecf20Sopenharmony_ci if (seq > 0 && seq != (rtwdev->fw.prev_dump_seq + 1)) { 3438c2ecf20Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_FW, 3448c2ecf20Sopenharmony_ci "fw crash dump's seq is wrong: %d\n", seq); 3458c2ecf20Sopenharmony_ci goto free_buf; 3468c2ecf20Sopenharmony_ci } 3478c2ecf20Sopenharmony_ci if (seq == 0 && 3488c2ecf20Sopenharmony_ci (GET_FW_DUMP_TLV_TYPE(buf) != FW_CD_TYPE || 3498c2ecf20Sopenharmony_ci GET_FW_DUMP_TLV_LEN(buf) != FW_CD_LEN || 3508c2ecf20Sopenharmony_ci GET_FW_DUMP_TLV_VAL(buf) != FW_CD_VAL)) { 3518c2ecf20Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_FW, "fw crash dump's tlv is wrong\n"); 3528c2ecf20Sopenharmony_ci goto free_buf; 3538c2ecf20Sopenharmony_ci } 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci print_hex_dump_bytes("rtw88 fw dump: ", DUMP_PREFIX_OFFSET, buf, size); 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci if (GET_FW_DUMP_MORE(buf) == 1) { 3588c2ecf20Sopenharmony_ci rtwdev->fw.prev_dump_seq = seq; 3598c2ecf20Sopenharmony_ci ret = false; 3608c2ecf20Sopenharmony_ci } 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_cifree_buf: 3638c2ecf20Sopenharmony_ci vfree(buf); 3648c2ecf20Sopenharmony_ciexit: 3658c2ecf20Sopenharmony_ci rtw_write8(rtwdev, REG_MCU_TST_CFG, 0); 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ci return ret; 3688c2ecf20Sopenharmony_ci} 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_civoid rtw_vif_assoc_changed(struct rtw_vif *rtwvif, 3718c2ecf20Sopenharmony_ci struct ieee80211_bss_conf *conf) 3728c2ecf20Sopenharmony_ci{ 3738c2ecf20Sopenharmony_ci if (conf && conf->assoc) { 3748c2ecf20Sopenharmony_ci rtwvif->aid = conf->aid; 3758c2ecf20Sopenharmony_ci rtwvif->net_type = RTW_NET_MGD_LINKED; 3768c2ecf20Sopenharmony_ci } else { 3778c2ecf20Sopenharmony_ci rtwvif->aid = 0; 3788c2ecf20Sopenharmony_ci rtwvif->net_type = RTW_NET_NO_LINK; 3798c2ecf20Sopenharmony_ci } 3808c2ecf20Sopenharmony_ci} 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_cistatic void rtw_reset_key_iter(struct ieee80211_hw *hw, 3838c2ecf20Sopenharmony_ci struct ieee80211_vif *vif, 3848c2ecf20Sopenharmony_ci struct ieee80211_sta *sta, 3858c2ecf20Sopenharmony_ci struct ieee80211_key_conf *key, 3868c2ecf20Sopenharmony_ci void *data) 3878c2ecf20Sopenharmony_ci{ 3888c2ecf20Sopenharmony_ci struct rtw_dev *rtwdev = (struct rtw_dev *)data; 3898c2ecf20Sopenharmony_ci struct rtw_sec_desc *sec = &rtwdev->sec; 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci rtw_sec_clear_cam(rtwdev, sec, key->hw_key_idx); 3928c2ecf20Sopenharmony_ci} 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_cistatic void rtw_reset_sta_iter(void *data, struct ieee80211_sta *sta) 3958c2ecf20Sopenharmony_ci{ 3968c2ecf20Sopenharmony_ci struct rtw_dev *rtwdev = (struct rtw_dev *)data; 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci if (rtwdev->sta_cnt == 0) { 3998c2ecf20Sopenharmony_ci rtw_warn(rtwdev, "sta count before reset should not be 0\n"); 4008c2ecf20Sopenharmony_ci return; 4018c2ecf20Sopenharmony_ci } 4028c2ecf20Sopenharmony_ci rtw_sta_remove(rtwdev, sta, false); 4038c2ecf20Sopenharmony_ci} 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_cistatic void rtw_reset_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) 4068c2ecf20Sopenharmony_ci{ 4078c2ecf20Sopenharmony_ci struct rtw_dev *rtwdev = (struct rtw_dev *)data; 4088c2ecf20Sopenharmony_ci struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci rtw_bf_disassoc(rtwdev, vif, NULL); 4118c2ecf20Sopenharmony_ci rtw_vif_assoc_changed(rtwvif, NULL); 4128c2ecf20Sopenharmony_ci rtw_txq_cleanup(rtwdev, vif->txq); 4138c2ecf20Sopenharmony_ci} 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_civoid rtw_fw_recovery(struct rtw_dev *rtwdev) 4168c2ecf20Sopenharmony_ci{ 4178c2ecf20Sopenharmony_ci if (!test_bit(RTW_FLAG_RESTARTING, rtwdev->flags)) 4188c2ecf20Sopenharmony_ci ieee80211_queue_work(rtwdev->hw, &rtwdev->fw_recovery_work); 4198c2ecf20Sopenharmony_ci} 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_cistatic void rtw_fw_recovery_work(struct work_struct *work) 4228c2ecf20Sopenharmony_ci{ 4238c2ecf20Sopenharmony_ci struct rtw_dev *rtwdev = container_of(work, struct rtw_dev, 4248c2ecf20Sopenharmony_ci fw_recovery_work); 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci /* rtw_fw_dump_crash_log() returns false indicates that there are 4278c2ecf20Sopenharmony_ci * still more log to dump. Driver set 0x1cf[7:0] = 0x1 to tell firmware 4288c2ecf20Sopenharmony_ci * to dump the remaining part of the log, and firmware will trigger an 4298c2ecf20Sopenharmony_ci * IMR_C2HCMD interrupt to inform driver the log is ready. 4308c2ecf20Sopenharmony_ci */ 4318c2ecf20Sopenharmony_ci if (!rtw_fw_dump_crash_log(rtwdev)) { 4328c2ecf20Sopenharmony_ci rtw_write8(rtwdev, REG_HRCV_MSG, 1); 4338c2ecf20Sopenharmony_ci return; 4348c2ecf20Sopenharmony_ci } 4358c2ecf20Sopenharmony_ci rtwdev->fw.prev_dump_seq = 0; 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci WARN(1, "firmware crash, start reset and recover\n"); 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci mutex_lock(&rtwdev->mutex); 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_ci set_bit(RTW_FLAG_RESTARTING, rtwdev->flags); 4428c2ecf20Sopenharmony_ci rcu_read_lock(); 4438c2ecf20Sopenharmony_ci rtw_iterate_keys_rcu(rtwdev, NULL, rtw_reset_key_iter, rtwdev); 4448c2ecf20Sopenharmony_ci rcu_read_unlock(); 4458c2ecf20Sopenharmony_ci rtw_iterate_stas_atomic(rtwdev, rtw_reset_sta_iter, rtwdev); 4468c2ecf20Sopenharmony_ci rtw_iterate_vifs_atomic(rtwdev, rtw_reset_vif_iter, rtwdev); 4478c2ecf20Sopenharmony_ci rtw_enter_ips(rtwdev); 4488c2ecf20Sopenharmony_ci 4498c2ecf20Sopenharmony_ci mutex_unlock(&rtwdev->mutex); 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_ci ieee80211_restart_hw(rtwdev->hw); 4528c2ecf20Sopenharmony_ci} 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_cistruct rtw_txq_ba_iter_data { 4558c2ecf20Sopenharmony_ci}; 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_cistatic void rtw_txq_ba_iter(void *data, struct ieee80211_sta *sta) 4588c2ecf20Sopenharmony_ci{ 4598c2ecf20Sopenharmony_ci struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv; 4608c2ecf20Sopenharmony_ci int ret; 4618c2ecf20Sopenharmony_ci u8 tid; 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_ci tid = find_first_bit(si->tid_ba, IEEE80211_NUM_TIDS); 4648c2ecf20Sopenharmony_ci while (tid != IEEE80211_NUM_TIDS) { 4658c2ecf20Sopenharmony_ci clear_bit(tid, si->tid_ba); 4668c2ecf20Sopenharmony_ci ret = ieee80211_start_tx_ba_session(sta, tid, 0); 4678c2ecf20Sopenharmony_ci if (ret == -EINVAL) { 4688c2ecf20Sopenharmony_ci struct ieee80211_txq *txq; 4698c2ecf20Sopenharmony_ci struct rtw_txq *rtwtxq; 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci txq = sta->txq[tid]; 4728c2ecf20Sopenharmony_ci rtwtxq = (struct rtw_txq *)txq->drv_priv; 4738c2ecf20Sopenharmony_ci set_bit(RTW_TXQ_BLOCK_BA, &rtwtxq->flags); 4748c2ecf20Sopenharmony_ci } 4758c2ecf20Sopenharmony_ci 4768c2ecf20Sopenharmony_ci tid = find_first_bit(si->tid_ba, IEEE80211_NUM_TIDS); 4778c2ecf20Sopenharmony_ci } 4788c2ecf20Sopenharmony_ci} 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_cistatic void rtw_txq_ba_work(struct work_struct *work) 4818c2ecf20Sopenharmony_ci{ 4828c2ecf20Sopenharmony_ci struct rtw_dev *rtwdev = container_of(work, struct rtw_dev, ba_work); 4838c2ecf20Sopenharmony_ci struct rtw_txq_ba_iter_data data; 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci rtw_iterate_stas_atomic(rtwdev, rtw_txq_ba_iter, &data); 4868c2ecf20Sopenharmony_ci} 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_civoid rtw_get_channel_params(struct cfg80211_chan_def *chandef, 4898c2ecf20Sopenharmony_ci struct rtw_channel_params *chan_params) 4908c2ecf20Sopenharmony_ci{ 4918c2ecf20Sopenharmony_ci struct ieee80211_channel *channel = chandef->chan; 4928c2ecf20Sopenharmony_ci enum nl80211_chan_width width = chandef->width; 4938c2ecf20Sopenharmony_ci u8 *cch_by_bw = chan_params->cch_by_bw; 4948c2ecf20Sopenharmony_ci u32 primary_freq, center_freq; 4958c2ecf20Sopenharmony_ci u8 center_chan; 4968c2ecf20Sopenharmony_ci u8 bandwidth = RTW_CHANNEL_WIDTH_20; 4978c2ecf20Sopenharmony_ci u8 primary_chan_idx = 0; 4988c2ecf20Sopenharmony_ci u8 i; 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_ci center_chan = channel->hw_value; 5018c2ecf20Sopenharmony_ci primary_freq = channel->center_freq; 5028c2ecf20Sopenharmony_ci center_freq = chandef->center_freq1; 5038c2ecf20Sopenharmony_ci 5048c2ecf20Sopenharmony_ci /* assign the center channel used while 20M bw is selected */ 5058c2ecf20Sopenharmony_ci cch_by_bw[RTW_CHANNEL_WIDTH_20] = channel->hw_value; 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci switch (width) { 5088c2ecf20Sopenharmony_ci case NL80211_CHAN_WIDTH_20_NOHT: 5098c2ecf20Sopenharmony_ci case NL80211_CHAN_WIDTH_20: 5108c2ecf20Sopenharmony_ci bandwidth = RTW_CHANNEL_WIDTH_20; 5118c2ecf20Sopenharmony_ci primary_chan_idx = RTW_SC_DONT_CARE; 5128c2ecf20Sopenharmony_ci break; 5138c2ecf20Sopenharmony_ci case NL80211_CHAN_WIDTH_40: 5148c2ecf20Sopenharmony_ci bandwidth = RTW_CHANNEL_WIDTH_40; 5158c2ecf20Sopenharmony_ci if (primary_freq > center_freq) { 5168c2ecf20Sopenharmony_ci primary_chan_idx = RTW_SC_20_UPPER; 5178c2ecf20Sopenharmony_ci center_chan -= 2; 5188c2ecf20Sopenharmony_ci } else { 5198c2ecf20Sopenharmony_ci primary_chan_idx = RTW_SC_20_LOWER; 5208c2ecf20Sopenharmony_ci center_chan += 2; 5218c2ecf20Sopenharmony_ci } 5228c2ecf20Sopenharmony_ci break; 5238c2ecf20Sopenharmony_ci case NL80211_CHAN_WIDTH_80: 5248c2ecf20Sopenharmony_ci bandwidth = RTW_CHANNEL_WIDTH_80; 5258c2ecf20Sopenharmony_ci if (primary_freq > center_freq) { 5268c2ecf20Sopenharmony_ci if (primary_freq - center_freq == 10) { 5278c2ecf20Sopenharmony_ci primary_chan_idx = RTW_SC_20_UPPER; 5288c2ecf20Sopenharmony_ci center_chan -= 2; 5298c2ecf20Sopenharmony_ci } else { 5308c2ecf20Sopenharmony_ci primary_chan_idx = RTW_SC_20_UPMOST; 5318c2ecf20Sopenharmony_ci center_chan -= 6; 5328c2ecf20Sopenharmony_ci } 5338c2ecf20Sopenharmony_ci /* assign the center channel used 5348c2ecf20Sopenharmony_ci * while 40M bw is selected 5358c2ecf20Sopenharmony_ci */ 5368c2ecf20Sopenharmony_ci cch_by_bw[RTW_CHANNEL_WIDTH_40] = center_chan + 4; 5378c2ecf20Sopenharmony_ci } else { 5388c2ecf20Sopenharmony_ci if (center_freq - primary_freq == 10) { 5398c2ecf20Sopenharmony_ci primary_chan_idx = RTW_SC_20_LOWER; 5408c2ecf20Sopenharmony_ci center_chan += 2; 5418c2ecf20Sopenharmony_ci } else { 5428c2ecf20Sopenharmony_ci primary_chan_idx = RTW_SC_20_LOWEST; 5438c2ecf20Sopenharmony_ci center_chan += 6; 5448c2ecf20Sopenharmony_ci } 5458c2ecf20Sopenharmony_ci /* assign the center channel used 5468c2ecf20Sopenharmony_ci * while 40M bw is selected 5478c2ecf20Sopenharmony_ci */ 5488c2ecf20Sopenharmony_ci cch_by_bw[RTW_CHANNEL_WIDTH_40] = center_chan - 4; 5498c2ecf20Sopenharmony_ci } 5508c2ecf20Sopenharmony_ci break; 5518c2ecf20Sopenharmony_ci default: 5528c2ecf20Sopenharmony_ci center_chan = 0; 5538c2ecf20Sopenharmony_ci break; 5548c2ecf20Sopenharmony_ci } 5558c2ecf20Sopenharmony_ci 5568c2ecf20Sopenharmony_ci chan_params->center_chan = center_chan; 5578c2ecf20Sopenharmony_ci chan_params->bandwidth = bandwidth; 5588c2ecf20Sopenharmony_ci chan_params->primary_chan_idx = primary_chan_idx; 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_ci /* assign the center channel used while current bw is selected */ 5618c2ecf20Sopenharmony_ci cch_by_bw[bandwidth] = center_chan; 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_ci for (i = bandwidth + 1; i <= RTW_MAX_CHANNEL_WIDTH; i++) 5648c2ecf20Sopenharmony_ci cch_by_bw[i] = 0; 5658c2ecf20Sopenharmony_ci} 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_civoid rtw_set_channel(struct rtw_dev *rtwdev) 5688c2ecf20Sopenharmony_ci{ 5698c2ecf20Sopenharmony_ci struct ieee80211_hw *hw = rtwdev->hw; 5708c2ecf20Sopenharmony_ci struct rtw_hal *hal = &rtwdev->hal; 5718c2ecf20Sopenharmony_ci struct rtw_chip_info *chip = rtwdev->chip; 5728c2ecf20Sopenharmony_ci struct rtw_channel_params ch_param; 5738c2ecf20Sopenharmony_ci u8 center_chan, bandwidth, primary_chan_idx; 5748c2ecf20Sopenharmony_ci u8 i; 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci rtw_get_channel_params(&hw->conf.chandef, &ch_param); 5778c2ecf20Sopenharmony_ci if (WARN(ch_param.center_chan == 0, "Invalid channel\n")) 5788c2ecf20Sopenharmony_ci return; 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_ci center_chan = ch_param.center_chan; 5818c2ecf20Sopenharmony_ci bandwidth = ch_param.bandwidth; 5828c2ecf20Sopenharmony_ci primary_chan_idx = ch_param.primary_chan_idx; 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_ci hal->current_band_width = bandwidth; 5858c2ecf20Sopenharmony_ci hal->current_channel = center_chan; 5868c2ecf20Sopenharmony_ci hal->current_band_type = center_chan > 14 ? RTW_BAND_5G : RTW_BAND_2G; 5878c2ecf20Sopenharmony_ci 5888c2ecf20Sopenharmony_ci for (i = RTW_CHANNEL_WIDTH_20; i <= RTW_MAX_CHANNEL_WIDTH; i++) 5898c2ecf20Sopenharmony_ci hal->cch_by_bw[i] = ch_param.cch_by_bw[i]; 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_ci chip->ops->set_channel(rtwdev, center_chan, bandwidth, primary_chan_idx); 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_ci if (hal->current_band_type == RTW_BAND_5G) { 5948c2ecf20Sopenharmony_ci rtw_coex_switchband_notify(rtwdev, COEX_SWITCH_TO_5G); 5958c2ecf20Sopenharmony_ci } else { 5968c2ecf20Sopenharmony_ci if (test_bit(RTW_FLAG_SCANNING, rtwdev->flags)) 5978c2ecf20Sopenharmony_ci rtw_coex_switchband_notify(rtwdev, COEX_SWITCH_TO_24G); 5988c2ecf20Sopenharmony_ci else 5998c2ecf20Sopenharmony_ci rtw_coex_switchband_notify(rtwdev, COEX_SWITCH_TO_24G_NOFORSCAN); 6008c2ecf20Sopenharmony_ci } 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_ci rtw_phy_set_tx_power_level(rtwdev, center_chan); 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_ci /* if the channel isn't set for scanning, we will do RF calibration 6058c2ecf20Sopenharmony_ci * in ieee80211_ops::mgd_prepare_tx(). Performing the calibration 6068c2ecf20Sopenharmony_ci * during scanning on each channel takes too long. 6078c2ecf20Sopenharmony_ci */ 6088c2ecf20Sopenharmony_ci if (!test_bit(RTW_FLAG_SCANNING, rtwdev->flags)) 6098c2ecf20Sopenharmony_ci rtwdev->need_rfk = true; 6108c2ecf20Sopenharmony_ci} 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_civoid rtw_chip_prepare_tx(struct rtw_dev *rtwdev) 6138c2ecf20Sopenharmony_ci{ 6148c2ecf20Sopenharmony_ci struct rtw_chip_info *chip = rtwdev->chip; 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci if (rtwdev->need_rfk) { 6178c2ecf20Sopenharmony_ci rtwdev->need_rfk = false; 6188c2ecf20Sopenharmony_ci chip->ops->phy_calibration(rtwdev); 6198c2ecf20Sopenharmony_ci } 6208c2ecf20Sopenharmony_ci} 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_cistatic void rtw_vif_write_addr(struct rtw_dev *rtwdev, u32 start, u8 *addr) 6238c2ecf20Sopenharmony_ci{ 6248c2ecf20Sopenharmony_ci int i; 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ci for (i = 0; i < ETH_ALEN; i++) 6278c2ecf20Sopenharmony_ci rtw_write8(rtwdev, start + i, addr[i]); 6288c2ecf20Sopenharmony_ci} 6298c2ecf20Sopenharmony_ci 6308c2ecf20Sopenharmony_civoid rtw_vif_port_config(struct rtw_dev *rtwdev, 6318c2ecf20Sopenharmony_ci struct rtw_vif *rtwvif, 6328c2ecf20Sopenharmony_ci u32 config) 6338c2ecf20Sopenharmony_ci{ 6348c2ecf20Sopenharmony_ci u32 addr, mask; 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_ci if (config & PORT_SET_MAC_ADDR) { 6378c2ecf20Sopenharmony_ci addr = rtwvif->conf->mac_addr.addr; 6388c2ecf20Sopenharmony_ci rtw_vif_write_addr(rtwdev, addr, rtwvif->mac_addr); 6398c2ecf20Sopenharmony_ci } 6408c2ecf20Sopenharmony_ci if (config & PORT_SET_BSSID) { 6418c2ecf20Sopenharmony_ci addr = rtwvif->conf->bssid.addr; 6428c2ecf20Sopenharmony_ci rtw_vif_write_addr(rtwdev, addr, rtwvif->bssid); 6438c2ecf20Sopenharmony_ci } 6448c2ecf20Sopenharmony_ci if (config & PORT_SET_NET_TYPE) { 6458c2ecf20Sopenharmony_ci addr = rtwvif->conf->net_type.addr; 6468c2ecf20Sopenharmony_ci mask = rtwvif->conf->net_type.mask; 6478c2ecf20Sopenharmony_ci rtw_write32_mask(rtwdev, addr, mask, rtwvif->net_type); 6488c2ecf20Sopenharmony_ci } 6498c2ecf20Sopenharmony_ci if (config & PORT_SET_AID) { 6508c2ecf20Sopenharmony_ci addr = rtwvif->conf->aid.addr; 6518c2ecf20Sopenharmony_ci mask = rtwvif->conf->aid.mask; 6528c2ecf20Sopenharmony_ci rtw_write32_mask(rtwdev, addr, mask, rtwvif->aid); 6538c2ecf20Sopenharmony_ci } 6548c2ecf20Sopenharmony_ci if (config & PORT_SET_BCN_CTRL) { 6558c2ecf20Sopenharmony_ci addr = rtwvif->conf->bcn_ctrl.addr; 6568c2ecf20Sopenharmony_ci mask = rtwvif->conf->bcn_ctrl.mask; 6578c2ecf20Sopenharmony_ci rtw_write8_mask(rtwdev, addr, mask, rtwvif->bcn_ctrl); 6588c2ecf20Sopenharmony_ci } 6598c2ecf20Sopenharmony_ci} 6608c2ecf20Sopenharmony_ci 6618c2ecf20Sopenharmony_cistatic u8 hw_bw_cap_to_bitamp(u8 bw_cap) 6628c2ecf20Sopenharmony_ci{ 6638c2ecf20Sopenharmony_ci u8 bw = 0; 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_ci switch (bw_cap) { 6668c2ecf20Sopenharmony_ci case EFUSE_HW_CAP_IGNORE: 6678c2ecf20Sopenharmony_ci case EFUSE_HW_CAP_SUPP_BW80: 6688c2ecf20Sopenharmony_ci bw |= BIT(RTW_CHANNEL_WIDTH_80); 6698c2ecf20Sopenharmony_ci fallthrough; 6708c2ecf20Sopenharmony_ci case EFUSE_HW_CAP_SUPP_BW40: 6718c2ecf20Sopenharmony_ci bw |= BIT(RTW_CHANNEL_WIDTH_40); 6728c2ecf20Sopenharmony_ci fallthrough; 6738c2ecf20Sopenharmony_ci default: 6748c2ecf20Sopenharmony_ci bw |= BIT(RTW_CHANNEL_WIDTH_20); 6758c2ecf20Sopenharmony_ci break; 6768c2ecf20Sopenharmony_ci } 6778c2ecf20Sopenharmony_ci 6788c2ecf20Sopenharmony_ci return bw; 6798c2ecf20Sopenharmony_ci} 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_cistatic void rtw_hw_config_rf_ant_num(struct rtw_dev *rtwdev, u8 hw_ant_num) 6828c2ecf20Sopenharmony_ci{ 6838c2ecf20Sopenharmony_ci struct rtw_hal *hal = &rtwdev->hal; 6848c2ecf20Sopenharmony_ci struct rtw_chip_info *chip = rtwdev->chip; 6858c2ecf20Sopenharmony_ci 6868c2ecf20Sopenharmony_ci if (hw_ant_num == EFUSE_HW_CAP_IGNORE || 6878c2ecf20Sopenharmony_ci hw_ant_num >= hal->rf_path_num) 6888c2ecf20Sopenharmony_ci return; 6898c2ecf20Sopenharmony_ci 6908c2ecf20Sopenharmony_ci switch (hw_ant_num) { 6918c2ecf20Sopenharmony_ci case 1: 6928c2ecf20Sopenharmony_ci hal->rf_type = RF_1T1R; 6938c2ecf20Sopenharmony_ci hal->rf_path_num = 1; 6948c2ecf20Sopenharmony_ci if (!chip->fix_rf_phy_num) 6958c2ecf20Sopenharmony_ci hal->rf_phy_num = hal->rf_path_num; 6968c2ecf20Sopenharmony_ci hal->antenna_tx = BB_PATH_A; 6978c2ecf20Sopenharmony_ci hal->antenna_rx = BB_PATH_A; 6988c2ecf20Sopenharmony_ci break; 6998c2ecf20Sopenharmony_ci default: 7008c2ecf20Sopenharmony_ci WARN(1, "invalid hw configuration from efuse\n"); 7018c2ecf20Sopenharmony_ci break; 7028c2ecf20Sopenharmony_ci } 7038c2ecf20Sopenharmony_ci} 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_cistatic u64 get_vht_ra_mask(struct ieee80211_sta *sta) 7068c2ecf20Sopenharmony_ci{ 7078c2ecf20Sopenharmony_ci u64 ra_mask = 0; 7088c2ecf20Sopenharmony_ci u16 mcs_map = le16_to_cpu(sta->vht_cap.vht_mcs.rx_mcs_map); 7098c2ecf20Sopenharmony_ci u8 vht_mcs_cap; 7108c2ecf20Sopenharmony_ci int i, nss; 7118c2ecf20Sopenharmony_ci 7128c2ecf20Sopenharmony_ci /* 4SS, every two bits for MCS7/8/9 */ 7138c2ecf20Sopenharmony_ci for (i = 0, nss = 12; i < 4; i++, mcs_map >>= 2, nss += 10) { 7148c2ecf20Sopenharmony_ci vht_mcs_cap = mcs_map & 0x3; 7158c2ecf20Sopenharmony_ci switch (vht_mcs_cap) { 7168c2ecf20Sopenharmony_ci case 2: /* MCS9 */ 7178c2ecf20Sopenharmony_ci ra_mask |= 0x3ffULL << nss; 7188c2ecf20Sopenharmony_ci break; 7198c2ecf20Sopenharmony_ci case 1: /* MCS8 */ 7208c2ecf20Sopenharmony_ci ra_mask |= 0x1ffULL << nss; 7218c2ecf20Sopenharmony_ci break; 7228c2ecf20Sopenharmony_ci case 0: /* MCS7 */ 7238c2ecf20Sopenharmony_ci ra_mask |= 0x0ffULL << nss; 7248c2ecf20Sopenharmony_ci break; 7258c2ecf20Sopenharmony_ci default: 7268c2ecf20Sopenharmony_ci break; 7278c2ecf20Sopenharmony_ci } 7288c2ecf20Sopenharmony_ci } 7298c2ecf20Sopenharmony_ci 7308c2ecf20Sopenharmony_ci return ra_mask; 7318c2ecf20Sopenharmony_ci} 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_cistatic u8 get_rate_id(u8 wireless_set, enum rtw_bandwidth bw_mode, u8 tx_num) 7348c2ecf20Sopenharmony_ci{ 7358c2ecf20Sopenharmony_ci u8 rate_id = 0; 7368c2ecf20Sopenharmony_ci 7378c2ecf20Sopenharmony_ci switch (wireless_set) { 7388c2ecf20Sopenharmony_ci case WIRELESS_CCK: 7398c2ecf20Sopenharmony_ci rate_id = RTW_RATEID_B_20M; 7408c2ecf20Sopenharmony_ci break; 7418c2ecf20Sopenharmony_ci case WIRELESS_OFDM: 7428c2ecf20Sopenharmony_ci rate_id = RTW_RATEID_G; 7438c2ecf20Sopenharmony_ci break; 7448c2ecf20Sopenharmony_ci case WIRELESS_CCK | WIRELESS_OFDM: 7458c2ecf20Sopenharmony_ci rate_id = RTW_RATEID_BG; 7468c2ecf20Sopenharmony_ci break; 7478c2ecf20Sopenharmony_ci case WIRELESS_OFDM | WIRELESS_HT: 7488c2ecf20Sopenharmony_ci if (tx_num == 1) 7498c2ecf20Sopenharmony_ci rate_id = RTW_RATEID_GN_N1SS; 7508c2ecf20Sopenharmony_ci else if (tx_num == 2) 7518c2ecf20Sopenharmony_ci rate_id = RTW_RATEID_GN_N2SS; 7528c2ecf20Sopenharmony_ci else if (tx_num == 3) 7538c2ecf20Sopenharmony_ci rate_id = RTW_RATEID_ARFR5_N_3SS; 7548c2ecf20Sopenharmony_ci break; 7558c2ecf20Sopenharmony_ci case WIRELESS_CCK | WIRELESS_OFDM | WIRELESS_HT: 7568c2ecf20Sopenharmony_ci if (bw_mode == RTW_CHANNEL_WIDTH_40) { 7578c2ecf20Sopenharmony_ci if (tx_num == 1) 7588c2ecf20Sopenharmony_ci rate_id = RTW_RATEID_BGN_40M_1SS; 7598c2ecf20Sopenharmony_ci else if (tx_num == 2) 7608c2ecf20Sopenharmony_ci rate_id = RTW_RATEID_BGN_40M_2SS; 7618c2ecf20Sopenharmony_ci else if (tx_num == 3) 7628c2ecf20Sopenharmony_ci rate_id = RTW_RATEID_ARFR5_N_3SS; 7638c2ecf20Sopenharmony_ci else if (tx_num == 4) 7648c2ecf20Sopenharmony_ci rate_id = RTW_RATEID_ARFR7_N_4SS; 7658c2ecf20Sopenharmony_ci } else { 7668c2ecf20Sopenharmony_ci if (tx_num == 1) 7678c2ecf20Sopenharmony_ci rate_id = RTW_RATEID_BGN_20M_1SS; 7688c2ecf20Sopenharmony_ci else if (tx_num == 2) 7698c2ecf20Sopenharmony_ci rate_id = RTW_RATEID_BGN_20M_2SS; 7708c2ecf20Sopenharmony_ci else if (tx_num == 3) 7718c2ecf20Sopenharmony_ci rate_id = RTW_RATEID_ARFR5_N_3SS; 7728c2ecf20Sopenharmony_ci else if (tx_num == 4) 7738c2ecf20Sopenharmony_ci rate_id = RTW_RATEID_ARFR7_N_4SS; 7748c2ecf20Sopenharmony_ci } 7758c2ecf20Sopenharmony_ci break; 7768c2ecf20Sopenharmony_ci case WIRELESS_OFDM | WIRELESS_VHT: 7778c2ecf20Sopenharmony_ci if (tx_num == 1) 7788c2ecf20Sopenharmony_ci rate_id = RTW_RATEID_ARFR1_AC_1SS; 7798c2ecf20Sopenharmony_ci else if (tx_num == 2) 7808c2ecf20Sopenharmony_ci rate_id = RTW_RATEID_ARFR0_AC_2SS; 7818c2ecf20Sopenharmony_ci else if (tx_num == 3) 7828c2ecf20Sopenharmony_ci rate_id = RTW_RATEID_ARFR4_AC_3SS; 7838c2ecf20Sopenharmony_ci else if (tx_num == 4) 7848c2ecf20Sopenharmony_ci rate_id = RTW_RATEID_ARFR6_AC_4SS; 7858c2ecf20Sopenharmony_ci break; 7868c2ecf20Sopenharmony_ci case WIRELESS_CCK | WIRELESS_OFDM | WIRELESS_VHT: 7878c2ecf20Sopenharmony_ci if (bw_mode >= RTW_CHANNEL_WIDTH_80) { 7888c2ecf20Sopenharmony_ci if (tx_num == 1) 7898c2ecf20Sopenharmony_ci rate_id = RTW_RATEID_ARFR1_AC_1SS; 7908c2ecf20Sopenharmony_ci else if (tx_num == 2) 7918c2ecf20Sopenharmony_ci rate_id = RTW_RATEID_ARFR0_AC_2SS; 7928c2ecf20Sopenharmony_ci else if (tx_num == 3) 7938c2ecf20Sopenharmony_ci rate_id = RTW_RATEID_ARFR4_AC_3SS; 7948c2ecf20Sopenharmony_ci else if (tx_num == 4) 7958c2ecf20Sopenharmony_ci rate_id = RTW_RATEID_ARFR6_AC_4SS; 7968c2ecf20Sopenharmony_ci } else { 7978c2ecf20Sopenharmony_ci if (tx_num == 1) 7988c2ecf20Sopenharmony_ci rate_id = RTW_RATEID_ARFR2_AC_2G_1SS; 7998c2ecf20Sopenharmony_ci else if (tx_num == 2) 8008c2ecf20Sopenharmony_ci rate_id = RTW_RATEID_ARFR3_AC_2G_2SS; 8018c2ecf20Sopenharmony_ci else if (tx_num == 3) 8028c2ecf20Sopenharmony_ci rate_id = RTW_RATEID_ARFR4_AC_3SS; 8038c2ecf20Sopenharmony_ci else if (tx_num == 4) 8048c2ecf20Sopenharmony_ci rate_id = RTW_RATEID_ARFR6_AC_4SS; 8058c2ecf20Sopenharmony_ci } 8068c2ecf20Sopenharmony_ci break; 8078c2ecf20Sopenharmony_ci default: 8088c2ecf20Sopenharmony_ci break; 8098c2ecf20Sopenharmony_ci } 8108c2ecf20Sopenharmony_ci 8118c2ecf20Sopenharmony_ci return rate_id; 8128c2ecf20Sopenharmony_ci} 8138c2ecf20Sopenharmony_ci 8148c2ecf20Sopenharmony_ci#define RA_MASK_CCK_RATES 0x0000f 8158c2ecf20Sopenharmony_ci#define RA_MASK_OFDM_RATES 0x00ff0 8168c2ecf20Sopenharmony_ci#define RA_MASK_HT_RATES_1SS (0xff000ULL << 0) 8178c2ecf20Sopenharmony_ci#define RA_MASK_HT_RATES_2SS (0xff000ULL << 8) 8188c2ecf20Sopenharmony_ci#define RA_MASK_HT_RATES_3SS (0xff000ULL << 16) 8198c2ecf20Sopenharmony_ci#define RA_MASK_HT_RATES (RA_MASK_HT_RATES_1SS | \ 8208c2ecf20Sopenharmony_ci RA_MASK_HT_RATES_2SS | \ 8218c2ecf20Sopenharmony_ci RA_MASK_HT_RATES_3SS) 8228c2ecf20Sopenharmony_ci#define RA_MASK_VHT_RATES_1SS (0x3ff000ULL << 0) 8238c2ecf20Sopenharmony_ci#define RA_MASK_VHT_RATES_2SS (0x3ff000ULL << 10) 8248c2ecf20Sopenharmony_ci#define RA_MASK_VHT_RATES_3SS (0x3ff000ULL << 20) 8258c2ecf20Sopenharmony_ci#define RA_MASK_VHT_RATES (RA_MASK_VHT_RATES_1SS | \ 8268c2ecf20Sopenharmony_ci RA_MASK_VHT_RATES_2SS | \ 8278c2ecf20Sopenharmony_ci RA_MASK_VHT_RATES_3SS) 8288c2ecf20Sopenharmony_ci#define RA_MASK_CCK_IN_HT 0x00005 8298c2ecf20Sopenharmony_ci#define RA_MASK_CCK_IN_VHT 0x00005 8308c2ecf20Sopenharmony_ci#define RA_MASK_OFDM_IN_VHT 0x00010 8318c2ecf20Sopenharmony_ci#define RA_MASK_OFDM_IN_HT_2G 0x00010 8328c2ecf20Sopenharmony_ci#define RA_MASK_OFDM_IN_HT_5G 0x00030 8338c2ecf20Sopenharmony_ci 8348c2ecf20Sopenharmony_cistatic u64 rtw_update_rate_mask(struct rtw_dev *rtwdev, 8358c2ecf20Sopenharmony_ci struct rtw_sta_info *si, 8368c2ecf20Sopenharmony_ci u64 ra_mask, bool is_vht_enable, 8378c2ecf20Sopenharmony_ci u8 wireless_set) 8388c2ecf20Sopenharmony_ci{ 8398c2ecf20Sopenharmony_ci struct rtw_hal *hal = &rtwdev->hal; 8408c2ecf20Sopenharmony_ci const struct cfg80211_bitrate_mask *mask = si->mask; 8418c2ecf20Sopenharmony_ci u64 cfg_mask = GENMASK_ULL(63, 0); 8428c2ecf20Sopenharmony_ci u8 rssi_level, band; 8438c2ecf20Sopenharmony_ci 8448c2ecf20Sopenharmony_ci if (wireless_set != WIRELESS_CCK) { 8458c2ecf20Sopenharmony_ci rssi_level = si->rssi_level; 8468c2ecf20Sopenharmony_ci if (rssi_level == 0) 8478c2ecf20Sopenharmony_ci ra_mask &= 0xffffffffffffffffULL; 8488c2ecf20Sopenharmony_ci else if (rssi_level == 1) 8498c2ecf20Sopenharmony_ci ra_mask &= 0xfffffffffffffff0ULL; 8508c2ecf20Sopenharmony_ci else if (rssi_level == 2) 8518c2ecf20Sopenharmony_ci ra_mask &= 0xffffffffffffefe0ULL; 8528c2ecf20Sopenharmony_ci else if (rssi_level == 3) 8538c2ecf20Sopenharmony_ci ra_mask &= 0xffffffffffffcfc0ULL; 8548c2ecf20Sopenharmony_ci else if (rssi_level == 4) 8558c2ecf20Sopenharmony_ci ra_mask &= 0xffffffffffff8f80ULL; 8568c2ecf20Sopenharmony_ci else if (rssi_level >= 5) 8578c2ecf20Sopenharmony_ci ra_mask &= 0xffffffffffff0f00ULL; 8588c2ecf20Sopenharmony_ci } 8598c2ecf20Sopenharmony_ci 8608c2ecf20Sopenharmony_ci if (!si->use_cfg_mask) 8618c2ecf20Sopenharmony_ci return ra_mask; 8628c2ecf20Sopenharmony_ci 8638c2ecf20Sopenharmony_ci band = hal->current_band_type; 8648c2ecf20Sopenharmony_ci if (band == RTW_BAND_2G) { 8658c2ecf20Sopenharmony_ci band = NL80211_BAND_2GHZ; 8668c2ecf20Sopenharmony_ci cfg_mask = mask->control[band].legacy; 8678c2ecf20Sopenharmony_ci } else if (band == RTW_BAND_5G) { 8688c2ecf20Sopenharmony_ci band = NL80211_BAND_5GHZ; 8698c2ecf20Sopenharmony_ci cfg_mask = u64_encode_bits(mask->control[band].legacy, 8708c2ecf20Sopenharmony_ci RA_MASK_OFDM_RATES); 8718c2ecf20Sopenharmony_ci } 8728c2ecf20Sopenharmony_ci 8738c2ecf20Sopenharmony_ci if (!is_vht_enable) { 8748c2ecf20Sopenharmony_ci if (ra_mask & RA_MASK_HT_RATES_1SS) 8758c2ecf20Sopenharmony_ci cfg_mask |= u64_encode_bits(mask->control[band].ht_mcs[0], 8768c2ecf20Sopenharmony_ci RA_MASK_HT_RATES_1SS); 8778c2ecf20Sopenharmony_ci if (ra_mask & RA_MASK_HT_RATES_2SS) 8788c2ecf20Sopenharmony_ci cfg_mask |= u64_encode_bits(mask->control[band].ht_mcs[1], 8798c2ecf20Sopenharmony_ci RA_MASK_HT_RATES_2SS); 8808c2ecf20Sopenharmony_ci } else { 8818c2ecf20Sopenharmony_ci if (ra_mask & RA_MASK_VHT_RATES_1SS) 8828c2ecf20Sopenharmony_ci cfg_mask |= u64_encode_bits(mask->control[band].vht_mcs[0], 8838c2ecf20Sopenharmony_ci RA_MASK_VHT_RATES_1SS); 8848c2ecf20Sopenharmony_ci if (ra_mask & RA_MASK_VHT_RATES_2SS) 8858c2ecf20Sopenharmony_ci cfg_mask |= u64_encode_bits(mask->control[band].vht_mcs[1], 8868c2ecf20Sopenharmony_ci RA_MASK_VHT_RATES_2SS); 8878c2ecf20Sopenharmony_ci } 8888c2ecf20Sopenharmony_ci 8898c2ecf20Sopenharmony_ci ra_mask &= cfg_mask; 8908c2ecf20Sopenharmony_ci 8918c2ecf20Sopenharmony_ci return ra_mask; 8928c2ecf20Sopenharmony_ci} 8938c2ecf20Sopenharmony_ci 8948c2ecf20Sopenharmony_civoid rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si) 8958c2ecf20Sopenharmony_ci{ 8968c2ecf20Sopenharmony_ci struct ieee80211_sta *sta = si->sta; 8978c2ecf20Sopenharmony_ci struct rtw_efuse *efuse = &rtwdev->efuse; 8988c2ecf20Sopenharmony_ci struct rtw_hal *hal = &rtwdev->hal; 8998c2ecf20Sopenharmony_ci u8 wireless_set; 9008c2ecf20Sopenharmony_ci u8 bw_mode; 9018c2ecf20Sopenharmony_ci u8 rate_id; 9028c2ecf20Sopenharmony_ci u8 rf_type = RF_1T1R; 9038c2ecf20Sopenharmony_ci u8 stbc_en = 0; 9048c2ecf20Sopenharmony_ci u8 ldpc_en = 0; 9058c2ecf20Sopenharmony_ci u8 tx_num = 1; 9068c2ecf20Sopenharmony_ci u64 ra_mask = 0; 9078c2ecf20Sopenharmony_ci bool is_vht_enable = false; 9088c2ecf20Sopenharmony_ci bool is_support_sgi = false; 9098c2ecf20Sopenharmony_ci 9108c2ecf20Sopenharmony_ci if (sta->vht_cap.vht_supported) { 9118c2ecf20Sopenharmony_ci is_vht_enable = true; 9128c2ecf20Sopenharmony_ci ra_mask |= get_vht_ra_mask(sta); 9138c2ecf20Sopenharmony_ci if (sta->vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK) 9148c2ecf20Sopenharmony_ci stbc_en = VHT_STBC_EN; 9158c2ecf20Sopenharmony_ci if (sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC) 9168c2ecf20Sopenharmony_ci ldpc_en = VHT_LDPC_EN; 9178c2ecf20Sopenharmony_ci } else if (sta->ht_cap.ht_supported) { 9188c2ecf20Sopenharmony_ci ra_mask |= (sta->ht_cap.mcs.rx_mask[1] << 20) | 9198c2ecf20Sopenharmony_ci (sta->ht_cap.mcs.rx_mask[0] << 12); 9208c2ecf20Sopenharmony_ci if (sta->ht_cap.cap & IEEE80211_HT_CAP_RX_STBC) 9218c2ecf20Sopenharmony_ci stbc_en = HT_STBC_EN; 9228c2ecf20Sopenharmony_ci if (sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING) 9238c2ecf20Sopenharmony_ci ldpc_en = HT_LDPC_EN; 9248c2ecf20Sopenharmony_ci } 9258c2ecf20Sopenharmony_ci 9268c2ecf20Sopenharmony_ci if (efuse->hw_cap.nss == 1) 9278c2ecf20Sopenharmony_ci ra_mask &= RA_MASK_VHT_RATES_1SS | RA_MASK_HT_RATES_1SS; 9288c2ecf20Sopenharmony_ci 9298c2ecf20Sopenharmony_ci if (hal->current_band_type == RTW_BAND_5G) { 9308c2ecf20Sopenharmony_ci ra_mask |= (u64)sta->supp_rates[NL80211_BAND_5GHZ] << 4; 9318c2ecf20Sopenharmony_ci if (sta->vht_cap.vht_supported) { 9328c2ecf20Sopenharmony_ci ra_mask &= RA_MASK_VHT_RATES | RA_MASK_OFDM_IN_VHT; 9338c2ecf20Sopenharmony_ci wireless_set = WIRELESS_OFDM | WIRELESS_VHT; 9348c2ecf20Sopenharmony_ci } else if (sta->ht_cap.ht_supported) { 9358c2ecf20Sopenharmony_ci ra_mask &= RA_MASK_HT_RATES | RA_MASK_OFDM_IN_HT_5G; 9368c2ecf20Sopenharmony_ci wireless_set = WIRELESS_OFDM | WIRELESS_HT; 9378c2ecf20Sopenharmony_ci } else { 9388c2ecf20Sopenharmony_ci wireless_set = WIRELESS_OFDM; 9398c2ecf20Sopenharmony_ci } 9408c2ecf20Sopenharmony_ci } else if (hal->current_band_type == RTW_BAND_2G) { 9418c2ecf20Sopenharmony_ci ra_mask |= sta->supp_rates[NL80211_BAND_2GHZ]; 9428c2ecf20Sopenharmony_ci if (sta->vht_cap.vht_supported) { 9438c2ecf20Sopenharmony_ci ra_mask &= RA_MASK_VHT_RATES | RA_MASK_CCK_IN_VHT | 9448c2ecf20Sopenharmony_ci RA_MASK_OFDM_IN_VHT; 9458c2ecf20Sopenharmony_ci wireless_set = WIRELESS_CCK | WIRELESS_OFDM | 9468c2ecf20Sopenharmony_ci WIRELESS_HT | WIRELESS_VHT; 9478c2ecf20Sopenharmony_ci } else if (sta->ht_cap.ht_supported) { 9488c2ecf20Sopenharmony_ci ra_mask &= RA_MASK_HT_RATES | RA_MASK_CCK_IN_HT | 9498c2ecf20Sopenharmony_ci RA_MASK_OFDM_IN_HT_2G; 9508c2ecf20Sopenharmony_ci wireless_set = WIRELESS_CCK | WIRELESS_OFDM | 9518c2ecf20Sopenharmony_ci WIRELESS_HT; 9528c2ecf20Sopenharmony_ci } else if (sta->supp_rates[0] <= 0xf) { 9538c2ecf20Sopenharmony_ci wireless_set = WIRELESS_CCK; 9548c2ecf20Sopenharmony_ci } else { 9558c2ecf20Sopenharmony_ci wireless_set = WIRELESS_CCK | WIRELESS_OFDM; 9568c2ecf20Sopenharmony_ci } 9578c2ecf20Sopenharmony_ci } else { 9588c2ecf20Sopenharmony_ci rtw_err(rtwdev, "Unknown band type\n"); 9598c2ecf20Sopenharmony_ci wireless_set = 0; 9608c2ecf20Sopenharmony_ci } 9618c2ecf20Sopenharmony_ci 9628c2ecf20Sopenharmony_ci switch (sta->bandwidth) { 9638c2ecf20Sopenharmony_ci case IEEE80211_STA_RX_BW_80: 9648c2ecf20Sopenharmony_ci bw_mode = RTW_CHANNEL_WIDTH_80; 9658c2ecf20Sopenharmony_ci is_support_sgi = sta->vht_cap.vht_supported && 9668c2ecf20Sopenharmony_ci (sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80); 9678c2ecf20Sopenharmony_ci break; 9688c2ecf20Sopenharmony_ci case IEEE80211_STA_RX_BW_40: 9698c2ecf20Sopenharmony_ci bw_mode = RTW_CHANNEL_WIDTH_40; 9708c2ecf20Sopenharmony_ci is_support_sgi = sta->ht_cap.ht_supported && 9718c2ecf20Sopenharmony_ci (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40); 9728c2ecf20Sopenharmony_ci break; 9738c2ecf20Sopenharmony_ci default: 9748c2ecf20Sopenharmony_ci bw_mode = RTW_CHANNEL_WIDTH_20; 9758c2ecf20Sopenharmony_ci is_support_sgi = sta->ht_cap.ht_supported && 9768c2ecf20Sopenharmony_ci (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20); 9778c2ecf20Sopenharmony_ci break; 9788c2ecf20Sopenharmony_ci } 9798c2ecf20Sopenharmony_ci 9808c2ecf20Sopenharmony_ci if (sta->vht_cap.vht_supported && ra_mask & 0xffc00000) { 9818c2ecf20Sopenharmony_ci tx_num = 2; 9828c2ecf20Sopenharmony_ci rf_type = RF_2T2R; 9838c2ecf20Sopenharmony_ci } else if (sta->ht_cap.ht_supported && ra_mask & 0xfff00000) { 9848c2ecf20Sopenharmony_ci tx_num = 2; 9858c2ecf20Sopenharmony_ci rf_type = RF_2T2R; 9868c2ecf20Sopenharmony_ci } 9878c2ecf20Sopenharmony_ci 9888c2ecf20Sopenharmony_ci rate_id = get_rate_id(wireless_set, bw_mode, tx_num); 9898c2ecf20Sopenharmony_ci 9908c2ecf20Sopenharmony_ci ra_mask = rtw_update_rate_mask(rtwdev, si, ra_mask, is_vht_enable, 9918c2ecf20Sopenharmony_ci wireless_set); 9928c2ecf20Sopenharmony_ci 9938c2ecf20Sopenharmony_ci si->bw_mode = bw_mode; 9948c2ecf20Sopenharmony_ci si->stbc_en = stbc_en; 9958c2ecf20Sopenharmony_ci si->ldpc_en = ldpc_en; 9968c2ecf20Sopenharmony_ci si->rf_type = rf_type; 9978c2ecf20Sopenharmony_ci si->wireless_set = wireless_set; 9988c2ecf20Sopenharmony_ci si->sgi_enable = is_support_sgi; 9998c2ecf20Sopenharmony_ci si->vht_enable = is_vht_enable; 10008c2ecf20Sopenharmony_ci si->ra_mask = ra_mask; 10018c2ecf20Sopenharmony_ci si->rate_id = rate_id; 10028c2ecf20Sopenharmony_ci 10038c2ecf20Sopenharmony_ci rtw_fw_send_ra_info(rtwdev, si); 10048c2ecf20Sopenharmony_ci} 10058c2ecf20Sopenharmony_ci 10068c2ecf20Sopenharmony_cistatic int rtw_wait_firmware_completion(struct rtw_dev *rtwdev) 10078c2ecf20Sopenharmony_ci{ 10088c2ecf20Sopenharmony_ci struct rtw_chip_info *chip = rtwdev->chip; 10098c2ecf20Sopenharmony_ci struct rtw_fw_state *fw; 10108c2ecf20Sopenharmony_ci 10118c2ecf20Sopenharmony_ci fw = &rtwdev->fw; 10128c2ecf20Sopenharmony_ci wait_for_completion(&fw->completion); 10138c2ecf20Sopenharmony_ci if (!fw->firmware) 10148c2ecf20Sopenharmony_ci return -EINVAL; 10158c2ecf20Sopenharmony_ci 10168c2ecf20Sopenharmony_ci if (chip->wow_fw_name) { 10178c2ecf20Sopenharmony_ci fw = &rtwdev->wow_fw; 10188c2ecf20Sopenharmony_ci wait_for_completion(&fw->completion); 10198c2ecf20Sopenharmony_ci if (!fw->firmware) 10208c2ecf20Sopenharmony_ci return -EINVAL; 10218c2ecf20Sopenharmony_ci } 10228c2ecf20Sopenharmony_ci 10238c2ecf20Sopenharmony_ci return 0; 10248c2ecf20Sopenharmony_ci} 10258c2ecf20Sopenharmony_ci 10268c2ecf20Sopenharmony_cistatic int rtw_power_on(struct rtw_dev *rtwdev) 10278c2ecf20Sopenharmony_ci{ 10288c2ecf20Sopenharmony_ci struct rtw_chip_info *chip = rtwdev->chip; 10298c2ecf20Sopenharmony_ci struct rtw_fw_state *fw = &rtwdev->fw; 10308c2ecf20Sopenharmony_ci bool wifi_only; 10318c2ecf20Sopenharmony_ci int ret; 10328c2ecf20Sopenharmony_ci 10338c2ecf20Sopenharmony_ci ret = rtw_hci_setup(rtwdev); 10348c2ecf20Sopenharmony_ci if (ret) { 10358c2ecf20Sopenharmony_ci rtw_err(rtwdev, "failed to setup hci\n"); 10368c2ecf20Sopenharmony_ci goto err; 10378c2ecf20Sopenharmony_ci } 10388c2ecf20Sopenharmony_ci 10398c2ecf20Sopenharmony_ci /* power on MAC before firmware downloaded */ 10408c2ecf20Sopenharmony_ci ret = rtw_mac_power_on(rtwdev); 10418c2ecf20Sopenharmony_ci if (ret) { 10428c2ecf20Sopenharmony_ci rtw_err(rtwdev, "failed to power on mac\n"); 10438c2ecf20Sopenharmony_ci goto err; 10448c2ecf20Sopenharmony_ci } 10458c2ecf20Sopenharmony_ci 10468c2ecf20Sopenharmony_ci ret = rtw_wait_firmware_completion(rtwdev); 10478c2ecf20Sopenharmony_ci if (ret) { 10488c2ecf20Sopenharmony_ci rtw_err(rtwdev, "failed to wait firmware completion\n"); 10498c2ecf20Sopenharmony_ci goto err_off; 10508c2ecf20Sopenharmony_ci } 10518c2ecf20Sopenharmony_ci 10528c2ecf20Sopenharmony_ci ret = rtw_download_firmware(rtwdev, fw); 10538c2ecf20Sopenharmony_ci if (ret) { 10548c2ecf20Sopenharmony_ci rtw_err(rtwdev, "failed to download firmware\n"); 10558c2ecf20Sopenharmony_ci goto err_off; 10568c2ecf20Sopenharmony_ci } 10578c2ecf20Sopenharmony_ci 10588c2ecf20Sopenharmony_ci /* config mac after firmware downloaded */ 10598c2ecf20Sopenharmony_ci ret = rtw_mac_init(rtwdev); 10608c2ecf20Sopenharmony_ci if (ret) { 10618c2ecf20Sopenharmony_ci rtw_err(rtwdev, "failed to configure mac\n"); 10628c2ecf20Sopenharmony_ci goto err_off; 10638c2ecf20Sopenharmony_ci } 10648c2ecf20Sopenharmony_ci 10658c2ecf20Sopenharmony_ci chip->ops->phy_set_param(rtwdev); 10668c2ecf20Sopenharmony_ci 10678c2ecf20Sopenharmony_ci ret = rtw_hci_start(rtwdev); 10688c2ecf20Sopenharmony_ci if (ret) { 10698c2ecf20Sopenharmony_ci rtw_err(rtwdev, "failed to start hci\n"); 10708c2ecf20Sopenharmony_ci goto err_off; 10718c2ecf20Sopenharmony_ci } 10728c2ecf20Sopenharmony_ci 10738c2ecf20Sopenharmony_ci /* send H2C after HCI has started */ 10748c2ecf20Sopenharmony_ci rtw_fw_send_general_info(rtwdev); 10758c2ecf20Sopenharmony_ci rtw_fw_send_phydm_info(rtwdev); 10768c2ecf20Sopenharmony_ci 10778c2ecf20Sopenharmony_ci wifi_only = !rtwdev->efuse.btcoex; 10788c2ecf20Sopenharmony_ci rtw_coex_power_on_setting(rtwdev); 10798c2ecf20Sopenharmony_ci rtw_coex_init_hw_config(rtwdev, wifi_only); 10808c2ecf20Sopenharmony_ci 10818c2ecf20Sopenharmony_ci return 0; 10828c2ecf20Sopenharmony_ci 10838c2ecf20Sopenharmony_cierr_off: 10848c2ecf20Sopenharmony_ci rtw_mac_power_off(rtwdev); 10858c2ecf20Sopenharmony_ci 10868c2ecf20Sopenharmony_cierr: 10878c2ecf20Sopenharmony_ci return ret; 10888c2ecf20Sopenharmony_ci} 10898c2ecf20Sopenharmony_ci 10908c2ecf20Sopenharmony_ciint rtw_core_start(struct rtw_dev *rtwdev) 10918c2ecf20Sopenharmony_ci{ 10928c2ecf20Sopenharmony_ci int ret; 10938c2ecf20Sopenharmony_ci 10948c2ecf20Sopenharmony_ci ret = rtw_power_on(rtwdev); 10958c2ecf20Sopenharmony_ci if (ret) 10968c2ecf20Sopenharmony_ci return ret; 10978c2ecf20Sopenharmony_ci 10988c2ecf20Sopenharmony_ci rtw_sec_enable_sec_engine(rtwdev); 10998c2ecf20Sopenharmony_ci 11008c2ecf20Sopenharmony_ci /* rcr reset after powered on */ 11018c2ecf20Sopenharmony_ci rtw_write32(rtwdev, REG_RCR, rtwdev->hal.rcr); 11028c2ecf20Sopenharmony_ci 11038c2ecf20Sopenharmony_ci ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->watch_dog_work, 11048c2ecf20Sopenharmony_ci RTW_WATCH_DOG_DELAY_TIME); 11058c2ecf20Sopenharmony_ci 11068c2ecf20Sopenharmony_ci set_bit(RTW_FLAG_RUNNING, rtwdev->flags); 11078c2ecf20Sopenharmony_ci 11088c2ecf20Sopenharmony_ci return 0; 11098c2ecf20Sopenharmony_ci} 11108c2ecf20Sopenharmony_ci 11118c2ecf20Sopenharmony_cistatic void rtw_power_off(struct rtw_dev *rtwdev) 11128c2ecf20Sopenharmony_ci{ 11138c2ecf20Sopenharmony_ci rtw_hci_stop(rtwdev); 11148c2ecf20Sopenharmony_ci rtw_mac_power_off(rtwdev); 11158c2ecf20Sopenharmony_ci} 11168c2ecf20Sopenharmony_ci 11178c2ecf20Sopenharmony_civoid rtw_core_stop(struct rtw_dev *rtwdev) 11188c2ecf20Sopenharmony_ci{ 11198c2ecf20Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 11208c2ecf20Sopenharmony_ci 11218c2ecf20Sopenharmony_ci clear_bit(RTW_FLAG_RUNNING, rtwdev->flags); 11228c2ecf20Sopenharmony_ci clear_bit(RTW_FLAG_FW_RUNNING, rtwdev->flags); 11238c2ecf20Sopenharmony_ci 11248c2ecf20Sopenharmony_ci mutex_unlock(&rtwdev->mutex); 11258c2ecf20Sopenharmony_ci 11268c2ecf20Sopenharmony_ci cancel_work_sync(&rtwdev->c2h_work); 11278c2ecf20Sopenharmony_ci cancel_delayed_work_sync(&rtwdev->watch_dog_work); 11288c2ecf20Sopenharmony_ci cancel_delayed_work_sync(&coex->bt_relink_work); 11298c2ecf20Sopenharmony_ci cancel_delayed_work_sync(&coex->bt_reenable_work); 11308c2ecf20Sopenharmony_ci cancel_delayed_work_sync(&coex->defreeze_work); 11318c2ecf20Sopenharmony_ci cancel_delayed_work_sync(&coex->wl_remain_work); 11328c2ecf20Sopenharmony_ci cancel_delayed_work_sync(&coex->bt_remain_work); 11338c2ecf20Sopenharmony_ci 11348c2ecf20Sopenharmony_ci mutex_lock(&rtwdev->mutex); 11358c2ecf20Sopenharmony_ci 11368c2ecf20Sopenharmony_ci rtw_power_off(rtwdev); 11378c2ecf20Sopenharmony_ci} 11388c2ecf20Sopenharmony_ci 11398c2ecf20Sopenharmony_cistatic void rtw_init_ht_cap(struct rtw_dev *rtwdev, 11408c2ecf20Sopenharmony_ci struct ieee80211_sta_ht_cap *ht_cap) 11418c2ecf20Sopenharmony_ci{ 11428c2ecf20Sopenharmony_ci struct rtw_efuse *efuse = &rtwdev->efuse; 11438c2ecf20Sopenharmony_ci 11448c2ecf20Sopenharmony_ci ht_cap->ht_supported = true; 11458c2ecf20Sopenharmony_ci ht_cap->cap = 0; 11468c2ecf20Sopenharmony_ci ht_cap->cap |= IEEE80211_HT_CAP_SGI_20 | 11478c2ecf20Sopenharmony_ci IEEE80211_HT_CAP_MAX_AMSDU | 11488c2ecf20Sopenharmony_ci (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT); 11498c2ecf20Sopenharmony_ci 11508c2ecf20Sopenharmony_ci if (rtw_chip_has_rx_ldpc(rtwdev)) 11518c2ecf20Sopenharmony_ci ht_cap->cap |= IEEE80211_HT_CAP_LDPC_CODING; 11528c2ecf20Sopenharmony_ci 11538c2ecf20Sopenharmony_ci if (efuse->hw_cap.bw & BIT(RTW_CHANNEL_WIDTH_40)) 11548c2ecf20Sopenharmony_ci ht_cap->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40 | 11558c2ecf20Sopenharmony_ci IEEE80211_HT_CAP_DSSSCCK40 | 11568c2ecf20Sopenharmony_ci IEEE80211_HT_CAP_SGI_40; 11578c2ecf20Sopenharmony_ci ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; 11588c2ecf20Sopenharmony_ci ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_16; 11598c2ecf20Sopenharmony_ci ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; 11608c2ecf20Sopenharmony_ci if (efuse->hw_cap.nss > 1) { 11618c2ecf20Sopenharmony_ci ht_cap->mcs.rx_mask[0] = 0xFF; 11628c2ecf20Sopenharmony_ci ht_cap->mcs.rx_mask[1] = 0xFF; 11638c2ecf20Sopenharmony_ci ht_cap->mcs.rx_mask[4] = 0x01; 11648c2ecf20Sopenharmony_ci ht_cap->mcs.rx_highest = cpu_to_le16(300); 11658c2ecf20Sopenharmony_ci } else { 11668c2ecf20Sopenharmony_ci ht_cap->mcs.rx_mask[0] = 0xFF; 11678c2ecf20Sopenharmony_ci ht_cap->mcs.rx_mask[1] = 0x00; 11688c2ecf20Sopenharmony_ci ht_cap->mcs.rx_mask[4] = 0x01; 11698c2ecf20Sopenharmony_ci ht_cap->mcs.rx_highest = cpu_to_le16(150); 11708c2ecf20Sopenharmony_ci } 11718c2ecf20Sopenharmony_ci} 11728c2ecf20Sopenharmony_ci 11738c2ecf20Sopenharmony_cistatic void rtw_init_vht_cap(struct rtw_dev *rtwdev, 11748c2ecf20Sopenharmony_ci struct ieee80211_sta_vht_cap *vht_cap) 11758c2ecf20Sopenharmony_ci{ 11768c2ecf20Sopenharmony_ci struct rtw_efuse *efuse = &rtwdev->efuse; 11778c2ecf20Sopenharmony_ci u16 mcs_map; 11788c2ecf20Sopenharmony_ci __le16 highest; 11798c2ecf20Sopenharmony_ci 11808c2ecf20Sopenharmony_ci if (efuse->hw_cap.ptcl != EFUSE_HW_CAP_IGNORE && 11818c2ecf20Sopenharmony_ci efuse->hw_cap.ptcl != EFUSE_HW_CAP_PTCL_VHT) 11828c2ecf20Sopenharmony_ci return; 11838c2ecf20Sopenharmony_ci 11848c2ecf20Sopenharmony_ci vht_cap->vht_supported = true; 11858c2ecf20Sopenharmony_ci vht_cap->cap = IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | 11868c2ecf20Sopenharmony_ci IEEE80211_VHT_CAP_SHORT_GI_80 | 11878c2ecf20Sopenharmony_ci IEEE80211_VHT_CAP_RXSTBC_1 | 11888c2ecf20Sopenharmony_ci IEEE80211_VHT_CAP_HTC_VHT | 11898c2ecf20Sopenharmony_ci IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK | 11908c2ecf20Sopenharmony_ci 0; 11918c2ecf20Sopenharmony_ci if (rtwdev->hal.rf_path_num > 1) 11928c2ecf20Sopenharmony_ci vht_cap->cap |= IEEE80211_VHT_CAP_TXSTBC; 11938c2ecf20Sopenharmony_ci vht_cap->cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE | 11948c2ecf20Sopenharmony_ci IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE; 11958c2ecf20Sopenharmony_ci vht_cap->cap |= (rtwdev->hal.bfee_sts_cap << 11968c2ecf20Sopenharmony_ci IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT); 11978c2ecf20Sopenharmony_ci 11988c2ecf20Sopenharmony_ci if (rtw_chip_has_rx_ldpc(rtwdev)) 11998c2ecf20Sopenharmony_ci vht_cap->cap |= IEEE80211_VHT_CAP_RXLDPC; 12008c2ecf20Sopenharmony_ci 12018c2ecf20Sopenharmony_ci mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 | 12028c2ecf20Sopenharmony_ci IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 | 12038c2ecf20Sopenharmony_ci IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 | 12048c2ecf20Sopenharmony_ci IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 | 12058c2ecf20Sopenharmony_ci IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 | 12068c2ecf20Sopenharmony_ci IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 | 12078c2ecf20Sopenharmony_ci IEEE80211_VHT_MCS_NOT_SUPPORTED << 14; 12088c2ecf20Sopenharmony_ci if (efuse->hw_cap.nss > 1) { 12098c2ecf20Sopenharmony_ci highest = cpu_to_le16(780); 12108c2ecf20Sopenharmony_ci mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << 2; 12118c2ecf20Sopenharmony_ci } else { 12128c2ecf20Sopenharmony_ci highest = cpu_to_le16(390); 12138c2ecf20Sopenharmony_ci mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << 2; 12148c2ecf20Sopenharmony_ci } 12158c2ecf20Sopenharmony_ci 12168c2ecf20Sopenharmony_ci vht_cap->vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map); 12178c2ecf20Sopenharmony_ci vht_cap->vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map); 12188c2ecf20Sopenharmony_ci vht_cap->vht_mcs.rx_highest = highest; 12198c2ecf20Sopenharmony_ci vht_cap->vht_mcs.tx_highest = highest; 12208c2ecf20Sopenharmony_ci} 12218c2ecf20Sopenharmony_ci 12228c2ecf20Sopenharmony_cistatic void rtw_set_supported_band(struct ieee80211_hw *hw, 12238c2ecf20Sopenharmony_ci struct rtw_chip_info *chip) 12248c2ecf20Sopenharmony_ci{ 12258c2ecf20Sopenharmony_ci struct rtw_dev *rtwdev = hw->priv; 12268c2ecf20Sopenharmony_ci struct ieee80211_supported_band *sband; 12278c2ecf20Sopenharmony_ci 12288c2ecf20Sopenharmony_ci if (chip->band & RTW_BAND_2G) { 12298c2ecf20Sopenharmony_ci sband = kmemdup(&rtw_band_2ghz, sizeof(*sband), GFP_KERNEL); 12308c2ecf20Sopenharmony_ci if (!sband) 12318c2ecf20Sopenharmony_ci goto err_out; 12328c2ecf20Sopenharmony_ci if (chip->ht_supported) 12338c2ecf20Sopenharmony_ci rtw_init_ht_cap(rtwdev, &sband->ht_cap); 12348c2ecf20Sopenharmony_ci hw->wiphy->bands[NL80211_BAND_2GHZ] = sband; 12358c2ecf20Sopenharmony_ci } 12368c2ecf20Sopenharmony_ci 12378c2ecf20Sopenharmony_ci if (chip->band & RTW_BAND_5G) { 12388c2ecf20Sopenharmony_ci sband = kmemdup(&rtw_band_5ghz, sizeof(*sband), GFP_KERNEL); 12398c2ecf20Sopenharmony_ci if (!sband) 12408c2ecf20Sopenharmony_ci goto err_out; 12418c2ecf20Sopenharmony_ci if (chip->ht_supported) 12428c2ecf20Sopenharmony_ci rtw_init_ht_cap(rtwdev, &sband->ht_cap); 12438c2ecf20Sopenharmony_ci if (chip->vht_supported) 12448c2ecf20Sopenharmony_ci rtw_init_vht_cap(rtwdev, &sband->vht_cap); 12458c2ecf20Sopenharmony_ci hw->wiphy->bands[NL80211_BAND_5GHZ] = sband; 12468c2ecf20Sopenharmony_ci } 12478c2ecf20Sopenharmony_ci 12488c2ecf20Sopenharmony_ci return; 12498c2ecf20Sopenharmony_ci 12508c2ecf20Sopenharmony_cierr_out: 12518c2ecf20Sopenharmony_ci rtw_err(rtwdev, "failed to set supported band\n"); 12528c2ecf20Sopenharmony_ci kfree(sband); 12538c2ecf20Sopenharmony_ci} 12548c2ecf20Sopenharmony_ci 12558c2ecf20Sopenharmony_cistatic void rtw_unset_supported_band(struct ieee80211_hw *hw, 12568c2ecf20Sopenharmony_ci struct rtw_chip_info *chip) 12578c2ecf20Sopenharmony_ci{ 12588c2ecf20Sopenharmony_ci kfree(hw->wiphy->bands[NL80211_BAND_2GHZ]); 12598c2ecf20Sopenharmony_ci kfree(hw->wiphy->bands[NL80211_BAND_5GHZ]); 12608c2ecf20Sopenharmony_ci} 12618c2ecf20Sopenharmony_ci 12628c2ecf20Sopenharmony_cistatic void __update_firmware_info(struct rtw_dev *rtwdev, 12638c2ecf20Sopenharmony_ci struct rtw_fw_state *fw) 12648c2ecf20Sopenharmony_ci{ 12658c2ecf20Sopenharmony_ci const struct rtw_fw_hdr *fw_hdr = 12668c2ecf20Sopenharmony_ci (const struct rtw_fw_hdr *)fw->firmware->data; 12678c2ecf20Sopenharmony_ci 12688c2ecf20Sopenharmony_ci fw->h2c_version = le16_to_cpu(fw_hdr->h2c_fmt_ver); 12698c2ecf20Sopenharmony_ci fw->version = le16_to_cpu(fw_hdr->version); 12708c2ecf20Sopenharmony_ci fw->sub_version = fw_hdr->subversion; 12718c2ecf20Sopenharmony_ci fw->sub_index = fw_hdr->subindex; 12728c2ecf20Sopenharmony_ci} 12738c2ecf20Sopenharmony_ci 12748c2ecf20Sopenharmony_cistatic void __update_firmware_info_legacy(struct rtw_dev *rtwdev, 12758c2ecf20Sopenharmony_ci struct rtw_fw_state *fw) 12768c2ecf20Sopenharmony_ci{ 12778c2ecf20Sopenharmony_ci struct rtw_fw_hdr_legacy *legacy = 12788c2ecf20Sopenharmony_ci (struct rtw_fw_hdr_legacy *)fw->firmware->data; 12798c2ecf20Sopenharmony_ci 12808c2ecf20Sopenharmony_ci fw->h2c_version = 0; 12818c2ecf20Sopenharmony_ci fw->version = le16_to_cpu(legacy->version); 12828c2ecf20Sopenharmony_ci fw->sub_version = legacy->subversion1; 12838c2ecf20Sopenharmony_ci fw->sub_index = legacy->subversion2; 12848c2ecf20Sopenharmony_ci} 12858c2ecf20Sopenharmony_ci 12868c2ecf20Sopenharmony_cistatic void update_firmware_info(struct rtw_dev *rtwdev, 12878c2ecf20Sopenharmony_ci struct rtw_fw_state *fw) 12888c2ecf20Sopenharmony_ci{ 12898c2ecf20Sopenharmony_ci if (rtw_chip_wcpu_11n(rtwdev)) 12908c2ecf20Sopenharmony_ci __update_firmware_info_legacy(rtwdev, fw); 12918c2ecf20Sopenharmony_ci else 12928c2ecf20Sopenharmony_ci __update_firmware_info(rtwdev, fw); 12938c2ecf20Sopenharmony_ci} 12948c2ecf20Sopenharmony_ci 12958c2ecf20Sopenharmony_cistatic void rtw_load_firmware_cb(const struct firmware *firmware, void *context) 12968c2ecf20Sopenharmony_ci{ 12978c2ecf20Sopenharmony_ci struct rtw_fw_state *fw = context; 12988c2ecf20Sopenharmony_ci struct rtw_dev *rtwdev = fw->rtwdev; 12998c2ecf20Sopenharmony_ci 13008c2ecf20Sopenharmony_ci if (!firmware || !firmware->data) { 13018c2ecf20Sopenharmony_ci rtw_err(rtwdev, "failed to request firmware\n"); 13028c2ecf20Sopenharmony_ci complete_all(&fw->completion); 13038c2ecf20Sopenharmony_ci return; 13048c2ecf20Sopenharmony_ci } 13058c2ecf20Sopenharmony_ci 13068c2ecf20Sopenharmony_ci fw->firmware = firmware; 13078c2ecf20Sopenharmony_ci update_firmware_info(rtwdev, fw); 13088c2ecf20Sopenharmony_ci complete_all(&fw->completion); 13098c2ecf20Sopenharmony_ci 13108c2ecf20Sopenharmony_ci rtw_info(rtwdev, "Firmware version %u.%u.%u, H2C version %u\n", 13118c2ecf20Sopenharmony_ci fw->version, fw->sub_version, fw->sub_index, fw->h2c_version); 13128c2ecf20Sopenharmony_ci} 13138c2ecf20Sopenharmony_ci 13148c2ecf20Sopenharmony_cistatic int rtw_load_firmware(struct rtw_dev *rtwdev, enum rtw_fw_type type) 13158c2ecf20Sopenharmony_ci{ 13168c2ecf20Sopenharmony_ci const char *fw_name; 13178c2ecf20Sopenharmony_ci struct rtw_fw_state *fw; 13188c2ecf20Sopenharmony_ci int ret; 13198c2ecf20Sopenharmony_ci 13208c2ecf20Sopenharmony_ci switch (type) { 13218c2ecf20Sopenharmony_ci case RTW_WOWLAN_FW: 13228c2ecf20Sopenharmony_ci fw = &rtwdev->wow_fw; 13238c2ecf20Sopenharmony_ci fw_name = rtwdev->chip->wow_fw_name; 13248c2ecf20Sopenharmony_ci break; 13258c2ecf20Sopenharmony_ci 13268c2ecf20Sopenharmony_ci case RTW_NORMAL_FW: 13278c2ecf20Sopenharmony_ci fw = &rtwdev->fw; 13288c2ecf20Sopenharmony_ci fw_name = rtwdev->chip->fw_name; 13298c2ecf20Sopenharmony_ci break; 13308c2ecf20Sopenharmony_ci 13318c2ecf20Sopenharmony_ci default: 13328c2ecf20Sopenharmony_ci rtw_warn(rtwdev, "unsupported firmware type\n"); 13338c2ecf20Sopenharmony_ci return -ENOENT; 13348c2ecf20Sopenharmony_ci } 13358c2ecf20Sopenharmony_ci 13368c2ecf20Sopenharmony_ci fw->rtwdev = rtwdev; 13378c2ecf20Sopenharmony_ci init_completion(&fw->completion); 13388c2ecf20Sopenharmony_ci 13398c2ecf20Sopenharmony_ci ret = request_firmware_nowait(THIS_MODULE, true, fw_name, rtwdev->dev, 13408c2ecf20Sopenharmony_ci GFP_KERNEL, fw, rtw_load_firmware_cb); 13418c2ecf20Sopenharmony_ci if (ret) { 13428c2ecf20Sopenharmony_ci rtw_err(rtwdev, "failed to async firmware request\n"); 13438c2ecf20Sopenharmony_ci return ret; 13448c2ecf20Sopenharmony_ci } 13458c2ecf20Sopenharmony_ci 13468c2ecf20Sopenharmony_ci return 0; 13478c2ecf20Sopenharmony_ci} 13488c2ecf20Sopenharmony_ci 13498c2ecf20Sopenharmony_cistatic int rtw_chip_parameter_setup(struct rtw_dev *rtwdev) 13508c2ecf20Sopenharmony_ci{ 13518c2ecf20Sopenharmony_ci struct rtw_chip_info *chip = rtwdev->chip; 13528c2ecf20Sopenharmony_ci struct rtw_hal *hal = &rtwdev->hal; 13538c2ecf20Sopenharmony_ci struct rtw_efuse *efuse = &rtwdev->efuse; 13548c2ecf20Sopenharmony_ci int ret = 0; 13558c2ecf20Sopenharmony_ci 13568c2ecf20Sopenharmony_ci switch (rtw_hci_type(rtwdev)) { 13578c2ecf20Sopenharmony_ci case RTW_HCI_TYPE_PCIE: 13588c2ecf20Sopenharmony_ci rtwdev->hci.rpwm_addr = 0x03d9; 13598c2ecf20Sopenharmony_ci rtwdev->hci.cpwm_addr = 0x03da; 13608c2ecf20Sopenharmony_ci break; 13618c2ecf20Sopenharmony_ci default: 13628c2ecf20Sopenharmony_ci rtw_err(rtwdev, "unsupported hci type\n"); 13638c2ecf20Sopenharmony_ci return -EINVAL; 13648c2ecf20Sopenharmony_ci } 13658c2ecf20Sopenharmony_ci 13668c2ecf20Sopenharmony_ci hal->chip_version = rtw_read32(rtwdev, REG_SYS_CFG1); 13678c2ecf20Sopenharmony_ci hal->cut_version = BIT_GET_CHIP_VER(hal->chip_version); 13688c2ecf20Sopenharmony_ci hal->mp_chip = (hal->chip_version & BIT_RTL_ID) ? 0 : 1; 13698c2ecf20Sopenharmony_ci if (hal->chip_version & BIT_RF_TYPE_ID) { 13708c2ecf20Sopenharmony_ci hal->rf_type = RF_2T2R; 13718c2ecf20Sopenharmony_ci hal->rf_path_num = 2; 13728c2ecf20Sopenharmony_ci hal->antenna_tx = BB_PATH_AB; 13738c2ecf20Sopenharmony_ci hal->antenna_rx = BB_PATH_AB; 13748c2ecf20Sopenharmony_ci } else { 13758c2ecf20Sopenharmony_ci hal->rf_type = RF_1T1R; 13768c2ecf20Sopenharmony_ci hal->rf_path_num = 1; 13778c2ecf20Sopenharmony_ci hal->antenna_tx = BB_PATH_A; 13788c2ecf20Sopenharmony_ci hal->antenna_rx = BB_PATH_A; 13798c2ecf20Sopenharmony_ci } 13808c2ecf20Sopenharmony_ci hal->rf_phy_num = chip->fix_rf_phy_num ? chip->fix_rf_phy_num : 13818c2ecf20Sopenharmony_ci hal->rf_path_num; 13828c2ecf20Sopenharmony_ci 13838c2ecf20Sopenharmony_ci efuse->physical_size = chip->phy_efuse_size; 13848c2ecf20Sopenharmony_ci efuse->logical_size = chip->log_efuse_size; 13858c2ecf20Sopenharmony_ci efuse->protect_size = chip->ptct_efuse_size; 13868c2ecf20Sopenharmony_ci 13878c2ecf20Sopenharmony_ci /* default use ack */ 13888c2ecf20Sopenharmony_ci rtwdev->hal.rcr |= BIT_VHT_DACK; 13898c2ecf20Sopenharmony_ci 13908c2ecf20Sopenharmony_ci hal->bfee_sts_cap = 3; 13918c2ecf20Sopenharmony_ci 13928c2ecf20Sopenharmony_ci return ret; 13938c2ecf20Sopenharmony_ci} 13948c2ecf20Sopenharmony_ci 13958c2ecf20Sopenharmony_cistatic int rtw_chip_efuse_enable(struct rtw_dev *rtwdev) 13968c2ecf20Sopenharmony_ci{ 13978c2ecf20Sopenharmony_ci struct rtw_fw_state *fw = &rtwdev->fw; 13988c2ecf20Sopenharmony_ci int ret; 13998c2ecf20Sopenharmony_ci 14008c2ecf20Sopenharmony_ci ret = rtw_hci_setup(rtwdev); 14018c2ecf20Sopenharmony_ci if (ret) { 14028c2ecf20Sopenharmony_ci rtw_err(rtwdev, "failed to setup hci\n"); 14038c2ecf20Sopenharmony_ci goto err; 14048c2ecf20Sopenharmony_ci } 14058c2ecf20Sopenharmony_ci 14068c2ecf20Sopenharmony_ci ret = rtw_mac_power_on(rtwdev); 14078c2ecf20Sopenharmony_ci if (ret) { 14088c2ecf20Sopenharmony_ci rtw_err(rtwdev, "failed to power on mac\n"); 14098c2ecf20Sopenharmony_ci goto err; 14108c2ecf20Sopenharmony_ci } 14118c2ecf20Sopenharmony_ci 14128c2ecf20Sopenharmony_ci rtw_write8(rtwdev, REG_C2HEVT, C2H_HW_FEATURE_DUMP); 14138c2ecf20Sopenharmony_ci 14148c2ecf20Sopenharmony_ci wait_for_completion(&fw->completion); 14158c2ecf20Sopenharmony_ci if (!fw->firmware) { 14168c2ecf20Sopenharmony_ci ret = -EINVAL; 14178c2ecf20Sopenharmony_ci rtw_err(rtwdev, "failed to load firmware\n"); 14188c2ecf20Sopenharmony_ci goto err; 14198c2ecf20Sopenharmony_ci } 14208c2ecf20Sopenharmony_ci 14218c2ecf20Sopenharmony_ci ret = rtw_download_firmware(rtwdev, fw); 14228c2ecf20Sopenharmony_ci if (ret) { 14238c2ecf20Sopenharmony_ci rtw_err(rtwdev, "failed to download firmware\n"); 14248c2ecf20Sopenharmony_ci goto err_off; 14258c2ecf20Sopenharmony_ci } 14268c2ecf20Sopenharmony_ci 14278c2ecf20Sopenharmony_ci return 0; 14288c2ecf20Sopenharmony_ci 14298c2ecf20Sopenharmony_cierr_off: 14308c2ecf20Sopenharmony_ci rtw_mac_power_off(rtwdev); 14318c2ecf20Sopenharmony_ci 14328c2ecf20Sopenharmony_cierr: 14338c2ecf20Sopenharmony_ci return ret; 14348c2ecf20Sopenharmony_ci} 14358c2ecf20Sopenharmony_ci 14368c2ecf20Sopenharmony_cistatic int rtw_dump_hw_feature(struct rtw_dev *rtwdev) 14378c2ecf20Sopenharmony_ci{ 14388c2ecf20Sopenharmony_ci struct rtw_efuse *efuse = &rtwdev->efuse; 14398c2ecf20Sopenharmony_ci u8 hw_feature[HW_FEATURE_LEN]; 14408c2ecf20Sopenharmony_ci u8 id; 14418c2ecf20Sopenharmony_ci u8 bw; 14428c2ecf20Sopenharmony_ci int i; 14438c2ecf20Sopenharmony_ci 14448c2ecf20Sopenharmony_ci id = rtw_read8(rtwdev, REG_C2HEVT); 14458c2ecf20Sopenharmony_ci if (id != C2H_HW_FEATURE_REPORT) { 14468c2ecf20Sopenharmony_ci rtw_err(rtwdev, "failed to read hw feature report\n"); 14478c2ecf20Sopenharmony_ci return -EBUSY; 14488c2ecf20Sopenharmony_ci } 14498c2ecf20Sopenharmony_ci 14508c2ecf20Sopenharmony_ci for (i = 0; i < HW_FEATURE_LEN; i++) 14518c2ecf20Sopenharmony_ci hw_feature[i] = rtw_read8(rtwdev, REG_C2HEVT + 2 + i); 14528c2ecf20Sopenharmony_ci 14538c2ecf20Sopenharmony_ci rtw_write8(rtwdev, REG_C2HEVT, 0); 14548c2ecf20Sopenharmony_ci 14558c2ecf20Sopenharmony_ci bw = GET_EFUSE_HW_CAP_BW(hw_feature); 14568c2ecf20Sopenharmony_ci efuse->hw_cap.bw = hw_bw_cap_to_bitamp(bw); 14578c2ecf20Sopenharmony_ci efuse->hw_cap.hci = GET_EFUSE_HW_CAP_HCI(hw_feature); 14588c2ecf20Sopenharmony_ci efuse->hw_cap.nss = GET_EFUSE_HW_CAP_NSS(hw_feature); 14598c2ecf20Sopenharmony_ci efuse->hw_cap.ptcl = GET_EFUSE_HW_CAP_PTCL(hw_feature); 14608c2ecf20Sopenharmony_ci efuse->hw_cap.ant_num = GET_EFUSE_HW_CAP_ANT_NUM(hw_feature); 14618c2ecf20Sopenharmony_ci 14628c2ecf20Sopenharmony_ci rtw_hw_config_rf_ant_num(rtwdev, efuse->hw_cap.ant_num); 14638c2ecf20Sopenharmony_ci 14648c2ecf20Sopenharmony_ci if (efuse->hw_cap.nss == EFUSE_HW_CAP_IGNORE || 14658c2ecf20Sopenharmony_ci efuse->hw_cap.nss > rtwdev->hal.rf_path_num) 14668c2ecf20Sopenharmony_ci efuse->hw_cap.nss = rtwdev->hal.rf_path_num; 14678c2ecf20Sopenharmony_ci 14688c2ecf20Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_EFUSE, 14698c2ecf20Sopenharmony_ci "hw cap: hci=0x%02x, bw=0x%02x, ptcl=0x%02x, ant_num=%d, nss=%d\n", 14708c2ecf20Sopenharmony_ci efuse->hw_cap.hci, efuse->hw_cap.bw, efuse->hw_cap.ptcl, 14718c2ecf20Sopenharmony_ci efuse->hw_cap.ant_num, efuse->hw_cap.nss); 14728c2ecf20Sopenharmony_ci 14738c2ecf20Sopenharmony_ci return 0; 14748c2ecf20Sopenharmony_ci} 14758c2ecf20Sopenharmony_ci 14768c2ecf20Sopenharmony_cistatic void rtw_chip_efuse_disable(struct rtw_dev *rtwdev) 14778c2ecf20Sopenharmony_ci{ 14788c2ecf20Sopenharmony_ci rtw_hci_stop(rtwdev); 14798c2ecf20Sopenharmony_ci rtw_mac_power_off(rtwdev); 14808c2ecf20Sopenharmony_ci} 14818c2ecf20Sopenharmony_ci 14828c2ecf20Sopenharmony_cistatic int rtw_chip_efuse_info_setup(struct rtw_dev *rtwdev) 14838c2ecf20Sopenharmony_ci{ 14848c2ecf20Sopenharmony_ci struct rtw_efuse *efuse = &rtwdev->efuse; 14858c2ecf20Sopenharmony_ci int ret; 14868c2ecf20Sopenharmony_ci 14878c2ecf20Sopenharmony_ci mutex_lock(&rtwdev->mutex); 14888c2ecf20Sopenharmony_ci 14898c2ecf20Sopenharmony_ci /* power on mac to read efuse */ 14908c2ecf20Sopenharmony_ci ret = rtw_chip_efuse_enable(rtwdev); 14918c2ecf20Sopenharmony_ci if (ret) 14928c2ecf20Sopenharmony_ci goto out_unlock; 14938c2ecf20Sopenharmony_ci 14948c2ecf20Sopenharmony_ci ret = rtw_parse_efuse_map(rtwdev); 14958c2ecf20Sopenharmony_ci if (ret) 14968c2ecf20Sopenharmony_ci goto out_disable; 14978c2ecf20Sopenharmony_ci 14988c2ecf20Sopenharmony_ci ret = rtw_dump_hw_feature(rtwdev); 14998c2ecf20Sopenharmony_ci if (ret) 15008c2ecf20Sopenharmony_ci goto out_disable; 15018c2ecf20Sopenharmony_ci 15028c2ecf20Sopenharmony_ci ret = rtw_check_supported_rfe(rtwdev); 15038c2ecf20Sopenharmony_ci if (ret) 15048c2ecf20Sopenharmony_ci goto out_disable; 15058c2ecf20Sopenharmony_ci 15068c2ecf20Sopenharmony_ci if (efuse->crystal_cap == 0xff) 15078c2ecf20Sopenharmony_ci efuse->crystal_cap = 0; 15088c2ecf20Sopenharmony_ci if (efuse->pa_type_2g == 0xff) 15098c2ecf20Sopenharmony_ci efuse->pa_type_2g = 0; 15108c2ecf20Sopenharmony_ci if (efuse->pa_type_5g == 0xff) 15118c2ecf20Sopenharmony_ci efuse->pa_type_5g = 0; 15128c2ecf20Sopenharmony_ci if (efuse->lna_type_2g == 0xff) 15138c2ecf20Sopenharmony_ci efuse->lna_type_2g = 0; 15148c2ecf20Sopenharmony_ci if (efuse->lna_type_5g == 0xff) 15158c2ecf20Sopenharmony_ci efuse->lna_type_5g = 0; 15168c2ecf20Sopenharmony_ci if (efuse->channel_plan == 0xff) 15178c2ecf20Sopenharmony_ci efuse->channel_plan = 0x7f; 15188c2ecf20Sopenharmony_ci if (efuse->rf_board_option == 0xff) 15198c2ecf20Sopenharmony_ci efuse->rf_board_option = 0; 15208c2ecf20Sopenharmony_ci if (efuse->bt_setting & BIT(0)) 15218c2ecf20Sopenharmony_ci efuse->share_ant = true; 15228c2ecf20Sopenharmony_ci if (efuse->regd == 0xff) 15238c2ecf20Sopenharmony_ci efuse->regd = 0; 15248c2ecf20Sopenharmony_ci if (efuse->tx_bb_swing_setting_2g == 0xff) 15258c2ecf20Sopenharmony_ci efuse->tx_bb_swing_setting_2g = 0; 15268c2ecf20Sopenharmony_ci if (efuse->tx_bb_swing_setting_5g == 0xff) 15278c2ecf20Sopenharmony_ci efuse->tx_bb_swing_setting_5g = 0; 15288c2ecf20Sopenharmony_ci 15298c2ecf20Sopenharmony_ci efuse->btcoex = (efuse->rf_board_option & 0xe0) == 0x20; 15308c2ecf20Sopenharmony_ci efuse->ext_pa_2g = efuse->pa_type_2g & BIT(4) ? 1 : 0; 15318c2ecf20Sopenharmony_ci efuse->ext_lna_2g = efuse->lna_type_2g & BIT(3) ? 1 : 0; 15328c2ecf20Sopenharmony_ci efuse->ext_pa_5g = efuse->pa_type_5g & BIT(0) ? 1 : 0; 15338c2ecf20Sopenharmony_ci efuse->ext_lna_2g = efuse->lna_type_5g & BIT(3) ? 1 : 0; 15348c2ecf20Sopenharmony_ci 15358c2ecf20Sopenharmony_ciout_disable: 15368c2ecf20Sopenharmony_ci rtw_chip_efuse_disable(rtwdev); 15378c2ecf20Sopenharmony_ci 15388c2ecf20Sopenharmony_ciout_unlock: 15398c2ecf20Sopenharmony_ci mutex_unlock(&rtwdev->mutex); 15408c2ecf20Sopenharmony_ci return ret; 15418c2ecf20Sopenharmony_ci} 15428c2ecf20Sopenharmony_ci 15438c2ecf20Sopenharmony_cistatic int rtw_chip_board_info_setup(struct rtw_dev *rtwdev) 15448c2ecf20Sopenharmony_ci{ 15458c2ecf20Sopenharmony_ci struct rtw_hal *hal = &rtwdev->hal; 15468c2ecf20Sopenharmony_ci const struct rtw_rfe_def *rfe_def = rtw_get_rfe_def(rtwdev); 15478c2ecf20Sopenharmony_ci 15488c2ecf20Sopenharmony_ci if (!rfe_def) 15498c2ecf20Sopenharmony_ci return -ENODEV; 15508c2ecf20Sopenharmony_ci 15518c2ecf20Sopenharmony_ci rtw_phy_setup_phy_cond(rtwdev, 0); 15528c2ecf20Sopenharmony_ci 15538c2ecf20Sopenharmony_ci rtw_phy_init_tx_power(rtwdev); 15548c2ecf20Sopenharmony_ci rtw_load_table(rtwdev, rfe_def->phy_pg_tbl); 15558c2ecf20Sopenharmony_ci rtw_load_table(rtwdev, rfe_def->txpwr_lmt_tbl); 15568c2ecf20Sopenharmony_ci rtw_phy_tx_power_by_rate_config(hal); 15578c2ecf20Sopenharmony_ci rtw_phy_tx_power_limit_config(hal); 15588c2ecf20Sopenharmony_ci 15598c2ecf20Sopenharmony_ci return 0; 15608c2ecf20Sopenharmony_ci} 15618c2ecf20Sopenharmony_ci 15628c2ecf20Sopenharmony_ciint rtw_chip_info_setup(struct rtw_dev *rtwdev) 15638c2ecf20Sopenharmony_ci{ 15648c2ecf20Sopenharmony_ci int ret; 15658c2ecf20Sopenharmony_ci 15668c2ecf20Sopenharmony_ci ret = rtw_chip_parameter_setup(rtwdev); 15678c2ecf20Sopenharmony_ci if (ret) { 15688c2ecf20Sopenharmony_ci rtw_err(rtwdev, "failed to setup chip parameters\n"); 15698c2ecf20Sopenharmony_ci goto err_out; 15708c2ecf20Sopenharmony_ci } 15718c2ecf20Sopenharmony_ci 15728c2ecf20Sopenharmony_ci ret = rtw_chip_efuse_info_setup(rtwdev); 15738c2ecf20Sopenharmony_ci if (ret) { 15748c2ecf20Sopenharmony_ci rtw_err(rtwdev, "failed to setup chip efuse info\n"); 15758c2ecf20Sopenharmony_ci goto err_out; 15768c2ecf20Sopenharmony_ci } 15778c2ecf20Sopenharmony_ci 15788c2ecf20Sopenharmony_ci ret = rtw_chip_board_info_setup(rtwdev); 15798c2ecf20Sopenharmony_ci if (ret) { 15808c2ecf20Sopenharmony_ci rtw_err(rtwdev, "failed to setup chip board info\n"); 15818c2ecf20Sopenharmony_ci goto err_out; 15828c2ecf20Sopenharmony_ci } 15838c2ecf20Sopenharmony_ci 15848c2ecf20Sopenharmony_ci return 0; 15858c2ecf20Sopenharmony_ci 15868c2ecf20Sopenharmony_cierr_out: 15878c2ecf20Sopenharmony_ci return ret; 15888c2ecf20Sopenharmony_ci} 15898c2ecf20Sopenharmony_ciEXPORT_SYMBOL(rtw_chip_info_setup); 15908c2ecf20Sopenharmony_ci 15918c2ecf20Sopenharmony_cistatic void rtw_stats_init(struct rtw_dev *rtwdev) 15928c2ecf20Sopenharmony_ci{ 15938c2ecf20Sopenharmony_ci struct rtw_traffic_stats *stats = &rtwdev->stats; 15948c2ecf20Sopenharmony_ci struct rtw_dm_info *dm_info = &rtwdev->dm_info; 15958c2ecf20Sopenharmony_ci int i; 15968c2ecf20Sopenharmony_ci 15978c2ecf20Sopenharmony_ci ewma_tp_init(&stats->tx_ewma_tp); 15988c2ecf20Sopenharmony_ci ewma_tp_init(&stats->rx_ewma_tp); 15998c2ecf20Sopenharmony_ci 16008c2ecf20Sopenharmony_ci for (i = 0; i < RTW_EVM_NUM; i++) 16018c2ecf20Sopenharmony_ci ewma_evm_init(&dm_info->ewma_evm[i]); 16028c2ecf20Sopenharmony_ci for (i = 0; i < RTW_SNR_NUM; i++) 16038c2ecf20Sopenharmony_ci ewma_snr_init(&dm_info->ewma_snr[i]); 16048c2ecf20Sopenharmony_ci} 16058c2ecf20Sopenharmony_ci 16068c2ecf20Sopenharmony_ciint rtw_core_init(struct rtw_dev *rtwdev) 16078c2ecf20Sopenharmony_ci{ 16088c2ecf20Sopenharmony_ci struct rtw_chip_info *chip = rtwdev->chip; 16098c2ecf20Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 16108c2ecf20Sopenharmony_ci int ret; 16118c2ecf20Sopenharmony_ci 16128c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&rtwdev->rsvd_page_list); 16138c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&rtwdev->txqs); 16148c2ecf20Sopenharmony_ci 16158c2ecf20Sopenharmony_ci timer_setup(&rtwdev->tx_report.purge_timer, 16168c2ecf20Sopenharmony_ci rtw_tx_report_purge_timer, 0); 16178c2ecf20Sopenharmony_ci tasklet_setup(&rtwdev->tx_tasklet, rtw_tx_tasklet); 16188c2ecf20Sopenharmony_ci 16198c2ecf20Sopenharmony_ci INIT_DELAYED_WORK(&rtwdev->watch_dog_work, rtw_watch_dog_work); 16208c2ecf20Sopenharmony_ci INIT_DELAYED_WORK(&coex->bt_relink_work, rtw_coex_bt_relink_work); 16218c2ecf20Sopenharmony_ci INIT_DELAYED_WORK(&coex->bt_reenable_work, rtw_coex_bt_reenable_work); 16228c2ecf20Sopenharmony_ci INIT_DELAYED_WORK(&coex->defreeze_work, rtw_coex_defreeze_work); 16238c2ecf20Sopenharmony_ci INIT_DELAYED_WORK(&coex->wl_remain_work, rtw_coex_wl_remain_work); 16248c2ecf20Sopenharmony_ci INIT_DELAYED_WORK(&coex->bt_remain_work, rtw_coex_bt_remain_work); 16258c2ecf20Sopenharmony_ci INIT_WORK(&rtwdev->c2h_work, rtw_c2h_work); 16268c2ecf20Sopenharmony_ci INIT_WORK(&rtwdev->fw_recovery_work, rtw_fw_recovery_work); 16278c2ecf20Sopenharmony_ci INIT_WORK(&rtwdev->ba_work, rtw_txq_ba_work); 16288c2ecf20Sopenharmony_ci skb_queue_head_init(&rtwdev->c2h_queue); 16298c2ecf20Sopenharmony_ci skb_queue_head_init(&rtwdev->coex.queue); 16308c2ecf20Sopenharmony_ci skb_queue_head_init(&rtwdev->tx_report.queue); 16318c2ecf20Sopenharmony_ci 16328c2ecf20Sopenharmony_ci spin_lock_init(&rtwdev->rf_lock); 16338c2ecf20Sopenharmony_ci spin_lock_init(&rtwdev->h2c.lock); 16348c2ecf20Sopenharmony_ci spin_lock_init(&rtwdev->txq_lock); 16358c2ecf20Sopenharmony_ci spin_lock_init(&rtwdev->tx_report.q_lock); 16368c2ecf20Sopenharmony_ci 16378c2ecf20Sopenharmony_ci mutex_init(&rtwdev->mutex); 16388c2ecf20Sopenharmony_ci mutex_init(&rtwdev->coex.mutex); 16398c2ecf20Sopenharmony_ci mutex_init(&rtwdev->hal.tx_power_mutex); 16408c2ecf20Sopenharmony_ci 16418c2ecf20Sopenharmony_ci init_waitqueue_head(&rtwdev->coex.wait); 16428c2ecf20Sopenharmony_ci 16438c2ecf20Sopenharmony_ci rtwdev->sec.total_cam_num = 32; 16448c2ecf20Sopenharmony_ci rtwdev->hal.current_channel = 1; 16458c2ecf20Sopenharmony_ci set_bit(RTW_BC_MC_MACID, rtwdev->mac_id_map); 16468c2ecf20Sopenharmony_ci if (!(BIT(rtw_fw_lps_deep_mode) & chip->lps_deep_mode_supported)) 16478c2ecf20Sopenharmony_ci rtwdev->lps_conf.deep_mode = LPS_DEEP_MODE_NONE; 16488c2ecf20Sopenharmony_ci else 16498c2ecf20Sopenharmony_ci rtwdev->lps_conf.deep_mode = rtw_fw_lps_deep_mode; 16508c2ecf20Sopenharmony_ci 16518c2ecf20Sopenharmony_ci rtw_stats_init(rtwdev); 16528c2ecf20Sopenharmony_ci 16538c2ecf20Sopenharmony_ci /* default rx filter setting */ 16548c2ecf20Sopenharmony_ci rtwdev->hal.rcr = BIT_APP_FCS | BIT_APP_MIC | BIT_APP_ICV | 16558c2ecf20Sopenharmony_ci BIT_PKTCTL_DLEN | BIT_HTC_LOC_CTRL | BIT_APP_PHYSTS | 16568c2ecf20Sopenharmony_ci BIT_AB | BIT_AM | BIT_APM; 16578c2ecf20Sopenharmony_ci 16588c2ecf20Sopenharmony_ci ret = rtw_load_firmware(rtwdev, RTW_NORMAL_FW); 16598c2ecf20Sopenharmony_ci if (ret) { 16608c2ecf20Sopenharmony_ci rtw_warn(rtwdev, "no firmware loaded\n"); 16618c2ecf20Sopenharmony_ci return ret; 16628c2ecf20Sopenharmony_ci } 16638c2ecf20Sopenharmony_ci 16648c2ecf20Sopenharmony_ci if (chip->wow_fw_name) { 16658c2ecf20Sopenharmony_ci ret = rtw_load_firmware(rtwdev, RTW_WOWLAN_FW); 16668c2ecf20Sopenharmony_ci if (ret) { 16678c2ecf20Sopenharmony_ci rtw_warn(rtwdev, "no wow firmware loaded\n"); 16688c2ecf20Sopenharmony_ci wait_for_completion(&rtwdev->fw.completion); 16698c2ecf20Sopenharmony_ci if (rtwdev->fw.firmware) 16708c2ecf20Sopenharmony_ci release_firmware(rtwdev->fw.firmware); 16718c2ecf20Sopenharmony_ci return ret; 16728c2ecf20Sopenharmony_ci } 16738c2ecf20Sopenharmony_ci } 16748c2ecf20Sopenharmony_ci return 0; 16758c2ecf20Sopenharmony_ci} 16768c2ecf20Sopenharmony_ciEXPORT_SYMBOL(rtw_core_init); 16778c2ecf20Sopenharmony_ci 16788c2ecf20Sopenharmony_civoid rtw_core_deinit(struct rtw_dev *rtwdev) 16798c2ecf20Sopenharmony_ci{ 16808c2ecf20Sopenharmony_ci struct rtw_fw_state *fw = &rtwdev->fw; 16818c2ecf20Sopenharmony_ci struct rtw_fw_state *wow_fw = &rtwdev->wow_fw; 16828c2ecf20Sopenharmony_ci struct rtw_rsvd_page *rsvd_pkt, *tmp; 16838c2ecf20Sopenharmony_ci unsigned long flags; 16848c2ecf20Sopenharmony_ci 16858c2ecf20Sopenharmony_ci rtw_wait_firmware_completion(rtwdev); 16868c2ecf20Sopenharmony_ci 16878c2ecf20Sopenharmony_ci if (fw->firmware) 16888c2ecf20Sopenharmony_ci release_firmware(fw->firmware); 16898c2ecf20Sopenharmony_ci 16908c2ecf20Sopenharmony_ci if (wow_fw->firmware) 16918c2ecf20Sopenharmony_ci release_firmware(wow_fw->firmware); 16928c2ecf20Sopenharmony_ci 16938c2ecf20Sopenharmony_ci tasklet_kill(&rtwdev->tx_tasklet); 16948c2ecf20Sopenharmony_ci spin_lock_irqsave(&rtwdev->tx_report.q_lock, flags); 16958c2ecf20Sopenharmony_ci skb_queue_purge(&rtwdev->tx_report.queue); 16968c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&rtwdev->tx_report.q_lock, flags); 16978c2ecf20Sopenharmony_ci 16988c2ecf20Sopenharmony_ci list_for_each_entry_safe(rsvd_pkt, tmp, &rtwdev->rsvd_page_list, 16998c2ecf20Sopenharmony_ci build_list) { 17008c2ecf20Sopenharmony_ci list_del(&rsvd_pkt->build_list); 17018c2ecf20Sopenharmony_ci kfree(rsvd_pkt); 17028c2ecf20Sopenharmony_ci } 17038c2ecf20Sopenharmony_ci 17048c2ecf20Sopenharmony_ci mutex_destroy(&rtwdev->mutex); 17058c2ecf20Sopenharmony_ci mutex_destroy(&rtwdev->coex.mutex); 17068c2ecf20Sopenharmony_ci mutex_destroy(&rtwdev->hal.tx_power_mutex); 17078c2ecf20Sopenharmony_ci} 17088c2ecf20Sopenharmony_ciEXPORT_SYMBOL(rtw_core_deinit); 17098c2ecf20Sopenharmony_ci 17108c2ecf20Sopenharmony_ciint rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw) 17118c2ecf20Sopenharmony_ci{ 17128c2ecf20Sopenharmony_ci struct rtw_hal *hal = &rtwdev->hal; 17138c2ecf20Sopenharmony_ci int max_tx_headroom = 0; 17148c2ecf20Sopenharmony_ci int ret; 17158c2ecf20Sopenharmony_ci 17168c2ecf20Sopenharmony_ci /* TODO: USB & SDIO may need extra room? */ 17178c2ecf20Sopenharmony_ci max_tx_headroom = rtwdev->chip->tx_pkt_desc_sz; 17188c2ecf20Sopenharmony_ci 17198c2ecf20Sopenharmony_ci hw->extra_tx_headroom = max_tx_headroom; 17208c2ecf20Sopenharmony_ci hw->queues = IEEE80211_NUM_ACS; 17218c2ecf20Sopenharmony_ci hw->txq_data_size = sizeof(struct rtw_txq); 17228c2ecf20Sopenharmony_ci hw->sta_data_size = sizeof(struct rtw_sta_info); 17238c2ecf20Sopenharmony_ci hw->vif_data_size = sizeof(struct rtw_vif); 17248c2ecf20Sopenharmony_ci 17258c2ecf20Sopenharmony_ci ieee80211_hw_set(hw, SIGNAL_DBM); 17268c2ecf20Sopenharmony_ci ieee80211_hw_set(hw, RX_INCLUDES_FCS); 17278c2ecf20Sopenharmony_ci ieee80211_hw_set(hw, AMPDU_AGGREGATION); 17288c2ecf20Sopenharmony_ci ieee80211_hw_set(hw, MFP_CAPABLE); 17298c2ecf20Sopenharmony_ci ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS); 17308c2ecf20Sopenharmony_ci ieee80211_hw_set(hw, SUPPORTS_PS); 17318c2ecf20Sopenharmony_ci ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS); 17328c2ecf20Sopenharmony_ci ieee80211_hw_set(hw, SUPPORT_FAST_XMIT); 17338c2ecf20Sopenharmony_ci ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU); 17348c2ecf20Sopenharmony_ci ieee80211_hw_set(hw, HAS_RATE_CONTROL); 17358c2ecf20Sopenharmony_ci ieee80211_hw_set(hw, TX_AMSDU); 17368c2ecf20Sopenharmony_ci 17378c2ecf20Sopenharmony_ci hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | 17388c2ecf20Sopenharmony_ci BIT(NL80211_IFTYPE_AP) | 17398c2ecf20Sopenharmony_ci BIT(NL80211_IFTYPE_ADHOC) | 17408c2ecf20Sopenharmony_ci BIT(NL80211_IFTYPE_MESH_POINT); 17418c2ecf20Sopenharmony_ci hw->wiphy->available_antennas_tx = hal->antenna_tx; 17428c2ecf20Sopenharmony_ci hw->wiphy->available_antennas_rx = hal->antenna_rx; 17438c2ecf20Sopenharmony_ci 17448c2ecf20Sopenharmony_ci hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS | 17458c2ecf20Sopenharmony_ci WIPHY_FLAG_TDLS_EXTERNAL_SETUP; 17468c2ecf20Sopenharmony_ci 17478c2ecf20Sopenharmony_ci hw->wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR; 17488c2ecf20Sopenharmony_ci 17498c2ecf20Sopenharmony_ci wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0); 17508c2ecf20Sopenharmony_ci 17518c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 17528c2ecf20Sopenharmony_ci hw->wiphy->wowlan = rtwdev->chip->wowlan_stub; 17538c2ecf20Sopenharmony_ci hw->wiphy->max_sched_scan_ssids = rtwdev->chip->max_sched_scan_ssids; 17548c2ecf20Sopenharmony_ci#endif 17558c2ecf20Sopenharmony_ci rtw_set_supported_band(hw, rtwdev->chip); 17568c2ecf20Sopenharmony_ci SET_IEEE80211_PERM_ADDR(hw, rtwdev->efuse.addr); 17578c2ecf20Sopenharmony_ci 17588c2ecf20Sopenharmony_ci rtw_regd_init(rtwdev, rtw_regd_notifier); 17598c2ecf20Sopenharmony_ci 17608c2ecf20Sopenharmony_ci ret = ieee80211_register_hw(hw); 17618c2ecf20Sopenharmony_ci if (ret) { 17628c2ecf20Sopenharmony_ci rtw_err(rtwdev, "failed to register hw\n"); 17638c2ecf20Sopenharmony_ci return ret; 17648c2ecf20Sopenharmony_ci } 17658c2ecf20Sopenharmony_ci 17668c2ecf20Sopenharmony_ci if (regulatory_hint(hw->wiphy, rtwdev->regd.alpha2)) 17678c2ecf20Sopenharmony_ci rtw_err(rtwdev, "regulatory_hint fail\n"); 17688c2ecf20Sopenharmony_ci 17698c2ecf20Sopenharmony_ci rtw_debugfs_init(rtwdev); 17708c2ecf20Sopenharmony_ci 17718c2ecf20Sopenharmony_ci rtwdev->bf_info.bfer_mu_cnt = 0; 17728c2ecf20Sopenharmony_ci rtwdev->bf_info.bfer_su_cnt = 0; 17738c2ecf20Sopenharmony_ci 17748c2ecf20Sopenharmony_ci return 0; 17758c2ecf20Sopenharmony_ci} 17768c2ecf20Sopenharmony_ciEXPORT_SYMBOL(rtw_register_hw); 17778c2ecf20Sopenharmony_ci 17788c2ecf20Sopenharmony_civoid rtw_unregister_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw) 17798c2ecf20Sopenharmony_ci{ 17808c2ecf20Sopenharmony_ci struct rtw_chip_info *chip = rtwdev->chip; 17818c2ecf20Sopenharmony_ci 17828c2ecf20Sopenharmony_ci ieee80211_unregister_hw(hw); 17838c2ecf20Sopenharmony_ci rtw_unset_supported_band(hw, chip); 17848c2ecf20Sopenharmony_ci} 17858c2ecf20Sopenharmony_ciEXPORT_SYMBOL(rtw_unregister_hw); 17868c2ecf20Sopenharmony_ci 17878c2ecf20Sopenharmony_ciMODULE_AUTHOR("Realtek Corporation"); 17888c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Realtek 802.11ac wireless core module"); 17898c2ecf20Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL"); 1790