mirror of
https://github.com/outbackdingo/mt76.git
synced 2026-10-24 13:26:48 +00:00
wifi: mt76: account non-AQL frames per peer rather than per link
wcid->non_aql_packets is charged when a frame reaches the hardware queue and credited back from the completion path. For an MLO peer the hardware reports the completion against the link it actually transmitted on, which need not be the link the frame was queued for, so the charge and the credit can land on different link wcids. The credited side is clamped at zero while the charged side keeps the residue. Once it passes MT_MAX_NON_AQL_PKT, mt76_txq_schedule_list() skips that station on every pass and its traffic stops for good, with the frames left sitting in the mac80211 queues and nothing counted as dropped. Only a reassociation, which allocates new wcids, recovers it. Keep the count on the primary link's wcid, as is already done for the other peer-wide state. Signed-off-by: Felix Fietkau <[email protected]>
This commit is contained in:
@@ -1435,6 +1435,13 @@ mtxq_to_txq(struct mt76_txq *mtxq)
|
||||
return container_of(ptr, struct ieee80211_txq, drv_priv);
|
||||
}
|
||||
|
||||
/* Peer-wide state lives on the primary link's wcid */
|
||||
static inline struct mt76_wcid *
|
||||
mt76_wcid_primary(struct mt76_wcid *wcid)
|
||||
{
|
||||
return wcid->def_wcid ? wcid->def_wcid : wcid;
|
||||
}
|
||||
|
||||
static inline struct ieee80211_sta *
|
||||
wcid_to_sta(struct mt76_wcid *wcid)
|
||||
{
|
||||
|
||||
@@ -234,6 +234,8 @@ mt76_tx_check_non_aql(struct mt76_dev *dev, struct mt76_wcid *wcid,
|
||||
if (!wcid || info->tx_time_est)
|
||||
return;
|
||||
|
||||
wcid = mt76_wcid_primary(wcid);
|
||||
|
||||
pending = atomic_dec_return(&wcid->non_aql_packets);
|
||||
if (pending < 0)
|
||||
atomic_cmpxchg(&wcid->non_aql_packets, pending, 0);
|
||||
@@ -344,7 +346,10 @@ __mt76_tx_queue_skb(struct mt76_phy *phy, int qid, struct sk_buff *skb,
|
||||
if (!non_aql)
|
||||
return idx;
|
||||
|
||||
pending = atomic_inc_return(&wcid->non_aql_packets);
|
||||
/* Completions come back on whichever link the hardware used, so
|
||||
* counting per link would leak the charge on every link switch.
|
||||
*/
|
||||
pending = atomic_inc_return(&mt76_wcid_primary(wcid)->non_aql_packets);
|
||||
if (stop && pending >= MT_MAX_NON_AQL_PKT)
|
||||
*stop = true;
|
||||
|
||||
@@ -527,7 +532,8 @@ mt76_txq_send_burst(struct mt76_phy *phy, struct mt76_queue *q,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (atomic_read(&wcid->non_aql_packets) >= MT_MAX_NON_AQL_PKT)
|
||||
if (atomic_read(&mt76_wcid_primary(wcid)->non_aql_packets) >=
|
||||
MT_MAX_NON_AQL_PKT)
|
||||
return 0;
|
||||
|
||||
skb = mt76_txq_dequeue(phy, mtxq);
|
||||
@@ -636,7 +642,8 @@ mt76_txq_schedule_list(struct mt76_phy *phy, enum mt76_txq_id qid)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (atomic_read(&wcid->non_aql_packets) >= MT_MAX_NON_AQL_PKT)
|
||||
if (atomic_read(&mt76_wcid_primary(wcid)->non_aql_packets) >=
|
||||
MT_MAX_NON_AQL_PKT)
|
||||
continue;
|
||||
if (dev->queue_ops->tx_cleanup &&
|
||||
q->queued + 2 * MT_TXQ_FREE_THR >= q->ndesc) {
|
||||
|
||||
Reference in New Issue
Block a user