Handle possible 'mt76_poll_msec()' timeout in 'mt7603_pse_client_reset()', convert the latter from 'void' to return 'int', propagate return value to 'mt7603_dma_init()' and 'WARN_ON()' on it in 'mt7603_mac_watchdog_reset()'. Found by Linux Verification Center (linuxtesting.org) with SVACE. Signed-off-by: Dmitry Antipov <dmantipov@xxxxxxxxx> --- drivers/net/wireless/mediatek/mt76/mt7603/dma.c | 4 +++- drivers/net/wireless/mediatek/mt76/mt7603/mac.c | 16 ++++++++++------ .../net/wireless/mediatek/mt76/mt7603/mt7603.h | 2 +- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c index 03ba11a61c90..15c6564f212a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c @@ -169,7 +169,9 @@ int mt7603_dma_init(struct mt7603_dev *dev) MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE); mt76_wr(dev, MT_WPDMA_RST_IDX, ~0); - mt7603_pse_client_reset(dev); + ret = mt7603_pse_client_reset(dev); + if (ret) + return ret; for (i = 0; i < ARRAY_SIZE(wmm_queue_map); i++) { ret = mt76_init_tx_queue(&dev->mphy, i, wmm_queue_map[i], diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c index 12e0af52082a..fe38b9a8034d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c @@ -1367,7 +1367,7 @@ void mt7603_mac_stop(struct mt7603_dev *dev) mt76_clear(dev, MT_WF_ARB_RQCR, MT_WF_ARB_RQCR_RX_START); } -void mt7603_pse_client_reset(struct mt7603_dev *dev) +int mt7603_pse_client_reset(struct mt7603_dev *dev) { u32 addr; @@ -1383,20 +1383,24 @@ void mt7603_pse_client_reset(struct mt7603_dev *dev) /* Start PSE client TX abort */ mt76_set(dev, addr, MT_CLIENT_RESET_TX_R_E_1); - mt76_poll_msec(dev, addr, MT_CLIENT_RESET_TX_R_E_1_S, - MT_CLIENT_RESET_TX_R_E_1_S, 500); + if (!mt76_poll_msec(dev, addr, MT_CLIENT_RESET_TX_R_E_1_S, + MT_CLIENT_RESET_TX_R_E_1_S, 500)) + return -ETIMEDOUT; mt76_set(dev, addr, MT_CLIENT_RESET_TX_R_E_2); mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_SW_RESET); /* Wait for PSE client to clear TX FIFO */ - mt76_poll_msec(dev, addr, MT_CLIENT_RESET_TX_R_E_2_S, - MT_CLIENT_RESET_TX_R_E_2_S, 500); + if (!mt76_poll_msec(dev, addr, MT_CLIENT_RESET_TX_R_E_2_S, + MT_CLIENT_RESET_TX_R_E_2_S, 500)) + return -ETIMEDOUT; /* Clear PSE client TX abort state */ mt76_clear(dev, addr, MT_CLIENT_RESET_TX_R_E_1 | MT_CLIENT_RESET_TX_R_E_2); + + return 0; } static void mt7603_dma_sched_reset(struct mt7603_dev *dev) @@ -1450,7 +1454,7 @@ static void mt7603_mac_watchdog_reset(struct mt7603_dev *dev) mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_FORCE_TX_EOF); - mt7603_pse_client_reset(dev); + WARN_ON(mt7603_pse_client_reset(dev) < 0); mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WM], true); for (i = 0; i < __MT_TXQ_MAX; i++) diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h index 7c3be596da09..d651a13efe8c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h @@ -215,7 +215,7 @@ void mt7603_mac_tx_ba_reset(struct mt7603_dev *dev, int wcid, int tid, int ba_size); void mt7603_mac_sta_poll(struct mt7603_dev *dev); -void mt7603_pse_client_reset(struct mt7603_dev *dev); +int mt7603_pse_client_reset(struct mt7603_dev *dev); int mt7603_mcu_set_channel(struct mt7603_dev *dev); int mt7603_mcu_set_eeprom(struct mt7603_dev *dev); -- 2.41.0