mt76: mt7921: enable rx header traslation offload

As already done for mt7615 and mt7915, enable rx header translation
offload for mt7921 in order to reduce cpu load in the rx path.

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
Lorenzo Bianconi 2021-05-06 20:13:34 +02:00 committed by Felix Fietkau
parent 868fe07ee6
commit 24299fc869
6 changed files with 101 additions and 16 deletions

View file

@ -418,6 +418,33 @@ void mt76_connac_mcu_wtbl_hdr_trans_tlv(struct sk_buff *skb,
} }
EXPORT_SYMBOL_GPL(mt76_connac_mcu_wtbl_hdr_trans_tlv); EXPORT_SYMBOL_GPL(mt76_connac_mcu_wtbl_hdr_trans_tlv);
int mt76_connac_mcu_sta_update_hdr_trans(struct mt76_dev *dev,
struct ieee80211_vif *vif,
struct mt76_wcid *wcid, int cmd)
{
struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
struct wtbl_req_hdr *wtbl_hdr;
struct tlv *sta_wtbl;
struct sk_buff *skb;
skb = mt76_connac_mcu_alloc_sta_req(dev, mvif, wcid);
if (IS_ERR(skb))
return PTR_ERR(skb);
sta_wtbl = mt76_connac_mcu_add_tlv(skb, STA_REC_WTBL,
sizeof(struct tlv));
wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(dev, wcid, WTBL_SET,
sta_wtbl, &skb);
if (IS_ERR(wtbl_hdr))
return PTR_ERR(wtbl_hdr);
mt76_connac_mcu_wtbl_hdr_trans_tlv(skb, vif, wcid, sta_wtbl, wtbl_hdr);
return mt76_mcu_skb_send_msg(dev, skb, cmd, true);
}
EXPORT_SYMBOL_GPL(mt76_connac_mcu_sta_update_hdr_trans);
void mt76_connac_mcu_wtbl_generic_tlv(struct mt76_dev *dev, void mt76_connac_mcu_wtbl_generic_tlv(struct mt76_dev *dev,
struct sk_buff *skb, struct sk_buff *skb,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
@ -870,6 +897,8 @@ int mt76_connac_mcu_add_sta_cmd(struct mt76_phy *phy,
mt76_connac_mcu_wtbl_generic_tlv(dev, skb, info->vif, mt76_connac_mcu_wtbl_generic_tlv(dev, skb, info->vif,
info->sta, sta_wtbl, info->sta, sta_wtbl,
wtbl_hdr); wtbl_hdr);
mt76_connac_mcu_wtbl_hdr_trans_tlv(skb, info->vif, info->wcid,
sta_wtbl, wtbl_hdr);
if (info->sta) if (info->sta)
mt76_connac_mcu_wtbl_ht_tlv(dev, skb, info->sta, mt76_connac_mcu_wtbl_ht_tlv(dev, skb, info->sta,
sta_wtbl, wtbl_hdr); sta_wtbl, wtbl_hdr);

View file

@ -972,6 +972,9 @@ void mt76_connac_mcu_wtbl_hdr_trans_tlv(struct sk_buff *skb,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
struct mt76_wcid *wcid, struct mt76_wcid *wcid,
void *sta_wtbl, void *wtbl_tlv); void *sta_wtbl, void *wtbl_tlv);
int mt76_connac_mcu_sta_update_hdr_trans(struct mt76_dev *dev,
struct ieee80211_vif *vif,
struct mt76_wcid *wcid, int cmd);
void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb, void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb,
struct ieee80211_sta *sta, struct ieee80211_sta *sta,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,

View file

@ -78,6 +78,7 @@ mt7921_init_wiphy(struct ieee80211_hw *hw)
ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS); ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS);
ieee80211_hw_set(hw, HAS_RATE_CONTROL); ieee80211_hw_set(hw, HAS_RATE_CONTROL);
ieee80211_hw_set(hw, SUPPORTS_TX_ENCAP_OFFLOAD); ieee80211_hw_set(hw, SUPPORTS_TX_ENCAP_OFFLOAD);
ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD);
ieee80211_hw_set(hw, WANT_MONITOR_VIF); ieee80211_hw_set(hw, WANT_MONITOR_VIF);
ieee80211_hw_set(hw, SUPPORTS_PS); ieee80211_hw_set(hw, SUPPORTS_PS);
ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS); ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);
@ -127,7 +128,8 @@ void mt7921_mac_init(struct mt7921_dev *dev)
mt76_rmw_field(dev, MT_MDP_DCR1, MT_MDP_DCR1_MAX_RX_LEN, 1536); mt76_rmw_field(dev, MT_MDP_DCR1, MT_MDP_DCR1_MAX_RX_LEN, 1536);
/* enable hardware de-agg */ /* enable hardware de-agg */
mt76_set(dev, MT_MDP_DCR0, MT_MDP_DCR0_DAMSDU_EN); mt76_set(dev, MT_MDP_DCR0, MT_MDP_DCR0_DAMSDU_EN);
mt76_clear(dev, MT_MDP_DCR0, MT_MDP_DCR0_RX_HDR_TRANS_EN); /* enable hardware rx header translation */
mt76_set(dev, MT_MDP_DCR0, MT_MDP_DCR0_RX_HDR_TRANS_EN);
for (i = 0; i < MT7921_WTBL_SIZE; i++) for (i = 0; i < MT7921_WTBL_SIZE; i++)
mt7921_mac_wtbl_update(dev, i, mt7921_mac_wtbl_update(dev, i,

View file

@ -309,6 +309,8 @@ mt7921_mac_assoc_rssi(struct mt7921_dev *dev, struct sk_buff *skb)
int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb) int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
{ {
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
bool hdr_trans, unicast, insert_ccmp_hdr = false;
u8 chfreq, qos_ctl = 0, remove_pad, amsdu_info;
struct mt76_phy *mphy = &dev->mt76.phy; struct mt76_phy *mphy = &dev->mt76.phy;
struct mt7921_phy *phy = &dev->phy; struct mt7921_phy *phy = &dev->phy;
struct ieee80211_supported_band *sband; struct ieee80211_supported_band *sband;
@ -320,10 +322,9 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
u32 rxd2 = le32_to_cpu(rxd[2]); u32 rxd2 = le32_to_cpu(rxd[2]);
u32 rxd3 = le32_to_cpu(rxd[3]); u32 rxd3 = le32_to_cpu(rxd[3]);
u32 rxd4 = le32_to_cpu(rxd[4]); u32 rxd4 = le32_to_cpu(rxd[4]);
bool unicast, insert_ccmp_hdr = false; u16 seq_ctrl = 0;
u8 remove_pad, amsdu_info; __le16 fc = 0;
int i, idx; int i, idx;
u8 chfreq;
memset(status, 0, sizeof(*status)); memset(status, 0, sizeof(*status));
@ -339,6 +340,7 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
chfreq = FIELD_GET(MT_RXD3_NORMAL_CH_FREQ, rxd3); chfreq = FIELD_GET(MT_RXD3_NORMAL_CH_FREQ, rxd3);
unicast = FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, rxd3) == MT_RXD3_NORMAL_U2M; unicast = FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, rxd3) == MT_RXD3_NORMAL_U2M;
idx = FIELD_GET(MT_RXD1_NORMAL_WLAN_IDX, rxd1); idx = FIELD_GET(MT_RXD1_NORMAL_WLAN_IDX, rxd1);
hdr_trans = rxd2 & MT_RXD2_NORMAL_HDR_TRANS;
status->wcid = mt7921_rx_get_wcid(dev, idx, unicast); status->wcid = mt7921_rx_get_wcid(dev, idx, unicast);
if (status->wcid) { if (status->wcid) {
@ -381,6 +383,13 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
rxd += 6; rxd += 6;
if (rxd1 & MT_RXD1_NORMAL_GROUP_4) { if (rxd1 & MT_RXD1_NORMAL_GROUP_4) {
u32 v0 = le32_to_cpu(rxd[0]);
u32 v2 = le32_to_cpu(rxd[2]);
fc = cpu_to_le16(FIELD_GET(MT_RXD6_FRAME_CONTROL, v0));
seq_ctrl = FIELD_GET(MT_RXD8_SEQ_CTRL, v2);
qos_ctl = FIELD_GET(MT_RXD8_QOS_CTL, v2);
rxd += 4; rxd += 4;
if ((u8 *)rxd - skb->data >= skb->len) if ((u8 *)rxd - skb->data >= skb->len)
return -EINVAL; return -EINVAL;
@ -549,30 +558,43 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
if (status->amsdu) { if (status->amsdu) {
status->first_amsdu = amsdu_info == MT_RXD4_FIRST_AMSDU_FRAME; status->first_amsdu = amsdu_info == MT_RXD4_FIRST_AMSDU_FRAME;
status->last_amsdu = amsdu_info == MT_RXD4_LAST_AMSDU_FRAME; status->last_amsdu = amsdu_info == MT_RXD4_LAST_AMSDU_FRAME;
if (!hdr_trans) {
memmove(skb->data + 2, skb->data, memmove(skb->data + 2, skb->data,
ieee80211_get_hdrlen_from_skb(skb)); ieee80211_get_hdrlen_from_skb(skb));
skb_pull(skb, 2); skb_pull(skb, 2);
} }
}
if (!hdr_trans) {
if (insert_ccmp_hdr) { if (insert_ccmp_hdr) {
u8 key_id = FIELD_GET(MT_RXD1_NORMAL_KEY_ID, rxd1); u8 key_id = FIELD_GET(MT_RXD1_NORMAL_KEY_ID, rxd1);
mt76_insert_ccmp_hdr(skb, key_id); mt76_insert_ccmp_hdr(skb, key_id);
} }
hdr = mt76_skb_get_hdr(skb);
fc = hdr->frame_control;
if (ieee80211_is_data_qos(fc)) {
seq_ctrl = le16_to_cpu(hdr->seq_ctrl);
qos_ctl = *ieee80211_get_qos_ctl(hdr);
}
} else {
status->flag &= ~(RX_FLAG_RADIOTAP_HE |
RX_FLAG_RADIOTAP_HE_MU);
status->flag |= RX_FLAG_8023;
}
mt7921_mac_assoc_rssi(dev, skb); mt7921_mac_assoc_rssi(dev, skb);
if (rxv && status->flag & RX_FLAG_RADIOTAP_HE) if (rxv && status->flag & RX_FLAG_RADIOTAP_HE)
mt7921_mac_decode_he_radiotap(skb, status, rxv, mode); mt7921_mac_decode_he_radiotap(skb, status, rxv, mode);
hdr = mt76_skb_get_hdr(skb); if (!status->wcid || !ieee80211_is_data_qos(fc))
if (!status->wcid || !ieee80211_is_data_qos(hdr->frame_control))
return 0; return 0;
status->aggr = unicast && status->aggr = unicast && !ieee80211_is_qos_nullfunc(fc);
!ieee80211_is_qos_nullfunc(hdr->frame_control); status->seqno = IEEE80211_SEQ_TO_SN(seq_ctrl);
status->qos_ctl = *ieee80211_get_qos_ctl(hdr); status->qos_ctl = qos_ctl;
status->seqno = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));
return 0; return 0;
} }

View file

@ -100,6 +100,17 @@ enum rx_pkt_type {
#define MT_RXD3_NORMAL_PF_MODE BIT(29) #define MT_RXD3_NORMAL_PF_MODE BIT(29)
#define MT_RXD3_NORMAL_PF_STS GENMASK(31, 30) #define MT_RXD3_NORMAL_PF_STS GENMASK(31, 30)
/* RXD GROUP4 */
#define MT_RXD6_FRAME_CONTROL GENMASK(15, 0)
#define MT_RXD6_TA_LO GENMASK(31, 16)
#define MT_RXD7_TA_HI GENMASK(31, 0)
#define MT_RXD8_SEQ_CTRL GENMASK(15, 0)
#define MT_RXD8_QOS_CTL GENMASK(31, 16)
#define MT_RXD9_HT_CONTROL GENMASK(31, 0)
/* P-RXV DW0 */ /* P-RXV DW0 */
#define MT_PRXV_TX_RATE GENMASK(6, 0) #define MT_PRXV_TX_RATE GENMASK(6, 0)
#define MT_PRXV_TX_DCM BIT(4) #define MT_PRXV_TX_DCM BIT(4)

View file

@ -1163,6 +1163,23 @@ static void mt7921_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
HZ / 2); HZ / 2);
} }
static void mt7921_sta_set_decap_offload(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
bool enabled)
{
struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv;
struct mt7921_dev *dev = mt7921_hw_dev(hw);
if (enabled)
set_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags);
else
clear_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags);
mt76_connac_mcu_sta_update_hdr_trans(&dev->mt76, vif, &msta->wcid,
MCU_UNI_CMD_STA_REC_UPDATE);
}
const struct ieee80211_ops mt7921_ops = { const struct ieee80211_ops mt7921_ops = {
.tx = mt7921_tx, .tx = mt7921_tx,
.start = mt7921_start, .start = mt7921_start,
@ -1177,6 +1194,7 @@ const struct ieee80211_ops mt7921_ops = {
.sta_remove = mt7921_sta_remove, .sta_remove = mt7921_sta_remove,
.sta_pre_rcu_remove = mt76_sta_pre_rcu_remove, .sta_pre_rcu_remove = mt76_sta_pre_rcu_remove,
.set_key = mt7921_set_key, .set_key = mt7921_set_key,
.sta_set_decap_offload = mt7921_sta_set_decap_offload,
.ampdu_action = mt7921_ampdu_action, .ampdu_action = mt7921_ampdu_action,
.set_rts_threshold = mt7921_set_rts_threshold, .set_rts_threshold = mt7921_set_rts_threshold,
.wake_tx_queue = mt76_wake_tx_queue, .wake_tx_queue = mt76_wake_tx_queue,