diff options
author | Bob Copeland <me@bobcopeland.com> | 2009-12-21 22:26:48 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-01-06 15:04:10 -0800 |
commit | d5086b90c5986d33308b1ee99546a86ff1571d07 (patch) | |
tree | 06e125541e5c4c19508e8b20f04e88060aeef51d /drivers/net | |
parent | 477702056912abc2120a18e8494fb2204ccdd958 (diff) |
ath5k: fix SWI calibration interrupt storm
commit 242ab7ad689accafd5e87ffd22b85cf1bf7fbbef upstream.
The calibration period is now invoked by triggering a software
interrupt from within the ISR by ath5k_hw_calibration_poll()
instead of via a timer.
However, the calibration interval isn't initialized before
interrupts are enabled, so we can have a situation where an
interrupt occurs before the interval is assigned, so the
interval is actually negative. As a result, the ISR will
arm a software interrupt to schedule the tasklet, and then
rearm it when the SWI is processed, and so on, leading to a
softlockup at modprobe time.
Move the initialization order around so the calibration interval
is set before interrupts are active. Another possible fix
is to schedule the tasklet directly from the poll routine,
but I think there are additional plans for the SWI.
Signed-off-by: Bob Copeland <me@bobcopeland.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/ath/ath5k/base.c | 7 |
1 files changed, 3 insertions, 4 deletions
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 95a8e232b58f..8a82c757ea63 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -2349,6 +2349,9 @@ ath5k_init(struct ath5k_softc *sc) */ ath5k_stop_locked(sc); + /* Set PHY calibration interval */ + ah->ah_cal_intval = ath5k_calinterval; + /* * The basic interface to setting the hardware in a good * state is ``reset''. On return the hardware is known to @@ -2376,10 +2379,6 @@ ath5k_init(struct ath5k_softc *sc) /* Set ack to be sent at low bit-rates */ ath5k_hw_set_ack_bitrate_high(ah, false); - - /* Set PHY calibration inteval */ - ah->ah_cal_intval = ath5k_calinterval; - ret = 0; done: mmiowb(); |