Skip to content

Commit

Permalink
mt76: mt7615: add support for rx decapsulation offload
Browse files Browse the repository at this point in the history
For AP and Client mode, the hardware can pass received packets
as 802.3 frames that can be passed to the network stack as-is.

Tested-by: Frank Wunderlich <frank-w@public-files.de>
Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
  • Loading branch information
ryderlee1110 authored and nbd168 committed Mar 14, 2021
1 parent 9002b0b commit 8e3f5bf
Show file tree
Hide file tree
Showing 9 changed files with 127 additions and 13 deletions.
5 changes: 4 additions & 1 deletion mt7615/init.c
Expand Up @@ -118,7 +118,8 @@ mt7615_mac_init(struct mt7615_dev *dev)

mt76_wr(dev, MT_DMA_DCR0,
FIELD_PREP(MT_DMA_DCR0_MAX_RX_LEN, 3072) |
MT_DMA_DCR0_RX_VEC_DROP | MT_DMA_DCR0_DAMSDU_EN);
MT_DMA_DCR0_RX_VEC_DROP | MT_DMA_DCR0_DAMSDU_EN |
MT_DMA_DCR0_RX_HDR_TRANS_EN);
/* disable TDLS filtering */
mt76_clear(dev, MT_WF_PFCR, MT_WF_PFCR_TDLS_EN);
mt76_set(dev, MT_WF_MIB_SCR0, MT_MIB_SCR0_AGG_CNT_RANGE_EN);
Expand All @@ -128,6 +129,7 @@ mt7615_mac_init(struct mt7615_dev *dev)
} else {
mt7615_init_mac_chain(dev, 1);
}
mt7615_mcu_set_rx_hdr_trans_blacklist(dev);
}

static void
Expand Down Expand Up @@ -368,6 +370,7 @@ mt7615_init_wiphy(struct ieee80211_hw *hw)
ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS);
ieee80211_hw_set(hw, TX_STATUS_NO_AMPDU_LEN);
ieee80211_hw_set(hw, WANT_MONITOR_VIF);
ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD);

if (is_mt7615(&phy->dev->mt76))
hw->max_tx_fragments = MT_TXP_MAX_BUF_NUM;
Expand Down
44 changes: 33 additions & 11 deletions mt7615/mac.c
Expand Up @@ -236,10 +236,12 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb)
u32 rxd2 = le32_to_cpu(rxd[2]);
u32 csum_mask = MT_RXD0_NORMAL_IP_SUM | MT_RXD0_NORMAL_UDP_TCP_SUM;
__le32 rxd12 = rxd[12];
bool unicast, remove_pad, insert_ccmp_hdr = false;
bool unicast, hdr_trans, remove_pad, insert_ccmp_hdr = false;
int phy_idx;
int i, idx;
u8 chfreq, amsdu_info;
u8 chfreq, amsdu_info, qos_ctl = 0;
u16 seq_ctrl = 0;
__le16 fc = 0;

memset(status, 0, sizeof(*status));

Expand All @@ -260,6 +262,7 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb)

unicast = (rxd1 & MT_RXD1_NORMAL_ADDR_TYPE) == MT_RXD1_NORMAL_U2M;
idx = FIELD_GET(MT_RXD2_NORMAL_WLAN_IDX, rxd2);
hdr_trans = rxd1 & MT_RXD1_NORMAL_HDR_TRANS;
status->wcid = mt7615_rx_get_wcid(dev, idx, unicast);

if (status->wcid) {
Expand Down Expand Up @@ -295,6 +298,13 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb)

