Changeset 3867

Show
Ignore:
Timestamp:
09/23/08 20:21:56 (4 months ago)
Author:
br1
Message:

IBSS ATIM window fixes

due to unlucky timing of beacon timer configuration (which we try to avoid) and
due to unlucky timing of local TSF updates (triggered by the reception of a
beacon with the same BSSID - something we can't avoid) the beacon timers (we
have 4) can be updated seperately, leaving one of them in the past, not beeing
updated until the timers wrap around. due to the fact that the beacon interval
does not fit into the timer period (16 bit) a whole number of times the size of
the ATIM window can get bigger than desired (we don't use ATIM right now so the
window size should always be 1).

this results in a phaenome described as "ramping" (ticket #1154) which is
actually a transmission delay, since the hardware is not allowed to transmit
data in the ATIM period.

the problem is described and discussed in length at
http://thread.gmane.org/gmane.linux.drivers.madwifi.devel/6066

since we don't know of a way to disable ATIM alltogether, the following adds
some workarounds to this problem:

1.) disable interrupts in timing critical function ath_beacon_config

2.) stop beacons before reconfiguring them

3.) check ATIM window after critical code which might have changed the timers

3a.) beacon configuration

3b.) reception of a beacon with the same BSSID. the hardware will have updated

the local TSF and this might have left one of the beacon timers in the past.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • madwifi/trunk/ath/if_ath.c

    r3809 r3867  
    53895389        u_int32_t intval, nexttbtt = 0; 
    53905390        int reset_tsf = 0; 
     5391        unsigned long irqstate; 
    53915392 
    53925393        if (vap == NULL) 
     
    53945395 
    53955396        ni = vap->iv_bss; 
     5397 
     5398        /* TSF calculation is timing critical - we don't want to be interrupted here */ 
     5399        local_irq_save(irqstate); 
    53965400 
    53975401        hw_tsf = ath_hal_gettsf64(ah); 
     
    55705574#endif 
    55715575                sc->sc_nexttbtt = nexttbtt; 
     5576 
     5577                /* stop beacons before reconfiguring the timers to avoid race 
     5578                 * conditions. ath_hal_beaconinit will start them again */ 
     5579                ath_hw_beacon_stop(sc); 
     5580 
    55725581                ath_hal_beaconinit(ah, nexttbtt, intval); 
    55735582                if (intval & HAL_BEACON_RESET_TSF) { 
     
    55765585                sc->sc_bmisscount = 0; 
    55775586                ath_hal_intrset(ah, sc->sc_imask); 
     5587 
     5588                if (ath_hw_check_atim(sc, 1, intval & HAL_BEACON_PERIOD)) { 
     5589                        DPRINTF(sc, ATH_DEBUG_BEACON, 
     5590                                "fixed atim window after beacon init\n"); 
     5591                } 
    55785592        } 
    55795593 
    55805594ath_beacon_config_debug: 
     5595 
     5596        local_irq_restore(irqstate); 
     5597 
    55815598        /* We print all debug messages here, in order to preserve the 
    55825599         * time critical aspect of this function. */ 
     
    63286345                                "Updated beacon timers\n"); 
    63296346                } 
     6347 
     6348                if (IEEE80211_ADDR_EQ(ni->ni_bssid, vap->iv_bss->ni_bssid)) { 
     6349                        if (ath_hw_check_atim(sc, 1, vap->iv_bss->ni_intval)) { 
     6350                                DPRINTF(sc, ATH_DEBUG_BEACON, 
     6351                                        "fixed atim window after beacon recv\n"); 
     6352                        } 
     6353                } 
     6354 
    63306355                /* NB: Fall Through */ 
    63316356        case IEEE80211_FC0_SUBTYPE_PROBE_RESP: 
  • madwifi/trunk/ath/if_ath_hal_extensions.c

    r3658 r3867  
    162162        return name; 
    163163} 
     164 
     165 
     166void 
     167ath_hw_beacon_stop(struct ath_softc *sc) { 
     168        HAL_BEACON_TIMERS btimers; 
     169 
     170        btimers.bt_intval = 0; 
     171        btimers.bt_nexttbtt = 0; 
     172        btimers.bt_nextdba = 0xffffffff; 
     173        btimers.bt_nextswba = 0xffffffff; 
     174        btimers.bt_nextatim = 0; 
     175 
     176        ath_hal_setbeacontimers(sc->sc_ah, &btimers); 
     177} 
     178 
     179 
     180/* 
     181 * IBSS mode: check the ATIM window size and fix it if necessary. 
     182 * 
     183 * the need for this function arises from the problem that due to unlucky timing 
     184 * of beacon timer configuration (which we try to avoid) and due to unlucky 
     185 * timing of local TSF updates (triggered by the reception of a beacon with the 
     186 * same BSSID - something we can't avoid) the beacon timers can be up updated 
     187 * seperately, leaving one of them in the past, not beeing updated until the 
     188 * timers wrap around. due to the fact that the beacon interval does not fit 
     189 * into the timer period (16 bit) a whole number of times the size of the ATIM 
     190 * window can get bigger than desired. 
     191 * 
     192 * usually we have an ATIM window size of 1 but this function is written to 
     193 * handle other window sizes as well. 
     194 */ 
     195int 
     196ath_hw_check_atim(struct ath_softc *sc, int window, int intval) 
     197{ 
     198        struct ath_hal *ah = sc->sc_ah; 
     199        unsigned int nbtt, atim, is5210 = 0; 
     200 
     201        if (ATH_SREV_FROM_AH(ah) >= AR5K_SREV_VER_AR5416) 
     202                return 0; /* AR5416+ doesn't do ATIM in HW */ 
     203 
     204        if (ATH_SREV_FROM_AH(ah) == AR5K_SREV_VER_AR5210) { 
     205                nbtt = OS_REG_READ(ah, AR5K_TIMER0_5210); 
     206                atim = OS_REG_READ(ah, AR5K_TIMER3_5210); 
     207                is5210 = 1; 
     208        } 
     209        else { 
     210                nbtt = OS_REG_READ(ah, AR5K_TIMER0_5211); 
     211                atim = OS_REG_READ(ah, AR5K_TIMER3_5211); 
     212        } 
     213 
     214        /* 
     215         * check if the ATIM window is still correct: 
     216         *   1.) usually ATIM should be NBTT + window 
     217         *   2.) nbtt already updated 
     218         *   3.) nbtt already updated and has wrapped around 
     219         *   4.) atim has wrapped around 
     220         */ 
     221        if ((atim - nbtt != window) &&                          /* 1.) */ 
     222            (nbtt - atim != intval - window) &&                 /* 2.) */ 
     223            ((nbtt | 0x10000) - atim != intval - window) &&     /* 3.) */ 
     224            ((atim | 0x10000) - nbtt != window)) {              /* 4.) */ 
     225                if (is5210) 
     226                        OS_REG_WRITE(ah, AR5K_TIMER3_5210, nbtt + window ); 
     227                else 
     228                        OS_REG_WRITE(ah, AR5K_TIMER3_5211, nbtt + window ); 
     229                return atim - nbtt; 
     230        } 
     231        return 0; 
     232} 
  • madwifi/trunk/ath/if_ath_hal_extensions.h

    r3710 r3867  
    177177#define AR5K_STA_ID1_BASE_RATE_11B      0x02000000      /* Use 11b base rate (for ACK/CTS ?) [5211+] */ 
    178178 
     179/* 
     180 * PCU beacon control register 
     181 */ 
     182#define AR5K_BEACON_5210        0x8024 
     183#define AR5K_BEACON_5211        0x8020 
     184 
     185/* 
     186 * Next beacon time register 
     187 */ 
     188#define AR5K_TIMER0_5210        0x802c 
     189#define AR5K_TIMER0_5211        0x8028 
     190/* 
     191 * Next DMA beacon alert register 
     192 */ 
     193#define AR5K_TIMER1_5210        0x8030 
     194#define AR5K_TIMER1_5211        0x802c 
     195 
     196/* 
     197 * Next software beacon alert register 
     198 */ 
     199#define AR5K_TIMER2_5210        0x8034 
     200#define AR5K_TIMER2_5211        0x8030 
     201 
     202/* 
     203 * Next ATIM window time register 
     204 */ 
     205#define AR5K_TIMER3_5210        0x8038 
     206#define AR5K_TIMER3_5211        0x8034 
     207 
    179208 
    180209enum ath5k_srev_type { 
     
    242271int ar_device(int devid); 
    243272const char * ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val); 
     273void ath_hw_beacon_stop(struct ath_softc *sc); 
     274int ath_hw_check_atim(struct ath_softc *sc, int window, int intval); 
    244275 
    245276static inline unsigned long field_width(unsigned long mask, unsigned long shift)