mirror of
git://projects.qi-hardware.com/openwrt-xburst.git
synced 2025-04-21 12:27:27 +03:00
madwifi patch cleanup and stability fixes
- fix a semi-random heisenbug by replacing the previous noderef fix with a simple hack that is not 100% correct, but safe. - add ad-hoc atim fixes by bruno - add napi polling fixes by sven-ola - fix compile breakage with debug enabled git-svn-id: svn://svn.openwrt.org/openwrt/trunk@12838 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
@@ -1,43 +1,79 @@
|
||||
--- a/ath/if_ath.c
|
||||
+++ b/ath/if_ath.c
|
||||
@@ -2785,6 +2785,44 @@
|
||||
@@ -161,6 +161,7 @@
|
||||
static void ath_beacon_return(struct ath_softc *, struct ath_buf *);
|
||||
static void ath_beacon_free(struct ath_softc *);
|
||||
static void ath_beacon_config(struct ath_softc *, struct ieee80211vap *);
|
||||
+static void ath_hw_beacon_stop(struct ath_softc *sc);
|
||||
static int ath_desc_alloc(struct ath_softc *);
|
||||
static void ath_desc_free(struct ath_softc *);
|
||||
static void ath_desc_swap(struct ath_desc *);
|
||||
@@ -2783,6 +2784,72 @@
|
||||
return 1;
|
||||
}
|
||||
|
||||
+static void
|
||||
+ath_hw_beacon_stop(struct ath_softc *sc)
|
||||
+{
|
||||
+ HAL_BEACON_TIMERS btimers;
|
||||
+
|
||||
+ btimers.bt_intval = 0;
|
||||
+ btimers.bt_nexttbtt = 0;
|
||||
+ btimers.bt_nextdba = 0xffffffff;
|
||||
+ btimers.bt_nextswba = 0xffffffff;
|
||||
+ btimers.bt_nextatim = 0;
|
||||
+
|
||||
+ ath_hal_setbeacontimers(sc->sc_ah, &btimers);
|
||||
+}
|
||||
+
|
||||
+/* Fix up the ATIM window after TSF resync */
|
||||
+static int
|
||||
+ath_hw_check_atim(struct ath_softc *sc, int window)
|
||||
+ath_hw_check_atim(struct ath_softc *sc, int window, int intval)
|
||||
+{
|
||||
+#define AR5K_TIMER0_5210 0x802c /* Next beacon time register */
|
||||
+#define AR5K_TIMER0_5211 0x8028
|
||||
+#define AR5K_TIMER3_5210 0x8038 /* End of ATIM window time register */
|
||||
+#define AR5K_TIMER3_5211 0x8034
|
||||
+ struct ath_hal *ah = sc->sc_ah;
|
||||
+ int dev = sc->sc_ah->ah_macType;
|
||||
+ unsigned int nbtt, atim;
|
||||
+ int dev = ar_device(sc->devid);
|
||||
+ bool is_5210 = false;
|
||||
+
|
||||
+ /*
|
||||
+ * check if the ATIM window is still correct:
|
||||
+ * 1.) usually ATIM should be NBTT + window
|
||||
+ * 2.) nbtt already updated
|
||||
+ * 3.) nbtt already updated and has wrapped around
|
||||
+ * 4.) atim has wrapped around
|
||||
+ */
|
||||
+ switch(dev) {
|
||||
+ case 5210:
|
||||
+ nbtt = OS_REG_READ(ah, AR5K_TIMER0_5210);
|
||||
+ atim = OS_REG_READ(ah, AR5K_TIMER3_5210);
|
||||
+ if (atim - nbtt != window) {
|
||||
+ OS_REG_WRITE(ah, AR5K_TIMER3_5210, nbtt + window );
|
||||
+ return atim - nbtt;
|
||||
+ }
|
||||
+ is_5210 = true;
|
||||
+ break;
|
||||
+ case 5211:
|
||||
+ case 5212:
|
||||
+ nbtt = OS_REG_READ(ah, AR5K_TIMER0_5211);
|
||||
+ atim = OS_REG_READ(ah, AR5K_TIMER3_5211);
|
||||
+ if (atim - nbtt != window) {
|
||||
+ OS_REG_WRITE(ah, AR5K_TIMER3_5211, nbtt + window );
|
||||
+ return atim - nbtt;
|
||||
+ }
|
||||
+ break;
|
||||
+ /* NB: 5416+ doesn't do ATIM in hw */
|
||||
+ case 5416:
|
||||
+ default:
|
||||
+ break;
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ if ((atim - nbtt != window) && /* 1.) */
|
||||
+ (nbtt - atim != intval - window) && /* 2.) */
|
||||
+ ((nbtt | 0x10000) - atim != intval - window) && /* 3.) */
|
||||
+ ((atim | 0x10000) - nbtt != window)) { /* 4.) */
|
||||
+ if (is_5210)
|
||||
+ OS_REG_WRITE(ah, AR5K_TIMER3_5210, nbtt + window );
|
||||
+ else
|
||||
+ OS_REG_WRITE(ah, AR5K_TIMER3_5211, nbtt + window );
|
||||
+ return atim - nbtt;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
@@ -45,13 +81,59 @@
|
||||
/*
|
||||
* Reset the hardware w/o losing operational state. This is
|
||||
* basically a more efficient way of doing ath_stop, ath_init,
|
||||
@@ -6391,6 +6429,11 @@
|
||||
@@ -5282,6 +5349,7 @@
|
||||
u_int64_t tsf, hw_tsf;
|
||||
u_int32_t tsftu, hw_tsftu;
|
||||
u_int32_t intval, nexttbtt = 0;
|
||||
+ unsigned long flags;
|
||||
int reset_tsf = 0;
|
||||
|
||||
if (vap == NULL)
|
||||
@@ -5289,6 +5357,9 @@
|
||||
|
||||
ni = vap->iv_bss;
|
||||
|
||||
+ /* TSF calculation is timing critical - we don't want to be interrupted here */
|
||||
+ local_irq_save(flags);
|
||||
+
|
||||
hw_tsf = ath_hal_gettsf64(ah);
|
||||
tsf = le64_to_cpu(ni->ni_tstamp.tsf);
|
||||
hw_tsftu = hw_tsf >> 10;
|
||||
@@ -5478,15 +5549,27 @@
|
||||
<= ath_hal_sw_beacon_response_time)
|
||||
nexttbtt += intval;
|
||||
sc->sc_nexttbtt = nexttbtt;
|
||||
+
|
||||
+ /* stop beacons before reconfiguring the timers to avoid race
|
||||
+ * conditions. ath_hal_beaconinit will start them again */
|
||||
+ ath_hw_beacon_stop(sc);
|
||||
+
|
||||
ath_hal_beaconinit(ah, nexttbtt, intval);
|
||||
if (intval & HAL_BEACON_RESET_TSF) {
|
||||
sc->sc_last_tsf = 0;
|
||||
}
|
||||
sc->sc_bmisscount = 0;
|
||||
ath_hal_intrset(ah, sc->sc_imask);
|
||||
+
|
||||
+ if (ath_hw_check_atim(sc, 1, intval & HAL_BEACON_PERIOD)) {
|
||||
+ DPRINTF(sc, ATH_DEBUG_BEACON,
|
||||
+ "fixed atim window after beacon init\n");
|
||||
+ }
|
||||
}
|
||||
|
||||
ath_beacon_config_debug:
|
||||
+ local_irq_restore(flags);
|
||||
+
|
||||
/* We print all debug messages here, in order to preserve the
|
||||
* time critical aspect of this function */
|
||||
DPRINTF(sc, ATH_DEBUG_BEACON,
|
||||
@@ -6389,6 +6472,11 @@
|
||||
DPRINTF(sc, ATH_DEBUG_BEACON,
|
||||
"Updated beacon timers\n");
|
||||
}
|
||||
+ if ((sc->sc_opmode == IEEE80211_M_IBSS) &&
|
||||
+ IEEE80211_ADDR_EQ(ni->ni_bssid, vap->iv_bss->ni_bssid) &&
|
||||
+ ath_hw_check_atim(sc, 1)) {
|
||||
+ ath_hw_check_atim(sc, 1, vap->iv_bss->ni_intval)) {
|
||||
+ DPRINTF(sc, ATH_DEBUG_ANY, "Fixed ATIM window after beacon recv\n");
|
||||
+ }
|
||||
/* NB: Fall Through */
|
||||
|
||||
Reference in New Issue
Block a user