summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/realtek/rtw88
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/realtek/rtw88')
-rw-r--r--drivers/net/wireless/realtek/rtw88/coex.c3
-rw-r--r--drivers/net/wireless/realtek/rtw88/debug.c30
-rw-r--r--drivers/net/wireless/realtek/rtw88/fw.c17
-rw-r--r--drivers/net/wireless/realtek/rtw88/fw.h2
-rw-r--r--drivers/net/wireless/realtek/rtw88/mac80211.c27
-rw-r--r--drivers/net/wireless/realtek/rtw88/main.c11
-rw-r--r--drivers/net/wireless/realtek/rtw88/main.h2
-rw-r--r--drivers/net/wireless/realtek/rtw88/reg.h1
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8821c.c405
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8821c.h26
-rw-r--r--drivers/net/wireless/realtek/rtw88/tx.c104
-rw-r--r--drivers/net/wireless/realtek/rtw88/tx.h13
12 files changed, 594 insertions, 47 deletions
diff --git a/drivers/net/wireless/realtek/rtw88/coex.c b/drivers/net/wireless/realtek/rtw88/coex.c
index 3abae32341c4..aa08fd7d9fcd 100644
--- a/drivers/net/wireless/realtek/rtw88/coex.c
+++ b/drivers/net/wireless/realtek/rtw88/coex.c
@@ -1962,7 +1962,8 @@ static void rtw_coex_run_coex(struct rtw_dev *rtwdev, u8 reason)
if (coex_stat->wl_under_ips)
return;
- if (coex->freeze && !coex_stat->bt_setup_link)
+ if (coex->freeze && coex_dm->reason == COEX_RSN_BTINFO &&
+ !coex_stat->bt_setup_link)
return;
coex_stat->cnt_wl[COEX_CNT_WL_COEXRUN]++;
diff --git a/drivers/net/wireless/realtek/rtw88/debug.c b/drivers/net/wireless/realtek/rtw88/debug.c
index 09f04feb8fe1..f769c982cc91 100644
--- a/drivers/net/wireless/realtek/rtw88/debug.c
+++ b/drivers/net/wireless/realtek/rtw88/debug.c
@@ -344,6 +344,31 @@ static ssize_t rtw_debugfs_set_write_reg(struct file *filp,
return count;
}
+static ssize_t rtw_debugfs_set_h2c(struct file *filp,
+ const char __user *buffer,
+ size_t count, loff_t *loff)
+{
+ struct rtw_debugfs_priv *debugfs_priv = filp->private_data;
+ struct rtw_dev *rtwdev = debugfs_priv->rtwdev;
+ char tmp[32 + 1];
+ u8 param[8];
+ int num;
+
+ rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 3);
+
+ num = sscanf(tmp, "%hhx,%hhx,%hhx,%hhx,%hhx,%hhx,%hhx,%hhx",
+ &param[0], &param[1], &param[2], &param[3],
+ &param[4], &param[5], &param[6], &param[7]);
+ if (num != 8) {
+ rtw_info(rtwdev, "invalid H2C command format for debug\n");
+ return -EINVAL;
+ }
+
+ rtw_fw_h2c_cmd_dbg(rtwdev, param);
+
+ return count;
+}
+
static ssize_t rtw_debugfs_set_rf_write(struct file *filp,
const char __user *buffer,
size_t count, loff_t *loff)
@@ -808,6 +833,10 @@ static struct rtw_debugfs_priv rtw_debug_priv_write_reg = {
.cb_write = rtw_debugfs_set_write_reg,
};
+static struct rtw_debugfs_priv rtw_debug_priv_h2c = {
+ .cb_write = rtw_debugfs_set_h2c,
+};
+
static struct rtw_debugfs_priv rtw_debug_priv_rf_write = {
.cb_write = rtw_debugfs_set_rf_write,
};
@@ -877,6 +906,7 @@ void rtw_debugfs_init(struct rtw_dev *rtwdev)
rtw_debugfs_add_r(phy_info);
rtw_debugfs_add_r(coex_info);
rtw_debugfs_add_rw(coex_enable);
+ rtw_debugfs_add_w(h2c);
rtw_debugfs_add_r(mac_0);
rtw_debugfs_add_r(mac_1);
rtw_debugfs_add_r(mac_2);
diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c
index 6478fd7a78f6..63b00bc19000 100644
--- a/drivers/net/wireless/realtek/rtw88/fw.c
+++ b/drivers/net/wireless/realtek/rtw88/fw.c
@@ -253,6 +253,11 @@ out:
spin_unlock(&rtwdev->h2c.lock);
}
+void rtw_fw_h2c_cmd_dbg(struct rtw_dev *rtwdev, u8 *h2c)
+{
+ rtw_fw_send_h2c_command(rtwdev, h2c);
+}
+
static void rtw_fw_send_h2c_packet(struct rtw_dev *rtwdev, u8 *h2c_pkt)
{
int ret;
@@ -456,7 +461,7 @@ void rtw_fw_send_ra_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si)
SET_RA_INFO_INIT_RA_LVL(h2c_pkt, si->init_ra_lv);
SET_RA_INFO_SGI_EN(h2c_pkt, si->sgi_enable);
SET_RA_INFO_BW_MODE(h2c_pkt, si->bw_mode);
- SET_RA_INFO_LDPC(h2c_pkt, si->ldpc_en);
+ SET_RA_INFO_LDPC(h2c_pkt, !!si->ldpc_en);
SET_RA_INFO_NO_UPDATE(h2c_pkt, no_update);
SET_RA_INFO_VHT_EN(h2c_pkt, si->vht_enable);
SET_RA_INFO_DIS_PT(h2c_pkt, disable_pt);
@@ -915,14 +920,14 @@ static struct sk_buff *rtw_get_rsvd_page_skb(struct ieee80211_hw *hw,
return skb_new;
}
-static void rtw_fill_rsvd_page_desc(struct rtw_dev *rtwdev, struct sk_buff *skb)
+static void rtw_fill_rsvd_page_desc(struct rtw_dev *rtwdev, struct sk_buff *skb,
+ enum rtw_rsvd_packet_type type)
{
- struct rtw_tx_pkt_info pkt_info;
+ struct rtw_tx_pkt_info pkt_info = {0};
struct rtw_chip_info *chip = rtwdev->chip;
u8 *pkt_desc;
- memset(&pkt_info, 0, sizeof(pkt_info));
- rtw_rsvd_page_pkt_info_update(rtwdev, &pkt_info, skb);
+ rtw_tx_rsvd_page_pkt_info_update(rtwdev, &pkt_info, skb, type);
pkt_desc = skb_push(skb, chip->tx_pkt_desc_sz);
memset(pkt_desc, 0, chip->tx_pkt_desc_sz);
rtw_tx_fill_tx_desc(&pkt_info, skb);
@@ -1261,7 +1266,7 @@ static u8 *rtw_build_rsvd_page(struct rtw_dev *rtwdev, u32 *size)
* And iter->len will be added with size of tx_desc_sz.
*/
if (rsvd_pkt->add_txdesc)
- rtw_fill_rsvd_page_desc(rtwdev, iter);
+ rtw_fill_rsvd_page_desc(rtwdev, iter, rsvd_pkt->type);
rsvd_pkt->skb = iter;
rsvd_pkt->page = total_page;
diff --git a/drivers/net/wireless/realtek/rtw88/fw.h b/drivers/net/wireless/realtek/rtw88/fw.h
index 470e1809645a..686dcd3bbda6 100644
--- a/drivers/net/wireless/realtek/rtw88/fw.h
+++ b/drivers/net/wireless/realtek/rtw88/fw.h
@@ -563,4 +563,6 @@ void rtw_fw_set_nlo_info(struct rtw_dev *rtwdev, bool enable);
void rtw_fw_update_pkt_probe_req(struct rtw_dev *rtwdev,
struct cfg80211_ssid *ssid);
void rtw_fw_channel_switch(struct rtw_dev *rtwdev, bool enable);
+void rtw_fw_h2c_cmd_dbg(struct rtw_dev *rtwdev, u8 *h2c);
+
#endif
diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c b/drivers/net/wireless/realtek/rtw88/mac80211.c
index c412bc54efde..6b199152abcf 100644
--- a/drivers/net/wireless/realtek/rtw88/mac80211.c
+++ b/drivers/net/wireless/realtek/rtw88/mac80211.c
@@ -231,6 +231,23 @@ static void rtw_ops_remove_interface(struct ieee80211_hw *hw,
mutex_unlock(&rtwdev->mutex);
}
+static int rtw_ops_change_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ enum nl80211_iftype type, bool p2p)
+{
+ struct rtw_dev *rtwdev = hw->priv;
+
+ rtw_info(rtwdev, "change vif %pM (%d)->(%d), p2p (%d)->(%d)\n",
+ vif->addr, vif->type, type, vif->p2p, p2p);
+
+ rtw_ops_remove_interface(hw, vif);
+
+ vif->type = type;
+ vif->p2p = p2p;
+
+ return rtw_ops_add_interface(hw, vif);
+}
+
static void rtw_ops_configure_filter(struct ieee80211_hw *hw,
unsigned int changed_flags,
unsigned int *new_flags,
@@ -373,6 +390,15 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw,
if (changed & BSS_CHANGED_BEACON)
rtw_fw_download_rsvd_page(rtwdev);
+ if (changed & BSS_CHANGED_BEACON_ENABLED) {
+ if (conf->enable_beacon)
+ rtw_write32_set(rtwdev, REG_FWHW_TXQ_CTRL,
+ BIT_EN_BCNQ_DL);
+ else
+ rtw_write32_clr(rtwdev, REG_FWHW_TXQ_CTRL,
+ BIT_EN_BCNQ_DL);
+ }
+
if (changed & BSS_CHANGED_MU_GROUPS)
rtw_chip_set_gid_table(rtwdev, vif, conf);
@@ -827,6 +853,7 @@ const struct ieee80211_ops rtw_ops = {
.config = rtw_ops_config,
.add_interface = rtw_ops_add_interface,
.remove_interface = rtw_ops_remove_interface,
+ .change_interface = rtw_ops_change_interface,
.configure_filter = rtw_ops_configure_filter,
.bss_info_changed = rtw_ops_bss_info_changed,
.conf_tx = rtw_ops_conf_tx,
diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c
index 7304e8bc5e31..54044abf30d7 100644
--- a/drivers/net/wireless/realtek/rtw88/main.c
+++ b/drivers/net/wireless/realtek/rtw88/main.c
@@ -722,8 +722,6 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si)
stbc_en = VHT_STBC_EN;
if (sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC)
ldpc_en = VHT_LDPC_EN;
- if (sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80)
- is_support_sgi = true;
} else if (sta->ht_cap.ht_supported) {
ra_mask |= (sta->ht_cap.mcs.rx_mask[1] << 20) |
(sta->ht_cap.mcs.rx_mask[0] << 12);
@@ -731,9 +729,6 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si)
stbc_en = HT_STBC_EN;
if (sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING)
ldpc_en = HT_LDPC_EN;
- if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20 ||
- sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40)
- is_support_sgi = true;
}
if (efuse->hw_cap.nss == 1)
@@ -775,12 +770,18 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si)
switch (sta->bandwidth) {
case IEEE80211_STA_RX_BW_80:
bw_mode = RTW_CHANNEL_WIDTH_80;
+ is_support_sgi = sta->vht_cap.vht_supported &&
+ (sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80);
break;
case IEEE80211_STA_RX_BW_40:
bw_mode = RTW_CHANNEL_WIDTH_40;
+ is_support_sgi = sta->ht_cap.ht_supported &&
+ (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40);
break;
default:
bw_mode = RTW_CHANNEL_WIDTH_20;
+ is_support_sgi = sta->ht_cap.ht_supported &&
+ (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20);
break;
}
diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h
index 45ebc5a70b1e..276b5d381467 100644
--- a/drivers/net/wireless/realtek/rtw88/main.h
+++ b/drivers/net/wireless/realtek/rtw88/main.h
@@ -592,6 +592,8 @@ struct rtw_tx_pkt_info {
bool dis_qselseq;
bool en_hwseq;
u8 hw_ssn_sel;
+ bool nav_use_hdr;
+ bool bt_null;
};
struct rtw_rx_pkt_stat {
diff --git a/drivers/net/wireless/realtek/rtw88/reg.h b/drivers/net/wireless/realtek/rtw88/reg.h
index f1275757f6b4..8f468d6b5f78 100644
--- a/drivers/net/wireless/realtek/rtw88/reg.h
+++ b/drivers/net/wireless/realtek/rtw88/reg.h
@@ -61,6 +61,7 @@
#define BIT_FSPI_EN BIT(19)
#define BIT_EN_SIC BIT(12)
#define BIT_BT_AOD_GPIO3 BIT(9)
+#define BIT_PO_BT_PTA_PINS BIT(9)
#define BIT_BT_PTA_EN BIT(5)
#define BIT_WLRFE_4_5_EN BIT(2)
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c.c b/drivers/net/wireless/realtek/rtw88/rtw8821c.c
index c41c61ee2fb6..d8863d8a5468 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8821c.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.c
@@ -649,6 +649,197 @@ static void rtw8821c_phy_calibration(struct rtw_dev *rtwdev)
rtw8821c_do_iqk(rtwdev);
}
+/* for coex */
+static void rtw8821c_coex_cfg_init(struct rtw_dev *rtwdev)
+{
+ /* enable TBTT nterrupt */
+ rtw_write8_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION);
+
+ /* BT report packet sample rate */
+ rtw_write8_mask(rtwdev, REG_BT_TDMA_TIME, SAMPLE_RATE_MASK,
+ SAMPLE_RATE);
+
+ /* enable BT counter statistics */
+ rtw_write8(rtwdev, REG_BT_STAT_CTRL, BT_CNT_ENABLE);
+
+ /* enable PTA (3-wire function form BT side) */
+ rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_BT_PTA_EN);
+ rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_PO_BT_PTA_PINS);
+
+ /* enable PTA (tx/rx signal form WiFi side) */
+ rtw_write8_set(rtwdev, REG_QUEUE_CTRL, BIT_PTA_WL_TX_EN);
+ /* wl tx signal to PTA not case EDCCA */
+ rtw_write8_clr(rtwdev, REG_QUEUE_CTRL, BIT_PTA_EDCCA_EN);
+ /* GNT_BT=1 while select both */
+ rtw_write16_set(rtwdev, REG_BT_COEX_V2, BIT_GNT_BT_POLARITY);
+
+ /* beacon queue always hi-pri */
+ rtw_write8_mask(rtwdev, REG_BT_COEX_TABLE_H + 3, BIT_BCN_QUEUE,
+ BCN_PRI_EN);
+}
+
+static void rtw8821c_coex_cfg_ant_switch(struct rtw_dev *rtwdev, u8 ctrl_type,
+ u8 pos_type)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_dm *coex_dm = &coex->dm;
+ struct rtw_coex_rfe *coex_rfe = &coex->rfe;
+ u32 switch_status = FIELD_PREP(CTRL_TYPE_MASK, ctrl_type) | pos_type;
+ bool polarity_inverse;
+ u8 regval = 0;
+
+ if (switch_status == coex_dm->cur_switch_status)
+ return;
+
+ coex_dm->cur_switch_status = switch_status;
+
+ if (coex_rfe->ant_switch_diversity &&
+ ctrl_type == COEX_SWITCH_CTRL_BY_BBSW)
+ ctrl_type = COEX_SWITCH_CTRL_BY_ANTDIV;
+
+ polarity_inverse = (coex_rfe->ant_switch_polarity == 1);
+
+ switch (ctrl_type) {
+ default:
+ case COEX_SWITCH_CTRL_BY_BBSW:
+ rtw_write32_clr(rtwdev, REG_LED_CFG, BIT_DPDT_SEL_EN);
+ rtw_write32_set(rtwdev, REG_LED_CFG, BIT_DPDT_WL_SEL);
+ /* BB SW, DPDT use RFE_ctrl8 and RFE_ctrl9 as ctrl pin */
+ rtw_write8_mask(rtwdev, REG_RFE_CTRL8, BIT_MASK_RFE_SEL89,
+ DPDT_CTRL_PIN);
+
+ if (pos_type == COEX_SWITCH_TO_WLG_BT) {
+ if (coex_rfe->rfe_module_type != 0x4 &&
+ coex_rfe->rfe_module_type != 0x2)
+ regval = 0x3;
+ else
+ regval = (!polarity_inverse ? 0x2 : 0x1);
+ } else if (pos_type == COEX_SWITCH_TO_WLG) {
+ regval = (!polarity_inverse ? 0x2 : 0x1);
+ } else {
+ regval = (!polarity_inverse ? 0x1 : 0x2);
+ }
+
+ rtw_write8_mask(rtwdev, REG_RFE_CTRL8, BIT_MASK_R_RFE_SEL_15,
+ regval);
+ break;
+ case COEX_SWITCH_CTRL_BY_PTA:
+ rtw_write32_clr(rtwdev, REG_LED_CFG, BIT_DPDT_SEL_EN);
+ rtw_write32_set(rtwdev, REG_LED_CFG, BIT_DPDT_WL_SEL);
+ /* PTA, DPDT use RFE_ctrl8 and RFE_ctrl9 as ctrl pin */
+ rtw_write8_mask(rtwdev, REG_RFE_CTRL8, BIT_MASK_RFE_SEL89,
+ PTA_CTRL_PIN);
+
+ regval = (!polarity_inverse ? 0x2 : 0x1);
+ rtw_write8_mask(rtwdev, REG_RFE_CTRL8, BIT_MASK_R_RFE_SEL_15,
+ regval);
+ break;
+ case COEX_SWITCH_CTRL_BY_ANTDIV:
+ rtw_write32_clr(rtwdev, REG_LED_CFG, BIT_DPDT_SEL_EN);
+ rtw_write32_set(rtwdev, REG_LED_CFG, BIT_DPDT_WL_SEL);
+ rtw_write8_mask(rtwdev, REG_RFE_CTRL8, BIT_MASK_RFE_SEL89,
+ ANTDIC_CTRL_PIN);
+ break;
+ case COEX_SWITCH_CTRL_BY_MAC:
+ rtw_write32_set(rtwdev, REG_LED_CFG, BIT_DPDT_SEL_EN);
+
+ regval = (!polarity_inverse ? 0x0 : 0x1);
+ rtw_write8_mask(rtwdev, REG_PAD_CTRL1, BIT_SW_DPDT_SEL_DATA,
+ regval);
+ break;
+ case COEX_SWITCH_CTRL_BY_FW:
+ rtw_write32_clr(rtwdev, REG_LED_CFG, BIT_DPDT_SEL_EN);
+ rtw_write32_set(rtwdev, REG_LED_CFG, BIT_DPDT_WL_SEL);
+ break;
+ case COEX_SWITCH_CTRL_BY_BT:
+ rtw_write32_clr(rtwdev, REG_LED_CFG, BIT_DPDT_SEL_EN);
+ rtw_write32_clr(rtwdev, REG_LED_CFG, BIT_DPDT_WL_SEL);
+ break;
+ }
+
+ if (ctrl_type == COEX_SWITCH_CTRL_BY_BT) {
+ rtw_write32_clr(rtwdev, REG_CTRL_TYPE, BIT_CTRL_TYPE1);
+ rtw_write32_clr(rtwdev, REG_CTRL_TYPE, BIT_CTRL_TYPE2);
+ } else {
+ rtw_write32_set(rtwdev, REG_CTRL_TYPE, BIT_CTRL_TYPE1);
+ rtw_write32_set(rtwdev, REG_CTRL_TYPE, BIT_CTRL_TYPE2);
+ }
+}
+
+static void rtw8821c_coex_cfg_gnt_fix(struct rtw_dev *rtwdev)
+{}
+
+static void rtw8821c_coex_cfg_gnt_debug(struct rtw_dev *rtwdev)
+{
+ rtw_write32_clr(rtwdev, REG_PAD_CTRL1, BIT_BTGP_SPI_EN);
+ rtw_write32_clr(rtwdev, REG_PAD_CTRL1, BIT_BTGP_JTAG_EN);
+ rtw_write32_clr(rtwdev, REG_GPIO_MUXCFG, BIT_FSPI_EN);
+ rtw_write32_clr(rtwdev, REG_PAD_CTRL1, BIT_LED1DIS);
+ rtw_write32_clr(rtwdev, REG_SYS_SDIO_CTRL, BIT_SDIO_INT);
+ rtw_write32_clr(rtwdev, REG_SYS_SDIO_CTRL, BIT_DBG_GNT_WL_BT);
+}
+
+static void rtw8821c_coex_cfg_rfe_type(struct rtw_dev *rtwdev)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_rfe *coex_rfe = &coex->rfe;
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+
+ coex_rfe->rfe_module_type = efuse->rfe_option;
+ coex_rfe->ant_switch_polarity = 0;
+ coex_rfe->ant_switch_exist = true;
+ coex_rfe->wlg_at_btg = false;
+
+ switch (coex_rfe->rfe_module_type) {
+ case 0:
+ case 8:
+ case 1:
+ case 9: /* 1-Ant, Main, WLG */
+ default: /* 2-Ant, DPDT, WLG */
+ break;
+ case 2:
+ case 10: /* 1-Ant, Main, BTG */
+ case 7:
+ case 15: /* 2-Ant, DPDT, BTG */
+ coex_rfe->wlg_at_btg = true;
+ break;
+ case 3:
+ case 11: /* 1-Ant, Aux, WLG */
+ coex_rfe->ant_switch_polarity = 1;
+ break;
+ case 4:
+ case 12: /* 1-Ant, Aux, BTG */
+ coex_rfe->wlg_at_btg = true;
+ coex_rfe->ant_switch_polarity = 1;
+ break;
+ case 5:
+ case 13: /* 2-Ant, no switch, WLG */
+ case 6:
+ case 14: /* 2-Ant, no antenna switch, WLG */
+ coex_rfe->ant_switch_exist = false;
+ break;
+ }
+}
+
+static void rtw8821c_coex_cfg_wl_tx_power(struct rtw_dev *rtwdev, u8 wl_pwr)
+{
+ struct rtw_coex *coex = &rtwdev->coex;
+ struct rtw_coex_dm *coex_dm = &coex->dm;
+ struct rtw_efuse *efuse = &rtwdev->efuse;
+ bool share_ant = efuse->share_ant;
+
+ if (share_ant)
+ return;
+
+ if (wl_pwr == coex_dm->cur_wl_pwr_lvl)
+ return;
+
+ coex_dm->cur_wl_pwr_lvl = wl_pwr;
+}
+
+static void rtw8821c_coex_cfg_wl_rx_gain(struct rtw_dev *rtwdev, bool low_gain)
+{}
+
static void
rtw8821c_txagc_swing_offset(struct rtw_dev *rtwdev, u8 pwr_idx_offset,
s8 pwr_idx_offset_lower,
@@ -1293,8 +1484,166 @@ static struct rtw_chip_ops rtw8821c_ops = {
.config_bfee = rtw8821c_bf_config_bfee,
.set_gid_table = rtw_bf_set_gid_table,
.cfg_csi_rate = rtw_bf_cfg_csi_rate,
+
+ .coex_set_init = rtw8821c_coex_cfg_init,
+ .coex_set_ant_switch = rtw8821c_coex_cfg_ant_switch,
+ .coex_set_gnt_fix = rtw8821c_coex_cfg_gnt_fix,
+ .coex_set_gnt_debug = rtw8821c_coex_cfg_gnt_debug,
+ .coex_set_rfe_type = rtw8821c_coex_cfg_rfe_type,
+ .coex_set_wl_tx_power = rtw8821c_coex_cfg_wl_tx_power,
+ .coex_set_wl_rx_gain = rtw8821c_coex_cfg_wl_rx_gain,
+};
+
+/* rssi in percentage % (dbm = % - 100) */
+static const u8 wl_rssi_step_8821c[] = {101, 45, 101, 40};
+static const u8 bt_rssi_step_8821c[] = {101, 101, 101, 101};
+
+/* Shared-Antenna Coex Table */
+static const struct coex_table_para table_sant_8821c[] = {
+ {0x55555555, 0x55555555}, /* case-0 */
+ {0x55555555, 0x55555555},
+ {0x66555555, 0x66555555},
+ {0xaaaaaaaa, 0xaaaaaaaa},
+ {0x5a5a5a5a, 0x5a5a5a5a},
+ {0xfafafafa, 0xfafafafa}, /* case-5 */
+ {0x6a5a5555, 0xaaaaaaaa},
+ {0x6a5a56aa, 0x6a5a56aa},
+ {0x6a5a5a5a, 0x6a5a5a5a},
+ {0x66555555, 0x5a5a5a5a},
+ {0x66555555, 0x6a5a5a5a}, /* case-10 */
+ {0x66555555, 0xaaaaaaaa},
+ {0x66555555, 0x6a5a5aaa},
+ {0x66555555, 0x6aaa6aaa},
+ {0x66555555, 0x6a5a5aaa},
+ {0x66555555, 0xaaaaaaaa}, /* case-15 */
+ {0xffff55ff, 0xfafafafa},
+ {0xffff55ff, 0x6afa5afa},
+ {0xaaffffaa, 0xfafafafa},
+ {0xaa5555aa, 0x5a5a5a5a},
+ {0xaa5555aa, 0x6a5a5a5a}, /* case-20 */
+ {0xaa5555aa, 0xaaaaaaaa},
+ {0xffffffff, 0x55555555},
+ {0xffffffff, 0x5a5a5a5a},
+ {0xffffffff, 0x5a5a5a5a},
+ {0xffffffff, 0x5a5a5aaa}, /* case-25 */
+ {0x55555555, 0x5a5a5a5a},
+ {0x55555555, 0xaaaaaaaa},
+ {0x66555555, 0x6a5a6a5a},
+ {0x66556655, 0x66556655},
+ {0x66556aaa, 0x6a5a6aaa}, /* case-30 */
+ {0xffffffff, 0x5aaa5aaa},
+ {0x56555555, 0x5a5a5aaa}
+};
+
+/* Non-Shared-Antenna Coex Table */
+static const struct coex_table_para table_nsant_8821c[] = {
+ {0xffffffff, 0xffffffff}, /* case-100 */
+ {0xffff55ff, 0xfafafafa},
+ {0x66555555, 0x66555555},
+ {0xaaaaaaaa, 0xaaaaaaaa},
+ {0x5a5a5a5a, 0x5a5a5a5a},
+ {0xffffffff, 0xffffffff}, /* case-105 */
+ {0x5afa5afa, 0x5afa5afa},
+ {0x55555555, 0xfafafafa},
+ {0x66555555, 0xfafafafa},
+ {0x66555555, 0x5a5a5a5a},
+ {0x66555555, 0x6a5a5a5a}, /* case-110 */
+ {0x66555555, 0xaaaaaaaa},
+ {0xffff55ff, 0xfafafafa},
+ {0xffff55ff, 0x5afa5afa},
+ {0xffff55ff, 0xaaaaaaaa},
+ {0xffff55ff, 0xffff55ff}, /* case-115 */
+ {0xaaffffaa, 0x5afa5afa},
+ {0xaaffffaa, 0xaaaaaaaa},
+ {0xffffffff, 0xfafafafa},
+ {0xffff55ff, 0xfafafafa},
+ {0xffffffff, 0xaaaaaaaa}, /* case-120 */
+ {0xffff55ff, 0x5afa5afa},
+ {0xffff55ff, 0x5afa5afa},
+ {0x55ff55ff, 0x55ff55ff}
+};
+
+/* Shared-Antenna TDMA */
+static const struct coex_tdma_para tdma_sant_8821c[] = {
+ { {0x00, 0x00, 0x00, 0x00, 0x00} }, /* case-0 */
+ { {0x61, 0x45, 0x03, 0x11, 0x11} }, /* case-1 */
+ { {0x61, 0x3a, 0x03, 0x11, 0x11} },
+ { {0x61, 0x35, 0x03, 0x11, 0x11} },
+ { {0x61, 0x20, 0x03, 0x11, 0x11} },
+ { {0x61, 0x3a, 0x03, 0x11, 0x11} }, /* case-5 */
+ { {0x61, 0x45, 0x03, 0x11, 0x10} },
+ { {0x61, 0x35, 0x03, 0x11, 0x10} },
+ { {0x61, 0x30, 0x03, 0x11, 0x10} },
+ { {0x61, 0x20, 0x03, 0x11, 0x10} },
+ { {0x61, 0x10, 0x03, 0x11, 0x10} }, /* case-10 */
+ { {0x61, 0x08, 0x03, 0x11, 0x15} },
+ { {0x61, 0x08, 0x03, 0x10, 0x14} },
+ { {0x51, 0x08, 0x03, 0x10, 0x54} },
+ { {0x51, 0x08, 0x03, 0x10, 0x55} },
+ { {0x51, 0x08, 0x07, 0x10, 0x54} }, /* case-15 */
+ { {0x51, 0x45, 0x03, 0x10, 0x50} },
+ { {0x51, 0x3a, 0x03, 0x11, 0x50} },
+ { {0x51, 0x30, 0x03, 0x10, 0x50} },
+ { {0x51, 0x21, 0x03, 0x10, 0x50} },
+ { {0x51, 0x10, 0x03, 0x10, 0x50} }, /* case-20 */
+ { {0x51, 0x4a, 0x03, 0x10, 0x50} },
+ { {0x51, 0x08, 0x03, 0x30, 0x54} },
+ { {0x55, 0x08, 0x03, 0x10, 0x54} },
+ { {0x65, 0x10, 0x03, 0x11, 0x10} },
+ { {0x51, 0x10, 0x03, 0x10, 0x51} }, /* case-25 */
+ { {0x51, 0x21, 0x03, 0x10, 0x50} },
+ { {0x61, 0x08, 0x03, 0x11, 0x11} }
+};
+
+/* Non-Shared-Antenna TDMA */
+static const struct coex_tdma_para tdma_nsant_8821c[] = {
+ { {0x00, 0x00, 0x00, 0x40, 0x00} }, /* case-100 */
+ { {0x61, 0x45, 0x03, 0x11, 0x11} },
+ { {0x61, 0x25, 0x03, 0x11, 0x11} },
+ { {0x61, 0x35, 0x03, 0x11, 0x11} },
+ { {0x61, 0x20, 0x03, 0x11, 0x11} },
+ { {0x61, 0x10, 0x03, 0x11, 0x11} }, /* case-105 */
+ { {0x61, 0x45, 0x03, 0x11, 0x10} },
+ { {0x61, 0x30, 0x03, 0x11, 0x10} },
+ { {0x61, 0x30, 0x03, 0x11, 0x10} },
+ { {0x61, 0x20, 0x03, 0x11, 0x10} },
+ { {0x61, 0x10, 0x03, 0x11, 0x10} }, /* case-110 */
+ { {0x61, 0x10, 0x03, 0x11, 0x11} },
+ { {0x61, 0x08, 0x03, 0x10, 0x14} },
+ { {0x51, 0x08, 0x03, 0x10, 0x54} },
+ { {0x51, 0x08, 0x03, 0x10, 0x55} },
+ { {0x51, 0x08, 0x07, 0x10, 0x54} }, /* case-115 */
+ { {0x51, 0x45, 0x03, 0x10, 0x50} },
+ { {0x51, 0x3a, 0x03, 0x10, 0x50} },
+ { {0x51, 0x30, 0x03, 0x10, 0x50} },
+ { {0x51, 0x21, 0x03, 0x10, 0x50} },
+ { {0x51, 0x21, 0x03, 0x10, 0x50} }, /* case-120 */
+ { {0x51, 0x10, 0x03, 0x10, 0x50} }
};
+static const struct coex_5g_afh_map afh_5g_8821c[] = { {0, 0, 0} };
+
+/* wl_tx_dec_power, bt_tx_dec_power, wl_rx_gain, bt_rx_lna_constrain */
+static const struct coex_rf_para rf_para_tx_8821c[] = {
+ {0, 0, false, 7}, /* for normal */
+ {0, 20, false, 7}, /* for WL-CPT */
+ {8, 17, true, 4},
+ {7, 18, true, 4},
+ {6, 19, true, 4},
+ {5, 20, true, 4}
+};
+
+static const struct coex_rf_para rf_para_rx_8821c[] = {
+ {0, 0, false, 7}, /* for normal */
+ {0, 20, false, 7}, /* for WL-CPT */
+ {3, 24, true, 5},
+ {2, 26, true, 5},
+ {1, 27, true, 5},
+ {0, 28, true, 5}
+};
+
+static_assert(ARRAY_SIZE(rf_para_tx_8821c) == ARRAY_SIZE(rf_para_rx_8821c));
+
static const u8 rtw8821c_pwrtrk_5gb_n[][RTW_PWR_TRK_TBL_SZ] = {
{0, 1, 1, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 8, 8, 8, 9, 9, 9, 10, 10,
11, 11, 12, 12, 12, 12, 12},
@@ -1371,7 +1720,7 @@ static const u8 rtw8821c_pwrtrk_2g_cck_a_p[] = {
5, 6, 6, 7, 7, 7, 8, 8, 9, 9, 9, 9, 9, 9
};
-const struct rtw_pwr_track_tbl rtw8821c_rtw_pwr_track_tbl = {
+static const struct rtw_pwr_track_tbl rtw8821c_rtw_pwr_track_tbl = {
.pwrtrk_5gb_n[0] = rtw8821c_pwrtrk_5gb_n[0],
.pwrtrk_5gb_n[1] = rtw8821c_pwrtrk_5gb_n[1],
.pwrtrk_5gb_n[2] = rtw8821c_pwrtrk_5gb_n[2],
@@ -1394,6 +1743,31 @@ const struct rtw_pwr_track_tbl rtw8821c_rtw_pwr_track_tbl = {
.pwrtrk_2g_ccka_p = rtw8821c_pwrtrk_2g_cck_a_p,
};
+static const struct rtw_reg_domain coex_info_hw_regs_8821c[] = {
+ {0xCB0, MASKDWORD, RTW_REG_DOMAIN_MAC32},
+ {0xCB4, MASKDWORD, RTW_REG_DOMAIN_MAC32},
+ {0xCBA, MASKBYTE0, RTW_REG_DOMAIN_MAC8},
+ {0, 0, RTW_REG_DOMAIN_NL},
+ {0x430, MASKDWORD, RTW_REG_DOMAIN_MAC32},
+ {0x434, MASKDWORD, RTW_REG_DOMAIN_MAC32},
+ {0x42a, MASKLWORD, RTW_REG_DOMAIN_MAC16},
+ {0x426, MASKBYTE0, RTW_REG_DOMAIN_MAC8},
+ {0x45e, BIT(3), RTW_REG_DOMAIN_MAC8},
+ {0x454, MASKLWORD, RTW_REG_DOMAIN_MAC16},
+ {0, 0, RTW_REG_DOMAIN_NL},
+ {0x4c, BIT(24) | BIT(23), RTW_REG_DOMAIN_MAC32},
+ {0x64, BIT(0), RTW_REG_DOMAIN_MAC8},
+ {0x4c6, BIT(4), RTW_REG_DOMAIN_MAC8},
+ {0x40, BIT(5), RTW_REG_DOMAIN_MAC8},
+ {0x1, RFREG_MASK, RTW_REG_DOMAIN_RF_A},
+ {0, 0, RTW_REG_DOMAIN_NL},
+ {0x550, MASKDWORD, RTW_REG_DOMAIN_MAC32},
+ {0x522, MASKBYTE0, RTW_REG_DOMAIN_MAC8},
+ {0x953, BIT(1), RTW_REG_DOMAIN_MAC8},
+ {0xc50, MASKBYTE0, RTW_REG_DOMAIN_MAC8},
+ {0x60A, MASKBYTE0, RTW_REG_DOMAIN_MAC8},
+};
+
struct rtw_chip_info rtw8821c_hw_spec = {
.ops = &rtw8821c_ops,
.id = RTW_CHIP_TYPE_8821C,
@@ -1440,6 +1814,35 @@ struct rtw_chip_info rtw8821c_hw_spec = {
.iqk_threshold = 8,
.bfer_su_max_num = 2,
.bfer_mu_max_num = 1,
+
+ .coex_para_ver = 0x19092746,
+ .bt_desired_ver = 0x46,
+ .scbd_support = true,
+ .new_scbd10_def = false,
+ .pstdma_type = COEX_PSTDMA_FORCE_LPSOFF,
+ .bt_rssi_type = COEX_BTRSSI_RATIO,
+ .ant_isolation = 15,
+ .rssi_tolerance = 2,
+ .wl_rssi_step = wl_rssi_step_8821c,
+ .bt_rssi_step = bt_rssi_step_8821c,
+ .table_sant_num = ARRAY_SIZE(table_sant_8821c),
+ .table_sant = table_sant_8821c,
+ .table_nsant_num = ARRAY_SIZE(table_nsant_8821c),
+ .table_nsant = table_nsant_8821c,
+ .tdma_sant_num = ARRAY_SIZE(tdma_sant_8821c),
+ .tdma_sant = tdma_sant_8821c,
+ .tdma_nsant_num = ARRAY_SIZE(tdma_nsant_8821c),
+ .tdma_nsant = tdma_nsant_8821c,
+ .wl_rf_para_num = ARRAY_SIZE(rf_para_tx_8821c),
+ .wl_rf_para_tx = rf_para_tx_8821c,
+ .wl_rf_para_rx = rf_para_rx_8821c,
+ .bt_afh_span_bw20 = 0x24,
+ .bt_afh_span_bw40 = 0x36,
+ .afh_5g_num = ARRAY_SIZE(afh_5g_8821c),
+ .afh_5g = afh_5g_8821c,
+
+ .coex_info_hw_regs_num = ARRAY_SIZE(coex_info_hw_regs_8821c),
+ .coex_info_hw_regs = coex_info_hw_regs_8821c,
};
EXPORT_SYMBOL(rtw8821c_hw_spec);
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c.h b/drivers/net/wireless/realtek/rtw88/rtw8821c.h
index 166bd0e9294e..bd01e82b6bcd 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8821c.h
+++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.h
@@ -160,6 +160,18 @@ _rtw_write32s_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 data)
le32_get_bits(*((__le32 *)(phy_stat) + 0x01), GENMASK(11, 8))
#define GET_PHY_STAT_P1_HT_RXSC(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x01), GENMASK(15, 12))
+#define GET_PHY_STAT_P1_RXEVM_A(phy_stat) \
+ le32_get_bits(*((__le32 *)(phy_stat) + 0x04), GENMASK(7, 0))
+#define GET_PHY_STAT_P1_RXEVM_B(phy_stat) \
+ le32_get_bits(*((__le32 *)(phy_stat) + 0x04), GENMASK(15, 8))
+#define GET_PHY_STAT_P1_CFO_TAIL_A(phy_stat) \
+ le32_get_bits(*((__le32 *)(phy_stat) + 0x05), GENMASK(7, 0))
+#define GET_PHY_STAT_P1_CFO_TAIL_B(phy_stat) \
+ le32_get_bits(*((__le32 *)(phy_stat) + 0x05), GENMASK(15, 8))
+#define GET_PHY_STAT_P1_RXSNR_A(phy_stat) \
+ le32_get_bits(*((__le32 *)(phy_stat) + 0x06), GENMASK(7, 0))
+#define GET_PHY_STAT_P1_RXSNR_B(phy_stat) \
+ le32_get_bits(*((__le32 *)(phy_stat) + 0x06), GENMASK(15, 8))
#define REG_INIRTS_RATE_SEL 0x0480
#define REG_HTSTFWT 0x800
@@ -217,6 +229,20 @@ _rtw_write32s_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 data)
#define REG_CCA_CCK 0xfcc
#define REG_ANTWT 0x1904
#define REG_IQKFAILMSK 0x1bf0
+#define BIT_MASK_R_RFE_SEL_15 GENMASK(31, 28)
+#define BIT_SDIO_INT BIT(18)
+#define SAMPLE_RATE_MASK GENMASK(5, 0)
+#define SAMPLE_RATE 0x5
+#define BT_CNT_ENABLE 0x1
+#define BIT_BCN_QUEUE BIT(3)
+#define BCN_PRI_EN 0x1
+#define PTA_CTRL_PIN 0x66
+#define DPDT_CTRL_PIN 0x77
+#define ANTDIC_CTRL_PIN 0x88
+#define REG_CTRL_TYPE 0x67
+#define BIT_CTRL_TYPE1 BIT(5)
+#define BIT_CTRL_TYPE2 BIT(4)
+#define CTRL_TYPE_MASK GENMASK(15, 8)
#define RF18_BAND_MASK (BIT(16) | BIT(9) | BIT(8))
#define RF18_BAND_2G (0)
diff --git a/drivers/net/wireless/realtek/rtw88/tx.c b/drivers/net/wireless/realtek/rtw88/tx.c
index 79c42118825f..7fcc992b01a8 100644
--- a/drivers/net/wireless/realtek/rtw88/tx.c
+++ b/drivers/net/wireless/realtek/rtw88/tx.c
@@ -61,6 +61,8 @@ void rtw_tx_fill_tx_desc(struct rtw_tx_pkt_info *pkt_info, struct sk_buff *skb)
SET_TX_DESC_DISQSELSEQ(txdesc, pkt_info->dis_qselseq);
SET_TX_DESC_EN_HWSEQ(txdesc, pkt_info->en_hwseq);
SET_TX_DESC_HW_SSN_SEL(txdesc, pkt_info->hw_ssn_sel);
+ SET_TX_DESC_NAVUSEHDR(txdesc, pkt_info->nav_use_hdr);
+ SET_TX_DESC_BT_NULL(txdesc, pkt_info->bt_null);
}
EXPORT_SYMBOL(rtw_tx_fill_tx_desc);
@@ -227,17 +229,58 @@ void rtw_tx_report_handle(struct rtw_dev *rtwdev, struct sk_buff *skb, int src)
spin_unlock_irqrestore(&tx_report->q_lock, flags);
}
-static void rtw_tx_mgmt_pkt_info_update(struct rtw_dev *rtwdev,
+static void rtw_tx_pkt_info_update_rate(struct rtw_dev *rtwdev,
struct rtw_tx_pkt_info *pkt_info,
- struct ieee80211_sta *sta,
struct sk_buff *skb)
{
+ if (rtwdev->hal.current_band_type == RTW_BAND_2G) {
+ pkt_info->rate_id = RTW_RATEID_B_20M;
+ pkt_info->rate = DESC_RATE1M;
+ } else {
+ pkt_info->rate_id = RTW_RATEID_G;
+ pkt_info->rate = DESC_RATE6M;
+ }
pkt_info->use_rate = true;
- pkt_info->rate_id = 6;
pkt_info->dis_rate_fallback = true;
+}
+
+static void rtw_tx_pkt_info_update_sec(struct rtw_dev *rtwdev,
+ struct rtw_tx_pkt_info *pkt_info,
+ struct sk_buff *skb)
+{
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ u8 sec_type = 0;
+
+ if (info && info->control.hw_key) {
+ struct ieee80211_key_conf *key = info->control.hw_key;
+
+ switch (key->cipher) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ case WLAN_CIPHER_SUITE_WEP104:
+ case WLAN_CIPHER_SUITE_TKIP:
+ sec_type = 0x01;
+ break;
+ case WLAN_CIPHER_SUITE_CCMP:
+ sec_type = 0x03;
+ break;
+ default:
+ break;
+ }
+ }
+
+ pkt_info->sec_type = sec_type;
+}
+
+static void rtw_tx_mgmt_pkt_info_update(struct rtw_dev *rtwdev,
+ struct rtw_tx_pkt_info *pkt_info,
+ struct ieee80211_sta *sta,
+ struct sk_buff *skb)
+{
+ rtw_tx_pkt_info_update_rate(rtwdev, pkt_info, skb);
pkt_info->dis_qselseq = true;
pkt_info->en_hwseq = true;
pkt_info->hw_ssn_sel = 0;
+ /* TODO: need to change hw port and hw ssn sel for multiple vifs */
}
static void rtw_tx_data_pkt_info_update(struct rtw_dev *rtwdev,
@@ -312,7 +355,6 @@ void rtw_tx_pkt_info_update(struct rtw_dev *rtwdev,
struct rtw_sta_info *si;
struct ieee80211_vif *vif = NULL;
__le16 fc = hdr->frame_control;
- u8 sec_type = 0;
bool bmc;
if (sta) {
@@ -325,23 +367,6 @@ void rtw_tx_pkt_info_update(struct rtw_dev *rtwdev,
else if (ieee80211_is_data(fc))
rtw_tx_data_pkt_info_update(rtwdev, pkt_info, sta, skb);
- if (info->control.hw_key) {
- struct ieee80211_key_conf *key = info->control.hw_key;
-
- switch (key->cipher) {
- case WLAN_CIPHER_SUITE_WEP40:
- case WLAN_CIPHER_SUITE_WEP104:
- case WLAN_CIPHER_SUITE_TKIP:
- sec_type = 0x01;
- break;
- case WLAN_CIPHER_SUITE_CCMP:
- sec_type = 0x03;
- break;
- default:
- break;
- }
- }
-
bmc = is_broadcast_ether_addr(hdr->addr1) ||
is_multicast_ether_addr(hdr->addr1);
@@ -349,7 +374,7 @@ void rtw_tx_pkt_info_update(struct rtw_dev *rtwdev,
rtw_tx_report_enable(rtwdev, pkt_info);
pkt_info->bmc = bmc;
- pkt_info->sec_type = sec_type;
+ rtw_tx_pkt_info_update_sec(rtwdev, pkt_info, skb);
pkt_info->tx_pkt_size = skb->len;
pkt_info->offset = chip->tx_pkt_desc_sz;
pkt_info->qsel = skb->priority;
@@ -359,24 +384,42 @@ void rtw_tx_pkt_info_update(struct rtw_dev *rtwdev,
rtw_tx_stats(rtwdev, vif, skb);
}
-void rtw_rsvd_page_pkt_info_update(struct rtw_dev *rtwdev,
- struct rtw_tx_pkt_info *pkt_info,
- struct sk_buff *skb)
+void rtw_tx_rsvd_page_pkt_info_update(struct rtw_dev *rtwdev,
+ struct rtw_tx_pkt_info *pkt_info,
+ struct sk_buff *skb,
+ enum rtw_rsvd_packet_type type)
{
struct rtw_chip_info *chip = rtwdev->chip;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
bool bmc;
+ /* A beacon or dummy reserved page packet indicates that it is the first
+ * reserved page, and the qsel of it will be set in each hci.
+ */
+ if (type != RSVD_BEACON && type != RSVD_DUMMY)
+ pkt_info->qsel = TX_DESC_QSEL_MGMT;
+
+ rtw_tx_pkt_info_update_rate(rtwdev, pkt_info, skb);
+
bmc = is_broadcast_ether_addr(hdr->addr1) ||
is_multicast_ether_addr(hdr->addr1);
- pkt_info->use_rate = true;
- pkt_info->rate_id = 6;
- pkt_info->dis_rate_fallback = true;
pkt_info->bmc = bmc;
pkt_info->tx_pkt_size = skb->len;
pkt_info->offset = chip->tx_pkt_desc_sz;
- pkt_info->qsel = TX_DESC_QSEL_MGMT;
pkt_info->ls = true;
+ if (type == RSVD_PS_POLL) {
+ pkt_info->nav_use_hdr = true;
+ } else {
+ pkt_info->dis_qselseq = true;
+ pkt_info->en_hwseq = true;
+ pkt_info->hw_ssn_sel = 0;
+ }
+ if (type == RSVD_QOS_NULL)
+ pkt_info->bt_null = true;
+
+ rtw_tx_pkt_info_update_sec(rtwdev, pkt_info, skb);
+
+ /* TODO: need to change hw port and hw ssn sel for multiple vifs */
}
struct sk_buff *
@@ -399,8 +442,7 @@ rtw_tx_write_data_rsvd_page_get(struct rtw_dev *rtwdev,
skb_reserve(skb, tx_pkt_desc_sz);
skb_put_data(skb, buf, size);
- pkt_info->tx_pkt_size = size;
- pkt_info->offset = tx_pkt_desc_sz;
+ rtw_tx_rsvd_page_pkt_info_update(rtwdev, pkt_info, skb, RSVD_BEACON);
return skb;
}
diff --git a/drivers/net/wireless/realtek/rtw88/tx.h b/drivers/net/wireless/realtek/rtw88/tx.h
index 72dfd4059f03..cfe84eef5923 100644
--- a/drivers/net/wireless/realtek/rtw88/tx.h
+++ b/drivers/net/wireless/realtek/rtw88/tx.h
@@ -59,6 +59,10 @@
le32p_replace_bits((__le32 *)(txdesc) + 0x08, value, BIT(15))
#define SET_TX_DESC_HW_SSN_SEL(txdesc, value) \
le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, GENMASK(7, 6))
+#define SET_TX_DESC_NAVUSEHDR(txdesc, value) \
+ le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, BIT(15))
+#define SET_TX_DESC_BT_NULL(txdesc, value) \
+ le32p_replace_bits((__le32 *)(txdesc) + 0x02, value, BIT(23))
enum rtw_tx_desc_queue_select {
TX_DESC_QSEL_TID0 = 0,
@@ -83,6 +87,8 @@ enum rtw_tx_desc_queue_select {
TX_DESC_QSEL_H2C = 19,
};
+enum rtw_rsvd_packet_type;
+
void rtw_tx(struct rtw_dev *rtwdev,
struct ieee80211_tx_control *control,
struct sk_buff *skb);
@@ -96,9 +102,10 @@ void rtw_tx_pkt_info_update(struct rtw_dev *rtwdev,
void rtw_tx_fill_tx_desc(struct rtw_tx_pkt_info *pkt_info, struct sk_buff *skb);
void rtw_tx_report_enqueue(struct rtw_dev *rtwdev, struct sk_buff *skb, u8 sn);
void rtw_tx_report_handle(struct rtw_dev *rtwdev, struct sk_buff *skb, int src);
-void rtw_rsvd_page_pkt_info_update(struct rtw_dev *rtwdev,
- struct rtw_tx_pkt_info *pkt_info,
- struct sk_buff *skb);
+void rtw_tx_rsvd_page_pkt_info_update(struct rtw_dev *rtwdev,
+ struct rtw_tx_pkt_info *pkt_info,
+ struct sk_buff *skb,
+ enum rtw_rsvd_packet_type type);
struct sk_buff *
rtw_tx_write_data_rsvd_page_get(struct rtw_dev *rtwdev,
struct rtw_tx_pkt_info *pkt_info,