diff --git a/Makefile b/Makefile index ba8dc3ed..5c41afe7 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause SHELL := /bin/sh KVER ?= $(shell uname -r) KSRC := /lib/modules/$(KVER)/build @@ -24,8 +25,8 @@ EXTRA_CFLAGS += -O2 EXTRA_CFLAGS += -DCONFIG_RTW89_DEBUGMSG EXTRA_CFLAGS += -DCONFIG_RTW89_DEBUGFS -obj-m += rtw89core.o -rtw89core-y += core.o \ +obj-m += rtw89_core.o +rtw89_core-y += core.o \ debug.o \ mac80211.o \ mac.o \ @@ -43,8 +44,8 @@ rtw89core-y += core.o \ sar.o \ ser.o -obj-m += rtw89pci.o -rtw89pci-y := pci.o +obj-m += rtw89_pci.o +rtw89_pci-y := pci.o ccflags-y += -D__CHECK_ENDIAN__ @@ -86,7 +87,7 @@ clean: @rm -fr modules.order sign: - kmodsign sha512 $(MOK_KEY_DIR)/MOK.priv $(MOK_KEY_DIR)/MOK.der rtw89core.ko - kmodsign sha512 $(MOK_KEY_DIR)/MOK.priv $(MOK_KEY_DIR)/MOK.der rtw89pci.ko + kmodsign sha512 $(MOK_KEY_DIR)/MOK.priv $(MOK_KEY_DIR)/MOK.der rtw89_core.ko + kmodsign sha512 $(MOK_KEY_DIR)/MOK.priv $(MOK_KEY_DIR)/MOK.der rtw89_pci.ko sign-install: all sign install diff --git a/cam.c b/cam.c index 66ff607a..c1e8c76c 100644 --- a/cam.c +++ b/cam.c @@ -348,15 +348,8 @@ int rtw89_cam_sec_key_add(struct rtw89_dev *rtwdev, key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; ext_key = true; break; - case WLAN_CIPHER_SUITE_TKIP: - case WLAN_CIPHER_SUITE_AES_CMAC: - case WLAN_CIPHER_SUITE_BIP_CMAC_256: - case WLAN_CIPHER_SUITE_BIP_GMAC_128: - case WLAN_CIPHER_SUITE_BIP_GMAC_256: - /* suppress error messages */ - return -EOPNOTSUPP; default: - return -ENOTSUPP; + return -EOPNOTSUPP; } key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; @@ -394,8 +387,9 @@ int rtw89_cam_sec_key_del(struct rtw89_dev *rtwdev, rtwvif = (struct rtw89_vif *)vif->drv_priv; addr_cam = &rtwvif->addr_cam; sec_cam = addr_cam->sec_entries[key_idx]; - if (!sec_cam || !sec_cam->sec_cam_idx) + if (!sec_cam) return -EINVAL; + /* detach sec cam from addr cam */ clear_bit(key_idx, addr_cam->sec_cam_map); addr_cam->sec_entries[key_idx] = NULL; @@ -578,15 +572,9 @@ int rtw89_cam_init(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) int rtw89_cam_fill_bssid_cam_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, u8 *cmd) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0) struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); -#endif struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif->bssid_cam; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0) u8 bss_color = vif->bss_conf.he_bss_color.color; -#else - u8 bss_color = 0; -#endif FWCMD_SET_ADDR_BSSID_IDX(cmd, bssid_cam->bssid_cam_idx); FWCMD_SET_ADDR_BSSID_OFFSET(cmd, bssid_cam->offset); diff --git a/coex.c b/coex.c index 34117acf..abe4b654 100644 --- a/coex.c +++ b/coex.c @@ -786,9 +786,7 @@ struct rtw89_btc_fbtc_cysta_cpu { u32 skip_cnt; u32 exception; u32 except_cnt; -#if (FCXCYSTA_VER > 1) u16 tslot_cycle[BTC_CYCLE_SLOT_MAX]; -#endif }; static void rtw89_btc_fbtc_cysta_to_cpu(const struct rtw89_btc_fbtc_cysta *src, @@ -826,9 +824,7 @@ static void rtw89_btc_fbtc_cysta_to_cpu(const struct rtw89_btc_fbtc_cysta *src, __CPY_LE32(skip_cnt); __CPY_LE32(exception); __CPY_LE32(except_cnt); -#if (FCXCYSTA_VER > 1) __CPY_LE16S(tslot_cycle); -#endif #undef __CPY_U8 #undef __CPY_LE16 @@ -1004,12 +1000,12 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev, return 0; } - memcpy((void *)pfinfo, (void *)rpt_content, pcinfo->req_len); + memcpy(pfinfo, rpt_content, pcinfo->req_len); pcinfo->valid = 1; if (rpt_type == BTC_RPT_TYPE_TDMA) { rtw89_debug(rtwdev, RTW89_DBG_BTC, - "[BTC], %s(): check %d %ld\n", __func__, + "[BTC], %s(): check %d %zu\n", __func__, BTC_DCNT_TDMA_NONSYNC, sizeof(dm->tdma_now)); if (memcmp(&dm->tdma_now, &pfwinfo->rpt_fbtc_tdma.finfo, @@ -1043,7 +1039,7 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev, if (rpt_type == BTC_RPT_TYPE_SLOT) { rtw89_debug(rtwdev, RTW89_DBG_BTC, - "[BTC], %s(): check %d %ld\n", + "[BTC], %s(): check %d %zu\n", __func__, BTC_DCNT_SLOT_NONSYNC, sizeof(dm->slot_now)); @@ -1299,7 +1295,7 @@ static void btc_fw_set_monreg(struct rtw89_dev *rtwdev) monreg->fver = BTF_SET_MON_REG_VER; monreg->reg_num = n; ptr = &monreg->buf[0]; - memcpy((void *)ptr, chip->mon_reg, n * ulen); + memcpy(ptr, chip->mon_reg, n * ulen); rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): sz=%d ulen=%d n=%d\n", __func__, sz, ulen, n); @@ -1497,8 +1493,6 @@ static void _set_wl_tx_power(struct rtw89_dev *rtwdev, u32 level) chip->ops->btc_set_wl_txpwr_ctrl(rtwdev, pwr_val); } -#define rtw89_btc_wl_rx_gain(rtwdev, level) do {} while (0) - static void _set_wl_rx_gain(struct rtw89_dev *rtwdev, u32 level) { struct rtw89_btc *btc = &rtwdev->btc; @@ -1513,15 +1507,13 @@ static void _set_wl_rx_gain(struct rtw89_dev *rtwdev, u32 level) rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): level = %d\n", __func__, level); - - rtw89_btc_wl_rx_gain(rtwdev, level); } static void _set_bt_tx_power(struct rtw89_dev *rtwdev, u8 level) { struct rtw89_btc *btc = &rtwdev->btc; struct rtw89_btc_bt_info *bt = &btc->cx.bt; - u8 buf = 0; + u8 buf; if (bt->rf_para.tx_pwr_freerun == level) return; @@ -1692,11 +1684,7 @@ static void _set_bt_afh_info(struct rtw89_dev *rtwdev) switch (bw) { case RTW89_CHANNEL_WIDTH_20: -#ifdef BTC_NON_SHARED_ANT_FREERUN - bw = 48; -#else bw = 20 + chip->afh_guard_ch * 2; -#endif break; case RTW89_CHANNEL_WIDTH_40: bw = 40 + chip->afh_guard_ch * 2; @@ -2922,8 +2910,6 @@ static void _set_wl_tx_limit(struct rtw89_dev *rtwdev) &data); } -#define _set_bt_slot_req(rtwdev) do {} while (0) - static void _set_bt_rx_agc(struct rtw89_dev *rtwdev) { struct rtw89_btc *btc = &rtwdev->btc; @@ -2948,7 +2934,6 @@ static void _action_common(struct rtw89_dev *rtwdev) _set_wl_tx_limit(rtwdev); _set_bt_afh_info(rtwdev); _set_bt_rx_agc(rtwdev); - _set_bt_slot_req(rtwdev); _set_rf_trx_para(rtwdev); } @@ -3547,8 +3532,6 @@ static bool _chk_wl_rfk_request(struct rtw89_dev *rtwdev) return false; } -#define _get_wl_nhm_dbm(rtwdev) do {} while (0) - static void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason) { @@ -3568,7 +3551,6 @@ void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason) dm->run_reason = reason; _update_dm_step(rtwdev, reason); _update_btc_state_map(rtwdev); - _get_wl_nhm_dbm(rtwdev); /* Be careful to change the following function sequence!! */ if (btc->ctrl.manual) { @@ -3902,6 +3884,10 @@ void rtw89_btc_ntfy_specific_packet(struct rtw89_dev *rtwdev, rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): ARP cnt=%d\n", __func__, cnt); return; + case PACKET_ICMP: + rtw89_debug(rtwdev, RTW89_DBG_BTC, + "[BTC], %s(): ICMP pkt\n", __func__); + return; default: rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): unknown packet type %d\n", @@ -3951,6 +3937,17 @@ void rtw89_btc_ntfy_dhcp_packet_work(struct work_struct *work) mutex_unlock(&rtwdev->mutex); } +void rtw89_btc_ntfy_icmp_packet_work(struct work_struct *work) +{ + struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, + btc.icmp_notify_work); + + mutex_lock(&rtwdev->mutex); + rtw89_leave_ps_mode(rtwdev); + rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ICMP); + mutex_unlock(&rtwdev->mutex); +} + static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len) { const struct rtw89_chip_info *chip = rtwdev->chip; @@ -3991,7 +3988,7 @@ static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len) b->profile_cnt.now = 0; hid->type = 0; - /* ======= parse raw info low-Byte2 ======= */ + /* parse raw info low-Byte2 */ btinfo.val = bt->raw_info[BTC_BTINFO_L2]; b->status.map.connect = btinfo.lb2.connect; b->status.map.sco_busy = btinfo.lb2.sco_busy; @@ -4008,7 +4005,7 @@ static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len) b->profile_cnt.now += (u8)a2dp->exist; pan->active = btinfo.lb2.pan; - /* ======= parse raw info low-Byte3 ======= */ + /* parse raw info low-Byte3 */ btinfo.val = bt->raw_info[BTC_BTINFO_L3]; if (btinfo.lb3.retry != 0) cx->cnt_bt[BTC_BCNT_RETRY]++; @@ -4019,12 +4016,12 @@ static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len) bt->pag = btinfo.lb3.pag; b->status.map.mesh_busy = btinfo.lb3.mesh_busy; - /* ======= parse raw info high-Byte0 ======= */ + /* parse raw info high-Byte0 */ btinfo.val = bt->raw_info[BTC_BTINFO_H0]; /* raw val is dBm unit, translate from -100~ 0dBm to 0~100%*/ b->rssi = chip->ops->btc_get_bt_rssi(rtwdev, btinfo.hb0.rssi); - /* ======= parse raw info high-Byte1 ======= */ + /* parse raw info high-Byte1 */ btinfo.val = bt->raw_info[BTC_BTINFO_H1]; b->status.map.ble_connect = btinfo.hb1.ble_connect; if (btinfo.hb1.ble_connect) @@ -4048,7 +4045,7 @@ static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len) b->multi_link.now = btinfo.hb1.multi_link; - /* ======= parse raw info high-Byte2 ======= */ + /* parse raw info high-Byte2 */ btinfo.val = bt->raw_info[BTC_BTINFO_H2]; pan->exist = btinfo.hb2.pan_active; b->profile_cnt.now += (u8)pan->exist; @@ -4061,7 +4058,7 @@ static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len) hid->pair_cnt = btinfo.hb2.hid_cnt; hid->type |= (hid->slot_info == BTC_HID_218 ? BTC_HID_218 : BTC_HID_418); - /* ======= parse raw info high-Byte3 ======= */ + /* parse raw info high-Byte3 */ btinfo.val = bt->raw_info[BTC_BTINFO_H3]; a2dp->bitpool = btinfo.hb3.a2dp_bitpool; @@ -4447,7 +4444,7 @@ static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta) #define BTC_NHM_CHK_INTVL 20 -static void _ntfy_wl_sta(struct rtw89_dev *rtwdev) +void rtw89_btc_ntfy_wl_sta(struct rtw89_dev *rtwdev) { struct rtw89_btc *btc = &rtwdev->btc; struct rtw89_btc_wl_info *wl = &btc->cx.wl; @@ -4481,7 +4478,6 @@ static void _ntfy_wl_sta(struct rtw89_dev *rtwdev) _run_coex(rtwdev, BTC_RSN_NTFY_WL_STA); } else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] >= btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] + BTC_NHM_CHK_INTVL) { - _get_wl_nhm_dbm(rtwdev); btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] = btc->dm.cnt_notify[BTC_NCNT_WL_STA]; } else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] < @@ -4491,37 +4487,18 @@ static void _ntfy_wl_sta(struct rtw89_dev *rtwdev) } } -void rtw89_btc_ntfy_wl_sta_work(struct work_struct *work) -{ - struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, - btc.wl_sta_notify_work); - - mutex_lock(&rtwdev->mutex); - rtw89_leave_ps_mode(rtwdev); - _ntfy_wl_sta(rtwdev); - mutex_unlock(&rtwdev->mutex); -} - -#define _update_bt_psd(rtwdev, buf, len) do {} while (0) -#define _update_offload_runinfo(rtwdev, buf, len) do {} while (0) - void rtw89_btc_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb, u32 len, u8 class, u8 func) { - /* The below is just sample code. Don't use magic number in your release - * version. - */ struct rtw89_btc *btc = &rtwdev->btc; struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; - - /* note: 'len' includes header, so 'buf' length is 'len - 8' */ - u8 *buf = &skb->data[8]; /* size of C2H header is 8 */ + u8 *buf = &skb->data[RTW89_C2H_HEADER_LEN]; rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): C2H BT len:%d class:%d fun:%d\n", __func__, len, class, func); - if (class != 0x12) + if (class != BTFC_FW_EVENT) return; switch (func) { @@ -4546,12 +4523,11 @@ void rtw89_btc_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb, _update_bt_scbd(rtwdev, false); break; case BTF_EVNT_BT_PSD: - _update_bt_psd(rtwdev, buf, len); break; case BTF_EVNT_BT_REG: btc->dbg.rb_done = true; - btc->dbg.rb_val = ((buf[3] << 24) | (buf[2] << 16) | - (buf[1] << 8) | (buf[0])); + btc->dbg.rb_val = le32_to_cpu(*((__le32 *)buf)); + break; case BTF_EVNT_C2H_LOOPBACK: btc->dbg.rb_done = true; @@ -4559,8 +4535,8 @@ void rtw89_btc_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb, break; case BTF_EVNT_CX_RUNINFO: btc->dm.cnt_dm[BTC_DCNT_CX_RUNINFO]++; - _update_offload_runinfo(rtwdev, buf, len); - break; } + break; + } } #define BTC_CX_FW_OFFLOAD 0 @@ -4730,8 +4706,6 @@ static void _show_wl_info(struct rtw89_dev *rtwdev, struct seq_file *m) _show_wl_role_info(rtwdev, m); } -#define _get_bt_polt_cnt(rtwdev, phy, polt_cnt) do {} while (0) - enum btc_bt_a2dp_type { BTC_A2DP_LEGACY = 0, BTC_A2DP_TWS_SNIFF = 1, @@ -4880,7 +4854,6 @@ static void _show_bt_info(struct rtw89_dev *rtwdev, struct seq_file *m) chip->ops->btc_update_bt_cnt(rtwdev); _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_FREEZE, 0); - _get_bt_polt_cnt(rtwdev, RTW89_PHY_0, &polt_cnt); seq_printf(m, " %-15s : Hi-rx = %d, Hi-tx = %d, Lo-rx = %d, Lo-tx = %d (bt_polut_wl_tx = %d)\n", diff --git a/coex.h b/coex.h index f180db24..4b4565d1 100644 --- a/coex.h +++ b/coex.h @@ -30,7 +30,7 @@ enum btc_wl_rfk_type { #define RTW89_COEX_ACT1_WORK_PERIOD round_jiffies_relative(HZ * 4) #define RTW89_COEX_BT_DEVINFO_WORK_PERIOD round_jiffies_relative(HZ * 16) -#define RTW89_COEX_RFK_CHK_WORK_PERIOD round_jiffies_relative(HZ * 0.3) +#define RTW89_COEX_RFK_CHK_WORK_PERIOD msecs_to_jiffies(300) #define BTC_RFK_PATH_MAP GENMASK(3, 0) #define BTC_RFK_PHY_MAP GENMASK(5, 4) #define BTC_RFK_BAND_MAP GENMASK(7, 6) @@ -102,6 +102,7 @@ enum btc_pkt_type { PACKET_ARP, PACKET_EAPOL, PACKET_EAPOL_END, + PACKET_ICMP, PACKET_MAX }; @@ -140,13 +141,14 @@ void rtw89_btc_ntfy_specific_packet(struct rtw89_dev *rtwdev, void rtw89_btc_ntfy_eapol_packet_work(struct work_struct *work); void rtw89_btc_ntfy_arp_packet_work(struct work_struct *work); void rtw89_btc_ntfy_dhcp_packet_work(struct work_struct *work); +void rtw89_btc_ntfy_icmp_packet_work(struct work_struct *work); void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, struct rtw89_sta *rtwsta, enum btc_role_state state); void rtw89_btc_ntfy_radio_state(struct rtw89_dev *rtwdev, enum btc_rfctrl rf_state); void rtw89_btc_ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_map, enum btc_wl_rfk_type type, enum btc_wl_rfk_state state); -void rtw89_btc_ntfy_wl_sta_work(struct work_struct *work); +void rtw89_btc_ntfy_wl_sta(struct rtw89_dev *rtwdev); void rtw89_btc_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb, u32 len, u8 class, u8 func); void rtw89_btc_dump_info(struct rtw89_dev *rtwdev, struct seq_file *m); diff --git a/core.c b/core.c index 68645240..06fb6e5b 100644 --- a/core.c +++ b/core.c @@ -544,6 +544,10 @@ static void rtw89_core_tx_update_data_info(struct rtw89_dev *rtwdev, struct rtw89_core_tx_request *tx_req) { + struct ieee80211_vif *vif = tx_req->vif; + struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct rtw89_phy_rate_pattern *rate_pattern = &rtwvif->rate_pattern; + struct rtw89_hal *hal = &rtwdev->hal; struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info; struct sk_buff *skb = tx_req->skb; u8 tid, tid_indicate; @@ -565,6 +569,13 @@ rtw89_core_tx_update_data_info(struct rtw89_dev *rtwdev, rtw89_core_tx_update_ampdu_info(rtwdev, tx_req, tid); if (IEEE80211_SKB_CB(skb)->control.hw_key) rtw89_core_tx_update_sec_key(rtwdev, tx_req); + + if (rate_pattern->enable) + desc_info->data_retry_lowest_rate = rate_pattern->rate; + else if (hal->current_band_type == RTW89_BAND_2G) + desc_info->data_retry_lowest_rate = RTW89_HW_RATE_CCK1; + else + desc_info->data_retry_lowest_rate = RTW89_HW_RATE_OFDM6; } static enum btc_pkt_type @@ -595,6 +606,12 @@ rtw89_core_tx_btc_spec_pkt_notify(struct rtw89_dev *rtwdev, } } + if (skb->protocol == htons(ETH_P_IP) && + ip_hdr(skb)->protocol == IPPROTO_ICMP) { + ieee80211_queue_work(rtwdev->hw, &rtwdev->btc.icmp_notify_work); + return PACKET_ICMP; + } + return PACKET_MAX; } @@ -706,38 +723,93 @@ int rtw89_core_tx_write(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, return 0; } +static __le32 rtw89_build_txwd_body0(struct rtw89_tx_desc_info *desc_info) +{ + u32 dword = FIELD_PREP(RTW89_TXWD_BODY0_WP_OFFSET, desc_info->wp_offset) | + FIELD_PREP(RTW89_TXWD_BODY0_WD_INFO_EN, desc_info->en_wd_info) | + FIELD_PREP(RTW89_TXWD_BODY0_CHANNEL_DMA, desc_info->ch_dma) | + FIELD_PREP(RTW89_TXWD_BODY0_HDR_LLC_LEN, desc_info->hdr_llc_len) | + FIELD_PREP(RTW89_TXWD_BODY0_WD_PAGE, desc_info->wd_page) | + FIELD_PREP(RTW89_TXWD_BODY0_FW_DL, desc_info->fw_dl); + + return cpu_to_le32(dword); +} + +static __le32 rtw89_build_txwd_body2(struct rtw89_tx_desc_info *desc_info) +{ + u32 dword = FIELD_PREP(RTW89_TXWD_BODY2_TID_INDICATE, desc_info->tid_indicate) | + FIELD_PREP(RTW89_TXWD_BODY2_QSEL, desc_info->qsel) | + FIELD_PREP(RTW89_TXWD_BODY2_TXPKT_SIZE, desc_info->pkt_size); + + return cpu_to_le32(dword); +} + +static __le32 rtw89_build_txwd_body3(struct rtw89_tx_desc_info *desc_info) +{ + u32 dword = FIELD_PREP(RTW89_TXWD_BODY3_SW_SEQ, desc_info->seq) | + FIELD_PREP(RTW89_TXWD_BODY3_AGG_EN, desc_info->agg_en) | + FIELD_PREP(RTW89_TXWD_BODY3_BK, desc_info->bk); + + return cpu_to_le32(dword); +} + +static __le32 rtw89_build_txwd_info0(struct rtw89_tx_desc_info *desc_info) +{ + u32 dword = FIELD_PREP(RTW89_TXWD_INFO0_USE_RATE, desc_info->use_rate) | + FIELD_PREP(RTW89_TXWD_INFO0_DATA_RATE, desc_info->data_rate) | + FIELD_PREP(RTW89_TXWD_INFO0_DISDATAFB, desc_info->dis_data_fb); + + return cpu_to_le32(dword); +} + +static __le32 rtw89_build_txwd_info1(struct rtw89_tx_desc_info *desc_info) +{ + u32 dword = FIELD_PREP(RTW89_TXWD_INFO1_MAX_AGGNUM, desc_info->ampdu_num) | + FIELD_PREP(RTW89_TXWD_INFO1_A_CTRL_BSR, desc_info->a_ctrl_bsr) | + FIELD_PREP(RTW89_TXWD_INFO1_DATA_RTY_LOWEST_RATE, + desc_info->data_retry_lowest_rate); + + return cpu_to_le32(dword); +} + +static __le32 rtw89_build_txwd_info2(struct rtw89_tx_desc_info *desc_info) +{ + u32 dword = FIELD_PREP(RTW89_TXWD_INFO2_AMPDU_DENSITY, desc_info->ampdu_density) | + FIELD_PREP(RTW89_TXWD_INFO2_SEC_TYPE, desc_info->sec_type) | + FIELD_PREP(RTW89_TXWD_INFO2_SEC_HW_ENC, desc_info->sec_en) | + FIELD_PREP(RTW89_TXWD_INFO2_SEC_CAM_IDX, desc_info->sec_cam_idx); + + return cpu_to_le32(dword); +} + +static __le32 rtw89_build_txwd_info4(struct rtw89_tx_desc_info *desc_info) +{ + u32 dword = FIELD_PREP(RTW89_TXWD_INFO4_RTS_EN, 1) | + FIELD_PREP(RTW89_TXWD_INFO4_HW_RTS_EN, 1); + + return cpu_to_le32(dword); +} + void rtw89_core_fill_txdesc(struct rtw89_dev *rtwdev, struct rtw89_tx_desc_info *desc_info, void *txdesc) { - RTW89_SET_TXWD_BODY_WP_OFFSET(txdesc, desc_info->wp_offset); - RTW89_SET_TXWD_BODY_WD_INFO_EN(txdesc, desc_info->en_wd_info); - RTW89_SET_TXWD_BODY_CHANNEL_DMA(txdesc, desc_info->ch_dma); - RTW89_SET_TXWD_BODY_HDR_LLC_LEN(txdesc, desc_info->hdr_llc_len); - RTW89_SET_TXWD_BODY_WD_PAGE(txdesc, desc_info->wd_page); - RTW89_SET_TXWD_BODY_FW_DL(txdesc, desc_info->fw_dl); - RTW89_SET_TXWD_BODY_SW_SEQ(txdesc, desc_info->seq); + struct rtw89_txwd_body *txwd_body = (struct rtw89_txwd_body *)txdesc; + struct rtw89_txwd_info *txwd_info; - RTW89_SET_TXWD_BODY_TID_INDICATE(txdesc, desc_info->tid_indicate); - RTW89_SET_TXWD_BODY_QSEL(txdesc, desc_info->qsel); - RTW89_SET_TXWD_BODY_TXPKT_SIZE(txdesc, desc_info->pkt_size); - RTW89_SET_TXWD_BODY_AGG_EN(txdesc, desc_info->agg_en); - RTW89_SET_TXWD_BODY_BK(txdesc, desc_info->bk); + txwd_body->dword0 = rtw89_build_txwd_body0(desc_info); + txwd_body->dword2 = rtw89_build_txwd_body2(desc_info); + txwd_body->dword3 = rtw89_build_txwd_body3(desc_info); if (!desc_info->en_wd_info) return; - RTW89_SET_TXWD_INFO_USE_RATE(txdesc, desc_info->use_rate); - RTW89_SET_TXWD_INFO_DATA_RATE(txdesc, desc_info->data_rate); - RTW89_SET_TXWD_INFO_DISDATAFB(txdesc, desc_info->dis_data_fb); - RTW89_SET_TXWD_INFO_MAX_AGGNUM(txdesc, desc_info->ampdu_num); - RTW89_SET_TXWD_INFO_AMPDU_DENSITY(txdesc, desc_info->ampdu_density); - RTW89_SET_TXWD_INFO_SEC_TYPE(txdesc, desc_info->sec_type); - RTW89_SET_TXWD_INFO_SEC_HW_ENC(txdesc, desc_info->sec_en); - RTW89_SET_TXWD_INFO_SEC_CAM_IDX(txdesc, desc_info->sec_cam_idx); - RTW89_SET_TXWD_INFO_RTS_EN(txdesc, 1); - RTW89_SET_TXWD_INFO_HW_RTS_EN(txdesc, 1); - RTW89_SET_TXWD_INFO_A_CTRL_BSR(txdesc, desc_info->a_ctrl_bsr); + txwd_info = (struct rtw89_txwd_info *)(txwd_body + 1); + txwd_info->dword0 = rtw89_build_txwd_info0(desc_info); + txwd_info->dword1 = rtw89_build_txwd_info1(desc_info); + txwd_info->dword2 = rtw89_build_txwd_info2(desc_info); + txwd_info->dword4 = rtw89_build_txwd_info4(desc_info); + } EXPORT_SYMBOL(rtw89_core_fill_txdesc); @@ -1583,10 +1655,8 @@ static bool rtw89_traffic_stats_calc(struct rtw89_dev *rtwdev, stats->tx_cnt = 0; stats->rx_cnt = 0; - if (tx_tfc_lv != stats->tx_tfc_lv || rx_tfc_lv != stats->rx_tfc_lv) { - ieee80211_queue_work(rtwdev->hw, &rtwdev->btc.wl_sta_notify_work); + if (tx_tfc_lv != stats->tx_tfc_lv || rx_tfc_lv != stats->rx_tfc_lv) return true; - } return false; } @@ -1652,8 +1722,10 @@ static void rtw89_track_work(struct work_struct *work) rtw89_leave_lps(rtwdev); - if (tfc_changed) + if (tfc_changed) { rtw89_hci_recalc_int_mit(rtwdev); + rtw89_btc_ntfy_wl_sta(rtwdev); + } rtw89_mac_bf_monitor_track(rtwdev); rtw89_phy_stat_track(rtwdev); rtw89_phy_env_monitor_track(rtwdev); @@ -2002,19 +2074,11 @@ static void rtw89_init_he_cap(struct rtw89_dev *rtwdev, mac_cap_info[1] = IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US; mac_cap_info[2] = IEEE80211_HE_MAC_CAP2_ALL_ACK | IEEE80211_HE_MAC_CAP2_BSR; -#if LINUX_VERSION_CODE < KERNEL_VERSION(5,13,0) - mac_cap_info[3] = IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_VHT_2; -#else mac_cap_info[3] = IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_2; -#endif if (i == NL80211_IFTYPE_AP) mac_cap_info[3] |= IEEE80211_HE_MAC_CAP3_OMI_CONTROL; mac_cap_info[4] = IEEE80211_HE_MAC_CAP4_OPS | -#if LINUX_VERSION_CODE < KERNEL_VERSION(5,13,0) - IEEE80211_HE_MAC_CAP4_AMDSU_IN_AMPDU; -#else IEEE80211_HE_MAC_CAP4_AMSDU_IN_AMPDU; -#endif if (i == NL80211_IFTYPE_STATION) mac_cap_info[5] = IEEE80211_HE_MAC_CAP5_HT_VHT_TRIG_FRAME_RX; phy_cap_info[0] = IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G | @@ -2026,24 +2090,12 @@ static void rtw89_init_he_cap(struct rtw89_dev *rtwdev, IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ | IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ | IEEE80211_HE_PHY_CAP2_DOPPLER_TX; -#if LINUX_VERSION_CODE < KERNEL_VERSION(5,13,0) - phy_cap_info[3] = IEEE80211_HE_PHY_CAP3_RX_HE_MU_PPDU_FROM_NON_AP_STA; -#else phy_cap_info[3] = IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM; -#endif if (i == NL80211_IFTYPE_STATION) -#if LINUX_VERSION_CODE < KERNEL_VERSION(5,13,0) - phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_RX_HE_MU_PPDU_FROM_NON_AP_STA; -#else phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_16_QAM | -#endif IEEE80211_HE_PHY_CAP3_DCM_MAX_TX_NSS_2; if (i == NL80211_IFTYPE_AP) -#if LINUX_VERSION_CODE < KERNEL_VERSION(5,13,0) - phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_RX_HE_MU_PPDU_FROM_NON_AP_STA; -#else phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_RX_PARTIAL_BW_SU_IN_20MHZ_MU; -#endif phy_cap_info[4] = IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE | IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4; phy_cap_info[5] = no_ng16 ? 0 : @@ -2051,17 +2103,9 @@ static void rtw89_init_he_cap(struct rtw89_dev *rtwdev, IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK; phy_cap_info[6] = IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU | IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU | -#if LINUX_VERSION_CODE < KERNEL_VERSION(5,13,0) - IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB | -#else IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMING_FB | -#endif IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE; -#if LINUX_VERSION_CODE < KERNEL_VERSION(5,13,0) - phy_cap_info[7] = IEEE80211_HE_PHY_CAP7_POWER_BOOST_FACTOR_AR | -#else phy_cap_info[7] = IEEE80211_HE_PHY_CAP7_POWER_BOOST_FACTOR_SUPP | -#endif IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI | IEEE80211_HE_PHY_CAP7_MAX_NC_1; phy_cap_info[8] = IEEE80211_HE_PHY_CAP8_HE_ER_SU_PPDU_4XLTF_AND_08_US_GI | @@ -2204,7 +2248,7 @@ void rtw89_core_stop(struct rtw89_dev *rtwdev) cancel_work_sync(&btc->eapol_notify_work); cancel_work_sync(&btc->arp_notify_work); cancel_work_sync(&btc->dhcp_notify_work); - cancel_work_sync(&btc->wl_sta_notify_work); + cancel_work_sync(&btc->icmp_notify_work); cancel_delayed_work_sync(&rtwdev->txq_reinvoke_work); cancel_delayed_work_sync(&rtwdev->track_work); cancel_delayed_work_sync(&rtwdev->coex_act1_work); @@ -2230,6 +2274,7 @@ int rtw89_core_init(struct rtw89_dev *rtwdev) INIT_LIST_HEAD(&rtwdev->ba_list); INIT_LIST_HEAD(&rtwdev->rtwvifs_list); + INIT_LIST_HEAD(&rtwdev->early_h2c_list); INIT_WORK(&rtwdev->ba_work, rtw89_core_ba_work); INIT_WORK(&rtwdev->txq_work, rtw89_core_txq_work); INIT_DELAYED_WORK(&rtwdev->txq_reinvoke_work, rtw89_core_txq_reinvoke_work); @@ -2255,7 +2300,7 @@ int rtw89_core_init(struct rtw89_dev *rtwdev) INIT_WORK(&btc->eapol_notify_work, rtw89_btc_ntfy_eapol_packet_work); INIT_WORK(&btc->arp_notify_work, rtw89_btc_ntfy_arp_packet_work); INIT_WORK(&btc->dhcp_notify_work, rtw89_btc_ntfy_dhcp_packet_work); - INIT_WORK(&btc->wl_sta_notify_work, rtw89_btc_ntfy_wl_sta_work); + INIT_WORK(&btc->icmp_notify_work, rtw89_btc_ntfy_icmp_packet_work); ret = rtw89_load_firmware(rtwdev); if (ret) { @@ -2272,6 +2317,7 @@ void rtw89_core_deinit(struct rtw89_dev *rtwdev) { rtw89_ser_deinit(rtwdev); rtw89_unload_firmware(rtwdev); + rtw89_fw_free_all_early_h2c(rtwdev); destroy_workqueue(rtwdev->txq_wq); mutex_destroy(&rtwdev->rf_mutex); @@ -2401,9 +2447,8 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev) } hw->wiphy->reg_notifier = rtw89_regd_notifier; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) hw->wiphy->sar_capa = &rtw89_sar_capa; -#endif + ret = ieee80211_register_hw(hw); if (ret) { rtw89_err(rtwdev, "failed to register hw\n"); diff --git a/core.h b/core.h index 4845eb62..c2885e4d 100644 --- a/core.h +++ b/core.h @@ -5,7 +5,6 @@ #ifndef __RTW89_CORE_H__ #define __RTW89_CORE_H__ -#include #include #include #include @@ -686,6 +685,7 @@ struct rtw89_tx_desc_info { u8 sec_type; u8 sec_cam_idx; u16 data_rate; + u16 data_retry_lowest_rate; bool fw_dl; u16 seq; bool a_ctrl_bsr; @@ -1454,9 +1454,7 @@ struct rtw89_btc_fbtc_cysta { /* statistics for cycles */ __le32 skip_cnt; __le32 exception; __le32 except_cnt; -#if (FCXCYSTA_VER > 1) __le16 tslot_cycle[BTC_CYCLE_SLOT_MAX]; -#endif } __packed; #define FCXNULLSTA_VER 1 @@ -1722,7 +1720,7 @@ struct rtw89_btc { struct work_struct eapol_notify_work; struct work_struct arp_notify_work; struct work_struct dhcp_notify_work; - struct work_struct wl_sta_notify_work; + struct work_struct icmp_notify_work; u32 bt_req_len; @@ -1906,6 +1904,13 @@ struct rtw89_efuse { char country_code[2]; }; +struct rtw89_phy_rate_pattern { + u64 ra_mask; + u16 rate; + u8 ra_mode; + bool enable; +}; + struct rtw89_vif { struct list_head list; u8 mac_id; @@ -1941,6 +1946,7 @@ struct rtw89_vif { struct rtw89_bssid_cam_entry bssid_cam; struct ieee80211_tx_queue_params tx_params[IEEE80211_NUM_ACS]; struct rtw89_traffic_stats stats; + struct rtw89_phy_rate_pattern rate_pattern; }; enum rtw89_lv1_rcvy_step { @@ -1955,7 +1961,6 @@ struct rtw89_hci_ops { void (*reset)(struct rtw89_dev *rtwdev); int (*start)(struct rtw89_dev *rtwdev); void (*stop)(struct rtw89_dev *rtwdev); - void (*link_ps)(struct rtw89_dev *rtwdev, bool enter); void (*recalc_int_mit)(struct rtw89_dev *rtwdev); u8 (*read8)(struct rtw89_dev *rtwdev, u32 addr); @@ -2000,6 +2005,7 @@ struct rtw89_chip_ops { void (*rfk_init)(struct rtw89_dev *rtwdev); void (*rfk_channel)(struct rtw89_dev *rtwdev); void (*rfk_band_changed)(struct rtw89_dev *rtwdev); + void (*rfk_scan)(struct rtw89_dev *rtwdev, bool start); void (*rfk_track)(struct rtw89_dev *rtwdev); void (*power_trim)(struct rtw89_dev *rtwdev); void (*set_txpwr)(struct rtw89_dev *rtwdev); @@ -2094,17 +2100,17 @@ struct rtw89_hfc_param { bool en; bool h2c_en; u8 mode; - struct rtw89_hfc_ch_cfg *ch_cfg; + const struct rtw89_hfc_ch_cfg *ch_cfg; struct rtw89_hfc_ch_info ch_info[RTW89_DMA_CH_NUM]; - struct rtw89_hfc_pub_cfg *pub_cfg; + struct rtw89_hfc_pub_cfg pub_cfg; struct rtw89_hfc_pub_info pub_info; - struct rtw89_hfc_prec_cfg *prec_cfg; + struct rtw89_hfc_prec_cfg prec_cfg; }; struct rtw89_hfc_param_ini { - struct rtw89_hfc_ch_cfg *ch_cfg; - struct rtw89_hfc_pub_cfg *pub_cfg; - struct rtw89_hfc_prec_cfg *prec_cfg; + const struct rtw89_hfc_ch_cfg *ch_cfg; + const struct rtw89_hfc_pub_cfg *pub_cfg; + const struct rtw89_hfc_prec_cfg *prec_cfg; u8 mode; }; @@ -2137,12 +2143,12 @@ struct rtw89_ple_quota { struct rtw89_dle_mem { enum rtw89_qta_mode mode; - struct rtw89_dle_size *wde_size; - struct rtw89_dle_size *ple_size; - struct rtw89_wde_quota *wde_min_qt; - struct rtw89_wde_quota *wde_max_qt; - struct rtw89_ple_quota *ple_min_qt; - struct rtw89_ple_quota *ple_max_qt; + const struct rtw89_dle_size *wde_size; + const struct rtw89_dle_size *ple_size; + const struct rtw89_wde_quota *wde_min_qt; + const struct rtw89_wde_quota *wde_max_qt; + const struct rtw89_ple_quota *ple_min_qt; + const struct rtw89_ple_quota *ple_max_qt; }; struct rtw89_reg_def { @@ -2189,8 +2195,8 @@ struct rtw89_chip_info { u32 fifo_size; u16 max_amsdu_limit; bool dis_2g_40m_ul_ofdma; - struct rtw89_hfc_param_ini *hfc_param_ini; - struct rtw89_dle_mem *dle_mem; + const struct rtw89_hfc_param_ini *hfc_param_ini; + const struct rtw89_dle_mem *dle_mem; u32 rf_base_addr[2]; u8 rf_path_num; u8 tx_nss; @@ -2297,6 +2303,11 @@ struct rtw89_fw_suit { u8 cmd_ver; }; +#define RTW89_FW_VER_CODE(major, minor, sub, idx) \ + (((major) << 24) | ((minor) << 16) | ((sub) << 8) | (idx)) +#define RTW89_FW_SUIT_VER_CODE(s) \ + RTW89_FW_VER_CODE((s)->major_ver, (s)->minor_ver, (s)->sub_ver, (s)->sub_idex) + struct rtw89_fw_info { const struct firmware *firmware; struct rtw89_dev *rtwdev; @@ -2306,6 +2317,7 @@ struct rtw89_fw_info { struct rtw89_fw_suit normal; struct rtw89_fw_suit wowlan; bool fw_log_enable; + bool old_ht_ra_format; }; struct rtw89_cam_info { @@ -2760,6 +2772,12 @@ struct rtw89_ppdu_sts_info { u8 curr_rx_ppdu_cnt[RTW89_PHY_MAX]; }; +struct rtw89_early_h2c { + struct list_head list; + u8 *h2c; + u16 h2c_len; +}; + struct rtw89_dev { struct ieee80211_hw *hw; struct device *dev; @@ -2792,6 +2810,8 @@ struct rtw89_dev { struct sk_buff_head c2h_queue; struct work_struct c2h_work; + struct list_head early_h2c_list; + struct rtw89_ser ser; DECLARE_BITMAP(hw_port, RTW89_MAX_HW_PORT_NUM); @@ -2865,11 +2885,6 @@ static inline int rtw89_hci_deinit(struct rtw89_dev *rtwdev) return rtwdev->hci.ops->deinit(rtwdev); } -static inline void rtw89_hci_link_ps(struct rtw89_dev *rtwdev, bool enter) -{ - rtwdev->hci.ops->link_ps(rtwdev, enter); -} - static inline void rtw89_hci_recalc_int_mit(struct rtw89_dev *rtwdev) { rtwdev->hci.ops->recalc_int_mit(rtwdev); @@ -3166,6 +3181,14 @@ static inline void rtw89_chip_rfk_band_changed(struct rtw89_dev *rtwdev) chip->ops->rfk_band_changed(rtwdev); } +static inline void rtw89_chip_rfk_scan(struct rtw89_dev *rtwdev, bool start) +{ + const struct rtw89_chip_info *chip = rtwdev->chip; + + if (chip->ops->rfk_scan) + chip->ops->rfk_scan(rtwdev, start); +} + static inline void rtw89_chip_rfk_track(struct rtw89_dev *rtwdev) { const struct rtw89_chip_info *chip = rtwdev->chip; @@ -3358,150 +3381,4 @@ void rtw89_traffic_stats_init(struct rtw89_dev *rtwdev, int rtw89_core_start(struct rtw89_dev *rtwdev); void rtw89_core_stop(struct rtw89_dev *rtwdev); -#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 8, 0) -/** - * read_poll_timeout_atomic - Periodically poll an address until a condition is - * met or a timeout occurs - * @op: accessor function (takes @args as its arguments) - * @val: Variable to read the value into - * @cond: Break condition (usually involving @val) - * @delay_us: Time to udelay between reads in us (0 tight-loops). Should - * be less than ~10us since udelay is used (see - * Documentation/timers/timers-howto.rst). - * @timeout_us: Timeout in us, 0 means never timeout - * @delay_before_read: if it is true, delay @delay_us before read. - * @args: arguments for @op poll - * - * Returns 0 on success and -ETIMEDOUT upon a timeout. In either - * case, the last read value at @args is stored in @val. - * - * When available, you'll probably want to use one of the specialized - * macros defined below rather than this macro directly. - */ -#define read_poll_timeout_atomic(op, val, cond, delay_us, timeout_us, \ - delay_before_read, args...) \ -({ \ - u64 __timeout_us = (timeout_us); \ - unsigned long __delay_us = (delay_us); \ - ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us); \ - if (delay_before_read && __delay_us) \ - udelay(__delay_us); \ - for (;;) { \ - (val) = op(args); \ - if (cond) \ - break; \ - if (__timeout_us && \ - ktime_compare(ktime_get(), __timeout) > 0) { \ - (val) = op(args); \ - break; \ - } \ - if (__delay_us) \ - udelay(__delay_us); \ - } \ - (cond) ? 0 : -ETIMEDOUT; \ -}) - -/* see Documentation/timers/timers-howto.rst for the thresholds */ -static inline void fsleep(unsigned long usecs) -{ - if (usecs <= 10) - udelay(usecs); - else if (usecs <= 20000) - usleep_range(usecs, 2 * usecs); - else - msleep(DIV_ROUND_UP(usecs, 1000)); -} -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 7, 0) -/** - * read_poll_timeout_atomic - Periodically poll an address until a condition is - * met or a timeout occurs - * @op: accessor function (takes @args as its arguments) - * @val: Variable to read the value into - * @cond: Break condition (usually involving @val) - * @delay_us: Time to udelay between reads in us (0 tight-loops). Should - * be less than ~10us since udelay is used (see - * Documentation/timers/timers-howto.rst). - * @timeout_us: Timeout in us, 0 means never timeout - * @delay_before_read: if it is true, delay @delay_us before read. - * @args: arguments for @op poll - * - * Returns 0 on success and -ETIMEDOUT upon a timeout. In either - * case, the last read value at @args is stored in @val. - * - * When available, you'll probably want to use one of the specialized - * macros defined below rather than this macro directly. - */ -#define read_poll_timeout_atomic(op, val, cond, delay_us, timeout_us, \ - delay_before_read, args...) \ -({ \ - u64 __timeout_us = (timeout_us); \ - unsigned long __delay_us = (delay_us); \ - ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us); \ - if (delay_before_read && __delay_us) \ - udelay(__delay_us); \ - for (;;) { \ - (val) = op(args); \ - if (cond) \ - break; \ - if (__timeout_us && \ - ktime_compare(ktime_get(), __timeout) > 0) { \ - (val) = op(args); \ - break; \ - } \ - if (__delay_us) \ - udelay(__delay_us); \ - } \ - (cond) ? 0 : -ETIMEDOUT; \ -}) - -/** - * read_poll_timeout - Periodically poll an address until a condition is - * met or a timeout occurs - * @op: accessor function (takes @args as its arguments) - * @val: Variable to read the value into - * @cond: Break condition (usually involving @val) - * @sleep_us: Maximum time to sleep between reads in us (0 - * tight-loops). Should be less than ~20ms since usleep_range - * is used (see Documentation/timers/timers-howto.rst). - * @timeout_us: Timeout in us, 0 means never timeout - * @sleep_before_read: if it is true, sleep @sleep_us before read. - * @args: arguments for @op poll - * - * Returns 0 on success and -ETIMEDOUT upon a timeout. In either - * case, the last read value at @args is stored in @val. Must not - * be called from atomic context if sleep_us or timeout_us are used. - * - * When available, you'll probably want to use one of the specialized - * macros defined below rather than this macro directly. - */ -#define read_poll_timeout(op, val, cond, sleep_us, timeout_us, \ - sleep_before_read, args...) \ -({ \ - u64 __timeout_us = (timeout_us); \ - unsigned long __sleep_us = (sleep_us); \ - ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us); \ - might_sleep_if((__sleep_us) != 0); \ - if (sleep_before_read && __sleep_us) \ - usleep_range((__sleep_us >> 2) + 1, __sleep_us); \ - for (;;) { \ - (val) = op(args); \ - if (cond) \ - break; \ - if (__timeout_us && \ - ktime_compare(ktime_get(), __timeout) > 0) { \ - (val) = op(args); \ - break; \ - } \ - if (__sleep_us) \ - usleep_range((__sleep_us >> 2) + 1, __sleep_us); \ - } \ - (cond) ? 0 : -ETIMEDOUT; \ -}) - -#define BSS_CHANGED_HE_BSS_COLOR 1<<29 - -#endif - #endif diff --git a/debug.c b/debug.c index 41d8f2f5..29eb188c 100644 --- a/debug.c +++ b/debug.c @@ -560,13 +560,10 @@ static int rtw89_debug_priv_txpwr_table_get(struct seq_file *m, void *v) seq_puts(m, "[Regulatory] "); __print_regd(m, rtwdev); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) seq_puts(m, "[SAR]\n"); rtw89_print_sar(m, rtwdev); seq_puts(m, "\n[TX power byrate]\n"); - rtw89_print_sar(m, rtwdev); -#endif ret = __print_txpwr_map(m, rtwdev, &__txpwr_map_byr); if (ret) goto err; @@ -2095,29 +2092,108 @@ rtw89_debug_priv_mac_dbg_port_dump_get(struct seq_file *m, void *v) return 0; }; +static u8 *rtw89_hex2bin_user(struct rtw89_dev *rtwdev, + const char __user *user_buf, size_t count) +{ + char *buf; + u8 *bin; + int num; + int err = 0; + + buf = memdup_user(user_buf, count); + if (IS_ERR(buf)) + return buf; + + num = count / 2; + bin = kmalloc(num, GFP_KERNEL); + if (!bin) { + err = -EFAULT; + goto out; + } + + if (hex2bin(bin, buf, num)) { + rtw89_info(rtwdev, "valid format: H1H2H3...\n"); + kfree(bin); + err = -EINVAL; + } + +out: + kfree(buf); + + return err ? ERR_PTR(err) : bin; +} + static ssize_t rtw89_debug_priv_send_h2c_set(struct file *filp, const char __user *user_buf, size_t count, loff_t *loff) { struct rtw89_debugfs_priv *debugfs_priv = filp->private_data; struct rtw89_dev *rtwdev = debugfs_priv->rtwdev; - char buf[256]; - size_t buf_size; - u8 h2c[128]; - int num; + u8 *h2c; + u16 h2c_len = count / 2; - buf_size = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, buf_size)) + h2c = rtw89_hex2bin_user(rtwdev, user_buf, count); + if (IS_ERR(h2c)) return -EFAULT; - num = buf_size / 2; - if (hex2bin(h2c, buf, num)) { - rtw89_info(rtwdev, "invalid format: H1H2H3...\n"); - return -EINVAL; + rtw89_fw_h2c_raw(rtwdev, h2c, h2c_len); + + kfree(h2c); + + return count; +} + +static int +rtw89_debug_priv_early_h2c_get(struct seq_file *m, void *v) +{ + struct rtw89_debugfs_priv *debugfs_priv = m->private; + struct rtw89_dev *rtwdev = debugfs_priv->rtwdev; + struct rtw89_early_h2c *early_h2c; + int seq = 0; + + mutex_lock(&rtwdev->mutex); + list_for_each_entry(early_h2c, &rtwdev->early_h2c_list, list) + seq_printf(m, "%d: %*ph\n", ++seq, early_h2c->h2c_len, early_h2c->h2c); + mutex_unlock(&rtwdev->mutex); + + return 0; +} + +static ssize_t +rtw89_debug_priv_early_h2c_set(struct file *filp, const char __user *user_buf, + size_t count, loff_t *loff) +{ + struct seq_file *m = (struct seq_file *)filp->private_data; + struct rtw89_debugfs_priv *debugfs_priv = m->private; + struct rtw89_dev *rtwdev = debugfs_priv->rtwdev; + struct rtw89_early_h2c *early_h2c; + u8 *h2c; + u16 h2c_len = count / 2; + + h2c = rtw89_hex2bin_user(rtwdev, user_buf, count); + if (IS_ERR(h2c)) + return -EFAULT; + + if (h2c_len >= 2 && h2c[0] == 0x00 && h2c[1] == 0x00) { + kfree(h2c); + rtw89_fw_free_all_early_h2c(rtwdev); + goto out; + } + + early_h2c = kmalloc(sizeof(*early_h2c), GFP_KERNEL); + if (!early_h2c) { + kfree(h2c); + return -EFAULT; } - rtw89_fw_h2c_raw(rtwdev, h2c, num); + early_h2c->h2c = h2c; + early_h2c->h2c_len = h2c_len; + mutex_lock(&rtwdev->mutex); + list_add_tail(&early_h2c->list, &rtwdev->early_h2c_list); + mutex_unlock(&rtwdev->mutex); + +out: return count; } @@ -2328,6 +2404,11 @@ static struct rtw89_debugfs_priv rtw89_debug_priv_send_h2c = { .cb_write = rtw89_debug_priv_send_h2c_set, }; +static struct rtw89_debugfs_priv rtw89_debug_priv_early_h2c = { + .cb_read = rtw89_debug_priv_early_h2c_get, + .cb_write = rtw89_debug_priv_early_h2c_set, +}; + static struct rtw89_debugfs_priv rtw89_debug_priv_btc_info = { .cb_read = rtw89_debug_priv_btc_info_get, }; @@ -2377,6 +2458,7 @@ void rtw89_debugfs_init(struct rtw89_dev *rtwdev) rtw89_debugfs_add_rw(mac_mem_dump); rtw89_debugfs_add_rw(mac_dbg_port_dump); rtw89_debugfs_add_w(send_h2c); + rtw89_debugfs_add_rw(early_h2c); rtw89_debugfs_add_r(btc_info); rtw89_debugfs_add_w(btc_manual); rtw89_debugfs_add_w(fw_log_manual); diff --git a/fw.c b/fw.c index 5d64a047..212aaf57 100644 --- a/fw.c +++ b/fw.c @@ -194,6 +194,16 @@ int __rtw89_fw_recognize(struct rtw89_dev *rtwdev, enum rtw89_fw_type type) return 0; } +static void rtw89_fw_recognize_features(struct rtw89_dev *rtwdev) +{ + const struct rtw89_chip_info *chip = rtwdev->chip; + struct rtw89_fw_suit *fw_suit = rtw89_fw_suit_get(rtwdev, RTW89_FW_NORMAL); + + if (chip->chip_id == RTL8852A && + RTW89_FW_SUIT_VER_CODE(fw_suit) <= RTW89_FW_VER_CODE(0, 13, 29, 0)) + rtwdev->fw.old_ht_ra_format = true; +} + int rtw89_fw_recognize(struct rtw89_dev *rtwdev) { int ret; @@ -205,6 +215,8 @@ int rtw89_fw_recognize(struct rtw89_dev *rtwdev) /* It still works if wowlan firmware isn't existing. */ __rtw89_fw_recognize(rtwdev, RTW89_FW_WOWLAN); + rtw89_fw_recognize_features(rtwdev); + return 0; } @@ -807,6 +819,7 @@ int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { + struct rtw89_hal *hal = &rtwdev->hal; struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; struct sk_buff *skb; @@ -825,6 +838,10 @@ int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev, SET_CTRL_INFO_OPERATION(skb->data, 1); SET_CMC_TBL_DISRTSFB(skb->data, 1); SET_CMC_TBL_DISDATAFB(skb->data, 1); + if (hal->current_band_type == RTW89_BAND_2G) + SET_CMC_TBL_RTS_RTY_LOWEST_RATE(skb->data, RTW89_HW_RATE_CCK1); + else + SET_CMC_TBL_RTS_RTY_LOWEST_RATE(skb->data, RTW89_HW_RATE_OFDM6); SET_CMC_TBL_RTS_TXCNT_LMT_SEL(skb->data, 0); SET_CMC_TBL_DATA_TXCNT_LMT_SEL(skb->data, 0); if (vif->type == NL80211_IFTYPE_STATION) @@ -1433,6 +1450,30 @@ int rtw89_fw_h2c_raw(struct rtw89_dev *rtwdev, const u8 *buf, u16 len) return -EBUSY; } +void rtw89_fw_send_all_early_h2c(struct rtw89_dev *rtwdev) +{ + struct rtw89_early_h2c *early_h2c; + + lockdep_assert_held(&rtwdev->mutex); + + list_for_each_entry(early_h2c, &rtwdev->early_h2c_list, list) { + rtw89_fw_h2c_raw(rtwdev, early_h2c->h2c, early_h2c->h2c_len); + } +} + +void rtw89_fw_free_all_early_h2c(struct rtw89_dev *rtwdev) +{ + struct rtw89_early_h2c *early_h2c, *tmp; + + mutex_lock(&rtwdev->mutex); + list_for_each_entry_safe(early_h2c, tmp, &rtwdev->early_h2c_list, list) { + list_del(&early_h2c->list); + kfree(early_h2c->h2c); + kfree(early_h2c); + } + mutex_unlock(&rtwdev->mutex); +} + void rtw89_fw_c2h_irqsafe(struct rtw89_dev *rtwdev, struct sk_buff *c2h) { skb_queue_tail(&rtwdev->c2h_queue, c2h); diff --git a/fw.h b/fw.h index e00bb5e5..7ee0d932 100644 --- a/fw.h +++ b/fw.h @@ -157,95 +157,95 @@ struct rtw89_h2creg_sch_tx_en { } __packed; #define RTW89_SET_FWCMD_RA_IS_DIS(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x00, BIT(0)) + le32p_replace_bits((__le32 *)(cmd) + 0x00, val, BIT(0)) #define RTW89_SET_FWCMD_RA_MODE(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x00, GENMASK(5, 1)) + le32p_replace_bits((__le32 *)(cmd) + 0x00, val, GENMASK(5, 1)) #define RTW89_SET_FWCMD_RA_BW_CAP(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x00, GENMASK(7, 6)) + le32p_replace_bits((__le32 *)(cmd) + 0x00, val, GENMASK(7, 6)) #define RTW89_SET_FWCMD_RA_MACID(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x00, GENMASK(15, 8)) + le32p_replace_bits((__le32 *)(cmd) + 0x00, val, GENMASK(15, 8)) #define RTW89_SET_FWCMD_RA_DCM(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x00, BIT(16)) + le32p_replace_bits((__le32 *)(cmd) + 0x00, val, BIT(16)) #define RTW89_SET_FWCMD_RA_ER(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x00, BIT(17)) + le32p_replace_bits((__le32 *)(cmd) + 0x00, val, BIT(17)) #define RTW89_SET_FWCMD_RA_INIT_RATE_LV(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x00, GENMASK(19, 18)) + le32p_replace_bits((__le32 *)(cmd) + 0x00, val, GENMASK(19, 18)) #define RTW89_SET_FWCMD_RA_UPD_ALL(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x00, BIT(20)) + le32p_replace_bits((__le32 *)(cmd) + 0x00, val, BIT(20)) #define RTW89_SET_FWCMD_RA_SGI(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x00, BIT(21)) + le32p_replace_bits((__le32 *)(cmd) + 0x00, val, BIT(21)) #define RTW89_SET_FWCMD_RA_LDPC(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x00, BIT(22)) + le32p_replace_bits((__le32 *)(cmd) + 0x00, val, BIT(22)) #define RTW89_SET_FWCMD_RA_STBC(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x00, BIT(23)) + le32p_replace_bits((__le32 *)(cmd) + 0x00, val, BIT(23)) #define RTW89_SET_FWCMD_RA_SS_NUM(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x00, GENMASK(26, 24)) + le32p_replace_bits((__le32 *)(cmd) + 0x00, val, GENMASK(26, 24)) #define RTW89_SET_FWCMD_RA_GILTF(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x00, GENMASK(29, 27)) + le32p_replace_bits((__le32 *)(cmd) + 0x00, val, GENMASK(29, 27)) #define RTW89_SET_FWCMD_RA_UPD_BW_NSS_MASK(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x00, BIT(30)) + le32p_replace_bits((__le32 *)(cmd) + 0x00, val, BIT(30)) #define RTW89_SET_FWCMD_RA_UPD_MASK(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x00, BIT(31)) + le32p_replace_bits((__le32 *)(cmd) + 0x00, val, BIT(31)) #define RTW89_SET_FWCMD_RA_MASK_0(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x01, GENMASK(7, 0)) + le32p_replace_bits((__le32 *)(cmd) + 0x01, val, GENMASK(7, 0)) #define RTW89_SET_FWCMD_RA_MASK_1(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x01, GENMASK(15, 8)) + le32p_replace_bits((__le32 *)(cmd) + 0x01, val, GENMASK(15, 8)) #define RTW89_SET_FWCMD_RA_MASK_2(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x01, GENMASK(23, 16)) + le32p_replace_bits((__le32 *)(cmd) + 0x01, val, GENMASK(23, 16)) #define RTW89_SET_FWCMD_RA_MASK_3(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x01, GENMASK(31, 24)) + le32p_replace_bits((__le32 *)(cmd) + 0x01, val, GENMASK(31, 24)) #define RTW89_SET_FWCMD_RA_MASK_4(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x02, GENMASK(7, 0)) + le32p_replace_bits((__le32 *)(cmd) + 0x02, val, GENMASK(7, 0)) #define RTW89_SET_FWCMD_RA_BFEE_CSI_CTL(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x02, BIT(31)) + le32p_replace_bits((__le32 *)(cmd) + 0x02, val, BIT(31)) #define RTW89_SET_FWCMD_RA_BAND_NUM(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x03, GENMASK(7, 0)) + le32p_replace_bits((__le32 *)(cmd) + 0x03, val, GENMASK(7, 0)) #define RTW89_SET_FWCMD_RA_RA_CSI_RATE_EN(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x03, BIT(8)) + le32p_replace_bits((__le32 *)(cmd) + 0x03, val, BIT(8)) #define RTW89_SET_FWCMD_RA_FIXED_CSI_RATE_EN(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x03, BIT(9)) + le32p_replace_bits((__le32 *)(cmd) + 0x03, val, BIT(9)) #define RTW89_SET_FWCMD_RA_CR_TBL_SEL(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x03, BIT(10)) + le32p_replace_bits((__le32 *)(cmd) + 0x03, val, BIT(10)) #define RTW89_SET_FWCMD_RA_FIXED_CSI_MCS_SS_IDX(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x03, GENMASK(23, 16)) + le32p_replace_bits((__le32 *)(cmd) + 0x03, val, GENMASK(23, 16)) #define RTW89_SET_FWCMD_RA_FIXED_CSI_MODE(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x03, GENMASK(25, 24)) + le32p_replace_bits((__le32 *)(cmd) + 0x03, val, GENMASK(25, 24)) #define RTW89_SET_FWCMD_RA_FIXED_CSI_GI_LTF(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x03, GENMASK(28, 26)) + le32p_replace_bits((__le32 *)(cmd) + 0x03, val, GENMASK(28, 26)) #define RTW89_SET_FWCMD_RA_FIXED_CSI_BW(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x03, GENMASK(31, 29)) + le32p_replace_bits((__le32 *)(cmd) + 0x03, val, GENMASK(31, 29)) #define RTW89_SET_FWCMD_SEC_IDX(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x00, GENMASK(7, 0)) + le32p_replace_bits((__le32 *)(cmd) + 0x00, val, GENMASK(7, 0)) #define RTW89_SET_FWCMD_SEC_OFFSET(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x00, GENMASK(15, 8)) + le32p_replace_bits((__le32 *)(cmd) + 0x00, val, GENMASK(15, 8)) #define RTW89_SET_FWCMD_SEC_LEN(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x00, GENMASK(23, 16)) + le32p_replace_bits((__le32 *)(cmd) + 0x00, val, GENMASK(23, 16)) #define RTW89_SET_FWCMD_SEC_TYPE(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x01, GENMASK(3, 0)) + le32p_replace_bits((__le32 *)(cmd) + 0x01, val, GENMASK(3, 0)) #define RTW89_SET_FWCMD_SEC_EXT_KEY(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x01, BIT(4)) + le32p_replace_bits((__le32 *)(cmd) + 0x01, val, BIT(4)) #define RTW89_SET_FWCMD_SEC_SPP_MODE(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x01, BIT(5)) + le32p_replace_bits((__le32 *)(cmd) + 0x01, val, BIT(5)) #define RTW89_SET_FWCMD_SEC_KEY0(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x02, GENMASK(31, 0)) + le32p_replace_bits((__le32 *)(cmd) + 0x02, val, GENMASK(31, 0)) #define RTW89_SET_FWCMD_SEC_KEY1(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x03, GENMASK(31, 0)) + le32p_replace_bits((__le32 *)(cmd) + 0x03, val, GENMASK(31, 0)) #define RTW89_SET_FWCMD_SEC_KEY2(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x04, GENMASK(31, 0)) + le32p_replace_bits((__le32 *)(cmd) + 0x04, val, GENMASK(31, 0)) #define RTW89_SET_FWCMD_SEC_KEY3(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x05, GENMASK(31, 0)) + le32p_replace_bits((__le32 *)(cmd) + 0x05, val, GENMASK(31, 0)) #define RTW89_SET_EDCA_SEL(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x00, GENMASK(1, 0)) + le32p_replace_bits((__le32 *)(cmd) + 0x00, val, GENMASK(1, 0)) #define RTW89_SET_EDCA_BAND(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x00, BIT(3)) + le32p_replace_bits((__le32 *)(cmd) + 0x00, val, BIT(3)) #define RTW89_SET_EDCA_WMM(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x00, BIT(4)) + le32p_replace_bits((__le32 *)(cmd) + 0x00, val, BIT(4)) #define RTW89_SET_EDCA_AC(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x00, GENMASK(6, 5)) + le32p_replace_bits((__le32 *)(cmd) + 0x00, val, GENMASK(6, 5)) #define RTW89_SET_EDCA_PARAM(cmd, val) \ - RTW89_SET_FWCMD(cmd, val, 0x01, GENMASK(31, 0)) + le32p_replace_bits((__le32 *)(cmd) + 0x01, val, GENMASK(31, 0)) #define FW_EDCA_PARAM_TXOPLMT_MSK GENMASK(26, 16) #define FW_EDCA_PARAM_CWMAX_MSK GENMASK(15, 12) #define FW_EDCA_PARAM_CWMIN_MSK GENMASK(11, 8) @@ -1053,117 +1053,117 @@ enum rtw89_btc_cxdrvinfo { }; #define RTW89_SET_FWCMD_CXHDR_TYPE(cmd, val) \ - RTW89_SET_FWCMD_UA8(cmd, val, 0, GENMASK(7, 0)) + u8p_replace_bits((u8 *)(cmd) + 0, val, GENMASK(7, 0)) #define RTW89_SET_FWCMD_CXHDR_LEN(cmd, val) \ - RTW89_SET_FWCMD_UA8(cmd, val, 1, GENMASK(7, 0)) + u8p_replace_bits((u8 *)(cmd) + 1, val, GENMASK(7, 0)) #define RTW89_SET_FWCMD_CXINIT_ANT_TYPE(cmd, val) \ - RTW89_SET_FWCMD_UA8(cmd, val, 2, GENMASK(7, 0)) + u8p_replace_bits((u8 *)(cmd) + 2, val, GENMASK(7, 0)) #define RTW89_SET_FWCMD_CXINIT_ANT_NUM(cmd, val) \ - RTW89_SET_FWCMD_UA8(cmd, val, 3, GENMASK(7, 0)) + u8p_replace_bits((u8 *)(cmd) + 3, val, GENMASK(7, 0)) #define RTW89_SET_FWCMD_CXINIT_ANT_ISO(cmd, val) \ - RTW89_SET_FWCMD_UA8(cmd, val, 4, GENMASK(7, 0)) + u8p_replace_bits((u8 *)(cmd) + 4, val, GENMASK(7, 0)) #define RTW89_SET_FWCMD_CXINIT_ANT_POS(cmd, val) \ - RTW89_SET_FWCMD_UA8(cmd, val, 5, BIT(0)) + u8p_replace_bits((u8 *)(cmd) + 5, val, BIT(0)) #define RTW89_SET_FWCMD_CXINIT_ANT_DIVERSITY(cmd, val) \ - RTW89_SET_FWCMD_UA8(cmd, val, 5, BIT(1)) + u8p_replace_bits((u8 *)(cmd) + 5, val, BIT(1)) #define RTW89_SET_FWCMD_CXINIT_MOD_RFE(cmd, val) \ - RTW89_SET_FWCMD_UA8(cmd, val, 6, GENMASK(7, 0)) + u8p_replace_bits((u8 *)(cmd) + 6, val, GENMASK(7, 0)) #define RTW89_SET_FWCMD_CXINIT_MOD_CV(cmd, val) \ - RTW89_SET_FWCMD_UA8(cmd, val, 7, GENMASK(7, 0)) + u8p_replace_bits((u8 *)(cmd) + 7, val, GENMASK(7, 0)) #define RTW89_SET_FWCMD_CXINIT_MOD_BT_SOLO(cmd, val) \ - RTW89_SET_FWCMD_UA8(cmd, val, 8, BIT(0)) + u8p_replace_bits((u8 *)(cmd) + 8, val, BIT(0)) #define RTW89_SET_FWCMD_CXINIT_MOD_BT_POS(cmd, val) \ - RTW89_SET_FWCMD_UA8(cmd, val, 8, BIT(1)) + u8p_replace_bits((u8 *)(cmd) + 8, val, BIT(1)) #define RTW89_SET_FWCMD_CXINIT_MOD_SW_TYPE(cmd, val) \ - RTW89_SET_FWCMD_UA8(cmd, val, 8, BIT(2)) + u8p_replace_bits((u8 *)(cmd) + 8, val, BIT(2)) #define RTW89_SET_FWCMD_CXINIT_WL_GCH(cmd, val) \ - RTW89_SET_FWCMD_UA8(cmd, val, 10, GENMASK(7, 0)) + u8p_replace_bits((u8 *)(cmd) + 10, val, GENMASK(7, 0)) #define RTW89_SET_FWCMD_CXINIT_WL_ONLY(cmd, val) \ - RTW89_SET_FWCMD_UA8(cmd, val, 11, BIT(0)) + u8p_replace_bits((u8 *)(cmd) + 11, val, BIT(0)) #define RTW89_SET_FWCMD_CXINIT_WL_INITOK(cmd, val) \ - RTW89_SET_FWCMD_UA8(cmd, val, 11, BIT(1)) + u8p_replace_bits((u8 *)(cmd) + 11, val, BIT(1)) #define RTW89_SET_FWCMD_CXINIT_DBCC_EN(cmd, val) \ - RTW89_SET_FWCMD_UA8(cmd, val, 11, BIT(2)) + u8p_replace_bits((u8 *)(cmd) + 11, val, BIT(2)) #define RTW89_SET_FWCMD_CXINIT_CX_OTHER(cmd, val) \ - RTW89_SET_FWCMD_UA8(cmd, val, 11, BIT(3)) + u8p_replace_bits((u8 *)(cmd) + 11, val, BIT(3)) #define RTW89_SET_FWCMD_CXINIT_BT_ONLY(cmd, val) \ - RTW89_SET_FWCMD_UA8(cmd, val, 11, BIT(4)) + u8p_replace_bits((u8 *)(cmd) + 11, val, BIT(4)) #define RTW89_SET_FWCMD_CXROLE_CONNECT_CNT(cmd, val) \ - RTW89_SET_FWCMD_UA8(cmd, val, 2, GENMASK(7, 0)) + u8p_replace_bits((u8 *)(cmd) + 2, val, GENMASK(7, 0)) #define RTW89_SET_FWCMD_CXROLE_LINK_MODE(cmd, val) \ - RTW89_SET_FWCMD_UA8(cmd, val, 3, GENMASK(7, 0)) + u8p_replace_bits((u8 *)(cmd) + 3, val, GENMASK(7, 0)) #define RTW89_SET_FWCMD_CXROLE_ROLE_NONE(cmd, val) \ - RTW89_SET_FWCMD_UA16(cmd, val, 4, BIT(0)) + le16p_replace_bits((__le16 *)((u8 *)(cmd) + 4), val, BIT(0)) #define RTW89_SET_FWCMD_CXROLE_ROLE_STA(cmd, val) \ - RTW89_SET_FWCMD_UA16(cmd, val, 4, BIT(1)) + le16p_replace_bits((__le16 *)((u8 *)(cmd) + 4), val, BIT(1)) #define RTW89_SET_FWCMD_CXROLE_ROLE_AP(cmd, val) \ - RTW89_SET_FWCMD_UA16(cmd, val, 4, BIT(2)) + le16p_replace_bits((__le16 *)((u8 *)(cmd) + 4), val, BIT(2)) #define RTW89_SET_FWCMD_CXROLE_ROLE_VAP(cmd, val) \ - RTW89_SET_FWCMD_UA16(cmd, val, 4, BIT(3)) + le16p_replace_bits((__le16 *)((u8 *)(cmd) + 4), val, BIT(3)) #define RTW89_SET_FWCMD_CXROLE_ROLE_ADHOC(cmd, val) \ - RTW89_SET_FWCMD_UA16(cmd, val, 4, BIT(4)) + le16p_replace_bits((__le16 *)((u8 *)(cmd) + 4), val, BIT(4)) #define RTW89_SET_FWCMD_CXROLE_ROLE_ADHOC_MASTER(cmd, val) \ - RTW89_SET_FWCMD_UA16(cmd, val, 4, BIT(5)) + le16p_replace_bits((__le16 *)((u8 *)(cmd) + 4), val, BIT(5)) #define RTW89_SET_FWCMD_CXROLE_ROLE_MESH(cmd, val) \ - RTW89_SET_FWCMD_UA16(cmd, val, 4, BIT(6)) + le16p_replace_bits((__le16 *)((u8 *)(cmd) + 4), val, BIT(6)) #define RTW89_SET_FWCMD_CXROLE_ROLE_MONITOR(cmd, val) \ - RTW89_SET_FWCMD_UA16(cmd, val, 4, BIT(7)) + le16p_replace_bits((__le16 *)((u8 *)(cmd) + 4), val, BIT(7)) #define RTW89_SET_FWCMD_CXROLE_ROLE_P2P_DEV(cmd, val) \ - RTW89_SET_FWCMD_UA16(cmd, val, 4, BIT(8)) + le16p_replace_bits((__le16 *)((u8 *)(cmd) + 4), val, BIT(8)) #define RTW89_SET_FWCMD_CXROLE_ROLE_P2P_GC(cmd, val) \ - RTW89_SET_FWCMD_UA16(cmd, val, 4, BIT(9)) + le16p_replace_bits((__le16 *)((u8 *)(cmd) + 4), val, BIT(9)) #define RTW89_SET_FWCMD_CXROLE_ROLE_P2P_GO(cmd, val) \ - RTW89_SET_FWCMD_UA16(cmd, val, 4, BIT(10)) + le16p_replace_bits((__le16 *)((u8 *)(cmd) + 4), val, BIT(10)) #define RTW89_SET_FWCMD_CXROLE_ROLE_NAN(cmd, val) \ - RTW89_SET_FWCMD_UA16(cmd, val, 4, BIT(11)) + le16p_replace_bits((__le16 *)((u8 *)(cmd) + 4), val, BIT(11)) #define RTW89_SET_FWCMD_CXROLE_ACT_CONNECTED(cmd, val, n) \ - RTW89_SET_FWCMD_UA8(cmd, val, 6 + 12 * (n), BIT(0)) + u8p_replace_bits((u8 *)(cmd) + (6 + 12 * (n)), val, BIT(0)) #define RTW89_SET_FWCMD_CXROLE_ACT_PID(cmd, val, n) \ - RTW89_SET_FWCMD_UA8(cmd, val, 6 + 12 * (n), GENMASK(3, 1)) + u8p_replace_bits((u8 *)(cmd) + (6 + 12 * (n)), val, GENMASK(3, 1)) #define RTW89_SET_FWCMD_CXROLE_ACT_PHY(cmd, val, n) \ - RTW89_SET_FWCMD_UA8(cmd, val, 6 + 12 * (n), BIT(4)) + u8p_replace_bits((u8 *)(cmd) + (6 + 12 * (n)), val, BIT(4)) #define RTW89_SET_FWCMD_CXROLE_ACT_NOA(cmd, val, n) \ - RTW89_SET_FWCMD_UA8(cmd, val, 6 + 12 * (n), BIT(5)) + u8p_replace_bits((u8 *)(cmd) + (6 + 12 * (n)), val, BIT(5)) #define RTW89_SET_FWCMD_CXROLE_ACT_BAND(cmd, val, n) \ - RTW89_SET_FWCMD_UA8(cmd, val, 6 + 12 * (n), GENMASK(7, 6)) + u8p_replace_bits((u8 *)(cmd) + (6 + 12 * (n)), val, GENMASK(7, 6)) #define RTW89_SET_FWCMD_CXROLE_ACT_CLIENT_PS(cmd, val, n) \ - RTW89_SET_FWCMD_UA8(cmd, val, 7 + 12 * (n), BIT(0)) + u8p_replace_bits((u8 *)(cmd) + (7 + 12 * (n)), val, BIT(0)) #define RTW89_SET_FWCMD_CXROLE_ACT_BW(cmd, val, n) \ - RTW89_SET_FWCMD_UA8(cmd, val, 7 + 12 * (n), GENMASK(7, 1)) + u8p_replace_bits((u8 *)(cmd) + (7 + 12 * (n)), val, GENMASK(7, 1)) #define RTW89_SET_FWCMD_CXROLE_ACT_ROLE(cmd, val, n) \ - RTW89_SET_FWCMD_UA8(cmd, val, 8 + 12 * (n), GENMASK(7, 0)) + u8p_replace_bits((u8 *)(cmd) + (8 + 12 * (n)), val, GENMASK(7, 0)) #define RTW89_SET_FWCMD_CXROLE_ACT_CH(cmd, val, n) \ - RTW89_SET_FWCMD_UA8(cmd, val, 9 + 12 * (n), GENMASK(7, 0)) + u8p_replace_bits((u8 *)(cmd) + (9 + 12 * (n)), val, GENMASK(7, 0)) #define RTW89_SET_FWCMD_CXROLE_ACT_TX_LVL(cmd, val, n) \ - RTW89_SET_FWCMD_UA16(cmd, val, 10 + 12 * (n), GENMASK(15, 0)) + le16p_replace_bits((__le16 *)((u8 *)(cmd) + (10 + 12 * (n))), val, GENMASK(15, 0)) #define RTW89_SET_FWCMD_CXROLE_ACT_RX_LVL(cmd, val, n) \ - RTW89_SET_FWCMD_UA16(cmd, val, 12 + 12 * (n), GENMASK(15, 0)) + le16p_replace_bits((__le16 *)((u8 *)(cmd) + (12 + 12 * (n))), val, GENMASK(15, 0)) #define RTW89_SET_FWCMD_CXROLE_ACT_TX_RATE(cmd, val, n) \ - RTW89_SET_FWCMD_UA16(cmd, val, 14 + 12 * (n), GENMASK(15, 0)) + le16p_replace_bits((__le16 *)((u8 *)(cmd) + (14 + 12 * (n))), val, GENMASK(15, 0)) #define RTW89_SET_FWCMD_CXROLE_ACT_RX_RATE(cmd, val, n) \ - RTW89_SET_FWCMD_UA16(cmd, val, 16 + 12 * (n), GENMASK(15, 0)) + le16p_replace_bits((__le16 *)((u8 *)(cmd) + (16 + 12 * (n))), val, GENMASK(15, 0)) #define RTW89_SET_FWCMD_CXCTRL_MANUAL(cmd, val) \ - RTW89_SET_FWCMD_UA32(cmd, val, 2, BIT(0)) + le32p_replace_bits((__le32 *)((u8 *)(cmd) + 2), val, BIT(0)) #define RTW89_SET_FWCMD_CXCTRL_IGNORE_BT(cmd, val) \ - RTW89_SET_FWCMD_UA32(cmd, val, 2, BIT(1)) + le32p_replace_bits((__le32 *)((u8 *)(cmd) + 2), val, BIT(1)) #define RTW89_SET_FWCMD_CXCTRL_ALWAYS_FREERUN(cmd, val) \ - RTW89_SET_FWCMD_UA32(cmd, val, 2, BIT(2)) + le32p_replace_bits((__le32 *)((u8 *)(cmd) + 2), val, BIT(2)) #define RTW89_SET_FWCMD_CXCTRL_TRACE_STEP(cmd, val) \ - RTW89_SET_FWCMD_UA32(cmd, val, 2, GENMASK(18, 3)) + le32p_replace_bits((__le32 *)((u8 *)(cmd) + 2), val, GENMASK(18, 3)) #define RTW89_SET_FWCMD_CXRFK_STATE(cmd, val) \ - RTW89_SET_FWCMD_UA32(cmd, val, 2, GENMASK(1, 0)) + le32p_replace_bits((__le32 *)((u8 *)(cmd) + 2), val, GENMASK(1, 0)) #define RTW89_SET_FWCMD_CXRFK_PATH_MAP(cmd, val) \ - RTW89_SET_FWCMD_UA32(cmd, val, 2, GENMASK(5, 2)) + le32p_replace_bits((__le32 *)((u8 *)(cmd) + 2), val, GENMASK(5, 2)) #define RTW89_SET_FWCMD_CXRFK_PHY_MAP(cmd, val) \ - RTW89_SET_FWCMD_UA32(cmd, val, 2, GENMASK(7, 6)) + le32p_replace_bits((__le32 *)((u8 *)(cmd) + 2), val, GENMASK(7, 6)) #define RTW89_SET_FWCMD_CXRFK_BAND(cmd, val) \ - RTW89_SET_FWCMD_UA32(cmd, val, 2, GENMASK(9, 8)) + le32p_replace_bits((__le32 *)((u8 *)(cmd) + 2), val, GENMASK(9, 8)) #define RTW89_SET_FWCMD_CXRFK_TYPE(cmd, val) \ - RTW89_SET_FWCMD_UA32(cmd, val, 2, GENMASK(17, 10)) + le32p_replace_bits((__le32 *)((u8 *)(cmd) + 2), val, GENMASK(17, 10)) #define RTW89_C2H_HEADER_LEN 8 @@ -1212,8 +1212,12 @@ enum rtw89_btc_cxdrvinfo { #define RTW89_GET_PHY_C2H_RA_RPT_BW(c2h) \ le32_get_bits(*((__le32 *)(c2h) + 3), GENMASK(14, 13)) +/* VHT, HE, HT-old: [6:4]: NSS, [3:0]: MCS + * HT-new: [6:5]: NA, [4:0]: MCS + */ #define RTW89_RA_RATE_MASK_NSS GENMASK(6, 4) #define RTW89_RA_RATE_MASK_MCS GENMASK(3, 0) +#define RTW89_RA_RATE_MASK_HT_MCS GENMASK(4, 0) #define RTW89_MK_HT_RATE(nss, mcs) (FIELD_PREP(GENMASK(4, 3), nss) | \ FIELD_PREP(GENMASK(2, 0), mcs)) @@ -1356,6 +1360,8 @@ int rtw89_fw_h2c_raw_with_hdr(struct rtw89_dev *rtwdev, u8 h2c_class, u8 h2c_func, u8 *buf, u16 len, bool rack, bool dack); int rtw89_fw_h2c_raw(struct rtw89_dev *rtwdev, const u8 *buf, u16 len); +void rtw89_fw_send_all_early_h2c(struct rtw89_dev *rtwdev); +void rtw89_fw_free_all_early_h2c(struct rtw89_dev *rtwdev); int rtw89_fw_h2c_general_pkt(struct rtw89_dev *rtwdev, u8 macid); int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, bool valid, u8 macid, struct ieee80211_ampdu_params *params); @@ -1369,26 +1375,4 @@ int rtw89_fw_msg_reg(struct rtw89_dev *rtwdev, int rtw89_fw_h2c_fw_log(struct rtw89_dev *rtwdev, bool enable); void rtw89_fw_st_dbg_dump(struct rtw89_dev *rtwdev); -static __always_inline void RTW89_SET_FWCMD(u8 *cmd, u32 val, u8 offset, u32 mask) -{ - u32 *cmd32 = (u32 *)cmd; - - le32p_replace_bits((__le32 *)(cmd32 + offset), val, mask); -} - -static __always_inline void RTW89_SET_FWCMD_UA8(u8 *cmd, u8 val, u8 offset, u32 mask) -{ - u8p_replace_bits(cmd + offset, val, mask); -} - -static __always_inline void RTW89_SET_FWCMD_UA16(u8 *cmd, u16 val, u8 offset, u32 mask) -{ - le16p_replace_bits((__le16 *)(cmd + offset), val, mask); -} - -static __always_inline void RTW89_SET_FWCMD_UA32(u8 *cmd, u32 val, u8 offset, u32 mask) -{ - le32p_replace_bits((__le32 *)(cmd + offset), val, mask); -} - #endif diff --git a/mac.c b/mac.c index 6b63bad4..0171a5a7 100644 --- a/mac.c +++ b/mac.c @@ -481,7 +481,7 @@ int rtw89_mac_set_err_status(struct rtw89_dev *rtwdev, u32 err) } EXPORT_SYMBOL(rtw89_mac_set_err_status); -struct rtw89_hfc_prec_cfg rtw_hfc_preccfg_pcie = { +const struct rtw89_hfc_prec_cfg rtw_hfc_preccfg_pcie = { 2, 40, 0, 0, 1, 0, 0, 0 }; @@ -501,12 +501,12 @@ static int hfc_reset_param(struct rtw89_dev *rtwdev) } if (param_ini.pub_cfg) - param->pub_cfg = param_ini.pub_cfg; + param->pub_cfg = *param_ini.pub_cfg; if (param_ini.prec_cfg) { - param->prec_cfg = param_ini.prec_cfg; + param->prec_cfg = *param_ini.prec_cfg; rtwdev->hal.sw_amsdu_max_size = - param->prec_cfg->wp_ch07_prec * HFC_PAGE_UNIT; + param->prec_cfg.wp_ch07_prec * HFC_PAGE_UNIT; } if (param_ini.ch_cfg) @@ -522,9 +522,9 @@ static int hfc_reset_param(struct rtw89_dev *rtwdev) static int hfc_ch_cfg_chk(struct rtw89_dev *rtwdev, u8 ch) { struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param; - struct rtw89_hfc_ch_cfg *ch_cfg = param->ch_cfg; - struct rtw89_hfc_pub_cfg *pub_cfg = param->pub_cfg; - struct rtw89_hfc_prec_cfg *prec_cfg = param->prec_cfg; + const struct rtw89_hfc_ch_cfg *ch_cfg = param->ch_cfg; + const struct rtw89_hfc_pub_cfg *pub_cfg = ¶m->pub_cfg; + const struct rtw89_hfc_prec_cfg *prec_cfg = ¶m->prec_cfg; if (ch >= RTW89_DMA_CH_NUM) return -EINVAL; @@ -541,7 +541,7 @@ static int hfc_ch_cfg_chk(struct rtw89_dev *rtwdev, u8 ch) static int hfc_pub_info_chk(struct rtw89_dev *rtwdev) { struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param; - struct rtw89_hfc_pub_cfg *cfg = param->pub_cfg; + const struct rtw89_hfc_pub_cfg *cfg = ¶m->pub_cfg; struct rtw89_hfc_pub_info *info = ¶m->pub_info; if (info->g0_used + info->g1_used + info->pub_aval != cfg->pub_max) { @@ -557,7 +557,7 @@ static int hfc_pub_info_chk(struct rtw89_dev *rtwdev) static int hfc_pub_cfg_chk(struct rtw89_dev *rtwdev) { struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param; - struct rtw89_hfc_pub_cfg *pub_cfg = param->pub_cfg; + const struct rtw89_hfc_pub_cfg *pub_cfg = ¶m->pub_cfg; if (pub_cfg->grp0 + pub_cfg->grp1 != pub_cfg->pub_max) return 0; @@ -568,7 +568,7 @@ static int hfc_pub_cfg_chk(struct rtw89_dev *rtwdev) static int hfc_ch_ctrl(struct rtw89_dev *rtwdev, u8 ch) { struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param; - struct rtw89_hfc_ch_cfg *cfg = param->ch_cfg; + const struct rtw89_hfc_ch_cfg *cfg = param->ch_cfg; int ret = 0; u32 val = 0; @@ -595,7 +595,7 @@ static int hfc_upd_ch_info(struct rtw89_dev *rtwdev, u8 ch) { struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param; struct rtw89_hfc_ch_info *info = param->ch_info; - struct rtw89_hfc_ch_cfg *cfg = param->ch_cfg; + const struct rtw89_hfc_ch_cfg *cfg = param->ch_cfg; u32 val; u32 ret; @@ -618,7 +618,7 @@ static int hfc_upd_ch_info(struct rtw89_dev *rtwdev, u8 ch) static int hfc_pub_ctrl(struct rtw89_dev *rtwdev) { - struct rtw89_hfc_pub_cfg *cfg = rtwdev->mac.hfc_param.pub_cfg; + const struct rtw89_hfc_pub_cfg *cfg = &rtwdev->mac.hfc_param.pub_cfg; u32 val; int ret; @@ -643,8 +643,8 @@ static int hfc_pub_ctrl(struct rtw89_dev *rtwdev) static int hfc_upd_mix_info(struct rtw89_dev *rtwdev) { struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param; - struct rtw89_hfc_pub_cfg *pub_cfg = param->pub_cfg; - struct rtw89_hfc_prec_cfg *prec_cfg = param->prec_cfg; + struct rtw89_hfc_pub_cfg *pub_cfg = ¶m->pub_cfg; + struct rtw89_hfc_prec_cfg *prec_cfg = ¶m->prec_cfg; struct rtw89_hfc_pub_info *info = ¶m->pub_info; u32 val; int ret; @@ -707,7 +707,7 @@ static int hfc_upd_mix_info(struct rtw89_dev *rtwdev) static void hfc_h2c_cfg(struct rtw89_dev *rtwdev) { struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param; - struct rtw89_hfc_prec_cfg *prec_cfg = param->prec_cfg; + const struct rtw89_hfc_prec_cfg *prec_cfg = ¶m->prec_cfg; u32 val; val = u32_encode_bits(prec_cfg->h2c_prec, B_AX_PREC_PAGE_CH12_MASK); @@ -721,8 +721,8 @@ static void hfc_h2c_cfg(struct rtw89_dev *rtwdev) static void hfc_mix_cfg(struct rtw89_dev *rtwdev) { struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param; - struct rtw89_hfc_pub_cfg *pub_cfg = param->pub_cfg; - struct rtw89_hfc_prec_cfg *prec_cfg = param->prec_cfg; + const struct rtw89_hfc_pub_cfg *pub_cfg = ¶m->pub_cfg; + const struct rtw89_hfc_prec_cfg *prec_cfg = ¶m->prec_cfg; u32 val; val = u32_encode_bits(prec_cfg->ch011_prec, B_AX_PREC_PAGE_CH011_MASK) | @@ -880,22 +880,14 @@ static int rtw89_mac_sub_pwr_seq(struct rtw89_dev *rtwdev, u8 cv_msk, static int rtw89_mac_pwr_seq(struct rtw89_dev *rtwdev, const struct rtw89_pwr_cfg * const *cfg_seq) { - u32 idx = 0; - const struct rtw89_pwr_cfg *cfg; int ret; - do { - cfg = cfg_seq[idx]; - if (!cfg) - break; - + for (; *cfg_seq; cfg_seq++) { ret = rtw89_mac_sub_pwr_seq(rtwdev, BIT(rtwdev->hal.cv), - PWR_INTF_MSK_PCIE, cfg); + PWR_INTF_MSK_PCIE, *cfg_seq); if (ret) return -EBUSY; - - idx++; - } while (1); + } return 0; } @@ -1024,7 +1016,7 @@ static int rtw89_mac_power_switch(struct rtw89_dev *rtwdev, bool on) if (test_bit(RTW89_FLAG_FW_RDY, rtwdev->flags)) __rtw89_leave_ps_mode(rtwdev); - val = rtw89_read8(rtwdev, 0x3F1) & 0x3; + val = rtw89_read32_mask(rtwdev, R_AX_IC_PWR_STATE, B_AX_WLMAC_PWR_STE_MASK); if (on && val == PWR_ACT) { rtw89_err(rtwdev, "MAC has already powered on\n"); return -EBUSY; @@ -1145,55 +1137,55 @@ static int rtw89_mac_sys_init(struct rtw89_dev *rtwdev) } /* PCIE 64 */ -struct rtw89_dle_size wde_size0 = { +const struct rtw89_dle_size wde_size0 = { RTW89_WDE_PG_64, 4095, 1, }; /* DLFW */ -struct rtw89_dle_size wde_size4 = { +const struct rtw89_dle_size wde_size4 = { RTW89_WDE_PG_64, 0, 4096, }; /* PCIE */ -struct rtw89_dle_size ple_size0 = { +const struct rtw89_dle_size ple_size0 = { RTW89_PLE_PG_128, 1520, 16, }; /* DLFW */ -struct rtw89_dle_size ple_size4 = { +const struct rtw89_dle_size ple_size4 = { RTW89_PLE_PG_128, 64, 1472, }; /* PCIE 64 */ -struct rtw89_wde_quota wde_qt0 = { +const struct rtw89_wde_quota wde_qt0 = { 3792, 196, 0, 107, }; /* DLFW */ -struct rtw89_wde_quota wde_qt4 = { +const struct rtw89_wde_quota wde_qt4 = { 0, 0, 0, 0, }; /* PCIE SCC */ -struct rtw89_ple_quota ple_qt4 = { +const struct rtw89_ple_quota ple_qt4 = { 264, 0, 16, 20, 26, 13, 356, 0, 32, 40, 8, }; /* PCIE SCC */ -struct rtw89_ple_quota ple_qt5 = { +const struct rtw89_ple_quota ple_qt5 = { 264, 0, 32, 20, 64, 13, 1101, 0, 64, 128, 120, }; /* DLFW */ -struct rtw89_ple_quota ple_qt13 = { +const struct rtw89_ple_quota ple_qt13 = { 0, 0, 16, 48, 0, 0, 0, 0, 0, 0, 0 }; -static struct rtw89_dle_mem *get_dle_mem_cfg(struct rtw89_dev *rtwdev, - enum rtw89_qta_mode mode) +static const struct rtw89_dle_mem *get_dle_mem_cfg(struct rtw89_dev *rtwdev, + enum rtw89_qta_mode mode) { struct rtw89_mac_info *mac = &rtwdev->mac; - struct rtw89_dle_mem *cfg; + const struct rtw89_dle_mem *cfg; cfg = &rtwdev->chip->dle_mem[mode]; if (!cfg) @@ -1213,8 +1205,8 @@ static struct rtw89_dle_mem *get_dle_mem_cfg(struct rtw89_dev *rtwdev, return cfg; } -static inline u32 dle_used_size(struct rtw89_dle_size *wde, - struct rtw89_dle_size *ple) +static inline u32 dle_used_size(const struct rtw89_dle_size *wde, + const struct rtw89_dle_size *ple) { return wde->pge_size * (wde->lnk_pge_num + wde->unlnk_pge_num) + ple->pge_size * (ple->lnk_pge_num + ple->unlnk_pge_num); @@ -1240,9 +1232,9 @@ static void dle_clk_en(struct rtw89_dev *rtwdev, bool enable) B_AX_DLE_WDE_CLK_EN | B_AX_DLE_PLE_CLK_EN); } -static int dle_mix_cfg(struct rtw89_dev *rtwdev, struct rtw89_dle_mem *cfg) +static int dle_mix_cfg(struct rtw89_dev *rtwdev, const struct rtw89_dle_mem *cfg) { - struct rtw89_dle_size *size_cfg; + const struct rtw89_dle_size *size_cfg; u32 val; u8 bound = 0; @@ -1297,32 +1289,38 @@ static int dle_mix_cfg(struct rtw89_dev *rtwdev, struct rtw89_dle_mem *cfg) return 0; } -#define SET_QUOTA(_x, _module, _idx) \ +#define INVALID_QT_WCPU U16_MAX +#define SET_QUOTA_VAL(_min_x, _max_x, _module, _idx) \ do { \ - val = (min_cfg->_x & \ + val = ((_min_x) & \ B_AX_ ## _module ## _MIN_SIZE_MASK) | \ - ((max_cfg->_x << 16) & \ + (((_max_x) << 16) & \ B_AX_ ## _module ## _MAX_SIZE_MASK); \ rtw89_write32(rtwdev, \ R_AX_ ## _module ## _QTA ## _idx ## _CFG, \ val); \ } while (0) +#define SET_QUOTA(_x, _module, _idx) \ + SET_QUOTA_VAL(min_cfg->_x, max_cfg->_x, _module, _idx) static void wde_quota_cfg(struct rtw89_dev *rtwdev, - struct rtw89_wde_quota *min_cfg, - struct rtw89_wde_quota *max_cfg) + const struct rtw89_wde_quota *min_cfg, + const struct rtw89_wde_quota *max_cfg, + u16 ext_wde_min_qt_wcpu) { + u16 min_qt_wcpu = ext_wde_min_qt_wcpu != INVALID_QT_WCPU ? + ext_wde_min_qt_wcpu : min_cfg->wcpu; u32 val; SET_QUOTA(hif, WDE, 0); - SET_QUOTA(wcpu, WDE, 1); + SET_QUOTA_VAL(min_qt_wcpu, max_cfg->wcpu, WDE, 1); SET_QUOTA(pkt_in, WDE, 3); SET_QUOTA(cpu_io, WDE, 4); } static void ple_quota_cfg(struct rtw89_dev *rtwdev, - struct rtw89_ple_quota *min_cfg, - struct rtw89_ple_quota *max_cfg) + const struct rtw89_ple_quota *min_cfg, + const struct rtw89_ple_quota *max_cfg) { u32 val; @@ -1341,16 +1339,19 @@ static void ple_quota_cfg(struct rtw89_dev *rtwdev, #undef SET_QUOTA -static void dle_quota_cfg(struct rtw89_dev *rtwdev, struct rtw89_dle_mem *cfg) +static void dle_quota_cfg(struct rtw89_dev *rtwdev, + const struct rtw89_dle_mem *cfg, + u16 ext_wde_min_qt_wcpu) { - wde_quota_cfg(rtwdev, cfg->wde_min_qt, cfg->wde_max_qt); + wde_quota_cfg(rtwdev, cfg->wde_min_qt, cfg->wde_max_qt, ext_wde_min_qt_wcpu); ple_quota_cfg(rtwdev, cfg->ple_min_qt, cfg->ple_max_qt); } static int dle_init(struct rtw89_dev *rtwdev, enum rtw89_qta_mode mode, enum rtw89_qta_mode ext_mode) { - struct rtw89_dle_mem *cfg, *ext_cfg; + const struct rtw89_dle_mem *cfg, *ext_cfg; + u16 ext_wde_min_qt_wcpu = INVALID_QT_WCPU; int ret = 0; u32 ini; @@ -1373,7 +1374,7 @@ static int dle_init(struct rtw89_dev *rtwdev, enum rtw89_qta_mode mode, ret = -EINVAL; goto error; } - cfg->wde_min_qt->wcpu = ext_cfg->wde_min_qt->wcpu; + ext_wde_min_qt_wcpu = ext_cfg->wde_min_qt->wcpu; } if (dle_used_size(cfg->wde_size, cfg->ple_size) != rtwdev->chip->fifo_size) { @@ -1390,7 +1391,7 @@ static int dle_init(struct rtw89_dev *rtwdev, enum rtw89_qta_mode mode, rtw89_err(rtwdev, "[ERR] dle mix cfg\n"); goto error; } - dle_quota_cfg(rtwdev, cfg); + dle_quota_cfg(rtwdev, cfg, ext_wde_min_qt_wcpu); dle_func_en(rtwdev, true); @@ -1872,7 +1873,7 @@ static int cmac_com_init(struct rtw89_dev *rtwdev, u8 mac_idx) static bool is_qta_dbcc(struct rtw89_dev *rtwdev, enum rtw89_qta_mode mode) { - struct rtw89_dle_mem *cfg; + const struct rtw89_dle_mem *cfg; cfg = get_dle_mem_cfg(rtwdev, mode); if (!cfg) { @@ -2205,7 +2206,7 @@ static int rtw89_mac_set_cpuio(struct rtw89_dev *rtwdev, static int dle_quota_change(struct rtw89_dev *rtwdev, enum rtw89_qta_mode mode) { - struct rtw89_dle_mem *cfg; + const struct rtw89_dle_mem *cfg; struct rtw89_cpuio_ctrl ctrl_para = {0}; u16 pkt_id; int ret; @@ -2221,7 +2222,7 @@ static int dle_quota_change(struct rtw89_dev *rtwdev, enum rtw89_qta_mode mode) return -EINVAL; } - dle_quota_cfg(rtwdev, cfg); + dle_quota_cfg(rtwdev, cfg, INVALID_QT_WCPU); pkt_id = rtw89_mac_dle_buf_req(rtwdev, 0x20, true); if (pkt_id == 0xffff) { @@ -2672,6 +2673,7 @@ int rtw89_mac_init(struct rtw89_dev *rtwdev) goto fail; } + rtw89_fw_send_all_early_h2c(rtwdev); rtw89_fw_h2c_set_ofld_cfg(rtwdev); return ret; @@ -2904,9 +2906,7 @@ static void rtw89_mac_port_cfg_tbtt_early(struct rtw89_dev *rtwdev, static void rtw89_mac_port_cfg_bss_color(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0) struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); -#endif static const u32 masks[RTW89_PORT_NUM] = { B_AX_BSS_COLOB_AX_PORT_0_MASK, B_AX_BSS_COLOB_AX_PORT_1_MASK, B_AX_BSS_COLOB_AX_PORT_2_MASK, B_AX_BSS_COLOB_AX_PORT_3_MASK, @@ -2917,11 +2917,7 @@ static void rtw89_mac_port_cfg_bss_color(struct rtw89_dev *rtwdev, u32 reg; u8 bss_color; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0) bss_color = vif->bss_conf.he_bss_color.color; -#else - bss_color = 0; -#endif reg_base = port >= 4 ? R_AX_PTCL_BSS_COLOR_1 : R_AX_PTCL_BSS_COLOR_0; reg = rtw89_mac_reg_by_idx(reg_base, rtwvif->mac_idx); rtw89_write32_mask(rtwdev, reg, masks[port], bss_color); @@ -3121,7 +3117,8 @@ rtw89_mac_c2h_log(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len) RTW89_GET_C2H_LOG_SRT_PRT(c2h->data)); } -static void (*rtw89_mac_c2h_ofld_handler[])(struct rtw89_dev *rtwdev, +static +void (* const rtw89_mac_c2h_ofld_handler[])(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len) = { [RTW89_MAC_C2H_FUNC_EFUSE_DUMP] = NULL, [RTW89_MAC_C2H_FUNC_READ_RSP] = NULL, @@ -3130,7 +3127,8 @@ static void (*rtw89_mac_c2h_ofld_handler[])(struct rtw89_dev *rtwdev, [RTW89_MAC_C2H_FUNC_MACID_PAUSE] = rtw89_mac_c2h_macid_pause, }; -static void (*rtw89_mac_c2h_info_handler[])(struct rtw89_dev *rtwdev, +static +void (* const rtw89_mac_c2h_info_handler[])(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len) = { [RTW89_MAC_C2H_FUNC_REC_ACK] = rtw89_mac_c2h_rec_ack, [RTW89_MAC_C2H_FUNC_DONE_ACK] = rtw89_mac_c2h_done_ack, @@ -3170,7 +3168,7 @@ bool rtw89_mac_get_txpwr_cr(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, u32 reg_base, u32 *cr) { - struct rtw89_dle_mem *dle_mem = rtwdev->chip->dle_mem; + const struct rtw89_dle_mem *dle_mem = rtwdev->chip->dle_mem; enum rtw89_qta_mode mode = dle_mem->mode; u32 addr = rtw89_mac_reg_by_idx(reg_base, phy_idx); @@ -3430,6 +3428,7 @@ void rtw89_mac_cfg_sb(struct rtw89_dev *rtwdev, u32 val) FIELD_PREP(B_MAC_AX_SB_DRV_MASK, val) | FIELD_PREP(B_MAC_AX_SB_FW_MASK, fw_sb); rtw89_write32(rtwdev, R_AX_SCOREBOARD, val); + fsleep(1000); /* avoid BT FW loss information */ } u32 rtw89_mac_get_sb(struct rtw89_dev *rtwdev) diff --git a/mac.h b/mac.h index e1c9f485..6f3db8a2 100644 --- a/mac.h +++ b/mac.h @@ -660,16 +660,16 @@ enum mac_ax_err_info { MAC_AX_SET_ERR_MAX, }; -extern struct rtw89_hfc_prec_cfg rtw_hfc_preccfg_pcie; -extern struct rtw89_dle_size wde_size0; -extern struct rtw89_dle_size wde_size4; -extern struct rtw89_dle_size ple_size0; -extern struct rtw89_dle_size ple_size4; -extern struct rtw89_wde_quota wde_qt0; -extern struct rtw89_wde_quota wde_qt4; -extern struct rtw89_ple_quota ple_qt4; -extern struct rtw89_ple_quota ple_qt5; -extern struct rtw89_ple_quota ple_qt13; +extern const struct rtw89_hfc_prec_cfg rtw_hfc_preccfg_pcie; +extern const struct rtw89_dle_size wde_size0; +extern const struct rtw89_dle_size wde_size4; +extern const struct rtw89_dle_size ple_size0; +extern const struct rtw89_dle_size ple_size4; +extern const struct rtw89_wde_quota wde_qt0; +extern const struct rtw89_wde_quota wde_qt4; +extern const struct rtw89_ple_quota ple_qt4; +extern const struct rtw89_ple_quota ple_qt5; +extern const struct rtw89_ple_quota ple_qt13; static inline u32 rtw89_mac_reg_by_idx(u32 reg_base, u8 band) { diff --git a/mac80211.c b/mac80211.c index 2a56a7e7..16dc6fb7 100644 --- a/mac80211.c +++ b/mac80211.c @@ -469,12 +469,7 @@ static int rtw89_ops_ampdu_action(struct ieee80211_hw *hw, switch (params->action) { case IEEE80211_AMPDU_TX_START: -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) return IEEE80211_AMPDU_TX_START_IMMEDIATE; -#else - ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); - break; -#endif case IEEE80211_AMPDU_TX_STOP_CONT: case IEEE80211_AMPDU_TX_STOP_FLUSH: case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: @@ -579,6 +574,7 @@ static int rtw89_ops_set_bitrate_mask(struct ieee80211_hw *hw, struct rtw89_dev *rtwdev = hw->priv; mutex_lock(&rtwdev->mutex); + rtw89_phy_rate_pattern_vif(rtwdev, vif, mask); rtw89_ra_mask_info_update(rtwdev, vif, mask); mutex_unlock(&rtwdev->mutex); @@ -625,6 +621,7 @@ static void rtw89_ops_sw_scan_start(struct ieee80211_hw *hw, rtwdev->scanning = true; rtw89_leave_lps(rtwdev); rtw89_btc_ntfy_scan_start(rtwdev, RTW89_PHY_0, hal->current_band_type); + rtw89_chip_rfk_scan(rtwdev, true); rtw89_hci_recalc_int_mit(rtwdev); mutex_unlock(&rtwdev->mutex); } @@ -635,6 +632,7 @@ static void rtw89_ops_sw_scan_complete(struct ieee80211_hw *hw, struct rtw89_dev *rtwdev = hw->priv; mutex_lock(&rtwdev->mutex); + rtw89_chip_rfk_scan(rtwdev, false); rtw89_btc_ntfy_scan_finish(rtwdev, RTW89_PHY_0); rtwdev->scanning = false; rtwdev->dig.bypass_dig = true; @@ -673,8 +671,6 @@ const struct ieee80211_ops rtw89_ops = { .sw_scan_start = rtw89_ops_sw_scan_start, .sw_scan_complete = rtw89_ops_sw_scan_complete, .reconfig_complete = rtw89_ops_reconfig_complete, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) .set_sar_specs = rtw89_ops_set_sar_specs, -#endif }; EXPORT_SYMBOL(rtw89_ops); diff --git a/pci.c b/pci.c index d5a033cf..e9731012 100644 --- a/pci.c +++ b/pci.c @@ -2552,6 +2552,11 @@ static void rtw89_pci_clkreq_set(struct rtw89_dev *rtwdev, bool enable) if (rtw89_pci_disable_clkreq) return; + ret = rtw89_dbi_write8(rtwdev, RTW89_PCIE_CLK_CTRL, + PCIE_CLKDLY_HW_30US); + if (ret) + rtw89_err(rtwdev, "failed to set CLKREQ Delay\n"); + if (enable) ret = rtw89_dbi_write8_set(rtwdev, RTW89_PCIE_L1_CTRL, RTW89_PCIE_BIT_CLK); @@ -2565,11 +2570,24 @@ static void rtw89_pci_clkreq_set(struct rtw89_dev *rtwdev, bool enable) static void rtw89_pci_aspm_set(struct rtw89_dev *rtwdev, bool enable) { + u8 value = 0; int ret; if (rtw89_pci_disable_aspm_l1) return; + ret = rtw89_dbi_read8(rtwdev, RTW89_PCIE_ASPM_CTRL, &value); + if (ret) + rtw89_err(rtwdev, "failed to read ASPM Delay\n"); + + value &= ~(RTW89_L1DLY_MASK | RTW89_L0DLY_MASK); + value |= FIELD_PREP(RTW89_L1DLY_MASK, PCIE_L1DLY_16US) | + FIELD_PREP(RTW89_L0DLY_MASK, PCIE_L0SDLY_4US); + + ret = rtw89_dbi_write8(rtwdev, RTW89_PCIE_ASPM_CTRL, value); + if (ret) + rtw89_err(rtwdev, "failed to read ASPM Delay\n"); + if (enable) ret = rtw89_dbi_write8_set(rtwdev, RTW89_PCIE_L1_CTRL, RTW89_PCIE_BIT_L1); @@ -2581,24 +2599,6 @@ static void rtw89_pci_aspm_set(struct rtw89_dev *rtwdev, bool enable) enable ? "set" : "unset", ret); } -static void rtw89_pci_link_ps(struct rtw89_dev *rtwdev, bool enter) -{ - struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; - - /* Like CLKREQ, ASPM is also implemented by two HW modules, and can - * only be enabled when host supports it. - * - * And ASPM mechanism should be enabled when driver/firmware enters - * power save mode, without having heavy traffic. Because we've - * experienced some inter-operability issues that the link tends - * to enter L1 state on the fly even when driver is having high - * throughput. This is probably because the ASPM behavior slightly - * varies from different SOC. - */ - if (rtwpci->link_ctrl & PCI_EXP_LNKCTL_ASPM_L1) - rtw89_pci_aspm_set(rtwdev, enter); -} - static void rtw89_pci_recalc_int_mit(struct rtw89_dev *rtwdev) { struct rtw89_traffic_stats *stats = &rtwdev->stats; @@ -2648,7 +2648,8 @@ static void rtw89_pci_link_cfg(struct rtw89_dev *rtwdev) if (link_ctrl & PCI_EXP_LNKCTL_CLKREQ_EN) rtw89_pci_clkreq_set(rtwdev, true); - rtwpci->link_ctrl = link_ctrl; + if (link_ctrl & PCI_EXP_LNKCTL_ASPM_L1) + rtw89_pci_aspm_set(rtwdev, true); } static void rtw89_pci_l1ss_set(struct rtw89_dev *rtwdev, bool enable) @@ -2912,7 +2913,6 @@ static const struct rtw89_hci_ops rtw89_pci_ops = { .reset = rtw89_pci_ops_reset, .start = rtw89_pci_ops_start, .stop = rtw89_pci_ops_stop, - .link_ps = rtw89_pci_link_ps, .recalc_int_mit = rtw89_pci_recalc_int_mit, .read8 = rtw89_pci_ops_read8, diff --git a/pci.h b/pci.h index 7693181f..34333c44 100644 --- a/pci.h +++ b/pci.h @@ -334,6 +334,9 @@ #define RTW89_PCI_MULTITAG 8 /* PCIE CFG register */ +#define RTW89_PCIE_ASPM_CTRL 0x070F +#define RTW89_L1DLY_MASK GENMASK(5, 3) +#define RTW89_L0DLY_MASK GENMASK(2, 0) #define RTW89_PCIE_TIMER_CTRL 0x0718 #define RTW89_PCIE_BIT_L1SUB BIT(5) #define RTW89_PCIE_L1_CTRL 0x0719 @@ -358,13 +361,30 @@ enum mac_ax_func_sw { MAC_AX_FUNC_EN, }; +enum rtw89_pcie_l0sdly { + PCIE_L0SDLY_1US = 0, + PCIE_L0SDLY_2US = 1, + PCIE_L0SDLY_3US = 2, + PCIE_L0SDLY_4US = 3, + PCIE_L0SDLY_5US = 4, + PCIE_L0SDLY_6US = 5, + PCIE_L0SDLY_7US = 6, +}; + +enum rtw89_pcie_l1dly { + PCIE_L1DLY_16US = 4, + PCIE_L1DLY_32US = 5, + PCIE_L1DLY_64US = 6, + PCIE_L1DLY_HW_INFI = 7, +}; + enum rtw89_pcie_clkdly_hw { PCIE_CLKDLY_HW_0 = 0, PCIE_CLKDLY_HW_30US = 0x1, PCIE_CLKDLY_HW_50US = 0x2, PCIE_CLKDLY_HW_100US = 0x3, PCIE_CLKDLY_HW_150US = 0x4, - PCIE_CLKDLY_HW_200US = 0x5 + PCIE_CLKDLY_HW_200US = 0x5, }; struct rtw89_pci_bd_ram { @@ -522,7 +542,6 @@ struct rtw89_pci { u32 halt_c2h_intrs; u32 intrs[2]; - u16 link_ctrl; void __iomem *mmap; }; diff --git a/phy.c b/phy.c index fe99b6ee..53c36cc8 100644 --- a/phy.c +++ b/phy.c @@ -8,6 +8,7 @@ #include "ps.h" #include "reg.h" #include "sar.h" +#include "coex.h" static u16 get_max_amsdu_len(struct rtw89_dev *rtwdev, const struct rtw89_ra_report *report) @@ -189,6 +190,7 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev, { struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; struct rtw89_vif *rtwvif = rtwsta->rtwvif; + struct rtw89_phy_rate_pattern *rate_pattern = &rtwvif->rate_pattern; struct rtw89_ra_info *ra = &rtwsta->ra; const u64 *high_rate_masks = rtw89_ra_mask_ht_rates; u8 rssi = ewma_rssi_read(&rtwsta->avg_rssi); @@ -293,6 +295,12 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev, IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM) ra->dcm_cap = 1; + if (rate_pattern->enable) { + ra_mask = rtw89_phy_ra_mask_cfg(rtwdev, rtwsta); + ra_mask &= rate_pattern->ra_mask; + mode = rate_pattern->ra_mode; + } + ra->bw_cap = bw_mode; ra->mode_ctrl = mode; ra->macid = rtwsta->mac_id; @@ -333,6 +341,114 @@ void rtw89_phy_ra_updata_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta rtw89_fw_h2c_ra(rtwdev, ra, false); } +static bool __check_rate_pattern(struct rtw89_phy_rate_pattern *next, + u16 rate_base, u64 ra_mask, u8 ra_mode, + u32 rate_ctrl, u32 ctrl_skip, bool force) +{ + u8 n, c; + + if (rate_ctrl == ctrl_skip) + return true; + + n = hweight32(rate_ctrl); + if (n == 0) + return true; + + if (force && n != 1) + return false; + + if (next->enable) + return false; + + c = __fls(rate_ctrl); + next->rate = rate_base + c; + next->ra_mode = ra_mode; + next->ra_mask = ra_mask; + next->enable = true; + + return true; +} + +void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + const struct cfg80211_bitrate_mask *mask) +{ + struct ieee80211_supported_band *sband; + struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct rtw89_phy_rate_pattern next_pattern = {0}; + static const u16 hw_rate_he[] = {RTW89_HW_RATE_HE_NSS1_MCS0, + RTW89_HW_RATE_HE_NSS2_MCS0, + RTW89_HW_RATE_HE_NSS3_MCS0, + RTW89_HW_RATE_HE_NSS4_MCS0}; + static const u16 hw_rate_vht[] = {RTW89_HW_RATE_VHT_NSS1_MCS0, + RTW89_HW_RATE_VHT_NSS2_MCS0, + RTW89_HW_RATE_VHT_NSS3_MCS0, + RTW89_HW_RATE_VHT_NSS4_MCS0}; + static const u16 hw_rate_ht[] = {RTW89_HW_RATE_MCS0, + RTW89_HW_RATE_MCS8, + RTW89_HW_RATE_MCS16, + RTW89_HW_RATE_MCS24}; + u8 band = rtwdev->hal.current_band_type; + u8 tx_nss = rtwdev->hal.tx_nss; + u8 i; + + for (i = 0; i < tx_nss; i++) + if (!__check_rate_pattern(&next_pattern, hw_rate_he[i], + RA_MASK_HE_RATES, RTW89_RA_MODE_HE, + mask->control[band].he_mcs[i], + 0, true)) + goto out; + + for (i = 0; i < tx_nss; i++) + if (!__check_rate_pattern(&next_pattern, hw_rate_vht[i], + RA_MASK_VHT_RATES, RTW89_RA_MODE_VHT, + mask->control[band].vht_mcs[i], + 0, true)) + goto out; + + for (i = 0; i < tx_nss; i++) + if (!__check_rate_pattern(&next_pattern, hw_rate_ht[i], + RA_MASK_HT_RATES, RTW89_RA_MODE_HT, + mask->control[band].ht_mcs[i], + 0, true)) + goto out; + + /* lagacy cannot be empty for nl80211_parse_tx_bitrate_mask, and + * require at least one basic rate for ieee80211_set_bitrate_mask, + * so the decision just depends on if all bitrates are set or not. + */ + sband = rtwdev->hw->wiphy->bands[band]; + if (band == RTW89_BAND_2G) { + if (!__check_rate_pattern(&next_pattern, RTW89_HW_RATE_CCK1, + RA_MASK_CCK_RATES | RA_MASK_OFDM_RATES, + RTW89_RA_MODE_CCK | RTW89_RA_MODE_OFDM, + mask->control[band].legacy, + BIT(sband->n_bitrates) - 1, false)) + goto out; + } else { + if (!__check_rate_pattern(&next_pattern, RTW89_HW_RATE_OFDM6, + RA_MASK_OFDM_RATES, RTW89_RA_MODE_OFDM, + mask->control[band].legacy, + BIT(sband->n_bitrates) - 1, false)) + goto out; + } + + if (!next_pattern.enable) + goto out; + + rtwvif->rate_pattern = next_pattern; + rtw89_debug(rtwdev, RTW89_DBG_RA, + "configure pattern: rate 0x%x, mask 0x%llx, mode 0x%x\n", + next_pattern.rate, + next_pattern.ra_mask, + next_pattern.ra_mode); + return; + +out: + rtwvif->rate_pattern.enable = false; + rtw89_debug(rtwdev, RTW89_DBG_RA, "unset rate pattern\n"); +} + static void rtw89_phy_ra_updata_sta_iter(void *data, struct ieee80211_sta *sta) { struct rtw89_dev *rtwdev = (struct rtw89_dev *)data; @@ -978,11 +1094,7 @@ s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, u8 ch_idx = rtw89_channel_to_idx(rtwdev, ch); u8 band = rtwdev->hal.current_band_type; u8 regd = rtw89_regd_get(rtwdev, band); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) s8 lmt = 0, sar; -#else - s8 lmt = 0; -#endif switch (band) { case RTW89_BAND_2G: @@ -997,12 +1109,9 @@ s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, } lmt = _phy_txpwr_rf_to_mac(rtwdev, lmt); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) sar = rtw89_query_sar(rtwdev); + return min(lmt, sar); -#else - return lmt; -#endif } #define __fill_txpwr_limit_nonbf_bf(ptr, bw, ntx, rs, ch) \ @@ -1110,11 +1219,7 @@ static s8 rtw89_phy_read_txpwr_limit_ru(struct rtw89_dev *rtwdev, u8 ch_idx = rtw89_channel_to_idx(rtwdev, ch); u8 band = rtwdev->hal.current_band_type; u8 regd = rtw89_regd_get(rtwdev, band); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) s8 lmt_ru = 0, sar; -#else - s8 lmt_ru = 0; -#endif switch (band) { case RTW89_BAND_2G: @@ -1129,13 +1234,9 @@ static s8 rtw89_phy_read_txpwr_limit_ru(struct rtw89_dev *rtwdev, } lmt_ru = _phy_txpwr_rf_to_mac(rtwdev, lmt_ru); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) sar = rtw89_query_sar(rtwdev); return min(lmt_ru, sar); -#else - return lmt_ru; -#endif } static void @@ -1254,8 +1355,11 @@ static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta) break; case RTW89_RA_RPT_MODE_HT: ra_report->txrate.flags |= RATE_INFO_FLAGS_MCS; - rate = RTW89_MK_HT_RATE(FIELD_GET(RTW89_RA_RATE_MASK_NSS, rate), - FIELD_GET(RTW89_RA_RATE_MASK_MCS, rate)); + if (rtwdev->fw.old_ht_ra_format) + rate = RTW89_MK_HT_RATE(FIELD_GET(RTW89_RA_RATE_MASK_NSS, rate), + FIELD_GET(RTW89_RA_RATE_MASK_MCS, rate)); + else + rate = FIELD_GET(RTW89_RA_RATE_MASK_HT_MCS, rate); ra_report->txrate.mcs = rate; if (giltf) ra_report->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; @@ -1306,8 +1410,9 @@ rtw89_phy_c2h_ra_rpt(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len) &ra_data); } -static void (*rtw89_phy_c2h_ra_handler[])(struct rtw89_dev *rtwdev, - struct sk_buff *c2h, u32 len) = { +static +void (* const rtw89_phy_c2h_ra_handler[])(struct rtw89_dev *rtwdev, + struct sk_buff *c2h, u32 len) = { [RTW89_PHY_C2H_FUNC_STS_RPT] = rtw89_phy_c2h_ra_rpt, [RTW89_PHY_C2H_FUNC_MU_GPTBL_RPT] = NULL, [RTW89_PHY_C2H_FUNC_TXSTS] = NULL, @@ -1534,7 +1639,6 @@ static s32 rtw89_phy_multi_sta_cfo_calc(struct rtw89_dev *rtwdev) u8 active_entry_cnt = 0; u8 sta_cnt = 0; u32 tp_all = 0; - u64 active_entry = 0; u8 i; u8 cfo_tol = 0; @@ -1557,7 +1661,6 @@ static s32 rtw89_phy_multi_sta_cfo_calc(struct rtw89_dev *rtwdev) for (i = 0; i < CFO_TRACK_MAX_USER; i++) { if (cfo->cfo_cnt[i] == 0) continue; - active_entry |= BIT_ULL(i); cfo->cfo_avg[i] = phy_div(cfo->cfo_tail[i], (s32)cfo->cfo_cnt[i]); cfo_khz_all += cfo->cfo_avg[i]; @@ -1777,6 +1880,7 @@ static void rtw89_phy_stat_thermal_update(struct rtw89_dev *rtwdev) struct rtw89_phy_iter_rssi_data { struct rtw89_dev *rtwdev; struct rtw89_phy_ch_info *ch_info; + bool rssi_changed; }; static void rtw89_phy_stat_rssi_update_iter(void *data, @@ -1785,7 +1889,6 @@ static void rtw89_phy_stat_rssi_update_iter(void *data, struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; struct rtw89_phy_iter_rssi_data *rssi_data = (struct rtw89_phy_iter_rssi_data *)data; - struct rtw89_dev *rtwdev = rssi_data->rtwdev; struct rtw89_phy_ch_info *ch_info = rssi_data->ch_info; unsigned long rssi_curr; @@ -1800,13 +1903,13 @@ static void rtw89_phy_stat_rssi_update_iter(void *data, rtwsta->prev_rssi = rssi_curr; } else if (abs((int)rtwsta->prev_rssi - (int)rssi_curr) > (3 << RSSI_FACTOR)) { rtwsta->prev_rssi = rssi_curr; - ieee80211_queue_work(rtwdev->hw, &rtwdev->btc.wl_sta_notify_work); + rssi_data->rssi_changed = true; } } static void rtw89_phy_stat_rssi_update(struct rtw89_dev *rtwdev) { - struct rtw89_phy_iter_rssi_data rssi_data; + struct rtw89_phy_iter_rssi_data rssi_data = {0}; rssi_data.rtwdev = rtwdev; rssi_data.ch_info = &rtwdev->ch_info; @@ -1814,6 +1917,8 @@ static void rtw89_phy_stat_rssi_update(struct rtw89_dev *rtwdev) ieee80211_iterate_stations_atomic(rtwdev->hw, rtw89_phy_stat_rssi_update_iter, &rssi_data); + if (rssi_data.rssi_changed) + rtw89_btc_ntfy_wl_sta(rtwdev); } static void rtw89_phy_stat_init(struct rtw89_dev *rtwdev) diff --git a/phy.h b/phy.h index 53d71d29..37012934 100644 --- a/phy.h +++ b/phy.h @@ -35,14 +35,17 @@ #define RA_MASK_HT_2SS_RATES GENMASK_ULL(31, 24) #define RA_MASK_HT_3SS_RATES GENMASK_ULL(43, 36) #define RA_MASK_HT_4SS_RATES GENMASK_ULL(55, 48) +#define RA_MASK_HT_RATES GENMASK_ULL(55, 12) #define RA_MASK_VHT_1SS_RATES GENMASK_ULL(21, 12) #define RA_MASK_VHT_2SS_RATES GENMASK_ULL(33, 24) #define RA_MASK_VHT_3SS_RATES GENMASK_ULL(45, 36) #define RA_MASK_VHT_4SS_RATES GENMASK_ULL(57, 48) +#define RA_MASK_VHT_RATES GENMASK_ULL(57, 12) #define RA_MASK_HE_1SS_RATES GENMASK_ULL(23, 12) #define RA_MASK_HE_2SS_RATES GENMASK_ULL(35, 24) #define RA_MASK_HE_3SS_RATES GENMASK_ULL(47, 36) #define RA_MASK_HE_4SS_RATES GENMASK_ULL(59, 48) +#define RA_MASK_HE_RATES GENMASK_ULL(59, 12) #define CFO_TRK_ENABLE_TH (2 << 2) #define CFO_TRK_STOP_TH_4 (30 << 2) @@ -288,6 +291,9 @@ s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, void rtw89_phy_ra_assoc(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta); void rtw89_phy_ra_update(struct rtw89_dev *rtwdev); void rtw89_phy_ra_updata_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta); +void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + const struct cfg80211_bitrate_mask *mask); void rtw89_phy_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb, u32 len, u8 class, u8 func); void rtw89_phy_cfo_track(struct rtw89_dev *rtwdev); diff --git a/ps.c b/ps.c index 5cde9276..7eaa01e4 100644 --- a/ps.c +++ b/ps.c @@ -90,7 +90,6 @@ void rtw89_enter_lps(struct rtw89_dev *rtwdev, u8 mac_id) __rtw89_enter_lps(rtwdev, mac_id); __rtw89_enter_ps_mode(rtwdev); - rtw89_hci_link_ps(rtwdev, true); } static void rtw89_leave_lps_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) @@ -111,7 +110,6 @@ void rtw89_leave_lps(struct rtw89_dev *rtwdev) if (!test_and_clear_bit(RTW89_FLAG_LEISURE_PS, rtwdev->flags)) return; - rtw89_hci_link_ps(rtwdev, false); rtw89_for_each_rtwvif(rtwdev, rtwvif) rtw89_leave_lps_vif(rtwdev, rtwvif); } @@ -126,7 +124,6 @@ void rtw89_enter_ips(struct rtw89_dev *rtwdev) rtw89_mac_vif_deinit(rtwdev, rtwvif); rtw89_core_stop(rtwdev); - rtw89_hci_link_ps(rtwdev, true); } void rtw89_leave_ips(struct rtw89_dev *rtwdev) @@ -134,7 +131,6 @@ void rtw89_leave_ips(struct rtw89_dev *rtwdev) struct rtw89_vif *rtwvif; int ret; - rtw89_hci_link_ps(rtwdev, false); ret = rtw89_core_start(rtwdev); if (ret) rtw89_err(rtwdev, "failed to leave idle state\n"); diff --git a/reg.h b/reg.h index aff8565d..365d8c8c 100644 --- a/reg.h +++ b/reg.h @@ -144,6 +144,14 @@ #define B_AX_WLRF_CTRL_7 BIT(7) #define B_AX_WLRF_CTRL_1 BIT(1) +#define R_AX_IC_PWR_STATE 0x03F0 +#define B_AX_WHOLE_SYS_PWR_STE_MASK GENMASK(25, 16) +#define B_AX_WLMAC_PWR_STE_MASK GENMASK(9, 8) +#define B_AX_UART_HCISYS_PWR_STE_MASK GENMASK(7, 6) +#define B_AX_SDIO_HCISYS_PWR_STE_MASK GENMASK(5, 4) +#define B_AX_USB_HCISYS_PWR_STE_MASK GENMASK(3, 2) +#define B_AX_PCIE_HCISYS_PWR_STE_MASK GENMASK(1, 0) + #define R_AX_FILTER_MODEL_ADDR 0x0C04 #define R_AX_PCIE_DBG_CTRL 0x11C0 @@ -1780,6 +1788,8 @@ #define R_TSSI_THER 0x1C10 #define B_TSSI_THER GENMASK(29, 24) #define R_TXAGC_BB 0x1C60 +#define B_TXAGC_BB_OFT GENMASK(31, 16) +#define B_TXAGC_BB GENMASK(31, 24) #define R_S0_ADDCK 0x1E00 #define B_S0_ADDCK_I GENMASK(9, 0) #define B_S0_ADDCK_Q GENMASK(19, 10) @@ -1821,6 +1831,8 @@ #define B_S1_RXDC2_SEL GENMASK(9, 8) #define B_S1_RXDC2_Q2 GENMASK(3, 0) #define R_TXAGC_BB_S1 0x3C60 +#define B_TXAGC_BB_S1_OFT GENMASK(31, 16) +#define B_TXAGC_BB_S1 GENMASK(31, 24) #define R_S1_ADDCK 0x3E00 #define B_S1_ADDCK_I GENMASK(9, 0) #define B_S1_ADDCK_Q GENMASK(19, 10) @@ -1940,6 +1952,10 @@ #define B_P0_TMETER_TRK BIT(24) #define R_P0_TSSI_TRK 0x5818 #define B_P0_TSSI_TRK_EN BIT(30) +#define B_P0_TSSI_OFT_EN BIT(28) +#define B_P0_TSSI_OFT GENMASK(7, 0) +#define R_P0_TSSI_AVG 0x5820 +#define B_P0_TSSI_AVG GENMASK(15, 12) #define R_P0_RFCTM 0x5864 #define B_P0_RFCTM_VAL GENMASK(25, 20) #define R_P0_RFCTM_RDY BIT(26) @@ -1948,6 +1964,8 @@ #define R_P0_TXPW_RSTB 0x58DC #define B_P0_TXPW_RSTB_MANON BIT(30) #define B_P0_TXPW_RSTB_TSSI BIT(31) +#define R_P0_TSSI_MV_AVG 0x58E4 +#define B_P0_TSSI_MV_AVG GENMASK(13, 11) #define R_TXGAIN_SCALE 0x58F0 #define B_TXGAIN_SCALE_EN BIT(19) #define B_TXGAIN_SCALE_OFT GENMASK(31, 24) @@ -1976,12 +1994,18 @@ #define B_P1_TMETER_TRK BIT(24) #define R_P1_TSSI_TRK 0x7818 #define B_P1_TSSI_TRK_EN BIT(30) +#define B_P1_TSSI_OFT_EN BIT(28) +#define B_P1_TSSI_OFT GENMASK(7, 0) +#define R_P1_TSSI_AVG 0x7820 +#define B_P1_TSSI_AVG GENMASK(15, 12) #define R_P1_RFCTM 0x7864 #define R_P1_RFCTM_RDY BIT(26) #define B_P1_RFCTM_VAL GENMASK(25, 20) #define R_P1_TXPW_RSTB 0x78DC #define B_P1_TXPW_RSTB_MANON BIT(30) #define B_P1_TXPW_RSTB_TSSI BIT(31) +#define R_P1_TSSI_MV_AVG 0x78E4 +#define B_P1_TSSI_MV_AVG GENMASK(13, 11) #define R_TSSI_THOF 0x7C00 #define R_S1_DACKI 0x7E00 #define B_S1_DACKI_AR GENMASK(31, 28) diff --git a/rtw8852a.c b/rtw8852a.c index 1533cc80..b1b87f0a 100644 --- a/rtw8852a.c +++ b/rtw8852a.c @@ -11,7 +11,7 @@ #include "rtw8852a_table.h" #include "txrx.h" -static struct rtw89_hfc_ch_cfg rtw8852a_hfc_chcfg_pcie[] = { +static const struct rtw89_hfc_ch_cfg rtw8852a_hfc_chcfg_pcie[] = { {128, 1896, grp_0}, /* ACH 0 */ {128, 1896, grp_0}, /* ACH 1 */ {128, 1896, grp_0}, /* ACH 2 */ @@ -27,21 +27,21 @@ static struct rtw89_hfc_ch_cfg rtw8852a_hfc_chcfg_pcie[] = { {40, 0, 0} /* FWCMDQ */ }; -static struct rtw89_hfc_pub_cfg rtw8852a_hfc_pubcfg_pcie = { +static const struct rtw89_hfc_pub_cfg rtw8852a_hfc_pubcfg_pcie = { 1896, /* Group 0 */ 1896, /* Group 1 */ 3792, /* Public Max */ 0 /* WP threshold */ }; -static struct rtw89_hfc_param_ini rtw8852a_hfc_param_ini_pcie[] = { +static const struct rtw89_hfc_param_ini rtw8852a_hfc_param_ini_pcie[] = { [RTW89_QTA_SCC] = {rtw8852a_hfc_chcfg_pcie, &rtw8852a_hfc_pubcfg_pcie, &rtw_hfc_preccfg_pcie, RTW89_HCIFC_POH}, [RTW89_QTA_DLFW] = {NULL, NULL, &rtw_hfc_preccfg_pcie, RTW89_HCIFC_POH}, [RTW89_QTA_INVALID] = {NULL}, }; -static struct rtw89_dle_mem rtw8852a_dle_mem_pcie[] = { +static const struct rtw89_dle_mem rtw8852a_dle_mem_pcie[] = { [RTW89_QTA_SCC] = {RTW89_QTA_SCC, &wde_size0, &ple_size0, &wde_qt0, &wde_qt0, &ple_qt4, &ple_qt5}, [RTW89_QTA_DLFW] = {RTW89_QTA_DLFW, &wde_size4, &ple_size4, @@ -1200,6 +1200,11 @@ static void rtw8852a_rfk_band_changed(struct rtw89_dev *rtwdev) rtw8852a_tssi_scan(rtwdev, RTW89_PHY_0); } +static void rtw8852a_rfk_scan(struct rtw89_dev *rtwdev, bool start) +{ + rtw8852a_wifi_scan_notify(rtwdev, start, RTW89_PHY_0); +} + static void rtw8852a_rfk_track(struct rtw89_dev *rtwdev) { rtw8852a_dpk_track(rtwdev); @@ -1949,6 +1954,7 @@ static const struct rtw89_chip_ops rtw8852a_chip_ops = { .rfk_init = rtw8852a_rfk_init, .rfk_channel = rtw8852a_rfk_channel, .rfk_band_changed = rtw8852a_rfk_band_changed, + .rfk_scan = rtw8852a_rfk_scan, .rfk_track = rtw8852a_rfk_track, .power_trim = rtw8852a_power_trim, .set_txpwr = rtw8852a_set_txpwr, diff --git a/rtw8852a_rfk.c b/rtw8852a_rfk.c index eba31fa8..c021e93e 100644 --- a/rtw8852a_rfk.c +++ b/rtw8852a_rfk.c @@ -3799,3 +3799,113 @@ void rtw8852a_tssi_track(struct rtw89_dev *rtwdev) { _tssi_track(rtwdev); } + +static +void _rtw8852a_tssi_avg_scan(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy) +{ + if (!rtwdev->is_tssi_mode[RF_PATH_A] && !rtwdev->is_tssi_mode[RF_PATH_B]) + return; + + /* disable */ + rtw89_rfk_parser(rtwdev, &rtw8852a_tssi_disable_defs_tbl); + + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_AVG, B_P0_TSSI_AVG, 0x0); + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_MV_AVG, B_P0_TSSI_MV_AVG, 0x0); + + rtw89_phy_write32_mask(rtwdev, R_P1_TSSI_AVG, B_P1_TSSI_AVG, 0x0); + rtw89_phy_write32_mask(rtwdev, R_P1_TSSI_MV_AVG, B_P1_TSSI_MV_AVG, 0x0); + + /* enable */ + rtw89_rfk_parser(rtwdev, &rtw8852a_tssi_enable_defs_ab_tbl); +} + +static +void _rtw8852a_tssi_set_avg(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy) +{ + if (!rtwdev->is_tssi_mode[RF_PATH_A] && !rtwdev->is_tssi_mode[RF_PATH_B]) + return; + + /* disable */ + rtw89_rfk_parser(rtwdev, &rtw8852a_tssi_disable_defs_tbl); + + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_AVG, B_P0_TSSI_AVG, 0x4); + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_MV_AVG, B_P0_TSSI_MV_AVG, 0x2); + + rtw89_phy_write32_mask(rtwdev, R_P1_TSSI_AVG, B_P1_TSSI_AVG, 0x4); + rtw89_phy_write32_mask(rtwdev, R_P1_TSSI_MV_AVG, B_P1_TSSI_MV_AVG, 0x2); + + /* enable */ + rtw89_rfk_parser(rtwdev, &rtw8852a_tssi_enable_defs_ab_tbl); +} + +static void rtw8852a_tssi_set_avg(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy, bool enable) +{ + if (!rtwdev->is_tssi_mode[RF_PATH_A] && !rtwdev->is_tssi_mode[RF_PATH_B]) + return; + + if (enable) { + /* SCAN_START */ + _rtw8852a_tssi_avg_scan(rtwdev, phy); + } else { + /* SCAN_END */ + _rtw8852a_tssi_set_avg(rtwdev, phy); + } +} + +static void rtw8852a_tssi_default_txagc(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy, bool enable) +{ + struct rtw89_tssi_info *tssi_info = &rtwdev->tssi; + u8 i; + + if (!rtwdev->is_tssi_mode[RF_PATH_A] && !rtwdev->is_tssi_mode[RF_PATH_B]) + return; + + if (enable) { + if (rtw89_phy_read32_mask(rtwdev, R_TXAGC_BB, B_TXAGC_BB_OFT) != 0xc000 && + rtw89_phy_read32_mask(rtwdev, R_TXAGC_BB, B_TXAGC_BB_OFT) != 0x0) { + for (i = 0; i < 6; i++) { + tssi_info->default_txagc_offset[RF_PATH_A] = + rtw89_phy_read32_mask(rtwdev, R_TXAGC_BB, + B_TXAGC_BB); + if (tssi_info->default_txagc_offset[RF_PATH_A]) + break; + } + } + + if (rtw89_phy_read32_mask(rtwdev, R_TXAGC_BB_S1, B_TXAGC_BB_S1_OFT) != 0xc000 && + rtw89_phy_read32_mask(rtwdev, R_TXAGC_BB_S1, B_TXAGC_BB_S1_OFT) != 0x0) { + for (i = 0; i < 6; i++) { + tssi_info->default_txagc_offset[RF_PATH_B] = + rtw89_phy_read32_mask(rtwdev, R_TXAGC_BB_S1, + B_TXAGC_BB_S1); + if (tssi_info->default_txagc_offset[RF_PATH_B]) + break; + } + } + } else { + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT, + tssi_info->default_txagc_offset[RF_PATH_A]); + rtw89_phy_write32_mask(rtwdev, R_P1_TSSI_TRK, B_P1_TSSI_OFT, + tssi_info->default_txagc_offset[RF_PATH_B]); + + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT_EN, 0x0); + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT_EN, 0x1); + + rtw89_phy_write32_mask(rtwdev, R_P1_TSSI_TRK, B_P1_TSSI_OFT_EN, 0x0); + rtw89_phy_write32_mask(rtwdev, R_P1_TSSI_TRK, B_P1_TSSI_OFT_EN, 0x1); + } +} + +void rtw8852a_wifi_scan_notify(struct rtw89_dev *rtwdev, + bool scan_start, enum rtw89_phy_idx phy_idx) +{ + if (scan_start) { + rtw8852a_tssi_default_txagc(rtwdev, phy_idx, true); + rtw8852a_tssi_set_avg(rtwdev, phy_idx, true); + } else { + rtw8852a_tssi_default_txagc(rtwdev, phy_idx, false); + rtw8852a_tssi_set_avg(rtwdev, phy_idx, false); + } +} diff --git a/rtw8852a_rfk.h b/rtw8852a_rfk.h index a6da27fd..ea36553a 100644 --- a/rtw8852a_rfk.h +++ b/rtw8852a_rfk.h @@ -18,5 +18,7 @@ void rtw8852a_dpk_track(struct rtw89_dev *rtwdev); void rtw8852a_tssi(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy); void rtw8852a_tssi_scan(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy); void rtw8852a_tssi_track(struct rtw89_dev *rtwdev); +void rtw8852a_wifi_scan_notify(struct rtw89_dev *rtwdev, bool scan_start, + enum rtw89_phy_idx phy_idx); #endif diff --git a/rtw8852a_rfk_table.c b/rtw8852a_rfk_table.c index 91c0fade..51057009 100644 --- a/rtw8852a_rfk_table.c +++ b/rtw8852a_rfk_table.c @@ -962,6 +962,17 @@ static const struct rtw89_reg5_def rtw8852a_tssi_disable_defs[] = { DECLARE_RFK_TBL(rtw8852a_tssi_disable_defs); +static const struct rtw89_reg5_def rtw8852a_tssi_enable_defs_ab[] = { + DECL_RFK_WM(0x5820, 0x80000000, 0x0), + DECL_RFK_WM(0x5820, 0x80000000, 0x1), + DECL_RFK_WM(0x5818, 0x18000000, 0x3), + DECL_RFK_WM(0x7820, 0x80000000, 0x0), + DECL_RFK_WM(0x7820, 0x80000000, 0x1), + DECL_RFK_WM(0x7818, 0x18000000, 0x3), +}; + +DECLARE_RFK_TBL(rtw8852a_tssi_enable_defs_ab); + static const struct rtw89_reg5_def rtw8852a_tssi_tracking_defs[] = { DECL_RFK_WM(0x5800, 0x10000000, 0x00000000), DECL_RFK_WM(0x58f0, 0x00080000, 0x00000000), diff --git a/rtw8852a_rfk_table.h b/rtw8852a_rfk_table.h index 2a4ba5b3..4a4a45d7 100644 --- a/rtw8852a_rfk_table.h +++ b/rtw8852a_rfk_table.h @@ -87,6 +87,7 @@ extern const struct rtw89_rfk_tbl rtw8852a_tssi_pak_defs_b_5g_3_tbl; extern const struct rtw89_rfk_tbl rtw8852a_tssi_pak_defs_b_5g_4_tbl; extern const struct rtw89_rfk_tbl rtw8852a_tssi_enable_defs_a_tbl; extern const struct rtw89_rfk_tbl rtw8852a_tssi_enable_defs_b_tbl; +extern const struct rtw89_rfk_tbl rtw8852a_tssi_enable_defs_ab_tbl; extern const struct rtw89_rfk_tbl rtw8852a_tssi_disable_defs_tbl; extern const struct rtw89_rfk_tbl rtw8852a_tssi_tracking_defs_tbl; diff --git a/rtw8852a_table.c b/rtw8852a_table.c index 60e1df4e..3a4fe720 100644 --- a/rtw8852a_table.c +++ b/rtw8852a_table.c @@ -1165,7 +1165,7 @@ static const struct rtw89_reg2_def rtw89_8852a_phy_bb_regs[] = { {0x12D8, 0x00000040}, {0x12DC, 0x4486888C}, {0x12E0, 0xC43A10E1}, - {0x12E4, 0x30D52A68}, + {0x12E4, 0x30D52C68}, {0x12E8, 0x02024128}, {0x12EC, 0x888C272B}, {0x12EC, 0x888CA72B}, @@ -1175,7 +1175,7 @@ static const struct rtw89_reg2_def rtw89_8852a_phy_bb_regs[] = { {0x32D8, 0x00000040}, {0x32DC, 0x4486888C}, {0x32E0, 0xC43A10E1}, - {0x32E4, 0x30D52A68}, + {0x32E4, 0x30D52C68}, {0x32E8, 0x02024128}, {0x32EC, 0x888C272B}, {0x32EC, 0x888CA72B}, diff --git a/sar.c b/sar.c index 527e144f..097c8789 100644 --- a/sar.c +++ b/sar.c @@ -5,7 +5,6 @@ #include "debug.h" #include "sar.h" -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) static int rtw89_query_sar_config_common(struct rtw89_dev *rtwdev, s32 *cfg) { struct rtw89_sar_cfg_common *rtwsar = &rtwdev->sar.cfg_common; @@ -189,4 +188,3 @@ int rtw89_ops_set_sar_specs(struct ieee80211_hw *hw, return rtw89_apply_sar_common(rtwdev, &sar_common); } -#endif diff --git a/sar.h b/sar.h index b24dab92..7b5484c8 100644 --- a/sar.h +++ b/sar.h @@ -10,7 +10,6 @@ #define RTW89_SAR_TXPWR_MAC_MAX S8_MAX #define RTW89_SAR_TXPWR_MAC_MIN S8_MIN -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) struct rtw89_sar_handler { const char *descr_sar_source; u8 txpwr_factor_sar; @@ -23,6 +22,5 @@ s8 rtw89_query_sar(struct rtw89_dev *rtwdev); void rtw89_print_sar(struct seq_file *m, struct rtw89_dev *rtwdev); int rtw89_ops_set_sar_specs(struct ieee80211_hw *hw, const struct cfg80211_sar_specs *sar); -#endif #endif diff --git a/txrx.h b/txrx.h index 0dc99cbc..f1e0fe36 100644 --- a/txrx.h +++ b/txrx.h @@ -23,84 +23,56 @@ #define GET_DATA_RATE_NSS(r) FIELD_GET(DATA_RATE_VHT_HE_NSS_MASK, r) /* TX WD BODY DWORD 0 */ -#define RTW89_SET_TXWD_BODY_WP_OFFSET(txdesc, val) \ - RTW89_SET_TXWD(txdesc, val, 0x00, GENMASK(31, 24)) -#define RTW89_SET_TXWD_BODY_MORE_DATA(txdesc, val) \ - RTW89_SET_TXWD(txdesc, val, 0x00, BIT(23)) -#define RTW89_SET_TXWD_BODY_WD_INFO_EN(txdesc, val) \ - RTW89_SET_TXWD(txdesc, val, 0x00, BIT(22)) -#define RTW89_SET_TXWD_BODY_FW_DL(txdesc, val) \ - RTW89_SET_TXWD(txdesc, val, 0x00, BIT(20)) -#define RTW89_SET_TXWD_BODY_CHANNEL_DMA(txdesc, val) \ - RTW89_SET_TXWD(txdesc, val, 0x00, GENMASK(19, 16)) -#define RTW89_SET_TXWD_BODY_HDR_LLC_LEN(txdesc, val) \ - RTW89_SET_TXWD(txdesc, val, 0x00, GENMASK(15, 11)) -#define RTW89_SET_TXWD_BODY_WD_PAGE(txdesc, val) \ - RTW89_SET_TXWD(txdesc, val, 0x00, BIT(7)) -#define RTW89_SET_TXWD_BODY_HW_AMSDU(txdesc, val) \ - RTW89_SET_TXWD(txdesc, val, 0x00, BIT(5)) +#define RTW89_TXWD_BODY0_WP_OFFSET GENMASK(31, 24) +#define RTW89_TXWD_BODY0_MORE_DATA BIT(23) +#define RTW89_TXWD_BODY0_WD_INFO_EN BIT(22) +#define RTW89_TXWD_BODY0_FW_DL BIT(20) +#define RTW89_TXWD_BODY0_CHANNEL_DMA GENMASK(19, 16) +#define RTW89_TXWD_BODY0_HDR_LLC_LEN GENMASK(15, 11) +#define RTW89_TXWD_BODY0_WD_PAGE BIT(7) +#define RTW89_TXWD_BODY0_HW_AMSDU BIT(5) /* TX WD BODY DWORD 1 */ -#define RTW89_SET_TXWD_BODY_PAYLOAD_ID(txdesc, val) \ - RTW89_SET_TXWD(txdesc, val, 0x01, GENMASK(31, 16)) +#define RTW89_TXWD_BODY1_PAYLOAD_ID GENMASK(31, 16) /* TX WD BODY DWORD 2 */ -#define RTW89_SET_TXWD_BODY_MACID(txdesc, val) \ - RTW89_SET_TXWD(txdesc, val, 0x02, GENMASK(30, 24)) -#define RTW89_SET_TXWD_BODY_TID_INDICATE(txdesc, val) \ - RTW89_SET_TXWD(txdesc, val, 0x02, BIT(23)) -#define RTW89_SET_TXWD_BODY_QSEL(txdesc, val) \ - RTW89_SET_TXWD(txdesc, val, 0x02, GENMASK(22, 17)) -#define RTW89_SET_TXWD_BODY_TXPKT_SIZE(txdesc, val) \ - RTW89_SET_TXWD(txdesc, val, 0x02, GENMASK(13, 0)) +#define RTW89_TXWD_BODY2_MACID GENMASK(30, 24) +#define RTW89_TXWD_BODY2_TID_INDICATE BIT(23) +#define RTW89_TXWD_BODY2_QSEL GENMASK(22, 17) +#define RTW89_TXWD_BODY2_TXPKT_SIZE GENMASK(13, 0) /* TX WD BODY DWORD 3 */ -#define RTW89_SET_TXWD_BODY_BK(txdesc, val) \ - RTW89_SET_TXWD(txdesc, val, 0x03, BIT(13)) -#define RTW89_SET_TXWD_BODY_AGG_EN(txdesc, val) \ - RTW89_SET_TXWD(txdesc, val, 0x03, BIT(12)) -#define RTW89_SET_TXWD_BODY_SW_SEQ(txdesc, val) \ - RTW89_SET_TXWD(txdesc, val, 0x03, GENMASK(11, 0)) +#define RTW89_TXWD_BODY3_BK BIT(13) +#define RTW89_TXWD_BODY3_AGG_EN BIT(12) +#define RTW89_TXWD_BODY3_SW_SEQ GENMASK(11, 0) /* TX WD BODY DWORD 4 */ /* TX WD BODY DWORD 5 */ /* TX WD INFO DWORD 0 */ -#define RTW89_SET_TXWD_INFO_USE_RATE(txdesc, val) \ - RTW89_SET_TXWD(txdesc, val, 0x6, BIT(30)) -#define RTW89_SET_TXWD_INFO_DATA_BW(txdesc, val) \ - RTW89_SET_TXWD(txdesc, val, 0x6, GENMASK(29, 28)) -#define RTW89_SET_TXWD_INFO_GI_LTF(txdesc, val) \ - RTW89_SET_TXWD(txdesc, val, 0x6, GENMASK(27, 25)) -#define RTW89_SET_TXWD_INFO_DATA_RATE(txdesc, val) \ - RTW89_SET_TXWD(txdesc, val, 0x6, GENMASK(24, 16)) -#define RTW89_SET_TXWD_INFO_DISDATAFB(txdesc, val) \ - RTW89_SET_TXWD(txdesc, val, 0x6, BIT(10)) +#define RTW89_TXWD_INFO0_USE_RATE BIT(30) +#define RTW89_TXWD_INFO0_DATA_BW GENMASK(29, 28) +#define RTW89_TXWD_INFO0_GI_LTF GENMASK(27, 25) +#define RTW89_TXWD_INFO0_DATA_RATE GENMASK(24, 16) +#define RTW89_TXWD_INFO0_DISDATAFB BIT(10) /* TX WD INFO DWORD 1 */ -#define RTW89_SET_TXWD_INFO_A_CTRL_BSR(txdesc, val) \ - RTW89_SET_TXWD(txdesc, val, 0x7, BIT(14)) -#define RTW89_SET_TXWD_INFO_MAX_AGGNUM(txdesc, val) \ - RTW89_SET_TXWD(txdesc, val, 0x7, GENMASK(7, 0)) +#define RTW89_TXWD_INFO1_DATA_RTY_LOWEST_RATE GENMASK(24, 16) +#define RTW89_TXWD_INFO1_A_CTRL_BSR BIT(14) +#define RTW89_TXWD_INFO1_MAX_AGGNUM GENMASK(7, 0) /* TX WD INFO DWORD 2 */ -#define RTW89_SET_TXWD_INFO_AMPDU_DENSITY(txdesc, val) \ - RTW89_SET_TXWD(txdesc, val, 0x8, GENMASK(20, 18)) -#define RTW89_SET_TXWD_INFO_SEC_TYPE(txdesc, val) \ - RTW89_SET_TXWD(txdesc, val, 0x8, GENMASK(12, 9)) -#define RTW89_SET_TXWD_INFO_SEC_HW_ENC(txdesc, val) \ - RTW89_SET_TXWD(txdesc, val, 0x8, BIT(8)) -#define RTW89_SET_TXWD_INFO_SEC_CAM_IDX(txdesc, val) \ - RTW89_SET_TXWD(txdesc, val, 0x8, GENMASK(7, 0)) +#define RTW89_TXWD_INFO2_AMPDU_DENSITY GENMASK(20, 18) +#define RTW89_TXWD_INFO2_SEC_TYPE GENMASK(12, 9) +#define RTW89_TXWD_INFO2_SEC_HW_ENC BIT(8) +#define RTW89_TXWD_INFO2_SEC_CAM_IDX GENMASK(7, 0) /* TX WD INFO DWORD 3 */ /* TX WD INFO DWORD 4 */ -#define RTW89_SET_TXWD_INFO_RTS_EN(txdesc, val) \ - RTW89_SET_TXWD(txdesc, val, 0xA, BIT(27)) -#define RTW89_SET_TXWD_INFO_HW_RTS_EN(txdesc, val) \ - RTW89_SET_TXWD(txdesc, val, 0xA, BIT(31)) +#define RTW89_TXWD_INFO4_RTS_EN BIT(27) +#define RTW89_TXWD_INFO4_HW_RTS_EN BIT(31) /* TX WD INFO DWORD 5 */ @@ -383,11 +355,4 @@ static inline u8 rtw89_core_get_tid_indicate(struct rtw89_dev *rtwdev, u8 tid) } } -static __always_inline void RTW89_SET_TXWD(u8 *txdesc, u32 val, u8 offset, u32 mask) -{ - u32 *txd32 = (u32 *)txdesc; - - le32p_replace_bits((__le32 *)(txd32 + offset), val, mask); -} - #endif