mt76: add hash lookup for skb on TXS status_list
Subsystems (2)
PATCH v5 1/11 mt76: add hash lookup for skb on TXS status_list
From: Ben Greear <[email protected]>
This improves performance when sending lots of frames that are requesting being mapped to a TXS callback.
Add comments to help next person understood the tx path better.
---
v5: Rebased on top of previous series.
drivers/net/wireless/mediatek/mt76/mt76.h | 48 +++++++--- .../net/wireless/mediatek/mt76/mt7603/mac.c | 2 +- .../net/wireless/mediatek/mt76/mt7615/mac.c | 2 +- .../net/wireless/mediatek/mt76/mt76x02_mac.c | 2 +- .../net/wireless/mediatek/mt76/mt7915/mac.c | 8 +- .../net/wireless/mediatek/mt76/mt7921/mac.c | 9 +- drivers/net/wireless/mediatek/mt76/tx.c | 90 ++++++++++++++++--- 7 files changed, 132 insertions(+), 29 deletions(-)
drivers/net/wireless/mediatek/mt76/mt76.h +37 -11
@@ -235,6 +235,14 @@ DECLARE_EWMA(signal, 10, 8);#define MT_WCID_TX_INFO_TXPWR_ADJ GENMASK(25, 18)#define MT_WCID_TX_INFO_SET BIT(31) +#define MT_PACKET_ID_MASK GENMASK(6, 0) +#define MT_PACKET_ID_NO_ACK 0 +/* Request TXS, but don't try to match with skb. */ +#define MT_PACKET_ID_NO_SKB 1 +#define MT_PACKET_ID_FIRST 2 +#define MT_PACKET_ID_HAS_RATE BIT(7) +#define MT_PACKET_ID_MAX (GENMASK(7, 0) - 1) +struct mt76_wcid {struct mt76_rx_tid __rcu *aggr[IEEE80211_NUM_TIDS ];
@@ -246,6 +254,8 @@ struct mt76_wcid {struct rate_info rate; +struct sk_buff *skb_status_array[MT_PACKET_ID_MAX +1 ]; +u16 idx;u8 hw_key_idx;u8 hw_key_idx2;
@@ -302,13 +312,8 @@ 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(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 +/* This is timer for when to give up when waiting for TXS callback. */ +#define MT_TX_STATUS_SKB_TIMEOUT (HZ / 8)struct mt76_tx_cb {unsigned long jiffies;
@@ -651,6 +656,7 @@ struct mt76_dev {spinlock_t cc_lock;u32 cur_cc_bss_rx; +unsigned long next_status_jiffies;struct mt76_rx_status rx_ampdu_status;u32 rx_ampdu_len;
@@ -1090,7 +1096,7 @@ struct sk_buff *mt76_tx_status_skb_get(struct mt76_dev *dev, struct mt76_wcid *wcid, int pktid, struct sk_buff_head *list);void mt76_tx_status_skb_done (struct mt76_dev *dev,struct sk_buff *skb, -struct sk_buff_head *list); +struct sk_buff_head *list,struct mt76_wcid *wcid);void __mt76_tx_complete_skb (struct mt76_dev *dev,u16 wcid,struct sk_buff *skb,struct list_head *free_list); static inline void
@@ -1297,13 +1303,33 @@ mt76_token_put(struct mt76_dev *dev, int token) }static inline int -mt76_get_next_pkt_id (struct mt76_wcid *wcid) +mt76_get_next_pkt_id (struct mt76_dev *dev,struct mt76_wcid *wcid, +struct sk_buff *skb) { +struct sk_buff *qskb; + +lockdep_assert_held (&dev->status_list.lock); + wcid->packet_id = (wcid->packet_id +1 ) &MT_PACKET_ID_MASK ; -if (wcid->packet_id ==MT_PACKET_ID_NO_ACK || - wcid->packet_id ==MT_PACKET_ID_NO_SKB ) +if (wcid->packet_id <MT_PACKET_ID_FIRST ) wcid->packet_id =MT_PACKET_ID_FIRST ; + qskb = wcid->skb_status_array[wcid->packet_id]; +if (qskb) { +/* bummer, already waiting on this pid. See if it is stale. */ +struct mt76_tx_cb *cb =mt76_tx_skb_cb (qskb); + +if (!time_after (jiffies, cb->jiffies +MT_TX_STATUS_SKB_TIMEOUT )) { +/* ok, not stale. Increment pid anyway, will try next +* slot next time +*/ +return MT_PACKET_ID_NO_SKB ; + } + } + +/* cache this skb for fast lookup by packet-id */ + wcid->skb_status_array[wcid->packet_id] = skb; +return wcid->packet_id; }#endif
drivers/net/wireless/mediatek/mt76/mt7603/mac.c +1 -1
@@ -1230,7 +1230,7 @@ mt7603_mac_add_txs_skb(struct mt7603_dev *dev, struct mt7603_sta *sta, int pid, info->status.rates[0 ].idx =-1 ; } -mt76_tx_status_skb_done (mdev, skb, &list); +mt76_tx_status_skb_done (mdev, skb, &list, &sta->wcid); }mt76_tx_status_unlock (mdev, &list);
drivers/net/wireless/mediatek/mt76/mt7615/mac.c +1 -1
@@ -1433,7 +1433,7 @@ static bool mt7615_mac_add_txs_skb(struct mt7615_dev *dev, info->status.rates[0 ].idx =-1 ; } -mt76_tx_status_skb_done (mdev, skb, &list); +mt76_tx_status_skb_done (mdev, skb, &list, &sta->wcid); }mt76_tx_status_unlock (mdev, &list);
drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +1 -1
@@ -622,7 +622,7 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev, info = *status.info; len = status.skb->len; ac =skb_get_queue_mapping (status.skb); -mt76_tx_status_skb_done (mdev, status.skb, &list); +mt76_tx_status_skb_done (mdev, status.skb, &list, wcid); }else if (msta) { len = status.info->status.ampdu_len *ewma_pktlen_read (&msta->pktlen); ac =FIELD_GET (MT_PKTID_AC , cur_pktid);
drivers/net/wireless/mediatek/mt76/mt7915/mac.c +7 -1
@@ -1318,6 +1318,8 @@ mt7915_mac_add_txs_skb(struct mt7915_dev *dev, struct mt76_wcid *wcid, int pid,mt76_tx_status_lock (mdev, &list); skb =mt76_tx_status_skb_get (mdev, wcid, pid, &list); + +/* TODO: Gather stats anyway, even if we are not matching on an skb. */ if (!skb) goto out;
@@ -1417,10 +1419,14 @@ mt7915_mac_add_txs_skb(struct mt7915_dev *dev, struct mt76_wcid *wcid, int pid, stats->tx_bw[0 ]++;break ; } + +/* Cache rate for packets that don't get a TXS callback for some +* reason. +*/ wcid->rate = rate; out: -mt76_tx_status_skb_done (mdev, skb, &list); +mt76_tx_status_skb_done (mdev, skb, &list, wcid);mt76_tx_status_unlock (mdev, &list);return !!skb;
drivers/net/wireless/mediatek/mt76/mt7921/mac.c +5 -4
@@ -732,7 +732,9 @@ mt7921_mac_write_txwi_80211(struct mt7921_dev *dev, __le32 *txwi, txwi[7 ] |=cpu_to_le32 (val); } -static void mt7921_update_txs (struct mt76_wcid *wcid,__le32 *txwi) +static void mt7921_update_txs (struct mt7921_dev *dev, +struct mt76_wcid *wcid,__le32 *txwi, +struct sk_buff *skb) { struct mt7921_sta *msta = container_of(wcid, struct mt7921_sta, wcid);u32 pid, frame_type =FIELD_GET (MT_TXD2_FRAME_TYPE , txwi[2 ]);
@@ -744,7 +746,7 @@ static void mt7921_update_txs(struct mt76_wcid *wcid, __le32 *txwi)return ; msta->next_txs_ts = jiffies +msecs_to_jiffies (250 ); - pid =mt76_get_next_pkt_id (wcid); + pid =mt76_get_next_pkt_id (&dev->mt76, wcid, skb); txwi[5 ] |=cpu_to_le32 (MT_TXD5_TX_STATUS_MCU |FIELD_PREP (MT_TXD5_PID , pid)); }
@@ -771,7 +773,6 @@ void mt7921_mac_write_txwi(struct mt7921_dev *dev, __le32 *txwi, {struct ieee80211_tx_info *info =IEEE80211_SKB_CB (skb);struct ieee80211_vif *vif = info->control.vif; -struct mt76_phy *mphy = &dev->mphy;u8 p_fmt, q_idx, omac_idx =0 , wmm_idx =0 ;bool is_8023 = info->flags &IEEE80211_TX_CTL_HW_80211_ENCAP ;u16 tx_count =15 ;
@@ -839,7 +840,7 @@ void mt7921_mac_write_txwi(struct mt7921_dev *dev, __le32 *txwi, txwi[3 ] |=cpu_to_le32 (MT_TXD3_BA_DISABLE ); } -mt7921_update_txs (wcid, txwi); +mt7921_update_txs (dev, wcid, txwi, skb); } static void
drivers/net/wireless/mediatek/mt76/tx.c +80 -10
174 lines not on this page · raw message
Signature · 1 line
2.20.1
PATCH v5 2/11 mt76: mt7915: fix potential NPE in TXS processing
From: Ben Greear <[email protected]>
If skb is null, then don't try to dereference it.
--- drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/net/wireless/mediatek/mt76/mt7915/mac.c +3 -1
@@ -1321,7 +1321,7 @@ mt7915_mac_add_txs_skb(struct mt7915_dev *dev, struct mt76_wcid *wcid, int pid,/* TODO: Gather stats anyway, even if we are not matching on an skb. */ if (!skb) - goto out; + goto out_no_skb; txs =le32_to_cpu (txs_data[0 ]);
@@ -1427,6 +1427,8 @@ mt7915_mac_add_txs_skb(struct mt7915_dev *dev, struct mt76_wcid *wcid, int pid, out:mt76_tx_status_skb_done (mdev, skb, &list, wcid); + +out_no_skb:mt76_tx_status_unlock (mdev, &list);return !!skb;
Signature · 1 line
2.20.1
PATCH v5 3/11 mt76: mt7915: move TXS parsing to its own method
In reply to [email protected]From: Ben Greear <[email protected]>
This will allow us to also parse TXS when we have no skb on the status callback list in future patches.
Explicitly cache short_gi and he_gi in wcid, don't try to store it in the wcid.rate object. Slightly less confusing and less fragile when TXS starts parsing lots of frames.
--- drivers/net/wireless/mediatek/mt76/mt76.h | 5 + .../net/wireless/mediatek/mt76/mt7915/mac.c | 122 ++++++++++-------- 2 files changed, 74 insertions(+), 53 deletions(-)
drivers/net/wireless/mediatek/mt76/mt76.h +5 -0
@@ -252,7 +252,12 @@ struct mt76_wcid {struct ewma_signal rssi;int inactive_count; +/* cached rate, updated from mac_sta_poll() and from TXS callback logic, in 7915 +* at least. +*/ struct rate_info rate; +bool rate_short_gi;/* cached HT/VHT short_gi, from mac_sta_poll() */ +u8 rate_he_gi;/* cached HE GI, from mac_sta_poll() */ struct sk_buff *skb_status_array[MT_PACKET_ID_MAX +1 ];
drivers/net/wireless/mediatek/mt76/mt7915/mac.c +69 -53
202 lines not on this page · raw message
Signature · 1 line
2.20.1
PATCH v5 4/11 mt76: mt7915: allow processing TXS for 'NO_SKB' pkt-ids
In reply to [email protected]From: Ben Greear <[email protected]>
This will let us update stats and wcid.rate for every TXS callback we receive for a particular wcid.
For now, the TXS is not requested for NO_SKB frames, however. That will be allowed in next patch.
--- .../net/wireless/mediatek/mt76/mt7915/mac.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7915/mac.c +13 -5
@@ -1047,6 +1047,7 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi, txwi[4 ] =0 ; val =FIELD_PREP (MT_TXD5_PID , pid); +/* NOTE: mt7916 does NOT request TXS for 'NO_SKB' frames by default. */ if (pid >=MT_PACKET_ID_FIRST ) val |=MT_TXD5_TX_STATUS_HOST ; txwi[5 ] =cpu_to_le32 (val);
@@ -1430,10 +1431,16 @@ mt7915_mac_add_txs_skb(struct mt7915_dev *dev, struct mt76_wcid *wcid, int pid,* paired with TXS data. This is normal datapath. */ struct rate_info *rate = &wcid->rate; -struct sk_buff *skb; +struct sk_buff *skb =NULL ; +bool check_status; -mt76_tx_status_lock (mdev, &list); - skb =mt76_tx_status_skb_get (mdev, wcid, pid, &list); + check_status = ((pid >=MT_PACKET_ID_FIRST ) || +time_after (jiffies, mdev->next_status_jiffies)); + +if (check_status) { +mt76_tx_status_lock (mdev, &list); + skb =mt76_tx_status_skb_get (mdev, wcid, pid, &list); + }memset (rate,0 ,sizeof (*rate));
@@ -1447,7 +1454,8 @@ mt7915_mac_add_txs_skb(struct mt7915_dev *dev, struct mt76_wcid *wcid, int pid,if (skb)mt76_tx_status_skb_done (mdev, skb, &list, wcid); -mt76_tx_status_unlock (mdev, &list); +if (check_status) +mt76_tx_status_unlock (mdev, &list); }static void mt7915_mac_add_txs (struct mt7915_dev *dev,void *data)
@@ -1469,7 +1477,7 @@ static void mt7915_mac_add_txs(struct mt7915_dev *dev, void *data) txs =le32_to_cpu (txs_data[3 ]); pid =FIELD_GET (MT_TXS3_PID , txs); -if (pid <MT_PACKET_ID_FIRST ) +if (pid <MT_PACKET_ID_NO_SKB )return ;if (wcidx >=MT7915_WTBL_SIZE )
Signature · 1 line
2.20.1
Felix Fietkau
maintainerRe: [PATCH v5 04/11] mt76: mt7915: allow processing TXS for 'NO_SKB' pkt-ids
Quoted 18 lines · On 2021-08-04 15:44, [email protected] wrote:
From: Ben Greear <[email protected]>
This will let us update stats and wcid.rate for every TXS callback we receive for a particular wcid.
For now, the TXS is not requested for
NO_SKBframes, however. That will be allowed in next patch.Signed-off-by Ben Greear <[email protected]>--- .../net/wireless/mediatek/mt76/mt7915/mac.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-)drivers/net/wireless/mediatek/mt76/mt7915/mac.c +0
-0
drivers/net/wireless/mediatek/mt76/mt7915/mac.c void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi, · line 1050
Quoted 4 lines
drivers/net/wireless/mediatek/mt76/mt7915/mac.c +1
-0@@ -1047,6 +1047,7 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi, txwi[4 ] =0 ; val =FIELD_PREP (MT_TXD5_PID , pid); +/* NOTE: mt7916 does NOT request TXS for 'NO_SKB' frames by default. */
I think this comment can be dropped, given that you're adding extra checks in the next patch that clarify this.
drivers/net/wireless/mediatek/mt76/mt7915/mac.c void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi, · line 1053
Quoted 3 lines
drivers/net/wireless/mediatek/mt76/mt7915/mac.c +0
-0if (pid >=MT_PACKET_ID_FIRST ) val |=MT_TXD5_TX_STATUS_HOST ; txwi[5 ] =cpu_to_le32 (val);
- Felix
PATCH v5 5/11 mt76: mt7915: debugfs hook to enable TXS for NO_SKB pkt-ids
In reply to [email protected]From: Ben Greear <[email protected]>
This lets user turn on/off this feature. Enabling gives better tx-rate related stats, but will cause extra driver and (maybe) firmware work. Not sure if it actually affects performance or not.
--- .../wireless/mediatek/mt76/mt7915/debugfs.c | 24 +++++++++++++++++++ .../net/wireless/mediatek/mt76/mt7915/mac.c | 3 ++- .../wireless/mediatek/mt76/mt7915/mt7915.h | 5 ++++ 3 files changed, 31 insertions(+), 1 deletion(-)
drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c +24 -0
@@ -109,6 +109,29 @@ mt7915_fw_debug_get(void *data, u64 *val)DEFINE_DEBUGFS_ATTRIBUTE (fops_fw_debug, mt7915_fw_debug_get, mt7915_fw_debug_set,"%lld\n" ); +static int +mt7915_txs_for_no_skb_set (void *data,u64 val) +{ +struct mt7915_dev *dev = data; + + dev->txs_for_no_skb_enabled = !!val; + +return 0 ; +} + +static int +mt7915_txs_for_no_skb_get (void *data,u64 *val) +{ +struct mt7915_dev *dev = data; + + *val = dev->txs_for_no_skb_enabled; + +return 0 ; +} + +DEFINE_DEBUGFS_ATTRIBUTE (fops_txs_for_no_skb, mt7915_txs_for_no_skb_get, + mt7915_txs_for_no_skb_set,"%lld\n" ); +static void mt7915_ampdu_stat_read_phy (struct mt7915_phy *phy,struct seq_file *file)
@@ -344,6 +367,7 @@ int mt7915_init_debugfs(struct mt7915_dev *dev) mt7915_queues_acq);debugfs_create_file ("tx_stats" ,0400 , dir, dev, &mt7915_tx_stats_fops);debugfs_create_file ("fw_debug" ,0600 , dir, dev, &fops_fw_debug); +debugfs_create_file ("txs_for_no_skb" ,0600 , dir, dev, &fops_txs_for_no_skb);debugfs_create_file ("implicit_txbf" ,0600 , dir, dev, &fops_implicit_txbf);debugfs_create_u32 ("dfs_hw_pattern" ,0400 , dir, &dev->hw_pattern);
drivers/net/wireless/mediatek/mt76/mt7915/mac.c +2 -1
@@ -1048,7 +1048,8 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi, val =FIELD_PREP (MT_TXD5_PID , pid);/* NOTE: mt7916 does NOT request TXS for 'NO_SKB' frames by default. */ -if (pid >=MT_PACKET_ID_FIRST ) +if (pid >=MT_PACKET_ID_FIRST || + (pid ==MT_PACKET_ID_NO_SKB && dev->txs_for_no_skb_enabled)) val |=MT_TXD5_TX_STATUS_HOST ; txwi[5 ] =cpu_to_le32 (val);
drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +5 -0
@@ -223,6 +223,11 @@ struct mt7915_dev {u16 chainmask;u32 hif_idx; +/* Should we request TXS for MT_PACKET_ID_NO_SKB? Doing so gives better +* costs but causes a great deal more TXS packet processing by driver and +* creation by firmware, so may be a performance drag. +*/ +bool txs_for_no_skb_enabled;struct work_struct init_work;struct work_struct rc_work;
Signature · 1 line
2.20.1
Felix Fietkau
maintainerRe: [PATCH v5 05/11] mt76: mt7915: debugfs hook to enable TXS for NO_SKB pkt-ids
Quoted 19 lines · On 2021-08-04 15:44, [email protected] wrote:
From: Ben Greear <[email protected]>
This lets user turn on/off this feature. Enabling gives better tx-rate related stats, but will cause extra driver and (maybe) firmware work. Not sure if it actually affects performance or not.
Signed-off-by Ben Greear <[email protected]>--- .../wireless/mediatek/mt76/mt7915/debugfs.c | 24 +++++++++++++++++++ .../net/wireless/mediatek/mt76/mt7915/mac.c | 3 ++- .../wireless/mediatek/mt76/mt7915/mt7915.h | 5 ++++ 3 files changed, 31 insertions(+), 1 deletion(-)drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c +0
-0
drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c int mt7915_init_debugfs(struct mt7915_dev *dev) · line 370
Quoted 4 lines
drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c +1
-0@@ -344,6 +367,7 @@ int mt7915_init_debugfs(struct mt7915_dev *dev) mt7915_queues_acq);debugfs_create_file ("tx_stats" ,0400 , dir, dev, &mt7915_tx_stats_fops);debugfs_create_file ("fw_debug" ,0600 , dir, dev, &fops_fw_debug); +debugfs_create_file ("txs_for_no_skb" ,0600 , dir, dev, &fops_txs_for_no_skb);
I think this is a rather confusing name. Maybe "force_txs"?
- Felix
-
Re: [PATCH v5 05/11] mt76: mt7915: debugfs hook to enable TXS for NO_SKB pkt-ids
In reply to [email protected]Quoted 8 lines · [email protected] writes:
From: Ben Greear <[email protected]>
This lets user turn on/off this feature. Enabling gives better tx-rate related stats, but will cause extra driver and (maybe) firmware work. Not sure if it actually affects performance or not.
Signed-off-by Ben Greear <[email protected]>
This is grey area, debugfs is not really meant to be used for users enabling driver features.
Signature · 3 lines
https://patchwork.kernel.org/project/linux-wireless/list/ https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
Re: [PATCH v5 05/11] mt76: mt7915: debugfs hook to enable TXS for NO_SKB pkt-ids
Quoted 9 lines · Kalle Valo
Quoted 7 lines · [email protected] writes:
From: Ben Greear <[email protected]>
This lets user turn on/off this feature. Enabling gives better tx-rate related stats, but will cause extra driver and (maybe) firmware work. Not sure if it actually affects performance or not.
Quoted 5 lines
Quoted 1 line
Signed-off-by Ben Greear <[email protected]>This is grey area, debugfs is not really meant to be used for users enabling driver features.
What method do you suggest? Surely not trying to drive something down through netlink for something this chipset specific?
Thanks,
Ben
Signature · 2 lines
Ben Greear <[email protected]> Candela Technologies Inc http://www.candelatech.com
Re: [PATCH v5 05/11] mt76: mt7915: debugfs hook to enable TXS for NO_SKB pkt-ids
Quoted 10 lines · Ben Greear
Quoted 9 lines · Kalle Valo
Quoted 7 lines · [email protected] writes:
From: Ben Greear <[email protected]>
This lets user turn on/off this feature. Enabling gives better tx-rate related stats, but will cause extra driver and (maybe) firmware work. Not sure if it actually affects performance or not.
Quoted 8 lines
Quoted 5 lines
Quoted 1 line
Signed-off-by Ben Greear <[email protected]>This is grey area, debugfs is not really meant to be used for users enabling driver features.
What method do you suggest? Surely not trying to drive something down through netlink for something this chipset specific?
I think a module parameter would be a good choise for enabling this kind of feature.
Of course the downside of a module parater is that when it's not possible to configure this per device, only per driver. Like discussed many times in the past, we would really need some kind more advanced module parameters which can be per device.
Signature · 3 lines
https://patchwork.kernel.org/project/linux-wireless/list/ https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
Re: [PATCH v5 05/11] mt76: mt7915: debugfs hook to enable TXS for NO_SKB pkt-ids
Quoted 21 lines · Kalle Valo
Quoted 10 lines · Ben Greear
Quoted 9 lines · Kalle Valo
Quoted 7 lines · [email protected] writes:
From: Ben Greear <[email protected]>
This lets user turn on/off this feature. Enabling gives better tx-rate related stats, but will cause extra driver and (maybe) firmware work. Not sure if it actually affects performance or not.
Quoted 8 lines
Quoted 5 lines
Quoted 1 line
Signed-off-by Ben Greear <[email protected]>This is grey area, debugfs is not really meant to be used for users enabling driver features.
What method do you suggest? Surely not trying to drive something down through netlink for something this chipset specific?
Quoted 7 lines
I think a module parameter would be a good choise for enabling this kind of feature.
Of course the downside of a module parater is that when it's not possible to configure this per device, only per driver. Like discussed many times in the past, we would really need some kind more advanced module parameters which can be per device.
Enabling/disabling via debugfs is way more useful than a module parameter. It is per-device and also changeable at run-time. Maybe you want to enable detailed stats for a bit of time for some reason, and then go back to lower overhead approach.
You are asking for a worse technical solution than debugfs implementation.
For the per-device module parameters, I implemented something similar for ath10k using a 'fwcfg' file that is loaded with device options sort of like a board file. That worked well enough for that sort of thing.
Thanks,
Ben
Signature · 2 lines
Ben Greear <[email protected]> Candela Technologies Inc http://www.candelatech.com
PATCH v5 6/11 mt76: mt7915: add note about TXSFM 0x2
In reply to [email protected]From: Ben Greear <[email protected]>
This format is not supported by any current hardware, add note to mention this.
--- drivers/net/wireless/mediatek/mt76/mt7915/mac.h | 4 ++++ 1 file changed, 4 insertions(+)
drivers/net/wireless/mediatek/mt76/mt7915/mac.h +4 -0
@@ -347,6 +347,10 @@ struct mt7915_tx_free {#define MT_TXS4_TIMESTAMP GENMASK(31, 0) +/* The F0 variables are for TXSFM 0x0 and 0x1. The F1 variables +* are for TXSFM 0x2 aka PPDU format. TXSFM 0x2 not supported +* at this time. +*/ #define MT_TXS5_F0_FINAL_MPDU BIT(31)#define MT_TXS5_F0_QOS BIT(30)#define MT_TXS5_F0_TX_COUNT GENMASK(29, 25)
Signature · 1 line
2.20.1
PATCH v5 7/11 mt76: mt7915: add support for tx-overrides
In reply to [email protected]From: Ben Greear <[email protected]>
Allow setting fix rate on transmit without using full testmode logic.
txpower, dynbw, retry count is not currently supported. And, probably later need additional logic to not apply this txo to non-data frames and to smaller frames, to allow ARP and such to go through while also forcing test data frames to arbitrary tx-rates (rates which very well may not be received by peer.)
--- drivers/net/wireless/mediatek/mt76/mt76.h | 4 + .../wireless/mediatek/mt76/mt7915/debugfs.c | 224 ++++++++++++++++++ .../net/wireless/mediatek/mt76/mt7915/mac.c | 98 ++++++-- .../wireless/mediatek/mt76/mt7915/mt7915.h | 2 + 4 files changed, 302 insertions(+), 26 deletions(-)
drivers/net/wireless/mediatek/mt76/mt76.h +4 -0
@@ -566,6 +566,7 @@ struct mt76_testmode_ops {struct mt76_testmode_data {enum mt76_testmode_state state; +u8 txo_active;/* tx overrides are active */ u32 param_set[DIV_ROUND_UP (NUM_MT76_TM_ATTRS ,32 )];struct sk_buff *tx_skb;
@@ -580,6 +581,9 @@ struct mt76_testmode_data {u8 tx_rate_ldpc;u8 tx_rate_stbc;u8 tx_ltf; +u8 txbw;/* specify TX bandwidth: 0 20Mhz, 1 40Mhz, 2 80Mhz, 3 160Mhz */ +u8 tx_xmit_count;/* 0 means no-ack, 1 means one transmit, etc */ +u8 tx_dynbw;/* 0: dynamic bw disabled, 1: dynamic bw enabled */ u8 tx_antenna_mask;u8 tx_spe_idx;
drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c +224 -0
236 lines not on this page · raw message
drivers/net/wireless/mediatek/mt76/mt7915/mac.c +72 -26
142 lines not on this page · raw message
drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +2 -0
@@ -92,6 +92,8 @@ struct mt7915_sta {struct mt7915_sta_stats stats;struct mt7915_sta_key_conf bip; + +struct mt76_testmode_data test; };struct mt7915_vif {
Signature · 1 line
2.20.1
Re: [PATCH v5 07/11] mt76: mt7915: add support for tx-overrides
Quoted 4 lines · [email protected] writes:
From: Ben Greear <[email protected]>
Allow setting fix rate on transmit without using full testmode logic.
Why?
Quoted 6 lines
txpower, dynbw, retry count is not currently supported. And, probably later need additional logic to not apply this txo to non-data frames and to smaller frames, to allow ARP and such to go through while also forcing test data frames to arbitrary tx-rates (rates which very well may not be received by peer.)
Please include an example how to use the debugfs file.
IIRC there was a similar rtw88 patch adding a debugfs to force setting the tx rate. So what's the consensus, are we going to allow each driver have their own custom interfaces setting tx rates? In my opinion this should go via a generic nl80211 command, but if people think having custom tx rate interfaces is ok I guess I need to reconsider.
As this patch needs more discussion, please separate it from rest of the series so that it can be applied separately.
Signature · 3 lines
https://patchwork.kernel.org/project/linux-wireless/list/ https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
Re: [PATCH v5 07/11] mt76: mt7915: add support for tx-overrides
Quoted 8 lines · Kalle Valo
Quoted 4 lines · [email protected] writes:
From: Ben Greear <[email protected]>
Allow setting fix rate on transmit without using full testmode logic.
Why?
I use it for testing purposes, so I can send specific frame encodings to see if peer can receive it or not (receiver sensitivity testing).
Others may be interested in similar API to test that their system transmits specific MCS frames at proper txpower or other regulatory-related stuff.
And to some degree, the underlying logic gives clever people a way to do driver-defined per-skb rate-control instead of depending on the firmware. I hacked similar thing into my ath10k and at least one person attempted that as I recall.
Quoted 9 lines
Quoted 7 lines
txpower, dynbw, retry count is not currently supported. And, probably later need additional logic to not apply this txo to non-data frames and to smaller frames, to allow ARP and such to go through while also forcing test data frames to arbitrary tx-rates (rates which very well may not be received by peer.)
Please include an example how to use the debugfs file.
It is in the patch:
+ const char buf[] =
+ "This allows specify specif tx rate parameters for all DATA"
+ " frames on a vdev\n"
+ "To set a value, you specify the dev-name and key-value pairs:\n"
+ "tpc=10 sgi=1 mcs=x nss=x pream=x retries=x dynbw=0|1 bw=x enable=0|1\n"
+ "pream: 0=cck, 1=ofdm, 2=HT, 3=VHT, 4=HE_SU\n"
+ "cck-mcs: 0=1Mbps, 1=2Mbps, 3=5.5Mbps, 3=11Mbps\n"
+ "ofdm-mcs: 0=6Mbps, 1=9Mbps, 2=12Mbps, 3=18Mbps, 4=24Mbps, 5=36Mbps,"
+ " 6=48Mbps, 7=54Mbps\n"
+ "tpc is not implemented currently, bw is 0-3 for 20-160\n"
+ " For example, wlan0:\n"
+ "echo \"wlan0 tpc=255 sgi=1 mcs=0 nss=1 pream=3 retries=1 dynbw=0 bw=0"
+ " active=1\" > ...mt76/set_rate_override\n";
Quoted 9 lines
IIRC there was a similar rtw88 patch adding a debugfs to force setting the tx rate. So what's the consensus, are we going to allow each driver have their own custom interfaces setting tx rates? In my opinion this should go via a generic nl80211 command, but if people think having custom tx rate interfaces is ok I guess I need to reconsider.
As this patch needs more discussion, please separate it from rest of the series so that it can be applied separately.
Ok, will do.
Thanks,
Ben
Signature · 2 lines
Ben Greear <[email protected]> Candela Technologies Inc http://www.candelatech.com
PATCH v5 8/11 mt76: mt7915: fix SGI reporting when using tx-overrides
In reply to [email protected]From: Ben Greear <[email protected]>
The station wtbl logic to read rate-ctrl settings does not work when fixed rates are used. So, read sgi settings from the txo configuration in this case.
--- drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 9 +++++++++ 1 file changed, 9 insertions(+)
drivers/net/wireless/mediatek/mt76/mt7915/mac.c +9 -0
@@ -176,6 +176,15 @@ static void mt7915_mac_sta_poll(struct mt7915_dev *dev) rx_cur); } +/* If we are in tx-override mode, then wtbl doesn't provide useful report +* for the SGI/LGI stuff, so just get it from the override struct. +*/ +if (msta->test.txo_active) { + msta->wcid.rate_he_gi = msta->test.tx_rate_sgi; + msta->wcid.rate_short_gi = msta->test.tx_rate_sgi; +continue ; + } +/* * We don't support reading GI info from txs packets. * For accurate tx status reporting and AQL improvement,
Signature · 1 line
2.20.1
PATCH v5 9/11 mt76: mt7915: txfree status to show txcount instead of latency
In reply to [email protected]From: Ben Greear <[email protected]>
Latency is not obviously that useful, but txcount can let us deduce retries, which may be more interesting.
--- drivers/net/wireless/mediatek/mt76/mt7915/init.c | 3 +++ drivers/net/wireless/mediatek/mt76/mt7915/mac.h | 8 +++++--- drivers/net/wireless/mediatek/mt76/mt7915/regs.h | 4 ++++ 3 files changed, 12 insertions(+), 3 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7915/init.c +3 -0
@@ -304,6 +304,9 @@ static void mt7915_mac_init(struct mt7915_dev *dev)/* enable hardware de-agg */ mt76_set (dev,MT_MDP_DCR0 ,MT_MDP_DCR0_DAMSDU_EN ); +/* disable Tx latency report to enable Tx count in txfree path */ +mt76_clear (dev,MT_PLE_HOST_RPT0 ,MT_PLE_HOST_RPT0_TX_LATENCY ); +for (i =0 ; i <MT7915_WTBL_SIZE ; i++)mt7915_mac_wtbl_update (dev, i,MT_WTBL_UPDATE_ADM_COUNT_CLEAR );
drivers/net/wireless/mediatek/mt76/mt7915/mac.h +5 -3
@@ -304,13 +304,15 @@ struct mt7915_tx_free {#define MT_TX_FREE_MSDU_CNT GENMASK(9, 0)#define MT_TX_FREE_WLAN_ID GENMASK(23, 14) +/* when configured for txfree latency mode. See MT_PLE_HOST_RPT0_TX_LATENCY +* Not enabled by default now. +*/ #define MT_TX_FREE_LATENCY GENMASK(12, 0) -/* 0: success, others: dropped */ +/* when configured for txcount mode. See MT_PLE_HOST_RPT0_TX_LATENCY. */ +#define MT_TX_FREE_TXCNT GENMASK(12, 0)#define MT_TX_FREE_STATUS GENMASK(14, 13)#define MT_TX_FREE_MSDU_ID GENMASK(30, 16)#define MT_TX_FREE_PAIR BIT(31) -/* will support this field in further revision */ -#define MT_TX_FREE_RATE GENMASK(13, 0)#define MT_TXS0_FIXED_RATE BIT(31)#define MT_TXS0_BW GENMASK(30, 29)
drivers/net/wireless/mediatek/mt76/mt7915/regs.h +4 -0
@@ -22,6 +22,10 @@#define MT_PLE_BASE 0x8000#define MT_PLE (ofs) (MT_PLE_BASE + (ofs)) +/* Modify whether txfree struct returns latency or txcount. */ +#define MT_PLE_HOST_RPT0 MT_PLE(0x030) +#define MT_PLE_HOST_RPT0_TX_LATENCY BIT(3) +#define MT_PLE_FL_Q0_CTRL MT_PLE(0x1b0)#define MT_PLE_FL_Q1_CTRL MT_PLE(0x1b4)#define MT_PLE_FL_Q2_CTRL MT_PLE(0x1b8)
Signature · 1 line
2.20.1
PATCH v5 10/11 mt76: mt7915: report tx-retries
In reply to [email protected]From: Ben Greear <[email protected]>
mac80211 stack will only report tx-status for skb claiming to be ampdu heads, so lie a bit in mt7915 and set the flag so that mac80211 will record status for each skb.
mt7915 appears to report retry status on an individual per-skb manner, so that method above seems to work.
Re-constitute the txinfo status rate info so that the rix and flags is also at least close to correct. No direct way to report HE rates that way, so mac80211 might could use some tweaking in the ieee80211_tx_status_ext to take both info and status->rate into account.
--- .../net/wireless/mediatek/mt76/mt7915/init.c | 1 + .../net/wireless/mediatek/mt76/mt7915/mac.c | 93 ++++++++++++++++++- .../net/wireless/mediatek/mt76/mt7915/mac.h | 4 +- .../net/wireless/mediatek/mt76/mt7915/main.c | 8 ++ .../wireless/mediatek/mt76/mt7915/mt7915.h | 4 + drivers/net/wireless/mediatek/mt76/tx.c | 6 +- 6 files changed, 109 insertions(+), 7 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7915/init.c +1 -0
@@ -217,6 +217,7 @@ mt7915_init_wiphy(struct ieee80211_hw *hw)struct wiphy *wiphy = hw->wiphy; hw->queues =4 ; + hw->max_report_rates =1 ; hw->max_rx_aggregation_subframes =IEEE80211_MAX_AMPDU_BUF ; hw->max_tx_aggregation_subframes =IEEE80211_MAX_AMPDU_BUF ; hw->netdev_features =NETIF_F_RXCSUM ;
drivers/net/wireless/mediatek/mt76/mt7915/mac.c +88 -5
141 lines not on this page · raw message
drivers/net/wireless/mediatek/mt76/mt7915/mac.h +3 -1
@@ -299,7 +299,7 @@ struct mt7915_tx_free {__le16 ctrl;u8 txd_cnt;u8 rsv[3 ]; -__le32 info[]; +__le32 info[];/* DW3+ */ } __packed__aligned(4) ;#define MT_TX_FREE_MSDU_CNT GENMASK(9, 0)
@@ -311,6 +311,8 @@ struct mt7915_tx_free {/* when configured for txcount mode. See MT_PLE_HOST_RPT0_TX_LATENCY. */ #define MT_TX_FREE_TXCNT GENMASK(12, 0)#define MT_TX_FREE_STATUS GENMASK(14, 13) +/* 0: not MPDU, 1: MSDU is head pkt of TXD page (MPDU) */ +#define MT_TX_FREE_HEAD_OF_PAGE BIT(15)#define MT_TX_FREE_MSDU_ID GENMASK(30, 16)#define MT_TX_FREE_PAIR BIT(31)
drivers/net/wireless/mediatek/mt76/mt7915/main.c +8 -0
@@ -1093,6 +1093,10 @@ static const char mt7915_gstrings_stats[][ETH_GSTRING_LEN] = {"rx_ba_cnt" ,/* per vif counters */ +"v_tx_mpdu_attempts" ,/* counting any retries */ +"v_tx_mpdu_fail" ,/* frames that failed even after retry */ +"v_tx_mpdu_retry" ,/* number of times frames were retried */ +"v_tx_mpdu_ok" ,/* frames that succeeded, perhaps after retry */ "v_tx_mode_cck" ,"v_tx_mode_ofdm" , "v_tx_mode_ht",
@@ -1165,6 +1169,10 @@ static void mt7915_ethtool_worker(void *wi_data, struct ieee80211_sta *sta) wi->sta_count++; + data[ei++] += mstats->tx_mpdu_attempts; + data[ei++] += mstats->tx_mpdu_fail; + data[ei++] += mstats->tx_mpdu_retry; + data[ei++] += mstats->tx_mpdu_ok; data[ei++] += mstats->tx_mode[MT_PHY_TYPE_CCK ]; data[ei++] += mstats->tx_mode[MT_PHY_TYPE_OFDM ]; data[ei++] += mstats->tx_mode[MT_PHY_TYPE_HT ];
drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +4 -0
@@ -65,6 +65,10 @@ enum mt7915_rxq_id { };struct mt7915_sta_stats { +unsigned long tx_mpdu_attempts;/* counting any retries */ +unsigned long tx_mpdu_fail;/* frames that failed even after retry */ +unsigned long tx_mpdu_ok;/* frames that succeeded, perhaps after retry */ +unsigned long tx_mpdu_retry;/* number of times frames were retried */ unsigned long tx_mode[MT_PHY_TYPE_HE_LAST ];/* See mt76_phy_type */ unsigned long tx_bw[4 ];/* 20, 40, 80, 160 */ unsigned long tx_nss[4 ];/* 1, 2, 3, 4 */
drivers/net/wireless/mediatek/mt76/tx.c +5 -1
@@ -274,6 +274,7 @@ void __mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid_idx, struct sk_buff *struct ieee80211_tx_status status = { .skb = skb, .free_list = free_list, + .info =IEEE80211_SKB_CB (skb), };struct mt76_wcid *wcid =NULL ;struct ieee80211_hw *hw;
@@ -281,8 +282,11 @@ void __mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid_idx, struct sk_buff *rcu_read_lock (); -if (wcid_idx <ARRAY_SIZE (dev->wcid)) +if (wcid_idx <ARRAY_SIZE (dev->wcid)) { wcid =rcu_dereference (dev->wcid[wcid_idx]); +if (wcid) + status.rate = &wcid->rate; + }mt76_tx_check_non_aql (dev, wcid, skb);
Signature · 1 line
2.20.1
PATCH v5 11/11 mt76: mt7915: add a missing HT flag for GI parsing
In reply to [email protected]From: Ryder Lee <[email protected]>
The previous commit missed a HT flag.
--- drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7915/mac.c +2 -2
@@ -215,7 +215,8 @@ static void mt7915_mac_sta_poll(struct mt7915_dev *dev) rate->he_gi = (val & (0x3 << offs)) >> offs; msta->wcid.rate_he_gi = rate->he_gi;/* cache for later */ - }else if (rate->flags &RATE_INFO_FLAGS_VHT_MCS ) { + }else if (rate->flags & + (RATE_INFO_FLAGS_VHT_MCS |RATE_INFO_FLAGS_MCS )) {if (val &BIT (12 + bw)) { rate->flags |=RATE_INFO_FLAGS_SHORT_GI ; msta->wcid.rate_short_gi =1 ;
@@ -224,7 +225,6 @@ static void mt7915_mac_sta_poll(struct mt7915_dev *dev) msta->wcid.rate_short_gi =0 ; } } -/* TODO: Deal with HT_MCS */ }rcu_read_unlock ();
Signature · 1 line
2.20.1
Felix Fietkau
maintainerQuoted 42 lines · On 2021-08-04 15:44, [email protected] wrote:
From: Ben Greear <[email protected]>
This improves performance when sending lots of frames that are requesting being mapped to a TXS callback.
Add comments to help next person understood the tx path better.
Signed-off-by Ben Greear <[email protected]>---
v5: Rebased on top of previous series.
drivers/net/wireless/mediatek/mt76/mt76.h | 48 +++++++--- .../net/wireless/mediatek/mt76/mt7603/mac.c | 2 +- .../net/wireless/mediatek/mt76/mt7615/mac.c | 2 +- .../net/wireless/mediatek/mt76/mt76x02_mac.c | 2 +- .../net/wireless/mediatek/mt76/mt7915/mac.c | 8 +- .../net/wireless/mediatek/mt76/mt7921/mac.c | 9 +- drivers/net/wireless/mediatek/mt76/tx.c | 90 ++++++++++++++++--- 7 files changed, 132 insertions(+), 29 deletions(-)drivers/net/wireless/mediatek/mt76/mt76.h +8
-0@@ -235,6 +235,14 @@ DECLARE_EWMA(signal, 10, 8);#define MT_WCID_TX_INFO_TXPWR_ADJ GENMASK(25, 18)#define MT_WCID_TX_INFO_SET BIT(31) +#define MT_PACKET_ID_MASK GENMASK(6, 0) +#define MT_PACKET_ID_NO_ACK 0 +/* Request TXS, but don't try to match with skb. */ +#define MT_PACKET_ID_NO_SKB 1 +#define MT_PACKET_ID_FIRST 2 +#define MT_PACKET_ID_HAS_RATE BIT(7) +#define MT_PACKET_ID_MAX (GENMASK(7, 0) - 1) +struct mt76_wcid {struct mt76_rx_tid __rcu *aggr[IEEE80211_NUM_TIDS ];
drivers/net/wireless/mediatek/mt76/mt76.h struct mt76_wcid { · line 257
Quoted 4 lines
drivers/net/wireless/mediatek/mt76/mt76.h +1
-0@@ -246,6 +254,8 @@ struct mt76_wcid {struct rate_info rate; +struct sk_buff *skb_status_array[MT_PACKET_ID_MAX +1 ];
You could add this to reduce the struct size:
#define MT_NUM_STATUS_PACKETS \ (MT_PACKET_ID_MAX + 1 - MT_PACKET_ID_FIRST)
And then subtract MT_PACKET_ID_FIRST from cache entries.
Quoted 6 lines
drivers/net/wireless/mediatek/mt76/mt76.h +0
-0u16 idx;u8 hw_key_idx;u8 hw_key_idx2;@@ -302,13 +312,8 @@ struct mt76_rx_tid {#define MT_TX_CB_TXS_DONE BIT(1)#define MT_TX_CB_TXS_FAILED BIT(2)
drivers/net/wireless/mediatek/mt76/mt76.h struct mt76_rx_tid { · line 316
Quoted 10 lines
drivers/net/wireless/mediatek/mt76/mt76.h +2
-7-#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 +/* This is timer for when to give up when waiting for TXS callback. */ +#define MT_TX_STATUS_SKB_TIMEOUT (HZ / 8)
I think the way timeouts are checked now, HZ/8 is way too short. I would recommend checking timeout only for packets where MT_TX_CB_DMA_DONE is already set, and setting cb->jiffies from within __mt76_tx_status_skb_done on DMA completion. That should make it possible to keep the timeout short without running into it in cases where significant congestion adds huge completion latency.
Quoted 24 lines
drivers/net/wireless/mediatek/mt76/mt76.h +13
-3@@ -1297,13 +1303,33 @@ mt76_token_put(struct mt76_dev *dev, int token) }static inline int -mt76_get_next_pkt_id (struct mt76_wcid *wcid) +mt76_get_next_pkt_id (struct mt76_dev *dev,struct mt76_wcid *wcid, +struct sk_buff *skb) { +struct sk_buff *qskb; + +lockdep_assert_held (&dev->status_list.lock); + wcid->packet_id = (wcid->packet_id +1 ) &MT_PACKET_ID_MASK ; -if (wcid->packet_id ==MT_PACKET_ID_NO_ACK || - wcid->packet_id ==MT_PACKET_ID_NO_SKB ) +if (wcid->packet_id <MT_PACKET_ID_FIRST ) wcid->packet_id =MT_PACKET_ID_FIRST ; + qskb = wcid->skb_status_array[wcid->packet_id]; +if (qskb) { +/* bummer, already waiting on this pid. See if it is stale. */ +struct mt76_tx_cb *cb =mt76_tx_skb_cb (qskb); + +if (!time_after (jiffies, cb->jiffies +MT_TX_STATUS_SKB_TIMEOUT )) {
drivers/net/wireless/mediatek/mt76/mt76.h mt76_token_put(struct mt76_dev *dev, int token) · line 1332
Quoted 10 lines
drivers/net/wireless/mediatek/mt76/mt76.h +10
-0+/* ok, not stale. Increment pid anyway, will try next +* slot next time +*/ +return MT_PACKET_ID_NO_SKB ; + } + } + +/* cache this skb for fast lookup by packet-id */ + wcid->skb_status_array[wcid->packet_id] = skb; +
I think mt76_get_next_pkt_id is not a good place for caching the skb. Better cache it in the same place that also puts the skb in the status
list: mt76_tx_status_skb_add
That way you can drop your (possibly broken) changes to mt7921, which calls mt76_get_next_pkt_id directly, but does not support tx status tracking for skbs.
drivers/net/wireless/mediatek/mt76/mt7915/mac.c mt7915_mac_add_txs_skb(struct mt7915_dev *dev, struct mt76_wcid *wcid, int pid, · line 1322
Quoted 10 lines
drivers/net/wireless/mediatek/mt76/mt7915/mac.c +2
-0@@ -1318,6 +1318,8 @@ mt7915_mac_add_txs_skb(struct mt7915_dev *dev, struct mt76_wcid *wcid, int pid,mt76_tx_status_lock (mdev, &list); skb =mt76_tx_status_skb_get (mdev, wcid, pid, &list); + +/* TODO: Gather stats anyway, even if we are not matching on an skb. */
Please drop this comment, since you're deleting in another patch in this series anyway.
drivers/net/wireless/mediatek/mt76/mt7915/mac.c mt7915_mac_add_txs_skb(struct mt7915_dev *dev, struct mt76_wcid *wcid, int pid, · line 1426
Quoted 9 lines
drivers/net/wireless/mediatek/mt76/mt7915/mac.c +4
-0@@ -1417,10 +1419,14 @@ mt7915_mac_add_txs_skb(struct mt7915_dev *dev, struct mt76_wcid *wcid, int pid, stats->tx_bw[0 ]++;break ; } + +/* Cache rate for packets that don't get a TXS callback for some +* reason. +*/ wcid->rate = rate;
That comment is wrong, wcid->rate is cached because HE rates can't be reported via skb->cb due to lack of space.
Quoted 10 lines
drivers/net/wireless/mediatek/mt76/tx.c +2
-0@@ -130,15 +154,30 @@ mt76_tx_status_skb_add(struct mt76_dev *dev, struct mt76_wcid *wcid, IEEE80211_TX_CTL_RATE_CTRL_PROBE)))return MT_PACKET_ID_NO_SKB ; +/* due to limited range of the pktid (7 bits), we can only +* have a limited number of outstanding frames. I think it is OK to
drivers/net/wireless/mediatek/mt76/tx.c mt76_tx_status_skb_add(struct mt76_dev *dev, struct mt76_wcid *wcid, · line 168
Quoted 10 lines
drivers/net/wireless/mediatek/mt76/tx.c +10
-0+* check the length outside of a lock since it doesn't matter too much +* if we read wrong data here. +* The TX-status callbacks don't always return a callback for an SKB, +* so the status_list may contain some stale skbs. Those will be cleaned +* out periodically, see MT_TX_STATUS_SKB_TIMEOUT. +*/ + + qlen =skb_queue_len (&dev->status_list); +if (qlen >120 ) +return MT_PACKET_ID_NO_SKB ;
Checking the length of the per-device status list doesn't make sense, since pktid allocation is per-wcid.
- Felix
Quoted 45 lines · Felix Fietkau
Quoted 43 lines · On 2021-08-04 15:44, [email protected] wrote:
From: Ben Greear <[email protected]>
This improves performance when sending lots of frames that are requesting being mapped to a TXS callback.
Add comments to help next person understood the tx path better.
Signed-off-by Ben Greear <[email protected]>---
v5: Rebased on top of previous series.
drivers/net/wireless/mediatek/mt76/mt76.h | 48 +++++++--- .../net/wireless/mediatek/mt76/mt7603/mac.c | 2 +- .../net/wireless/mediatek/mt76/mt7615/mac.c | 2 +- .../net/wireless/mediatek/mt76/mt76x02_mac.c | 2 +- .../net/wireless/mediatek/mt76/mt7915/mac.c | 8 +- .../net/wireless/mediatek/mt76/mt7921/mac.c | 9 +- drivers/net/wireless/mediatek/mt76/tx.c | 90 ++++++++++++++++--- 7 files changed, 132 insertions(+), 29 deletions(-)drivers/net/wireless/mediatek/mt76/mt76.h +8
-0@@ -235,6 +235,14 @@ DECLARE_EWMA(signal, 10, 8);#define MT_WCID_TX_INFO_TXPWR_ADJ GENMASK(25, 18)#define MT_WCID_TX_INFO_SET BIT(31) +#define MT_PACKET_ID_MASK GENMASK(6, 0) +#define MT_PACKET_ID_NO_ACK 0 +/* Request TXS, but don't try to match with skb. */ +#define MT_PACKET_ID_NO_SKB 1 +#define MT_PACKET_ID_FIRST 2 +#define MT_PACKET_ID_HAS_RATE BIT(7) +#define MT_PACKET_ID_MAX (GENMASK(7, 0) - 1) +struct mt76_wcid {struct mt76_rx_tid __rcu *aggr[IEEE80211_NUM_TIDS ];@@ -246,6 +254,8 @@ struct mt76_wcid {
Quoted 8 lines
drivers/net/wireless/mediatek/mt76/mt76.h struct mt76_wcid { · line 257
Quoted 3 lines
drivers/net/wireless/mediatek/mt76/mt76.h +1
-0struct rate_info rate; +struct sk_buff *skb_status_array[MT_PACKET_ID_MAX +1 ];You could add this to reduce the struct size:
#define MT_NUM_STATUS_PACKETS \ (MT_PACKET_ID_MAX + 1 - MT_PACKET_ID_FIRST)And then subtract
MT_PACKET_ID_FIRSTfrom cache entries.
That saves two void* bytes of memory, and complicates the code a bit? I can do the change, just doesn't seem worthwhile to me.
Quoted 7 lines
Quoted 7 lines
drivers/net/wireless/mediatek/mt76/mt76.h +0
-0u16 idx;u8 hw_key_idx;u8 hw_key_idx2;@@ -302,13 +312,8 @@ struct mt76_rx_tid {#define MT_TX_CB_TXS_DONE BIT(1)#define MT_TX_CB_TXS_FAILED BIT(2)
Quoted 15 lines
drivers/net/wireless/mediatek/mt76/mt76.h struct mt76_rx_tid { · line 316
Quoted 9 lines
drivers/net/wireless/mediatek/mt76/mt76.h +2
-7-#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 +/* This is timer for when to give up when waiting for TXS callback. */ +#define MT_TX_STATUS_SKB_TIMEOUT (HZ / 8)I think the way timeouts are checked now, HZ/8 is way too short. I would recommend checking timeout only for packets where
MT_TX_CB_DMA_DONEis already set, and settingcb->jiffiesfrom within__mt76_tx_status_skb_doneon DMA completion. That should make it possible to keep the timeout short without running into it in cases where significant congestion adds huge completion latency.
Ok, I like that idea. What is reasonable timeout from time of DMA done before we give up on TXS callback?
Quoted 39 lines
Quoted 25 lines
drivers/net/wireless/mediatek/mt76/mt76.h +13
-3@@ -1297,13 +1303,33 @@ mt76_token_put(struct mt76_dev *dev, int token) }static inline int -mt76_get_next_pkt_id (struct mt76_wcid *wcid) +mt76_get_next_pkt_id (struct mt76_dev *dev,struct mt76_wcid *wcid, +struct sk_buff *skb) { +struct sk_buff *qskb; + +lockdep_assert_held (&dev->status_list.lock); + wcid->packet_id = (wcid->packet_id +1 ) &MT_PACKET_ID_MASK ; -if (wcid->packet_id ==MT_PACKET_ID_NO_ACK || - wcid->packet_id ==MT_PACKET_ID_NO_SKB ) +if (wcid->packet_id <MT_PACKET_ID_FIRST ) wcid->packet_id =MT_PACKET_ID_FIRST ; + qskb = wcid->skb_status_array[wcid->packet_id]; +if (qskb) { +/* bummer, already waiting on this pid. See if it is stale. */ +struct mt76_tx_cb *cb =mt76_tx_skb_cb (qskb); + +if (!time_after (jiffies, cb->jiffies +MT_TX_STATUS_SKB_TIMEOUT )) {drivers/net/wireless/mediatek/mt76/mt76.h mt76_token_put(struct mt76_dev *dev, int token) · line 1332
Quoted 10 lines
drivers/net/wireless/mediatek/mt76/mt76.h +10
-0+/* ok, not stale. Increment pid anyway, will try next +* slot next time +*/ +return MT_PACKET_ID_NO_SKB ; + } + } + +/* cache this skb for fast lookup by packet-id */ + wcid->skb_status_array[wcid->packet_id] = skb; +I think
mt76_get_next_pkt_idis not a good place for caching the skb. Better cache it in the same place that also puts the skb in the status
list:mt76_tx_status_skb_add
Quoted 3 lines
That way you can drop your (possibly broken) changes to mt7921, which calls
mt76_get_next_pkt_iddirectly, but does not support tx status tracking for skbs.
Ok, I will try that.
Quoted 14 lines
drivers/net/wireless/mediatek/mt76/mt7915/mac.c mt7915_mac_add_txs_skb(struct mt7915_dev *dev, struct mt76_wcid *wcid, int pid, · line 1322
Quoted 11 lines
drivers/net/wireless/mediatek/mt76/mt7915/mac.c +2
-0@@ -1318,6 +1318,8 @@ mt7915_mac_add_txs_skb(struct mt7915_dev *dev, struct mt76_wcid *wcid, int pid,mt76_tx_status_lock (mdev, &list); skb =mt76_tx_status_skb_get (mdev, wcid, pid, &list); + +/* TODO: Gather stats anyway, even if we are not matching on an skb. */ Please drop this comment, since you're deleting in another patch in this series anyway.
Quoted 11 lines
drivers/net/wireless/mediatek/mt76/mt7915/mac.c mt7915_mac_add_txs_skb(struct mt7915_dev *dev, struct mt76_wcid *wcid, int pid, · line 1426
Quoted 9 lines
drivers/net/wireless/mediatek/mt76/mt7915/mac.c +4
-0@@ -1417,10 +1419,14 @@ mt7915_mac_add_txs_skb(struct mt7915_dev *dev, struct mt76_wcid *wcid, int pid, stats->tx_bw[0 ]++;break ; } + +/* Cache rate for packets that don't get a TXS callback for some +* reason. +*/ wcid->rate = rate;That comment is wrong,
wcid->rateis cached because HE rates can't be reported viaskb->cbdue to lack of space.
We can update the rate from txs callback, and and from txfree path, and also from querying the firmware rate-ctrl registers (I think?). TXS is disabled for most frames by default. txfree gives only some info, not enough. And polling rate-ctrl registers is slow.
So I think the comment is OK, but I end up modifying the code later anyway, so I can remove this comment if you prefer.
Quoted 10 lines
Quoted 10 lines
drivers/net/wireless/mediatek/mt76/tx.c +0
-0@@ -130,15 +154,30 @@ mt76_tx_status_skb_add(struct mt76_dev *dev, struct mt76_wcid *wcid, IEEE80211_TX_CTL_RATE_CTRL_PROBE)))return MT_PACKET_ID_NO_SKB ;
Quoted 14 lines
drivers/net/wireless/mediatek/mt76/tx.c mt76_tx_status_skb_add(struct mt76_dev *dev, struct mt76_wcid *wcid, · line 168
Quoted 12 lines
drivers/net/wireless/mediatek/mt76/tx.c +12
-0+/* due to limited range of the pktid (7 bits), we can only +* have a limited number of outstanding frames. I think it is OK to +* check the length outside of a lock since it doesn't matter too much +* if we read wrong data here. +* The TX-status callbacks don't always return a callback for an SKB, +* so the status_list may contain some stale skbs. Those will be cleaned +* out periodically, see MT_TX_STATUS_SKB_TIMEOUT. +*/ + + qlen =skb_queue_len (&dev->status_list); +if (qlen >120 ) +return MT_PACKET_ID_NO_SKB ;Checking the length of the per-device status list doesn't make sense, since pktid allocation is per-wcid.
Ok, so just remove this code, or should I set some other higher limit to bound the list?
Thanks,
Ben
Quoted 3 lines
- Felix
Signature · 2 lines
Ben Greear <[email protected]> Candela Technologies Inc http://www.candelatech.com
Felix Fietkau
maintainerQuoted 53 lines · Ben Greear
Quoted 52 lines · Felix Fietkau
Quoted 42 lines · On 2021-08-04 15:44, [email protected] wrote:
From: Ben Greear <[email protected]>
This improves performance when sending lots of frames that are requesting being mapped to a TXS callback.
Add comments to help next person understood the tx path better.
Signed-off-by Ben Greear <[email protected]>---
v5: Rebased on top of previous series.
drivers/net/wireless/mediatek/mt76/mt76.h | 48 +++++++--- .../net/wireless/mediatek/mt76/mt7603/mac.c | 2 +- .../net/wireless/mediatek/mt76/mt7615/mac.c | 2 +- .../net/wireless/mediatek/mt76/mt76x02_mac.c | 2 +- .../net/wireless/mediatek/mt76/mt7915/mac.c | 8 +- .../net/wireless/mediatek/mt76/mt7921/mac.c | 9 +- drivers/net/wireless/mediatek/mt76/tx.c | 90 ++++++++++++++++--- 7 files changed, 132 insertions(+), 29 deletions(-)drivers/net/wireless/mediatek/mt76/mt76.h +8
-0@@ -235,6 +235,14 @@ DECLARE_EWMA(signal, 10, 8);#define MT_WCID_TX_INFO_TXPWR_ADJ GENMASK(25, 18)#define MT_WCID_TX_INFO_SET BIT(31) +#define MT_PACKET_ID_MASK GENMASK(6, 0) +#define MT_PACKET_ID_NO_ACK 0 +/* Request TXS, but don't try to match with skb. */ +#define MT_PACKET_ID_NO_SKB 1 +#define MT_PACKET_ID_FIRST 2 +#define MT_PACKET_ID_HAS_RATE BIT(7) +#define MT_PACKET_ID_MAX (GENMASK(7, 0) - 1) +struct mt76_wcid {struct mt76_rx_tid __rcu *aggr[IEEE80211_NUM_TIDS ];drivers/net/wireless/mediatek/mt76/mt76.h struct mt76_wcid { · line 257
Quoted 4 lines
drivers/net/wireless/mediatek/mt76/mt76.h +1
-0@@ -246,6 +254,8 @@ struct mt76_wcid {struct rate_info rate; +struct sk_buff *skb_status_array[MT_PACKET_ID_MAX +1 ];You could add this to reduce the struct size:
#define MT_NUM_STATUS_PACKETS \ (MT_PACKET_ID_MAX + 1 - MT_PACKET_ID_FIRST)
Quoted 4 lines
Quoted 1 line
And then subtract
MT_PACKET_ID_FIRSTfrom cache entries.That saves two void* bytes of memory, and complicates the code a bit? I can do the change, just doesn't seem worthwhile to me.
It's not much more complicated (simple subtraction in very few places), and the memory saved is per station.
Quoted 23 lines
Quoted 7 lines
Quoted 7 lines
drivers/net/wireless/mediatek/mt76/mt76.h +0
-0u16 idx;u8 hw_key_idx;u8 hw_key_idx2;@@ -302,13 +312,8 @@ struct mt76_rx_tid {#define MT_TX_CB_TXS_DONE BIT(1)#define MT_TX_CB_TXS_FAILED BIT(2)Quoted 15 lines
drivers/net/wireless/mediatek/mt76/mt76.h struct mt76_rx_tid { · line 316
Quoted 9 lines
drivers/net/wireless/mediatek/mt76/mt76.h +2
-7-#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 +/* This is timer for when to give up when waiting for TXS callback. */ +#define MT_TX_STATUS_SKB_TIMEOUT (HZ / 8)I think the way timeouts are checked now, HZ/8 is way too short. I would recommend checking timeout only for packets where
MT_TX_CB_DMA_DONEis already set, and settingcb->jiffiesfrom within__mt76_tx_status_skb_doneon DMA completion. That should make it possible to keep the timeout short without running into it in cases where significant congestion adds huge completion latency.
Quoted 2 lines
Ok, I like that idea. What is reasonable timeout from time of DMA done before we give up on TXS callback?
Your value of HZ / 8 seems reasonable to me for that case.
Quoted 25 lines
Quoted 13 lines
drivers/net/wireless/mediatek/mt76/mt7915/mac.c mt7915_mac_add_txs_skb(struct mt7915_dev *dev, struct mt76_wcid *wcid, int pid, · line 1322
Quoted 10 lines
drivers/net/wireless/mediatek/mt76/mt7915/mac.c +2
-0@@ -1318,6 +1318,8 @@ mt7915_mac_add_txs_skb(struct mt7915_dev *dev, struct mt76_wcid *wcid, int pid,mt76_tx_status_lock (mdev, &list); skb =mt76_tx_status_skb_get (mdev, wcid, pid, &list); + +/* TODO: Gather stats anyway, even if we are not matching on an skb. */ Please drop this comment, since you're deleting in another patch in this series anyway.
Quoted 11 lines
drivers/net/wireless/mediatek/mt76/mt7915/mac.c mt7915_mac_add_txs_skb(struct mt7915_dev *dev, struct mt76_wcid *wcid, int pid, · line 1426
Quoted 9 lines
drivers/net/wireless/mediatek/mt76/mt7915/mac.c +4
-0@@ -1417,10 +1419,14 @@ mt7915_mac_add_txs_skb(struct mt7915_dev *dev, struct mt76_wcid *wcid, int pid, stats->tx_bw[0 ]++;break ; } + +/* Cache rate for packets that don't get a TXS callback for some +* reason. +*/ wcid->rate = rate;That comment is wrong,
wcid->rateis cached because HE rates can't be reported viaskb->cbdue to lack of space.
Quoted 7 lines
We can update the rate from txs callback, and and from txfree path, and also from querying the firmware rate-ctrl registers (I think?). TXS is disabled for most frames by default. txfree gives only some info, not enough. And polling rate-ctrl registers is slow.
So I think the comment is OK, but I end up modifying the code later anyway, so I can remove this comment if you prefer.
Yes, please do that.
Quoted 23 lines
Quoted 8 lines
Quoted 8 lines
drivers/net/wireless/mediatek/mt76/tx.c +0
-0@@ -130,15 +154,30 @@ mt76_tx_status_skb_add(struct mt76_dev *dev, struct mt76_wcid *wcid, IEEE80211_TX_CTL_RATE_CTRL_PROBE)))return MT_PACKET_ID_NO_SKB ;Quoted 14 lines
drivers/net/wireless/mediatek/mt76/tx.c mt76_tx_status_skb_add(struct mt76_dev *dev, struct mt76_wcid *wcid, · line 168
Quoted 12 lines
drivers/net/wireless/mediatek/mt76/tx.c +12
-0+/* due to limited range of the pktid (7 bits), we can only +* have a limited number of outstanding frames. I think it is OK to +* check the length outside of a lock since it doesn't matter too much +* if we read wrong data here. +* The TX-status callbacks don't always return a callback for an SKB, +* so the status_list may contain some stale skbs. Those will be cleaned +* out periodically, see MT_TX_STATUS_SKB_TIMEOUT. +*/ + + qlen =skb_queue_len (&dev->status_list); +if (qlen >120 ) +return MT_PACKET_ID_NO_SKB ;Checking the length of the per-device status list doesn't make sense, since pktid allocation is per-wcid.
Quoted 2 lines
Ok, so just remove this code, or should I set some other higher limit to bound the list?
You could just check for a duplicate skb_status_array entry.
- Felix
Quoted 23 lines · Felix Fietkau
Quoted 23 lines
Quoted 22 lines
Quoted 10 lines
drivers/net/wireless/mediatek/mt76/tx.c +2
-0@@ -130,15 +154,30 @@ mt76_tx_status_skb_add(struct mt76_dev *dev, struct mt76_wcid *wcid, IEEE80211_TX_CTL_RATE_CTRL_PROBE)))return MT_PACKET_ID_NO_SKB ; +/* due to limited range of the pktid (7 bits), we can only +* have a limited number of outstanding frames. I think it is OK to drivers/net/wireless/mediatek/mt76/tx.c mt76_tx_status_skb_add(struct mt76_dev *dev, struct mt76_wcid *wcid, · line 168
Quoted 10 lines
drivers/net/wireless/mediatek/mt76/tx.c +10
-0+* check the length outside of a lock since it doesn't matter too much +* if we read wrong data here. +* The TX-status callbacks don't always return a callback for an SKB, +* so the status_list may contain some stale skbs. Those will be cleaned +* out periodically, see MT_TX_STATUS_SKB_TIMEOUT. +*/ + + qlen =skb_queue_len (&dev->status_list); +if (qlen >120 ) +return MT_PACKET_ID_NO_SKB ;Checking the length of the per-device status list doesn't make sense, since pktid allocation is per-wcid.
Quoted 3 lines
Quoted 2 lines
Ok, so just remove this code, or should I set some other higher limit to bound the list?
You could just check for a duplicate
skb_status_arrayentry.
Ok, that will happen anyway when searching for next wcid pkt-id.
The check above was a quick bail-out before locks were acquired.
I'll just remove that qlen check...
Thanks,
Ben
Quoted 3 lines
- Felix
Signature · 2 lines
Ben Greear <[email protected]> Candela Technologies Inc http://www.candelatech.com