mt76: mt7615: add support for rx decapsulation offload
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>
This commit is contained in:
parent
2122dfbfd0
commit
d4b98c63d7
9 changed files with 127 additions and 13 deletions
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -360,6 +362,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;
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
@ -2500,6 +2519,26 @@ out:
|
|||
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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue