mt76: mt7921: enable rx header traslation offload
authorLorenzo Bianconi <lorenzo@kernel.org>
Thu, 6 May 2021 18:13:34 +0000 (20:13 +0200)
committerFelix Fietkau <nbd@nbd.name>
Sat, 19 Jun 2021 07:22:43 +0000 (09:22 +0200)
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>
drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
drivers/net/wireless/mediatek/mt76/mt7921/init.c
drivers/net/wireless/mediatek/mt76/mt7921/mac.c
drivers/net/wireless/mediatek/mt76/mt7921/mac.h
drivers/net/wireless/mediatek/mt76/mt7921/main.c

index 443e510..7b8f8e6 100644 (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);
 
+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,
                                      struct sk_buff *skb,
                                      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,
                                                 info->sta, sta_wtbl,
                                                 wtbl_hdr);
+               mt76_connac_mcu_wtbl_hdr_trans_tlv(skb, info->vif, info->wcid,
+                                                  sta_wtbl, wtbl_hdr);
                if (info->sta)
                        mt76_connac_mcu_wtbl_ht_tlv(dev, skb, info->sta,
                                                    sta_wtbl, wtbl_hdr);
index f049392..01fc9f2 100644 (file)
@@ -972,6 +972,9 @@ void mt76_connac_mcu_wtbl_hdr_trans_tlv(struct sk_buff *skb,
                                        struct ieee80211_vif *vif,
                                        struct mt76_wcid *wcid,
                                        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,
                             struct ieee80211_sta *sta,
                             struct ieee80211_vif *vif,
index 73741e1..d5ad92a 100644 (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, HAS_RATE_CONTROL);
        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, SUPPORTS_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);
        /* enable hardware de-agg */
        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++)
                mt7921_mac_wtbl_update(dev, i,
index 7e57d23..74974f6 100644 (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)
 {
        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 mt7921_phy *phy = &dev->phy;
        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 rxd3 = le32_to_cpu(rxd[3]);
        u32 rxd4 = le32_to_cpu(rxd[4]);
-       bool unicast, insert_ccmp_hdr = false;
-       u8 remove_pad, amsdu_info;
+       u16 seq_ctrl = 0;
+       __le16 fc = 0;
        int i, idx;
-       u8 chfreq;
 
        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);
        unicast = FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, rxd3) == MT_RXD3_NORMAL_U2M;
        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);
 
        if (status->wcid) {
@@ -381,6 +383,13 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
 
        rxd += 6;
        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;
                if ((u8 *)rxd - skb->data >= skb->len)
                        return -EINVAL;
@@ -549,15 +558,30 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
        if (status->amsdu) {
                status->first_amsdu = amsdu_info == MT_RXD4_FIRST_AMSDU_FRAME;
                status->last_amsdu = amsdu_info == MT_RXD4_LAST_AMSDU_FRAME;
-               memmove(skb->data + 2, skb->data,
-                       ieee80211_get_hdrlen_from_skb(skb));
-               skb_pull(skb, 2);
+               if (!hdr_trans) {
+                       memmove(skb->data + 2, skb->data,
+                               ieee80211_get_hdrlen_from_skb(skb));
+                       skb_pull(skb, 2);
+               }
        }
 
-       if (insert_ccmp_hdr) {
-               u8 key_id = FIELD_GET(MT_RXD1_NORMAL_KEY_ID, rxd1);
+       if (!hdr_trans) {
+               if (insert_ccmp_hdr) {
+                       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);
@@ -565,14 +589,12 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
        if (rxv && status->flag & RX_FLAG_RADIOTAP_HE)
                mt7921_mac_decode_he_radiotap(skb, status, rxv, mode);
 
-       hdr = mt76_skb_get_hdr(skb);
-       if (!status->wcid || !ieee80211_is_data_qos(hdr->frame_control))
+       if (!status->wcid || !ieee80211_is_data_qos(fc))
                return 0;
 
-       status->aggr = unicast &&
-                      !ieee80211_is_qos_nullfunc(hdr->frame_control);
-       status->qos_ctl = *ieee80211_get_qos_ctl(hdr);
-       status->seqno = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));
+       status->aggr = unicast && !ieee80211_is_qos_nullfunc(fc);
+       status->seqno = IEEE80211_SEQ_TO_SN(seq_ctrl);
+       status->qos_ctl = qos_ctl;
 
        return 0;
 }
index 435c138..3af67fa 100644 (file)
@@ -100,6 +100,17 @@ enum rx_pkt_type {
 #define MT_RXD3_NORMAL_PF_MODE         BIT(29)
 #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 */
 #define MT_PRXV_TX_RATE                        GENMASK(6, 0)
 #define MT_PRXV_TX_DCM                 BIT(4)
index 97a0ef3..8016f83 100644 (file)
@@ -1163,6 +1163,23 @@ static void mt7921_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
                           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 = {
        .tx = mt7921_tx,
        .start = mt7921_start,
@@ -1177,6 +1194,7 @@ const struct ieee80211_ops mt7921_ops = {
        .sta_remove = mt7921_sta_remove,
        .sta_pre_rcu_remove = mt76_sta_pre_rcu_remove,
        .set_key = mt7921_set_key,
+       .sta_set_decap_offload = mt7921_sta_set_decap_offload,
        .ampdu_action = mt7921_ampdu_action,
        .set_rts_threshold = mt7921_set_rts_threshold,
        .wake_tx_queue = mt76_wake_tx_queue,