Changeset 2725

Show
Ignore:
Timestamp:
10/05/07 07:58:04 (1 year ago)
Author:
mtaylor
Message:

merged from trunk r2724

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • madwifi/branches/madwifi-dfs/net80211/ieee80211_scan_ap.c

    r2530 r2725  
    5353#include <net80211/ieee80211_var.h> 
    5454 
     55#define AP_PURGE_SCANS  2               /* age for purging entries (scans) */ 
     56#define RSSI_LPF_LEN    10 
     57#define RSSI_EP_MULTIPLIER      (1<<7)  /* pow2 to optimize out * and / */ 
     58#define RSSI_IN(x)              ((x) * RSSI_EP_MULTIPLIER) 
     59#define LPF_RSSI(x, y, len)     (((x) * ((len) - 1) + (y)) / (len)) 
     60#define RSSI_LPF(x, y) do {                                             \ 
     61        if ((y) >= -20)                                                 \ 
     62                x = LPF_RSSI((x), RSSI_IN((y)), RSSI_LPF_LEN);                  \ 
     63} while (0) 
     64#define EP_RND(x, mul) \ 
     65        ((((x)%(mul)) >= ((mul)/2)) ? howmany(x, mul) : (x)/(mul)) 
     66#define RSSI_GET(x)     EP_RND(x, RSSI_EP_MULTIPLIER) 
     67#define AP_HASHSIZE     32 
     68/* simple hash is enough for variation of macaddr */ 
     69#define AP_HASH(addr)   \ 
     70        (((const u_int8_t *)(addr))[IEEE80211_ADDR_LEN - 1] % AP_HASHSIZE) 
     71#define SCAN_AP_LOCK_INIT(_st, _name)                                   \ 
     72        spin_lock_init(&(_st)->as_lock) 
     73#define SCAN_AP_LOCK_DESTROY(_st) 
     74#define SCAN_AP_LOCK_IRQ(_st) do {                                      \ 
     75        unsigned long __stlockflags;                                    \ 
     76        spin_lock_irqsave(&(_st)->as_lock, __stlockflags); 
     77#define SCAN_AP_UNLOCK_IRQ(_st)                                         \ 
     78        spin_unlock_irqrestore(&(_st)->as_lock, __stlockflags);         \ 
     79} while (0) 
     80#define SCAN_AP_UNLOCK_IRQ_EARLY(_st)                                   \ 
     81        spin_unlock_irqrestore(&(_st)->as_lock, __stlockflags); 
     82 
     83#define SCAN_AP_GEN_LOCK_INIT(_st, _name)                               \ 
     84        spin_lock_init(&(_st)->as_scanlock) 
     85#define SCAN_AP_GEN_LOCK_DESTROY(_st) 
     86#define SCAN_AP_GEN_LOCK(_st)           spin_lock(&(_st)->as_scanlock); 
     87#define SCAN_AP_GEN_UNLOCK(_st) spin_unlock(&(_st)->as_scanlock); 
     88 
     89struct scan_entry { 
     90        struct ieee80211_scan_entry base; 
     91        TAILQ_ENTRY(scan_entry) se_list; 
     92        LIST_ENTRY(scan_entry) se_hash; 
     93        u_int8_t        se_seen;                /* seen during current scan */ 
     94        u_int8_t        se_notseen;             /* not seen in previous scans */ 
     95        u_int32_t se_avgrssi;           /* LPF rssi state */ 
     96        unsigned long se_lastupdate;    /* time of last update */ 
     97        unsigned long se_lastfail;      /* time of last failure */ 
     98        unsigned long se_lastassoc;     /* time of last association */ 
     99        u_int se_scangen;               /* iterator scan gen# */ 
     100}; 
     101 
    55102struct ap_state { 
    56         int as_maxrssi[IEEE80211_CHAN_MAX]; 
     103        unsigned int as_vap_desired_mode;       /* Used for channel selection, vap->iv_des_mode */ 
     104        unsigned int as_required_mode;          /* Used for channel selection, filtered version of as_vap_desired_mode */ 
     105        int as_maxrssi[IEEE80211_CHAN_MAX];     /* Used for channel selection */ 
     106 
     107        /* These fields are just for scan caching for returning responses to 
     108         * wireless extensions.  i.e. show peers, APs, etc. */ 
     109        spinlock_t as_lock;                     /* on scan table */ 
     110        int as_newscan;                         /* trigger for updating seen/not-seen for aging */ 
     111        TAILQ_HEAD(, scan_entry) as_entry;      /* all entries */ 
     112        ATH_LIST_HEAD(, scan_entry) as_hash[AP_HASHSIZE]; 
     113        spinlock_t as_scanlock;                 /* on as_scangen */ 
     114        u_int as_scangen;                       /* gen# for iterator */ 
     115 
    57116        struct IEEE80211_TQ_STRUCT as_actiontq; /* tasklet for "action" */ 
    58117        struct ieee80211_scan_entry as_selbss;  /* selected bss for action tasklet */ 
     
    62121static int ap_flush(struct ieee80211_scan_state *); 
    63122static void action_tasklet(IEEE80211_TQUEUE_ARG); 
     123static struct ieee80211_channel *find11gchannel(struct ieee80211com *ic, int i, int freq); 
     124 
     125static const u_int chanflags[] = { 
     126        IEEE80211_CHAN_B,       /* IEEE80211_MODE_AUTO */ 
     127        IEEE80211_CHAN_A,       /* IEEE80211_MODE_11A */ 
     128        IEEE80211_CHAN_B,       /* IEEE80211_MODE_11B */ 
     129        IEEE80211_CHAN_PUREG,   /* IEEE80211_MODE_11G */ 
     130        IEEE80211_CHAN_FHSS,    /* IEEE80211_MODE_FH */ 
     131        IEEE80211_CHAN_A,       /* IEEE80211_MODE_TURBO_A */ /* for turbo mode look for AP in normal channel */ 
     132        IEEE80211_CHAN_PUREG,   /* IEEE80211_MODE_TURBO_G */ 
     133        IEEE80211_CHAN_ST,      /* IEEE80211_MODE_TURBO_STATIC_A */ 
     134}; 
     135 
     136static const u_int16_t rcl1[] =         /* 8 FCC channel: 52, 56, 60, 64, 36, 40, 44, 48 */ 
     137{ 5260, 5280, 5300, 5320, 5180, 5200, 5220, 5240 }; 
     138static const u_int16_t rcl2[] =         /* 4 MKK channels: 34, 38, 42, 46 */ 
     139{ 5170, 5190, 5210, 5230 }; 
     140static const u_int16_t rcl3[] =         /* 2.4Ghz ch: 1,6,11,7,13 */ 
     141{ 2412, 2437, 2462, 2442, 2472 }; 
     142static const u_int16_t rcl4[] =         /* 5 FCC channel: 149, 153, 161, 165 */ 
     143{ 5745, 5765, 5785, 5805, 5825 }; 
     144static const u_int16_t rcl7[] =         /* 11 ETSI channel: 100,104,108,112,116,120,124,128,132,136,140 */ 
     145{ 5500, 5520, 5540, 5560, 5580, 5600, 5620, 5640, 5660, 5680, 5700 }; 
     146static const u_int16_t rcl8[] =         /* 2.4Ghz ch: 2,3,4,5,8,9,10,12 */ 
     147{ 2417, 2422, 2427, 2432, 2447, 2452, 2457, 2467 }; 
     148static const u_int16_t rcl9[] =         /* 2.4Ghz ch: 14 */ 
     149{ 2484 }; 
     150static const u_int16_t rcl10[] =        /* Added Korean channels 2312-2372 */ 
     151{ 2312, 2317, 2322, 2327, 2332, 2337, 2342, 2347, 2352, 2357, 2362, 2367, 2372 }; 
     152static const u_int16_t rcl11[] =        /* Added Japan channels in 4.9/5.0 spectrum */ 
     153{ 5040, 5060, 5080, 4920, 4940, 4960, 4980 }; 
     154#ifdef ATH_TURBO_SCAN 
     155static const u_int16_t rcl5[] =         /* 3 static turbo channels */ 
     156{ 5210, 5250, 5290 }; 
     157static const u_int16_t rcl6[] =         /* 2 static turbo channels */ 
     158{ 5760, 5800 }; 
     159static const u_int16_t rcl6x[] =                /* 4 FCC3 turbo channels */ 
     160{ 5540, 5580, 5620, 5660 }; 
     161static const u_int16_t rcl12[] =                /* 2.4Ghz Turbo channel 6 */ 
     162{ 2437 }; 
     163static const u_int16_t rcl13[] =                /* dynamic Turbo channels */ 
     164{ 5200, 5240, 5280, 5765, 5805 }; 
     165#endif /* ATH_TURBO_SCAN */ 
     166 
     167struct scanlist { 
     168        u_int16_t       mode; 
     169        u_int16_t       count; 
     170        const u_int16_t *list; 
     171}; 
     172 
     173#define IEEE80211_MODE_TURBO_STATIC_A   IEEE80211_MODE_MAX 
     174#define X(a)    .count = sizeof(a)/sizeof(a[0]), .list = a 
     175 
     176static const struct scanlist staScanTable[] = { 
     177        { IEEE80211_MODE_11B,                   X(rcl3) }, 
     178        { IEEE80211_MODE_11A,                   X(rcl1) }, 
     179        { IEEE80211_MODE_11A,                   X(rcl2) }, 
     180        { IEEE80211_MODE_11B,                   X(rcl8) }, 
     181        { IEEE80211_MODE_11B,                   X(rcl9) }, 
     182        { IEEE80211_MODE_11A,                   X(rcl4) }, 
     183#ifdef ATH_TURBO_SCAN 
     184        { IEEE80211_MODE_TURBO_STATIC_A,        X(rcl5) }, 
     185        { IEEE80211_MODE_TURBO_STATIC_A,        X(rcl6) }, 
     186        { IEEE80211_MODE_TURBO_A,               X(rcl6x) }, 
     187        { IEEE80211_MODE_TURBO_A,               X(rcl13) }, 
     188#endif /* ATH_TURBO_SCAN */ 
     189        { IEEE80211_MODE_11A,                   X(rcl7) }, 
     190        { IEEE80211_MODE_11B,                   X(rcl10) }, 
     191        { IEEE80211_MODE_11A,                   X(rcl11) }, 
     192#ifdef ATH_TURBO_SCAN 
     193        { IEEE80211_MODE_TURBO_G,               X(rcl12) }, 
     194#endif /* ATH_TURBO_SCAN */ 
     195        { .list = NULL } 
     196}; 
     197 
     198#undef X 
     199/* This function must be invoked with locks acquired */ 
     200static void 
     201add_channels(struct ieee80211com *ic, 
     202        struct ieee80211_scan_state *ss, 
     203        enum ieee80211_phymode mode, const u_int16_t freq[], int nfreq) 
     204{ 
     205#define N(a)    (sizeof(a) / sizeof(a[0])) 
     206        struct ieee80211_channel *c, *cg; 
     207        u_int modeflags; 
     208        int i; 
     209 
     210        KASSERT(mode < N(chanflags), ("Unexpected mode %u", mode)); 
     211        modeflags = chanflags[mode]; 
     212        for (i = 0; i < nfreq; i++) { 
     213                c = ieee80211_find_channel(ic, freq[i], modeflags); 
     214                if (c == NULL || isclr(ic->ic_chan_active, c->ic_ieee)) 
     215                        continue; 
     216                if (mode == IEEE80211_MODE_AUTO) { 
     217                        /* 
     218                         * XXX special-case 11b/g channels so we select 
     219                         *     the g channel if both are present. 
     220                         */ 
     221                        if (IEEE80211_IS_CHAN_B(c) && 
     222                            (cg = find11gchannel(ic, i, c->ic_freq)) != NULL) 
     223                                c = cg; 
     224                } 
     225                if (ss->ss_last >= IEEE80211_SCAN_MAX) 
     226                        break; 
     227                ss->ss_chans[ss->ss_last++] = c; 
     228        } 
     229#undef N 
     230} 
     231 
     232/* This function must be invoked with locks acquired */ 
     233static int 
     234checktable(const struct scanlist *scan, const struct ieee80211_channel *c) 
     235{ 
     236        int i; 
     237 
     238        for (; scan->list != NULL; scan++) { 
     239                for (i = 0; i < scan->count; i++) 
     240                        if (scan->list[i] == c->ic_freq) 
     241                                return 1; 
     242        } 
     243        return 0; 
     244} 
    64245 
    65246/* 
     
    74255 
    75256        MALLOC(as, struct ap_state *, sizeof(struct ap_state), 
    76                 M_SCANCACHE, M_NOWAIT); 
     257                M_80211_SCAN, M_NOWAIT | M_ZERO); 
     258        if (as == NULL) 
     259                return 0; 
     260        SCAN_AP_LOCK_INIT(as, "scan_ap"); 
     261        SCAN_AP_GEN_LOCK_INIT(as, "scan_ap_gen"); 
     262        TAILQ_INIT(&as->as_entry); 
     263        IEEE80211_INIT_TQUEUE(&as->as_actiontq, action_tasklet, ss); 
    77264        ss->ss_priv = as; 
    78         IEEE80211_INIT_TQUEUE(&as->as_actiontq, action_tasklet, ss); 
    79265        ap_flush(ss); 
    80266        return 1; 
     
    89275        struct ap_state *as = ss->ss_priv; 
    90276 
    91         if (as != NULL) 
    92                 FREE(as, M_SCANCACHE); 
     277        if (as != NULL) { 
     278                ap_flush(ss); 
     279                IEEE80211_CANCEL_TQUEUE(&as->as_actiontq); 
     280                FREE(as, M_80211_SCAN); 
     281        } 
    93282 
    94283        _MOD_DEC_USE(THIS_MODULE); 
     
    103292{ 
    104293        struct ap_state *as = ss->ss_priv; 
    105  
     294        struct scan_entry *se, *next; 
     295 
     296        SCAN_AP_LOCK_IRQ(as); 
    106297        memset(as->as_maxrssi, 0, sizeof(as->as_maxrssi)); 
     298        TAILQ_FOREACH_SAFE(se, &as->as_entry, se_list, next) { 
     299                TAILQ_REMOVE(&as->as_entry, se, se_list); 
     300                LIST_REMOVE(se, se_hash); 
     301                FREE(se, M_80211_SCAN); 
     302        } 
    107303        ss->ss_last = 0;                /* ensure no channel will be picked */ 
     304        SCAN_AP_UNLOCK_IRQ(as); 
    108305        return 0; 
    109306} 
    110307 
    111 static int 
     308/* This function must be invoked with locks acquired */ 
     309static void 
     310saveie(u_int8_t **iep, const u_int8_t *ie) 
     311
     312        if (ie == NULL) 
     313                *iep = NULL; 
     314        else 
     315                ieee80211_saveie(iep, ie); 
     316
     317 
     318/* This function must be invoked with locks acquired */ 
     319static struct ieee80211_channel * 
    112320find11gchannel(struct ieee80211com *ic, int i, int freq) 
    113321{ 
    114         const struct ieee80211_channel *c; 
     322        struct ieee80211_channel *c; 
    115323        int j; 
    116324 
     
    123331                c = &ic->ic_channels[j]; 
    124332                if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c)) 
    125                         return 1
     333                        return c
    126334        } 
    127335        for (j = 0; j < i; j++) { 
    128336                c = &ic->ic_channels[j]; 
    129337                if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c)) 
    130                         return 1
    131         } 
    132         return 0
     338                        return c
     339        } 
     340        return NULL
    133341} 
    134342 
     
    139347ap_start(struct ieee80211_scan_state *ss, struct ieee80211vap *vap) 
    140348{ 
    141         struct ieee80211com *ic = vap->iv_ic; 
    142         struct ieee80211_channel *c; 
     349        struct ap_state *as         = ss->ss_priv; 
     350        struct ieee80211com *ic     = NULL; 
     351        const struct scanlist *sl   = NULL; 
     352        struct ieee80211_channel *c = NULL; 
    143353        int i; 
     354        unsigned int mode = 0; 
     355 
     356        SCAN_AP_LOCK_IRQ(as); 
     357        ic = vap->iv_ic; 
     358        /* Determine mode flags to match, or leave zero for auto mode */ 
     359        as->as_vap_desired_mode = vap->iv_des_mode; 
     360        as->as_required_mode    = 0; 
     361        if (as->as_vap_desired_mode != IEEE80211_MODE_AUTO) { 
     362                as->as_required_mode = chanflags[as->as_vap_desired_mode]; 
     363                if (vap->iv_ath_cap & IEEE80211_ATHC_TURBOP &&  
     364                    as->as_required_mode != IEEE80211_CHAN_ST) { 
     365                        /* Fixup for dynamic turbo flags */ 
     366                        if (as->as_vap_desired_mode == IEEE80211_MODE_11G) 
     367                                as->as_required_mode = IEEE80211_CHAN_108G; 
     368                        else 
     369                                as->as_required_mode = IEEE80211_CHAN_108A; 
     370                } 
     371        } 
    144372 
    145373        ss->ss_last = 0; 
    146         if (vap->iv_des_mode == IEEE80211_MODE_AUTO) { 
    147                 for (i = 0; i < ic->ic_nchans; i++) { 
    148                         c = &ic->ic_channels[i]; 
    149                         if (IEEE80211_IS_CHAN_TURBO(c)) { 
    150                                 /* XR is not supported on turbo channels */ 
    151                                 if (vap->iv_ath_cap & IEEE80211_ATHC_XR) 
    152                                         continue; 
    153                                 /* dynamic channels are scanned in base mode */ 
    154                                 if (!IEEE80211_IS_CHAN_ST(c)) 
    155                                         continue; 
    156                         } else { 
    157                                 /* 
    158                                  * Use any 11g channel instead of 11b one. 
    159                                  */ 
    160                                 if (IEEE80211_IS_CHAN_B(c) && 
    161                                     find11gchannel(ic, i, c->ic_freq)) 
    162                                         continue; 
    163                         } 
    164                         if (c->ic_flags & IEEE80211_CHAN_RADAR) 
    165                                 continue; 
    166                         if (ss->ss_last >= IEEE80211_SCAN_MAX) 
    167                                 break; 
    168                         ss->ss_chans[ss->ss_last++] = c; 
    169                 } 
    170         } else { 
    171                 static const u_int chanflags[] = { 
    172                         0,                      /* IEEE80211_MODE_AUTO */ 
    173                         IEEE80211_CHAN_A,       /* IEEE80211_MODE_11A */ 
    174                         IEEE80211_CHAN_B,       /* IEEE80211_MODE_11B */ 
    175                         IEEE80211_CHAN_PUREG,   /* IEEE80211_MODE_11G */ 
    176                         IEEE80211_CHAN_FHSS,    /* IEEE80211_MODE_FH */ 
    177                         IEEE80211_CHAN_108A,    /* IEEE80211_MODE_TURBO_A */ 
    178                         IEEE80211_CHAN_108G,    /* IEEE80211_MODE_TURBO_G */ 
    179                         IEEE80211_CHAN_ST,      /* IEEE80211_MODE_TURBO_STATIC_A */ 
    180                 }; 
    181                 u_int modeflags; 
    182  
    183                 modeflags = chanflags[vap->iv_des_mode]; 
    184                 if (vap->iv_ath_cap & IEEE80211_ATHC_TURBOP && modeflags != IEEE80211_CHAN_ST) { 
    185                         if (vap->iv_des_mode == IEEE80211_MODE_11G) 
    186                                 modeflags = IEEE80211_CHAN_108G; 
    187                         else 
    188                                 modeflags = IEEE80211_CHAN_108A; 
    189                 } 
    190                 for (i = 0; i < ic->ic_nchans; i++) { 
    191                         c = &ic->ic_channels[i]; 
    192                         if ((c->ic_flags & modeflags) != modeflags) 
    193                                 continue; 
    194                         /* XR is not supported on turbo channels */ 
    195                         if (IEEE80211_IS_CHAN_TURBO(c) && vap->iv_ath_cap & IEEE80211_ATHC_XR) 
    196                                 continue; 
    197                         if (ss->ss_last >= IEEE80211_SCAN_MAX) 
    198                                 break; 
    199                         /*  
    200                          * do not select static turbo channels if the mode is not 
    201                          * static turbo . 
    202                          */ 
    203                         if (IEEE80211_IS_CHAN_STURBO(c) && vap->iv_des_mode != IEEE80211_MODE_MAX ) 
    204                                 continue; 
    205                         /* No dfs interference detected channels */ 
    206                         if (c->ic_flags & IEEE80211_CHAN_RADAR) 
    207                                 continue; 
    208                         ss->ss_chans[ss->ss_last++] = c; 
    209                 } 
     374        /* Use the table of ordered channels to construct the list 
     375         * of channels for scanning.  Any channels in the ordered 
     376         * list not in the master list will be discarded. */ 
     377        for (sl = staScanTable; sl->list != NULL; sl++) { 
     378                mode = sl->mode; 
     379                /* The scan table marks 2.4Ghz channels as b 
     380                 * so if the desired mode is 11g, then use 
     381                 * the 11b channel list but upgrade the mode. */ 
     382                if (as->as_vap_desired_mode && 
     383                    as->as_vap_desired_mode != mode &&  
     384                    as->as_vap_desired_mode == IEEE80211_MODE_11G &&  
     385                    mode == IEEE80211_MODE_11B) 
     386                        mode = IEEE80211_MODE_11G; 
     387                /* If we are in "AUTO" mode, upgrade the mode to auto.  
     388                 * This lets add_channels upgrade an 11b channel to  
     389                 * 11g if available. */ 
     390                if(!as->as_vap_desired_mode && mode == IEEE80211_MODE_11B) 
     391                        mode = IEEE80211_MODE_AUTO; 
     392                /* Add the list of the channels; any that are not 
     393                 * in the master channel list will be discarded. */ 
     394                add_channels(ic, ss, mode, sl->list, sl->count); 
     395        } 
     396 
     397        /* 
     398         * Add the channels from the ic (from HAL) that are not present 
     399         * in the staScanTable, assuming they pass the sanity checks... 
     400         */ 
     401        for (i = 0; i < ic->ic_nchans; i++) { 
     402                c = &ic->ic_channels[i]; 
     403                /* XR is not supported on turbo channels */ 
     404                if (IEEE80211_IS_CHAN_TURBO(c) && vap->iv_flags & IEEE80211_F_XR) 
     405                        continue; 
     406 
     407                /* Dynamic channels are scanned in base mode */ 
     408                if (!as->as_required_mode && !IEEE80211_IS_CHAN_ST(c)) 
     409                        continue; 
     410 
     411                /* Use any 11g channel instead of 11b one. */ 
     412                if (vap->iv_des_mode == IEEE80211_MODE_AUTO &&  
     413                    IEEE80211_IS_CHAN_B(c) && 
     414                    find11gchannel(ic, i, c->ic_freq)) 
     415                        continue; 
     416 
     417                /* Do not add channels already put into the scan list by the 
     418                 * scan table - these have already been filtered by mode 
     419                 * and for whether they are in the active channel list. */ 
     420                if (checktable(staScanTable, c)) 
     421                        continue; 
     422 
     423                /* Make sure the channel is active */ 
     424                if (c == NULL || isclr(ic->ic_chan_active, c->ic_ieee)) 
     425                        continue; 
     426 
     427                /* Don't overrun */ 
     428                if (ss->ss_last >= IEEE80211_SCAN_MAX) 
     429                        break; 
     430 
     431                ss->ss_chans[ss->ss_last++] = c; 
    210432        } 
    211433        ss->ss_next = 0; 
     
    223445#endif /* IEEE80211_DEBUG */ 
    224446 
     447        as->as_newscan = 1; 
     448        SCAN_AP_UNLOCK_IRQ(as); 
    225449        return 0; 
    226450} 
     
    232456ap_restart(struct ieee80211_scan_state *ss, struct ieee80211vap *vap) 
    233457{ 
     458        struct ap_state *as = ss->ss_priv; 
     459        as->as_newscan = 1; 
    234460        return 0; 
    235461} 
     
    242468{ 
    243469        struct ap_state *as = ss->ss_priv; 
    244  
    245470        IEEE80211_CANCEL_TQUEUE(&as->as_actiontq); 
    246471        return 0; 
     
    254479        const struct ieee80211_frame *wh, int subtype, int rssi, u_int64_t rtsf) 
    255480{ 
    256         struct ap_state *as = ss->ss_priv; 
    257         struct ieee80211vap *vap = ss->ss_vap; 
    258         struct ieee80211com *ic = vap->iv_ic; 
    259         int chan; 
    260  
    261         chan = ieee80211_chan2ieee(ic, ic->ic_curchan); 
    262         /* XXX better quantification of channel use? */ 
    263         /* XXX: count BSSs? */ 
     481        struct ap_state *as              = ss->ss_priv; 
     482        const u_int8_t *macaddr          = wh->i_addr2; 
     483        struct ieee80211vap *vap         = NULL; 
     484        struct ieee80211com *ic          = NULL; 
     485        struct scan_entry *se            = NULL; 
     486        struct ieee80211_scan_entry *ise = NULL; 
     487        int hash; 
     488        int chan = 0; 
     489 
     490        /* This section provides scan results to wireless extensions */ 
     491        SCAN_AP_LOCK_IRQ(as); 
     492        /* This is the only information used for channel selection by AP */ 
    264493        if (rssi > as->as_maxrssi[chan]) 
    265494                as->as_maxrssi[chan] = rssi; 
    266         /* XXX interference, turbo requirements */ 
     495        vap = ss->ss_vap; 
     496        ic = vap->iv_ic; 
     497        hash = AP_HASH(macaddr); 
     498        chan = ieee80211_chan2ieee(ic, ic->ic_curchan); 
     499        LIST_FOREACH(se, &as->as_hash[hash], se_hash) 
     500                if (IEEE80211_ADDR_EQ(se->base.se_macaddr, macaddr) && 
     501                    sp->ssid[1] == se->base.se_ssid[1] && 
     502                    !memcmp(se->base.se_ssid+2, sp->ssid+2, se->base.se_ssid[1])) 
     503                        goto found; 
     504 
     505        MALLOC(se, struct scan_entry *, sizeof(struct scan_entry), 
     506                M_80211_SCAN, M_NOWAIT | M_ZERO); 
     507        if (se == NULL) { 
     508                SCAN_AP_UNLOCK_IRQ_EARLY(as); 
     509                return 0; 
     510        } 
     511        se->se_scangen = as->as_scangen-1; 
     512        IEEE80211_ADDR_COPY(se->base.se_macaddr, macaddr); 
     513        TAILQ_INSERT_TAIL(&as->as_entry, se, se_list); 
     514        LIST_INSERT_HEAD(&as->as_hash[hash], se, se_hash); 
     515found: 
     516        ise = &se->base; 
     517        /* XXX ap beaconing multiple ssid w/ same bssid */ 
     518        if (sp->ssid[1] != 0 && 
     519            ((subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP) || ise->se_ssid[1] == 0)) 
     520        { 
     521                memcpy(ise->se_ssid, sp->ssid, 2 + sp->ssid[1]); 
     522        } 
     523        KASSERT(sp->rates[1] <= IEEE80211_RATE_MAXSIZE, 
     524                ("rate set too large: %u", sp->rates[1])); 
     525        memcpy(ise->se_rates, sp->rates, 2 + sp->rates[1]); 
     526        if (sp->xrates != NULL) { 
     527                /* XXX validate xrates[1] */ 
     528                KASSERT(sp->xrates[1] <= IEEE80211_RATE_MAXSIZE, 
     529                        ("xrate set too large: %u", sp->xrates[1])); 
     530                memcpy(ise->se_xrates, sp->xrates, 2 + sp->xrates[1]); 
     531        } else 
     532                ise->se_xrates[1] = 0; 
     533        IEEE80211_ADDR_COPY(ise->se_bssid, wh->i_addr3); 
     534        /* 
     535         * Record rssi data using extended precision LPF filter. 
     536         */ 
     537        if (se->se_lastupdate == 0)             /* first sample */ 
     538                se->se_avgrssi = RSSI_IN(rssi); 
     539        else                                    /* avg w/ previous samples */ 
     540                RSSI_LPF(se->se_avgrssi, rssi); 
     541        se->base.se_rssi = RSSI_GET(se->se_avgrssi); 
     542        ise->se_rtsf = rtsf; 
     543        memcpy(ise->se_tstamp.data, sp->tstamp, sizeof(ise->se_tstamp)); 
     544        ise->se_intval = sp->bintval; 
     545        ise->se_capinfo = sp->capinfo; 
     546        ise->se_chan = ic->ic_curchan; 
     547        ise->se_fhdwell = sp->fhdwell; 
     548        ise->se_fhindex = sp->fhindex; 
     549        ise->se_erp = sp->erp; 
     550        ise->se_timoff = sp->timoff; 
     551        if (sp->tim != NULL) { 
     552                const struct ieee80211_tim_ie *tim = 
     553                    (const struct ieee80211_tim_ie *) sp->tim; 
     554                ise->se_dtimperiod = tim->tim_period; 
     555        } 
     556        saveie(&ise->se_wme_ie, sp->wme); 
     557        saveie(&ise->se_wpa_ie, sp->wpa); 
     558        saveie(&ise->se_rsn_ie, sp->rsn); 
     559        saveie(&ise->se_ath_ie, sp->ath); 
     560 
     561        se->se_lastupdate = jiffies;            /* update time */ 
     562        se->se_seen = 1; 
     563        se->se_notseen = 0; 
     564 
     565        SCAN_AP_UNLOCK_IRQ(as); 
     566 
    267567        return 1; 
    268568} 
    269569 
    270  
    271 /* 
    272  * ap_end 
    273  * 
    274  * Choose the most optimal channel taking under consideration rssi of the 
    275  * received packets and the current Spectrum Management algorithm. 
    276  * 
    277  * This can be called a stub since it is of no important use unless there is a 
    278  * way to keep the scan results up-to-date without interrupting BSS operation. 
    279  * 
    280  */ 
    281  
    282 struct ap_pc_params { 
     570struct pc_params { 
    283571        struct ieee80211vap *vap; 
    284572        struct ieee80211_scan_state *ss; 
     
    289577        struct ieee80211_channel *chan; 
    290578        int orig; 
    291         struct ap_pc_params *params; 
     579        struct pc_params *params; 
    292580}; 
    293581 
    294 static int 
    295 ap_pc_cmp_radar(struct ieee80211_channel *a, struct ieee80211_channel *b) 
     582/* This function must be invoked with locks acquired */ 
     583static int 
     584pc_cmp_radar(struct ieee80211_channel *a, struct ieee80211_channel *b) 
    296585{ 
    297586        /* a is better than b (return < 0) when b is marked while a is not */ 
     
    299588} 
    300589 
    301 static int 
    302 ap_pc_cmp_keepmode(struct ap_pc_params *params, struct ieee80211_channel *a, 
     590/* This function must be invoked with locks acquired */ 
     591static int 
     592pc_cmp_keepmode(struct pc_params *params, struct ieee80211_channel *a, 
    303593                struct ieee80211_channel *b) 
    304594{ 
     
    315605} 
    316606 
    317 static int 
    318 ap_pc_cmp_sc(struct ieee80211com *ic, struct ieee80211_channel *a, 
     607/* This function must be invoked with locks acquired */ 
     608static int 
     609pc_cmp_sc(struct ieee80211com *ic, struct ieee80211_channel *a, 
    319610                struct ieee80211_channel *b) 
    320611{ 
     
    325616} 
    326617 
    327 static int 
    328 ap_pc_cmp_rssi(struct ap_state *as, struct ieee80211_channel *a, 
     618/* This function must be invoked with locks acquired */ 
     619static int 
     620pc_cmp_rssi(struct ap_state *as, struct ieee80211_channel *a, 
    329621                struct ieee80211_channel *b) 
    330622{ 
     
    335627} 
    336628 
    337 static int 
    338 ap_pc_cmp_samechan(struct ieee80211com *ic, struct ieee80211_channel *a, 
     629/* This function must be invoked with locks acquired */ 
     630static int 
     631pc_cmp_samechan(struct ieee80211com *ic, struct ieee80211_channel *a, 
    339632                struct ieee80211_channel *b) 
    340633{ 
     
    346639} 
    347640 
    348 /* use original scan list order */ 
    349 static int 
    350 ap_pc_cmp_orig(struct channel *a, struct channel *b) 
     641/* This function must be invoked with locks acquired */ 
     642static int 
     643pc_cmp_orig(struct channel *a, struct channel *b) 
    351644{ 
    352645        return a->orig - b->orig; 
    353646} 
    354647 
    355 static int 
    356 ap_pc_cmp(const void *_a, const void *_b) 
     648/* This function must be invoked with locks acquired */ 
     649static int 
     650pc_cmp(const void *_a, const void *_b) 
    357651{ 
    358652        struct ieee80211_channel *a = ((struct channel *)_a)->chan; 
    359653        struct ieee80211_channel *b = ((struct channel *)_b)->chan; 
    360         struct ap_pc_params *params = ((struct channel *)_a)->params; 
     654        struct pc_params *params = ((struct channel *)_a)->params; 
    361655        struct ieee80211com *ic = params->vap->iv_ic; 
    362656        int res; 
    363657 
    364658#define EVALUATE_CRITERIUM(name, ...) do {                      \ 
    365         if ((res = ap_pc_cmp_##name(__VA_ARGS__)) != 0)       \ 
     659        if ((res = pc_cmp_##name(__VA_ARGS__)) != 0)  \ 
    366660                return res;                                     \ 
    367661} while (0) 
     
    370664        EVALUATE_CRITERIUM(keepmode, params, a, b); 
    371665        EVALUATE_CRITERIUM(sc, ic, a, b); 
    372         EVALUATE_CRITERIUM(rssi, params->ss->ss_priv, a, b);            /* useless? ap_pick_channel evaluates it anyway */ 
     666        EVALUATE_CRITERIUM(rssi, params->ss->ss_priv, a, b);            /* useless? pick_channel evaluates it anyway */ 
    373667        EVALUATE_CRITERIUM(samechan, ic, a, b); 
    374668        EVALUATE_CRITERIUM(orig, (struct channel *)_a, (struct channel *)_b); 
     
    378672} 
    379673 
     674/* This function must be invoked with locks acquired */ 
    380675static void 
    381 ap_pc_swap(void *a, void *b, int n) 
     676pc_swap(void *a, void *b, int n) 
    382677{ 
    383678        struct ieee80211_channel *t = ((struct channel *)a)->chan; 
     
    396691/* 
    397692 * Pick a quiet channel to use for ap operation. 
     693 * Must be invoked while we hold the locks. 
    398694 */ 
    399695static struct ieee80211_channel * 
    400 ap_pick_channel(struct ieee80211_scan_state *ss, struct ieee80211vap *vap, u_int32_t flags) 
     696pick_channel(struct ieee80211_scan_state *ss, struct ieee80211vap *vap, u_int32_t flags) 
    401697{ 
    402698        struct ieee80211com *ic = vap->iv_ic; 
    403         int i, best_rssi; 
     699        int i, beas_rssi; 
    404700        int ss_last = ss->ss_last; 
    405701        struct ieee80211_channel *best; 
    406702        struct ap_state *as = ss->ss_priv; 
    407703        struct channel chans[ss_last]; /* actually ss_last-1 is required */ 
    408         struct ap_pc_params params = { vap, ss, flags }; 
     704        struct channel *c = NULL; 
     705        struct pc_params params = { vap, ss, flags }; 
     706        int benefit = 0; 
     707        int sta_assoc = 0; 
    409708 
    410709        for (i = 0; i < ss_last; i++) { 
     
    414713        } 
    415714 
    416         sort(chans, ss_last, sizeof(*chans), ap_pc_cmp, ap_pc_swap); 
     715        sort(chans, ss_last, sizeof(*chans), pc_cmp, pc_swap); 
    417716 
    418717        for (i = 0; i < ss_last; i++) { 
     
    426725        } 
    427726 
    428         best = chans[0].chan
    429         best_rssi = -1; 
     727        best = NULL
     728        beas_rssi = -1; 
    430729 
    431730        for (i = 0; i < ss_last; i++) { 
    432                 int benefit = best_rssi - as->as_maxrssi[chans[i].chan->ic_ieee]; 
    433                 int sta_assoc = ic->ic_sta_assoc; 
    434  
     731                c = &chans[i]; 
     732                benefit = beas_rssi - as->as_maxrssi[c->chan->ic_ieee]; 
     733                sta_assoc = ic->ic_sta_assoc; 
     734 
     735                /* Don't switch... */ 
    435736                if (benefit <= 0) 
    436737                        continue; 
    437738 
    438                 if ((flags & IEEE80211_SCAN_KEEPMODE) && !IEEE80211_ARE_CHANS_SAME_MODE(chans[i].chan, ic->ic_bsschan)) 
    439                                 /* break the loop as the subsequent chans won't be better */ 
    440                                 break; 
    441  
    442                 if (!IEEE80211_ARE_CHANS_SAME_MODE(chans[i].chan, ic->ic_bsschan)) 
     739                /* Verify channel is not marked for non-occupancy */ 
     740                if (IEEE80211_IS_CHAN_RADAR(c->chan)) 
     741                        continue; 
     742 
     743                /* Do not select 802.11a ST if mode is specified and is not 802.11a ST */ 
     744                if (as->as_required_mode &&  
     745                    IEEE80211_IS_CHAN_STURBO(c->chan) && 
     746                    as->as_vap_desired_mode != IEEE80211_MODE_TURBO_STATIC_A) 
     747                        continue; 
     748 
     749                /* Verify mode matches any fixed mode specified */ 
     750                if((c->chan->ic_flags & as->as_required_mode) != as->as_required_mode) 
     751                        continue; 
     752 
     753                /* Make sure the channels are the same mode */ 
     754                if ((flags & IEEE80211_SCAN_KEEPMODE) && !IEEE80211_ARE_CHANS_SAME_MODE(c->chan, ic->ic_bsschan)) 
    443755                        /* break the loop as the subsequent chans won't be better */ 
    444756                        break; 
    445757 
     758                if (!IEEE80211_ARE_CHANS_SAME_MODE(c->chan, ic->ic_bsschan)) 
     759                        /* break the loop as the subsequent chans won't be better */ 
     760                        break; 
     761 
    446762                if (sta_assoc != 0) { 
    447                         int sl = ic->ic_cn_total - ic->ic_chan_nodes[chans[i].chan->ic_ieee]; /* count */ 
     763                        int sl = ic->ic_cn_total - ic->ic_chan_nodes[c->chan->ic_ieee]; /* count */ 
    448764                        if (ic->ic_sc_algorithm == IEEE80211_SC_LOOSE) { 
    449765                                int sl_max = ic->ic_sc_sldg * benefit; 
     
    451767                IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, 
    452768                                                "%s: chan %d, dB gained: %d, STAs lost: %d permil (max %d)\n", __func__, 
    453                                                 chans[i].chan->ic_ieee, benefit, sl, sl_max); 
     769                                                c->chan->ic_ieee, benefit, sl, sl_max); 
    454770                                if (sl > sl_max) 
    455771                                        continue; 
     
    461777                } 
    462778        } 
    463                 best = chans[i].chan; 
    464                 best_rssi = as->as_maxrssi[best->ic_ieee]; 
     779                best = c->chan; 
     780                beas_rssi = as->as_maxrssi[best->ic_ieee]; 
    465781        } 
    466782 
     
    478794{ 
    479795        struct ap_state *as = ss->ss_priv; 
    480         struct ieee80211com *ic = vap->iv_ic; 
    481         struct ieee80211_channel *bestchan; 
     796        struct ieee80211_channel *bestchan = NULL; 
     797        struct ieee80211com *ic = NULL; 
     798        int res = 1; 
     799 
     800        SCAN_AP_LOCK_IRQ(as); 
    482801 
    483802        KASSERT(vap->iv_opmode == IEEE80211_M_HOSTAP, 
    484803                ("wrong opmode %u", vap->iv_opmode)); 
    485804 
    486         bestchan = ap_pick_channel(ss, vap, flags); 
     805        ic = vap->iv_ic; 
     806        bestchan = pick_channel(ss, vap, flags); 
    487807        if (bestchan == NULL) { 
    488808                if (ss->ss_last > 0) { 
     
    492812                        /* XXX print something? */ 
    493813                } 
    494                 return 0; /* restart scan */ 
     814                res = 0; /* restart scan */ 
    495815        } else { 
    496816                struct ieee80211_scan_entry se; 
     
    517837                 */ 
    518838                IEEE80211_SCHEDULE_TQUEUE(&as->as_actiontq); 
    519                 return 1; 
    520         } 
     839                res = 1; 
     840        } 
     841        SCAN_AP_UNLOCK_IRQ(as); 
     842        return res; 
    521843} 
    522844 
     
    524846ap_age(struct ieee80211_scan_state *ss) 
    525847{ 
    526         /* XXX is there anything meaningful to do? */ 
     848        struct ap_state *as = ss->ss_priv; 
     849        struct scan_entry *se, *next; 
     850 
     851        SCAN_AP_LOCK_IRQ(as); 
     852        TAILQ_FOREACH_SAFE(se, &as->as_entry, se_list, next) { 
     853                if (se->se_notseen > AP_PURGE_SCANS) { 
     854                        TAILQ_REMOVE(&as->as_entry, se, se_list); 
     855                        LIST_REMOVE(se, se_hash); 
     856                        FREE(se, M_80211_SCAN); 
     857                } 
     858        } 
     859        SCAN_AP_UNLOCK_IRQ(as); 
    527860} 
    528861 
     
    531864        ieee80211_scan_iter_func *f, void *arg) 
    532865{ 
    533         /* NB: nothing meaningful we can do */ 
    534         return 0; 
     866        struct ap_state *as = ss->ss_priv; 
     867        struct scan_entry *se; 
     868        u_int gen; 
     869        int res = 0; 
     870 
     871        SCAN_AP_GEN_LOCK(as); 
     872        gen = as->as_scangen++; 
     873restart: 
     874        SCAN_AP_LOCK_IRQ(as); 
     875        TAILQ_FOREACH(se, &as->as_entry, se_list) { 
     876                if (se->se_scangen != gen) { 
     877                        se->se_scangen = gen; 
     878                        /* update public state */ 
     879                        se->base.se_age = jiffies - se->se_lastupdate; 
     880                        SCAN_AP_UNLOCK_IRQ_EARLY(as); 
     881 
     882                        res = (*f)(arg, &se->base); 
     883 
     884                        /* We probably ran out of buffer space. */ 
     885                        if (res != 0) 
     886                                goto done; 
     887 
     888                        goto restart; 
     889                } 
     890        } 
     891 
     892        SCAN_AP_UNLOCK_IRQ(as); 
     893 
     894done: