Commit 24299fc8 authored by Lorenzo Bianconi's avatar Lorenzo Bianconi Committed by Felix Fietkau
Browse files

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: default avatarLorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: default avatarFelix Fietkau <nbd@nbd.name>
parent 868fe07e
Loading
Loading
Loading
Loading
+29 −0
Original line number Diff line number Diff line
@@ -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);
+3 −0
Original line number Diff line number Diff line
@@ -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,
+3 −1
Original line number Diff line number Diff line
@@ -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,
+37 −15
Original line number Diff line number Diff line
@@ -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,30 +558,43 @@ 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;
		if (!hdr_trans) {
			memmove(skb->data + 2, skb->data,
				ieee80211_get_hdrlen_from_skb(skb));
			skb_pull(skb, 2);
		}
	}

	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);
		}

		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);

	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;
}
+11 −0
Original line number Diff line number Diff line
@@ -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)
Loading