X-Git-Url: http://git.rohieb.name/openwrt.git/blobdiff_plain/87aacb3b5bb8d4da4280d421b498237032459e82..31a40f97ef54e10e2b3dc3cacb9cff436657c586:/package/madwifi/patches/389-autochannel.patch?ds=sidebyside diff --git a/package/madwifi/patches/389-autochannel.patch b/package/madwifi/patches/389-autochannel.patch index 9c77b0e54..548f09e7d 100644 --- a/package/madwifi/patches/389-autochannel.patch +++ b/package/madwifi/patches/389-autochannel.patch @@ -8,7 +8,7 @@ /* calibrate every 30 secs in steady state but check every second at first. */ static int ath_calinterval = ATH_SHORT_CALINTERVAL; -@@ -2579,6 +2580,7 @@ ath_init(struct net_device *dev) +@@ -2581,6 +2582,7 @@ ath_init(struct net_device *dev) * be followed by initialization of the appropriate bits * and then setup of the interrupt mask. */ @@ -16,10 +16,14 @@ sc->sc_curchan.channel = ic->ic_curchan->ic_freq; sc->sc_curchan.channelFlags = ath_chan2flags(ic->ic_curchan); if (!ath_hal_reset(ah, sc->sc_opmode, &sc->sc_curchan, AH_FALSE, &status)) { -@@ -2913,6 +2915,37 @@ ath_hw_check_atim(struct ath_softc *sc, +@@ -2914,6 +2916,48 @@ ath_hw_check_atim(struct ath_softc *sc, + return 0; } - ++#define AR5K_MIBC 0x0040 ++#define AR5K_MIBC_FREEZE (1 << 1) ++#define AR5K_TXFC 0x80ec ++#define AR5K_RXFC 0x80f0 +#define AR5K_RXCLEAR 0x80f4 +#define AR5K_CYCLES 0x80f8 +static void @@ -36,10 +40,15 @@ + if (!ic->ic_curchan || (ic->ic_curchan == IEEE80211_CHAN_ANYC)) + return; + ++ OS_REG_WRITE(ah, AR5K_MIBC, AR5K_MIBC_FREEZE); + rx = OS_REG_READ(ah, AR5K_RXCLEAR); + cc = OS_REG_READ(ah, AR5K_CYCLES); ++ ++ if (!cc) ++ return; ++ + if (rx > cc) -+ return; /* wraparound */ ++ return; /* should not happen */ + + if (sc->sc_last_chan) + sc->sc_last_chan->ic_idletime = 100 * (cc - rx) / cc; @@ -47,14 +56,16 @@ + + OS_REG_WRITE(ah, AR5K_RXCLEAR, 0); + OS_REG_WRITE(ah, AR5K_CYCLES, 0); ++ OS_REG_WRITE(ah, AR5K_TXFC, 0); ++ OS_REG_WRITE(ah, AR5K_RXFC, 0); ++ OS_REG_WRITE(ah, AR5K_MIBC, 0); +} +#undef AR5K_RXCLEAR +#undef AR5K_CYCLES -+ + /* * Reset the hardware w/o losing operational state. This is - * basically a more efficient way of doing ath_stop, ath_init, -@@ -2939,6 +2972,7 @@ ath_reset(struct net_device *dev) +@@ -2941,6 +2985,7 @@ ath_reset(struct net_device *dev) * Convert to a HAL channel description with the flags * constrained to reflect the current operating mode. */ @@ -62,17 +73,32 @@ c = ic->ic_curchan; sc->sc_curchan.channel = c->ic_freq; sc->sc_curchan.channelFlags = ath_chan2flags(c); -@@ -9019,6 +9053,7 @@ ath_chan_set(struct ath_softc *sc, struc +@@ -9023,6 +9068,7 @@ ath_chan_set(struct ath_softc *sc, struc u_int8_t channel_change_required = 0; struct timeval tv; -+ ath_fetch_idle_time(sc); ++ /* * Convert to a HAL channel description with * the flags constrained to reflect the current +@@ -9031,6 +9077,14 @@ ath_chan_set(struct ath_softc *sc, struc + memset(&hchan, 0, sizeof(HAL_CHANNEL)); + hchan.channel = chan->ic_freq; + hchan.channelFlags = ath_chan2flags(chan); ++ ++ /* don't do duplicate channel changes, but do ++ * store the available idle time */ ++ ath_fetch_idle_time(sc); ++ if ((sc->sc_curchan.channel == hchan.channel) && ++ (sc->sc_curchan.channelFlags == hchan.channelFlags)) ++ return 0; ++ + KASSERT(hchan.channel != 0, + ("bogus channel %u/0x%x", hchan.channel, hchan.channelFlags)); + do_gettimeofday(&tv); --- a/ath/if_athvar.h +++ b/ath/if_athvar.h -@@ -773,6 +773,7 @@ struct ath_softc { +@@ -774,6 +774,7 @@ struct ath_softc { struct ieee80211vap **sc_bslot; /* beacon xmit slots */ int sc_bnext; /* next slot for beacon xmit */ @@ -92,7 +118,7 @@ #define IEEE80211_CHAN_MAX 255 --- a/net80211/ieee80211_scan_ap.c +++ b/net80211/ieee80211_scan_ap.c -@@ -423,6 +423,19 @@ pc_cmp_rssi(struct ap_state *as, struct +@@ -417,6 +417,19 @@ pc_cmp_rssi(struct ap_state *as, struct /* This function must be invoked with locks acquired */ static int @@ -112,11 +138,112 @@ pc_cmp_samechan(struct ieee80211com *ic, struct ieee80211_channel *a, struct ieee80211_channel *b) { -@@ -455,6 +468,7 @@ pc_cmp(const void *_a, const void *_b) - return res; \ - } while (0) +@@ -451,6 +464,7 @@ pc_cmp(const void *_a, const void *_b) -+ EVALUATE_CRITERION(idletime, a, b); EVALUATE_CRITERION(radar, a, b); EVALUATE_CRITERION(keepmode, params, a, b); ++ EVALUATE_CRITERION(idletime, a, b); EVALUATE_CRITERION(sc, ic, a, b); + /* XXX: rssi useless? pick_channel evaluates it anyway */ + EVALUATE_CRITERION(rssi, params->ss->ss_priv, a, b); +@@ -519,16 +533,9 @@ pick_channel(struct ieee80211_scan_state + #endif + + best = NULL; +- best_rssi = 0xff; /* If signal is bigger than 0xff, we'd be melting. */ + + for (i = 0; i < ss_last; i++) { + c = &chans[i]; +- benefit = best_rssi - as->as_maxrssi[c->chan->ic_ieee]; +- sta_assoc = ic->ic_sta_assoc; +- +- /* Don't switch... */ +- if (benefit <= 0) +- continue; + + /* Verify channel is not marked for non-occupancy */ + if (IEEE80211_IS_CHAN_RADAR(c->chan)) +@@ -546,31 +553,8 @@ pick_channel(struct ieee80211_scan_state + break; + } + +- if (sta_assoc != 0) { +- int sl = ic->ic_cn_total - +- ic->ic_chan_nodes[c->chan->ic_ieee]; /* count */ +- if (ic->ic_sc_algorithm == IEEE80211_SC_LOOSE) { +- int sl_max = ic->ic_sc_sldg * benefit; +- sl = 1000 * sl / sta_assoc; /* permil */ +- IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, +- "%s: chan %d, dB gained: %d, " +- "STAs lost: %d permil (max %d)\n", +- __func__, c->chan->ic_ieee, +- benefit, sl, sl_max); +- if (sl > sl_max) +- continue; +- } else if (((ic->ic_sc_algorithm == +- IEEE80211_SC_TIGHT) || +- (ic->ic_sc_algorithm == +- IEEE80211_SC_STRICT)) && +- (sl > 0)) { +- /* Break the loop as the subsequent chans +- * won't be better. */ +- break; +- } +- } + best = c->chan; +- best_rssi = as->as_maxrssi[best->ic_ieee]; ++ break; + } + + if (best != NULL) { +@@ -599,6 +583,9 @@ ap_end(struct ieee80211_scan_state *ss, + ("wrong opmode %u", vap->iv_opmode)); + + ic = vap->iv_ic; ++ ++ /* record stats for the channel that was scanned last */ ++ ic->ic_set_channel(ic); + bestchan = pick_channel(ss, vap, flags); + if (bestchan == NULL) { + if (ss->ss_last > 0) { +--- a/net80211/ieee80211_scan.c ++++ b/net80211/ieee80211_scan.c +@@ -1002,20 +1002,34 @@ ieee80211_scan_add_channels(struct ieee8 + { + struct ieee80211_channel *c, *cg; + u_int modeflags; ++ int has_non_turbo = 0; + int i; + + KASSERT(mode < ARRAY_SIZE(chanflags), ("Unexpected mode %u", mode)); + modeflags = chanflags[mode]; + for (i = 0; i < ic->ic_nchans; i++) { + c = &ic->ic_channels[i]; ++ if (c->ic_flags & (IEEE80211_CHAN_TURBO | IEEE80211_CHAN_STURBO)) ++ continue; ++ ++ has_non_turbo = 1; ++ break; ++ } ++ for (i = 0; i < ic->ic_nchans; i++) { ++ c = &ic->ic_channels[i]; + if (c == NULL || isclr(ic->ic_chan_active, c->ic_ieee)) + continue; + if (c->ic_scanflags & IEEE80211_NOSCAN_SET) + continue; +- if (modeflags && +- ((c->ic_flags & IEEE80211_CHAN_ALLTURBO) != +- (modeflags & IEEE80211_CHAN_ALLTURBO))) +- continue; ++ if (modeflags) { ++ if ((c->ic_flags & IEEE80211_CHAN_ALLTURBO) != ++ (modeflags & IEEE80211_CHAN_ALLTURBO)) ++ continue; ++ } else if (has_non_turbo) { ++ if ((ss->ss_vap->iv_opmode == IEEE80211_M_HOSTAP) && ++ (c->ic_flags & (IEEE80211_CHAN_TURBO | IEEE80211_CHAN_STURBO))) ++ continue; ++ } + if (mode == IEEE80211_MODE_AUTO) { + /* + * XXX special-case 11b/g channels so we select