Commit e195dad1 authored by Felix Fietkau's avatar Felix Fietkau
Browse files

mt76: add support for 802.3 rx frames



Do not try to access the header when receiving them

Signed-off-by: default avatarFelix Fietkau <nbd@nbd.name>
parent fa9f5d0e
Loading
Loading
Loading
Loading
+7 −6
Original line number Diff line number Diff line
@@ -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))
@@ -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;

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

+17 −6
Original line number Diff line number Diff line
@@ -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))
@@ -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;
@@ -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);
@@ -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
@@ -823,7 +825,6 @@ 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;

@@ -831,6 +832,11 @@ mt76_airtime_check(struct mt76_dev *dev, struct sk_buff *skb)
		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;

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

@@ -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;
+1 −1
Original line number Diff line number Diff line
@@ -499,7 +499,7 @@ struct mt76_rx_status {

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

	u16 freq;
+1 −1
Original line number Diff line number Diff line
@@ -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;
+1 −1
Original line number Diff line number Diff line
@@ -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;
Loading