Skip to content

Commit

Permalink
mt76: add support for 802.3 rx frames
Browse files Browse the repository at this point in the history
Do not try to access the header when receiving them

Signed-off-by: Felix Fietkau <nbd@nbd.name>
  • Loading branch information
nbd168 committed Apr 11, 2021
1 parent fa9f5d0 commit e195dad
Show file tree
Hide file tree
Showing 8 changed files with 32 additions and 18 deletions.
13 changes: 7 additions & 6 deletions drivers/net/wireless/mediatek/mt76/agg-rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ mt76_rx_aggr_check_ctl(struct sk_buff *skb, struct sk_buff_head *frames)
struct ieee80211_bar *bar = mt76_skb_get_hdr(skb);
struct mt76_wcid *wcid = status->wcid;
struct mt76_rx_tid *tid;
u8 tidno = status->qos_ctl & IEEE80211_QOS_CTL_TID_MASK;
u16 seqno;

if (!ieee80211_is_ctl(bar->frame_control))
Expand All @@ -130,9 +131,9 @@ mt76_rx_aggr_check_ctl(struct sk_buff *skb, struct sk_buff_head *frames)
if (!ieee80211_is_back_req(bar->frame_control))
return;

status->tid = le16_to_cpu(bar->control) >> 12;
status->qos_ctl = tidno = le16_to_cpu(bar->control) >> 12;
seqno = IEEE80211_SEQ_TO_SN(le16_to_cpu(bar->start_seq_num));
tid = rcu_dereference(wcid->aggr[status->tid]);
tid = rcu_dereference(wcid->aggr[tidno]);
if (!tid)
return;

Expand All @@ -147,12 +148,12 @@ mt76_rx_aggr_check_ctl(struct sk_buff *skb, struct sk_buff_head *frames)
void mt76_rx_aggr_reorder(struct sk_buff *skb, struct sk_buff_head *frames)
{
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb);
struct mt76_wcid *wcid = status->wcid;
struct ieee80211_sta *sta;
struct mt76_rx_tid *tid;
bool sn_less;
u16 seqno, head, size, idx;
u8 tidno = status->qos_ctl & IEEE80211_QOS_CTL_TID_MASK;
u8 ackp;

__skb_queue_tail(frames, skb);
Expand All @@ -161,18 +162,18 @@ void mt76_rx_aggr_reorder(struct sk_buff *skb, struct sk_buff_head *frames)
if (!sta)
return;

if (!status->aggr) {
if (!status->aggr && !(status->flag & RX_FLAG_8023)) {
mt76_rx_aggr_check_ctl(skb, frames);
return;
}

/* not part of a BA session */
ackp = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_ACK_POLICY_MASK;
ackp = status->qos_ctl & IEEE80211_QOS_CTL_ACK_POLICY_MASK;
if (ackp != IEEE80211_QOS_CTL_ACK_POLICY_BLOCKACK &&
ackp != IEEE80211_QOS_CTL_ACK_POLICY_NORMAL)
return;

tid = rcu_dereference(wcid->aggr[status->tid]);
tid = rcu_dereference(wcid->aggr[tidno]);
if (!tid)
return;

Expand Down
23 changes: 17 additions & 6 deletions drivers/net/wireless/mediatek/mt76/mac80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,7 @@ mt76_check_ccmp_pn(struct sk_buff *skb)
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
struct mt76_wcid *wcid = status->wcid;
struct ieee80211_hdr *hdr;
u8 tidno = status->qos_ctl & IEEE80211_QOS_CTL_TID_MASK;
int ret;

if (!(status->flag & RX_FLAG_DECRYPTED))
Expand All @@ -757,12 +758,12 @@ mt76_check_ccmp_pn(struct sk_buff *skb)
}

