diff --git a/mt76.h b/mt76.h index eb72e4bf..91cc6ef7 100644 --- a/mt76.h +++ b/mt76.h @@ -252,10 +252,11 @@ struct mt76_rx_tid { #define MT_TX_CB_TXS_DONE BIT(1) #define MT_TX_CB_TXS_FAILED BIT(2) -#define MT_PACKET_ID_MASK GENMASK(7, 0) +#define MT_PACKET_ID_MASK GENMASK(6, 0) #define MT_PACKET_ID_NO_ACK 0 #define MT_PACKET_ID_NO_SKB 1 #define MT_PACKET_ID_FIRST 2 +#define MT_PACKET_ID_HAS_RATE BIT(7) #define MT_TX_STATUS_SKB_TIMEOUT HZ @@ -647,10 +648,17 @@ static inline struct mt76_tx_cb *mt76_tx_skb_cb(struct sk_buff *skb) return ((void *) IEEE80211_SKB_CB(skb)->status.status_driver_data); } +static inline bool mt76_is_skb_pktid(u8 pktid) +{ + if (pktid & MT_PACKET_ID_HAS_RATE) + return false; + + return pktid >= MT_PACKET_ID_FIRST; +} + int mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, struct sk_buff *skb, struct mt76_wcid *wcid, struct ieee80211_sta *sta); - void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb); void mt76_tx(struct mt76_dev *dev, struct ieee80211_sta *sta, struct mt76_wcid *wcid, struct sk_buff *skb); diff --git a/mt76x02_mac.c b/mt76x02_mac.c index 9ed231ab..dd050416 100644 --- a/mt76x02_mac.c +++ b/mt76x02_mac.c @@ -411,31 +411,87 @@ void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi, } EXPORT_SYMBOL_GPL(mt76x02_mac_write_txwi); +static void +mt76x02_tx_rate_fallback(struct ieee80211_tx_rate *rates, int idx, int phy) +{ + u8 mcs, nss; + + if (!idx) + return; + + rates += idx - 1; + rates[1] = rates[0]; + switch (phy) { + case MT_PHY_TYPE_VHT: + mcs = ieee80211_rate_get_vht_mcs(rates); + nss = ieee80211_rate_get_vht_nss(rates); + + if (mcs == 0) + nss = max_t(int, nss - 1, 1); + else + mcs--; + + ieee80211_rate_set_vht(rates + 1, mcs, nss); + break; + case MT_PHY_TYPE_HT_GF: + case MT_PHY_TYPE_HT: + /* MCS 8 falls back to MCS 0 */ + if (rates[0].idx == 8) { + rates[1].idx = 0; + break; + } + /* fall through */ + default: + rates[1].idx = max_t(int, rates[0].idx - 1, 0); + break; + } +} + static void mt76x02_mac_fill_tx_status(struct mt76x02_dev *dev, struct ieee80211_tx_info *info, struct mt76x02_tx_status *st, int n_frames) { struct ieee80211_tx_rate *rate = info->status.rates; - int cur_idx, last_rate; + struct ieee80211_tx_rate last_rate; + u16 first_rate; + int retry = st->retry; + int phy; int i; if (!n_frames) return; - last_rate = min_t(int, st->retry, IEEE80211_TX_MAX_RATES - 1); - mt76x02_mac_process_tx_rate(&rate[last_rate], st->rate, - dev->mt76.chandef.chan->band); - if (last_rate < IEEE80211_TX_MAX_RATES - 1) - rate[last_rate + 1].idx = -1; + phy = FIELD_GET(MT_RXWI_RATE_PHY, st->rate); - cur_idx = rate[last_rate].idx + last_rate; - for (i = 0; i <= last_rate; i++) { - rate[i].flags = rate[last_rate].flags; - rate[i].idx = max_t(int, 0, cur_idx - i); - rate[i].count = 1; + if (st->pktid & MT_PACKET_ID_HAS_RATE) { + first_rate = st->rate & ~MT_RXWI_RATE_INDEX; + first_rate |= st->pktid & MT_RXWI_RATE_INDEX; + + mt76x02_mac_process_tx_rate(&rate[0], first_rate, + dev->mt76.chandef.chan->band); + } + + mt76x02_mac_process_tx_rate(&last_rate, st->rate, + dev->mt76.chandef.chan->band); + + for (i = 0; i < ARRAY_SIZE(info->status.rates); i++) { + retry--; + if (i + 1 == ARRAY_SIZE(info->status.rates)) { + info->status.rates[i] = last_rate; + info->status.rates[i].count = max_t(int, retry, 1); + break; + } + + mt76x02_tx_rate_fallback(info->status.rates, i, phy); + if (info->status.rates[i].idx == last_rate.idx) + break; + } + + if (i + 1 < ARRAY_SIZE(info->status.rates)) { + info->status.rates[i + 1].idx = -1; + info->status.rates[i + 1].count = 0; } - rate[last_rate].count = st->retry + 1 - last_rate; info->status.ampdu_len = n_frames; info->status.ampdu_ack_len = st->success ? n_frames : 0; @@ -480,13 +536,19 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev, } if (wcid) { - if (stat->pktid >= MT_PACKET_ID_FIRST) + if (mt76_is_skb_pktid(stat->pktid)) status.skb = mt76_tx_status_skb_get(mdev, wcid, stat->pktid, &list); if (status.skb) status.info = IEEE80211_SKB_CB(status.skb); } + if (!status.skb && !(stat->pktid & MT_PACKET_ID_HAS_RATE)) { + mt76_tx_status_unlock(mdev, &list); + rcu_read_unlock(); + return; + } + if (msta && stat->aggr && !status.skb) { u32 stat_val, stat_cache; diff --git a/mt76x02_txrx.c b/mt76x02_txrx.c index 94f47248..a842e0aa 100644 --- a/mt76x02_txrx.c +++ b/mt76x02_txrx.c @@ -163,13 +163,18 @@ int mt76x02_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, mt76x02_mac_write_txwi(dev, txwi, skb, wcid, sta, skb->len); pid = mt76_tx_status_skb_add(mdev, wcid, skb); + + /* encode packet rate for no-skb packet id to fix up status reporting */ + if (pid == MT_PACKET_ID_NO_SKB) + pid = MT_PACKET_ID_HAS_RATE | (txwi->rate & MT_RXWI_RATE_INDEX); + txwi->pktid = pid; ret = mt76x02_insert_hdr_pad(skb); if (ret < 0) return ret; - if (pid >= MT_PACKET_ID_FIRST) + if (mt76_is_skb_pktid(pid)) qsel = MT_QSEL_MGMT; *tx_info = FIELD_PREP(MT_TXD_INFO_QSEL, qsel) | diff --git a/mt76x02_usb_core.c b/mt76x02_usb_core.c index 6fb52b59..b5deecd1 100644 --- a/mt76x02_usb_core.c +++ b/mt76x02_usb_core.c @@ -90,9 +90,14 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data, skb_push(skb, sizeof(struct mt76x02_txwi)); pid = mt76_tx_status_skb_add(mdev, wcid, skb); + + /* encode packet rate for no-skb packet id to fix up status reporting */ + if (pid == MT_PACKET_ID_NO_SKB) + pid = MT_PACKET_ID_HAS_RATE | (txwi->rate & MT_RXWI_RATE_INDEX); + txwi->pktid = pid; - if (pid >= MT_PACKET_ID_FIRST || q2ep(q->hw_idx) == MT_EP_OUT_HCCA) + if (mt76_is_skb_pktid(pid) || q2ep(q->hw_idx) == MT_EP_OUT_HCCA) qsel = MT_QSEL_MGMT; else qsel = MT_QSEL_EDCA;