aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/realtek/rtw88/tx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/realtek/rtw88/tx.c')
-rw-r--r--drivers/net/wireless/realtek/rtw88/tx.c77
1 files changed, 60 insertions, 17 deletions
diff --git a/drivers/net/wireless/realtek/rtw88/tx.c b/drivers/net/wireless/realtek/rtw88/tx.c
index 3a101aa139ed..ab39245e9c2f 100644
--- a/drivers/net/wireless/realtek/rtw88/tx.c
+++ b/drivers/net/wireless/realtek/rtw88/tx.c
@@ -67,12 +67,16 @@ void rtw_tx_fill_tx_desc(struct rtw_tx_pkt_info *pkt_info, struct sk_buff *skb)
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);
+ if (pkt_info->tim_offset) {
+ SET_TX_DESC_TIM_EN(txdesc, 1);
+ SET_TX_DESC_TIM_OFFSET(txdesc, pkt_info->tim_offset);
+ }
}
EXPORT_SYMBOL(rtw_tx_fill_tx_desc);
static u8 get_tx_ampdu_factor(struct ieee80211_sta *sta)
{
- u8 exp = sta->ht_cap.ampdu_factor;
+ u8 exp = sta->deflink.ht_cap.ampdu_factor;
/* the least ampdu factor is 8K, and the value in the tx desc is the
* max aggregation num, which represents val * 2 packets can be
@@ -83,7 +87,7 @@ static u8 get_tx_ampdu_factor(struct ieee80211_sta *sta)
static u8 get_tx_ampdu_density(struct ieee80211_sta *sta)
{
- return sta->ht_cap.ampdu_density;
+ return sta->deflink.ht_cap.ampdu_density;
}
static u8 get_highest_ht_tx_rate(struct rtw_dev *rtwdev,
@@ -91,7 +95,7 @@ static u8 get_highest_ht_tx_rate(struct rtw_dev *rtwdev,
{
u8 rate;
- if (rtwdev->hal.rf_type == RF_2T2R && sta->ht_cap.mcs.rx_mask[1] != 0)
+ if (rtwdev->hal.rf_type == RF_2T2R && sta->deflink.ht_cap.mcs.rx_mask[1] != 0)
rate = DESC_RATEMCS15;
else
rate = DESC_RATEMCS7;
@@ -106,7 +110,7 @@ static u8 get_highest_vht_tx_rate(struct rtw_dev *rtwdev,
u8 rate;
u16 tx_mcs_map;
- tx_mcs_map = le16_to_cpu(sta->vht_cap.vht_mcs.tx_mcs_map);
+ tx_mcs_map = le16_to_cpu(sta->deflink.vht_cap.vht_mcs.tx_mcs_map);
if (efuse->hw_cap.nss == 1) {
switch (tx_mcs_map & 0x3) {
case IEEE80211_VHT_MCS_SUPPORT_0_7:
@@ -233,17 +237,34 @@ void rtw_tx_report_handle(struct rtw_dev *rtwdev, struct sk_buff *skb, int src)
spin_unlock_irqrestore(&tx_report->q_lock, flags);
}
+static u8 rtw_get_mgmt_rate(struct rtw_dev *rtwdev, struct sk_buff *skb,
+ u8 lowest_rate, bool ignore_rate)
+{
+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_vif *vif = tx_info->control.vif;
+ bool force_lowest = test_bit(RTW_FLAG_FORCE_LOWEST_RATE, rtwdev->flags);
+
+ if (!vif || !vif->bss_conf.basic_rates || ignore_rate || force_lowest)
+ return lowest_rate;
+
+ return __ffs(vif->bss_conf.basic_rates) + lowest_rate;
+}
+
static void rtw_tx_pkt_info_update_rate(struct rtw_dev *rtwdev,
struct rtw_tx_pkt_info *pkt_info,
- struct sk_buff *skb)
+ struct sk_buff *skb,
+ bool ignore_rate)
{
if (rtwdev->hal.current_band_type == RTW_BAND_2G) {
pkt_info->rate_id = RTW_RATEID_B_20M;
- pkt_info->rate = DESC_RATE1M;
+ pkt_info->rate = rtw_get_mgmt_rate(rtwdev, skb, DESC_RATE1M,
+ ignore_rate);
} else {
pkt_info->rate_id = RTW_RATEID_G;
- pkt_info->rate = DESC_RATE6M;
+ pkt_info->rate = rtw_get_mgmt_rate(rtwdev, skb, DESC_RATE6M,
+ ignore_rate);
}
+
pkt_info->use_rate = true;
pkt_info->dis_rate_fallback = true;
}
@@ -280,7 +301,7 @@ static void rtw_tx_mgmt_pkt_info_update(struct rtw_dev *rtwdev,
struct ieee80211_sta *sta,
struct sk_buff *skb)
{
- rtw_tx_pkt_info_update_rate(rtwdev, pkt_info, skb);
+ rtw_tx_pkt_info_update_rate(rtwdev, pkt_info, skb, false);
pkt_info->dis_qselseq = true;
pkt_info->en_hwseq = true;
pkt_info->hw_ssn_sel = 0;
@@ -295,7 +316,9 @@ static void rtw_tx_data_pkt_info_update(struct rtw_dev *rtwdev,
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_hw *hw = rtwdev->hw;
+ struct rtw_dm_info *dm_info = &rtwdev->dm_info;
struct rtw_sta_info *si;
+ u8 fix_rate;
u16 seq;
u8 ampdu_factor = 0;
u8 ampdu_density = 0;
@@ -321,11 +344,11 @@ static void rtw_tx_data_pkt_info_update(struct rtw_dev *rtwdev,
if (info->control.use_rts || skb->len > hw->wiphy->rts_threshold)
pkt_info->rts = true;
- if (sta->vht_cap.vht_supported)
+ if (sta->deflink.vht_cap.vht_supported)
rate = get_highest_vht_tx_rate(rtwdev, sta);
- else if (sta->ht_cap.ht_supported)
+ else if (sta->deflink.ht_cap.ht_supported)
rate = get_highest_ht_tx_rate(rtwdev, sta);
- else if (sta->supp_rates[0] <= 0xf)
+ else if (sta->deflink.supp_rates[0] <= 0xf)
rate = DESC_RATE11M;
else
rate = DESC_RATE54M;
@@ -334,7 +357,7 @@ static void rtw_tx_data_pkt_info_update(struct rtw_dev *rtwdev,
bw = si->bw_mode;
rate_id = si->rate_id;
- stbc = si->stbc_en;
+ stbc = rtwdev->hal.txrx_1ss ? false : si->stbc_en;
ldpc = si->ldpc_en;
out:
@@ -347,6 +370,13 @@ out:
pkt_info->bw = bw;
pkt_info->stbc = stbc;
pkt_info->ldpc = ldpc;
+
+ fix_rate = dm_info->fix_rate;
+ if (fix_rate < DESC_RATE_MAX) {
+ pkt_info->rate = fix_rate;
+ pkt_info->dis_rate_fallback = true;
+ pkt_info->use_rate = true;
+ }
}
void rtw_tx_pkt_info_update(struct rtw_dev *rtwdev,
@@ -354,7 +384,7 @@ void rtw_tx_pkt_info_update(struct rtw_dev *rtwdev,
struct ieee80211_sta *sta,
struct sk_buff *skb)
{
- struct rtw_chip_info *chip = rtwdev->chip;
+ const struct rtw_chip_info *chip = rtwdev->chip;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct rtw_sta_info *si;
@@ -394,7 +424,7 @@ void rtw_tx_rsvd_page_pkt_info_update(struct rtw_dev *rtwdev,
struct sk_buff *skb,
enum rtw_rsvd_packet_type type)
{
- struct rtw_chip_info *chip = rtwdev->chip;
+ const struct rtw_chip_info *chip = rtwdev->chip;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
bool bmc;
@@ -404,7 +434,7 @@ void rtw_tx_rsvd_page_pkt_info_update(struct rtw_dev *rtwdev,
if (type != RSVD_BEACON && type != RSVD_DUMMY)
pkt_info->qsel = TX_DESC_QSEL_MGMT;
- rtw_tx_pkt_info_update_rate(rtwdev, pkt_info, skb);
+ rtw_tx_pkt_info_update_rate(rtwdev, pkt_info, skb, true);
bmc = is_broadcast_ether_addr(hdr->addr1) ||
is_multicast_ether_addr(hdr->addr1);
@@ -422,6 +452,19 @@ void rtw_tx_rsvd_page_pkt_info_update(struct rtw_dev *rtwdev,
if (type == RSVD_QOS_NULL)
pkt_info->bt_null = true;
+ if (type == RSVD_BEACON) {
+ struct rtw_rsvd_page *rsvd_pkt;
+ int hdr_len;
+
+ rsvd_pkt = list_first_entry_or_null(&rtwdev->rsvd_page_list,
+ struct rtw_rsvd_page,
+ build_list);
+ if (rsvd_pkt && rsvd_pkt->tim_offset != 0) {
+ hdr_len = sizeof(struct ieee80211_hdr_3addr);
+ pkt_info->tim_offset = rsvd_pkt->tim_offset - hdr_len;
+ }
+ }
+
rtw_tx_pkt_info_update_sec(rtwdev, pkt_info, skb);
/* TODO: need to change hw port and hw ssn sel for multiple vifs */
@@ -432,7 +475,7 @@ rtw_tx_write_data_rsvd_page_get(struct rtw_dev *rtwdev,
struct rtw_tx_pkt_info *pkt_info,
u8 *buf, u32 size)
{
- struct rtw_chip_info *chip = rtwdev->chip;
+ const struct rtw_chip_info *chip = rtwdev->chip;
struct sk_buff *skb;
u32 tx_pkt_desc_sz;
u32 length;
@@ -458,7 +501,7 @@ rtw_tx_write_data_h2c_get(struct rtw_dev *rtwdev,
struct rtw_tx_pkt_info *pkt_info,
u8 *buf, u32 size)
{
- struct rtw_chip_info *chip = rtwdev->chip;
+ const struct rtw_chip_info *chip = rtwdev->chip;
struct sk_buff *skb;
u32 tx_pkt_desc_sz;
u32 length;