BUILD_BUG_ON(sizeof(status->iv) != sizeof(wcid->rx_key_pn[0]));
ret = memcmp(status->iv, wcid->rx_key_pn[status->tid],
ret = memcmp(status->iv, wcid->rx_key_pn[tidno],
sizeof(status->iv));
if (ret <= 0)
return -EINVAL; /* replay */

memcpy(wcid->rx_key_pn[status->tid], status->iv, sizeof(status->iv));
memcpy(wcid->rx_key_pn[tidno], status->iv, sizeof(status->iv));

if (status->flag & RX_FLAG_IV_STRIPPED)
status->flag |= RX_FLAG_PN_VALIDATED;
Expand All @@ -785,6 +786,7 @@ mt76_airtime_report(struct mt76_dev *dev, struct mt76_rx_status *status,
};
struct ieee80211_sta *sta;
u32 airtime;
u8 tidno = status->qos_ctl & IEEE80211_QOS_CTL_TID_MASK;

airtime = ieee80211_calc_rx_airtime(dev->hw, &info, len);
spin_lock(&dev->cc_lock);
Expand All @@ -795,7 +797,7 @@ mt76_airtime_report(struct mt76_dev *dev, struct mt76_rx_status *status,
return;

sta = container_of((void *)wcid, struct ieee80211_sta, drv_priv);
ieee80211_sta_register_airtime(sta, status->tid, 0, airtime);
ieee80211_sta_register_airtime(sta, tidno, 0, airtime);
}

static void
Expand Down Expand Up @@ -823,14 +825,18 @@ mt76_airtime_flush_ampdu(struct mt76_dev *dev)
static void
mt76_airtime_check(struct mt76_dev *dev, struct sk_buff *skb)
{
struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb);
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
struct mt76_wcid *wcid = status->wcid;

if (!(dev->drv->drv_flags & MT_DRV_SW_RX_AIRTIME))
return;

if (!wcid || !wcid->sta) {
struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb);

if (status->flag & RX_FLAG_8023)
return;

if (!ether_addr_equal(hdr->addr1, dev->phy.macaddr))
return;

Expand Down Expand Up @@ -864,10 +870,12 @@ mt76_check_sta(struct mt76_dev *dev, struct sk_buff *skb)
struct ieee80211_sta *sta;
struct ieee80211_hw *hw;
struct mt76_wcid *wcid = status->wcid;
u8 tidno = status->qos_ctl & IEEE80211_QOS_CTL_TID_MASK;
bool ps;

hw = mt76_phy_hw(dev, status->ext_phy);
if (ieee80211_is_pspoll(hdr->frame_control) && !wcid) {
if (ieee80211_is_pspoll(hdr->frame_control) && !wcid &&
!(status->flag & RX_FLAG_8023)) {
sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, NULL);
if (sta)
wcid = status->wcid = (struct mt76_wcid *)sta->drv_priv;
Expand All @@ -885,6 +893,9 @@ mt76_check_sta(struct mt76_dev *dev, struct sk_buff *skb)

wcid->inactive_count = 0;

if (status->flag & RX_FLAG_8023)
return;

if (!test_bit(MT_WCID_FLAG_CHECK_PS, &wcid->flags))
return;

Expand All @@ -902,7 +913,7 @@ mt76_check_sta(struct mt76_dev *dev, struct sk_buff *skb)

if (ps && (ieee80211_is_data_qos(hdr->frame_control) ||
ieee80211_is_qos_nullfunc(hdr->frame_control)))
ieee80211_sta_uapsd_trigger(sta, status->tid);
ieee80211_sta_uapsd_trigger(sta, tidno);

if (!!test_bit(MT_WCID_FLAG_PS, &wcid->flags) == ps)
return;
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/mediatek/mt76/mt76.h
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,7 @@ struct mt76_rx_status {

u8 ext_phy:1;
u8 aggr:1;
u8 tid;
u8 qos_ctl;
u16 seqno;

u16 freq;
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/mediatek/mt76/mt7603/mac.c
Original file line number Diff line number Diff line change
Expand Up @@ -651,7 +651,7 @@ mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb)

status->aggr = unicast &&
!ieee80211_is_qos_nullfunc(hdr->frame_control);
status->tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
status->qos_ctl = *ieee80211_get_qos_ctl(hdr);
status->seqno = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));

return 0;
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/mediatek/mt76/mt7615/mac.c
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,7 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb)

status->aggr = unicast &&
!ieee80211_is_qos_nullfunc(hdr->frame_control);
status->tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
status->qos_ctl = *ieee80211_get_qos_ctl(hdr);
status->seqno = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));

return 0;
Expand Down
4 changes: 3 additions & 1 deletion drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
Original file line number Diff line number Diff line change
Expand Up @@ -770,6 +770,7 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb,
void *rxi)
{
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
struct ieee80211_hdr *hdr;
struct mt76x02_rxwi *rxwi = rxi;
struct mt76x02_sta *sta;
u32 rxinfo = le32_to_cpu(rxwi->rxinfo);
Expand Down Expand Up @@ -864,7 +865,8 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb,
status->freq = dev->mphy.chandef.chan->center_freq;
status->band = dev->mphy.chandef.chan->band;

status->tid = FIELD_GET(MT_RXWI_TID, tid_sn);
hdr = (struct ieee80211_hdr *)skb->data;
status->qos_ctl = *ieee80211_get_qos_ctl(hdr);
status->seqno = FIELD_GET(MT_RXWI_SN, tid_sn);

return mt76x02_mac_process_rate(dev, status, rate);
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/mediatek/mt76/mt7915/mac.c
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,7 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)

status->aggr = unicast &&
!ieee80211_is_qos_nullfunc(hdr->frame_control);
status->tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
status->qos_ctl = *ieee80211_get_qos_ctl(hdr);
status->seqno = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));

return 0;
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/mediatek/mt76/mt7921/mac.c
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)

status->aggr = unicast &&
!ieee80211_is_qos_nullfunc(hdr->frame_control);
status->tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
status->qos_ctl = *ieee80211_get_qos_ctl(hdr);
status->seqno = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));

return 0;
Expand Down

0 comments on commit e195dad

Please sign in to comment.