mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-02 22:46:42 +07:00
ath5k: fix suspend-related oops on rmmod
Based on a patch by Elias Oltmanns, we call ath5k_init in resume even if we didn't previously open the device. Besides starting up the device unnecessarily, this also causes an oops on rmmod because mac80211 will not invoke ath5k_stop and softirqs are left running after the module has been unloaded. Add a new state bit, ATH_STAT_STARTED, to indicate that we have been started up. Reported-by: Toralf Förster <toralf.foerster@gmx.de> Signed-off-by: Elias Oltmanns <eo@nebensachen.de> Signed-off-by: Bob Copeland <me@bobcopeland.com> Cc: stable@kernel.org Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
75e3d8db53
commit
8bdd5b9c6b
@ -340,9 +340,9 @@ static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp)
|
||||
}
|
||||
|
||||
/* Interrupt handling */
|
||||
static int ath5k_init(struct ath5k_softc *sc);
|
||||
static int ath5k_init(struct ath5k_softc *sc, bool is_resume);
|
||||
static int ath5k_stop_locked(struct ath5k_softc *sc);
|
||||
static int ath5k_stop_hw(struct ath5k_softc *sc);
|
||||
static int ath5k_stop_hw(struct ath5k_softc *sc, bool is_suspend);
|
||||
static irqreturn_t ath5k_intr(int irq, void *dev_id);
|
||||
static void ath5k_tasklet_reset(unsigned long data);
|
||||
|
||||
@ -646,7 +646,7 @@ ath5k_pci_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
|
||||
ath5k_led_off(sc);
|
||||
|
||||
ath5k_stop_hw(sc);
|
||||
ath5k_stop_hw(sc, true);
|
||||
|
||||
free_irq(pdev->irq, sc);
|
||||
pci_save_state(pdev);
|
||||
@ -683,7 +683,7 @@ ath5k_pci_resume(struct pci_dev *pdev)
|
||||
goto err_no_irq;
|
||||
}
|
||||
|
||||
err = ath5k_init(sc);
|
||||
err = ath5k_init(sc, true);
|
||||
if (err)
|
||||
goto err_irq;
|
||||
ath5k_led_enable(sc);
|
||||
@ -2200,12 +2200,17 @@ ath5k_beacon_config(struct ath5k_softc *sc)
|
||||
\********************/
|
||||
|
||||
static int
|
||||
ath5k_init(struct ath5k_softc *sc)
|
||||
ath5k_init(struct ath5k_softc *sc, bool is_resume)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mutex_lock(&sc->lock);
|
||||
|
||||
if (is_resume && !test_bit(ATH_STAT_STARTED, sc->status))
|
||||
goto out_ok;
|
||||
|
||||
__clear_bit(ATH_STAT_STARTED, sc->status);
|
||||
|
||||
ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mode %d\n", sc->opmode);
|
||||
|
||||
/*
|
||||
@ -2230,12 +2235,15 @@ ath5k_init(struct ath5k_softc *sc)
|
||||
if (ret)
|
||||
goto done;
|
||||
|
||||
__set_bit(ATH_STAT_STARTED, sc->status);
|
||||
|
||||
/* Set ack to be sent at low bit-rates */
|
||||
ath5k_hw_set_ack_bitrate_high(sc->ah, false);
|
||||
|
||||
mod_timer(&sc->calib_tim, round_jiffies(jiffies +
|
||||
msecs_to_jiffies(ath5k_calinterval * 1000)));
|
||||
|
||||
out_ok:
|
||||
ret = 0;
|
||||
done:
|
||||
mmiowb();
|
||||
@ -2290,7 +2298,7 @@ ath5k_stop_locked(struct ath5k_softc *sc)
|
||||
* stop is preempted).
|
||||
*/
|
||||
static int
|
||||
ath5k_stop_hw(struct ath5k_softc *sc)
|
||||
ath5k_stop_hw(struct ath5k_softc *sc, bool is_suspend)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@ -2321,6 +2329,9 @@ ath5k_stop_hw(struct ath5k_softc *sc)
|
||||
}
|
||||
}
|
||||
ath5k_txbuf_free(sc, sc->bbuf);
|
||||
if (!is_suspend)
|
||||
__clear_bit(ATH_STAT_STARTED, sc->status);
|
||||
|
||||
mmiowb();
|
||||
mutex_unlock(&sc->lock);
|
||||
|
||||
@ -2718,12 +2729,12 @@ ath5k_reset_wake(struct ath5k_softc *sc)
|
||||
|
||||
static int ath5k_start(struct ieee80211_hw *hw)
|
||||
{
|
||||
return ath5k_init(hw->priv);
|
||||
return ath5k_init(hw->priv, false);
|
||||
}
|
||||
|
||||
static void ath5k_stop(struct ieee80211_hw *hw)
|
||||
{
|
||||
ath5k_stop_hw(hw->priv);
|
||||
ath5k_stop_hw(hw->priv, false);
|
||||
}
|
||||
|
||||
static int ath5k_add_interface(struct ieee80211_hw *hw,
|
||||
|
@ -128,11 +128,12 @@ struct ath5k_softc {
|
||||
size_t desc_len; /* size of TX/RX descriptors */
|
||||
u16 cachelsz; /* cache line size */
|
||||
|
||||
DECLARE_BITMAP(status, 4);
|
||||
DECLARE_BITMAP(status, 5);
|
||||
#define ATH_STAT_INVALID 0 /* disable hardware accesses */
|
||||
#define ATH_STAT_MRRETRY 1 /* multi-rate retry support */
|
||||
#define ATH_STAT_PROMISC 2
|
||||
#define ATH_STAT_LEDSOFT 3 /* enable LED gpio status */
|
||||
#define ATH_STAT_STARTED 4 /* opened & irqs enabled */
|
||||
|
||||
unsigned int filter_flags; /* HW flags, AR5K_RX_FILTER_* */
|
||||
unsigned int curmode; /* current phy mode */
|
||||
|
Loading…
Reference in New Issue
Block a user