diff options
| -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 | ||
