Skip to content

Commit

Permalink
mt7603: improve recovery from MCU hang
Browse files Browse the repository at this point in the history
Fix forcing watchdog reset after a MCU hang
Run watchdog work immediately after a failed channel change

Signed-off-by: Felix Fietkau <nbd@nbd.name>
  • Loading branch information
nbd168 committed Nov 7, 2018
1 parent 5ee0523 commit 417cf49
Show file tree
Hide file tree
Showing 5 changed files with 16 additions and 4 deletions.
1 change: 1 addition & 0 deletions mt7603/debugfs.c
Expand Up @@ -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;

Expand Down
4 changes: 4 additions & 0 deletions mt7603/mac.c
Expand Up @@ -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;
Expand Down
11 changes: 8 additions & 3 deletions mt7603/main.c
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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);

Expand All @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down
2 changes: 1 addition & 1 deletion mt7603/mcu.c
Expand Up @@ -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;
}
Expand Down
2 changes: 2 additions & 0 deletions mt7603/mt7603.h
Expand Up @@ -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
};

Expand Down Expand Up @@ -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];
Expand Down

2 comments on commit 417cf49

@lukasz1992
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think something is wrong with definition - failed should be initiated to false, not true:

bool failed = true;

Currently condition if (failed) is always true.

@nbd168
Copy link
Member Author

@nbd168 nbd168 commented on 417cf49 Nov 8, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I will fix that. It should be harmless though, so it didn't show up in any negative way in my own tests.

Please sign in to comment.