From: Felix Fietkau Date: Sun, 1 Jun 2008 03:00:59 +0000 (+0000) Subject: madwifi: clean up scanning code, add support for changing scan lists X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=c05f60e0d0c4f57b99e21982f4bff5d385d073d0;p=openwrt%2Fstaging%2Fdangole.git madwifi: clean up scanning code, add support for changing scan lists SVN-Revision: 11315 --- diff --git a/package/madwifi/patches/351-scanlist.patch b/package/madwifi/patches/351-scanlist.patch new file mode 100644 index 0000000000..87ef5a97c4 --- /dev/null +++ b/package/madwifi/patches/351-scanlist.patch @@ -0,0 +1,890 @@ +Index: madwifi-trunk-r3314/net80211/ieee80211_scan_sta.c +=================================================================== +--- madwifi-trunk-r3314.orig/net80211/ieee80211_scan_sta.c 2008-06-01 03:41:58.000000000 +0200 ++++ madwifi-trunk-r3314/net80211/ieee80211_scan_sta.c 2008-06-01 03:42:18.000000000 +0200 +@@ -317,147 +317,6 @@ + #undef ISPROBE + } + +-static struct ieee80211_channel * +-find11gchannel(struct ieee80211com *ic, int i, int freq) +-{ +- struct ieee80211_channel *c; +- int j; +- +- /* +- * The normal ordering in the channel list is b channel +- * immediately followed by g so optimize the search for +- * this. We'll still do a full search just in case. +- */ +- for (j = i+1; j < ic->ic_nchans; j++) { +- c = &ic->ic_channels[j]; +- if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c)) +- return c; +- } +- for (j = 0; j < i; j++) { +- c = &ic->ic_channels[j]; +- if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c)) +- return c; +- } +- return NULL; +-} +-static const u_int chanflags[] = { +- IEEE80211_CHAN_B, /* IEEE80211_MODE_AUTO */ +- IEEE80211_CHAN_A, /* IEEE80211_MODE_11A */ +- IEEE80211_CHAN_B, /* IEEE80211_MODE_11B */ +- IEEE80211_CHAN_PUREG, /* IEEE80211_MODE_11G */ +- IEEE80211_CHAN_FHSS, /* IEEE80211_MODE_FH */ +- IEEE80211_CHAN_A, /* IEEE80211_MODE_TURBO_A */ /* for turbo mode look for AP in normal channel */ +- IEEE80211_CHAN_PUREG, /* IEEE80211_MODE_TURBO_G */ +- IEEE80211_CHAN_ST, /* IEEE80211_MODE_TURBO_STATIC_A */ +-}; +- +-static void +-add_channels(struct ieee80211com *ic, +- struct ieee80211_scan_state *ss, +- enum ieee80211_phymode mode, const u_int16_t freq[], int nfreq) +-{ +- struct ieee80211_channel *c, *cg; +- u_int modeflags; +- int i; +- +- KASSERT(mode < ARRAY_SIZE(chanflags), ("Unexpected mode %u", mode)); +- modeflags = chanflags[mode]; +- for (i = 0; i < nfreq; i++) { +- c = ieee80211_find_channel(ic, freq[i], modeflags); +- if (c == NULL || isclr(ic->ic_chan_active, c->ic_ieee)) +- continue; +- if (mode == IEEE80211_MODE_AUTO) { +- /* +- * XXX special-case 11b/g channels so we select +- * the g channel if both are present. +- */ +- if (IEEE80211_IS_CHAN_B(c) && +- (cg = find11gchannel(ic, i, c->ic_freq)) != NULL) +- c = cg; +- } +- if (ss->ss_last >= IEEE80211_SCAN_MAX) +- break; +- ss->ss_chans[ss->ss_last++] = c; +- } +-} +- +-static const u_int16_t rcl1[] = /* 8 FCC channel: 52, 56, 60, 64, 36, 40, 44, 48 */ +-{ 5260, 5280, 5300, 5320, 5180, 5200, 5220, 5240 }; +-static const u_int16_t rcl2[] = /* 4 MKK channels: 34, 38, 42, 46 */ +-{ 5170, 5190, 5210, 5230 }; +-static const u_int16_t rcl3[] = /* 2.4Ghz ch: 1,6,11,7,13 */ +-{ 2412, 2437, 2462, 2442, 2472 }; +-static const u_int16_t rcl4[] = /* 5 FCC channel: 149, 153, 161, 165 */ +-{ 5745, 5765, 5785, 5805, 5825 }; +-static const u_int16_t rcl7[] = /* 11 ETSI channel: 100,104,108,112,116,120,124,128,132,136,140 */ +-{ 5500, 5520, 5540, 5560, 5580, 5600, 5620, 5640, 5660, 5680, 5700 }; +-static const u_int16_t rcl8[] = /* 2.4Ghz ch: 2,3,4,5,8,9,10,12 */ +-{ 2417, 2422, 2427, 2432, 2447, 2452, 2457, 2467 }; +-static const u_int16_t rcl9[] = /* 2.4Ghz ch: 14 */ +-{ 2484 }; +-static const u_int16_t rcl10[] = /* Added Korean channels 2312-2372 */ +-{ 2312, 2317, 2322, 2327, 2332, 2337, 2342, 2347, 2352, 2357, 2362, 2367, 2372 }; +-static const u_int16_t rcl11[] = /* Added Japan channels in 4.9/5.0 spectrum */ +-{ 5040, 5060, 5080, 4920, 4940, 4960, 4980 }; +-#ifdef ATH_TURBO_SCAN +-static const u_int16_t rcl5[] = /* 3 static turbo channels */ +-{ 5210, 5250, 5290 }; +-static const u_int16_t rcl6[] = /* 2 static turbo channels */ +-{ 5760, 5800 }; +-static const u_int16_t rcl6x[] = /* 4 FCC3 turbo channels */ +-{ 5540, 5580, 5620, 5660 }; +-static const u_int16_t rcl12[] = /* 2.4Ghz Turbo channel 6 */ +-{ 2437 }; +-static const u_int16_t rcl13[] = /* dynamic Turbo channels */ +-{ 5200, 5240, 5280, 5765, 5805 }; +-#endif /* ATH_TURBO_SCAN */ +- +-struct scanlist { +- u_int16_t mode; +- u_int16_t count; +- const u_int16_t *list; +-}; +- +-#define IEEE80211_MODE_TURBO_STATIC_A IEEE80211_MODE_MAX +-#define X(a) .count = sizeof(a)/sizeof(a[0]), .list = a +- +-static const struct scanlist staScanTable[] = { +- { IEEE80211_MODE_11B, X(rcl3) }, +- { IEEE80211_MODE_11A, X(rcl1) }, +- { IEEE80211_MODE_11A, X(rcl2) }, +- { IEEE80211_MODE_11B, X(rcl8) }, +- { IEEE80211_MODE_11B, X(rcl9) }, +- { IEEE80211_MODE_11A, X(rcl4) }, +-#ifdef ATH_TURBO_SCAN +- { IEEE80211_MODE_TURBO_STATIC_A, X(rcl5) }, +- { IEEE80211_MODE_TURBO_STATIC_A, X(rcl6) }, +- { IEEE80211_MODE_TURBO_A, X(rcl6x) }, +- { IEEE80211_MODE_TURBO_A, X(rcl13) }, +-#endif /* ATH_TURBO_SCAN */ +- { IEEE80211_MODE_11A, X(rcl7) }, +- { IEEE80211_MODE_11B, X(rcl10) }, +- { IEEE80211_MODE_11A, X(rcl11) }, +-#ifdef ATH_TURBO_SCAN +- { IEEE80211_MODE_TURBO_G, X(rcl12) }, +-#endif /* ATH_TURBO_SCAN */ +- { .list = NULL } +-}; +- +-#undef X +- +-static int +-checktable(const struct scanlist *scan, const struct ieee80211_channel *c) +-{ +- int i; +- +- for (; scan->list != NULL; scan++) { +- for (i = 0; i < scan->count; i++) +- if (scan->list[i] == c->ic_freq) +- return 1; +- } +- return 0; +-} +- + /* + * Start a station-mode scan by populating the channel list. + */ +@@ -466,81 +325,14 @@ + { + struct ieee80211com *ic = vap->iv_ic; + struct sta_table *st = ss->ss_priv; +- const struct scanlist *scan; + enum ieee80211_phymode mode; + struct ieee80211_channel *c; + int i; + + ss->ss_last = 0; +- /* +- * Use the table of ordered channels to construct the list +- * of channels for scanning. Any channels in the ordered +- * list not in the master list will be discarded. +- */ +- for (scan = staScanTable; scan->list != NULL; scan++) { +- mode = scan->mode; +- if (vap->iv_des_mode != IEEE80211_MODE_AUTO) { +- /* +- * If a desired mode was specified, scan only +- * channels that satisfy that constraint. +- */ +- if (vap->iv_des_mode != mode) { +- /* +- * The scan table marks 2.4Ghz channels as b +- * so if the desired mode is 11g, then use +- * the 11b channel list but upgrade the mode. +- */ +- if (vap->iv_des_mode != IEEE80211_MODE_11G || +- mode != IEEE80211_MODE_11B) +- continue; +- mode = IEEE80211_MODE_11G; /* upgrade */ +- } +- } else { +- /* +- * This lets ieee80211_scan_add_channels +- * upgrade an 11b channel to 11g if available. +- */ +- if (mode == IEEE80211_MODE_11B) +- mode = IEEE80211_MODE_AUTO; +- } +- /* XR does not operate on turbo channels */ +- if ((vap->iv_flags & IEEE80211_F_XR) && +- (mode == IEEE80211_MODE_TURBO_A || +- mode == IEEE80211_MODE_TURBO_G)) +- continue; +- /* +- * Add the list of the channels; any that are not +- * in the master channel list will be discarded. +- */ +- add_channels(ic, ss, mode, scan->list, scan->count); +- } +- +- /* +- * Add the channels from the ic (from HAL) that are not present +- * in the staScanTable. +- */ +- for (i = 0; i < ic->ic_nchans; i++) { +- c = &ic->ic_channels[i]; +- /* +- * scan dynamic turbo channels in normal mode. +- */ +- if (IEEE80211_IS_CHAN_DTURBO(c)) +- continue; +- mode = ieee80211_chan2mode(c); +- if (vap->iv_des_mode != IEEE80211_MODE_AUTO) { +- /* +- * If a desired mode was specified, scan only +- * channels that satisfy that constraint. +- */ +- if (vap->iv_des_mode != mode) +- continue; +- +- } +- if (!checktable(staScanTable, c)) +- ss->ss_chans[ss->ss_last++] = c; +- } +- ++ ieee80211_scan_add_channels(ic, ss, vap->iv_des_mode); + ss->ss_next = 0; ++ + /* XXX tunables */ + /* + * The scanner will stay on station for ss_maxdwell ms (using a +@@ -749,17 +541,7 @@ + fail = 0; + if (isclr(ic->ic_chan_active, ieee80211_chan2ieee(ic, se->se_chan))) + fail |= 0x01; +- /* +- * NB: normally the desired mode is used to construct +- * the channel list, but it's possible for the scan +- * cache to include entries for stations outside this +- * list so we check the desired mode here to weed them +- * out. +- */ +- if (vap->iv_des_mode != IEEE80211_MODE_AUTO && +- (se->se_chan->ic_flags & IEEE80211_CHAN_ALLTURBO) != +- chanflags[vap->iv_des_mode]) +- fail |= 0x01; ++ + if (vap->iv_opmode == IEEE80211_M_IBSS) { + if ((se->se_capinfo & IEEE80211_CAPINFO_IBSS) == 0) + fail |= 0x02; +@@ -1168,78 +950,6 @@ + .scan_default = ieee80211_sta_join, + }; + +-/* +- * Start an adhoc-mode scan by populating the channel list. +- */ +-static int +-adhoc_start(struct ieee80211_scan_state *ss, struct ieee80211vap *vap) +-{ +- struct ieee80211com *ic = vap->iv_ic; +- struct sta_table *st = ss->ss_priv; +- const struct scanlist *scan; +- enum ieee80211_phymode mode; +- +- ss->ss_last = 0; +- /* +- * Use the table of ordered channels to construct the list +- * of channels for scanning. Any channels in the ordered +- * list not in the master list will be discarded. +- */ +- for (scan = staScanTable; scan->list != NULL; scan++) { +- mode = scan->mode; +- if (vap->iv_des_mode != IEEE80211_MODE_AUTO) { +- /* +- * If a desired mode was specified, scan only +- * channels that satisfy that constraint. +- */ +- if (vap->iv_des_mode != mode) { +- /* +- * The scan table marks 2.4Ghz channels as b +- * so if the desired mode is 11g, then use +- * the 11b channel list but upgrade the mode. +- */ +- if (vap->iv_des_mode != IEEE80211_MODE_11G || +- mode != IEEE80211_MODE_11B) +- continue; +- mode = IEEE80211_MODE_11G; /* upgrade */ +- } +- } else { +- /* +- * This lets ieee80211_scan_add_channels +- * upgrade an 11b channel to 11g if available. +- */ +- if (mode == IEEE80211_MODE_11B) +- mode = IEEE80211_MODE_AUTO; +- } +- /* XR does not operate on turbo channels */ +- if ((vap->iv_flags & IEEE80211_F_XR) && +- (mode == IEEE80211_MODE_TURBO_A || +- mode == IEEE80211_MODE_TURBO_G)) +- continue; +- /* +- * Add the list of the channels; any that are not +- * in the master channel list will be discarded. +- */ +- add_channels(ic, ss, mode, scan->list, scan->count); +- } +- ss->ss_next = 0; +- /* XXX tunables */ +- ss->ss_mindwell = msecs_to_jiffies(200); /* 200ms */ +- ss->ss_maxdwell = msecs_to_jiffies(200); /* 200ms */ +- +-#ifdef IEEE80211_DEBUG +- if (ieee80211_msg_scan(vap)) { +- printk("%s: scan set ", vap->iv_dev->name); +- ieee80211_scan_dump_channels(ss); +- printk(" dwell min %ld max %ld\n", +- ss->ss_mindwell, ss->ss_maxdwell); +- } +-#endif /* IEEE80211_DEBUG */ +- +- st->st_newscan = 1; +- +- return 0; +-} + + /* + * Select a channel to start an adhoc network on. +@@ -1405,7 +1115,7 @@ + .scan_name = "default", + .scan_attach = sta_attach, + .scan_detach = sta_detach, +- .scan_start = adhoc_start, ++ .scan_start = sta_start, + .scan_restart = sta_restart, + .scan_cancel = sta_cancel, + .scan_end = adhoc_pick_bss, +Index: madwifi-trunk-r3314/net80211/ieee80211.c +=================================================================== +--- madwifi-trunk-r3314.orig/net80211/ieee80211.c 2008-06-01 03:41:58.000000000 +0200 ++++ madwifi-trunk-r3314/net80211/ieee80211.c 2008-06-01 03:42:18.000000000 +0200 +@@ -278,6 +278,11 @@ + ("channel with bogus ieee number %u", c->ic_ieee)); + setbit(ic->ic_chan_avail, c->ic_ieee); + ++ if (c->ic_scanflags & IEEE80211_NOSCAN_DEFAULT) ++ c->ic_scanflags |= IEEE80211_NOSCAN_SET; ++ else ++ c->ic_scanflags &= ~IEEE80211_NOSCAN_SET; ++ + /* Identify mode capabilities. */ + if (IEEE80211_IS_CHAN_A(c)) + ic->ic_modecaps |= 1 << IEEE80211_MODE_11A; +Index: madwifi-trunk-r3314/net80211/_ieee80211.h +=================================================================== +--- madwifi-trunk-r3314.orig/net80211/_ieee80211.h 2008-06-01 03:41:58.000000000 +0200 ++++ madwifi-trunk-r3314/net80211/_ieee80211.h 2008-06-01 03:42:18.000000000 +0200 +@@ -132,6 +132,11 @@ + IEEE80211_SCAN_FIRST = 2, /* take first suitable candidate */ + }; + ++enum ieee80211_scanflags { ++ IEEE80211_NOSCAN_DEFAULT = (1 << 0), ++ IEEE80211_NOSCAN_SET = (1 << 1), ++}; ++ + /* + * Channels are specified by frequency and attributes. + */ +@@ -142,6 +147,7 @@ + int8_t ic_maxregpower; /* maximum regulatory tx power in dBm */ + int8_t ic_maxpower; /* maximum tx power in dBm */ + int8_t ic_minpower; /* minimum tx power in dBm */ ++ u_int8_t ic_scanflags; + }; + + #define IEEE80211_CHAN_MAX 255 +Index: madwifi-trunk-r3314/net80211/ieee80211_ioctl.h +=================================================================== +--- madwifi-trunk-r3314.orig/net80211/ieee80211_ioctl.h 2008-06-01 03:41:58.000000000 +0200 ++++ madwifi-trunk-r3314/net80211/ieee80211_ioctl.h 2008-06-01 03:42:18.000000000 +0200 +@@ -555,6 +555,7 @@ + #define IEEE80211_IOCTL_WDSADDMAC (SIOCIWFIRSTPRIV+26) + #define IEEE80211_IOCTL_WDSDELMAC (SIOCIWFIRSTPRIV+28) + #define IEEE80211_IOCTL_KICKMAC (SIOCIWFIRSTPRIV+30) ++#define IEEE80211_IOCTL_SETSCANLIST (SIOCIWFIRSTPRIV+31) + + enum { + IEEE80211_WMMPARAMS_CWMIN = 1, +Index: madwifi-trunk-r3314/net80211/ieee80211_scan_ap.c +=================================================================== +--- madwifi-trunk-r3314.orig/net80211/ieee80211_scan_ap.c 2008-06-01 03:41:58.000000000 +0200 ++++ madwifi-trunk-r3314/net80211/ieee80211_scan_ap.c 2008-06-01 03:42:18.000000000 +0200 +@@ -129,131 +129,7 @@ + + static int ap_flush(struct ieee80211_scan_state *); + static void action_tasklet(IEEE80211_TQUEUE_ARG); +-static struct ieee80211_channel *find11gchannel(struct ieee80211com *ic, +- int i, int freq); + +-static const u_int chanflags[] = { +- IEEE80211_CHAN_B, /* IEEE80211_MODE_AUTO */ +- IEEE80211_CHAN_A, /* IEEE80211_MODE_11A */ +- IEEE80211_CHAN_B, /* IEEE80211_MODE_11B */ +- IEEE80211_CHAN_PUREG, /* IEEE80211_MODE_11G */ +- IEEE80211_CHAN_FHSS, /* IEEE80211_MODE_FH */ +- IEEE80211_CHAN_A, /* IEEE80211_MODE_TURBO_A */ /* for turbo mode +- * look for AP in +- * normal channel +- */ +- IEEE80211_CHAN_PUREG, /* IEEE80211_MODE_TURBO_G */ +- IEEE80211_CHAN_ST, /* IEEE80211_MODE_TURBO_STATIC_A */ +-}; +- +-static const u_int16_t rcl1[] = /* 8 FCC channel: 52, 56, 60, 64, +- * 36, 40, 44, 48 */ +-{ 5260, 5280, 5300, 5320, 5180, 5200, 5220, 5240 }; +-static const u_int16_t rcl2[] = /* 4 MKK channels: 34, 38, 42, 46 */ +-{ 5170, 5190, 5210, 5230 }; +-static const u_int16_t rcl3[] = /* 2.4Ghz ch: 1,6,11,7,13 */ +-{ 2412, 2437, 2462, 2442, 2472 }; +-static const u_int16_t rcl4[] = /* 5 FCC channel: 149, 153, 161, 165 */ +-{ 5745, 5765, 5785, 5805, 5825 }; +-static const u_int16_t rcl7[] = /* 11 ETSI channel: 100, 104, 108, 112, +- * 116, 120, 124, 128, +- * 132, 136, 140 */ +-{ 5500, 5520, 5540, 5560, 5580, 5600, 5620, 5640, 5660, 5680, 5700 }; +-static const u_int16_t rcl8[] = /* 2.4Ghz ch: 2,3,4,5,8,9,10,12 */ +-{ 2417, 2422, 2427, 2432, 2447, 2452, 2457, 2467 }; +-static const u_int16_t rcl9[] = /* 2.4Ghz ch: 14 */ +-{ 2484 }; +-static const u_int16_t rcl10[] = /* Added Korean channels 2312-2372 */ +-{ 2312, 2317, 2322, 2327, 2332, 2337, 2342, 2347, 2352, 2357, 2362, 2367, 2372 }; +-static const u_int16_t rcl11[] = /* Added Japan channels in 4.9/5.0 spectrum */ +-{ 5040, 5060, 5080, 4920, 4940, 4960, 4980 }; +-#ifdef ATH_TURBO_SCAN +-static const u_int16_t rcl5[] = /* 3 static turbo channels */ +-{ 5210, 5250, 5290 }; +-static const u_int16_t rcl6[] = /* 2 static turbo channels */ +-{ 5760, 5800 }; +-static const u_int16_t rcl6x[] = /* 4 FCC3 turbo channels */ +-{ 5540, 5580, 5620, 5660 }; +-static const u_int16_t rcl12[] = /* 2.4Ghz Turbo channel 6 */ +-{ 2437 }; +-static const u_int16_t rcl13[] = /* dynamic Turbo channels */ +-{ 5200, 5240, 5280, 5765, 5805 }; +-#endif /* ATH_TURBO_SCAN */ +- +-struct scanlist { +- u_int16_t mode; +- u_int16_t count; +- const u_int16_t *list; +-}; +- +-#define IEEE80211_MODE_TURBO_STATIC_A IEEE80211_MODE_MAX +-#define X(a) .count = ARRAY_SIZE(a), .list = a +- +-static const struct scanlist staScanTable[] = { +- { IEEE80211_MODE_11B, X(rcl3) }, +- { IEEE80211_MODE_11A, X(rcl1) }, +- { IEEE80211_MODE_11A, X(rcl2) }, +- { IEEE80211_MODE_11B, X(rcl8) }, +- { IEEE80211_MODE_11B, X(rcl9) }, +- { IEEE80211_MODE_11A, X(rcl4) }, +-#ifdef ATH_TURBO_SCAN +- { IEEE80211_MODE_TURBO_STATIC_A, X(rcl5) }, +- { IEEE80211_MODE_TURBO_STATIC_A, X(rcl6) }, +- { IEEE80211_MODE_TURBO_A, X(rcl6x) }, +- { IEEE80211_MODE_TURBO_A, X(rcl13) }, +-#endif /* ATH_TURBO_SCAN */ +- { IEEE80211_MODE_11A, X(rcl7) }, +- { IEEE80211_MODE_11B, X(rcl10) }, +- { IEEE80211_MODE_11A, X(rcl11) }, +-#ifdef ATH_TURBO_SCAN +- { IEEE80211_MODE_TURBO_G, X(rcl12) }, +-#endif /* ATH_TURBO_SCAN */ +- { .list = NULL } +-}; +- +-#undef X +-/* This function must be invoked with locks acquired */ +-static void +-add_channels(struct ieee80211com *ic, +- struct ieee80211_scan_state *ss, +- enum ieee80211_phymode mode, const u_int16_t freq[], int nfreq) +-{ +- struct ieee80211_channel *c, *cg; +- u_int modeflags; +- int i; +- +- KASSERT(mode < ARRAY_SIZE(chanflags), ("Unexpected mode %u", mode)); +- modeflags = chanflags[mode]; +- for (i = 0; i < nfreq; i++) { +- c = ieee80211_find_channel(ic, freq[i], modeflags); +- if ((c == NULL) || isclr(ic->ic_chan_active, c->ic_ieee)) +- continue; +- if (mode == IEEE80211_MODE_AUTO) { +- /* XXX special-case 11b/g channels so we select +- * the g channel if both are present. */ +- if (IEEE80211_IS_CHAN_B(c) && +- (cg = find11gchannel(ic, i, c->ic_freq)) != NULL) +- c = cg; +- } +- if (ss->ss_last >= IEEE80211_SCAN_MAX) +- break; +- ss->ss_chans[ss->ss_last++] = c; +- } +-} +- +-/* This function must be invoked with locks acquired */ +-static int +-checktable(const struct scanlist *scan, const struct ieee80211_channel *c) +-{ +- int i; +- +- for (; scan->list != NULL; scan++) { +- for (i = 0; i < scan->count; i++) +- if (scan->list[i] == c->ic_freq) +- return 1; +- } +- return 0; +-} + + /* + * Attach prior to any scanning work. +@@ -327,29 +203,6 @@ + ieee80211_saveie(iep, ie); + } + +-/* This function must be invoked with locks acquired */ +-static struct ieee80211_channel * +-find11gchannel(struct ieee80211com *ic, int i, int freq) +-{ +- struct ieee80211_channel *c; +- int j; +- +- /* The normal ordering in the channel list is b channel +- * immediately followed by g so optimize the search for +- * this. We'll still do a full search just in case. */ +- for (j = i + 1; j < ic->ic_nchans; j++) { +- c = &ic->ic_channels[j]; +- if ((c->ic_freq == freq) && IEEE80211_IS_CHAN_ANYG(c)) +- return c; +- } +- for (j = 0; j < i; j++) { +- c = &ic->ic_channels[j]; +- if ((c->ic_freq == freq) && IEEE80211_IS_CHAN_ANYG(c)) +- return c; +- } +- return NULL; +-} +- + /* + * Start an ap scan by populating the channel list. + */ +@@ -358,8 +211,6 @@ + { + struct ap_state *as = ss->ss_priv; + struct ieee80211com *ic = NULL; +- const struct scanlist *sl = NULL; +- struct ieee80211_channel *c = NULL; + int i; + unsigned int mode = 0; + +@@ -368,80 +219,8 @@ + /* Determine mode flags to match, or leave zero for auto mode */ + as->as_vap_desired_mode = vap->iv_des_mode; + as->as_required_mode = 0; +- if (as->as_vap_desired_mode != IEEE80211_MODE_AUTO) { +- as->as_required_mode = chanflags[as->as_vap_desired_mode]; +- if ((vap->iv_ath_cap & IEEE80211_ATHC_TURBOP) && +- (as->as_required_mode != IEEE80211_CHAN_ST)) { +- /* Fixup for dynamic turbo flags */ +- if (as->as_vap_desired_mode == IEEE80211_MODE_11G) +- as->as_required_mode = IEEE80211_CHAN_108G; +- else +- as->as_required_mode = IEEE80211_CHAN_108A; +- } +- } +- +- ss->ss_last = 0; +- /* Use the table of ordered channels to construct the list +- * of channels for scanning. Any channels in the ordered +- * list not in the master list will be discarded. */ +- for (sl = staScanTable; sl->list != NULL; sl++) { +- mode = sl->mode; +- +- /* The scan table marks 2.4Ghz channels as b +- * so if the desired mode is 11g, then use +- * the 11b channel list but upgrade the mode. */ +- if (as->as_vap_desired_mode && +- (as->as_vap_desired_mode != mode) && +- (as->as_vap_desired_mode == IEEE80211_MODE_11G) && +- (mode == IEEE80211_MODE_11B)) +- mode = IEEE80211_MODE_11G; +- +- /* If we are in "AUTO" mode, upgrade the mode to auto. +- * This lets add_channels upgrade an 11b channel to +- * 11g if available. */ +- if (!as->as_vap_desired_mode && (mode == IEEE80211_MODE_11B)) +- mode = IEEE80211_MODE_AUTO; +- +- /* Add the list of the channels; any that are not +- * in the master channel list will be discarded. */ +- add_channels(ic, ss, mode, sl->list, sl->count); +- } +- +- /* Add the channels from the ic (from HAL) that are not present +- * in the staScanTable, assuming they pass the sanity checks... */ +- for (i = 0; i < ic->ic_nchans; i++) { +- c = &ic->ic_channels[i]; +- +- /* XR is not supported on turbo channels */ +- if (IEEE80211_IS_CHAN_TURBO(c) && vap->iv_flags & IEEE80211_F_XR) +- continue; ++ ieee80211_scan_add_channels(ic, ss, vap->iv_des_mode); + +- /* Dynamic channels are scanned in base mode */ +- if (!as->as_required_mode && !IEEE80211_IS_CHAN_ST(c)) +- continue; +- +- /* Use any 11g channel instead of 11b one. */ +- if (vap->iv_des_mode == IEEE80211_MODE_AUTO && +- IEEE80211_IS_CHAN_B(c) && +- find11gchannel(ic, i, c->ic_freq)) +- continue; +- +- /* Do not add channels already put into the scan list by the +- * scan table - these have already been filtered by mode +- * and for whether they are in the active channel list. */ +- if (checktable(staScanTable, c)) +- continue; +- +- /* Make sure the channel is active */ +- if ((c == NULL) || isclr(ic->ic_chan_active, c->ic_ieee)) +- continue; +- +- /* Don't overrun */ +- if (ss->ss_last >= IEEE80211_SCAN_MAX) +- break; +- +- ss->ss_chans[ss->ss_last++] = c; +- } + ss->ss_next = 0; + /* XXX tunables */ + ss->ss_mindwell = msecs_to_jiffies(200); /* 200ms */ +@@ -759,13 +538,6 @@ + if (IEEE80211_IS_CHAN_RADAR(c->chan)) + continue; + +- /* Do not select 802.11a ST if mode is specified and is not +- * 802.11a ST */ +- if (as->as_required_mode && +- IEEE80211_IS_CHAN_STURBO(c->chan) && +- (as->as_vap_desired_mode != IEEE80211_MODE_TURBO_STATIC_A)) +- continue; +- + /* Verify mode matches any fixed mode specified */ + if((c->chan->ic_flags & as->as_required_mode) != + as->as_required_mode) +Index: madwifi-trunk-r3314/net80211/ieee80211_scan.c +=================================================================== +--- madwifi-trunk-r3314.orig/net80211/ieee80211_scan.c 2008-06-01 03:41:58.000000000 +0200 ++++ madwifi-trunk-r3314/net80211/ieee80211_scan.c 2008-06-01 03:42:18.000000000 +0200 +@@ -958,6 +958,79 @@ + } + } + ++static const u_int chanflags[] = { ++ 0, /* IEEE80211_MODE_AUTO */ ++ IEEE80211_CHAN_A, /* IEEE80211_MODE_11A */ ++ IEEE80211_CHAN_B, /* IEEE80211_MODE_11B */ ++ IEEE80211_CHAN_PUREG, /* IEEE80211_MODE_11G */ ++ IEEE80211_CHAN_FHSS, /* IEEE80211_MODE_FH */ ++ IEEE80211_CHAN_A, /* IEEE80211_MODE_TURBO_A */ /* for turbo mode look for AP in normal channel */ ++ IEEE80211_CHAN_PUREG, /* IEEE80211_MODE_TURBO_G */ ++ IEEE80211_CHAN_ST, /* IEEE80211_MODE_TURBO_STATIC_A */ ++}; ++ ++static struct ieee80211_channel * ++find11gchannel(struct ieee80211com *ic, int i, int freq) ++{ ++ struct ieee80211_channel *c; ++ int j; ++ ++ /* ++ * The normal ordering in the channel list is b channel ++ * immediately followed by g so optimize the search for ++ * this. We'll still do a full search just in case. ++ */ ++ for (j = i+1; j < ic->ic_nchans; j++) { ++ c = &ic->ic_channels[j]; ++ if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c)) ++ return c; ++ } ++ for (j = 0; j < i; j++) { ++ c = &ic->ic_channels[j]; ++ if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c)) ++ return c; ++ } ++ return NULL; ++} ++ ++ ++void ++ieee80211_scan_add_channels(struct ieee80211com *ic, ++ struct ieee80211_scan_state *ss, ++ enum ieee80211_phymode mode) ++{ ++ struct ieee80211_channel *c, *cg; ++ u_int modeflags; ++ 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 == 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 (mode == IEEE80211_MODE_AUTO) { ++ /* ++ * XXX special-case 11b/g channels so we select ++ * the g channel if both are present. ++ */ ++ if (IEEE80211_IS_CHAN_B(c) && ++ (cg = find11gchannel(ic, i, c->ic_freq)) != NULL) ++ continue; ++ } ++ if (ss->ss_last >= IEEE80211_SCAN_MAX) ++ break; ++ ss->ss_chans[ss->ss_last++] = c; ++ } ++} ++ ++ + /* + * Execute radar channel change. This is called when a radar/dfs + * signal is detected. AP mode only. Return 1 on success, 0 on +Index: madwifi-trunk-r3314/net80211/ieee80211_scan.h +=================================================================== +--- madwifi-trunk-r3314.orig/net80211/ieee80211_scan.h 2008-06-01 03:41:58.000000000 +0200 ++++ madwifi-trunk-r3314/net80211/ieee80211_scan.h 2008-06-01 03:42:18.000000000 +0200 +@@ -219,4 +219,7 @@ + void ieee80211_scanner_unregister(enum ieee80211_opmode, + const struct ieee80211_scanner *); + void ieee80211_scanner_unregister_all(const struct ieee80211_scanner *); ++void ieee80211_scan_add_channels(struct ieee80211com *ic, ++ struct ieee80211_scan_state *ss, ++ enum ieee80211_phymode mode); + #endif /* _NET80211_IEEE80211_SCAN_H_ */ +Index: madwifi-trunk-r3314/net80211/ieee80211_wireless.c +=================================================================== +--- madwifi-trunk-r3314.orig/net80211/ieee80211_wireless.c 2008-06-01 03:41:58.000000000 +0200 ++++ madwifi-trunk-r3314/net80211/ieee80211_wireless.c 2008-06-01 03:42:53.000000000 +0200 +@@ -3873,6 +3873,106 @@ + return ieee80211_ioctl_setmlme(dev, info, w, (char *)&mlme); + } + ++static inline void setflag(struct ieee80211_channel *c, int flag) ++{ ++ if (flag) ++ c->ic_scanflags |= IEEE80211_NOSCAN_SET; ++ else ++ c->ic_scanflags &= ~IEEE80211_NOSCAN_SET; ++} ++ ++static void setscanflag(struct ieee80211com *ic, int min, int max, int set) ++{ ++ int i; ++ ++ for (i = 0; i < ic->ic_nchans; i++) { ++ struct ieee80211_channel *c = &ic->ic_channels[i]; ++ ++ if (min == -1) { ++ if (!(c->ic_scanflags & IEEE80211_NOSCAN_DEFAULT)) ++ setflag(c, set); ++ } else if ((c->ic_freq >= min) && (c->ic_freq <= max)) { ++ setflag(c, set); ++ } ++ } ++} ++ ++static int ++ieee80211_ioctl_setscanlist(struct net_device *dev, ++ struct iw_request_info *info, ++ struct iw_point *data, char *extra) ++{ ++ struct ieee80211vap *vap = dev->priv; ++ struct ieee80211com *ic = vap->iv_ic; ++ char *s, *next; ++ int val = 1; ++ ++ if (data->length <= 0) ++ return -EINVAL; ++ ++ s = kmalloc(data->length + 1, GFP_KERNEL); ++ if (!s) ++ return -ENOMEM; ++ ++ memset(s, 0, data->length + 1); ++ if (copy_from_user(s, data->pointer, data->length)) ++ return -EFAULT; ++ ++ s[data->length - 1] = '\0'; /* ensure null termination */ ++ ++ switch(*s) { ++ case '-': ++ val = 1; ++ break; ++ case '+': ++ val = 0; ++ break; ++ default: ++ goto error; ++ } ++ s++; ++ next = s; ++ do { ++ next = strchr(s, ','); ++ if (next) { ++ *next = 0; ++ next++; ++ } ++ if (!strcmp(s, "ALL")) { ++ setscanflag(ic, 0, 10000, val); ++ } else if (!strcmp(s, "REG")) { ++ setscanflag(ic, -1, -1, val); ++ } else { ++ int min, max; ++ char *n, *end = NULL; ++ ++ n = strchr(s, '-'); ++ if (n) { ++ *n = 0; ++ n++; ++ } ++ min = simple_strtoul(s, &end, 10); ++ if (end && *end) ++ goto error; ++ if (n) { ++ max = simple_strtoul(n, &end, 10); ++ if (end && *end) ++ goto error; ++ } else { ++ max = min; ++ } ++ setscanflag(ic, min, max, val); ++ } ++ s = next; ++ } while (next); ++ return 0; ++ ++error: ++ if (s) ++ kfree(s); ++ return -EINVAL; ++} ++ + static int + ieee80211_ioctl_addmac(struct net_device *dev, struct iw_request_info *info, + void *w, char *extra) +@@ -5656,6 +5756,8 @@ + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "minrate"}, + {IEEE80211_PARAM_MINRATE, + 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_minrate"}, ++ { IEEE80211_IOCTL_SETSCANLIST, ++ IW_PRIV_TYPE_CHAR | 255, 0, "setscanlist"}, + + #ifdef ATH_REVERSE_ENGINEERING + /* +@@ -5753,6 +5855,7 @@ + set_priv(IEEE80211_IOCTL_WDSADDMAC, ieee80211_ioctl_wdsmac), + set_priv(IEEE80211_IOCTL_WDSDELMAC, ieee80211_ioctl_wdsdelmac), + set_priv(IEEE80211_IOCTL_KICKMAC, ieee80211_ioctl_kickmac), ++ set_priv(IEEE80211_IOCTL_SETSCANLIST, ieee80211_ioctl_setscanlist), + #ifdef ATH_REVERSE_ENGINEERING + set_priv(IEEE80211_IOCTL_READREG, ieee80211_ioctl_readreg), + set_priv(IEEE80211_IOCTL_WRITEREG, ieee80211_ioctl_writereg),