From d521cd80384dccc7974c50887ef71d859213d43b Mon Sep 17 00:00:00 2001
From: nbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Date: Fri, 11 Dec 2009 02:12:19 +0000
Subject: [PATCH] madwifi: add a watchdog for software beacon alert interrupts

git-svn-id: svn://svn.openwrt.org/openwrt/trunk@18740 3c298f89-4303-0410-b956-a3cf2f4a3e73
---
 .../madwifi/patches/455-beacon_watchdog.patch | 95 +++++++++++++++++++
 1 file changed, 95 insertions(+)
 create mode 100644 package/madwifi/patches/455-beacon_watchdog.patch

diff --git a/package/madwifi/patches/455-beacon_watchdog.patch b/package/madwifi/patches/455-beacon_watchdog.patch
new file mode 100644
index 000000000..e399564df
--- /dev/null
+++ b/package/madwifi/patches/455-beacon_watchdog.patch
@@ -0,0 +1,95 @@
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -379,6 +379,7 @@ static u_int32_t ath_get_clamped_maxtxpo
+ static u_int32_t ath_set_clamped_maxtxpower(struct ath_softc *sc, 
+ 		u_int32_t new_clamped_maxtxpower);
+ 
++static void ath_bcn_timer(unsigned long arg);
+ static void ath_poll_disable(struct net_device *dev);
+ static void ath_poll_enable(struct net_device *dev);
+ static void ath_fetch_idle_time(struct ath_softc *sc);
+@@ -829,6 +830,10 @@ ath_attach(u_int16_t devid, struct net_d
+ 	sc->sc_cal_ch.function = ath_calibrate;
+ 	sc->sc_cal_ch.data = (unsigned long) dev;
+ 
++	init_timer(&sc->sc_bcntimer);
++	sc->sc_bcntimer.function = ath_bcn_timer;
++	sc->sc_bcntimer.data = (unsigned long) dev;
++
+ 	/* initialize DFS related variables */
+ 	sc->sc_dfswait = 0;
+ 	sc->sc_dfs_cac = 0;
+@@ -2704,6 +2709,7 @@ ath_stop_locked(struct net_device *dev)
+ 	DPRINTF(sc, ATH_DEBUG_RESET, "invalid=%u flags=0x%x\n",
+ 		sc->sc_invalid, dev->flags);
+ 
++	del_timer_sync(&sc->sc_bcntimer);
+ 	if (dev->flags & IFF_RUNNING) {
+ 		/*
+ 		 * Shutdown the hardware and driver:
+@@ -3006,6 +3012,7 @@ ath_reset(struct net_device *dev)
+ 	struct ieee80211_channel *c;
+ 	HAL_STATUS status;
+ 
++	del_timer_sync(&sc->sc_bcntimer);
+ 	/*
+ 	 * XXX: starting the calibration too early seems to lead to
+ 	 * problems with the beacons.
+@@ -5305,6 +5312,7 @@ ath_beacon_send(struct ath_softc *sc, in
+ 	if (ath_chan_unavail_dbgmsg(sc))
+ 		return;
+ 
++	mod_timer(&sc->sc_bcntimer, jiffies + sc->sc_bcntimer_reload);
+ 	/*
+ 	 * Check if the previous beacon has gone out.  If
+ 	 * not don't try to post another, skip this period
+@@ -5487,6 +5495,18 @@ ath_beacon_free(struct ath_softc *sc)
+ 		cleanup_ath_buf(sc, bf, BUS_DMA_TODEVICE);
+ }
+ 
++static void ath_bcn_timer(unsigned long arg)
++{
++	struct net_device *dev = (struct net_device *)arg;
++	struct ath_softc *sc = netdev_priv(dev);
++	struct ath_hal *ah = sc->sc_ah;
++
++	if (!sc->sc_beacons)
++		return;
++
++	ath_reset(dev);
++}
++
+ /*
+  * Configure the beacon and sleep timers.
+  *
+@@ -5523,6 +5543,7 @@ ath_beacon_config(struct ath_softc *sc, 
+ 	if (vap == NULL)
+ 		vap = TAILQ_FIRST(&ic->ic_vaps);   /* XXX */
+ 
++	del_timer_sync(&sc->sc_bcntimer);
+ 	ni = vap->iv_bss;
+ 
+ 	/* TSF calculation is timing critical - we don't want to be interrupted here */
+@@ -5699,6 +5720,9 @@ ath_beacon_config(struct ath_softc *sc, 
+ 			sc->sc_imask |= HAL_INT_SWBA;
+ 			ath_set_beacon_cal(sc, 1);
+ 			ath_beaconq_config(sc);
++
++			sc->sc_bcntimer_reload = msecs_to_jiffies(10 * (intval & HAL_BEACON_PERIOD));
++			mod_timer(&sc->sc_bcntimer, jiffies + sc->sc_bcntimer_reload);
+ 		} else
+ 			ath_set_beacon_cal(sc, 0);
+ 
+--- a/ath/if_athvar.h
++++ b/ath/if_athvar.h
+@@ -789,6 +789,10 @@ struct ath_softc {
+ 	u_int16_t sc_ledoff;			/* off time for current blink */
+ 	struct timer_list sc_ledtimer;		/* led off timer */
+ 
++	/* beacon watchdog timer */
++	u_int32_t sc_bcntimer_reload;
++	struct timer_list sc_bcntimer;
++
+ 	struct ATH_TQ_STRUCT sc_fataltq;	/* fatal error intr tasklet */
+ 
+ 	int sc_rxbufsize;			/* rx size based on mtu */
-- 
2.20.1