diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/ath/ath5k/base.c | 38 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/base.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/debug.c | 2 |
3 files changed, 24 insertions, 19 deletions
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 20328bdd138b..b290cc6c600f 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -388,7 +388,7 @@ static int ath5k_init(struct ath5k_softc *sc); | |||
388 | static int ath5k_stop_locked(struct ath5k_softc *sc); | 388 | static int ath5k_stop_locked(struct ath5k_softc *sc); |
389 | static int ath5k_stop_hw(struct ath5k_softc *sc); | 389 | static int ath5k_stop_hw(struct ath5k_softc *sc); |
390 | static irqreturn_t ath5k_intr(int irq, void *dev_id); | 390 | static irqreturn_t ath5k_intr(int irq, void *dev_id); |
391 | static void ath5k_tasklet_reset(unsigned long data); | 391 | static void ath5k_reset_work(struct work_struct *work); |
392 | 392 | ||
393 | static void ath5k_tasklet_calibrate(unsigned long data); | 393 | static void ath5k_tasklet_calibrate(unsigned long data); |
394 | 394 | ||
@@ -831,11 +831,12 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) | |||
831 | 831 | ||
832 | tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc); | 832 | tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc); |
833 | tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc); | 833 | tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc); |
834 | tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc); | ||
835 | tasklet_init(&sc->calib, ath5k_tasklet_calibrate, (unsigned long)sc); | 834 | tasklet_init(&sc->calib, ath5k_tasklet_calibrate, (unsigned long)sc); |
836 | tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc); | 835 | tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc); |
837 | tasklet_init(&sc->ani_tasklet, ath5k_tasklet_ani, (unsigned long)sc); | 836 | tasklet_init(&sc->ani_tasklet, ath5k_tasklet_ani, (unsigned long)sc); |
838 | 837 | ||
838 | INIT_WORK(&sc->reset_work, ath5k_reset_work); | ||
839 | |||
839 | ret = ath5k_eeprom_read_mac(ah, mac); | 840 | ret = ath5k_eeprom_read_mac(ah, mac); |
840 | if (ret) { | 841 | if (ret) { |
841 | ATH5K_ERR(sc, "unable to read address from EEPROM: 0x%04x\n", | 842 | ATH5K_ERR(sc, "unable to read address from EEPROM: 0x%04x\n", |
@@ -2294,8 +2295,8 @@ err_unmap: | |||
2294 | * frame contents are done as needed and the slot time is | 2295 | * frame contents are done as needed and the slot time is |
2295 | * also adjusted based on current state. | 2296 | * also adjusted based on current state. |
2296 | * | 2297 | * |
2297 | * This is called from software irq context (beacontq or restq | 2298 | * This is called from software irq context (beacontq tasklets) |
2298 | * tasklets) or user context from ath5k_beacon_config. | 2299 | * or user context from ath5k_beacon_config. |
2299 | */ | 2300 | */ |
2300 | static void | 2301 | static void |
2301 | ath5k_beacon_send(struct ath5k_softc *sc) | 2302 | ath5k_beacon_send(struct ath5k_softc *sc) |
@@ -2328,7 +2329,7 @@ ath5k_beacon_send(struct ath5k_softc *sc) | |||
2328 | sc->bmisscount); | 2329 | sc->bmisscount); |
2329 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, | 2330 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, |
2330 | "stuck beacon, resetting\n"); | 2331 | "stuck beacon, resetting\n"); |
2331 | tasklet_schedule(&sc->restq); | 2332 | ieee80211_queue_work(sc->hw, &sc->reset_work); |
2332 | } | 2333 | } |
2333 | return; | 2334 | return; |
2334 | } | 2335 | } |
@@ -2684,7 +2685,6 @@ ath5k_stop_hw(struct ath5k_softc *sc) | |||
2684 | 2685 | ||
2685 | tasklet_kill(&sc->rxtq); | 2686 | tasklet_kill(&sc->rxtq); |
2686 | tasklet_kill(&sc->txtq); | 2687 | tasklet_kill(&sc->txtq); |
2687 | tasklet_kill(&sc->restq); | ||
2688 | tasklet_kill(&sc->calib); | 2688 | tasklet_kill(&sc->calib); |
2689 | tasklet_kill(&sc->beacontq); | 2689 | tasklet_kill(&sc->beacontq); |
2690 | tasklet_kill(&sc->ani_tasklet); | 2690 | tasklet_kill(&sc->ani_tasklet); |
@@ -2737,7 +2737,7 @@ ath5k_intr(int irq, void *dev_id) | |||
2737 | */ | 2737 | */ |
2738 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, | 2738 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, |
2739 | "fatal int, resetting\n"); | 2739 | "fatal int, resetting\n"); |
2740 | tasklet_schedule(&sc->restq); | 2740 | ieee80211_queue_work(sc->hw, &sc->reset_work); |
2741 | } else if (unlikely(status & AR5K_INT_RXORN)) { | 2741 | } else if (unlikely(status & AR5K_INT_RXORN)) { |
2742 | /* | 2742 | /* |
2743 | * Receive buffers are full. Either the bus is busy or | 2743 | * Receive buffers are full. Either the bus is busy or |
@@ -2752,7 +2752,7 @@ ath5k_intr(int irq, void *dev_id) | |||
2752 | if (ah->ah_mac_srev < AR5K_SREV_AR5212) { | 2752 | if (ah->ah_mac_srev < AR5K_SREV_AR5212) { |
2753 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, | 2753 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, |
2754 | "rx overrun, resetting\n"); | 2754 | "rx overrun, resetting\n"); |
2755 | tasklet_schedule(&sc->restq); | 2755 | ieee80211_queue_work(sc->hw, &sc->reset_work); |
2756 | } | 2756 | } |
2757 | else | 2757 | else |
2758 | tasklet_schedule(&sc->rxtq); | 2758 | tasklet_schedule(&sc->rxtq); |
@@ -2799,14 +2799,6 @@ ath5k_intr(int irq, void *dev_id) | |||
2799 | return IRQ_HANDLED; | 2799 | return IRQ_HANDLED; |
2800 | } | 2800 | } |
2801 | 2801 | ||
2802 | static void | ||
2803 | ath5k_tasklet_reset(unsigned long data) | ||
2804 | { | ||
2805 | struct ath5k_softc *sc = (void *)data; | ||
2806 | |||
2807 | ath5k_reset(sc, sc->curchan); | ||
2808 | } | ||
2809 | |||
2810 | /* | 2802 | /* |
2811 | * Periodically recalibrate the PHY to account | 2803 | * Periodically recalibrate the PHY to account |
2812 | * for temperature/environment changes. | 2804 | * for temperature/environment changes. |
@@ -2830,7 +2822,7 @@ ath5k_tasklet_calibrate(unsigned long data) | |||
2830 | * to load new gain values. | 2822 | * to load new gain values. |
2831 | */ | 2823 | */ |
2832 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "calibration, resetting\n"); | 2824 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "calibration, resetting\n"); |
2833 | ath5k_reset(sc, sc->curchan); | 2825 | ieee80211_queue_work(sc->hw, &sc->reset_work); |
2834 | } | 2826 | } |
2835 | if (ath5k_hw_phy_calibrate(ah, sc->curchan)) | 2827 | if (ath5k_hw_phy_calibrate(ah, sc->curchan)) |
2836 | ATH5K_ERR(sc, "calibration of channel %u failed\n", | 2828 | ATH5K_ERR(sc, "calibration of channel %u failed\n", |
@@ -2934,6 +2926,8 @@ drop_packet: | |||
2934 | /* | 2926 | /* |
2935 | * Reset the hardware. If chan is not NULL, then also pause rx/tx | 2927 | * Reset the hardware. If chan is not NULL, then also pause rx/tx |
2936 | * and change to the given channel. | 2928 | * and change to the given channel. |
2929 | * | ||
2930 | * This should be called with sc->lock. | ||
2937 | */ | 2931 | */ |
2938 | static int | 2932 | static int |
2939 | ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan) | 2933 | ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan) |
@@ -2990,6 +2984,16 @@ err: | |||
2990 | return ret; | 2984 | return ret; |
2991 | } | 2985 | } |
2992 | 2986 | ||
2987 | static void ath5k_reset_work(struct work_struct *work) | ||
2988 | { | ||
2989 | struct ath5k_softc *sc = container_of(work, struct ath5k_softc, | ||
2990 | reset_work); | ||
2991 | |||
2992 | mutex_lock(&sc->lock); | ||
2993 | ath5k_reset(sc, sc->curchan); | ||
2994 | mutex_unlock(&sc->lock); | ||
2995 | } | ||
2996 | |||
2993 | static int ath5k_start(struct ieee80211_hw *hw) | 2997 | static int ath5k_start(struct ieee80211_hw *hw) |
2994 | { | 2998 | { |
2995 | return ath5k_init(hw->priv); | 2999 | return ath5k_init(hw->priv); |
diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h index 56221bc7c8cd..86c90f471b74 100644 --- a/drivers/net/wireless/ath/ath5k/base.h +++ b/drivers/net/wireless/ath/ath5k/base.h | |||
@@ -47,6 +47,7 @@ | |||
47 | #include <linux/if_ether.h> | 47 | #include <linux/if_ether.h> |
48 | #include <linux/leds.h> | 48 | #include <linux/leds.h> |
49 | #include <linux/rfkill.h> | 49 | #include <linux/rfkill.h> |
50 | #include <linux/workqueue.h> | ||
50 | 51 | ||
51 | #include "ath5k.h" | 52 | #include "ath5k.h" |
52 | #include "debug.h" | 53 | #include "debug.h" |
@@ -189,7 +190,7 @@ struct ath5k_softc { | |||
189 | unsigned int led_pin, /* GPIO pin for driving LED */ | 190 | unsigned int led_pin, /* GPIO pin for driving LED */ |
190 | led_on; /* pin setting for LED on */ | 191 | led_on; /* pin setting for LED on */ |
191 | 192 | ||
192 | struct tasklet_struct restq; /* reset tasklet */ | 193 | struct work_struct reset_work; /* deferred chip reset */ |
193 | 194 | ||
194 | unsigned int rxbufsize; /* rx size based on mtu */ | 195 | unsigned int rxbufsize; /* rx size based on mtu */ |
195 | struct list_head rxbuf; /* receive buffer */ | 196 | struct list_head rxbuf; /* receive buffer */ |
diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c index 8c638865c712..ebb9c237a0d5 100644 --- a/drivers/net/wireless/ath/ath5k/debug.c +++ b/drivers/net/wireless/ath/ath5k/debug.c | |||
@@ -279,7 +279,7 @@ static ssize_t write_file_reset(struct file *file, | |||
279 | { | 279 | { |
280 | struct ath5k_softc *sc = file->private_data; | 280 | struct ath5k_softc *sc = file->private_data; |
281 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "debug file triggered reset\n"); | 281 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "debug file triggered reset\n"); |
282 | tasklet_schedule(&sc->restq); | 282 | ieee80211_queue_work(sc->hw, &sc->reset_work); |
283 | return count; | 283 | return count; |
284 | } | 284 | } |
285 | 285 | ||