Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

wifi: mt76: only mark tx-status-failed frames as ACKed on mt76x0/2

The interrupt status polling is unreliable, which can cause status events
to get lost. On all newer chips, txs-timeout is an indication that the
packet was either never sent, or never acked.
Fixes issues with inactivity polling.

Link: https://patch.msgid.link/20250311103646.43346-6-nbd@nbd.name
Signed-off-by: Felix Fietkau <nbd@nbd.name>

+11 -5
+1
drivers/net/wireless/mediatek/mt76/mt76.h
··· 492 492 #define MT_DRV_RX_DMA_HDR BIT(3) 493 493 #define MT_DRV_HW_MGMT_TXQ BIT(4) 494 494 #define MT_DRV_AMSDU_OFFLOAD BIT(5) 495 + #define MT_DRV_IGNORE_TXS_FAILED BIT(6) 495 496 496 497 struct mt76_driver_ops { 497 498 u32 drv_flags;
+2 -1
drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
··· 156 156 static const struct mt76_driver_ops drv_ops = { 157 157 .txwi_size = sizeof(struct mt76x02_txwi), 158 158 .drv_flags = MT_DRV_TX_ALIGNED4_SKBS | 159 - MT_DRV_SW_RX_AIRTIME, 159 + MT_DRV_SW_RX_AIRTIME | 160 + MT_DRV_IGNORE_TXS_FAILED, 160 161 .survey_flags = SURVEY_INFO_TIME_TX, 161 162 .update_survey = mt76x02_update_channel, 162 163 .set_channel = mt76x0_set_channel,
+2 -1
drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
··· 214 214 const struct usb_device_id *id) 215 215 { 216 216 static const struct mt76_driver_ops drv_ops = { 217 - .drv_flags = MT_DRV_SW_RX_AIRTIME, 217 + .drv_flags = MT_DRV_SW_RX_AIRTIME | 218 + MT_DRV_IGNORE_TXS_FAILED, 218 219 .survey_flags = SURVEY_INFO_TIME_TX, 219 220 .update_survey = mt76x02_update_channel, 220 221 .set_channel = mt76x0_set_channel,
+2 -1
drivers/net/wireless/mediatek/mt76/mt76x2/pci.c
··· 22 22 static const struct mt76_driver_ops drv_ops = { 23 23 .txwi_size = sizeof(struct mt76x02_txwi), 24 24 .drv_flags = MT_DRV_TX_ALIGNED4_SKBS | 25 - MT_DRV_SW_RX_AIRTIME, 25 + MT_DRV_SW_RX_AIRTIME | 26 + MT_DRV_IGNORE_TXS_FAILED, 26 27 .survey_flags = SURVEY_INFO_TIME_TX, 27 28 .update_survey = mt76x02_update_channel, 28 29 .set_channel = mt76x2e_set_channel,
+2 -1
drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
··· 29 29 const struct usb_device_id *id) 30 30 { 31 31 static const struct mt76_driver_ops drv_ops = { 32 - .drv_flags = MT_DRV_SW_RX_AIRTIME, 32 + .drv_flags = MT_DRV_SW_RX_AIRTIME | 33 + MT_DRV_IGNORE_TXS_FAILED, 33 34 .survey_flags = SURVEY_INFO_TIME_TX, 34 35 .update_survey = mt76x02_update_channel, 35 36 .set_channel = mt76x2u_set_channel,
+2 -1
drivers/net/wireless/mediatek/mt76/tx.c
··· 100 100 return; 101 101 102 102 /* Tx status can be unreliable. if it fails, mark the frame as ACKed */ 103 - if (flags & MT_TX_CB_TXS_FAILED) { 103 + if (flags & MT_TX_CB_TXS_FAILED && 104 + (dev->drv->drv_flags & MT_DRV_IGNORE_TXS_FAILED)) { 104 105 info->status.rates[0].count = 0; 105 106 info->status.rates[0].idx = -1; 106 107 info->flags |= IEEE80211_TX_STAT_ACK;