rxd += 4;
if (rxd0 & MT_RXD0_NORMAL_GROUP_4) {
u32 v0 = le32_to_cpu(rxd[0]);
u32 v2 = le32_to_cpu(rxd[2]);

fc = cpu_to_le16(FIELD_GET(MT_RXD4_FRAME_CONTROL, v0));
qos_ctl = FIELD_GET(MT_RXD6_QOS_CTL, v2);
seq_ctrl = FIELD_GET(MT_RXD6_SEQ_CTRL, v2);

rxd += 4;
if ((u8 *)rxd - skb->data >= skb->len)
return -EINVAL;
Expand Down Expand Up @@ -458,25 +468,37 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb)
if (status->amsdu) {
status->first_amsdu = amsdu_info == MT_RXD1_FIRST_AMSDU_FRAME;
status->last_amsdu = amsdu_info == MT_RXD1_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) {
if (insert_ccmp_hdr && !hdr_trans) {
u8 key_id = FIELD_GET(MT_RXD1_NORMAL_KEY_ID, rxd1);

mt76_insert_ccmp_hdr(skb, key_id);
}

hdr = (struct ieee80211_hdr *)skb->data;
if (!status->wcid || !ieee80211_is_data_qos(hdr->frame_control))
if (!hdr_trans) {
hdr = (struct ieee80211_hdr *)skb->data;
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_8023;
}

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));
!ieee80211_is_qos_nullfunc(fc);
status->qos_ctl = qos_ctl;
status->seqno = IEEE80211_SEQ_TO_SN(seq_ctrl);

return 0;
}
Expand Down
5 changes: 5 additions & 0 deletions mt7615/mac.h
Expand Up @@ -81,6 +81,11 @@ enum rx_pkt_type {
#define MT_RXD3_NORMAL_TSF_COMPARE_LOSS BIT(8)
#define MT_RXD3_NORMAL_RXV_SEQ GENMASK(7, 0)

#define MT_RXD4_FRAME_CONTROL GENMASK(15, 0)

#define MT_RXD6_SEQ_CTRL GENMASK(15, 0)
#define MT_RXD6_QOS_CTL GENMASK(31, 16)

#define MT_RXV1_ACID_DET_H BIT(31)
#define MT_RXV1_ACID_DET_L BIT(30)
#define MT_RXV1_VHTA2_B8_B3 GENMASK(29, 24)
Expand Down
17 changes: 17 additions & 0 deletions mt7615/main.c
Expand Up @@ -1087,6 +1087,22 @@ static int mt7615_cancel_remain_on_channel(struct ieee80211_hw *hw,
return 0;
}

static void mt7615_sta_set_decap_offload(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
bool enabled)
{
struct mt7615_dev *dev = mt7615_hw_dev(hw);
struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv;

if (enabled)
set_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags);
else
clear_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags);

mt7615_mcu_sta_update_hdr_trans(dev, vif, sta);
}

#ifdef CONFIG_PM
static int mt7615_suspend(struct ieee80211_hw *hw,
struct cfg80211_wowlan *wowlan)
Expand Down Expand Up @@ -1187,6 +1203,7 @@ const struct ieee80211_ops mt7615_ops = {
.sta_remove = mt7615_sta_remove,
.sta_pre_rcu_remove = mt76_sta_pre_rcu_remove,
.set_key = mt7615_set_key,
.sta_set_decap_offload = mt7615_sta_set_decap_offload,
.ampdu_action = mt7615_ampdu_action,
.set_rts_threshold = mt7615_set_rts_threshold,
.wake_tx_queue = mt7615_wake_tx_queue,
Expand Down
39 changes: 39 additions & 0 deletions mt7615/mcu.c
Expand Up @@ -1097,6 +1097,25 @@ static const struct mt7615_mcu_ops sta_update_ops = {
.set_fw_ctrl = mt7615_mcu_fw_pmctrl,
};

int mt7615_mcu_sta_update_hdr_trans(struct mt7615_dev *dev,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
{
struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv;
struct wtbl_req_hdr *wtbl_hdr;
struct sk_buff *skb = NULL;

wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid,
WTBL_SET, NULL, &skb);
if (IS_ERR(wtbl_hdr))
return PTR_ERR(wtbl_hdr);

mt76_connac_mcu_wtbl_hdr_trans_tlv(skb, vif, sta, NULL, wtbl_hdr);

return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_EXT_CMD_WTBL_UPDATE,
true);
}

static int
mt7615_mcu_uni_ctrl_pm_state(struct mt7615_dev *dev, int band, int state)
{
Expand Down Expand Up @@ -2559,6 +2578,26 @@ int mt7615_mcu_apply_tx_dpd(struct mt7615_phy *phy)
return ret;
}

