From 417cf49ce811287b980767a1b7b44118b0ccc8e4 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 7 Nov 2018 16:53:28 +0100 Subject: [PATCH] mt7603: improve recovery from MCU hang Fix forcing watchdog reset after a MCU hang Run watchdog work immediately after a failed channel change Signed-off-by: Felix Fietkau --- mt7603/debugfs.c | 1 + mt7603/mac.c | 4 ++++ mt7603/main.c | 11 ++++++++--- mt7603/mcu.c | 2 +- mt7603/mt7603.h | 2 ++ 5 files changed, 16 insertions(+), 4 deletions(-) diff --git a/mt7603/debugfs.c b/mt7603/debugfs.c index 622b6ba7a..bf298a1c1 100644 --- a/mt7603/debugfs.c +++ b/mt7603/debugfs.c @@ -27,6 +27,7 @@ mt7603_reset_read(struct seq_file *s, void *data) [RESET_CAUSE_RX_BUSY] = "RX DMA busy stuck", [RESET_CAUSE_RX_PSE_BUSY] = "RX PSE busy stuck", [RESET_CAUSE_BEACON_STUCK] = "Beacon stuck", + [RESET_CAUSE_MCU_HANG] = "MCU hang", }; int i; diff --git a/mt7603/mac.c b/mt7603/mac.c index ca9e0b6e1..35f82d515 100644 --- a/mt7603/mac.c +++ b/mt7603/mac.c @@ -1375,12 +1375,16 @@ void mt7603_mac_work(struct work_struct *work) mt7603_watchdog_check(dev, &dev->beacon_check, RESET_CAUSE_BEACON_STUCK, NULL) || + mt7603_watchdog_check(dev, &dev->mcu_hang, + RESET_CAUSE_MCU_HANG, + NULL) || dev->pse_reset_failed) { dev->beacon_check = 0; dev->tx_dma_check = 0; dev->tx_hang_check = 0; dev->rx_dma_check = 0; dev->rx_pse_check = 0; + dev->mcu_hang = 0; dev->rx_dma_idx = ~0; memset(dev->tx_dma_idx, 0xff, sizeof(dev->tx_dma_idx)); reset = true; diff --git a/mt7603/main.c b/mt7603/main.c index 5940fc184..714df9f60 100644 --- a/mt7603/main.c +++ b/mt7603/main.c @@ -27,11 +27,10 @@ mt7603_start(struct ieee80211_hw *hw) { struct mt7603_dev *dev = hw->priv; - ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work, - MT7603_WATCHDOG_TIME); mt7603_mac_start(dev); dev->survey_time = ktime_get_boottime(); set_bit(MT76_STATE_RUNNING, &dev->mt76.state); + mt7603_mac_work(&dev->mac_work.work); return 0; } @@ -130,6 +129,7 @@ mt7603_set_channel(struct mt7603_dev *dev, struct cfg80211_chan_def *def) u8 *rssi_data = (u8 *) dev->mt76.eeprom.data; int idx, ret; u8 bw = MT_BW_20; + bool failed = true; cancel_delayed_work_sync(&dev->mac_work); @@ -145,8 +145,10 @@ mt7603_set_channel(struct mt7603_dev *dev, struct cfg80211_chan_def *def) dev->mt76.chandef = *def; mt76_rmw_field(dev, MT_AGG_BWCR, MT_AGG_BWCR_BW, bw); ret = mt7603_mcu_set_channel(dev); - if (ret) + if (ret) { + failed = true; goto out; + } if (def->chan->band == NL80211_BAND_5GHZ) { idx = 1; @@ -182,6 +184,9 @@ mt7603_set_channel(struct mt7603_dev *dev, struct cfg80211_chan_def *def) out: mutex_unlock(&dev->mt76.mutex); + if (failed) + mt7603_mac_work(&dev->mac_work.work); + return ret; } diff --git a/mt7603/mcu.c b/mt7603/mcu.c index 3fbc79630..f193e6f44 100644 --- a/mt7603/mcu.c +++ b/mt7603/mcu.c @@ -130,7 +130,7 @@ mt7603_mcu_msg_send(struct mt7603_dev *dev, struct sk_buff *skb, int cmd, int qu dev_err(mdev->dev, "MCU message %d (seq %d) timed out\n", cmd, seq); - dev->tx_dma_check = MT7603_WATCHDOG_TIMEOUT; + dev->mcu_hang = MT7603_WATCHDOG_TIMEOUT; ret = -ETIMEDOUT; break; } diff --git a/mt7603/mt7603.h b/mt7603/mt7603.h index 805f4b00b..806312f64 100644 --- a/mt7603/mt7603.h +++ b/mt7603/mt7603.h @@ -88,6 +88,7 @@ enum mt7603_reset_cause { RESET_CAUSE_RX_BUSY, RESET_CAUSE_BEACON_STUCK, RESET_CAUSE_RX_PSE_BUSY, + RESET_CAUSE_MCU_HANG, __RESET_CAUSE_MAX }; @@ -124,6 +125,7 @@ struct mt7603_dev { u8 tx_dma_check; u8 rx_dma_check; u8 rx_pse_check; + u8 mcu_hang; u8 pse_reset_failed; u16 tx_dma_idx[4];