mt76: report rx a-mpdu subframe status
authorFelix Fietkau <nbd@nbd.name>
Wed, 28 Aug 2019 09:28:36 +0000 (11:28 +0200)
committerFelix Fietkau <nbd@nbd.name>
Wed, 20 Nov 2019 12:23:48 +0000 (13:23 +0100)
This can be used in monitor mode to figure out which subframes were sent as
part of which A-MPDU

Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mac80211.c
drivers/net/wireless/mediatek/mt76/mt76.h
drivers/net/wireless/mediatek/mt76/mt7603/mac.c
drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h
drivers/net/wireless/mediatek/mt76/mt7615/mac.c
drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
drivers/net/wireless/mediatek/mt76/mt76x02_mac.c

index 1a2c143..cc30121 100644 (file)
@@ -502,6 +502,7 @@ static struct ieee80211_sta *mt76_rx_convert(struct sk_buff *skb)
        status->band = mstat.band;
        status->signal = mstat.signal;
        status->chains = mstat.chains;
+       status->ampdu_reference = mstat.ampdu_ref;
 
        BUILD_BUG_ON(sizeof(mstat) > sizeof(skb->cb));
        BUILD_BUG_ON(sizeof(status->chain_signal) !=
index b3e776e..187c3e8 100644 (file)
@@ -438,6 +438,7 @@ struct mt76_dev {
        spinlock_t rx_lock;
        struct napi_struct napi[__MT_RXQ_MAX];
        struct sk_buff_head rx_skb[__MT_RXQ_MAX];
+       u32 ampdu_ref;
 
        struct list_head txwi_cache;
        struct mt76_sw_queue q_tx[__MT_TXQ_MAX];
@@ -514,6 +515,8 @@ struct mt76_rx_status {
 
        unsigned long reorder_time;
 
+       u32 ampdu_ref;
+
        u8 iv[6];
 
        u8 aggr:1;
index c52c4bf..44d0939 100644 (file)
@@ -445,6 +445,20 @@ mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb)
                status->flag |= RX_FLAG_MMIC_STRIPPED | RX_FLAG_MIC_STRIPPED;
        }
 
+       if (!(rxd2 & (MT_RXD2_NORMAL_NON_AMPDU_SUB |
+                     MT_RXD2_NORMAL_NON_AMPDU))) {
+               status->flag |= RX_FLAG_AMPDU_DETAILS;
+
+               /* all subframes of an A-MPDU have the same timestamp */
+               if (dev->rx_ampdu_ts != rxd[12]) {
+                       if (!++dev->mt76.ampdu_ref)
+                               dev->mt76.ampdu_ref++;
+               }
+               dev->rx_ampdu_ts = rxd[12];
+
+               status->ampdu_ref = dev->mt76.ampdu_ref;
+       }
+
        remove_pad = rxd1 & MT_RXD1_NORMAL_HDR_OFFSET;
 
        if (rxd2 & MT_RXD2_NORMAL_MAX_LEN_ERROR)
index 17176de..01b9335 100644 (file)
@@ -109,6 +109,7 @@ struct mt7603_dev {
        u32 false_cca_ofdm, false_cca_cck;
        unsigned long last_cca_adj;
 
+       __le32 rx_ampdu_ts;
        u8 rssi_offset[3];
 
        u8 slottime;
index 237d155..8827152 100644 (file)
@@ -93,6 +93,20 @@ int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb)
                status->flag |= RX_FLAG_MMIC_STRIPPED | RX_FLAG_MIC_STRIPPED;
        }
 
+       if (!(rxd2 & (MT_RXD2_NORMAL_NON_AMPDU_SUB |
+                     MT_RXD2_NORMAL_NON_AMPDU))) {
+               status->flag |= RX_FLAG_AMPDU_DETAILS;
+
+               /* all subframes of an A-MPDU have the same timestamp */
+               if (dev->rx_ampdu_ts != rxd[12]) {
+                       if (!++dev->mt76.ampdu_ref)
+                               dev->mt76.ampdu_ref++;
+               }
+               dev->rx_ampdu_ts = rxd[12];
+
+               status->ampdu_ref = dev->mt76.ampdu_ref;
+       }
+
        remove_pad = rxd1 & MT_RXD1_NORMAL_HDR_OFFSET;
 
        if (rxd2 & MT_RXD2_NORMAL_MAX_LEN_ERROR)
index efb8be2..fa8f2f1 100644 (file)
@@ -81,6 +81,8 @@ struct mt7615_dev {
        u32 vif_mask;
        u32 omac_mask;
 
+       __le32 rx_ampdu_ts;
+
        struct {
                u8 n_pulses;
                u32 period;
index 0d00090..9d2795c 100644 (file)
@@ -789,6 +789,21 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb,
        if ((rxinfo & MT_RXINFO_BA) && !(rxinfo & MT_RXINFO_NULL))
                status->aggr = true;
 
+       if (rxinfo & MT_RXINFO_AMPDU) {
+               status->flag |= RX_FLAG_AMPDU_DETAILS;
+               status->ampdu_ref = dev->mt76.ampdu_ref;
+
+               /*
+                * When receiving an A-MPDU subframe and RSSI info is not valid,
+                * we can assume that more subframes belonging to the same A-MPDU
+                * are coming. The last one will have valid RSSI info
+                */
+               if (!(rxinfo & MT_RXINFO_RSSI)) {
+                       if (!++dev->mt76.ampdu_ref)
+                               dev->mt76.ampdu_ref++;
+               }
+       }
+
        if (WARN_ON_ONCE(len > skb->len))
                return -EINVAL;