[source] ath9k: add stability fixes for long standing hang issues (FS#13, #34, #373, #383)

LEDE Commits lede-commits at lists.infradead.org
Wed Jan 25 08:28:43 PST 2017


nbd pushed a commit to source.git, branch lede-17.01:
https://git.lede-project.org/f9022964cfa0a44984d2efa2dafe3452899acfdf

commit f9022964cfa0a44984d2efa2dafe3452899acfdf
Author: Felix Fietkau <nbd at nbd.name>
AuthorDate: Wed Jan 25 15:32:18 2017 +0100

    ath9k: add stability fixes for long standing hang issues (FS#13, #34, #373, #383)
    
    The radio would stop communicating completely. This issue was easiest to
    trigger on AR913x devices, e.g. the TP-Link TL-WR1043ND, but other
    hardware was occasionally affected as well.
    
    The most critical issue was a race condition in disabling/enabling IRQs
    between the IRQ handler and the IRQ processing tasklet
    
    Signed-off-by: Felix Fietkau <nbd at nbd.name>
---
 ...-rename-tx_complete_work-to-hw_check_work.patch | 175 +++++++++++++++++++++
 ...9k_hw-check-if-the-chip-failed-to-wake-up.patch |  30 ++++
 .../356-ath9k-check-for-deaf-rx-path-state.patch   | 100 ++++++++++++
 ...race-condition-in-enabling-disabling-IRQs.patch | 165 +++++++++++++++++++
 .../patches/410-ath9k_allow_adhoc_and_ap.patch     |   2 +-
 .../patches/500-ath9k_eeprom_debugfs.patch         |   4 +-
 .../mac80211/patches/501-ath9k_ahb_init.patch      |   2 +-
 .../patches/512-ath9k_channelbw_debugfs.patch      |   4 +-
 .../mac80211/patches/530-ath9k_extra_leds.patch    |  20 +--
 .../mac80211/patches/542-ath9k_debugfs_diag.patch  |  10 +-
 .../patches/543-ath9k_entropy_from_adc.patch       |   6 +-
 .../544-ath9k-ar933x-usb-hang-workaround.patch     |   4 +-
 .../patches/548-ath9k_enable_gpio_chip.patch       |   2 +-
 .../patches/549-ath9k_enable_gpio_buttons.patch    |   2 +-
 ...e-all-EEPROM-fields-in-Little-Endian-form.patch |  50 +++---
 .../patches/560-ath9k_ubnt_uap_plus_hsr.patch      |   4 +-
 16 files changed, 523 insertions(+), 57 deletions(-)

diff --git a/package/kernel/mac80211/patches/354-ath9k-rename-tx_complete_work-to-hw_check_work.patch b/package/kernel/mac80211/patches/354-ath9k-rename-tx_complete_work-to-hw_check_work.patch
new file mode 100644
index 0000000..31a0277
--- /dev/null
+++ b/package/kernel/mac80211/patches/354-ath9k-rename-tx_complete_work-to-hw_check_work.patch
@@ -0,0 +1,175 @@
+From: Felix Fietkau <nbd at nbd.name>
+Date: Wed, 25 Jan 2017 12:57:05 +0100
+Subject: [PATCH] ath9k: rename tx_complete_work to hw_check_work
+
+Also include common MAC alive check. This should make the hang checks
+more reliable for modes where beacons are not sent and is used as a
+starting point for further hang check improvements
+
+Signed-off-by: Felix Fietkau <nbd at nbd.name>
+---
+
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -108,7 +108,7 @@ int ath_descdma_setup(struct ath_softc *
+ #define ATH_AGGR_MIN_QDEPTH        2
+ /* minimum h/w qdepth for non-aggregated traffic */
+ #define ATH_NON_AGGR_MIN_QDEPTH    8
+-#define ATH_TX_COMPLETE_POLL_INT   1000
++#define ATH_HW_CHECK_POLL_INT      1000
+ #define ATH_TXFIFO_DEPTH           8
+ #define ATH_TX_ERROR               0x01
+ 
+@@ -745,7 +745,7 @@ void ath9k_csa_update(struct ath_softc *
+ #define ATH_PAPRD_TIMEOUT         100 /* msecs */
+ #define ATH_PLL_WORK_INTERVAL     100
+ 
+-void ath_tx_complete_poll_work(struct work_struct *work);
++void ath_hw_check_work(struct work_struct *work);
+ void ath_reset_work(struct work_struct *work);
+ bool ath_hw_check(struct ath_softc *sc);
+ void ath_hw_pll_work(struct work_struct *work);
+@@ -1053,7 +1053,7 @@ struct ath_softc {
+ #ifdef CPTCFG_ATH9K_DEBUGFS
+ 	struct ath9k_debug debug;
+ #endif
+-	struct delayed_work tx_complete_work;
++	struct delayed_work hw_check_work;
+ 	struct delayed_work hw_pll_work;
+ 	struct timer_list sleep_timer;
+ 
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -681,6 +681,7 @@ static int ath9k_init_softc(u16 devid, s
+ 	INIT_WORK(&sc->hw_reset_work, ath_reset_work);
+ 	INIT_WORK(&sc->paprd_work, ath_paprd_calibrate);
+ 	INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work);
++	INIT_DELAYED_WORK(&sc->hw_check_work, ath_hw_check_work);
+ 
+ 	ath9k_init_channel_context(sc);
+ 
+--- a/drivers/net/wireless/ath/ath9k/link.c
++++ b/drivers/net/wireless/ath/ath9k/link.c
+@@ -20,20 +20,13 @@
+  * TX polling - checks if the TX engine is stuck somewhere
+  * and issues a chip reset if so.
+  */
+-void ath_tx_complete_poll_work(struct work_struct *work)
++static bool ath_tx_complete_check(struct ath_softc *sc)
+ {
+-	struct ath_softc *sc = container_of(work, struct ath_softc,
+-					    tx_complete_work.work);
+ 	struct ath_txq *txq;
+ 	int i;
+-	bool needreset = false;
+-
+ 
+-	if (sc->tx99_state) {
+-		ath_dbg(ath9k_hw_common(sc->sc_ah), RESET,
+-			"skip tx hung detection on tx99\n");
+-		return;
+-	}
++	if (sc->tx99_state)
++		return true;
+ 
+ 	for (i = 0; i < IEEE80211_NUM_ACS; i++) {
+ 		txq = sc->tx.txq_map[i];
+@@ -41,25 +34,36 @@ void ath_tx_complete_poll_work(struct wo
+ 		ath_txq_lock(sc, txq);
+ 		if (txq->axq_depth) {
+ 			if (txq->axq_tx_inprogress) {
+-				needreset = true;
+ 				ath_txq_unlock(sc, txq);
+-				break;
+-			} else {
+-				txq->axq_tx_inprogress = true;
++				goto reset;
+ 			}
++
++			txq->axq_tx_inprogress = true;
+ 		}
+ 		ath_txq_unlock(sc, txq);
+ 	}
+ 
+-	if (needreset) {
+-		ath_dbg(ath9k_hw_common(sc->sc_ah), RESET,
+-			"tx hung, resetting the chip\n");
+-		ath9k_queue_reset(sc, RESET_TYPE_TX_HANG);
++	return true;
++
++reset:
++	ath_dbg(ath9k_hw_common(sc->sc_ah), RESET,
++		"tx hung, resetting the chip\n");
++	ath9k_queue_reset(sc, RESET_TYPE_TX_HANG);
++	return false;
++
++}
++
++void ath_hw_check_work(struct work_struct *work)
++{
++	struct ath_softc *sc = container_of(work, struct ath_softc,
++					    hw_check_work.work);
++
++	if (!ath_hw_check(sc) ||
++	    !ath_tx_complete_check(sc))
+ 		return;
+-	}
+ 
+-	ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
+-				     msecs_to_jiffies(ATH_TX_COMPLETE_POLL_INT));
++	ieee80211_queue_delayed_work(sc->hw, &sc->hw_check_work,
++				     msecs_to_jiffies(ATH_HW_CHECK_POLL_INT));
+ }
+ 
+ /*
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -181,7 +181,7 @@ void ath9k_ps_restore(struct ath_softc *
+ static void __ath_cancel_work(struct ath_softc *sc)
+ {
+ 	cancel_work_sync(&sc->paprd_work);
+-	cancel_delayed_work_sync(&sc->tx_complete_work);
++	cancel_delayed_work_sync(&sc->hw_check_work);
+ 	cancel_delayed_work_sync(&sc->hw_pll_work);
+ 
+ #ifdef CPTCFG_ATH9K_BTCOEX_SUPPORT
+@@ -198,7 +198,8 @@ void ath_cancel_work(struct ath_softc *s
+ 
+ void ath_restart_work(struct ath_softc *sc)
+ {
+-	ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
++	ieee80211_queue_delayed_work(sc->hw, &sc->hw_check_work,
++				     ATH_HW_CHECK_POLL_INT);
+ 
+ 	if (AR_SREV_9340(sc->sc_ah) || AR_SREV_9330(sc->sc_ah))
+ 		ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work,
+@@ -2091,7 +2092,7 @@ void __ath9k_flush(struct ieee80211_hw *
+ 	int timeout;
+ 	bool drain_txq;
+ 
+-	cancel_delayed_work_sync(&sc->tx_complete_work);
++	cancel_delayed_work_sync(&sc->hw_check_work);
+ 
+ 	if (ah->ah_flags & AH_UNPLUGGED) {
+ 		ath_dbg(common, ANY, "Device has been unplugged!\n");
+@@ -2129,7 +2130,8 @@ void __ath9k_flush(struct ieee80211_hw *
+ 		ath9k_ps_restore(sc);
+ 	}
+ 
+-	ieee80211_queue_delayed_work(hw, &sc->tx_complete_work, 0);
++	ieee80211_queue_delayed_work(hw, &sc->hw_check_work,
++				     ATH_HW_CHECK_POLL_INT);
+ }
+ 
+ static bool ath9k_tx_frames_pending(struct ieee80211_hw *hw)
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -2915,8 +2915,6 @@ int ath_tx_init(struct ath_softc *sc, in
+ 		return error;
+ 	}
+ 
+-	INIT_DELAYED_WORK(&sc->tx_complete_work, ath_tx_complete_poll_work);
+-
+ 	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
+ 		error = ath_tx_edma_init(sc);
+ 
diff --git a/package/kernel/mac80211/patches/355-ath9k_hw-check-if-the-chip-failed-to-wake-up.patch b/package/kernel/mac80211/patches/355-ath9k_hw-check-if-the-chip-failed-to-wake-up.patch
new file mode 100644
index 0000000..b0cb74a
--- /dev/null
+++ b/package/kernel/mac80211/patches/355-ath9k_hw-check-if-the-chip-failed-to-wake-up.patch
@@ -0,0 +1,30 @@
+From: Felix Fietkau <nbd at nbd.name>
+Date: Wed, 25 Jan 2017 12:58:17 +0100
+Subject: [PATCH] ath9k_hw: check if the chip failed to wake up
+
+In an RFC patch, Sven Eckelmann and Simon Wunderlich reported:
+
+"QCA 802.11n chips (especially AR9330/AR9340) sometimes end up in a
+state in which a read of AR_CFG always returns 0xdeadbeef.
+This should not happen when when the power_mode of the device is
+ATH9K_PM_AWAKE."
+
+Include the check for the default register state in the existing MAC
+hang check.
+
+Signed-off-by: Felix Fietkau <nbd at nbd.name>
+---
+
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -1624,6 +1624,10 @@ bool ath9k_hw_check_alive(struct ath_hw
+ 	int count = 50;
+ 	u32 reg, last_val;
+ 
++	/* Check if chip failed to wake up */
++	if (REG_READ(ah, AR_CFG) == 0xdeadbeef)
++		return false;
++
+ 	if (AR_SREV_9300(ah))
+ 		return !ath9k_hw_detect_mac_hang(ah);
+ 
diff --git a/package/kernel/mac80211/patches/356-ath9k-check-for-deaf-rx-path-state.patch b/package/kernel/mac80211/patches/356-ath9k-check-for-deaf-rx-path-state.patch
new file mode 100644
index 0000000..347d06e
--- /dev/null
+++ b/package/kernel/mac80211/patches/356-ath9k-check-for-deaf-rx-path-state.patch
@@ -0,0 +1,100 @@
+From: Felix Fietkau <nbd at nbd.name>
+Date: Wed, 25 Jan 2017 13:00:58 +0100
+Subject: [PATCH] ath9k: check for deaf rx path state
+
+Various chips occasionally run into a state where the tx path still
+appears to be working normally, but the rx path is deaf.
+
+There is no known register signature to check for this state explicitly,
+so use the lack of rx interrupts as an indicator.
+
+This detection is prone to false positives, since a device could also
+simply be in an environment where there are no frames on the air.
+However, in this case doing a reset should be harmless since it's
+obviously not interrupting any real activity. To avoid confusion, call
+the reset counters in this case "Rx path inactive" instead of something
+like "Rx path deaf", since it may not be an indication of a real
+hardware failure.
+
+Signed-off-by: Felix Fietkau <nbd at nbd.name>
+---
+
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -1027,6 +1027,7 @@ struct ath_softc {
+ 
+ 	u8 gtt_cnt;
+ 	u32 intrstatus;
++	u32 rx_active;
+ 	u16 ps_flags; /* PS_* */
+ 	bool ps_enabled;
+ 	bool ps_idle;
+--- a/drivers/net/wireless/ath/ath9k/debug.c
++++ b/drivers/net/wireless/ath/ath9k/debug.c
+@@ -763,6 +763,7 @@ static int read_file_reset(struct seq_fi
+ 		[RESET_TYPE_BEACON_STUCK] = "Stuck Beacon",
+ 		[RESET_TYPE_MCI] = "MCI Reset",
+ 		[RESET_TYPE_CALIBRATION] = "Calibration error",
++		[RESET_TYPE_RX_INACTIVE] = "Rx path inactive",
+ 		[RESET_TX_DMA_ERROR] = "Tx DMA stop error",
+ 		[RESET_RX_DMA_ERROR] = "Rx DMA stop error",
+ 	};
+--- a/drivers/net/wireless/ath/ath9k/debug.h
++++ b/drivers/net/wireless/ath/ath9k/debug.h
+@@ -50,6 +50,7 @@ enum ath_reset_type {
+ 	RESET_TYPE_BEACON_STUCK,
+ 	RESET_TYPE_MCI,
+ 	RESET_TYPE_CALIBRATION,
++	RESET_TYPE_RX_INACTIVE,
+ 	RESET_TX_DMA_ERROR,
+ 	RESET_RX_DMA_ERROR,
+ 	__RESET_TYPE_MAX
+--- a/drivers/net/wireless/ath/ath9k/link.c
++++ b/drivers/net/wireless/ath/ath9k/link.c
+@@ -53,13 +53,27 @@ reset:
+ 
+ }
+ 
++static bool ath_rx_active_check(struct ath_softc *sc)
++{
++	if (sc->rx_active) {
++		sc->rx_active = 0;
++		return true;
++	}
++
++	ath_dbg(ath9k_hw_common(sc->sc_ah), RESET,
++		"rx path inactive, resetting the chip\n");
++	ath9k_queue_reset(sc, RESET_TYPE_RX_INACTIVE);
++	return false;
++}
++
+ void ath_hw_check_work(struct work_struct *work)
+ {
+ 	struct ath_softc *sc = container_of(work, struct ath_softc,
+ 					    hw_check_work.work);
+ 
+ 	if (!ath_hw_check(sc) ||
+-	    !ath_tx_complete_check(sc))
++	    !ath_tx_complete_check(sc) ||
++	    !ath_rx_active_check(sc))
+ 		return;
+ 
+ 	ieee80211_queue_delayed_work(sc->hw, &sc->hw_check_work,
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -269,6 +269,7 @@ static bool ath_complete_reset(struct at
+ 	}
+ 
+ 	sc->gtt_cnt = 0;
++	sc->rx_active = 1;
+ 
+ 	ath9k_hw_set_interrupts(ah);
+ 	ath9k_hw_enable_interrupts(ah);
+@@ -452,6 +453,7 @@ void ath9k_tasklet(unsigned long data)
+ 			ath_rx_tasklet(sc, 0, true);
+ 
+ 		ath_rx_tasklet(sc, 0, false);
++		sc->rx_active = 1;
+ 	}
+ 
+ 	if (status & ATH9K_INT_TX) {
diff --git a/package/kernel/mac80211/patches/357-ath9k-fix-race-condition-in-enabling-disabling-IRQs.patch b/package/kernel/mac80211/patches/357-ath9k-fix-race-condition-in-enabling-disabling-IRQs.patch
new file mode 100644
index 0000000..962a08a
--- /dev/null
+++ b/package/kernel/mac80211/patches/357-ath9k-fix-race-condition-in-enabling-disabling-IRQs.patch
@@ -0,0 +1,165 @@
+From: Felix Fietkau <nbd at nbd.name>
+Date: Wed, 25 Jan 2017 15:10:37 +0100
+Subject: [PATCH] ath9k: fix race condition in enabling/disabling IRQs
+
+The code currently relies on refcounting to disable IRQs from within the
+IRQ handler and re-enabling them again after the tasklet has run.
+
+However, due to race conditions sometimes the IRQ handler might be
+called twice, or the tasklet may not run at all (if interrupted in the
+middle of a reset).
+
+This can cause nasty imbalances in the irq-disable refcount which will
+get the driver permanently stuck until the entire radio has been stopped
+and started again (ath_reset will not recover from this).
+
+Instead of using this fragile logic, change the code to ensure that
+running the irq handler during tasklet processing is safe, and leave the
+refcount untouched.
+
+Cc: stable at vger.kernel.org
+Signed-off-by: Felix Fietkau <nbd at nbd.name>
+---
+
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -998,6 +998,7 @@ struct ath_softc {
+ 	struct survey_info *cur_survey;
+ 	struct survey_info survey[ATH9K_NUM_CHANNELS];
+ 
++	spinlock_t intr_lock;
+ 	struct tasklet_struct intr_tq;
+ 	struct tasklet_struct bcon_tasklet;
+ 	struct ath_hw *sc_ah;
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -669,6 +669,7 @@ static int ath9k_init_softc(u16 devid, s
+ 		common->bt_ant_diversity = 1;
+ 
+ 	spin_lock_init(&common->cc_lock);
++	spin_lock_init(&sc->intr_lock);
+ 	spin_lock_init(&sc->sc_serial_rw);
+ 	spin_lock_init(&sc->sc_pm_lock);
+ 	spin_lock_init(&sc->chan_lock);
+--- a/drivers/net/wireless/ath/ath9k/mac.c
++++ b/drivers/net/wireless/ath/ath9k/mac.c
+@@ -810,21 +810,12 @@ void ath9k_hw_disable_interrupts(struct
+ }
+ EXPORT_SYMBOL(ath9k_hw_disable_interrupts);
+ 
+-void ath9k_hw_enable_interrupts(struct ath_hw *ah)
++static void __ath9k_hw_enable_interrupts(struct ath_hw *ah)
+ {
+ 	struct ath_common *common = ath9k_hw_common(ah);
+ 	u32 sync_default = AR_INTR_SYNC_DEFAULT;
+ 	u32 async_mask;
+ 
+-	if (!(ah->imask & ATH9K_INT_GLOBAL))
+-		return;
+-
+-	if (!atomic_inc_and_test(&ah->intr_ref_cnt)) {
+-		ath_dbg(common, INTERRUPT, "Do not enable IER ref count %d\n",
+-			atomic_read(&ah->intr_ref_cnt));
+-		return;
+-	}
+-
+ 	if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah) ||
+ 	    AR_SREV_9561(ah))
+ 		sync_default &= ~AR_INTR_SYNC_HOST1_FATAL;
+@@ -846,6 +837,39 @@ void ath9k_hw_enable_interrupts(struct a
+ 	ath_dbg(common, INTERRUPT, "AR_IMR 0x%x IER 0x%x\n",
+ 		REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER));
+ }
++
++void ath9k_hw_resume_interrupts(struct ath_hw *ah)
++{
++	struct ath_common *common = ath9k_hw_common(ah);
++
++	if (!(ah->imask & ATH9K_INT_GLOBAL))
++		return;
++
++	if (atomic_read(&ah->intr_ref_cnt) != 0) {
++		ath_dbg(common, INTERRUPT, "Do not enable IER ref count %d\n",
++			atomic_read(&ah->intr_ref_cnt));
++		return;
++	}
++
++	__ath9k_hw_enable_interrupts(ah);
++}
++EXPORT_SYMBOL(ath9k_hw_resume_interrupts);
++
++void ath9k_hw_enable_interrupts(struct ath_hw *ah)
++{
++	struct ath_common *common = ath9k_hw_common(ah);
++
++	if (!(ah->imask & ATH9K_INT_GLOBAL))
++		return;
++
++	if (!atomic_inc_and_test(&ah->intr_ref_cnt)) {
++		ath_dbg(common, INTERRUPT, "Do not enable IER ref count %d\n",
++			atomic_read(&ah->intr_ref_cnt));
++		return;
++	}
++
++	__ath9k_hw_enable_interrupts(ah);
++}
+ EXPORT_SYMBOL(ath9k_hw_enable_interrupts);
+ 
+ void ath9k_hw_set_interrupts(struct ath_hw *ah)
+--- a/drivers/net/wireless/ath/ath9k/mac.h
++++ b/drivers/net/wireless/ath/ath9k/mac.h
+@@ -744,6 +744,7 @@ void ath9k_hw_set_interrupts(struct ath_
+ void ath9k_hw_enable_interrupts(struct ath_hw *ah);
+ void ath9k_hw_disable_interrupts(struct ath_hw *ah);
+ void ath9k_hw_kill_interrupts(struct ath_hw *ah);
++void ath9k_hw_resume_interrupts(struct ath_hw *ah);
+ 
+ void ar9002_hw_attach_mac_ops(struct ath_hw *ah);
+ 
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -375,9 +375,14 @@ void ath9k_tasklet(unsigned long data)
+ 	struct ath_common *common = ath9k_hw_common(ah);
+ 	enum ath_reset_type type;
+ 	unsigned long flags;
+-	u32 status = sc->intrstatus;
++	u32 status;
+ 	u32 rxmask;
+ 
++	spin_lock_irqsave(&sc->intr_lock, flags);
++	status = sc->intrstatus;
++	sc->intrstatus = 0;
++	spin_unlock_irqrestore(&sc->intr_lock, flags);
++
+ 	ath9k_ps_wakeup(sc);
+ 	spin_lock(&sc->sc_pcu_lock);
+ 
+@@ -480,7 +485,7 @@ void ath9k_tasklet(unsigned long data)
+ 	ath9k_btcoex_handle_interrupt(sc, status);
+ 
+ 	/* re-enable hardware interrupt */
+-	ath9k_hw_enable_interrupts(ah);
++	ath9k_hw_resume_interrupts(ah);
+ out:
+ 	spin_unlock(&sc->sc_pcu_lock);
+ 	ath9k_ps_restore(sc);
+@@ -544,7 +549,9 @@ irqreturn_t ath_isr(int irq, void *dev)
+ 		return IRQ_NONE;
+ 
+ 	/* Cache the status */
+-	sc->intrstatus = status;
++	spin_lock(&sc->intr_lock);
++	sc->intrstatus |= status;
++	spin_unlock(&sc->intr_lock);
+ 
+ 	if (status & SCHED_INTR)
+ 		sched = true;
+@@ -590,7 +597,7 @@ chip_reset:
+ 
+ 	if (sched) {
+ 		/* turn off every interrupt */
+-		ath9k_hw_disable_interrupts(ah);
++		ath9k_hw_kill_interrupts(ah);
+ 		tasklet_schedule(&sc->intr_tq);
+ 	}
+ 
diff --git a/package/kernel/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch b/package/kernel/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch
index f15c451..1d3e4be 100644
--- a/package/kernel/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch
+++ b/package/kernel/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/init.c
 +++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -775,6 +775,7 @@ static const struct ieee80211_iface_limi
+@@ -777,6 +777,7 @@ static const struct ieee80211_iface_limi
  				 BIT(NL80211_IFTYPE_AP) },
  	{ .max = 1,	.types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
  				 BIT(NL80211_IFTYPE_P2P_GO) },
diff --git a/package/kernel/mac80211/patches/500-ath9k_eeprom_debugfs.patch b/package/kernel/mac80211/patches/500-ath9k_eeprom_debugfs.patch
index f21eed1..7352343 100644
--- a/package/kernel/mac80211/patches/500-ath9k_eeprom_debugfs.patch
+++ b/package/kernel/mac80211/patches/500-ath9k_eeprom_debugfs.patch
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/debug.c
 +++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -1315,6 +1315,53 @@ void ath9k_deinit_debug(struct ath_softc
+@@ -1316,6 +1316,53 @@ void ath9k_deinit_debug(struct ath_softc
  	ath9k_cmn_spectral_deinit_debug(&sc->spec_priv);
  }
  
@@ -54,7 +54,7 @@
  int ath9k_init_debug(struct ath_hw *ah)
  {
  	struct ath_common *common = ath9k_hw_common(ah);
-@@ -1334,6 +1381,8 @@ int ath9k_init_debug(struct ath_hw *ah)
+@@ -1335,6 +1382,8 @@ int ath9k_init_debug(struct ath_hw *ah)
  	ath9k_tx99_init_debug(sc);
  	ath9k_cmn_spectral_init_debug(&sc->spec_priv, sc->debug.debugfs_phy);
  
diff --git a/package/kernel/mac80211/patches/501-ath9k_ahb_init.patch b/package/kernel/mac80211/patches/501-ath9k_ahb_init.patch
index 5c357cf..59bc5fc 100644
--- a/package/kernel/mac80211/patches/501-ath9k_ahb_init.patch
+++ b/package/kernel/mac80211/patches/501-ath9k_ahb_init.patch
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/init.c
 +++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -1078,23 +1078,23 @@ static int __init ath9k_init(void)
+@@ -1080,23 +1080,23 @@ static int __init ath9k_init(void)
  {
  	int error;
  
diff --git a/package/kernel/mac80211/patches/512-ath9k_channelbw_debugfs.patch b/package/kernel/mac80211/patches/512-ath9k_channelbw_debugfs.patch
index c98072b..d6eb5f1 100644
--- a/package/kernel/mac80211/patches/512-ath9k_channelbw_debugfs.patch
+++ b/package/kernel/mac80211/patches/512-ath9k_channelbw_debugfs.patch
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/debug.c
 +++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -1362,6 +1362,52 @@ static const struct file_operations fops
+@@ -1363,6 +1363,52 @@ static const struct file_operations fops
  	.owner = THIS_MODULE
  };
  
@@ -53,7 +53,7 @@
  int ath9k_init_debug(struct ath_hw *ah)
  {
  	struct ath_common *common = ath9k_hw_common(ah);
-@@ -1383,6 +1429,8 @@ int ath9k_init_debug(struct ath_hw *ah)
+@@ -1384,6 +1430,8 @@ int ath9k_init_debug(struct ath_hw *ah)
  
  	debugfs_create_file("eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
  			    &fops_eeprom);
diff --git a/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch b/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch
index bbef79d..061288d 100644
--- a/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch
+++ b/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch
@@ -24,7 +24,7 @@
  struct ath_softc {
  	struct ieee80211_hw *hw;
  	struct device *dev;
-@@ -1045,9 +1055,8 @@ struct ath_softc {
+@@ -1047,9 +1057,8 @@ struct ath_softc {
  	spinlock_t chan_lock;
  
  #ifdef CPTCFG_MAC80211_LEDS
@@ -103,7 +103,8 @@
 +		      GFP_KERNEL);
 +	if (!led)
 +		return -ENOMEM;
-+
+ 
+-	ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, val);
 +	led->gpio = gpio = (struct gpio_led *) (led + 1);
 +	_name = (char *) (led->gpio + 1);
 +
@@ -116,8 +117,7 @@
 +	ret = ath_add_led(sc, led);
 +	if (unlikely(ret < 0))
 +		kfree(led);
- 
--	ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, val);
++
 +	return ret;
  }
  
@@ -125,11 +125,11 @@
  {
 -	if (!sc->led_registered)
 -		return;
-+	struct ath_led *led;
- 
+-
 -	ath_led_brightness(&sc->led_cdev, LED_OFF);
 -	led_classdev_unregister(&sc->led_cdev);
--
++	struct ath_led *led;
+ 
 -	ath9k_hw_gpio_free(sc->sc_ah, sc->sc_ah->led_pin);
 +	while (!list_empty(&sc->leds)) {
 +		led = list_first_entry(&sc->leds, struct ath_led, list);
@@ -181,7 +181,7 @@
  
 --- a/drivers/net/wireless/ath/ath9k/init.c
 +++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -990,7 +990,7 @@ int ath9k_init_device(u16 devid, struct
+@@ -992,7 +992,7 @@ int ath9k_init_device(u16 devid, struct
  
  #ifdef CPTCFG_MAC80211_LEDS
  	/* must be initialized before ieee80211_register_hw */
@@ -192,7 +192,7 @@
  #endif
 --- a/drivers/net/wireless/ath/ath9k/debug.c
 +++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -1407,6 +1407,61 @@ static const struct file_operations fops
+@@ -1408,6 +1408,61 @@ static const struct file_operations fops
  	.llseek = default_llseek,
  };
  
@@ -254,7 +254,7 @@
  
  int ath9k_init_debug(struct ath_hw *ah)
  {
-@@ -1431,6 +1486,10 @@ int ath9k_init_debug(struct ath_hw *ah)
+@@ -1432,6 +1487,10 @@ int ath9k_init_debug(struct ath_hw *ah)
  			    &fops_eeprom);
  	debugfs_create_file("chanbw", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
  			    sc, &fops_chanbw);
diff --git a/package/kernel/mac80211/patches/542-ath9k_debugfs_diag.patch b/package/kernel/mac80211/patches/542-ath9k_debugfs_diag.patch
index 08acc0e..ea73e6a 100644
--- a/package/kernel/mac80211/patches/542-ath9k_debugfs_diag.patch
+++ b/package/kernel/mac80211/patches/542-ath9k_debugfs_diag.patch
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/debug.c
 +++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -1463,6 +1463,50 @@ static const struct file_operations fops
+@@ -1464,6 +1464,50 @@ static const struct file_operations fops
  #endif
  
  
@@ -51,7 +51,7 @@
  int ath9k_init_debug(struct ath_hw *ah)
  {
  	struct ath_common *common = ath9k_hw_common(ah);
-@@ -1490,6 +1534,8 @@ int ath9k_init_debug(struct ath_hw *ah)
+@@ -1491,6 +1535,8 @@ int ath9k_init_debug(struct ath_hw *ah)
  	debugfs_create_file("gpio_led", S_IWUSR,
  			   sc->debug.debugfs_phy, sc, &fops_gpio_led);
  #endif
@@ -94,7 +94,7 @@
  struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah,
 --- a/drivers/net/wireless/ath/ath9k/hw.c
 +++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -1838,6 +1838,20 @@ u32 ath9k_hw_get_tsf_offset(struct times
+@@ -1842,6 +1842,20 @@ u32 ath9k_hw_get_tsf_offset(struct times
  }
  EXPORT_SYMBOL(ath9k_hw_get_tsf_offset);
  
@@ -115,7 +115,7 @@
  int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
  		   struct ath9k_hw_cal_data *caldata, bool fastcc)
  {
-@@ -2046,6 +2060,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+@@ -2050,6 +2064,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
  		ar9003_hw_disable_phy_restart(ah);
  
  	ath9k_hw_apply_gpio_override(ah);
@@ -125,7 +125,7 @@
  		REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON);
 --- a/drivers/net/wireless/ath/ath9k/main.c
 +++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -533,6 +533,11 @@ irqreturn_t ath_isr(int irq, void *dev)
+@@ -541,6 +541,11 @@ irqreturn_t ath_isr(int irq, void *dev)
  	if (test_bit(ATH_OP_HW_RESET, &common->op_flags))
  		return IRQ_HANDLED;
  
diff --git a/package/kernel/mac80211/patches/543-ath9k_entropy_from_adc.patch b/package/kernel/mac80211/patches/543-ath9k_entropy_from_adc.patch
index 7782479..bca23d3 100644
--- a/package/kernel/mac80211/patches/543-ath9k_entropy_from_adc.patch
+++ b/package/kernel/mac80211/patches/543-ath9k_entropy_from_adc.patch
@@ -55,7 +55,7 @@
  	ops->spectral_scan_config = ar9003_hw_spectral_scan_config;
 --- a/drivers/net/wireless/ath/ath9k/init.c
 +++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -763,7 +763,8 @@ static void ath9k_init_txpower_limits(st
+@@ -765,7 +765,8 @@ static void ath9k_init_txpower_limits(st
  	if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
  		ath9k_init_band_txpower(sc, NL80211_BAND_5GHZ);
  
@@ -65,7 +65,7 @@
  }
  
  static const struct ieee80211_iface_limit if_limits[] = {
-@@ -950,6 +951,18 @@ static void ath9k_set_hw_capab(struct at
+@@ -952,6 +953,18 @@ static void ath9k_set_hw_capab(struct at
  	SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
  }
  
@@ -84,7 +84,7 @@
  int ath9k_init_device(u16 devid, struct ath_softc *sc,
  		    const struct ath_bus_ops *bus_ops)
  {
-@@ -995,6 +1008,8 @@ int ath9k_init_device(u16 devid, struct
+@@ -997,6 +1010,8 @@ int ath9k_init_device(u16 devid, struct
  		ARRAY_SIZE(ath9k_tpt_blink));
  #endif
  
diff --git a/package/kernel/mac80211/patches/544-ath9k-ar933x-usb-hang-workaround.patch b/package/kernel/mac80211/patches/544-ath9k-ar933x-usb-hang-workaround.patch
index 200a3a2..680bb6d 100644
--- a/package/kernel/mac80211/patches/544-ath9k-ar933x-usb-hang-workaround.patch
+++ b/package/kernel/mac80211/patches/544-ath9k-ar933x-usb-hang-workaround.patch
@@ -40,7 +40,7 @@
  	return true;
  }
  
-@@ -1816,8 +1835,14 @@ static int ath9k_hw_do_fastcc(struct ath
+@@ -1820,8 +1839,14 @@ static int ath9k_hw_do_fastcc(struct ath
  	if (AR_SREV_9271(ah))
  		ar9002_hw_load_ani_reg(ah, chan);
  
@@ -55,7 +55,7 @@
  	return -EINVAL;
  }
  
-@@ -2071,6 +2096,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+@@ -2075,6 +2100,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st
  		ath9k_hw_set_radar_params(ah);
  	}
  
diff --git a/package/kernel/mac80211/patches/548-ath9k_enable_gpio_chip.patch b/package/kernel/mac80211/patches/548-ath9k_enable_gpio_chip.patch
index 666622d..0b9b7f3 100644
--- a/package/kernel/mac80211/patches/548-ath9k_enable_gpio_chip.patch
+++ b/package/kernel/mac80211/patches/548-ath9k_enable_gpio_chip.patch
@@ -33,7 +33,7 @@ Signed-off-by: Felix Fietkau <nbd at nbd.name>
  struct ath_softc {
  	struct ieee80211_hw *hw;
  	struct device *dev;
-@@ -1057,6 +1066,9 @@ struct ath_softc {
+@@ -1059,6 +1068,9 @@ struct ath_softc {
  #ifdef CPTCFG_MAC80211_LEDS
  	const char *led_default_trigger;
  	struct list_head leds;
diff --git a/package/kernel/mac80211/patches/549-ath9k_enable_gpio_buttons.patch b/package/kernel/mac80211/patches/549-ath9k_enable_gpio_buttons.patch
index b8dd263..0a26699 100644
--- a/package/kernel/mac80211/patches/549-ath9k_enable_gpio_buttons.patch
+++ b/package/kernel/mac80211/patches/549-ath9k_enable_gpio_buttons.patch
@@ -10,7 +10,7 @@ Signed-off-by: Felix Fietkau <nbd at nbd.name>
 ---
 --- a/drivers/net/wireless/ath/ath9k/ath9k.h
 +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -1068,6 +1068,7 @@ struct ath_softc {
+@@ -1070,6 +1070,7 @@ struct ath_softc {
  	struct list_head leds;
  #ifdef CONFIG_GPIOLIB
  	struct ath9k_gpio_chip *gpiochip;
diff --git a/package/kernel/mac80211/patches/556-ath9k-define-all-EEPROM-fields-in-Little-Endian-form.patch b/package/kernel/mac80211/patches/556-ath9k-define-all-EEPROM-fields-in-Little-Endian-form.patch
index 04714f8..292ea8a 100644
--- a/package/kernel/mac80211/patches/556-ath9k-define-all-EEPROM-fields-in-Little-Endian-form.patch
+++ b/package/kernel/mac80211/patches/556-ath9k-define-all-EEPROM-fields-in-Little-Endian-form.patch
@@ -349,16 +349,6 @@ Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
 -
 -		integer = swab32(eep->modalHeader.antCtrlCommon);
 -		eep->modalHeader.antCtrlCommon = integer;
--
--		for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) {
--			integer = swab32(eep->modalHeader.antCtrlChain[i]);
--			eep->modalHeader.antCtrlChain[i] = integer;
--		}
--
--		for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
--			word = swab16(eep->modalHeader.spurChans[i].spurChan);
--			eep->modalHeader.spurChans[i].spurChan = word;
--		}
 +		EEPROM_FIELD_SWAB16(eep->baseEepHeader.length);
 +		EEPROM_FIELD_SWAB16(eep->baseEepHeader.checksum);
 +		EEPROM_FIELD_SWAB16(eep->baseEepHeader.version);
@@ -368,10 +358,18 @@ Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
 +		EEPROM_FIELD_SWAB16(eep->baseEepHeader.blueToothOptions);
 +		EEPROM_FIELD_SWAB16(eep->baseEepHeader.deviceCap);
 +		EEPROM_FIELD_SWAB32(eep->modalHeader.antCtrlCommon);
-+
+ 
+-		for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) {
+-			integer = swab32(eep->modalHeader.antCtrlChain[i]);
+-			eep->modalHeader.antCtrlChain[i] = integer;
+-		}
 +		for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++)
 +			EEPROM_FIELD_SWAB32(eep->modalHeader.antCtrlChain[i]);
-+
+ 
+-		for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
+-			word = swab16(eep->modalHeader.spurChans[i].spurChan);
+-			eep->modalHeader.spurChans[i].spurChan = word;
+-		}
 +		for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++)
 +			EEPROM_FIELD_SWAB16(
 +				eep->modalHeader.spurChans[i].spurChan);
@@ -542,16 +540,6 @@ Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
 -
 -		integer = swab32(eep->modalHeader.antCtrlCommon);
 -		eep->modalHeader.antCtrlCommon = integer;
--
--		for (i = 0; i < AR9287_MAX_CHAINS; i++) {
--			integer = swab32(eep->modalHeader.antCtrlChain[i]);
--			eep->modalHeader.antCtrlChain[i] = integer;
--		}
--
--		for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
--			word = swab16(eep->modalHeader.spurChans[i].spurChan);
--			eep->modalHeader.spurChans[i].spurChan = word;
--		}
 +		EEPROM_FIELD_SWAB16(eep->baseEepHeader.length);
 +		EEPROM_FIELD_SWAB16(eep->baseEepHeader.checksum);
 +		EEPROM_FIELD_SWAB16(eep->baseEepHeader.version);
@@ -561,10 +549,18 @@ Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
 +		EEPROM_FIELD_SWAB16(eep->baseEepHeader.blueToothOptions);
 +		EEPROM_FIELD_SWAB16(eep->baseEepHeader.deviceCap);
 +		EEPROM_FIELD_SWAB32(eep->modalHeader.antCtrlCommon);
-+
+ 
+-		for (i = 0; i < AR9287_MAX_CHAINS; i++) {
+-			integer = swab32(eep->modalHeader.antCtrlChain[i]);
+-			eep->modalHeader.antCtrlChain[i] = integer;
+-		}
 +		for (i = 0; i < AR9287_MAX_CHAINS; i++)
 +			EEPROM_FIELD_SWAB32(eep->modalHeader.antCtrlChain[i]);
-+
+ 
+-		for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
+-			word = swab16(eep->modalHeader.spurChans[i].spurChan);
+-			eep->modalHeader.spurChans[i].spurChan = word;
+-		}
 +		for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++)
 +			EEPROM_FIELD_SWAB16(
 +				eep->modalHeader.spurChans[i].spurChan);
@@ -716,8 +712,7 @@ Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
  	if (need_swap) {
 -		u32 integer, j;
 -		u16 word;
-+		u32 j;
- 
+-
 -		word = swab16(eep->baseEepHeader.length);
 -		eep->baseEepHeader.length = word;
 -
@@ -738,7 +733,8 @@ Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
 -
 -		word = swab16(eep->baseEepHeader.blueToothOptions);
 -		eep->baseEepHeader.blueToothOptions = word;
--
++		u32 j;
+ 
 -		word = swab16(eep->baseEepHeader.deviceCap);
 -		eep->baseEepHeader.deviceCap = word;
 +		EEPROM_FIELD_SWAB16(eep->baseEepHeader.length);
diff --git a/package/kernel/mac80211/patches/560-ath9k_ubnt_uap_plus_hsr.patch b/package/kernel/mac80211/patches/560-ath9k_ubnt_uap_plus_hsr.patch
index 7237492..51fe1bd 100644
--- a/package/kernel/mac80211/patches/560-ath9k_ubnt_uap_plus_hsr.patch
+++ b/package/kernel/mac80211/patches/560-ath9k_ubnt_uap_plus_hsr.patch
@@ -343,7 +343,7 @@
  
  u8 ath9k_parse_mpdudensity(u8 mpdudensity)
  {
-@@ -652,6 +654,7 @@ void ath_reset_work(struct work_struct *
+@@ -662,6 +664,7 @@ void ath_reset_work(struct work_struct *
  static int ath9k_start(struct ieee80211_hw *hw)
  {
  	struct ath_softc *sc = hw->priv;
@@ -351,7 +351,7 @@
  	struct ath_hw *ah = sc->sc_ah;
  	struct ath_common *common = ath9k_hw_common(ah);
  	struct ieee80211_channel *curchan = sc->cur_chan->chandef.chan;
-@@ -730,6 +733,11 @@ static int ath9k_start(struct ieee80211_
+@@ -740,6 +743,11 @@ static int ath9k_start(struct ieee80211_
  					  AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
  	}
  



More information about the lede-commits mailing list