| 1 | --- a/ath/if_ath.c |
| 2 | +++ b/ath/if_ath.c |
| 3 | @@ -379,6 +379,7 @@ static u_int32_t ath_get_clamped_maxtxpo |
| 4 | static u_int32_t ath_set_clamped_maxtxpower(struct ath_softc *sc, |
| 5 | u_int32_t new_clamped_maxtxpower); |
| 6 | |
| 7 | +static void ath_bcn_timer(unsigned long arg); |
| 8 | static void ath_poll_disable(struct net_device *dev); |
| 9 | static void ath_poll_enable(struct net_device *dev); |
| 10 | static void ath_fetch_idle_time(struct ath_softc *sc); |
| 11 | @@ -829,6 +830,10 @@ ath_attach(u_int16_t devid, struct net_d |
| 12 | sc->sc_cal_ch.function = ath_calibrate; |
| 13 | sc->sc_cal_ch.data = (unsigned long) dev; |
| 14 | |
| 15 | + init_timer(&sc->sc_bcntimer); |
| 16 | + sc->sc_bcntimer.function = ath_bcn_timer; |
| 17 | + sc->sc_bcntimer.data = (unsigned long) dev; |
| 18 | + |
| 19 | /* initialize DFS related variables */ |
| 20 | sc->sc_dfswait = 0; |
| 21 | sc->sc_dfs_cac = 0; |
| 22 | @@ -2704,6 +2709,7 @@ ath_stop_locked(struct net_device *dev) |
| 23 | DPRINTF(sc, ATH_DEBUG_RESET, "invalid=%u flags=0x%x\n", |
| 24 | sc->sc_invalid, dev->flags); |
| 25 | |
| 26 | + del_timer_sync(&sc->sc_bcntimer); |
| 27 | if (dev->flags & IFF_RUNNING) { |
| 28 | /* |
| 29 | * Shutdown the hardware and driver: |
| 30 | @@ -3006,6 +3012,7 @@ ath_reset(struct net_device *dev) |
| 31 | struct ieee80211_channel *c; |
| 32 | HAL_STATUS status; |
| 33 | |
| 34 | + del_timer_sync(&sc->sc_bcntimer); |
| 35 | /* |
| 36 | * XXX: starting the calibration too early seems to lead to |
| 37 | * problems with the beacons. |
| 38 | @@ -5305,6 +5312,7 @@ ath_beacon_send(struct ath_softc *sc, in |
| 39 | if (ath_chan_unavail_dbgmsg(sc)) |
| 40 | return; |
| 41 | |
| 42 | + mod_timer(&sc->sc_bcntimer, jiffies + sc->sc_bcntimer_reload); |
| 43 | /* |
| 44 | * Check if the previous beacon has gone out. If |
| 45 | * not don't try to post another, skip this period |
| 46 | @@ -5487,6 +5495,18 @@ ath_beacon_free(struct ath_softc *sc) |
| 47 | cleanup_ath_buf(sc, bf, BUS_DMA_TODEVICE); |
| 48 | } |
| 49 | |
| 50 | +static void ath_bcn_timer(unsigned long arg) |
| 51 | +{ |
| 52 | + struct net_device *dev = (struct net_device *)arg; |
| 53 | + struct ath_softc *sc = netdev_priv(dev); |
| 54 | + struct ath_hal *ah = sc->sc_ah; |
| 55 | + |
| 56 | + if (!sc->sc_beacons) |
| 57 | + return; |
| 58 | + |
| 59 | + ath_reset(dev); |
| 60 | +} |
| 61 | + |
| 62 | /* |
| 63 | * Configure the beacon and sleep timers. |
| 64 | * |
| 65 | @@ -5523,6 +5543,7 @@ ath_beacon_config(struct ath_softc *sc, |
| 66 | if (vap == NULL) |
| 67 | vap = TAILQ_FIRST(&ic->ic_vaps); /* XXX */ |
| 68 | |
| 69 | + del_timer_sync(&sc->sc_bcntimer); |
| 70 | ni = vap->iv_bss; |
| 71 | |
| 72 | /* TSF calculation is timing critical - we don't want to be interrupted here */ |
| 73 | @@ -5699,6 +5720,9 @@ ath_beacon_config(struct ath_softc *sc, |
| 74 | sc->sc_imask |= HAL_INT_SWBA; |
| 75 | ath_set_beacon_cal(sc, 1); |
| 76 | ath_beaconq_config(sc); |
| 77 | + |
| 78 | + sc->sc_bcntimer_reload = msecs_to_jiffies(10 * (intval & HAL_BEACON_PERIOD)); |
| 79 | + mod_timer(&sc->sc_bcntimer, jiffies + sc->sc_bcntimer_reload); |
| 80 | } else |
| 81 | ath_set_beacon_cal(sc, 0); |
| 82 | |
| 83 | --- a/ath/if_athvar.h |
| 84 | +++ b/ath/if_athvar.h |
| 85 | @@ -789,6 +789,10 @@ struct ath_softc { |
| 86 | u_int16_t sc_ledoff; /* off time for current blink */ |
| 87 | struct timer_list sc_ledtimer; /* led off timer */ |
| 88 | |
| 89 | + /* beacon watchdog timer */ |
| 90 | + u_int32_t sc_bcntimer_reload; |
| 91 | + struct timer_list sc_bcntimer; |
| 92 | + |
| 93 | struct ATH_TQ_STRUCT sc_fataltq; /* fatal error intr tasklet */ |
| 94 | |
| 95 | int sc_rxbufsize; /* rx size based on mtu */ |
| 96 | |