| 1 | --- a/ath/if_ath.c |
| 2 | +++ b/ath/if_ath.c |
| 3 | @@ -148,7 +148,6 @@ static int ath_key_set(struct ieee80211v |
| 4 | static void ath_key_update_begin(struct ieee80211vap *); |
| 5 | static void ath_key_update_end(struct ieee80211vap *); |
| 6 | static void ath_mode_init(struct net_device *); |
| 7 | -static void ath_setslottime(struct ath_softc *); |
| 8 | static void ath_updateslot(struct net_device *); |
| 9 | static int ath_beaconq_setup(struct ath_softc *); |
| 10 | static int ath_beacon_alloc(struct ath_softc *, struct ieee80211_node *); |
| 11 | @@ -240,7 +239,7 @@ static void ath_setup_stationkey(struct |
| 12 | static void ath_setup_stationwepkey(struct ieee80211_node *); |
| 13 | static void ath_setup_keycacheslot(struct ath_softc *, struct ieee80211_node *); |
| 14 | static void ath_newassoc(struct ieee80211_node *, int); |
| 15 | -static int ath_getchannels(struct net_device *, u_int, HAL_BOOL, HAL_BOOL); |
| 16 | +static int ath_getchannels(struct net_device *); |
| 17 | static void ath_led_event(struct ath_softc *, int); |
| 18 | static void ath_update_txpow(struct ath_softc *); |
| 19 | |
| 20 | @@ -265,7 +264,6 @@ static int ath_change_mtu(struct net_dev |
| 21 | static int ath_ioctl(struct net_device *, struct ifreq *, int); |
| 22 | |
| 23 | static int ath_rate_setup(struct net_device *, u_int); |
| 24 | -static void ath_setup_subrates(struct net_device *); |
| 25 | #ifdef ATH_SUPERG_XR |
| 26 | static int ath_xr_rate_setup(struct net_device *); |
| 27 | static void ath_grppoll_txq_setup(struct ath_softc *, int, int); |
| 28 | @@ -387,8 +385,6 @@ static void ath_fetch_idle_time(struct a |
| 29 | |
| 30 | /* calibrate every 30 secs in steady state but check every second at first. */ |
| 31 | static int ath_calinterval = ATH_SHORT_CALINTERVAL; |
| 32 | -static int ath_countrycode = CTRY_DEFAULT; /* country code */ |
| 33 | -static int ath_outdoor = AH_FALSE; /* enable outdoor use */ |
| 34 | static int ath_xchanmode = AH_TRUE; /* enable extended channels */ |
| 35 | static int ath_maxvaps = ATH_MAXVAPS_DEFAULT; /* set default maximum vaps */ |
| 36 | static int bstuck_thresh = BSTUCK_THRESH; /* Stuck beacon count required for reset */ |
| 37 | @@ -396,9 +392,7 @@ static char *autocreate = NULL; |
| 38 | static char *ratectl = DEF_RATE_CTL; |
| 39 | static int rfkill = 0; |
| 40 | static int tpc = 1; |
| 41 | -static int countrycode = -1; |
| 42 | static int maxvaps = -1; |
| 43 | -static int outdoor = -1; |
| 44 | static int xchanmode = -1; |
| 45 | #include "ath_wprobe.c" |
| 46 | static int beacon_cal = 1; |
| 47 | @@ -437,9 +431,7 @@ static struct notifier_block ath_event_b |
| 48 | |
| 49 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,52)) |
| 50 | MODULE_PARM(beacon_cal, "i"); |
| 51 | -MODULE_PARM(countrycode, "i"); |
| 52 | MODULE_PARM(maxvaps, "i"); |
| 53 | -MODULE_PARM(outdoor, "i"); |
| 54 | MODULE_PARM(xchanmode, "i"); |
| 55 | MODULE_PARM(rfkill, "i"); |
| 56 | #ifdef ATH_CAP_TPC |
| 57 | @@ -451,9 +443,7 @@ MODULE_PARM(ratectl, "s"); |
| 58 | #else |
| 59 | #include <linux/moduleparam.h> |
| 60 | module_param(beacon_cal, int, 0600); |
| 61 | -module_param(countrycode, int, 0600); |
| 62 | module_param(maxvaps, int, 0600); |
| 63 | -module_param(outdoor, int, 0600); |
| 64 | module_param(xchanmode, int, 0600); |
| 65 | module_param(rfkill, int, 0600); |
| 66 | #ifdef ATH_CAP_TPC |
| 67 | @@ -463,9 +453,7 @@ module_param(bstuck_thresh, int, 0600); |
| 68 | module_param(autocreate, charp, 0600); |
| 69 | module_param(ratectl, charp, 0600); |
| 70 | #endif |
| 71 | -MODULE_PARM_DESC(countrycode, "Override default country code"); |
| 72 | MODULE_PARM_DESC(maxvaps, "Maximum VAPs"); |
| 73 | -MODULE_PARM_DESC(outdoor, "Enable/disable outdoor use"); |
| 74 | MODULE_PARM_DESC(xchanmode, "Enable/disable extended channel mode"); |
| 75 | MODULE_PARM_DESC(rfkill, "Enable/disable RFKILL capability"); |
| 76 | #ifdef ATH_CAP_TPC |
| 77 | @@ -531,6 +519,50 @@ MODULE_PARM_DESC(ieee80211_debug, "Load- |
| 78 | (bssid)[0] |= (((id) << 2) | 0x02); \ |
| 79 | } while (0) |
| 80 | |
| 81 | +static inline int ath_chan2mode(struct ieee80211_channel *c) |
| 82 | +{ |
| 83 | + if (IEEE80211_IS_CHAN_HALF(c)) |
| 84 | + return ATH_MODE_HALF; |
| 85 | + else if (IEEE80211_IS_CHAN_QUARTER(c)) |
| 86 | + return ATH_MODE_QUARTER; |
| 87 | + else |
| 88 | + return ieee80211_chan2mode(c); |
| 89 | +} |
| 90 | + |
| 91 | +static inline int rate_hal2ieee(int dot11Rate, int f) |
| 92 | +{ |
| 93 | + int flag = dot11Rate & ~(IEEE80211_RATE_VAL); |
| 94 | + dot11Rate &= IEEE80211_RATE_VAL; |
| 95 | + |
| 96 | + if (f == 4) { /* Quarter */ |
| 97 | + if (dot11Rate == 4) |
| 98 | + return 18 | flag; |
| 99 | + } |
| 100 | + return (dot11Rate * f) | flag; |
| 101 | +} |
| 102 | + |
| 103 | +static inline int rate_factor(int mode) |
| 104 | +{ |
| 105 | + int f; |
| 106 | + |
| 107 | + /* |
| 108 | + * NB: Fix up rates. HAL returns half or quarter dot11Rates, |
| 109 | + * while the stack deals with full rates only |
| 110 | + */ |
| 111 | + switch(mode) { |
| 112 | + case ATH_MODE_HALF: |
| 113 | + f = 2; |
| 114 | + break; |
| 115 | + case ATH_MODE_QUARTER: |
| 116 | + f = 4; |
| 117 | + break; |
| 118 | + default: |
| 119 | + f = 1; |
| 120 | + break; |
| 121 | + } |
| 122 | + return f; |
| 123 | +} |
| 124 | + |
| 125 | /* Initialize ath_softc structure */ |
| 126 | |
| 127 | int |
| 128 | @@ -647,14 +679,6 @@ ath_attach(u_int16_t devid, struct net_d |
| 129 | for (i = 0; i < sc->sc_keymax; i++) |
| 130 | ath_hal_keyreset(ah, i); |
| 131 | |
| 132 | - /* |
| 133 | - * Collect the channel list using the default country |
| 134 | - * code and including outdoor channels. The 802.11 layer |
| 135 | - * is responsible for filtering this list based on settings |
| 136 | - * like the phy mode. |
| 137 | - */ |
| 138 | - if (countrycode != -1) |
| 139 | - ath_countrycode = countrycode; |
| 140 | if (maxvaps != -1) { |
| 141 | ath_maxvaps = maxvaps; |
| 142 | if (ath_maxvaps < ATH_MAXVAPS_MIN) |
| 143 | @@ -662,17 +686,14 @@ ath_attach(u_int16_t devid, struct net_d |
| 144 | else if (ath_maxvaps > ATH_MAXVAPS_MAX) |
| 145 | ath_maxvaps = ATH_MAXVAPS_MAX; |
| 146 | } |
| 147 | - if (outdoor != -1) |
| 148 | - ath_outdoor = outdoor; |
| 149 | if (xchanmode != -1) |
| 150 | ath_xchanmode = xchanmode; |
| 151 | - error = ath_getchannels(dev, ath_countrycode, |
| 152 | - ath_outdoor, ath_xchanmode); |
| 153 | + error = ath_getchannels(dev); |
| 154 | if (error != 0) |
| 155 | goto bad; |
| 156 | |
| 157 | - ic->ic_country_code = ath_countrycode; |
| 158 | - ic->ic_country_outdoor = ath_outdoor; |
| 159 | + ic->ic_country_code = CTRY_DEFAULT; |
| 160 | + ic->ic_country_outdoor = 0; |
| 161 | |
| 162 | IPRINTF(sc, "Switching rfkill capability %s\n", |
| 163 | rfkill ? "on" : "off"); |
| 164 | @@ -686,9 +707,8 @@ ath_attach(u_int16_t devid, struct net_d |
| 165 | ath_rate_setup(dev, IEEE80211_MODE_11G); |
| 166 | ath_rate_setup(dev, IEEE80211_MODE_TURBO_A); |
| 167 | ath_rate_setup(dev, IEEE80211_MODE_TURBO_G); |
| 168 | - |
| 169 | - /* Setup for half/quarter rates */ |
| 170 | - ath_setup_subrates(dev); |
| 171 | + ath_rate_setup(dev, ATH_MODE_HALF); |
| 172 | + ath_rate_setup(dev, ATH_MODE_QUARTER); |
| 173 | |
| 174 | /* NB: setup here so ath_rate_update is happy */ |
| 175 | ath_setcurmode(sc, IEEE80211_MODE_11A); |
| 176 | @@ -908,10 +928,6 @@ ath_attach(u_int16_t devid, struct net_d |
| 177 | IEEE80211_ATHC_COMP : 0); |
| 178 | #endif |
| 179 | |
| 180 | -#ifdef ATH_SUPERG_DYNTURBO |
| 181 | - ic->ic_ath_cap |= (ath_hal_turboagsupported(ah, ath_countrycode) ? |
| 182 | - (IEEE80211_ATHC_TURBOP | IEEE80211_ATHC_AR) : 0); |
| 183 | -#endif |
| 184 | #ifdef ATH_SUPERG_XR |
| 185 | ic->ic_ath_cap |= (ath_hal_xrsupported(ah) ? IEEE80211_ATHC_XR : 0); |
| 186 | #endif |
| 187 | @@ -4470,17 +4486,17 @@ ath_mode_init(struct net_device *dev) |
| 188 | * Set the slot time based on the current setting. |
| 189 | */ |
| 190 | static void |
| 191 | -ath_setslottime(struct ath_softc *sc) |
| 192 | +ath_settiming(struct ath_softc *sc) |
| 193 | { |
| 194 | - struct ieee80211com *ic = &sc->sc_ic; |
| 195 | struct ath_hal *ah = sc->sc_ah; |
| 196 | + u_int offset = getTimingOffset(sc); |
| 197 | |
| 198 | - if (sc->sc_slottimeconf > 0) /* manual override */ |
| 199 | - ath_hal_setslottime(ah, sc->sc_slottimeconf); |
| 200 | - else if (ic->ic_flags & IEEE80211_F_SHSLOT) |
| 201 | - ath_hal_setslottime(ah, HAL_SLOT_TIME_9); |
| 202 | - else |
| 203 | - ath_hal_setslottime(ah, HAL_SLOT_TIME_20); |
| 204 | + if (sc->sc_slottimeconf > 0) |
| 205 | + ath_hal_setslottime(ah, offset + sc->sc_slottimeconf); |
| 206 | + if (sc->sc_acktimeconf > 0) |
| 207 | + ath_hal_setacktimeout(ah, 2 * offset + sc->sc_acktimeconf); |
| 208 | + if (sc->sc_ctstimeconf > 0) |
| 209 | + ath_hal_setctstimeout(ah, 2 * offset + sc->sc_ctstimeconf); |
| 210 | sc->sc_updateslot = OK; |
| 211 | } |
| 212 | |
| 213 | @@ -4502,7 +4518,7 @@ ath_updateslot(struct net_device *dev) |
| 214 | if (ic->ic_opmode == IEEE80211_M_HOSTAP) |
| 215 | sc->sc_updateslot = UPDATE; |
| 216 | else if (dev->flags & IFF_RUNNING) |
| 217 | - ath_setslottime(sc); |
| 218 | + ath_settiming(sc); |
| 219 | } |
| 220 | |
| 221 | #ifdef ATH_SUPERG_DYNTURBO |
| 222 | @@ -5346,7 +5362,7 @@ ath_beacon_send(struct ath_softc *sc, in |
| 223 | sc->sc_updateslot = COMMIT; /* commit next beacon */ |
| 224 | sc->sc_slotupdate = slot; |
| 225 | } else if ((sc->sc_updateslot == COMMIT) && (sc->sc_slotupdate == slot)) |
| 226 | - ath_setslottime(sc); /* commit change to hardware */ |
| 227 | + ath_settiming(sc); /* commit change to hardware */ |
| 228 | |
| 229 | if (bfaddr != 0) { |
| 230 | /* |
| 231 | @@ -7802,12 +7818,14 @@ ath_get_ivlen(struct ieee80211_key *k) |
| 232 | * Get transmit rate index using rate in Kbps |
| 233 | */ |
| 234 | static __inline int |
| 235 | -ath_tx_findindex(const HAL_RATE_TABLE *rt, int rate) |
| 236 | +ath_tx_findindex(struct ath_softc *sc, const HAL_RATE_TABLE *rt, int rate) |
| 237 | { |
| 238 | unsigned int i, ndx = 0; |
| 239 | + int f; |
| 240 | |
| 241 | + f = rate_factor(sc->sc_curmode); |
| 242 | for (i = 0; i < rt->rateCount; i++) { |
| 243 | - if (rt->info[i].rateKbps == rate) { |
| 244 | + if ((rt->info[i].rateKbps * f) == rate) { |
| 245 | ndx = i; |
| 246 | break; |
| 247 | } |
| 248 | @@ -8100,7 +8118,7 @@ ath_tx_start(struct net_device *dev, str |
| 249 | atype = HAL_PKT_TYPE_NORMAL; /* default */ |
| 250 | |
| 251 | if (ismcast) { |
| 252 | - rix = ath_tx_findindex(rt, vap->iv_mcast_rate); |
| 253 | + rix = ath_tx_findindex(sc, rt, vap->iv_mcast_rate); |
| 254 | txrate = rt->info[rix].rateCode; |
| 255 | if (shortPreamble) |
| 256 | txrate |= rt->info[rix].shortPreamble; |
| 257 | @@ -9067,7 +9085,7 @@ ath_chan_change(struct ath_softc *sc, st |
| 258 | struct net_device *dev = sc->sc_dev; |
| 259 | enum ieee80211_phymode mode; |
| 260 | |
| 261 | - mode = ieee80211_chan2mode(chan); |
| 262 | + mode = ath_chan2mode(chan); |
| 263 | |
| 264 | ath_rate_setup(dev, mode); |
| 265 | ath_setcurmode(sc, mode); |
| 266 | @@ -10124,8 +10142,7 @@ ath_newassoc(struct ieee80211_node *ni, |
| 267 | } |
| 268 | |
| 269 | static int |
| 270 | -ath_getchannels(struct net_device *dev, u_int cc, |
| 271 | - HAL_BOOL outdoor, HAL_BOOL xchanmode) |
| 272 | +ath_getchannels(struct net_device *dev) |
| 273 | { |
| 274 | struct ath_softc *sc = dev->priv; |
| 275 | struct ieee80211com *ic = &sc->sc_ic; |
| 276 | @@ -10139,17 +10156,31 @@ ath_getchannels(struct net_device *dev, |
| 277 | EPRINTF(sc, "Insufficient memory for channel table!\n"); |
| 278 | return -ENOMEM; |
| 279 | } |
| 280 | + |
| 281 | +restart: |
| 282 | if (!ath_hal_init_channels(ah, chans, IEEE80211_CHAN_MAX, &nchan, |
| 283 | ic->ic_regclassids, IEEE80211_REGCLASSIDS_MAX, &ic->ic_nregclass, |
| 284 | - cc, HAL_MODE_ALL, outdoor, xchanmode)) { |
| 285 | + ic->ic_country_code, HAL_MODE_ALL, ic->ic_country_outdoor, ath_xchanmode)) { |
| 286 | u_int32_t rd; |
| 287 | |
| 288 | ath_hal_getregdomain(ah, &rd); |
| 289 | EPRINTF(sc, "Unable to collect channel list from HAL; " |
| 290 | - "regdomain likely %u country code %u\n", rd, cc); |
| 291 | + "regdomain likely %u country code %u\n", rd, ic->ic_country_code); |
| 292 | + if ((ic->ic_country_code != CTRY_DEFAULT) || |
| 293 | + (ic->ic_country_outdoor != 0)) { |
| 294 | + EPRINTF(sc, "Reverting to defaults\n"); |
| 295 | + ic->ic_country_code = CTRY_DEFAULT; |
| 296 | + ic->ic_country_outdoor = 0; |
| 297 | + goto restart; |
| 298 | + } |
| 299 | kfree(chans); |
| 300 | return -EINVAL; |
| 301 | } |
| 302 | +#ifdef ATH_SUPERG_DYNTURBO |
| 303 | + ic->ic_ath_cap &= ~(IEEE80211_ATHC_TURBOP | IEEE80211_ATHC_AR); |
| 304 | + ic->ic_ath_cap |= (ath_hal_turboagsupported(ah, ic->ic_country_code) ? |
| 305 | + (IEEE80211_ATHC_TURBOP | IEEE80211_ATHC_AR) : 0); |
| 306 | +#endif |
| 307 | /* |
| 308 | * Convert HAL channels to ieee80211 ones. |
| 309 | */ |
| 310 | @@ -10395,7 +10426,7 @@ ath_xr_rate_setup(struct net_device *dev |
| 311 | struct ieee80211com *ic = &sc->sc_ic; |
| 312 | const HAL_RATE_TABLE *rt; |
| 313 | struct ieee80211_rateset *rs; |
| 314 | - unsigned int i, maxrates; |
| 315 | + unsigned int i, j, maxrates; |
| 316 | sc->sc_xr_rates = ath_hal_getratetable(ah, HAL_MODE_XR); |
| 317 | rt = sc->sc_xr_rates; |
| 318 | if (rt == NULL) |
| 319 | @@ -10408,57 +10439,16 @@ ath_xr_rate_setup(struct net_device *dev |
| 320 | } else |
| 321 | maxrates = rt->rateCount; |
| 322 | rs = &ic->ic_sup_xr_rates; |
| 323 | - for (i = 0; i < maxrates; i++) |
| 324 | - rs->rs_rates[i] = rt->info[i].dot11Rate; |
| 325 | - rs->rs_nrates = maxrates; |
| 326 | + for (j = 0, i = 0; i < maxrates; i++) { |
| 327 | + if (!rt->info[i].valid) |
| 328 | + continue; |
| 329 | + rs->rs_rates[j++] = rt->info[i].dot11Rate; |
| 330 | + } |
| 331 | + rs->rs_nrates = j; |
| 332 | return 1; |
| 333 | } |
| 334 | #endif |
| 335 | |
| 336 | -/* Setup half/quarter rate table support */ |
| 337 | -static void |
| 338 | -ath_setup_subrates(struct net_device *dev) |
| 339 | -{ |
| 340 | - struct ath_softc *sc = dev->priv; |
| 341 | - struct ath_hal *ah = sc->sc_ah; |
| 342 | - struct ieee80211com *ic = &sc->sc_ic; |
| 343 | - const HAL_RATE_TABLE *rt; |
| 344 | - struct ieee80211_rateset *rs; |
| 345 | - unsigned int i, maxrates; |
| 346 | - |
| 347 | - sc->sc_half_rates = ath_hal_getratetable(ah, HAL_MODE_11A_HALF_RATE); |
| 348 | - rt = sc->sc_half_rates; |
| 349 | - if (rt != NULL) { |
| 350 | - if (rt->rateCount > IEEE80211_RATE_MAXSIZE) { |
| 351 | - DPRINTF(sc, ATH_DEBUG_ANY, |
| 352 | - "The rate table is too small (%u > %u)\n", |
| 353 | - rt->rateCount, IEEE80211_RATE_MAXSIZE); |
| 354 | - maxrates = IEEE80211_RATE_MAXSIZE; |
| 355 | - } else |
| 356 | - maxrates = rt->rateCount; |
| 357 | - rs = &ic->ic_sup_half_rates; |
| 358 | - for (i = 0; i < maxrates; i++) |
| 359 | - rs->rs_rates[i] = rt->info[i].dot11Rate; |
| 360 | - rs->rs_nrates = maxrates; |
| 361 | - } |
| 362 | - |
| 363 | - sc->sc_quarter_rates = ath_hal_getratetable(ah, HAL_MODE_11A_QUARTER_RATE); |
| 364 | - rt = sc->sc_quarter_rates; |
| 365 | - if (rt != NULL) { |
| 366 | - if (rt->rateCount > IEEE80211_RATE_MAXSIZE) { |
| 367 | - DPRINTF(sc, ATH_DEBUG_ANY, |
| 368 | - "The rate table is too small (%u > %u)\n", |
| 369 | - rt->rateCount, IEEE80211_RATE_MAXSIZE); |
| 370 | - maxrates = IEEE80211_RATE_MAXSIZE; |
| 371 | - } else |
| 372 | - maxrates = rt->rateCount; |
| 373 | - rs = &ic->ic_sup_quarter_rates; |
| 374 | - for (i = 0; i < maxrates; i++) |
| 375 | - rs->rs_rates[i] = rt->info[i].dot11Rate; |
| 376 | - rs->rs_nrates = maxrates; |
| 377 | - } |
| 378 | -} |
| 379 | - |
| 380 | static int |
| 381 | ath_rate_setup(struct net_device *dev, u_int mode) |
| 382 | { |
| 383 | @@ -10467,7 +10457,7 @@ ath_rate_setup(struct net_device *dev, u |
| 384 | struct ieee80211com *ic = &sc->sc_ic; |
| 385 | const HAL_RATE_TABLE *rt; |
| 386 | struct ieee80211_rateset *rs; |
| 387 | - unsigned int i, maxrates; |
| 388 | + unsigned int i, j, maxrates, f; |
| 389 | |
| 390 | switch (mode) { |
| 391 | case IEEE80211_MODE_11A: |
| 392 | @@ -10485,6 +10475,12 @@ ath_rate_setup(struct net_device *dev, u |
| 393 | case IEEE80211_MODE_TURBO_G: |
| 394 | sc->sc_rates[mode] = ath_hal_getratetable(ah, HAL_MODE_108G); |
| 395 | break; |
| 396 | + case ATH_MODE_HALF: |
| 397 | + sc->sc_rates[mode] = ath_hal_getratetable(ah, HAL_MODE_11A_HALF_RATE); |
| 398 | + break; |
| 399 | + case ATH_MODE_QUARTER: |
| 400 | + sc->sc_rates[mode] = ath_hal_getratetable(ah, HAL_MODE_11A_QUARTER_RATE); |
| 401 | + break; |
| 402 | default: |
| 403 | DPRINTF(sc, ATH_DEBUG_ANY, "Invalid mode %u\n", mode); |
| 404 | return 0; |
| 405 | @@ -10499,10 +10495,16 @@ ath_rate_setup(struct net_device *dev, u |
| 406 | maxrates = IEEE80211_RATE_MAXSIZE; |
| 407 | } else |
| 408 | maxrates = rt->rateCount; |
| 409 | + |
| 410 | + /* NB: quarter/half rate channels hijack the 11A rateset */ |
| 411 | + if (mode >= IEEE80211_MODE_MAX) |
| 412 | + return 1; |
| 413 | + |
| 414 | rs = &ic->ic_sup_rates[mode]; |
| 415 | for (i = 0; i < maxrates; i++) |
| 416 | rs->rs_rates[i] = rt->info[i].dot11Rate; |
| 417 | rs->rs_nrates = maxrates; |
| 418 | + |
| 419 | return 1; |
| 420 | } |
| 421 | |
| 422 | @@ -10531,13 +10533,18 @@ ath_setcurmode(struct ath_softc *sc, enu |
| 423 | { 0, 500, 130 }, |
| 424 | }; |
| 425 | const HAL_RATE_TABLE *rt; |
| 426 | - unsigned int i, j; |
| 427 | + unsigned int i, j, f; |
| 428 | |
| 429 | + /* |
| 430 | + * NB: Fix up rixmap. HAL returns half or quarter dot11Rates, |
| 431 | + * while the stack deals with full rates only |
| 432 | + */ |
| 433 | + f = rate_factor(mode); |
| 434 | memset(sc->sc_rixmap, 0xff, sizeof(sc->sc_rixmap)); |
| 435 | rt = sc->sc_rates[mode]; |
| 436 | KASSERT(rt != NULL, ("no h/w rate set for phy mode %u", mode)); |
| 437 | for (i = 0; i < rt->rateCount; i++) |
| 438 | - sc->sc_rixmap[rt->info[i].dot11Rate & IEEE80211_RATE_VAL] = i; |
| 439 | + sc->sc_rixmap[rate_hal2ieee(rt->info[i].dot11Rate, f) & IEEE80211_RATE_VAL] = i; |
| 440 | memset(sc->sc_hwmap, 0, sizeof(sc->sc_hwmap)); |
| 441 | for (i = 0; i < 32; i++) { |
| 442 | u_int8_t ix = rt->rateCodeToIndex[i]; |
| 443 | @@ -10547,7 +10554,7 @@ ath_setcurmode(struct ath_softc *sc, enu |
| 444 | continue; |
| 445 | } |
| 446 | sc->sc_hwmap[i].ieeerate = |
| 447 | - rt->info[ix].dot11Rate & IEEE80211_RATE_VAL; |
| 448 | + rate_hal2ieee(rt->info[ix].dot11Rate, f) & IEEE80211_RATE_VAL; |
| 449 | if (rt->info[ix].shortPreamble || |
| 450 | rt->info[ix].phy == IEEE80211_T_OFDM) |
| 451 | sc->sc_hwmap[i].flags |= IEEE80211_RADIOTAP_F_SHORTPRE; |
| 452 | @@ -10948,9 +10955,106 @@ enum { |
| 453 | ATH_MAXVAPS = 26, |
| 454 | ATH_INTMIT = 27, |
| 455 | ATH_NOISE_IMMUNITY = 28, |
| 456 | - ATH_OFDM_WEAK_DET = 29 |
| 457 | + ATH_OFDM_WEAK_DET = 29, |
| 458 | + ATH_CHANBW = 30, |
| 459 | + ATH_OUTDOOR = 31, |
| 460 | }; |
| 461 | |
| 462 | +/* |
| 463 | + * perform the channel related sysctl, reload the channel list |
| 464 | + * and try to stay on the current frequency |
| 465 | + */ |
| 466 | +static int ath_sysctl_setchanparam(struct ath_softc *sc, unsigned long ctl, u_int val) |
| 467 | +{ |
| 468 | + struct ieee80211com *ic = &sc->sc_ic; |
| 469 | + struct ath_hal *ah = sc->sc_ah; |
| 470 | + struct ieee80211_channel *c = NULL; |
| 471 | + struct ieee80211vap *vap; |
| 472 | + u_int16_t freq = 0; |
| 473 | + struct ifreq ifr; |
| 474 | + |
| 475 | + if (ic->ic_curchan != IEEE80211_CHAN_ANYC) |
| 476 | + freq = ic->ic_curchan->ic_freq; |
| 477 | + |
| 478 | + switch(ctl) { |
| 479 | + case ATH_COUNTRYCODE: |
| 480 | + ic->ic_country_code = val; |
| 481 | + break; |
| 482 | + case ATH_OUTDOOR: |
| 483 | + ic->ic_country_outdoor = val; |
| 484 | + break; |
| 485 | + case ATH_CHANBW: |
| 486 | + switch(val) { |
| 487 | + case 0: |
| 488 | + case 5: |
| 489 | + case 10: |
| 490 | + case 20: |
| 491 | + case 40: |
| 492 | + if (ath_hal_setcapability(ah, HAL_CAP_CHANBW, 1, val, NULL) == AH_TRUE) { |
| 493 | + sc->sc_chanbw = val; |
| 494 | + break; |
| 495 | + } |
| 496 | + default: |
| 497 | + return -EINVAL; |
| 498 | + } |
| 499 | + break; |
| 500 | + } |
| 501 | + |
| 502 | + if (ic->ic_curchan != IEEE80211_CHAN_ANYC) |
| 503 | + freq = ic->ic_curchan->ic_freq; |
| 504 | + |
| 505 | + /* clear out any old state */ |
| 506 | + TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { |
| 507 | + vap->iv_des_mode = IEEE80211_MODE_AUTO; |
| 508 | + vap->iv_des_chan = IEEE80211_CHAN_ANYC; |
| 509 | + } |
| 510 | + ieee80211_scan_flush(ic); |
| 511 | + |
| 512 | + IEEE80211_LOCK_IRQ(ic); |
| 513 | + ath_getchannels(sc->sc_dev); |
| 514 | + ieee80211_update_channels(ic, 0); |
| 515 | + if (freq) |
| 516 | + c = ieee80211_find_channel(ic, freq, IEEE80211_MODE_AUTO); |
| 517 | + if (!c) |
| 518 | + c = &ic->ic_channels[0]; |
| 519 | + ic->ic_curchan = c; |
| 520 | + ic->ic_bsschan = c; |
| 521 | + ic->ic_curmode = IEEE80211_MODE_AUTO; |
| 522 | + IEEE80211_UNLOCK_IRQ(ic); |
| 523 | + |
| 524 | + if (!(sc->sc_dev->flags & IFF_RUNNING)) { |
| 525 | + ic->ic_bsschan = IEEE80211_CHAN_ANYC; |
| 526 | + return 0; |
| 527 | + } |
| 528 | + |
| 529 | +#ifndef ifr_media |
| 530 | +#define ifr_media ifr_ifru.ifru_ivalue |
| 531 | +#endif |
| 532 | + memset(&ifr, 0, sizeof(ifr)); |
| 533 | + ifr.ifr_media = ic->ic_media.ifm_cur->ifm_media & ~IFM_MMASK; |
| 534 | + ifr.ifr_media |= IFM_MAKEMODE(IEEE80211_MODE_AUTO); |
| 535 | + ifmedia_ioctl(ic->ic_dev, &ifr, &ic->ic_media, SIOCSIFMEDIA); |
| 536 | + |
| 537 | + /* apply the channel to the hw */ |
| 538 | + ath_set_channel(ic); |
| 539 | + |
| 540 | + TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { |
| 541 | + struct net_device *dev = vap->iv_dev; |
| 542 | + |
| 543 | + /* reactivate all active vaps */ |
| 544 | + vap->iv_state = IEEE80211_S_SCAN; |
| 545 | + if ((vap->iv_opmode == IEEE80211_M_HOSTAP) || |
| 546 | + (vap->iv_opmode == IEEE80211_M_MONITOR) || |
| 547 | + (vap->iv_opmode == IEEE80211_M_WDS)) |
| 548 | + ieee80211_new_state(vap, IEEE80211_S_RUN, 0); |
| 549 | + else |
| 550 | + ieee80211_new_state(vap, IEEE80211_S_INIT, -1); |
| 551 | + } |
| 552 | + |
| 553 | + return 0; |
| 554 | +} |
| 555 | + |
| 556 | + |
| 557 | static int |
| 558 | ath_sysctl_set_intmit(struct ath_softc *sc, long ctl, u_int val) |
| 559 | { |
| 560 | @@ -11029,6 +11133,7 @@ static int |
| 561 | ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl, write, filp, buffer, lenp, ppos) |
| 562 | { |
| 563 | struct ath_softc *sc = ctl->extra1; |
| 564 | + struct ieee80211com *ic = &sc->sc_ic; |
| 565 | struct ath_hal *ah = sc->sc_ah; |
| 566 | u_int val; |
| 567 | u_int tab_3_val[3]; |
| 568 | @@ -11052,25 +11157,34 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl |
| 569 | lenp, ppos); |
| 570 | if (ret == 0) { |
| 571 | switch ((long)ctl->extra2) { |
| 572 | + case ATH_REGDOMAIN: |
| 573 | + ath_hal_setregdomain(ah, val); |
| 574 | + break; |
| 575 | + case ATH_OUTDOOR: |
| 576 | + case ATH_COUNTRYCODE: |
| 577 | + case ATH_CHANBW: |
| 578 | + ret = ath_sysctl_setchanparam(sc, (long) ctl->extra2, val); |
| 579 | + break; |
| 580 | case ATH_SLOTTIME: |
| 581 | - if (val > 0) { |
| 582 | - if (!ath_hal_setslottime(ah, val)) |
| 583 | - ret = -EINVAL; |
| 584 | - else |
| 585 | - sc->sc_slottimeconf = val; |
| 586 | - } else { |
| 587 | - /* disable manual override */ |
| 588 | + if (val > 0) |
| 589 | + sc->sc_slottimeconf = val; |
| 590 | + else |
| 591 | sc->sc_slottimeconf = 0; |
| 592 | - ath_setslottime(sc); |
| 593 | - } |
| 594 | + ath_settiming(sc); |
| 595 | break; |
| 596 | case ATH_ACKTIMEOUT: |
| 597 | - if (!ath_hal_setacktimeout(ah, val)) |
| 598 | - ret = -EINVAL; |
| 599 | + if (val > 0) |
| 600 | + sc->sc_acktimeconf = val; |
| 601 | + else |
| 602 | + sc->sc_acktimeconf = 0; |
| 603 | + ath_settiming(sc); |
| 604 | break; |
| 605 | case ATH_CTSTIMEOUT: |
| 606 | - if (!ath_hal_setctstimeout(ah, val)) |
| 607 | - ret = -EINVAL; |
| 608 | + if (val > 0) |
| 609 | + sc->sc_ctstimeconf = val; |
| 610 | + else |
| 611 | + sc->sc_ctstimeconf = 0; |
| 612 | + ath_settiming(sc); |
| 613 | break; |
| 614 | case ATH_SOFTLED: |
| 615 | if (val != sc->sc_softled) { |
| 616 | @@ -11223,6 +11337,9 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl |
| 617 | } |
| 618 | } else { |
| 619 | switch ((long)ctl->extra2) { |
| 620 | + case ATH_CHANBW: |
| 621 | + val = sc->sc_chanbw ?: 20; |
| 622 | + break; |
| 623 | case ATH_SLOTTIME: |
| 624 | val = ath_hal_getslottime(ah); |
| 625 | break; |
| 626 | @@ -11241,6 +11358,9 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl |
| 627 | case ATH_COUNTRYCODE: |
| 628 | ath_hal_getcountrycode(ah, &val); |
| 629 | break; |
| 630 | + case ATH_OUTDOOR: |
| 631 | + val = ic->ic_country_outdoor; |
| 632 | + break; |
| 633 | case ATH_MAXVAPS: |
| 634 | val = ath_maxvaps; |
| 635 | break; |
| 636 | @@ -11354,11 +11474,17 @@ static const ctl_table ath_sysctl_templa |
| 637 | }, |
| 638 | { .ctl_name = CTL_AUTO, |
| 639 | .procname = "countrycode", |
| 640 | - .mode = 0444, |
| 641 | + .mode = 0644, |
| 642 | .proc_handler = ath_sysctl_halparam, |
| 643 | .extra2 = (void *)ATH_COUNTRYCODE, |
| 644 | }, |
| 645 | { .ctl_name = CTL_AUTO, |
| 646 | + .procname = "outdoor", |
| 647 | + .mode = 0644, |
| 648 | + .proc_handler = ath_sysctl_halparam, |
| 649 | + .extra2 = (void *)ATH_OUTDOOR, |
| 650 | + }, |
| 651 | + { .ctl_name = CTL_AUTO, |
| 652 | .procname = "maxvaps", |
| 653 | .mode = 0444, |
| 654 | .proc_handler = ath_sysctl_halparam, |
| 655 | @@ -11366,7 +11492,7 @@ static const ctl_table ath_sysctl_templa |
| 656 | }, |
| 657 | { .ctl_name = CTL_AUTO, |
| 658 | .procname = "regdomain", |
| 659 | - .mode = 0444, |
| 660 | + .mode = 0644, |
| 661 | .proc_handler = ath_sysctl_halparam, |
| 662 | .extra2 = (void *)ATH_REGDOMAIN, |
| 663 | }, |
| 664 | @@ -11429,6 +11555,12 @@ static const ctl_table ath_sysctl_templa |
| 665 | .extra2 = (void *)ATH_ACKRATE, |
| 666 | }, |
| 667 | { .ctl_name = CTL_AUTO, |
| 668 | + .procname = "channelbw", |
| 669 | + .mode = 0644, |
| 670 | + .proc_handler = ath_sysctl_halparam, |
| 671 | + .extra2 = (void *)ATH_CHANBW, |
| 672 | + }, |
| 673 | + { .ctl_name = CTL_AUTO, |
| 674 | .procname = "rp", |
| 675 | .mode = 0200, |
| 676 | .proc_handler = ath_sysctl_halparam, |
| 677 | @@ -11669,13 +11801,6 @@ static ctl_table ath_static_sysctls[] = |
| 678 | }, |
| 679 | #endif |
| 680 | { .ctl_name = CTL_AUTO, |
| 681 | - .procname = "countrycode", |
| 682 | - .mode = 0444, |
| 683 | - .data = &ath_countrycode, |
| 684 | - .maxlen = sizeof(ath_countrycode), |
| 685 | - .proc_handler = proc_dointvec |
| 686 | - }, |
| 687 | - { .ctl_name = CTL_AUTO, |
| 688 | .procname = "maxvaps", |
| 689 | .mode = 0444, |
| 690 | .data = &ath_maxvaps, |
| 691 | @@ -11683,13 +11808,6 @@ static ctl_table ath_static_sysctls[] = |
| 692 | .proc_handler = proc_dointvec |
| 693 | }, |
| 694 | { .ctl_name = CTL_AUTO, |
| 695 | - .procname = "outdoor", |
| 696 | - .mode = 0444, |
| 697 | - .data = &ath_outdoor, |
| 698 | - .maxlen = sizeof(ath_outdoor), |
| 699 | - .proc_handler = proc_dointvec |
| 700 | - }, |
| 701 | - { .ctl_name = CTL_AUTO, |
| 702 | .procname = "xchanmode", |
| 703 | .mode = 0444, |
| 704 | .data = &ath_xchanmode, |
| 705 | --- a/ath/if_athvar.h |
| 706 | +++ b/ath/if_athvar.h |
| 707 | @@ -688,17 +688,18 @@ struct ath_softc { |
| 708 | int8_t sc_ofdm_weak_det; /* OFDM weak frames detection, -1 == auto */ |
| 709 | |
| 710 | /* rate tables */ |
| 711 | - const HAL_RATE_TABLE *sc_rates[IEEE80211_MODE_MAX]; |
| 712 | +#define ATH_MODE_HALF (IEEE80211_MODE_MAX) |
| 713 | +#define ATH_MODE_QUARTER (IEEE80211_MODE_MAX + 1) |
| 714 | + const HAL_RATE_TABLE *sc_rates[IEEE80211_MODE_MAX + 2]; |
| 715 | const HAL_RATE_TABLE *sc_currates; /* current rate table */ |
| 716 | const HAL_RATE_TABLE *sc_xr_rates; /* XR rate table */ |
| 717 | - const HAL_RATE_TABLE *sc_half_rates; /* half rate table */ |
| 718 | - const HAL_RATE_TABLE *sc_quarter_rates; /* quarter rate table */ |
| 719 | HAL_OPMODE sc_opmode; /* current hal operating mode */ |
| 720 | enum ieee80211_phymode sc_curmode; /* current phy mode */ |
| 721 | u_int sc_poweroffset; /* hardware power offset */ |
| 722 | u_int16_t sc_curtxpow; /* current tx power limit */ |
| 723 | u_int16_t sc_curaid; /* current association id */ |
| 724 | HAL_CHANNEL sc_curchan; /* current h/w channel */ |
| 725 | + u_int8_t sc_chanbw; /* channel bandwidth */ |
| 726 | u_int8_t sc_curbssid[IEEE80211_ADDR_LEN]; |
| 727 | u_int8_t sc_rixmap[256]; /* IEEE to h/w rate table ix */ |
| 728 | struct { |
| 729 | @@ -809,6 +810,8 @@ struct ath_softc { |
| 730 | u_int32_t sc_dturbo_bw_turbo; /* bandwidth threshold */ |
| 731 | #endif |
| 732 | u_int sc_slottimeconf; /* manual override for slottime */ |
| 733 | + u_int sc_acktimeconf; /* manual override for acktime */ |
| 734 | + u_int sc_ctstimeconf; /* manual override for ctstime */ |
| 735 | |
| 736 | struct timer_list sc_dfs_excl_timer; /* mark expiration timer task */ |
| 737 | struct timer_list sc_dfs_cac_timer; /* dfs wait timer */ |
| 738 | @@ -827,6 +830,7 @@ struct ath_softc { |
| 739 | int sc_rp_num; |
| 740 | int sc_rp_min; |
| 741 | HAL_BOOL (*sc_rp_analyse)(struct ath_softc *sc); |
| 742 | + struct ATH_TQ_STRUCT sc_refresh_tq; |
| 743 | struct ATH_TQ_STRUCT sc_rp_tq; |
| 744 | |
| 745 | int sc_rp_ignored; /* if set, we ignored all |
| 746 | @@ -942,6 +946,48 @@ int ar_device(int devid); |
| 747 | DEV_NAME(_v->iv_ic->ic_dev)) |
| 748 | |
| 749 | void ath_radar_detected(struct ath_softc *sc, const char* message); |
| 750 | +static inline u_int getTimingOffset(struct ath_softc *sc) |
| 751 | +{ |
| 752 | + struct ieee80211com *ic = &sc->sc_ic; |
| 753 | + u_int usec = 9; |
| 754 | + if (IEEE80211_IS_CHAN_ANYG(ic->ic_curchan)) { |
| 755 | + usec = 20; |
| 756 | + if (ic->ic_flags & IEEE80211_F_SHSLOT) |
| 757 | + usec = 9; |
| 758 | + } else if (IEEE80211_IS_CHAN_A(ic->ic_curchan)) |
| 759 | + usec = 9; |
| 760 | + |
| 761 | + if (IEEE80211_IS_CHAN_TURBO(ic->ic_curchan)) |
| 762 | + usec = 6; |
| 763 | + |
| 764 | + if (IEEE80211_IS_CHAN_HALF(ic->ic_curchan)) |
| 765 | + usec = 13; |
| 766 | + else if (IEEE80211_IS_CHAN_QUARTER(ic->ic_curchan)) |
| 767 | + usec = 21; |
| 768 | + return usec; |
| 769 | +} |
| 770 | + |
| 771 | +static inline void ath_get_timings(struct ath_softc *sc, u_int *t_slot, u_int *t_sifs, u_int *t_difs) |
| 772 | +{ |
| 773 | + struct ieee80211_channel *c = sc->sc_ic.ic_curchan; |
| 774 | + |
| 775 | + *t_slot = getTimingOffset(sc) + sc->sc_slottimeconf; |
| 776 | + |
| 777 | + if (IEEE80211_IS_CHAN_HALF(c)) { |
| 778 | + *t_sifs = 32; |
| 779 | + *t_difs = 56; |
| 780 | + } else if (IEEE80211_IS_CHAN_QUARTER(c)) { |
| 781 | + *t_sifs = 64; |
| 782 | + *t_difs = 112; |
| 783 | + } else if (IEEE80211_IS_CHAN_TURBO(c)) { |
| 784 | + *t_sifs = 8; |
| 785 | + *t_difs = 28; |
| 786 | + } else { |
| 787 | + *t_sifs = 16; |
| 788 | + *t_difs = 28; |
| 789 | + } |
| 790 | +} |
| 791 | + |
| 792 | |
| 793 | struct ath_hw_detect { |
| 794 | const char *vendor_name; |
| 795 | --- a/tools/athctrl.c |
| 796 | +++ b/tools/athctrl.c |
| 797 | @@ -118,7 +118,7 @@ CMD(athctrl)(int argc, char *argv[]) |
| 798 | } |
| 799 | |
| 800 | if (distance >= 0) { |
| 801 | - int slottime = 9 + (distance / 300) + ((distance % 300) ? 1 : 0); |
| 802 | + int slottime = (distance / 300) + ((distance % 300) ? 1 : 0); |
| 803 | int acktimeout = slottime * 2 + 3; |
| 804 | int ctstimeout = slottime * 2 + 3; |
| 805 | |
| 806 | --- a/net80211/ieee80211.c |
| 807 | +++ b/net80211/ieee80211.c |
| 808 | @@ -243,34 +243,17 @@ static const struct country_code_to_str |
| 809 | {CTRY_ZIMBABWE, "ZW"} |
| 810 | }; |
| 811 | |
| 812 | -int |
| 813 | -ieee80211_ifattach(struct ieee80211com *ic) |
| 814 | +void ieee80211_update_channels(struct ieee80211com *ic, int init) |
| 815 | { |
| 816 | - struct net_device *dev = ic->ic_dev; |
| 817 | struct ieee80211_channel *c; |
| 818 | + struct ieee80211vap *vap; |
| 819 | struct ifmediareq imr; |
| 820 | + int ext = 0; |
| 821 | int i; |
| 822 | |
| 823 | - _MOD_INC_USE(THIS_MODULE, return -ENODEV); |
| 824 | - |
| 825 | - /* |
| 826 | - * Pick an initial operating mode until we have a vap |
| 827 | - * created to lock it down correctly. This is only |
| 828 | - * drivers have something defined for configuring the |
| 829 | - * hardware at startup. |
| 830 | - */ |
| 831 | - ic->ic_opmode = IEEE80211_M_STA; /* everyone supports this */ |
| 832 | - |
| 833 | - /* |
| 834 | - * Fill in 802.11 available channel set, mark |
| 835 | - * all available channels as active, and pick |
| 836 | - * a default channel if not already specified. |
| 837 | - */ |
| 838 | - KASSERT(0 < ic->ic_nchans && ic->ic_nchans < IEEE80211_CHAN_MAX, |
| 839 | - ("invalid number of channels specified: %u", ic->ic_nchans)); |
| 840 | memset(ic->ic_chan_avail, 0, sizeof(ic->ic_chan_avail)); |
| 841 | - ic->ic_modecaps |= 1 << IEEE80211_MODE_AUTO; |
| 842 | ic->ic_max_txpower = IEEE80211_TXPOWER_MIN; |
| 843 | + ic->ic_modecaps = 1 << IEEE80211_MODE_AUTO; |
| 844 | |
| 845 | for (i = 0; i < ic->ic_nchans; i++) { |
| 846 | c = &ic->ic_channels[i]; |
| 847 | @@ -298,6 +281,8 @@ ieee80211_ifattach(struct ieee80211com * |
| 848 | ic->ic_modecaps |= 1 << IEEE80211_MODE_TURBO_A; |
| 849 | if (IEEE80211_IS_CHAN_108G(c)) |
| 850 | ic->ic_modecaps |= 1 << IEEE80211_MODE_TURBO_G; |
| 851 | + if (IEEE80211_IS_CHAN_HALF(c) || IEEE80211_IS_CHAN_QUARTER(c)) |
| 852 | + ext = 1; |
| 853 | } |
| 854 | /* Initialize candidate channels to all available */ |
| 855 | memcpy(ic->ic_chan_active, ic->ic_chan_avail, |
| 856 | @@ -311,11 +296,59 @@ ieee80211_ifattach(struct ieee80211com * |
| 857 | * When 11g is supported, force the rate set to |
| 858 | * include basic rates suitable for a mixed b/g bss. |
| 859 | */ |
| 860 | - if (ic->ic_modecaps & (1 << IEEE80211_MODE_11G)) |
| 861 | + if ((ic->ic_modecaps & (1 << IEEE80211_MODE_11G)) && !ext) |
| 862 | ieee80211_set11gbasicrates( |
| 863 | &ic->ic_sup_rates[IEEE80211_MODE_11G], |
| 864 | IEEE80211_MODE_11G); |
| 865 | |
| 866 | + if (init) |
| 867 | + return; |
| 868 | + |
| 869 | + ifmedia_removeall(&ic->ic_media); |
| 870 | + ieee80211_media_setup(ic, &ic->ic_media, ic->ic_caps, NULL, NULL); |
| 871 | + ieee80211com_media_status(ic->ic_dev, &imr); |
| 872 | + ifmedia_set(&ic->ic_media, imr.ifm_active); |
| 873 | + |
| 874 | + TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { |
| 875 | + struct ieee80211vap *avp; |
| 876 | + TAILQ_FOREACH(avp, &vap->iv_wdslinks, iv_wdsnext) { |
| 877 | + (void) ieee80211_media_setup(ic, &vap->iv_media, vap->iv_caps, NULL, NULL); |
| 878 | + ieee80211_media_status(vap->iv_dev, &imr); |
| 879 | + ifmedia_set(&vap->iv_media, imr.ifm_active); |
| 880 | + } |
| 881 | + (void) ieee80211_media_setup(ic, &vap->iv_media, vap->iv_caps, NULL, NULL); |
| 882 | + ieee80211_media_status(vap->iv_dev, &imr); |
| 883 | + ifmedia_set(&vap->iv_media, imr.ifm_active); |
| 884 | + } |
| 885 | +} |
| 886 | +EXPORT_SYMBOL(ieee80211_update_channels); |
| 887 | + |
| 888 | +int |
| 889 | +ieee80211_ifattach(struct ieee80211com *ic) |
| 890 | +{ |
| 891 | + struct net_device *dev = ic->ic_dev; |
| 892 | + struct ieee80211_channel *c; |
| 893 | + struct ifmediareq imr; |
| 894 | + |
| 895 | + _MOD_INC_USE(THIS_MODULE, return -ENODEV); |
| 896 | + |
| 897 | + /* |
| 898 | + * Pick an initial operating mode until we have a vap |
| 899 | + * created to lock it down correctly. This is only |
| 900 | + * drivers have something defined for configuring the |
| 901 | + * hardware at startup. |
| 902 | + */ |
| 903 | + ic->ic_opmode = IEEE80211_M_STA; /* everyone supports this */ |
| 904 | + |
| 905 | + /* |
| 906 | + * Fill in 802.11 available channel set, mark |
| 907 | + * all available channels as active, and pick |
| 908 | + * a default channel if not already specified. |
| 909 | + */ |
| 910 | + KASSERT(0 < ic->ic_nchans && ic->ic_nchans < IEEE80211_CHAN_MAX, |
| 911 | + ("invalid number of channels specified: %u", ic->ic_nchans)); |
| 912 | + ieee80211_update_channels(ic, 1); |
| 913 | + |
| 914 | /* Setup initial channel settings */ |
| 915 | ic->ic_bsschan = IEEE80211_CHAN_ANYC; |
| 916 | /* Arbitrarily pick the first channel */ |
| 917 | @@ -327,6 +360,7 @@ ieee80211_ifattach(struct ieee80211com * |
| 918 | /* Enable WME by default, if we're capable. */ |
| 919 | if (ic->ic_caps & IEEE80211_C_WME) |
| 920 | ic->ic_flags |= IEEE80211_F_WME; |
| 921 | + |
| 922 | (void) ieee80211_setmode(ic, ic->ic_curmode); |
| 923 | |
| 924 | /* Store default beacon interval, as nec. */ |
| 925 | @@ -763,7 +797,8 @@ ieee80211_media_setup(struct ieee80211co |
| 926 | struct ieee80211_rateset allrates; |
| 927 | |
| 928 | /* Fill in media characteristics. */ |
| 929 | - ifmedia_init(media, 0, media_change, media_stat); |
| 930 | + if (media_change || media_stat) |
| 931 | + ifmedia_init(media, 0, media_change, media_stat); |
| 932 | maxrate = 0; |
| 933 | memset(&allrates, 0, sizeof(allrates)); |
| 934 | |
| 935 | @@ -793,7 +828,7 @@ ieee80211_media_setup(struct ieee80211co |
| 936 | ADD(media, IFM_AUTO, mopt | IFM_IEEE80211_WDS); |
| 937 | if (mode == IEEE80211_MODE_AUTO) |
| 938 | continue; |
| 939 | - rs = &ic->ic_sup_rates[mode]; |
| 940 | + rs = &ic->ic_sup_rates[ieee80211_chan2ratemode(ic->ic_curchan, mode)]; |
| 941 | |
| 942 | for (i = 0; i < rs->rs_nrates; i++) { |
| 943 | rate = rs->rs_rates[i]; |
| 944 | @@ -1207,7 +1242,7 @@ ieee80211_announce(struct ieee80211com * |
| 945 | if ((ic->ic_modecaps & (1 << mode)) == 0) |
| 946 | continue; |
| 947 | if_printf(dev, "%s rates: ", ieee80211_phymode_name[mode]); |
| 948 | - rs = &ic->ic_sup_rates[mode]; |
| 949 | + rs = &ic->ic_sup_rates[ieee80211_chan2ratemode(ic->ic_curchan, mode)]; |
| 950 | for (i = 0; i < rs->rs_nrates; i++) { |
| 951 | rate = rs->rs_rates[i]; |
| 952 | mword = ieee80211_rate2media(ic, rate, mode); |
| 953 | @@ -1417,7 +1452,7 @@ ieee80211com_media_change(struct net_dev |
| 954 | * now so drivers have a consistent state. |
| 955 | */ |
| 956 | KASSERT(vap->iv_bss != NULL, ("no bss node")); |
| 957 | - vap->iv_bss->ni_rates = ic->ic_sup_rates[newphymode]; |
| 958 | + vap->iv_bss->ni_rates = ic->ic_sup_rates[ieee80211_chan2ratemode(ic->ic_curchan, newphymode)]; |
| 959 | } |
| 960 | error = -ENETRESET; |
| 961 | } |
| 962 | @@ -1435,7 +1470,7 @@ findrate(struct ieee80211com *ic, enum i |
| 963 | { |
| 964 | #define IEEERATE(_ic,_m,_i) \ |
| 965 | ((_ic)->ic_sup_rates[_m].rs_rates[_i] & IEEE80211_RATE_VAL) |
| 966 | - int i, nrates = ic->ic_sup_rates[mode].rs_nrates; |
| 967 | + int i, nrates = ic->ic_sup_rates[ieee80211_chan2ratemode(ic->ic_curchan, mode)].rs_nrates; |
| 968 | for (i = 0; i < nrates; i++) |
| 969 | if (IEEERATE(ic, mode, i) == rate) |
| 970 | return i; |
| 971 | @@ -1877,11 +1912,6 @@ ieee80211_build_countryie(struct ieee802 |
| 972 | if (ieee80211_chan2mode(c) != curmode_noturbo) |
| 973 | continue; |
| 974 | |
| 975 | - /* Skip half/quarter rate channels */ |
| 976 | - if (IEEE80211_IS_CHAN_HALF(c) || |
| 977 | - IEEE80211_IS_CHAN_QUARTER(c)) |
| 978 | - continue; |
| 979 | - |
| 980 | if (*cur_runlen == 0) { |
| 981 | (*cur_runlen)++; |
| 982 | *cur_pow = c->ic_maxregpower; |
| 983 | @@ -1915,7 +1945,7 @@ void |
| 984 | ieee80211_build_sc_ie(struct ieee80211com *ic) |
| 985 | { |
| 986 | struct ieee80211_ie_sc *ie = &ic->ic_sc_ie; |
| 987 | - int i, j; |
| 988 | + int i, j, k; |
| 989 | struct ieee80211_channel *c; |
| 990 | u_int8_t prevchan; |
| 991 | |
| 992 | --- a/net80211/ieee80211_var.h |
| 993 | +++ b/net80211/ieee80211_var.h |
| 994 | @@ -336,8 +336,6 @@ struct ieee80211com { |
| 995 | u_int8_t ic_nopened; /* VAPs been opened */ |
| 996 | struct ieee80211_rateset ic_sup_rates[IEEE80211_MODE_MAX]; |
| 997 | struct ieee80211_rateset ic_sup_xr_rates; |
| 998 | - struct ieee80211_rateset ic_sup_half_rates; |
| 999 | - struct ieee80211_rateset ic_sup_quarter_rates; |
| 1000 | u_int16_t ic_modecaps; /* set of mode capabilities */ |
| 1001 | u_int16_t ic_curmode; /* current mode */ |
| 1002 | u_int16_t ic_lintval; /* beacon interval */ |
| 1003 | @@ -714,6 +712,7 @@ MALLOC_DECLARE(M_80211_VAP); |
| 1004 | |
| 1005 | int ieee80211_ifattach(struct ieee80211com *); |
| 1006 | void ieee80211_ifdetach(struct ieee80211com *); |
| 1007 | +void ieee80211_update_channels(struct ieee80211com *ic, int); |
| 1008 | int ieee80211_vap_setup(struct ieee80211com *, struct net_device *, |
| 1009 | const char *, int, int, struct ieee80211vap *); |
| 1010 | int ieee80211_vap_attach(struct ieee80211vap *, ifm_change_cb_t, ifm_stat_cb_t); |
| 1011 | @@ -793,6 +792,23 @@ ieee80211_anyhdrspace(struct ieee80211co |
| 1012 | return size; |
| 1013 | } |
| 1014 | |
| 1015 | +static __inline int |
| 1016 | +ieee80211_chan2ratemode(struct ieee80211_channel *c, int mode) |
| 1017 | +{ |
| 1018 | + if (mode == -1) |
| 1019 | + mode = ieee80211_chan2mode(c); |
| 1020 | + |
| 1021 | + /* |
| 1022 | + * Use 11a rateset for half/quarter to restrict things |
| 1023 | + * to pure OFDM |
| 1024 | + */ |
| 1025 | + if (IEEE80211_IS_CHAN_HALF(c) || |
| 1026 | + IEEE80211_IS_CHAN_QUARTER(c)) |
| 1027 | + return IEEE80211_MODE_11A; |
| 1028 | + |
| 1029 | + return mode; |
| 1030 | +} |
| 1031 | + |
| 1032 | /* Macros to print MAC address used in 802.11 headers */ |
| 1033 | |
| 1034 | #define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x" |
| 1035 | --- a/net80211/ieee80211_node.c |
| 1036 | +++ b/net80211/ieee80211_node.c |
| 1037 | @@ -287,7 +287,7 @@ ieee80211_node_set_chan(struct ieee80211 |
| 1038 | ni->ni_rates = ic->ic_sup_xr_rates; |
| 1039 | else |
| 1040 | #endif |
| 1041 | - ni->ni_rates = ic->ic_sup_rates[ieee80211_chan2mode(chan)]; |
| 1042 | + ni->ni_rates = ic->ic_sup_rates[ieee80211_chan2ratemode(chan, -1)]; |
| 1043 | } |
| 1044 | |
| 1045 | static __inline void |
| 1046 | @@ -387,6 +387,8 @@ ieee80211_create_ibss(struct ieee80211va |
| 1047 | ic->ic_bsschan = chan; |
| 1048 | ieee80211_node_set_chan(ic, ni); |
| 1049 | ic->ic_curmode = ieee80211_chan2mode(chan); |
| 1050 | + ni->ni_rates = ic->ic_sup_rates[ieee80211_chan2ratemode(chan, -1)]; |
| 1051 | + |
| 1052 | spin_lock_irqsave(&channel_lock, flags); |
| 1053 | ieee80211_scan_set_bss_channel(ic, ic->ic_bsschan); |
| 1054 | spin_unlock_irqrestore(&channel_lock, flags); |
| 1055 | @@ -394,14 +396,8 @@ ieee80211_create_ibss(struct ieee80211va |
| 1056 | /* Update country ie information */ |
| 1057 | ieee80211_build_countryie(ic); |
| 1058 | |
| 1059 | - if (IEEE80211_IS_CHAN_HALF(chan)) { |
| 1060 | - ni->ni_rates = ic->ic_sup_half_rates; |
| 1061 | - } else if (IEEE80211_IS_CHAN_QUARTER(chan)) { |
| 1062 | - ni->ni_rates = ic->ic_sup_quarter_rates; |
| 1063 | - } |
| 1064 | - |
| 1065 | - if ((vap->iv_flags & IEEE80211_F_PUREG) && |
| 1066 | - IEEE80211_IS_CHAN_ANYG(chan)) { |
| 1067 | + if ((ieee80211_chan2ratemode(chan, -1) != IEEE80211_MODE_11A) && |
| 1068 | + IEEE80211_IS_CHAN_ANYG(chan) && (vap->iv_flags & IEEE80211_F_PUREG)) { |
| 1069 | ieee80211_setpuregbasicrates(&ni->ni_rates); |
| 1070 | } |
| 1071 | |
| 1072 | --- a/net80211/ieee80211_scan_sta.c |
| 1073 | +++ b/net80211/ieee80211_scan_sta.c |
| 1074 | @@ -490,12 +490,7 @@ check_rate(struct ieee80211vap *vap, con |
| 1075 | |
| 1076 | okrate = badrate = fixedrate = 0; |
| 1077 | |
| 1078 | - if (IEEE80211_IS_CHAN_HALF(se->se_chan)) |
| 1079 | - srs = &ic->ic_sup_half_rates; |
| 1080 | - else if (IEEE80211_IS_CHAN_QUARTER(se->se_chan)) |
| 1081 | - srs = &ic->ic_sup_quarter_rates; |
| 1082 | - else |
| 1083 | - srs = &ic->ic_sup_rates[ieee80211_chan2mode(se->se_chan)]; |
| 1084 | + srs = &ic->ic_sup_rates[ieee80211_chan2ratemode(ic->ic_curchan, -1)]; |
| 1085 | nrs = se->se_rates[1]; |
| 1086 | rs = se->se_rates + 2; |
| 1087 | fixedrate = IEEE80211_FIXED_RATE_NONE; |
| 1088 | --- a/net80211/ieee80211_output.c |
| 1089 | +++ b/net80211/ieee80211_output.c |
| 1090 | @@ -1676,8 +1676,8 @@ ieee80211_send_probereq(struct ieee80211 |
| 1091 | |
| 1092 | frm = ieee80211_add_ssid(frm, ssid, ssidlen); |
| 1093 | mode = ieee80211_chan2mode(ic->ic_curchan); |
| 1094 | - frm = ieee80211_add_rates(frm, &ic->ic_sup_rates[mode]); |
| 1095 | - frm = ieee80211_add_xrates(frm, &ic->ic_sup_rates[mode]); |
| 1096 | + frm = ieee80211_add_rates(frm, &ic->ic_sup_rates[ieee80211_chan2ratemode(ic->ic_curchan, mode)]); |
| 1097 | + frm = ieee80211_add_xrates(frm, &ic->ic_sup_rates[ieee80211_chan2ratemode(ic->ic_curchan, mode)]); |
| 1098 | |
| 1099 | if (optie != NULL) { |
| 1100 | memcpy(frm, optie, optielen); |
| 1101 | --- a/net80211/ieee80211_proto.c |
| 1102 | +++ b/net80211/ieee80211_proto.c |
| 1103 | @@ -404,7 +404,7 @@ ieee80211_fix_rate(struct ieee80211_node |
| 1104 | |
| 1105 | error = 0; |
| 1106 | okrate = badrate = fixedrate = 0; |
| 1107 | - srs = &ic->ic_sup_rates[ieee80211_chan2mode(ni->ni_chan)]; |
| 1108 | + srs = &ic->ic_sup_rates[ieee80211_chan2ratemode(ic->ic_curchan, -1)]; |
| 1109 | nrs = &ni->ni_rates; |
| 1110 | fixedrate = IEEE80211_FIXED_RATE_NONE; |
| 1111 | for (i = 0; i < nrs->rs_nrates;) { |
| 1112 | @@ -1407,6 +1407,7 @@ ieee80211_new_state(struct ieee80211vap |
| 1113 | IEEE80211_VAPS_UNLOCK_IRQ(ic); |
| 1114 | return rc; |
| 1115 | } |
| 1116 | +EXPORT_SYMBOL(ieee80211_new_state); |
| 1117 | |
| 1118 | static int |
| 1119 | __ieee80211_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) |
| 1120 | --- a/ath_rate/minstrel/minstrel.c |
| 1121 | +++ b/ath_rate/minstrel/minstrel.c |
| 1122 | @@ -195,31 +195,7 @@ calc_usecs_unicast_packet(struct ath_sof |
| 1123 | return 0; |
| 1124 | } |
| 1125 | |
| 1126 | - /* XXX: Getting MAC/PHY level timings should be fixed for turbo |
| 1127 | - * rates, and there is probably a way to get this from the |
| 1128 | - * HAL... */ |
| 1129 | - switch (rt->info[rix].phy) { |
| 1130 | - case IEEE80211_T_OFDM: |
| 1131 | -#if 0 |
| 1132 | - t_slot = 9; |
| 1133 | - t_sifs = 16; |
| 1134 | - t_difs = 28; |
| 1135 | - /* fall through */ |
| 1136 | -#endif |
| 1137 | - case IEEE80211_T_TURBO: |
| 1138 | - t_slot = 9; |
| 1139 | - t_sifs = 8; |
| 1140 | - t_difs = 28; |
| 1141 | - break; |
| 1142 | - case IEEE80211_T_DS: |
| 1143 | - /* Fall through to default */ |
| 1144 | - default: |
| 1145 | - /* pg. 205 ieee.802.11.pdf */ |
| 1146 | - t_slot = 20; |
| 1147 | - t_difs = 50; |
| 1148 | - t_sifs = 10; |
| 1149 | - } |
| 1150 | - |
| 1151 | + ath_get_timings(sc, &t_slot, &t_sifs, &t_difs); |
| 1152 | if ((ic->ic_flags & IEEE80211_F_USEPROT) && |
| 1153 | (rt->info[rix].phy == IEEE80211_T_OFDM)) { |
| 1154 | if (ic->ic_protmode == IEEE80211_PROT_RTSCTS) |
| 1155 | --- a/ath_rate/sample/sample.c |
| 1156 | +++ b/ath_rate/sample/sample.c |
| 1157 | @@ -172,26 +172,7 @@ calc_usecs_unicast_packet(struct ath_sof |
| 1158 | * rates, and there is probably a way to get this from the |
| 1159 | * hal... |
| 1160 | */ |
| 1161 | - switch (rt->info[rix].phy) { |
| 1162 | - case IEEE80211_T_OFDM: |
| 1163 | - t_slot = 9; |
| 1164 | - t_sifs = 16; |
| 1165 | - t_difs = 28; |
| 1166 | - /* fall through */ |
| 1167 | - case IEEE80211_T_TURBO: |
| 1168 | - t_slot = 9; |
| 1169 | - t_sifs = 8; |
| 1170 | - t_difs = 28; |
| 1171 | - break; |
| 1172 | - case IEEE80211_T_DS: |
| 1173 | - /* fall through to default */ |
| 1174 | - default: |
| 1175 | - /* pg 205 ieee.802.11.pdf */ |
| 1176 | - t_slot = 20; |
| 1177 | - t_difs = 50; |
| 1178 | - t_sifs = 10; |
| 1179 | - } |
| 1180 | - |
| 1181 | + ath_get_timings(sc, &t_slot, &t_sifs, &t_difs); |
| 1182 | rts = cts = 0; |
| 1183 | |
| 1184 | if ((ic->ic_flags & IEEE80211_F_USEPROT) && |
| 1185 | --- a/net80211/ieee80211_wireless.c |
| 1186 | +++ b/net80211/ieee80211_wireless.c |
| 1187 | @@ -2142,7 +2142,7 @@ ieee80211_ioctl_setmode(struct net_devic |
| 1188 | |
| 1189 | vap->iv_des_mode = mode; |
| 1190 | if (IS_UP_AUTO(vap)) |
| 1191 | - ieee80211_new_state(vap, IEEE80211_S_SCAN, 0); |
| 1192 | + ieee80211_init(vap->iv_dev, 0); |
| 1193 | |
| 1194 | retv = 0; |
| 1195 | } |
| 1196 | @@ -4090,46 +4090,60 @@ ieee80211_ioctl_getchanlist(struct net_d |
| 1197 | return 0; |
| 1198 | } |
| 1199 | |
| 1200 | +static int alreadyListed(struct ieee80211req_chaninfo *chans, u_int16_t mhz) |
| 1201 | +{ |
| 1202 | + int i; |
| 1203 | + for (i = 0; i < chans->ic_nchans; i++) { |
| 1204 | + if (chans->ic_chans[i].ic_freq == mhz) |
| 1205 | + return 1; |
| 1206 | + } |
| 1207 | + return 0; |
| 1208 | +} |
| 1209 | + |
| 1210 | static int |
| 1211 | ieee80211_ioctl_getchaninfo(struct net_device *dev, |
| 1212 | - struct iw_request_info *info, void *w, char *extra) |
| 1213 | + struct iw_request_info *info, void *w, char *extra) |
| 1214 | { |
| 1215 | struct ieee80211vap *vap = dev->priv; |
| 1216 | struct ieee80211com *ic = vap->iv_ic; |
| 1217 | - struct ieee80211req_chaninfo chans; |
| 1218 | + struct ieee80211req_chaninfo *chans = |
| 1219 | + (struct ieee80211req_chaninfo *)extra; |
| 1220 | + |
| 1221 | u_int8_t reported[IEEE80211_CHAN_BYTES]; /* XXX stack usage? */ |
| 1222 | int i; |
| 1223 | |
| 1224 | - memset(&chans, 0, sizeof(chans)); |
| 1225 | - memset(&reported, 0, sizeof(reported)); |
| 1226 | + memset(chans, 0, sizeof(*chans)); |
| 1227 | + memset(reported, 0, sizeof(reported)); |
| 1228 | for (i = 0; i < ic->ic_nchans; i++) { |
| 1229 | const struct ieee80211_channel *c = &ic->ic_channels[i]; |
| 1230 | const struct ieee80211_channel *c1 = c; |
| 1231 | |
| 1232 | - if (isclr(reported, c->ic_ieee)) { |
| 1233 | + if (!alreadyListed(chans, c->ic_freq)) { |
| 1234 | setbit(reported, c->ic_ieee); |
| 1235 | |
| 1236 | - /* pick turbo channel over non-turbo channel, and |
| 1237 | - * 11g channel over 11b channel */ |
| 1238 | if (IEEE80211_IS_CHAN_A(c)) |
| 1239 | - c1 = findchannel(ic, c->ic_ieee, IEEE80211_MODE_TURBO_A); |
| 1240 | + c1 = findchannel(ic, c->ic_freq, |
| 1241 | + IEEE80211_MODE_TURBO_A); |
| 1242 | if (IEEE80211_IS_CHAN_ANYG(c)) |
| 1243 | - c1 = findchannel(ic, c->ic_ieee, IEEE80211_MODE_TURBO_G); |
| 1244 | + c1 = findchannel(ic, c->ic_freq, |
| 1245 | + IEEE80211_MODE_TURBO_G); |
| 1246 | else if (IEEE80211_IS_CHAN_B(c)) { |
| 1247 | - c1 = findchannel(ic, c->ic_ieee, IEEE80211_MODE_TURBO_G); |
| 1248 | + c1 = findchannel(ic, c->ic_freq, |
| 1249 | + IEEE80211_MODE_TURBO_G); |
| 1250 | if (!c1) |
| 1251 | - c1 = findchannel(ic, c->ic_ieee, IEEE80211_MODE_11G); |
| 1252 | + c1 = findchannel(ic, c->ic_freq, |
| 1253 | + IEEE80211_MODE_11G); |
| 1254 | } |
| 1255 | |
| 1256 | if (c1) |
| 1257 | c = c1; |
| 1258 | - /* Copy the entire structure, whereas it used to just copy a few fields */ |
| 1259 | - memcpy(&chans.ic_chans[chans.ic_nchans], c, sizeof(struct ieee80211_channel)); |
| 1260 | - if (++chans.ic_nchans >= IEEE80211_CHAN_MAX) |
| 1261 | + chans->ic_chans[chans->ic_nchans].ic_ieee = c->ic_ieee; |
| 1262 | + chans->ic_chans[chans->ic_nchans].ic_freq = c->ic_freq; |
| 1263 | + chans->ic_chans[chans->ic_nchans].ic_flags = c->ic_flags; |
| 1264 | + if (++chans->ic_nchans >= IEEE80211_CHAN_MAX) |
| 1265 | break; |
| 1266 | } |
| 1267 | } |
| 1268 | - memcpy(extra, &chans, sizeof(struct ieee80211req_chaninfo)); |
| 1269 | return 0; |
| 1270 | } |
| 1271 | |
| 1272 | --- a/net80211/ieee80211_scan_ap.c |
| 1273 | +++ b/net80211/ieee80211_scan_ap.c |
| 1274 | @@ -512,12 +512,13 @@ pick_channel(struct ieee80211_scan_state |
| 1275 | int ss_last = ss->ss_last; |
| 1276 | struct ieee80211_channel *best; |
| 1277 | struct ap_state *as = ss->ss_priv; |
| 1278 | - struct channel chans[ss_last]; /* actually ss_last-1 is required */ |
| 1279 | + struct channel *chans; /* actually ss_last-1 is required */ |
| 1280 | struct channel *c = NULL; |
| 1281 | struct pc_params params = { vap, ss, flags }; |
| 1282 | int benefit = 0; |
| 1283 | int sta_assoc = 0; |
| 1284 | |
| 1285 | + chans = (struct channel *)kmalloc(ss_last*sizeof(struct channel),GFP_ATOMIC); |
| 1286 | for (i = 0; i < ss_last; i++) { |
| 1287 | chans[i].chan = ss->ss_chans[i]; |
| 1288 | chans[i].orig = i; |
| 1289 | @@ -571,6 +572,7 @@ pick_channel(struct ieee80211_scan_state |
| 1290 | "%s: best: channel %u rssi %d\n", |
| 1291 | __func__, i, as->as_maxrssi[i]); |
| 1292 | } |
| 1293 | + kfree(chans); |
| 1294 | return best; |
| 1295 | } |
| 1296 | |
| 1297 | @@ -609,6 +611,7 @@ ap_end(struct ieee80211_scan_state *ss, |
| 1298 | res = 1; /* Do NOT restart scan */ |
| 1299 | } else { |
| 1300 | struct ieee80211_scan_entry se; |
| 1301 | + int i; |
| 1302 | /* XXX: notify all VAPs? */ |
| 1303 | /* if this is a dynamic turbo frequency , start with normal |
| 1304 | * mode first */ |
| 1305 | @@ -623,6 +626,11 @@ ap_end(struct ieee80211_scan_state *ss, |
| 1306 | return 0; |
| 1307 | } |
| 1308 | } |
| 1309 | + for (i = (bestchan - &ic->ic_channels[0])/sizeof(*bestchan) + 1; i < ic->ic_nchans; i++) { |
| 1310 | + if ((ic->ic_channels[i].ic_freq == bestchan->ic_freq) && |
| 1311 | + IEEE80211_IS_CHAN_ANYG(&ic->ic_channels[i])) |
| 1312 | + bestchan = &ic->ic_channels[i]; |
| 1313 | + } |
| 1314 | memset(&se, 0, sizeof(se)); |
| 1315 | se.se_chan = bestchan; |
| 1316 | |
| 1317 | --- a/tools/wlanconfig.c |
| 1318 | +++ b/tools/wlanconfig.c |
| 1319 | @@ -737,7 +737,7 @@ list_channels(const char *ifname, int al |
| 1320 | if (get80211priv(ifname, IEEE80211_IOCTL_GETCHANINFO, &chans, sizeof(chans)) < 0) |
| 1321 | errx(1, "unable to get channel information"); |
| 1322 | if (!allchans) { |
| 1323 | - uint8_t active[32]; |
| 1324 | + uint8_t active[IEEE80211_CHAN_BYTES]; |
| 1325 | |
| 1326 | if (get80211priv(ifname, IEEE80211_IOCTL_GETCHANLIST, &active, sizeof(active)) < 0) |
| 1327 | errx(1, "unable to get active channel list"); |
| 1328 | --- a/net80211/ieee80211_scan.c |
| 1329 | +++ b/net80211/ieee80211_scan.c |
| 1330 | @@ -1044,6 +1044,7 @@ ieee80211_scan_assoc_fail(struct ieee802 |
| 1331 | ss->ss_ops->scan_assoc_fail(ss, mac, reason); |
| 1332 | } |
| 1333 | } |
| 1334 | +EXPORT_SYMBOL(ieee80211_scan_flush); |
| 1335 | |
| 1336 | /* |
| 1337 | * Iterate over the contents of the scan cache. |
| 1338 | --- a/ath/if_ath_hal_wrappers.h |
| 1339 | +++ b/ath/if_ath_hal_wrappers.h |
| 1340 | @@ -111,6 +111,11 @@ static inline HAL_BOOL ath_hal_getregdom |
| 1341 | return (ath_hal_getcapability(ah, HAL_CAP_REG_DMN, 0, destination) == HAL_OK); |
| 1342 | } |
| 1343 | |
| 1344 | +static inline HAL_BOOL ath_hal_setregdomain(struct ath_hal *ah, u_int32_t v) |
| 1345 | +{ |
| 1346 | + return (ath_hal_setcapability(ah, HAL_CAP_REG_DMN, 0, v, NULL)); |
| 1347 | +} |
| 1348 | + |
| 1349 | static inline HAL_BOOL ath_hal_gettkipmic(struct ath_hal *ah) |
| 1350 | { |
| 1351 | return (ath_hal_getcapability(ah, HAL_CAP_TKIP_MIC, 1, NULL) == HAL_OK); |
| 1352 | |