From f466a624895d8374e0de33716b88a5da84ecd36c Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 4 Mar 2016 15:41:05 +0100 Subject: [PATCH] mt7603: add debugfs file to show MAC reset causes Signed-off-by: Felix Fietkau --- Makefile | 2 +- mt7603.h | 12 ++++++++++++ mt7603_debugfs.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ mt7603_init.c | 2 +- mt7603_mac.c | 25 ++++++++++++++++++++----- 5 files changed, 82 insertions(+), 7 deletions(-) create mode 100644 mt7603_debugfs.c diff --git a/Makefile b/Makefile index 5ec48c37..b0592f43 100644 --- a/Makefile +++ b/Makefile @@ -14,4 +14,4 @@ mt76x2e-y := \ mt7603e-y := \ mt7603_pci.o mt7603_soc.o mt7603_main.o mt7603_init.o mt7603_mcu.o \ mt7603_core.o mt7603_dma.o mt7603_mac.o mt7603_eeprom.o \ - mt7603_beacon.o + mt7603_beacon.o mt7603_debugfs.o diff --git a/mt7603.h b/mt7603.h index 8a6836b9..1cc71f6e 100644 --- a/mt7603.h +++ b/mt7603.h @@ -85,6 +85,15 @@ struct mt7603_vif { #define MT7603_CB_TXS_DONE BIT(1) #define MT7603_CB_TXS_FAILED BIT(2) +enum mt7603_reset_cause { + RESET_CAUSE_TX_HANG, + RESET_CAUSE_TX_BUSY, + RESET_CAUSE_RX_BUSY, + RESET_CAUSE_BEACON_STUCK, + RESET_CAUSE_RX_PSE_BUSY, + __RESET_CAUSE_MAX +}; + struct mt7603_cb { unsigned long jiffies; u8 wcid; @@ -136,6 +145,8 @@ struct mt7603_dev { u16 tx_dma_idx[4]; u16 rx_dma_idx; + unsigned int reset_cause[__RESET_CAUSE_MAX]; + struct delayed_work mac_work; struct tasklet_struct tx_tasklet; struct tasklet_struct pre_tbtt_tasklet; @@ -182,6 +193,7 @@ void mt7603_dma_cleanup(struct mt7603_dev *dev); int mt7603_mcu_init(struct mt7603_dev *dev); int mt7603_tx_queue_mcu(struct mt7603_dev *dev, enum mt76_txq_id qid, struct sk_buff *skb); +void mt7603_init_debugfs(struct mt7603_dev *dev); void mt7603_set_irq_mask(struct mt7603_dev *dev, u32 clear, u32 set); diff --git a/mt7603_debugfs.c b/mt7603_debugfs.c new file mode 100644 index 00000000..5f3d5644 --- /dev/null +++ b/mt7603_debugfs.c @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2016 Felix Fietkau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "mt7603.h" + +static int +mt7603_reset_read(struct seq_file *s, void *data) +{ + struct mt7603_dev *dev = dev_get_drvdata(s->private); + static const char * const reset_cause_str[] = { + [RESET_CAUSE_TX_HANG] = "TX hang", + [RESET_CAUSE_TX_BUSY] = "TX DMA busy stuck", + [RESET_CAUSE_RX_BUSY] = "RX DMA busy stuck", + [RESET_CAUSE_RX_PSE_BUSY] = "RX PSE busy stuck", + [RESET_CAUSE_BEACON_STUCK] = "Beacon stuck", + }; + int i; + + for (i = 0; i < ARRAY_SIZE(reset_cause_str); i++) { + if (!reset_cause_str[i]) + continue; + + seq_printf(s, "%20s: %u\n", reset_cause_str[i], dev->reset_cause[i]); + } + + return 0; +} + +void mt7603_init_debugfs(struct mt7603_dev *dev) +{ + struct dentry *dir; + + dir = mt76_register_debugfs(&dev->mt76); + if (!dir) + return; + + debugfs_create_devm_seqfile(dev->mt76.dev, "reset", dir, mt7603_reset_read); +} diff --git a/mt7603_init.c b/mt7603_init.c index 985cf024..fca0abe6 100644 --- a/mt7603_init.c +++ b/mt7603_init.c @@ -376,7 +376,7 @@ int mt7603_register_device(struct mt7603_dev *dev) sband = wiphy->bands[IEEE80211_BAND_2GHZ]; dev->chandef.chan = &sband->channels[0]; - mt76_register_debugfs(&dev->mt76); + mt7603_init_debugfs(dev); return 0; } diff --git a/mt7603_mac.c b/mt7603_mac.c index 88995efd..d019be69 100644 --- a/mt7603_mac.c +++ b/mt7603_mac.c @@ -1119,14 +1119,23 @@ static bool mt7603_rx_pse_busy(struct mt7603_dev *dev) static bool mt7603_watchdog_check(struct mt7603_dev *dev, u8 *counter, + enum mt7603_reset_cause cause, bool (*check)(struct mt7603_dev *dev)) { - if (!check(dev) && *counter < MT7603_WATCHDOG_TIMEOUT) { - *counter = 0; - return false; + if (check) { + if (!check(dev) && *counter < MT7603_WATCHDOG_TIMEOUT) { + *counter = 0; + return false; + } + + (*counter)++; } - return ++(*counter) >= MT7603_WATCHDOG_TIMEOUT; + if (*counter < MT7603_WATCHDOG_TIMEOUT) + return false; + + dev->reset_cause[cause]++; + return true; } void mt7603_mac_work(struct work_struct *work) @@ -1150,14 +1159,20 @@ void mt7603_mac_work(struct work_struct *work) mutex_lock(&dev->mutex); if (WARN_ON_ONCE(mt7603_watchdog_check(dev, &dev->tx_check, + RESET_CAUSE_TX_BUSY, mt7603_tx_dma_busy)) || WARN_ON_ONCE(mt7603_watchdog_check(dev, &dev->rx_dma_check, + RESET_CAUSE_RX_BUSY, mt7603_rx_dma_busy)) || WARN_ON_ONCE(mt7603_watchdog_check(dev, &dev->txrx_check, + RESET_CAUSE_TX_HANG, mt7603_tx_rx_dma_busy)) || WARN_ON_ONCE(mt7603_watchdog_check(dev, &dev->rx_pse_check, + RESET_CAUSE_RX_PSE_BUSY, mt7603_rx_pse_busy)) || - WARN_ON_ONCE(dev->beacon_check > MT7603_WATCHDOG_TIMEOUT)) { + WARN_ON_ONCE(mt7603_watchdog_check(dev, &dev->beacon_check, + RESET_CAUSE_BEACON_STUCK, + NULL))) { dev->beacon_check = 0; dev->tx_check = 0; dev->txrx_check = 0;