int mt7615_mcu_set_rx_hdr_trans_blacklist(struct mt7615_dev *dev)
{
struct {
u8 operation;
u8 count;
u8 _rsv[2];
u8 index;
u8 enable;
__le16 etype;
} req = {
.operation = 1,
.count = 1,
.enable = 1,
.etype = cpu_to_le16(ETH_P_PAE),
};

return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_RX_HDR_TRANS,
&req, sizeof(req), false);
}

int mt7615_mcu_set_bss_pm(struct mt7615_dev *dev, struct ieee80211_vif *vif,
bool enable)
{
Expand Down
4 changes: 4 additions & 0 deletions mt7615/mt7615.h
Expand Up @@ -519,6 +519,10 @@ void mt7615_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
void mt7615_mac_work(struct work_struct *work);
void mt7615_txp_skb_unmap(struct mt76_dev *dev,
struct mt76_txwi_cache *txwi);
int mt7615_mcu_sta_update_hdr_trans(struct mt7615_dev *dev,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
int mt7615_mcu_set_rx_hdr_trans_blacklist(struct mt7615_dev *dev);
int mt7615_mcu_set_fcc5_lpn(struct mt7615_dev *dev, int val);
int mt7615_mcu_set_pulse_th(struct mt7615_dev *dev,
const struct mt7615_dfs_pulse *pulse);
Expand Down
1 change: 1 addition & 0 deletions mt7615/regs.h
Expand Up @@ -370,6 +370,7 @@ enum mt7615_reg_base {
#define MT_DMA_DCR0_MAX_RX_LEN GENMASK(15, 2)
#define MT_DMA_DCR0_DAMSDU_EN BIT(16)
#define MT_DMA_DCR0_RX_VEC_DROP BIT(17)
#define MT_DMA_DCR0_RX_HDR_TRANS_EN BIT(19)

#define MT_DMA_RCFR0(_band) MT_WF_DMA(0x070 + (_band) * 0x40)
#define MT_DMA_RCFR0_MCU_RX_MGMT BIT(2)
Expand Down
19 changes: 19 additions & 0 deletions mt76_connac_mcu.c
Expand Up @@ -392,6 +392,25 @@ mt76_connac_mcu_sta_uapsd(struct sk_buff *skb, struct ieee80211_vif *vif,
uapsd->max_sp = sta->max_sp;
}

void mt76_connac_mcu_wtbl_hdr_trans_tlv(struct sk_buff *skb,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
void *sta_wtbl, void *wtbl_tlv)
{
struct mt76_wcid *wcid;
struct wtbl_hdr_trans *htr;
struct tlv *tlv;

tlv = mt76_connac_mcu_add_nested_tlv(skb, WTBL_HDR_TRANS,
sizeof(*htr),
wtbl_tlv, sta_wtbl);
htr = (struct wtbl_hdr_trans *)tlv;

wcid = (struct mt76_wcid *)sta->drv_priv;
htr->no_rx_trans = !test_bit(MT_WCID_FLAG_HDR_TRANS, &wcid->flags);
}
EXPORT_SYMBOL_GPL(mt76_connac_mcu_wtbl_hdr_trans_tlv);

void mt76_connac_mcu_wtbl_generic_tlv(struct mt76_dev *dev,
struct sk_buff *skb,
struct ieee80211_vif *vif,
Expand Down
6 changes: 5 additions & 1 deletion mt76_connac_mcu.h
Expand Up @@ -210,7 +210,7 @@ struct wtbl_hdr_trans {
__le16 len;
u8 to_ds;
u8 from_ds;
u8 disable_rx_trans;
u8 no_rx_trans;
u8 rsv;
} __packed;

Expand Down Expand Up @@ -922,6 +922,10 @@ void mt76_connac_mcu_wtbl_generic_tlv(struct mt76_dev *dev, struct sk_buff *skb,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta, void *sta_wtbl,
void *wtbl_tlv);
void mt76_connac_mcu_wtbl_hdr_trans_tlv(struct sk_buff *skb,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
void *sta_wtbl, void *wtbl_tlv);
void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb,
struct ieee80211_sta *sta,
struct ieee80211_vif *vif);
Expand Down

0 comments on commit 8e3f5bf

Please sign in to comment.