--- /dev/null +++ b/package/kernel/mac80211/patches/ath/301-ath-reset.patch @@ -0,0 +1,96 @@ +diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c +index 4c81b1d7f417..fb7a2952d0ce 100644 +--- a/drivers/net/wireless/ath/ath9k/debug.c ++++ b/drivers/net/wireless/ath/ath9k/debug.c +@@ -749,9 +749,9 @@ static int read_file_misc(struct seq_file *file, void *data) + + static int read_file_reset(struct seq_file *file, void *data) + { +- struct ieee80211_hw *hw = dev_get_drvdata(file->private); +- struct ath_softc *sc = hw->priv; ++ struct ath_softc *sc = file->private; + static const char * const reset_cause[__RESET_TYPE_MAX] = { ++ [RESET_TYPE_USER] = "User reset", + [RESET_TYPE_BB_HANG] = "Baseband Hang", + [RESET_TYPE_BB_WATCHDOG] = "Baseband Watchdog", + [RESET_TYPE_FATAL_INT] = "Fatal HW Error", +@@ -779,6 +779,55 @@ static int read_file_reset(struct seq_file *file, void *data) + return 0; + } + ++static int open_file_reset(struct inode *inode, struct file *f) ++{ ++ return single_open(f, read_file_reset, inode->i_private); ++} ++ ++static ssize_t write_file_reset(struct file *file, ++ const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath_softc *sc = file_inode(file)->i_private; ++ struct ath_hw *ah = sc->sc_ah; ++ struct ath_common *common = ath9k_hw_common(ah); ++ unsigned long val; ++ char buf[32]; ++ ssize_t len; ++ ++ len = min(count, sizeof(buf) - 1); ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ ++ buf[len] = '\0'; ++ if (kstrtoul(buf, 0, &val)) ++ return -EINVAL; ++ ++ if (val != 1) ++ return -EINVAL; ++ ++ /* avoid rearming hw_reset_work on shutdown */ ++ mutex_lock(&sc->mutex); ++ if (test_bit(ATH_OP_INVALID, &common->op_flags)) { ++ mutex_unlock(&sc->mutex); ++ return -EBUSY; ++ } ++ ++ ath9k_queue_reset(sc, RESET_TYPE_USER); ++ mutex_unlock(&sc->mutex); ++ ++ return count; ++} ++ ++static const struct file_operations fops_reset = { ++ .read = seq_read, ++ .write = write_file_reset, ++ .open = open_file_reset, ++ .owner = THIS_MODULE, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ + void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, + struct ath_tx_status *ts, struct ath_txq *txq, + unsigned int flags) +@@ -1393,8 +1442,8 @@ int ath9k_init_debug(struct ath_hw *ah) + read_file_queues); + debugfs_create_devm_seqfile(sc->dev, "misc", sc->debug.debugfs_phy, + read_file_misc); +- debugfs_create_devm_seqfile(sc->dev, "reset", sc->debug.debugfs_phy, +- read_file_reset); ++ debugfs_create_file("reset", 0600, sc->debug.debugfs_phy, ++ sc, &fops_reset); + + ath9k_cmn_debug_recv(sc->debug.debugfs_phy, &sc->debug.stats.rxstats); + ath9k_cmn_debug_phy_err(sc->debug.debugfs_phy, &sc->debug.stats.rxstats); +diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h +index 33826aa13687..389459c04d14 100644 +--- a/drivers/net/wireless/ath/ath9k/debug.h ++++ b/drivers/net/wireless/ath/ath9k/debug.h +@@ -39,6 +39,7 @@ struct fft_sample_tlv; + #endif + + enum ath_reset_type { ++ RESET_TYPE_USER, + RESET_TYPE_BB_HANG, + RESET_TYPE_BB_WATCHDOG, + RESET_TYPE_FATAL_INT, +