diff options
author | Bjoern A. Zeeb <bz@FreeBSD.org> | 2020-09-12 19:33:25 +0000 |
---|---|---|
committer | Bjoern A. Zeeb <bz@FreeBSD.org> | 2020-09-12 19:33:25 +0000 |
commit | 752c173687a3f220c24e8e251a98b448dbeed3ff (patch) | |
tree | 355b76d1a6f3b353a476194481bb93fbcff4c37c | |
parent | c55ffe543826f574f6560b05642ee4c06178853c (diff) | |
download | src-test2-752c173687a3f220c24e8e251a98b448dbeed3ff.tar.gz src-test2-752c173687a3f220c24e8e251a98b448dbeed3ff.zip |
Notes
322 files changed, 4230 insertions, 1749 deletions
diff --git a/lib/lib80211/lib80211_regdomain.c b/lib/lib80211/lib80211_regdomain.c index ba80ceb4b38e..8dfd435e07a0 100644 --- a/lib/lib80211/lib80211_regdomain.c +++ b/lib/lib80211/lib80211_regdomain.c @@ -192,7 +192,7 @@ decode_flag(struct mystate *mt, const char *p, int len) FLAG(IEEE80211_CHAN_VHT40), FLAG(IEEE80211_CHAN_VHT80), /* - * XXX VHT80_80? This likely should be done by + * XXX VHT80P80? This likely should be done by * 80MHz chan logic in net80211 / ifconfig. */ FLAG(IEEE80211_CHAN_VHT160), diff --git a/lib/lib80211/lib80211_regdomain.h b/lib/lib80211/lib80211_regdomain.h index a8a4207c98ac..913dc161cdb0 100644 --- a/lib/lib80211/lib80211_regdomain.h +++ b/lib/lib80211/lib80211_regdomain.h @@ -73,10 +73,10 @@ struct regdomain { netband_head bands_11b; /* 11b operation */ netband_head bands_11g; /* 11g operation */ netband_head bands_11a; /* 11a operation */ - netband_head bands_11ng;/* 11ng operation */ - netband_head bands_11na;/* 11na operation */ - netband_head bands_11ac;/* 11ac 5GHz operation */ - netband_head bands_11acg;/* 11ac 2GHz operation */ + netband_head bands_11ng; /* 11ng operation */ + netband_head bands_11na; /* 11na operation */ + netband_head bands_11ac; /* 11ac 5GHz operation */ + netband_head bands_11acg; /* 11ac 2GHz operation */ LIST_ENTRY(regdomain) next; }; diff --git a/lib/lib80211/regdomain.xml b/lib/lib80211/regdomain.xml index 21d544cbb043..cad3039c3d3d 100644 --- a/lib/lib80211/regdomain.xml +++ b/lib/lib80211/regdomain.xml @@ -111,6 +111,44 @@ <flags>IEEE80211_CHAN_HT40</flags> </band> </netband> + <netband mode="11ac"> + <band> + <freqband ref="AC1_5180_5240_20"/> + <maxpower>17</maxpower> + <flags>IEEE80211_CHAN_HT20</flags> + <flags>IEEE80211_CHAN_VHT20</flags> + </band> + <band> + <freqband ref="AC1_5180_5240_40"/> + <maxpower>17</maxpower> + <flags>IEEE80211_CHAN_HT40</flags> + <flags>IEEE80211_CHAN_VHT40</flags> + </band> + <band> + <freqband ref="AC1_5180_5240_80"/> + <maxpower>17</maxpower> + <flags>IEEE80211_CHAN_HT40</flags> + <flags>IEEE80211_CHAN_VHT80</flags> + </band> + <band> + <freqband ref="AC1_5745_5805_20"/> + <maxpower>17</maxpower> + <flags>IEEE80211_CHAN_HT20</flags> + <flags>IEEE80211_CHAN_VHT20</flags> + </band> + <band> + <freqband ref="AC1_5745_5805_40"/> + <maxpower>17</maxpower> + <flags>IEEE80211_CHAN_HT40</flags> + <flags>IEEE80211_CHAN_VHT40</flags> + </band> + <band> + <freqband ref="AC1_5745_5805_80"/> + <maxpower>17</maxpower> + <flags>IEEE80211_CHAN_HT40</flags> + <flags>IEEE80211_CHAN_VHT80</flags> + </band> + </netband> </rd> <!-- FCC3 is FCC w/ DFS on Upper-UNI --> @@ -1735,6 +1773,21 @@ <chanwidth>20</chanwidth> <chansep>20</chansep> <flags>IEEE80211_CHAN_A</flags> </freqband> +<freqband id="AC1_5180_5240_20"> + <freqstart>5180</freqstart> <freqend>5240</freqend> + <chanwidth>20</chanwidth> <chansep>20</chansep> + <flags>IEEE80211_CHAN_A</flags> +</freqband> +<freqband id="AC1_5180_5240_40"> + <freqstart>5180</freqstart> <freqend>5240</freqend> + <chanwidth>40</chanwidth> <chansep>20</chansep> + <flags>IEEE80211_CHAN_A</flags> +</freqband> +<freqband id="AC1_5180_5240_80"> + <freqstart>5180</freqstart> <freqend>5240</freqend> + <chanwidth>80</chanwidth> <chansep>20</chansep> + <flags>IEEE80211_CHAN_A</flags> +</freqband> <freqband id="H4_5180_5240"> <freqstart>5180</freqstart> <freqend>5240</freqend> <chanwidth>40</chanwidth> <chansep>20</chansep> @@ -1825,6 +1878,21 @@ <chanwidth>20</chanwidth> <chansep>20</chansep> <flags>IEEE80211_CHAN_A</flags> </freqband> +<freqband id="AC1_5745_5805_20"> + <freqstart>5745</freqstart> <freqend>5805</freqend> + <chanwidth>20</chanwidth> <chansep>20</chansep> + <flags>IEEE80211_CHAN_A</flags> +</freqband> +<freqband id="AC1_5745_5805_40"> + <freqstart>5745</freqstart> <freqend>5805</freqend> + <chanwidth>40</chanwidth> <chansep>20</chansep> + <flags>IEEE80211_CHAN_A</flags> +</freqband> +<freqband id="AC1_5745_5805_80"> + <freqstart>5745</freqstart> <freqend>5805</freqend> + <chanwidth>80</chanwidth> <chansep>20</chansep> + <flags>IEEE80211_CHAN_A</flags> +</freqband> <freqband id="H4_5745_5805"> <freqstart>5745</freqstart> <freqend>5805</freqend> <chanwidth>40</chanwidth> <chansep>20</chansep> diff --git a/sbin/ifconfig/ifieee80211.c b/sbin/ifconfig/ifieee80211.c index dcb91e0441da..d7794be320e5 100644 --- a/sbin/ifconfig/ifieee80211.c +++ b/sbin/ifconfig/ifieee80211.c @@ -125,6 +125,17 @@ #define IEEE80211_NODE_AMSDU_RX 0x040000 /* AMSDU rx enabled */ #define IEEE80211_NODE_AMSDU_TX 0x080000 /* AMSDU tx enabled */ #define IEEE80211_NODE_VHT 0x100000 /* VHT enabled */ +#define IEEE80211_NODE_LDPC 0x200000 /* LDPC enabled */ +#define IEEE80211_NODE_UAPSD 0x400000 /* UAPSD enabled */ +#endif + +/* XXX should also figure out where to put these for k/u-space sharing. */ +#ifndef IEEE80211_FVHT_VHT +#define IEEE80211_FVHT_VHT 0x000000001 /* CONF: VHT supported */ +#define IEEE80211_FVHT_USEVHT40 0x000000002 /* CONF: Use VHT40 */ +#define IEEE80211_FVHT_USEVHT80 0x000000004 /* CONF: Use VHT80 */ +#define IEEE80211_FVHT_USEVHT160 0x000000008 /* CONF: Use VHT160 */ +#define IEEE80211_FVHT_USEVHT80P80 0x000000010 /* CONF: Use VHT 80+80 */ #endif #define MAXCHAN 1536 /* max 1.5K channels */ @@ -1804,6 +1815,12 @@ set80211ldpc(const char *val, int d, int s, const struct afswtch *rafp) set80211(s, IEEE80211_IOC_LDPC, ldpc, 0, NULL); } +static void +set80211uapsd(const char *val, int d, int s, const struct afswtch *rafp) +{ + set80211(s, IEEE80211_IOC_UAPSD, d, 0, NULL); +} + static DECL_CMD_FUNC(set80211ampdulimit, val, d) { @@ -2159,8 +2176,6 @@ regdomain_addchans(struct ieee80211req_chaninfo *ci, /* * VHT first - HT is a subset. - * - * XXX TODO: VHT80p80, VHT160 is not yet done. */ if (flags & IEEE80211_CHAN_VHT) { if ((chanFlags & IEEE80211_CHAN_VHT20) && @@ -2184,7 +2199,20 @@ regdomain_addchans(struct ieee80211req_chaninfo *ci, "VHT80 channel\n", freq); continue; } - + if ((chanFlags & IEEE80211_CHAN_VHT160) && + (flags & IEEE80211_CHAN_VHT160) == 0) { + if (verbose) + printf("%u: skip, not a " + "VHT160 channel\n", freq); + continue; + } + if ((chanFlags & IEEE80211_CHAN_VHT80P80) && + (flags & IEEE80211_CHAN_VHT80P80) == 0) { + if (verbose) + printf("%u: skip, not a " + "VHT80+80 channel\n", freq); + continue; + } flags &= ~IEEE80211_CHAN_VHT; flags |= chanFlags & IEEE80211_CHAN_VHT; } @@ -2370,7 +2398,7 @@ regdomain_makechannels( &dc->dc_chaninfo); } - /* XXX TODO: VHT80_80, VHT160 */ + /* XXX TODO: VHT80P80, VHT160 */ } if (!LIST_EMPTY(&rd->bands_11ng) && dc->dc_htcaps != 0) { @@ -2631,6 +2659,10 @@ getflags(int flags) *cp++ = 't'; if (flags & IEEE80211_NODE_AMSDU_RX) *cp++ = 'r'; + if (flags & IEEE80211_NODE_UAPSD) + *cp++ = 'U'; + if (flags & IEEE80211_NODE_LDPC) + *cp++ = 'L'; *cp = '\0'; return flagstring; } @@ -3840,8 +3872,8 @@ list_stations(int s) , "TXSEQ" , "RXSEQ" ); - else - printf("%-17.17s %4s %4s %4s %4s %4s %6s %6s %4s %-7s\n" + else + printf("%-17.17s %4s %4s %4s %4s %4s %6s %6s %4s %-12s\n" , "ADDR" , "AID" , "CHAN" @@ -3875,8 +3907,8 @@ list_stations(int s) , gettxseq(si) , getrxseq(si) ); - else - printf("%s %4u %4d %3dM %4.1f %4d %6d %6d %-4.4s %-7.7s" + else + printf("%s %4u %4d %3dM %4.1f %4d %6d %6d %-4.4s %-12.12s" , ether_ntoa((const struct ether_addr*) si->isi_macaddr) , IEEE80211_AID(si->isi_associd) @@ -3937,8 +3969,11 @@ get_chaninfo(const struct ieee80211_channel *c, int precise, if (IEEE80211_IS_CHAN_TURBO(c)) strlcat(buf, " Turbo", bsize); if (precise) { - /* XXX should make VHT80U, VHT80D */ - if (IEEE80211_IS_CHAN_VHT80(c) && + if (IEEE80211_IS_CHAN_VHT80P80(c)) + strlcat(buf, " vht/80p80", bsize); + else if (IEEE80211_IS_CHAN_VHT160(c)) + strlcat(buf, " vht/160", bsize); + else if (IEEE80211_IS_CHAN_VHT80(c) && IEEE80211_IS_CHAN_HT40D(c)) strlcat(buf, " vht/80-", bsize); else if (IEEE80211_IS_CHAN_VHT80(c) && @@ -3992,10 +4027,11 @@ print_chaninfo(const struct ieee80211_channel *c, int verb) static int chanpref(const struct ieee80211_channel *c) { + + if (IEEE80211_IS_CHAN_VHT80P80(c)) + return 90; if (IEEE80211_IS_CHAN_VHT160(c)) return 80; - if (IEEE80211_IS_CHAN_VHT80_80(c)) - return 75; if (IEEE80211_IS_CHAN_VHT80(c)) return 70; if (IEEE80211_IS_CHAN_VHT40(c)) @@ -4767,6 +4803,23 @@ getid(int s, int ix, void *data, size_t len, int *plen, int mesh) return 0; } +static int +getdevicename(int s, void *data, size_t len, int *plen) +{ + struct ieee80211req ireq; + + (void) memset(&ireq, 0, sizeof(ireq)); + (void) strlcpy(ireq.i_name, name, sizeof(ireq.i_name)); + ireq.i_type = IEEE80211_IOC_IC_NAME; + ireq.i_val = -1; + ireq.i_data = data; + ireq.i_len = len; + if (ioctl(s, SIOCG80211, &ireq) < 0) + return (-1); + *plen = ireq.i_len; + return (0); +} + static void ieee80211_status(int s) { @@ -5288,30 +5341,40 @@ end: break; } } + if (get80211val(s, IEEE80211_IOC_UAPSD, &val) != -1) { + switch (val) { + case 0: + LINE_CHECK("-uapsd"); + break; + case 1: + LINE_CHECK("uapsd"); + break; + } + } } if (IEEE80211_IS_CHAN_VHT(c) || verbose) { getvhtconf(s); - if (vhtconf & 0x1) + if (vhtconf & IEEE80211_FVHT_VHT) LINE_CHECK("vht"); else LINE_CHECK("-vht"); - if (vhtconf & 0x2) + if (vhtconf & IEEE80211_FVHT_USEVHT40) LINE_CHECK("vht40"); else LINE_CHECK("-vht40"); - if (vhtconf & 0x4) + if (vhtconf & IEEE80211_FVHT_USEVHT80) LINE_CHECK("vht80"); else LINE_CHECK("-vht80"); - if (vhtconf & 0x8) - LINE_CHECK("vht80p80"); - else - LINE_CHECK("-vht80p80"); - if (vhtconf & 0x10) + if (vhtconf & IEEE80211_FVHT_USEVHT160) LINE_CHECK("vht160"); else LINE_CHECK("-vht160"); + if (vhtconf & IEEE80211_FVHT_USEVHT80P80) + LINE_CHECK("vht80p80"); + else + LINE_CHECK("-vht80p80"); } if (get80211val(s, IEEE80211_IOC_WME, &wme) != -1) { @@ -5481,6 +5544,12 @@ end: } LINE_BREAK(); + + if (getdevicename(s, data, sizeof(data), &len) < 0) + return; + LINE_CHECK("parent interface: %s", data); + + LINE_BREAK(); } static int @@ -5872,6 +5941,8 @@ static struct cmd ieee80211_cmds[] = { DEF_CMD("-ldpctx", -1, set80211ldpc), DEF_CMD("ldpc", 3, set80211ldpc), /* NB: tx+rx */ DEF_CMD("-ldpc", -3, set80211ldpc), + DEF_CMD("uapsd", 1, set80211uapsd), + DEF_CMD("-uapsd", 0, set80211uapsd), DEF_CMD("puren", 1, set80211puren), DEF_CMD("-puren", 0, set80211puren), DEF_CMD("doth", 1, set80211doth), @@ -5904,16 +5975,16 @@ static struct cmd ieee80211_cmds[] = { DEF_CMD("-ht40", 0, set80211htconf), DEF_CMD("ht", 3, set80211htconf), /* NB: 20+40 */ DEF_CMD("-ht", 0, set80211htconf), - DEF_CMD("vht", 1, set80211vhtconf), - DEF_CMD("-vht", 0, set80211vhtconf), - DEF_CMD("vht40", 2, set80211vhtconf), - DEF_CMD("-vht40", -2, set80211vhtconf), - DEF_CMD("vht80", 4, set80211vhtconf), - DEF_CMD("-vht80", -4, set80211vhtconf), - DEF_CMD("vht80p80", 8, set80211vhtconf), - DEF_CMD("-vht80p80", -8, set80211vhtconf), - DEF_CMD("vht160", 16, set80211vhtconf), - DEF_CMD("-vht160", -16, set80211vhtconf), + DEF_CMD("vht", IEEE80211_FVHT_VHT, set80211vhtconf), + DEF_CMD("-vht", 0, set80211vhtconf), + DEF_CMD("vht40", IEEE80211_FVHT_USEVHT40, set80211vhtconf), + DEF_CMD("-vht40", -IEEE80211_FVHT_USEVHT40, set80211vhtconf), + DEF_CMD("vht80", IEEE80211_FVHT_USEVHT80, set80211vhtconf), + DEF_CMD("-vht80", -IEEE80211_FVHT_USEVHT80, set80211vhtconf), + DEF_CMD("vht160", IEEE80211_FVHT_USEVHT160, set80211vhtconf), + DEF_CMD("-vht160", -IEEE80211_FVHT_USEVHT160, set80211vhtconf), + DEF_CMD("vht80p80", IEEE80211_FVHT_USEVHT80P80, set80211vhtconf), + DEF_CMD("-vht80p80", -IEEE80211_FVHT_USEVHT80P80, set80211vhtconf), DEF_CMD("rifs", 1, set80211rifs), DEF_CMD("-rifs", 0, set80211rifs), DEF_CMD("smps", IEEE80211_HTCAP_SMPS_ENA, set80211smps), diff --git a/share/man/man4/ath.4 b/share/man/man4/ath.4 index acd83a86d3ff..fb88c31569a2 100644 --- a/share/man/man4/ath.4 +++ b/share/man/man4/ath.4 @@ -28,7 +28,7 @@ .\" .\" $FreeBSD$ .\"/ -.Dd April 14, 2014 +.Dd June 16, 2020 .Dt ATH 4 .Os .Sh NAME @@ -60,10 +60,10 @@ The driver provides support for wireless network adapters based on the Atheros AR5210, AR5211, AR5212, AR5416 and AR9300 programming APIs. These APIs are used by a wide variety of chips; most all chips with -a PCI and/or CardBus interface are supported. +a PCI, PCIe and/or CardBus interface are supported. .Pp Supported features include 802.11 and 802.3 frames, power management, BSS, -IBSS, MBSS, TDMA, and host-based access point operation modes. +IBSS, MBSS, WDS/DWDS TDMA, and host-based access point operation modes. All host/device interaction is via DMA. .Pp Please note that from FreeBSD-9.0, the @@ -148,12 +148,13 @@ For more information on configuring this device, see .Pp Devices supported by the .Nm -driver come in either Cardbus or mini-PCI packages. -Wireless cards in Cardbus slots may be inserted and ejected on the fly. +driver come in Cardbus, ExpressCard, Mini-PCI and Mini-PCIe packages. +Wireless cards in Cardbus and ExpressCard slots may be inserted and +ejected on the fly. .Sh HARDWARE The .Nm -driver supports all Atheros Cardbus and PCI cards, +driver supports all Atheros Cardbus, ExpressCard, PCI and PCIe cards, except those that are based on the AR5005VL chipset. .Sh EXAMPLES Join a specific BSS network with WEP encryption: @@ -293,8 +294,7 @@ device driver first appeared in Revision A1 of the D-LINK DWL-G520 and DWL-G650 are based on an Intersil PrismGT chip and are not supported by this driver. .Sh BUGS -The driver does not fully enable power-save operation of the chip -in station mode; consequently power use is suboptimal (e.g. on a laptop). +The driver does supports optional station mode power-save operation. .Pp The AR5210 can only do WEP in hardware; consequently hardware assisted WEP is disabled in order to allow software implementations of TKIP and CCMP to diff --git a/share/man/man4/net80211.4 b/share/man/man4/net80211.4 index 650bbf48272a..629e84c35566 100644 --- a/share/man/man4/net80211.4 +++ b/share/man/man4/net80211.4 @@ -28,7 +28,7 @@ .\" .\" $FreeBSD$ .\" -.Dd July 10, 2009 +.Dd August 7, 2020 .Dt NET80211 4 .Os .Sh NAME @@ -393,6 +393,16 @@ Valid values are: and .Dv IEEE80211_HWMP_ROOTMODE_RANN (send broadcast Root Announcement (RANN) frames). +.It Dv IEEE80211_IOC_IC_NAME +Return the underlying hardware +.Xr device 9 +name in the buffer pointed to by +.Va i_data +and the name length including terminating NUL character in +.Va i_len . +If the buffer length is too small to hold the full name +.Er EINVAL +will be returned. .It Dv IEEE80211_IOC_INACTIVITY Return whether or not the system handles inactivity processing in .Va i_val . diff --git a/share/man/man4/run.4 b/share/man/man4/run.4 index 8e44dcfa4afd..b95a346f9697 100644 --- a/share/man/man4/run.4 +++ b/share/man/man4/run.4 @@ -16,7 +16,7 @@ .\" .\" $FreeBSD$ .\" -.Dd November 8, 2018 +.Dd June 16, 2020 .Dt RUN 4 .Os .Sh NAME @@ -251,5 +251,5 @@ driver was written by .Sh CAVEATS The .Nm -driver does not support any of the 802.11n capabilities offered by the +driver supports some of the 11n capabilities found in the RT2800, RT3000 and RT3900 chipsets. diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300.h b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300.h index 00807ac430ee..49e887353e52 100644 --- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300.h +++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300.h @@ -19,18 +19,14 @@ #include "ar9300_freebsd_inc.h" -#define AH_BIG_ENDIAN 4321 -#define AH_LITTLE_ENDIAN 1234 - -#if _BYTE_ORDER == _BIG_ENDIAN -#define AH_BYTE_ORDER AH_BIG_ENDIAN -#else -#define AH_BYTE_ORDER AH_LITTLE_ENDIAN -#endif - /* XXX doesn't belong here */ #define AR_EEPROM_MODAL_SPURS 5 +/* Ensure that AH_BYTE_ORDER is defined */ +#ifndef AH_BYTE_ORDER +#error AH_BYTE_ORDER needs to be defined! +#endif + /* * (a) this should be N(a), * (b) FreeBSD does define nitems, @@ -43,10 +39,8 @@ #include "ah_devid.h" #include "ar9300eep.h" /* For Eeprom definitions */ - #define AR9300_MAGIC 0x19741014 - /* MAC register values */ #define INIT_CONFIG_STATUS 0x00000000 @@ -1396,7 +1390,7 @@ extern void ar9300_wowoffload_download_ns_info(struct ath_hal *ah, u_int32_t id extern HAL_BOOL ar9300_reset(struct ath_hal *ah, HAL_OPMODE opmode, struct ieee80211_channel *chan, HAL_HT_MACMODE macmode, u_int8_t txchainmask, u_int8_t rxchainmask, HAL_HT_EXTPROTSPACING extprotspacing, - HAL_BOOL b_channel_change, HAL_STATUS *status, int is_scan); + HAL_BOOL b_channel_change, HAL_STATUS *status, HAL_RESET_TYPE reset_type, int is_scan); extern HAL_BOOL ar9300_lean_channel_change(struct ath_hal *ah, HAL_OPMODE opmode, struct ieee80211_channel *chan, HAL_HT_MACMODE macmode, u_int8_t txchainmask, u_int8_t rxchainmask); extern HAL_BOOL ar9300_set_reset_reg(struct ath_hal *ah, u_int32_t type); @@ -1406,7 +1400,7 @@ extern u_int16_t ar9300_is_single_ant_power_save_possible(struct ath_hal *ah); extern void ar9300_set_operating_mode(struct ath_hal *ah, int opmode); extern HAL_BOOL ar9300_phy_disable(struct ath_hal *ah); extern HAL_BOOL ar9300_disable(struct ath_hal *ah); -extern HAL_BOOL ar9300_chip_reset(struct ath_hal *ah, struct ieee80211_channel *); +extern HAL_BOOL ar9300_chip_reset(struct ath_hal *ah, struct ieee80211_channel *, HAL_RESET_TYPE type); extern HAL_BOOL ar9300_calibration(struct ath_hal *ah, struct ieee80211_channel *chan, u_int8_t rxchainmask, HAL_BOOL longcal, HAL_BOOL *isIQdone, int is_scan, u_int32_t *sched_cals); extern void ar9300_reset_cal_valid(struct ath_hal *ah, diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_ani.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_ani.c index ff22fb800064..dfa0cf619f8a 100644 --- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_ani.c +++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_ani.c @@ -462,13 +462,55 @@ ar9300_ani_control(struct ath_hal *ah, HAL_ANI_CMD cmd, int param) u_int level = param; u_int is_on; + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: cmd=%d, param=%d, chan=%p, funcmask=0x%08x\n", + __func__, + cmd, + param, + chan, + ahp->ah_ani_function); + + if (chan == NULL && cmd != HAL_ANI_MODE) { HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "%s: ignoring cmd 0x%02x - no channel\n", __func__, cmd); return AH_FALSE; } - switch (cmd & ahp->ah_ani_function) { + /* + * These two control the top-level cck/ofdm immunity levels and will + * program the rest of the values. + */ + if (cmd == HAL_ANI_NOISE_IMMUNITY_LEVEL) { + if (param > HAL_ANI_OFDM_NUM_LEVEL) + return AH_FALSE; + ar9300_ani_set_odfm_noise_immunity_level(ah, param); + return AH_TRUE; + } + + if (cmd == HAL_ANI_CCK_NOISE_IMMUNITY_LEVEL) { + if (param > HAL_ANI_CCK_NUM_LEVEL) + return AH_FALSE; + ar9300_ani_set_cck_noise_immunity_level(ah, param); + return AH_TRUE; + } + + /* + * Check to see if this command is available in the + * current operating mode. + */ + if (((1 << cmd) & ahp->ah_ani_function) == 0) { + HALDEBUG(ah, HAL_DEBUG_ANI, + "%s: early check: invalid cmd 0x%02x (allowed=0x%02x)\n", + __func__, cmd, ahp->ah_ani_function); + return AH_FALSE; + } + + /* + * The rest of these program in the requested parameter values + * into the PHY. + */ + switch (cmd) { + case HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION: { int m1_thresh_low, m2_thresh_low; @@ -887,13 +929,16 @@ ar9300_ani_reset(struct ath_hal *ah, HAL_BOOL is_scanning) /* only allow a subset of functions in AP mode */ if (AH_PRIVATE(ah)->ah_opmode == HAL_M_HOSTAP) { if (IS_CHAN_2GHZ(ichan)) { - ahp->ah_ani_function = (HAL_ANI_SPUR_IMMUNITY_LEVEL | - HAL_ANI_FIRSTEP_LEVEL | - HAL_ANI_MRC_CCK); + ahp->ah_ani_function = (1 << HAL_ANI_SPUR_IMMUNITY_LEVEL) | + (1 << HAL_ANI_FIRSTEP_LEVEL) | + (1 << HAL_ANI_MRC_CCK); } else { ahp->ah_ani_function = 0; } + } else { + ahp->ah_ani_function = HAL_ANI_ALL; } + /* always allow mode (on/off) to be controlled */ ahp->ah_ani_function |= HAL_ANI_MODE; @@ -1172,6 +1217,7 @@ ar9300_ani_ar_poll(struct ath_hal *ah, const HAL_NODE_STATS *stats, cck_phy_err_cnt = OS_REG_READ(ah, AR_PHY_ERR_2); /* Populate HAL_ANISTATS */ + /* XXX TODO: are these correct? */ if (ani_stats) { ani_stats->cckphyerr_cnt = cck_phy_err_cnt - ani_state->cck_phy_err_count; @@ -1212,18 +1258,32 @@ ar9300_ani_ar_poll(struct ath_hal *ah, const HAL_NODE_STATS *stats, return; } + /* + * Calculate the OFDM/CCK phy error rate over the listen time interval. + * This is used in subsequent math to see if the OFDM/CCK phy error rate + * is above or below the threshold checks. + */ + ofdm_phy_err_rate = ani_state->ofdm_phy_err_count * 1000 / ani_state->listen_time; cck_phy_err_rate = ani_state->cck_phy_err_count * 1000 / ani_state->listen_time; HALDEBUG(ah, HAL_DEBUG_ANI, - "%s: listen_time=%d OFDM:%d errs=%d/s CCK:%d errs=%d/s ofdm_turn=%d\n", + "%s: listen_time=%d (total: %d) OFDM:%d errs=%d/s CCK:%d errs=%d/s ofdm_turn=%d\n", __func__, listen_time, + ani_state->listen_time, ani_state->ofdm_noise_immunity_level, ofdm_phy_err_rate, ani_state->cck_noise_immunity_level, cck_phy_err_rate, ani_state->ofdms_turn); + /* + * Check for temporary noise spurs. This is intended to be used by + * rate control to check if we should try higher packet rates or not. + * If the noise period is short enough then we shouldn't avoid trying + * higher rates but if the noise is high/sustained then it's likely + * not a great idea to try the higher MCS rates. + */ if (ani_state->listen_time >= HAL_NOISE_DETECT_PERIOD) { old_phy_noise_spur = ani_state->phy_noise_spur; if (ofdm_phy_err_rate <= ani_state->ofdm_trig_low && @@ -1236,7 +1296,7 @@ ar9300_ani_ar_poll(struct ath_hal *ah, const HAL_NODE_STATS *stats, } if (old_phy_noise_spur != ani_state->phy_noise_spur) { HALDEBUG(ah, HAL_DEBUG_ANI, - "%s: enviroment change from %d to %d\n", + "%s: environment change from %d to %d\n", __func__, old_phy_noise_spur, ani_state->phy_noise_spur); } } @@ -1259,6 +1319,10 @@ ar9300_ani_ar_poll(struct ath_hal *ah, const HAL_NODE_STATS *stats, ar9300_ani_lower_immunity(ah); ani_state->ofdms_turn = !ani_state->ofdms_turn; } + /* + * Force an ANI restart regardless of whether the lower immunity + * level was met. + */ HALDEBUG(ah, HAL_DEBUG_ANI, "%s: 1 listen_time=%d ofdm=%d/s cck=%d/s - " "calling ar9300_ani_restart\n", @@ -1292,6 +1356,13 @@ ar9300_ani_ar_poll(struct ath_hal *ah, const HAL_NODE_STATS *stats, ani_state->ofdms_turn = AH_TRUE; } } + + /* + * Note that currently this poll function doesn't reset the listen + * time after it accumulates a second worth of error samples. + * It will continue to accumulate samples until a counter overflows, + * or a raise threshold is met, or 5 seconds passes. + */ } /* diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c index 063075e397d0..0251222c50b4 100644 --- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c +++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c @@ -3040,6 +3040,33 @@ ar9300_eeprom_set_transmit_power(struct ath_hal *ah, ahp->reg_dmn = ath_hal_getctl(ah, chan); /* + * After reading FCC/OET 13TR1003 (Directional Gain of IEEE 802.11 + * MIMO devices employing cyclic delay diversity) and looking at what + * ath9k does, let's disable the CDD check until it's clearer exactly + * how the maximum cap should be applied here. + * + * Right now the CDD check is simply unconditionally reducing the + * gain of legacy and 1/2 stream rates depending upon the chainmask. + * (CDD is used when transmitting rates that don't already use up the + * full set of streams - eg OFDM or MCS0-7 on a 2 or 3 chain TX path.) + * + * It's dropping the 2-chain TX by 3dB and 3-chain by 5dB to "meet" + * power spectral density requirements but it's not currently taking + * into account how close to the regulatory limit the hardware/antenna + * system is already at. It doesn't help that the conductive testing + * limits have the array gain at 0dB for all AR9300/derivative + * configurations. + * + * It also doesn't let us do single chain transmit at the full allowed + * power for the regulatory/CTL limits as it subtracts it from what's + * programmed into the hardware. + * + * ath9k doesn't factor any of the CDD stuff into account, so I'm going + * to disable it here and in the TPC path until I get a better idea + * of what to really do here. + */ +#if 0 + /* * Always use CDD/direct per rate power table for register based approach. * For FCC, CDD calculations should factor in the array gain, hence * this adjust call. ETSI and MKK does not have this requirement. @@ -3050,6 +3077,7 @@ ar9300_eeprom_set_transmit_power(struct ath_hal *ah, __func__); ar9300_adjust_reg_txpower_cdd(ah, target_power_val_t2); } +#endif if (ar9300_eeprom_get(ahp, EEP_PAPRD_ENABLED)) { for (i = 0; i < ar9300_rate_size; i++) { diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c index e066ff280231..37e64bc86cdd 100644 --- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c +++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c @@ -355,7 +355,7 @@ ar9300_attach_freebsd_ops(struct ath_hal *ah) ah->ah_setRxDP = ar9300_set_rx_dp; ah->ah_enableReceive = ar9300_enable_receive; ah->ah_stopDmaReceive = ar9300_stop_dma_receive_freebsd; - ah->ah_startPcuReceive = ar9300_start_pcu_receive_freebsd; + ah->ah_startPcuReceive = ar9300_start_pcu_receive; ah->ah_stopPcuReceive = ar9300_stop_pcu_receive; ah->ah_setMulticastFilter = ar9300_set_multicast_filter; ah->ah_setMulticastFilterIndex = ar9300SetMulticastFilterIndex; @@ -543,6 +543,7 @@ ar9300_reset_freebsd(struct ath_hal *ah, HAL_OPMODE opmode, HAL_HT_EXTPROTSPACING_20, /* always 20Mhz channel spacing */ bChannelChange, status, + resetType, AH_FALSE); /* XXX should really extend ath_hal_reset() */ return (r); @@ -679,14 +680,6 @@ ar9300_reset_cal_valid_freebsd(struct ath_hal *ah, } -void -ar9300_start_pcu_receive_freebsd(struct ath_hal *ah) -{ - - /* is_scanning flag == NULL */ - ar9300_start_pcu_receive(ah, AH_FALSE); -} - /* * FreeBSD will just pass in the descriptor value as 'pa'. * The Atheros HAL treats 'pa' as the physical address of the RX diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_misc.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_misc.c index 6e49325cdac3..1793cf06378b 100644 --- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_misc.c +++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_misc.c @@ -1263,15 +1263,13 @@ ar9300_get_diag_state(struct ath_hal *ah, int request, if (ani == AH_NULL) return AH_FALSE; /* Convert ar9300 HAL to FreeBSD HAL ANI state */ - /* XXX TODO: add all of these to the HAL ANI state structure */ bzero(&ahp->ext_ani_state, sizeof(ahp->ext_ani_state)); - /* XXX should this be OFDM or CCK noise immunity level? */ ahp->ext_ani_state.noiseImmunityLevel = ani->ofdm_noise_immunity_level; ahp->ext_ani_state.spurImmunityLevel = ani->spur_immunity_level; ahp->ext_ani_state.firstepLevel = ani->firstep_level; ahp->ext_ani_state.ofdmWeakSigDetectOff = ani->ofdm_weak_sig_detect_off; - /* mrc_cck_off */ - /* cck_noise_immunity_level */ + ahp->ext_ani_state.mrcCck = !! ani->mrc_cck_off; + ahp->ext_ani_state.cckNoiseImmunityLevel = ani->cck_noise_immunity_level; ahp->ext_ani_state.listenTime = ani->listen_time; @@ -1289,12 +1287,18 @@ ar9300_get_diag_state(struct ath_hal *ah, int request, 0 : sizeof(HAL_ANI_STATS); return AH_TRUE; case HAL_DIAG_ANI_CMD: + { + HAL_ANI_CMD savefunc = ahp->ah_ani_function; if (argsize != 2*sizeof(u_int32_t)) { return AH_FALSE; } + /* temporarly allow all functions so we can override */ + ahp->ah_ani_function = HAL_ANI_ALL; ar9300_ani_control( ah, ((const u_int32_t *)args)[0], ((const u_int32_t *)args)[1]); + ahp->ah_ani_function = savefunc; return AH_TRUE; + } #if 0 case HAL_DIAG_TXCONT: /*AR9300_CONTTXMODE(ah, (struct ath_desc *)args, argsize );*/ diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_phy.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_phy.c index 24622e732cbd..5bf342e43624 100644 --- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_phy.c +++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_phy.c @@ -55,10 +55,12 @@ static inline void ar9300_init_rate_txpower_stbc(struct ath_hal *ah, const HAL_RATE_TABLE *rt, HAL_BOOL is40, int rt_ss_offset, int rt_ds_offset, int rt_ts_offset, u_int8_t chainmask); +#if 0 static inline void ar9300_adjust_rate_txpower_cdd(struct ath_hal *ah, const HAL_RATE_TABLE *rt, HAL_BOOL is40, int rt_ss_offset, int rt_ds_offset, int rt_ts_offset, u_int8_t chainmask); +#endif #define AR9300_11A_RT_OFDM_OFFSET 0 HAL_RATE_TABLE ar9300_11a_table = { @@ -442,6 +444,8 @@ ar9300_adjust_reg_txpower_cdd(struct ath_hal *ah, ((int16_t)AH_MIN((ahp->twice_antenna_reduction - (ahp->twice_antenna_gain + AR9300_TXBF_2TX_ARRAY_GAIN)), 0)); cdd_power = ahp->upper_limit[1] + twice_array_gain; + + HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: 2 chain; cdd_power=%d", __func__, cdd_power); /* Adjust OFDM legacy rates as well */ for (i = ALL_TARGET_LEGACY_6_24; i <= ALL_TARGET_LEGACY_54; i++) { if (power_per_rate[i] > cdd_power) { @@ -471,6 +475,7 @@ ar9300_adjust_reg_txpower_cdd(struct ath_hal *ah, ((int16_t)AH_MIN((ahp->twice_antenna_reduction - (ahp->twice_antenna_gain + AR9300_TXBF_3TX_ARRAY_GAIN)), 0)); cdd_power = ahp->upper_limit[2] + twice_array_gain; + HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: 3 chain; cdd_power=%d", __func__, cdd_power); /* Adjust OFDM legacy rates as well */ for (i = ALL_TARGET_LEGACY_6_24; i <= ALL_TARGET_LEGACY_54; i++) { if (power_per_rate[i] > cdd_power) { @@ -531,6 +536,7 @@ ar9300_init_rate_txpower(struct ath_hal *ah, u_int mode, AR9300_11NA_RT_HT_SS_OFFSET, AR9300_11NA_RT_HT_DS_OFFSET, AR9300_11NA_RT_HT_TS_OFFSET, chainmask); +#if 0 /* For FCC the array gain has to be factored for CDD mode */ if (is_reg_dmn_fcc(ath_hal_getctl(ah, chan))) { ar9300_adjust_rate_txpower_cdd(ah, rt, is40, @@ -538,6 +544,7 @@ ar9300_init_rate_txpower(struct ath_hal *ah, u_int mode, AR9300_11NA_RT_HT_DS_OFFSET, AR9300_11NA_RT_HT_TS_OFFSET, chainmask); } +#endif break; case HAL_MODE_11G: ar9300_init_rate_txpower_cck(ah, rt, power_per_rate, chainmask); @@ -561,6 +568,7 @@ ar9300_init_rate_txpower(struct ath_hal *ah, u_int mode, AR9300_11NG_RT_HT_SS_OFFSET, AR9300_11NG_RT_HT_DS_OFFSET, AR9300_11NG_RT_HT_TS_OFFSET, chainmask); +#if 0 /* For FCC the array gain needs to be factored for CDD mode */ if (is_reg_dmn_fcc(ath_hal_getctl(ah, chan))) { ar9300_adjust_rate_txpower_cdd(ah, rt, is40, @@ -568,6 +576,7 @@ ar9300_init_rate_txpower(struct ath_hal *ah, u_int mode, AR9300_11NG_RT_HT_DS_OFFSET, AR9300_11NG_RT_HT_TS_OFFSET, chainmask); } +#endif break; default: HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid mode 0x%x\n", @@ -941,6 +950,10 @@ ar9300_init_rate_txpower_stbc(struct ath_hal *ah, const HAL_RATE_TABLE *rt, return; } +/* + * To see why this is disabled, look at ar9300_eeprom.c for FCC/OET 13TR1003. + */ +#if 0 static inline void ar9300_adjust_rate_txpower_cdd(struct ath_hal *ah, const HAL_RATE_TABLE *rt, HAL_BOOL is40, @@ -1037,6 +1050,7 @@ ar9300_adjust_rate_txpower_cdd(struct ath_hal *ah, const HAL_RATE_TABLE *rt, return; } +#endif void ar9300_disp_tpc_tables(struct ath_hal *ah) { diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_reset.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_reset.c index 40cdbdd173f2..2b4374d237bd 100644 --- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_reset.c +++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_reset.c @@ -2064,7 +2064,7 @@ ar9300_set_rf_mode(struct ath_hal *ah, struct ieee80211_channel *chan) * Places the hardware into reset and then pulls it out of reset */ HAL_BOOL -ar9300_chip_reset(struct ath_hal *ah, struct ieee80211_channel *chan) +ar9300_chip_reset(struct ath_hal *ah, struct ieee80211_channel *chan, HAL_RESET_TYPE reset_type) { struct ath_hal_9300 *ahp = AH9300(ah); int type = HAL_RESET_WARM; @@ -2080,8 +2080,13 @@ ar9300_chip_reset(struct ath_hal *ah, struct ieee80211_channel *chan) */ if (ahp->ah_chip_full_sleep || (ah->ah_config.ah_force_full_reset == 1) || + (reset_type == HAL_RESET_FORCE_COLD) || + (reset_type == HAL_RESET_BBPANIC) || OS_REG_READ(ah, AR_Q_TXE) || (OS_REG_READ(ah, AR_CR) & AR_CR_RXE)) { + HALDEBUG(ah, HAL_DEBUG_RESET, + "%s: full reset; reset_type=%d, full_sleep=%d\n", + __func__, reset_type, ahp->ah_chip_full_sleep); type = HAL_RESET_COLD; } @@ -4510,7 +4515,7 @@ HAL_BOOL ar9300_reset(struct ath_hal *ah, HAL_OPMODE opmode, struct ieee80211_channel *chan, HAL_HT_MACMODE macmode, u_int8_t txchainmask, u_int8_t rxchainmask, HAL_HT_EXTPROTSPACING extprotspacing, HAL_BOOL b_channel_change, - HAL_STATUS *status, int is_scan) + HAL_STATUS *status, HAL_RESET_TYPE reset_type, int is_scan) { #define FAIL(_code) do { ecode = _code; goto bad; } while (0) u_int32_t save_led_state; @@ -4864,7 +4869,7 @@ ar9300_reset(struct ath_hal *ah, HAL_OPMODE opmode, struct ieee80211_channel *ch /* Mark PHY inactive prior to reset, to be undone in ar9300_init_bb () */ ar9300_mark_phy_inactive(ah); - if (!ar9300_chip_reset(ah, chan)) { + if (!ar9300_chip_reset(ah, chan, reset_type)) { HALDEBUG(ah, HAL_DEBUG_RESET, "%s: chip reset failed\n", __func__); FAIL(HAL_EIO); } diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_stub_funcs.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_stub_funcs.c index 7fe4374a3456..8b587f941084 100644 --- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_stub_funcs.c +++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_stub_funcs.c @@ -691,7 +691,7 @@ ar9300_Stub_StopDmaReceive(struct ath_hal *ah) } void -ar9300_Stub_StartPcuReceive(struct ath_hal *ah) +ar9300_Stub_StartPcuReceive(struct ath_hal *ah, HAL_BOOL is_scanning) { ath_hal_printf(ah, "%s: called\n", __func__); diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_stub_funcs.h b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_stub_funcs.h index 82397f9fcb1a..f4dab5cbe55c 100644 --- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_stub_funcs.h +++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_stub_funcs.h @@ -112,7 +112,7 @@ extern void ar9300_Stub_SetRxDP(struct ath_hal *ah, uint32_t rxdp, HAL_RX_QUEUE); extern void ar9300_Stub_EnableReceive(struct ath_hal *ah); extern HAL_BOOL ar9300_Stub_StopDmaReceive(struct ath_hal *ah); -extern void ar9300_Stub_StartPcuReceive(struct ath_hal *ah); +extern void ar9300_Stub_StartPcuReceive(struct ath_hal *ah, HAL_BOOL); extern void ar9300_Stub_StopPcuReceive(struct ath_hal *ah); extern void ar9300_Stub_SetMulticastFilter(struct ath_hal *ah, uint32_t filter0, uint32_t filter1); diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300eep.h b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300eep.h index 516303033835..9230fd57e2e4 100644 --- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300eep.h +++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300eep.h @@ -18,13 +18,17 @@ #define _ATH_AR9300_EEP_H_ #include "opt_ah.h" - #include "ah.h" #if defined(WIN32) || defined(WIN64) #pragma pack (push, ar9300, 1) #endif +/* Ensure that AH_BYTE_ORDER is defined */ +#ifndef AH_BYTE_ORDER +#error AH_BYTE_ORDER needs to be defined! +#endif + /* FreeBSD extras - should be in ah_eeprom.h ? */ #define AR_EEPROM_EEPCAP_COMPRESS_DIS 0x0001 #define AR_EEPROM_EEPCAP_AES_DIS 0x0002 @@ -345,11 +349,13 @@ typedef struct CalCtlEdgePwr { u_int8_t flag :2, t_power :6; } __packed CAL_CTL_EDGE_PWR; -#else +#elif AH_BYTE_ORDER == AH_LITTLE_ENDIAN typedef struct CalCtlEdgePwr { u_int8_t t_power :6, flag :2; } __packed CAL_CTL_EDGE_PWR; +#else +#error AH_BYTE_ORDER undefined! #endif typedef struct ospCalCtlData_5G { diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300template_ap121.h b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300template_ap121.h index 6468445b8a82..fabed1cb8fe0 100644 --- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300template_ap121.h +++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300template_ap121.h @@ -25,6 +25,11 @@ #ifndef __ar9300templateAP121_h__ #define __ar9300templateAP121_h__ +/* Ensure that AH_BYTE_ORDER is defined */ +#ifndef AH_BYTE_ORDER +#error AH_BYTE_ORDER needs to be defined! +#endif + static ar9300_eeprom_t ar9300_template_ap121= { diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300template_aphrodite.h b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300template_aphrodite.h index a9e5f3635976..0f756b81cd81 100644 --- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300template_aphrodite.h +++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300template_aphrodite.h @@ -26,6 +26,11 @@ #ifndef __ar9300templateAphrodite_h__ #define __ar9300templateAphrodite_h__ +/* Ensure that AH_BYTE_ORDER is defined */ +#ifndef AH_BYTE_ORDER +#error AH_BYTE_ORDER needs to be defined! +#endif + static ar9300_eeprom_t ar9300_template_aphrodite= { diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300template_cus157.h b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300template_cus157.h index dc37977956ec..fab9558bf588 100644 --- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300template_cus157.h +++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300template_cus157.h @@ -25,6 +25,11 @@ #ifndef __ar9300template_cus157_h__ #define __ar9300template_cus157_h__ +/* Ensure that AH_BYTE_ORDER is defined */ +#ifndef AH_BYTE_ORDER +#error AH_BYTE_ORDER needs to be defined! +#endif + static ar9300_eeprom_t Ar9300Template_cus157= { diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300template_generic.h b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300template_generic.h index 6b7a0d1bb8f4..08b30c215eaf 100644 --- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300template_generic.h +++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300template_generic.h @@ -25,6 +25,11 @@ #ifndef __ar9300templateGeneric_h__ #define __ar9300templateGeneric_h__ +/* Ensure that AH_BYTE_ORDER is defined */ +#ifndef AH_BYTE_ORDER +#error AH_BYTE_ORDER needs to be defined! +#endif + static ar9300_eeprom_t ar9300_template_generic= { diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300template_hb112.h b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300template_hb112.h index c3bbc1d30203..674d8e430e94 100644 --- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300template_hb112.h +++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300template_hb112.h @@ -25,6 +25,11 @@ #ifndef __ar9300templateHB112_h__ #define __ar9300templateHB112_h__ +/* Ensure that AH_BYTE_ORDER is defined */ +#ifndef AH_BYTE_ORDER +#error AH_BYTE_ORDER needs to be defined! +#endif + static ar9300_eeprom_t ar9300_template_hb112= { diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300template_hb116.h b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300template_hb116.h index c1de18ebbe0e..600955181bbc 100644 --- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300template_hb116.h +++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300template_hb116.h @@ -26,6 +26,11 @@ #ifndef __ar9300templateHB116_h__ #define __ar9300templateHB116_h__ +/* Ensure that AH_BYTE_ORDER is defined */ +#ifndef AH_BYTE_ORDER +#error AH_BYTE_ORDER needs to be defined! +#endif + static ar9300_eeprom_t ar9300_template_hb116= { diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300template_osprey_k31.h b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300template_osprey_k31.h index b6b09e80985b..14fdaab18f2f 100644 --- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300template_osprey_k31.h +++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300template_osprey_k31.h @@ -25,6 +25,11 @@ #ifndef __ar9300templateOsprey_k31_h__ #define __ar9300templateOsprey_k31_h__ +/* Ensure that AH_BYTE_ORDER is defined */ +#ifndef AH_BYTE_ORDER +#error AH_BYTE_ORDER needs to be defined! +#endif + static ar9300_eeprom_t ar9300_template_osprey_k31= { diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300template_wasp_2.h b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300template_wasp_2.h index 2eb165f3a72f..0e53dace2b9e 100644 --- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300template_wasp_2.h +++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300template_wasp_2.h @@ -24,6 +24,12 @@ #ifndef __ar9300template_wasp_2_h__ #define __ar9300template_wasp_2_h__ + +/* Ensure that AH_BYTE_ORDER is defined */ +#ifndef AH_BYTE_ORDER +#error AH_BYTE_ORDER needs to be defined! +#endif + static ar9300_eeprom_t ar9300_template_wasp_2= { diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300template_xb112.h b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300template_xb112.h index 864efbab8ce1..645ab78a7157 100644 --- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300template_xb112.h +++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300template_xb112.h @@ -25,6 +25,11 @@ #ifndef __ar9300templateXB112_h__ #define __ar9300templateXB112_h__ +/* Ensure that AH_BYTE_ORDER is defined */ +#ifndef AH_BYTE_ORDER +#error AH_BYTE_ORDER needs to be defined! +#endif + static ar9300_eeprom_t ar9300_template_xb112= { diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300template_xb113.h b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300template_xb113.h index 7b715455a6cb..291b163be823 100644 --- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300template_xb113.h +++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300template_xb113.h @@ -25,6 +25,11 @@ #ifndef __ar9300templateXB113_h__ #define __ar9300templateXB113_h__ +/* Ensure that AH_BYTE_ORDER is defined */ +#ifndef AH_BYTE_ORDER +#error AH_BYTE_ORDER needs to be defined! +#endif + static ar9300_eeprom_t ar9300_template_xb113= { diff --git a/sys/dev/an/if_an.c b/sys/dev/an/if_an.c index 70866f1d002b..bbe248a4457b 100644 --- a/sys/dev/an/if_an.c +++ b/sys/dev/an/if_an.c @@ -2320,7 +2320,7 @@ an_ioctl(struct ifnet *ifp, u_long command, caddr_t data) } break; case SIOCS80211: - if ((error = priv_check(td, PRIV_NET80211_MANAGE))) + if ((error = priv_check(td, PRIV_NET80211_VAP_MANAGE))) goto out; AN_LOCK(sc); sc->areq.an_len = sizeof(sc->areq); diff --git a/sys/dev/ath/ah_osdep.c b/sys/dev/ath/ah_osdep.c index 23d967ec75e3..db9264546d23 100644 --- a/sys/dev/ath/ah_osdep.c +++ b/sys/dev/ath/ah_osdep.c @@ -444,7 +444,6 @@ ath_hal_modevent(module_t mod __unused, int type, void *data __unused) default: error = EOPNOTSUPP; break; - } return (error); } diff --git a/sys/dev/ath/ah_osdep_ar5210.c b/sys/dev/ath/ah_osdep_ar5210.c index 905befe9ca95..e47a2dc11054 100644 --- a/sys/dev/ath/ah_osdep_ar5210.c +++ b/sys/dev/ath/ah_osdep_ar5210.c @@ -64,7 +64,6 @@ ath_hal_ar5210_modevent(module_t mod __unused, int type, void *data __unused) default: error = EOPNOTSUPP; break; - } return (error); } diff --git a/sys/dev/ath/ah_osdep_ar5211.c b/sys/dev/ath/ah_osdep_ar5211.c index 92400965e55b..c87f9ff9b0cb 100644 --- a/sys/dev/ath/ah_osdep_ar5211.c +++ b/sys/dev/ath/ah_osdep_ar5211.c @@ -64,7 +64,6 @@ ath_hal_ar5211_modevent(module_t mod __unused, int type, void *data __unused) default: error = EOPNOTSUPP; break; - } return (error); } diff --git a/sys/dev/ath/ah_osdep_ar5212.c b/sys/dev/ath/ah_osdep_ar5212.c index 3bc21ef803ec..daaa81ff2509 100644 --- a/sys/dev/ath/ah_osdep_ar5212.c +++ b/sys/dev/ath/ah_osdep_ar5212.c @@ -85,7 +85,6 @@ ath_hal_ar5212_modevent(module_t mod __unused, int type, void *data __unused) default: error = EOPNOTSUPP; break; - } return (error); } diff --git a/sys/dev/ath/ah_osdep_ar5416.c b/sys/dev/ath/ah_osdep_ar5416.c index a735838068b6..058027b44c8f 100644 --- a/sys/dev/ath/ah_osdep_ar5416.c +++ b/sys/dev/ath/ah_osdep_ar5416.c @@ -92,7 +92,6 @@ ath_hal_ar5416_modevent(module_t mod __unused, int type, void *data __unused) default: error = EOPNOTSUPP; break; - } return (error); } diff --git a/sys/dev/ath/ah_osdep_ar9300.c b/sys/dev/ath/ah_osdep_ar9300.c index f481d7ea2a2d..70dbfc2c3d39 100644 --- a/sys/dev/ath/ah_osdep_ar9300.c +++ b/sys/dev/ath/ah_osdep_ar9300.c @@ -64,7 +64,6 @@ ath_hal_ar9300_modevent(module_t mod __unused, int type, void *data __unused) default: error = EOPNOTSUPP; break; - } return (error); } diff --git a/sys/dev/ath/ath_dfs/null/dfs_null.c b/sys/dev/ath/ath_dfs/null/dfs_null.c index 1463c8c96648..2c262d1c9ef5 100644 --- a/sys/dev/ath/ath_dfs/null/dfs_null.c +++ b/sys/dev/ath/ath_dfs/null/dfs_null.c @@ -54,7 +54,7 @@ __FBSDID("$FreeBSD$"); #include <sys/bus.h> #include <sys/socket.h> - + #include <net/if.h> #include <net/if_var.h> #include <net/if_media.h> diff --git a/sys/dev/ath/ath_hal/ah.c b/sys/dev/ath/ath_hal/ah.c index 7f5649ed4e8d..e2305d10b452 100644 --- a/sys/dev/ath/ath_hal/ah.c +++ b/sys/dev/ath/ath_hal/ah.c @@ -556,7 +556,6 @@ ath_hal_get_curmode(struct ath_hal *ah, const struct ieee80211_channel *chan) return HAL_MODE_11NG_HT20; } - typedef enum { WIRELESS_MODE_11a = 0, WIRELESS_MODE_TURBO = 1, @@ -971,7 +970,7 @@ ath_hal_getregdump(struct ath_hal *ah, const HAL_REGRANGE *regs, } return (char *) dp - (char *) dstbuf; } - + static void ath_hal_setregs(struct ath_hal *ah, const HAL_REGWRITE *regs, int space) { @@ -1127,7 +1126,6 @@ ath_hal_getTxQProps(struct ath_hal *ah, return AH_FALSE; } - qInfo->tqi_qflags = qi->tqi_qflags; qInfo->tqi_ver = qi->tqi_ver; qInfo->tqi_subtype = qi->tqi_subtype; qInfo->tqi_qflags = qi->tqi_qflags; @@ -1141,6 +1139,7 @@ ath_hal_getTxQProps(struct ath_hal *ah, qInfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit; qInfo->tqi_burstTime = qi->tqi_burstTime; qInfo->tqi_readyTime = qi->tqi_readyTime; + qInfo->tqi_compBuf = qi->tqi_physCompBuf; return AH_TRUE; } diff --git a/sys/dev/ath/ath_hal/ah.h b/sys/dev/ath/ath_hal/ah.h index b887e9f5afb4..e39ff2b7d03d 100644 --- a/sys/dev/ath/ath_hal/ah.h +++ b/sys/dev/ath/ath_hal/ah.h @@ -33,6 +33,18 @@ #include "ah_osdep.h" /* + * Endianness macros; used by various structures and code. + */ +#define AH_BIG_ENDIAN 4321 +#define AH_LITTLE_ENDIAN 1234 + +#if _BYTE_ORDER == _BIG_ENDIAN +#define AH_BYTE_ORDER AH_BIG_ENDIAN +#else +#define AH_BYTE_ORDER AH_LITTLE_ENDIAN +#endif + +/* * The maximum number of TX/RX chains supported. * This is intended to be used by various statistics gathering operations * (NF, RSSI, EVM). @@ -727,7 +739,6 @@ typedef enum { HAL_HT_EXTPROTSPACING_25 = 1, /* 25 MHz spacing */ } HAL_HT_EXTPROTSPACING; - typedef enum { HAL_RX_CLEAR_CTL_LOW = 0x1, /* force control channel to appear busy */ HAL_RX_CLEAR_EXT_LOW = 0x2, /* force extension channel to appear busy */ @@ -893,11 +904,13 @@ typedef struct { } HAL_ANI_STATS; typedef struct { - uint8_t noiseImmunityLevel; + uint8_t noiseImmunityLevel; /* Global for pre-AR9380; OFDM later*/ + uint8_t cckNoiseImmunityLevel; /* AR9380: CCK specific NI */ uint8_t spurImmunityLevel; uint8_t firstepLevel; uint8_t ofdmWeakSigDetectOff; uint8_t cckWeakSigThreshold; + uint8_t mrcCck; /* MRC CCK is enabled */ uint32_t listenTime; /* NB: intentionally ordered so data exported to user space is first */ @@ -956,7 +969,7 @@ typedef struct { */ typedef enum { HAL_ANI_PRESENT = 0, /* is ANI support present */ - HAL_ANI_NOISE_IMMUNITY_LEVEL = 1, /* set level */ + HAL_ANI_NOISE_IMMUNITY_LEVEL = 1, /* set level (global or ofdm) */ HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION = 2, /* enable/disable */ HAL_ANI_CCK_WEAK_SIGNAL_THR = 3, /* enable/disable */ HAL_ANI_FIRSTEP_LEVEL = 4, /* set level */ @@ -964,6 +977,7 @@ typedef enum { HAL_ANI_MODE = 6, /* 0 => manual, 1 => auto (XXX do not change) */ HAL_ANI_PHYERR_RESET = 7, /* reset phy error stats */ HAL_ANI_MRC_CCK = 8, + HAL_ANI_CCK_NOISE_IMMUNITY_LEVEL = 9, /* set level (cck) */ } HAL_ANI_CMD; #define HAL_ANI_ALL 0xffffffff @@ -1038,7 +1052,6 @@ typedef enum { HAL_DFS_MKK4_DOMAIN = 3, /* Japan dfs domain */ } HAL_DFS_DOMAIN; - /* * MFP decryption options for initializing the MAC. */ @@ -1311,7 +1324,7 @@ struct ath_hal { void __ahdecl(*ah_setRxDP)(struct ath_hal*, uint32_t rxdp, HAL_RX_QUEUE); void __ahdecl(*ah_enableReceive)(struct ath_hal*); HAL_BOOL __ahdecl(*ah_stopDmaReceive)(struct ath_hal*); - void __ahdecl(*ah_startPcuReceive)(struct ath_hal*); + void __ahdecl(*ah_startPcuReceive)(struct ath_hal*, HAL_BOOL); void __ahdecl(*ah_stopPcuReceive)(struct ath_hal*); void __ahdecl(*ah_setMulticastFilter)(struct ath_hal*, uint32_t filter0, uint32_t filter1); diff --git a/sys/dev/ath/ath_hal/ah_eeprom_9287.c b/sys/dev/ath/ath_hal/ah_eeprom_9287.c index 974580d26394..42b3ff8b3252 100644 --- a/sys/dev/ath/ath_hal/ah_eeprom_9287.c +++ b/sys/dev/ath/ath_hal/ah_eeprom_9287.c @@ -207,11 +207,11 @@ static uint16_t v9287EepromGetSpurChan(struct ath_hal *ah, int ix, HAL_BOOL is2GHz) { HAL_EEPROM_9287 *ee = AH_PRIVATE(ah)->ah_eeprom; - + HALASSERT(is2GHz == AH_TRUE); if (is2GHz != AH_TRUE) return 0; /* XXX ? */ - + HALASSERT(0 <= ix && ix < AR5416_EEPROM_MODAL_SPURS); return ee->ee_base.modalHeader.spurChans[ix].spurChan; } @@ -234,7 +234,6 @@ fbin2freq(uint8_t fbin, HAL_BOOL is2GHz) return (uint16_t)((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin)); } - /* * Copy EEPROM Conformance Testing Limits contents * into the allocated space @@ -247,7 +246,7 @@ v9287EepromReadCTLInfo(struct ath_hal *ah, HAL_EEPROM_9287 *ee) { RD_EDGES_POWER *rep = ee->ee_rdEdgesPower; int i, j; - + HALASSERT(AR9287_NUM_CTLS <= sizeof(ee->ee_rdEdgesPower)/NUM_EDGES); for (i = 0; ee->ee_base.ctlIndex[i] != 0 && i < AR9287_NUM_CTLS; i++) { @@ -359,7 +358,7 @@ ath_hal_9287EepromAttach(struct ath_hal *ah) len = ee->ee_base.baseEepHeader.length; } len = AH_MIN(len, sizeof(HAL_EEPROM_9287)) / sizeof(uint16_t); - + /* Apply the checksum, done in native eeprom format */ /* XXX - Need to check to make sure checksum calculation is done * in the correct endian format. Right now, it seems it would diff --git a/sys/dev/ath/ath_hal/ah_eeprom_9287.h b/sys/dev/ath/ath_hal/ah_eeprom_9287.h index 891b4841b153..6d15a6df0204 100644 --- a/sys/dev/ath/ath_hal/ah_eeprom_9287.h +++ b/sys/dev/ath/ath_hal/ah_eeprom_9287.h @@ -166,5 +166,4 @@ typedef struct { typedef struct modal_eep_ar9287_header MODAL_EEP_9287_HEADER; typedef struct base_eep_ar9287_header BASE_EEP_9287_HEADER; - #endif /* __AH_EEPROM_9287_H__ */ diff --git a/sys/dev/ath/ath_hal/ah_eeprom_v14.c b/sys/dev/ath/ath_hal/ah_eeprom_v14.c index 3ae81217327d..d8bb96d56b28 100644 --- a/sys/dev/ath/ath_hal/ah_eeprom_v14.c +++ b/sys/dev/ath/ath_hal/ah_eeprom_v14.c @@ -249,7 +249,7 @@ static uint16_t v14EepromGetSpurChan(struct ath_hal *ah, int ix, HAL_BOOL is2GHz) { HAL_EEPROM_v14 *ee = AH_PRIVATE(ah)->ah_eeprom; - + HALASSERT(0 <= ix && ix < AR5416_EEPROM_MODAL_SPURS); return ee->ee_base.modalHeader[is2GHz].spurChans[ix].spurChan; } @@ -284,7 +284,7 @@ v14EepromReadCTLInfo(struct ath_hal *ah, HAL_EEPROM_v14 *ee) { RD_EDGES_POWER *rep = ee->ee_rdEdgesPower; int i, j; - + HALASSERT(AR5416_NUM_CTLS <= sizeof(ee->ee_rdEdgesPower)/NUM_EDGES); for (i = 0; ee->ee_base.ctlIndex[i] != 0 && i < AR5416_NUM_CTLS; i++) { @@ -342,7 +342,7 @@ ath_hal_v14EepromAttach(struct ath_hal *ah) uint32_t sum; HALASSERT(ee == AH_NULL); - + /* * Don't check magic if we're supplied with an EEPROM block, * typically this is from Howl but it may also be from later @@ -398,7 +398,7 @@ ath_hal_v14EepromAttach(struct ath_hal *ah) len = ee->ee_base.baseEepHeader.length; } len = AH_MIN(len, sizeof(struct ar5416eeprom)) / sizeof(uint16_t); - + /* Apply the checksum, done in native eeprom format */ /* XXX - Need to check to make sure checksum calculation is done * in the correct endian format. Right now, it seems it would diff --git a/sys/dev/ath/ath_hal/ah_eeprom_v3.c b/sys/dev/ath/ath_hal/ah_eeprom_v3.c index 9d7d011fcd65..2f1b2940de47 100644 --- a/sys/dev/ath/ath_hal/ah_eeprom_v3.c +++ b/sys/dev/ath/ath_hal/ah_eeprom_v3.c @@ -739,14 +739,14 @@ readEepromRawPowerCalInfo2413(struct ath_hal *ah, HAL_EEPROM *ee) int numEEPROMWordsPerChannel; uint32_t off; HAL_BOOL ret = AH_FALSE; - + HALASSERT(ee->ee_version >= AR_EEPROM_VER5_0); HALASSERT(ee->ee_eepMap == 2); - + pCal = ath_hal_malloc(sizeof(EEPROM_DATA_STRUCT_2413)); if (pCal == AH_NULL) goto exit; - + off = ee->ee_eepMap2PowerCalStart; if (ee->ee_Amode) { OS_MEMZERO(pCal, sizeof(EEPROM_DATA_STRUCT_2413)); diff --git a/sys/dev/ath/ath_hal/ah_eeprom_v3.h b/sys/dev/ath/ath_hal/ah_eeprom_v3.h index 2ec54713b261..be71a2486fde 100644 --- a/sys/dev/ath/ath_hal/ah_eeprom_v3.h +++ b/sys/dev/ath/ath_hal/ah_eeprom_v3.h @@ -231,7 +231,6 @@ typedef struct cornerCalInfo { #define NUM_TARGET_POWER_LOCATIONS_11B 4 #define NUM_TARGET_POWER_LOCATIONS_11G 6 - typedef struct { uint16_t xpd_gain; uint16_t numPcdacs; diff --git a/sys/dev/ath/ath_hal/ah_eeprom_v4k.c b/sys/dev/ath/ath_hal/ah_eeprom_v4k.c index 69142ded5447..a9d16100d917 100644 --- a/sys/dev/ath/ath_hal/ah_eeprom_v4k.c +++ b/sys/dev/ath/ath_hal/ah_eeprom_v4k.c @@ -200,7 +200,7 @@ static uint16_t v4kEepromGetSpurChan(struct ath_hal *ah, int ix, HAL_BOOL is2GHz) { HAL_EEPROM_v4k *ee = AH_PRIVATE(ah)->ah_eeprom; - + HALASSERT(0 <= ix && ix < AR5416_EEPROM_MODAL_SPURS); HALASSERT(is2GHz); return ee->ee_base.modalHeader.spurChans[ix].spurChan; @@ -236,7 +236,7 @@ v4kEepromReadCTLInfo(struct ath_hal *ah, HAL_EEPROM_v4k *ee) { RD_EDGES_POWER *rep = ee->ee_rdEdgesPower; int i, j; - + HALASSERT(AR5416_4K_NUM_CTLS <= sizeof(ee->ee_rdEdgesPower)/NUM_EDGES); for (i = 0; ee->ee_base.ctlIndex[i] != 0 && i < AR5416_4K_NUM_CTLS; i++) { @@ -347,7 +347,7 @@ ath_hal_v4kEepromAttach(struct ath_hal *ah) len = ee->ee_base.baseEepHeader.length; } len = AH_MIN(len, sizeof(struct ar5416eeprom_4k)) / sizeof(uint16_t); - + /* Apply the checksum, done in native eeprom format */ /* XXX - Need to check to make sure checksum calculation is done * in the correct endian format. Right now, it seems it would diff --git a/sys/dev/ath/ath_hal/ah_internal.h b/sys/dev/ath/ath_hal/ah_internal.h index 6b584c2454b3..87c67d73ddca 100644 --- a/sys/dev/ath/ath_hal/ah_internal.h +++ b/sys/dev/ath/ath_hal/ah_internal.h @@ -849,7 +849,6 @@ typedef struct { uint16_t ee_data; /* write data */ } HAL_DIAG_EEVAL; - typedef struct { u_int offset; /* reg offset */ uint32_t val; /* reg value */ diff --git a/sys/dev/ath/ath_hal/ah_regdomain.c b/sys/dev/ath/ath_hal/ah_regdomain.c index 77bf417c2e41..c0ae4a94a4c6 100644 --- a/sys/dev/ath/ath_hal/ah_regdomain.c +++ b/sys/dev/ath/ath_hal/ah_regdomain.c @@ -695,7 +695,7 @@ getchannels(struct ath_hal *ah, else if (cm->flags & IEEE80211_CHAN_2GHZ) rd = rd2GHz; else { - ath_hal_printf(ah, "%s: Unkonwn HAL flags 0x%x\n", + ath_hal_printf(ah, "%s: Unknown HAL flags 0x%x\n", __func__, cm->flags); return HAL_EINVAL; } @@ -953,7 +953,6 @@ ath_hal_getctl(struct ath_hal *ah, const struct ieee80211_channel *c) return ctl; } - /* * Update the current dfsDomain setting based on the given * country code. @@ -979,7 +978,6 @@ ath_hal_update_dfsdomain(struct ath_hal *ah) __func__, AH_PRIVATE(ah)->ah_dfsDomain); } - /* * Return the max allowed antenna gain and apply any regulatory * domain specific changes. diff --git a/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_domains.h b/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_domains.h index 6555147b4e60..5956a804b03a 100644 --- a/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_domains.h +++ b/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_domains.h @@ -64,7 +64,6 @@ W1(_fg) | W1(_fh) | W1(_fi) } static REG_DOMAIN regDomains[] = { - {.regDmnEnum = DEBUG_REG_DMN, .conformanceTestLimit = FCC, .dfsMask = DFS_FCC3, diff --git a/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_freqbands.h b/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_freqbands.h index c7169113c11b..5475c6508972 100644 --- a/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_freqbands.h +++ b/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_freqbands.h @@ -198,7 +198,6 @@ static REG_DMN_FREQ_BAND regDmn5GhzFreq[] = { #define W2_5825_5825 AFTER(W2_5180_5240) }; - /* * 5GHz Turbo (dynamic & static) tags */ @@ -373,7 +372,7 @@ static REG_DMN_FREQ_BAND regDmn2Ghz11gFreq[] = { #define G3_2412_2462 AFTER(G2_2412_2462) { 2412, 2462, 27, 6, 5, 5, NO_DFS, NO_PSCAN }, #define G4_2412_2462 AFTER(G3_2412_2462) - + { 2432, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN }, #define G1_2432_2442 AFTER(G4_2412_2462) diff --git a/sys/dev/ath/ath_hal/ah_soc.h b/sys/dev/ath/ath_hal/ah_soc.h index 3d77b8234857..e391a2c869e8 100644 --- a/sys/dev/ath/ath_hal/ah_soc.h +++ b/sys/dev/ath/ath_hal/ah_soc.h @@ -62,18 +62,18 @@ struct ar531x_boarddata { #define BD_WLAN1_5G_EN 0x00040000 /* FLAG for radio0_2G */ uint16_t resetConfigGpio; /* Reset factory GPIO pin */ uint16_t sysLedGpio; /* System LED GPIO pin */ - + uint32_t cpuFreq; /* CPU core frequency in Hz */ uint32_t sysFreq; /* System frequency in Hz */ uint32_t cntFreq; /* Calculated C0_COUNT frequency */ - + uint8_t wlan0Mac[6]; uint8_t enet0Mac[6]; uint8_t enet1Mac[6]; - + uint16_t pciId; /* Pseudo PCIID for common code */ uint16_t memCap; /* cap bank1 in MB */ - + /* version 3 */ uint8_t wlan1Mac[6]; /* (ar5212) */ }; diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210.h b/sys/dev/ath/ath_hal/ar5210/ar5210.h index 756c8e03e51e..373c676e25b3 100644 --- a/sys/dev/ath/ath_hal/ar5210/ar5210.h +++ b/sys/dev/ath/ath_hal/ar5210/ar5210.h @@ -195,7 +195,7 @@ extern uint32_t ar5210GetRxDP(struct ath_hal *, HAL_RX_QUEUE); extern void ar5210SetRxDP(struct ath_hal *, uint32_t rxdp, HAL_RX_QUEUE); extern void ar5210EnableReceive(struct ath_hal *); extern HAL_BOOL ar5210StopDmaReceive(struct ath_hal *); -extern void ar5210StartPcuReceive(struct ath_hal *); +extern void ar5210StartPcuReceive(struct ath_hal *, HAL_BOOL); extern void ar5210StopPcuReceive(struct ath_hal *); extern void ar5210SetMulticastFilter(struct ath_hal *, uint32_t filter0, uint32_t filter1); diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210_recv.c b/sys/dev/ath/ath_hal/ar5210/ar5210_recv.c index 38295b99d1ca..a11e0300721f 100644 --- a/sys/dev/ath/ath_hal/ar5210/ar5210_recv.c +++ b/sys/dev/ath/ath_hal/ar5210/ar5210_recv.c @@ -50,7 +50,6 @@ ar5210SetRxDP(struct ath_hal *ah, uint32_t rxdp, HAL_RX_QUEUE qtype) OS_REG_WRITE(ah, AR_RXDP, rxdp); } - /* * Set Receive Enable bits. */ @@ -86,7 +85,7 @@ ar5210StopDmaReceive(struct ath_hal *ah) * Start Transmit at the PCU engine (unpause receive) */ void -ar5210StartPcuReceive(struct ath_hal *ah) +ar5210StartPcuReceive(struct ath_hal *ah, HAL_BOOL is_scanning) { ar5210UpdateDiagReg(ah, OS_REG_READ(ah, AR_DIAG_SW) & ~(AR_DIAG_SW_DIS_RX)); diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210_reset.c b/sys/dev/ath/ath_hal/ar5210/ar5210_reset.c index b5656fb36419..bf1b9683a2cc 100644 --- a/sys/dev/ath/ath_hal/ar5210/ar5210_reset.c +++ b/sys/dev/ath/ath_hal/ar5210/ar5210_reset.c @@ -611,7 +611,6 @@ ar5210SetResetReg(struct ath_hal *ah, uint32_t resetMask, u_int delay) return rt; } - /* * Returns: the pcdac value */ diff --git a/sys/dev/ath/ath_hal/ar5211/ar5211.h b/sys/dev/ath/ath_hal/ar5211/ar5211.h index 7188966ef9ea..186e69e9cd84 100644 --- a/sys/dev/ath/ath_hal/ar5211/ar5211.h +++ b/sys/dev/ath/ath_hal/ar5211/ar5211.h @@ -218,7 +218,7 @@ extern uint32_t ar5211GetRxDP(struct ath_hal *, HAL_RX_QUEUE); extern void ar5211SetRxDP(struct ath_hal *, uint32_t rxdp, HAL_RX_QUEUE); extern void ar5211EnableReceive(struct ath_hal *); extern HAL_BOOL ar5211StopDmaReceive(struct ath_hal *); -extern void ar5211StartPcuReceive(struct ath_hal *); +extern void ar5211StartPcuReceive(struct ath_hal *, HAL_BOOL); extern void ar5211StopPcuReceive(struct ath_hal *); extern void ar5211SetMulticastFilter(struct ath_hal *, uint32_t filter0, uint32_t filter1); diff --git a/sys/dev/ath/ath_hal/ar5211/ar5211_keycache.c b/sys/dev/ath/ath_hal/ar5211/ar5211_keycache.c index 8d703023edb3..7a8ed460ff80 100644 --- a/sys/dev/ath/ath_hal/ar5211/ar5211_keycache.c +++ b/sys/dev/ath/ath_hal/ar5211/ar5211_keycache.c @@ -163,7 +163,6 @@ ar5211SetKeyCacheEntry(struct ath_hal *ah, uint16_t entry, if (k->kv_len <= 104 / NBBY) key4 &= 0xff; - /* * Note: WEP key cache hardware requires that each double-word * pair be written in even/odd order (since the destination is diff --git a/sys/dev/ath/ath_hal/ar5211/ar5211_misc.c b/sys/dev/ath/ath_hal/ar5211/ar5211_misc.c index 4395818ab2bd..ea1327b11a6a 100644 --- a/sys/dev/ath/ath_hal/ar5211/ar5211_misc.c +++ b/sys/dev/ath/ath_hal/ar5211/ar5211_misc.c @@ -708,7 +708,6 @@ ar5211Get11nExtBusy(struct ath_hal *ah) return (0); } - /* * There's no channel survey support for the AR5211. */ diff --git a/sys/dev/ath/ath_hal/ar5211/ar5211_phy.c b/sys/dev/ath/ath_hal/ar5211/ar5211_phy.c index 6507c879ed92..42d9665396a1 100644 --- a/sys/dev/ath/ath_hal/ar5211/ar5211_phy.c +++ b/sys/dev/ath/ath_hal/ar5211/ar5211_phy.c @@ -81,7 +81,6 @@ HAL_RATE_TABLE ar5211_11b_table = { #undef CCK #undef TURBO - const HAL_RATE_TABLE * ar5211GetRateTable(struct ath_hal *ah, u_int mode) { diff --git a/sys/dev/ath/ath_hal/ar5211/ar5211_recv.c b/sys/dev/ath/ath_hal/ar5211/ar5211_recv.c index 9b3bb677d5d6..1922f8775d54 100644 --- a/sys/dev/ath/ath_hal/ar5211/ar5211_recv.c +++ b/sys/dev/ath/ath_hal/ar5211/ar5211_recv.c @@ -51,7 +51,6 @@ ar5211SetRxDP(struct ath_hal *ah, uint32_t rxdp, HAL_RX_QUEUE qtype) HALASSERT(OS_REG_READ(ah, AR_RXDP) == rxdp); } - /* * Set Receive Enable bits. */ @@ -87,7 +86,7 @@ ar5211StopDmaReceive(struct ath_hal *ah) * Start Transmit at the PCU engine (unpause receive) */ void -ar5211StartPcuReceive(struct ath_hal *ah) +ar5211StartPcuReceive(struct ath_hal *ah, HAL_BOOL is_scanning) { OS_REG_WRITE(ah, AR_DIAG_SW, OS_REG_READ(ah, AR_DIAG_SW) & ~(AR_DIAG_SW_DIS_RX)); diff --git a/sys/dev/ath/ath_hal/ar5211/ar5211_xmit.c b/sys/dev/ath/ath_hal/ar5211/ar5211_xmit.c index 4bcb8fd6497a..9b32c4de496e 100644 --- a/sys/dev/ath/ath_hal/ar5211/ar5211_xmit.c +++ b/sys/dev/ath/ath_hal/ar5211/ar5211_xmit.c @@ -193,7 +193,6 @@ setTxQInterrupts(struct ath_hal *ah, HAL_TX_QUEUE_INFO *qi) AR_IMR_S2_QCU_TXURN, ahp->ah_txUrnInterruptMask); } - /* * Free a tx DCU/QCU combination. */ @@ -677,7 +676,6 @@ ar5211GetTxCompletionRates(struct ath_hal *ah, const struct ath_desc *ds0, int * return AH_FALSE; } - void ar5211SetTxDescLink(struct ath_hal *ah, void *ds, uint32_t link) { diff --git a/sys/dev/ath/ath_hal/ar5211/ar5211phy.h b/sys/dev/ath/ath_hal/ar5211/ar5211phy.h index c344cdc9b054..9e44b903b085 100644 --- a/sys/dev/ath/ath_hal/ar5211/ar5211phy.h +++ b/sys/dev/ath/ath_hal/ar5211/ar5211phy.h @@ -48,7 +48,6 @@ #define AR_PHY_PLL_CTL_40 0x18 /* 40 MHz */ #define AR_PHY_PLL_CTL_20 0x13 /* 20 MHz half rate 11a for emulation */ - #define AR_PHY_RX_DELAY 0x9914 /* PHY analog_power_on_time, in 100ns increments */ #define AR_PHY_RX_DELAY_M 0x00003FFF /* Mask for delay from active assertion (wake up) */ /* to enable_receiver */ diff --git a/sys/dev/ath/ath_hal/ar5211/ar5211reg.h b/sys/dev/ath/ath_hal/ar5211/ar5211reg.h index ef2fb863d815..3cbdacc972c1 100644 --- a/sys/dev/ath/ath_hal/ar5211/ar5211reg.h +++ b/sys/dev/ath/ath_hal/ar5211/ar5211reg.h @@ -808,7 +808,6 @@ #define AR5211_USEC_RX_LAT_M 0x1F800000 /* Rx latency */ #define AR5211_USEC_RX_LAT_S 23 - #define AR_BEACON_PERIOD 0x0000FFFF /* Beacon period in TU/msec */ #define AR_BEACON_PERIOD_S 0 /* Byte offset of PERIOD start*/ #define AR_BEACON_TIM 0x007F0000 /* Byte offset of TIM start */ diff --git a/sys/dev/ath/ath_hal/ar5212/ar2316.c b/sys/dev/ath/ath_hal/ar5212/ar2316.c index 186e72e9856c..1259c777d99c 100644 --- a/sys/dev/ath/ath_hal/ar5212/ar2316.c +++ b/sys/dev/ath/ath_hal/ar5212/ar2316.c @@ -629,7 +629,7 @@ ar2316GetMaxPower(struct ath_hal *ah, const RAW_DATA_PER_CHANNEL_2316 *data) { uint32_t ii; uint16_t Pmax=0,numVpd; - + for (ii=0; ii< MAX_NUM_PDGAINS_PER_CHANNEL; ii++) { /* work forwards cuase lowest pdGain for highest power */ numVpd = data->pDataPerPDGain[ii].numVpd; @@ -664,7 +664,7 @@ ar2316GetChannelMaxMinPower(struct ath_hal *ah, numChannels = pRawDataset->numChannels; data = pRawDataset->pDataPerChannel; - + /* Make sure the channel is in the range of the TP values * (freq piers) */ diff --git a/sys/dev/ath/ath_hal/ar5212/ar2317.c b/sys/dev/ath/ath_hal/ar5212/ar2317.c index 29a9b369f3a5..814e4318b39d 100644 --- a/sys/dev/ath/ath_hal/ar5212/ar2317.c +++ b/sys/dev/ath/ath_hal/ar5212/ar2317.c @@ -608,7 +608,7 @@ ar2317GetMaxPower(struct ath_hal *ah, const RAW_DATA_PER_CHANNEL_2317 *data) uint32_t ii; uint16_t Pmax=0,numVpd; uint16_t vpdmax; - + for (ii=0; ii< MAX_NUM_PDGAINS_PER_CHANNEL; ii++) { /* work forwards cuase lowest pdGain for highest power */ numVpd = data->pDataPerPDGain[ii].numVpd; @@ -644,7 +644,7 @@ ar2317GetChannelMaxMinPower(struct ath_hal *ah, numChannels = pRawDataset->numChannels; data = pRawDataset->pDataPerChannel; - + /* Make sure the channel is in the range of the TP values * (freq piers) */ diff --git a/sys/dev/ath/ath_hal/ar5212/ar2413.c b/sys/dev/ath/ath_hal/ar5212/ar2413.c index e2a8d0203360..3c1ce6805a2a 100644 --- a/sys/dev/ath/ath_hal/ar5212/ar2413.c +++ b/sys/dev/ath/ath_hal/ar5212/ar2413.c @@ -624,7 +624,7 @@ ar2413GetMaxPower(struct ath_hal *ah, const RAW_DATA_PER_CHANNEL_2413 *data) { uint32_t ii; uint16_t Pmax=0,numVpd; - + for (ii=0; ii< MAX_NUM_PDGAINS_PER_CHANNEL; ii++) { /* work forwards cuase lowest pdGain for highest power */ numVpd = data->pDataPerPDGain[ii].numVpd; @@ -659,7 +659,7 @@ ar2413GetChannelMaxMinPower(struct ath_hal *ah, numChannels = pRawDataset->numChannels; data = pRawDataset->pDataPerChannel; - + /* Make sure the channel is in the range of the TP values * (freq piers) */ diff --git a/sys/dev/ath/ath_hal/ar5212/ar2425.c b/sys/dev/ath/ath_hal/ar5212/ar2425.c index 9159ad2370d1..979f45b3619e 100644 --- a/sys/dev/ath/ath_hal/ar5212/ar2425.c +++ b/sys/dev/ath/ath_hal/ar5212/ar2425.c @@ -492,7 +492,6 @@ ar2425getGainBoundariesAndPdadcsForPowers(struct ath_hal *ah, uint16_t channel, HALDEBUG(ah, HAL_DEBUG_RFPARAM, "<==%s\n", __func__); } - /* Same as 2413 set power table */ static HAL_BOOL ar2425SetPowerTable(struct ath_hal *ah, @@ -586,7 +585,7 @@ ar2425GetMaxPower(struct ath_hal *ah, const RAW_DATA_PER_CHANNEL_2413 *data) { uint32_t ii; uint16_t Pmax=0,numVpd; - + for (ii=0; ii< MAX_NUM_PDGAINS_PER_CHANNEL; ii++) { /* work forwards cuase lowest pdGain for highest power */ numVpd = data->pDataPerPDGain[ii].numVpd; @@ -622,7 +621,7 @@ ar2425GetChannelMaxMinPower(struct ath_hal *ah, numChannels = pRawDataset->numChannels; data = pRawDataset->pDataPerChannel; - + /* Make sure the channel is in the range of the TP values * (freq piers) */ diff --git a/sys/dev/ath/ath_hal/ar5212/ar5111.c b/sys/dev/ath/ath_hal/ar5212/ar5111.c index 128332266b52..fe8acccd0691 100644 --- a/sys/dev/ath/ath_hal/ar5212/ar5111.c +++ b/sys/dev/ath/ath_hal/ar5212/ar5111.c @@ -336,7 +336,6 @@ ar5111SetRfRegs(struct ath_hal *ah, const struct ieee80211_channel *chan, ar5212ModifyRfBuffer(rfReg, rfWaitS, 5, 19, 0); ar5212ModifyRfBuffer(rfReg, rfWaitI, 5, 24, 0); ar5212ModifyRfBuffer(rfReg, rfMaxTime, 2, 49, 0); - } HAL_INI_WRITE_BANK(ah, ar5212Bank7_5111, rfReg, regWrites); diff --git a/sys/dev/ath/ath_hal/ar5212/ar5112.c b/sys/dev/ath/ath_hal/ar5212/ar5112.c index 1e9e20355677..0c3a6032e5fa 100644 --- a/sys/dev/ath/ath_hal/ar5212/ar5112.c +++ b/sys/dev/ath/ath_hal/ar5212/ar5112.c @@ -281,7 +281,7 @@ ar5112SetRfRegs(struct ath_hal *ah, ar5212ModifyRfBuffer(priv->Bank6Data, ob5GHz, 3, 279, 0); ar5212ModifyRfBuffer(priv->Bank6Data, db5GHz, 3, 282, 0); } - + /* Lower synth voltage for X112 Rev 2.0 only */ if (IS_RADX112_REV2(ah)) { /* Non-Reversed analyg registers - so values are pre-reversed */ @@ -763,7 +763,7 @@ ar5112GetMinPower(struct ath_hal *ah, const EXPN_DATA_PER_CHANNEL_5112 *data) retVal = minPwr - (minPcdac*2); return(retVal); } - + static HAL_BOOL ar5112GetChannelMaxMinPower(struct ath_hal *ah, const struct ieee80211_channel *chan, diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212.h b/sys/dev/ath/ath_hal/ar5212/ar5212.h index 0baba50c55e6..f80f88c5df85 100644 --- a/sys/dev/ath/ath_hal/ar5212/ar5212.h +++ b/sys/dev/ath/ath_hal/ar5212/ar5212.h @@ -539,7 +539,7 @@ extern uint32_t ar5212GetRxDP(struct ath_hal *ath, HAL_RX_QUEUE); extern void ar5212SetRxDP(struct ath_hal *ah, uint32_t rxdp, HAL_RX_QUEUE); extern void ar5212EnableReceive(struct ath_hal *ah); extern HAL_BOOL ar5212StopDmaReceive(struct ath_hal *ah); -extern void ar5212StartPcuReceive(struct ath_hal *ah); +extern void ar5212StartPcuReceive(struct ath_hal *ah, HAL_BOOL); extern void ar5212StopPcuReceive(struct ath_hal *ah); extern void ar5212SetMulticastFilter(struct ath_hal *ah, uint32_t filter0, uint32_t filter1); diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_ani.c b/sys/dev/ath/ath_hal/ar5212/ar5212_ani.c index 4e2cd683df8c..eb9999e1ca5d 100644 --- a/sys/dev/ath/ath_hal/ar5212/ar5212_ani.c +++ b/sys/dev/ath/ath_hal/ar5212/ar5212_ani.c @@ -225,7 +225,7 @@ ar5212AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param) struct ath_hal_5212 *ahp = AH5212(ah); struct ar5212AniState *aniState = ahp->ah_curani; const struct ar5212AniParams *params = AH_NULL; - + /* * This function may be called before there's a current * channel (eg to disable ANI.) @@ -784,7 +784,7 @@ ar5212AniLowerImmunity(struct ath_hal *ah) struct ath_hal_5212 *ahp = AH5212(ah); struct ar5212AniState *aniState; const struct ar5212AniParams *params; - + HALASSERT(ANI_ENA(ah)); aniState = ahp->ah_curani; diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_interrupts.c b/sys/dev/ath/ath_hal/ar5212/ar5212_interrupts.c index ead62adfce48..b52045baea19 100644 --- a/sys/dev/ath/ath_hal/ar5212/ar5212_interrupts.c +++ b/sys/dev/ath/ath_hal/ar5212/ar5212_interrupts.c @@ -27,7 +27,6 @@ #include "ar5212/ar5212reg.h" #include "ar5212/ar5212phy.h" - /* * Checks to see if an interrupt is pending on our NIC * diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_keycache.c b/sys/dev/ath/ath_hal/ar5212/ar5212_keycache.c index fa6936231952..8daaf250ec0b 100644 --- a/sys/dev/ath/ath_hal/ar5212/ar5212_keycache.c +++ b/sys/dev/ath/ath_hal/ar5212/ar5212_keycache.c @@ -245,7 +245,6 @@ ar5212SetKeyCacheEntry(struct ath_hal *ah, uint16_t entry, OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType); (void) ar5212SetKeyCacheEntryMac(ah, entry, mac); - /* * Write MIC entry according to new or old key layout. * The MISC_MODE register is assumed already set so diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_misc.c b/sys/dev/ath/ath_hal/ar5212/ar5212_misc.c index 6450c8d6f426..577e1e7491b3 100644 --- a/sys/dev/ath/ath_hal/ar5212/ar5212_misc.c +++ b/sys/dev/ath/ath_hal/ar5212/ar5212_misc.c @@ -623,7 +623,7 @@ ar5212SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now) * timeouts. This value is in core clocks. */ timeout = ACK_CTS_TIMEOUT_11A + (coverageclass * 3 * clkRate); - + /* * Write the values: slot, eifs, ack/cts timeouts. */ @@ -1194,7 +1194,6 @@ ar5212EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) val &= ~ AR_PHY_RADAR_0_ENA; if (IS_5413(ah)) { - if (pe->pe_blockradar == 1) OS_REG_SET_BIT(ah, AR_PHY_RADAR_2, AR_PHY_RADAR_2_BLOCKOFDMWEAK); diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_phy.c b/sys/dev/ath/ath_hal/ar5212/ar5212_phy.c index 6f9c9dc1744b..ba56477fa506 100644 --- a/sys/dev/ath/ath_hal/ar5212/ar5212_phy.c +++ b/sys/dev/ath/ath_hal/ar5212/ar5212_phy.c @@ -129,7 +129,6 @@ HAL_RATE_TABLE ar5212_11b_table = { }, }; - /* Venice TODO: roundUpRate() is broken when the rate table does not represent rates * in increasing order e.g. 5.5, 11, 6, 9. * An average rate of 6 Mbps will currently map to 11 Mbps. diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_recv.c b/sys/dev/ath/ath_hal/ar5212/ar5212_recv.c index a2e36be5f70e..8ead1250fb87 100644 --- a/sys/dev/ath/ath_hal/ar5212/ar5212_recv.c +++ b/sys/dev/ath/ath_hal/ar5212/ar5212_recv.c @@ -87,7 +87,7 @@ ar5212StopDmaReceive(struct ath_hal *ah) * Start Transmit at the PCU engine (unpause receive) */ void -ar5212StartPcuReceive(struct ath_hal *ah) +ar5212StartPcuReceive(struct ath_hal *ah, HAL_BOOL is_scanning) { struct ath_hal_private *ahp = AH_PRIVATE(ah); @@ -95,8 +95,8 @@ ar5212StartPcuReceive(struct ath_hal *ah) OS_REG_WRITE(ah, AR_DIAG_SW, OS_REG_READ(ah, AR_DIAG_SW) &~ AR_DIAG_RX_DIS); ar5212EnableMibCounters(ah); - /* NB: restore current settings */ - ar5212AniReset(ah, ahp->ah_curchan, ahp->ah_opmode, AH_TRUE); + /* NB: restore current settings if we're not scanning */ + ar5212AniReset(ah, ahp->ah_curchan, ahp->ah_opmode, !is_scanning); } /* @@ -265,7 +265,6 @@ ar5212ProcRxDesc(struct ath_hal *ah, struct ath_desc *ds, rs->rs_datalen = ads->ds_rxstatus0 & AR_DataLen; rs->rs_tstamp = MS(ads->ds_rxstatus1, AR_RcvTimestamp); rs->rs_status = 0; - /* XXX what about KeyCacheMiss? */ rs->rs_rssi = MS(ads->ds_rxstatus0, AR_RcvSigStrength); /* discard invalid h/w rssi data */ if (rs->rs_rssi == -128) @@ -274,6 +273,8 @@ ar5212ProcRxDesc(struct ath_hal *ah, struct ath_desc *ds, rs->rs_keyix = MS(ads->ds_rxstatus1, AR_KeyIdx); else rs->rs_keyix = HAL_RXKEYIX_INVALID; + if (ads->ds_rxstatus1 & AR_KeyCacheMiss) + rs->rs_status |= HAL_RXERR_KEYMISS; /* NB: caller expected to do rate table mapping */ rs->rs_rate = MS(ads->ds_rxstatus0, AR_RcvRate); rs->rs_antenna = MS(ads->ds_rxstatus0, AR_RcvAntenna); diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_reset.c b/sys/dev/ath/ath_hal/ar5212/ar5212_reset.c index a5e9ca65d056..12fe41b0c19f 100644 --- a/sys/dev/ath/ath_hal/ar5212/ar5212_reset.c +++ b/sys/dev/ath/ath_hal/ar5212/ar5212_reset.c @@ -692,7 +692,7 @@ done: HALDEBUG(ah, HAL_DEBUG_RESET, "%s: done\n", __func__); RESTORE_CCK(ah, chan, isBmode); - + OS_MARK(ah, AH_MARK_RESET_DONE, 0); return AH_TRUE; @@ -1192,7 +1192,6 @@ ar5212MacStop(struct ath_hal *ah) return status; } - /* * Write the given reset bit mask into the reset register */ @@ -1923,7 +1922,6 @@ ar5212SetSpurMitigation(struct ath_hal *ah, #undef CHAN_TO_SPUR } - /* * Delta slope coefficient computation. * Required for OFDM operation. diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_xmit.c b/sys/dev/ath/ath_hal/ar5212/ar5212_xmit.c index 6b8730b0d063..cebaa989ef8d 100644 --- a/sys/dev/ath/ath_hal/ar5212/ar5212_xmit.c +++ b/sys/dev/ath/ath_hal/ar5212/ar5212_xmit.c @@ -107,7 +107,6 @@ ar5212GetTxQueueProps(struct ath_hal *ah, int q, HAL_TXQ_INFO *qInfo) struct ath_hal_5212 *ahp = AH5212(ah); HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; - if (q >= pCap->halTotalQueues) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid queue num %u\n", __func__, q); @@ -346,7 +345,7 @@ ar5212ResetTxQueue(struct ath_hal *ah, u_int q) SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_INT) | AR_Q_RDYTIMECFG_ENA); } - + OS_REG_WRITE(ah, AR_DCHNTIME(q), SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) | (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0)); @@ -473,7 +472,7 @@ ar5212ResetTxQueue(struct ath_hal *ah, u_int q) OS_REG_READ(ah, AR_Q0_MISC + 4*q) | AR_Q_MISC_QCU_COMP_EN); } - + /* * Always update the secondary interrupt mask registers - this * could be a new queue getting enabled in a running system or diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212phy.h b/sys/dev/ath/ath_hal/ar5212/ar5212phy.h index a91f2c10ee87..74ccb268fa0d 100644 --- a/sys/dev/ath/ath_hal/ar5212/ar5212phy.h +++ b/sys/dev/ath/ath_hal/ar5212/ar5212phy.h @@ -78,7 +78,6 @@ #define AR_PHY_TSTDAC_CONST_Q_S 9 #define AR_PHY_TSTDAC_CONST_I 0x000001FF - #define AR_PHY_SETTLING 0x9844 #define AR_PHY_SETTLING_AGC 0x0000007F #define AR_PHY_SETTLING_AGC_S 0 diff --git a/sys/dev/ath/ath_hal/ar5212/ar5413.c b/sys/dev/ath/ath_hal/ar5212/ar5413.c index 1d57b9ec7450..1b1817c6c3c4 100644 --- a/sys/dev/ath/ath_hal/ar5212/ar5413.c +++ b/sys/dev/ath/ath_hal/ar5212/ar5413.c @@ -241,7 +241,6 @@ ar5413SetRfRegs(struct ath_hal *ah, } else { ar5212ModifyRfBuffer(priv->Bank6Data, ob5GHz, 3, 247, 0); ar5212ModifyRfBuffer(priv->Bank6Data, db5GHz, 3, 244, 0); - } /* Bank 7 Setup */ @@ -668,7 +667,7 @@ ar5413GetMaxPower(struct ath_hal *ah, const RAW_DATA_PER_CHANNEL_2413 *data) { uint32_t ii; uint16_t Pmax=0,numVpd; - + for (ii=0; ii< MAX_NUM_PDGAINS_PER_CHANNEL; ii++) { /* work forwards cuase lowest pdGain for highest power */ numVpd = data->pDataPerPDGain[ii].numVpd; @@ -705,7 +704,7 @@ ar5413GetChannelMaxMinPower(struct ath_hal *ah, numChannels = pRawDataset->numChannels; data = pRawDataset->pDataPerChannel; - + /* Make sure the channel is in the range of the TP values * (freq piers) */ diff --git a/sys/dev/ath/ath_hal/ar5312/ar5312_eeprom.c b/sys/dev/ath/ath_hal/ar5312/ar5312_eeprom.c index 9b79c36c323f..74a7394665ee 100644 --- a/sys/dev/ath/ath_hal/ar5312/ar5312_eeprom.c +++ b/sys/dev/ath/ath_hal/ar5312/ar5312_eeprom.c @@ -20,7 +20,6 @@ */ #include "opt_ah.h" - #ifdef AH_SUPPORT_AR5312 #include "ah.h" @@ -39,7 +38,7 @@ ar5312EepromRead(struct ath_hal *ah, u_int off, uint16_t *dataIn) int i,offset; const char *eepromAddr = AR5312_RADIOCONFIG(ah); uint8_t *data; - + data = (uint8_t *) dataIn; for (i=0,offset=2*off; i<2; i++,offset++) { data[i] = eepromAddr[offset]; diff --git a/sys/dev/ath/ath_hal/ar5312/ar5312_gpio.c b/sys/dev/ath/ath_hal/ar5312/ar5312_gpio.c index 809904d649b5..84bfd50099c3 100644 --- a/sys/dev/ath/ath_hal/ar5312/ar5312_gpio.c +++ b/sys/dev/ath/ath_hal/ar5312/ar5312_gpio.c @@ -129,5 +129,4 @@ ar5312GpioSetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel) (void) ar5212SetInterrupts(ah, AH5212(ah)->ah_maskReg | HAL_INT_GPIO); } - #endif /* AH_SUPPORT_AR5312 */ diff --git a/sys/dev/ath/ath_hal/ar5312/ar5312_interrupts.c b/sys/dev/ath/ath_hal/ar5312/ar5312_interrupts.c index 43cdda719db6..926fcc2863e1 100644 --- a/sys/dev/ath/ath_hal/ar5312/ar5312_interrupts.c +++ b/sys/dev/ath/ath_hal/ar5312/ar5312_interrupts.c @@ -29,7 +29,6 @@ #include "ar5312/ar5312reg.h" #include "ar5312/ar5312phy.h" - /* * Checks to see if an interrupt is pending on our NIC * diff --git a/sys/dev/ath/ath_hal/ar5312/ar5312_reset.c b/sys/dev/ath/ath_hal/ar5312/ar5312_reset.c index ebc12277a736..2daea4007c98 100644 --- a/sys/dev/ath/ath_hal/ar5312/ar5312_reset.c +++ b/sys/dev/ath/ath_hal/ar5312/ar5312_reset.c @@ -271,7 +271,7 @@ ar5312Reset(struct ath_hal *ah, HAL_OPMODE opmode, /* Set the mute mask to the correct default */ OS_REG_WRITE(ah, AR_SEQ_MASK, 0x0000000F); } - + if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_3) { /* Clear reg to alllow RX_CLEAR line debug */ OS_REG_WRITE(ah, AR_PHY_BLUETOOTH, 0); @@ -827,12 +827,10 @@ ar5312MacReset(struct ath_hal *ah, unsigned int RCMask) OS_REG_READ(ah, (AR5315_RSTIMER_BASE- ((uint32_t) ah->ah_sh) +AR5315_RESET)); - } else #endif { - switch(wlanNum) { case 0: resetBB = AR5312_RC_BB0_CRES | AR5312_RC_WBB0_RES; diff --git a/sys/dev/ath/ath_hal/ar5312/ar5312reg.h b/sys/dev/ath/ath_hal/ar5312/ar5312reg.h index 0e78a52dfe9e..34c8aef51ef1 100644 --- a/sys/dev/ath/ath_hal/ar5312/ar5312reg.h +++ b/sys/dev/ath/ath_hal/ar5312/ar5312reg.h @@ -29,7 +29,6 @@ /* Register base addresses for modules which are not wmac modules */ /* 531X has a fixed memory map */ - #define REG_WRITE(_reg,_val) *((volatile uint32_t *)(_reg)) = (_val); #define REG_READ(_reg) *((volatile uint32_t *)(_reg)) /* @@ -129,7 +128,6 @@ #define AR5312_RC_WMAC1_RES 0x00020000 /* Warm reset to WMAC1 */ #define AR5312_RC_WBB1_RES 0x00040000 /* Warm reset to WBB */ - #define AR_RAD2112_SREV_MAJOR 0x40 /* 2112 Major Rev */ enum AR5312PowerMode { diff --git a/sys/dev/ath/ath_hal/ar5312/ar5315_gpio.c b/sys/dev/ath/ath_hal/ar5312/ar5315_gpio.c index 5fe8eec6c225..41a7bd6cfb38 100644 --- a/sys/dev/ath/ath_hal/ar5312/ar5315_gpio.c +++ b/sys/dev/ath/ath_hal/ar5312/ar5315_gpio.c @@ -128,5 +128,4 @@ ar5315GpioSetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel) (void) ar5212SetInterrupts(ah, AH5212(ah)->ah_maskReg | HAL_INT_GPIO); } - #endif /* AH_SUPPORT_2316 || AH_SUPPORT_2317 */ diff --git a/sys/dev/ath/ath_hal/ar5416/ar2133.c b/sys/dev/ath/ath_hal/ar5416/ar2133.c index c4ac3e9fee05..1cb5432609d7 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar2133.c +++ b/sys/dev/ath/ath_hal/ar5416/ar2133.c @@ -278,7 +278,7 @@ ar2133SetRfRegs(struct ath_hal *ah, const struct ieee80211_channel *chan, /* Setup Bank 6 Write */ ath_hal_ini_bank_setup(priv->Bank6Data, &AH5416(ah)->ah_ini_bank6, modesIndex); - + /* Only the 5 or 2 GHz OB/DB need to be set for a mode */ if (IEEE80211_IS_CHAN_2GHZ(chan)) { HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: 2ghz: OB_2:%d, DB_2:%d\n", @@ -419,6 +419,7 @@ ar2133GetChannelMaxMinPower(struct ath_hal *ah, return(AH_FALSE); } #else + // XXX TODO: actually go implement for 11n chips! *maxPow = *minPow = 0; return AH_FALSE; #endif @@ -472,7 +473,6 @@ ar2133GetNoiseFloor(struct ath_hal *ah, int16_t nfarray[]) "NF calibrated [ctl] [chain 1] is %d\n", nf); nfarray[1] = nf; - nf = MS(OS_REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR_PHY_CH1_EXT_MINCCA_PWR); if (nf & 0x100) nf = 0 - ((nf ^ 0x1ff) + 1); @@ -521,7 +521,7 @@ ar2133RfDetach(struct ath_hal *ah) ath_hal_free(ahp->ah_rfHal); ahp->ah_rfHal = AH_NULL; } - + /* * Allocate memory for analog bank scratch buffers * Scratch Buffer will be reinitialized every reset so no need to zero now diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416.h b/sys/dev/ath/ath_hal/ar5416/ar5416.h index d71d2f922919..3f0787ec17c3 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416.h +++ b/sys/dev/ath/ath_hal/ar5416/ar5416.h @@ -289,7 +289,7 @@ extern HAL_BOOL ar5416SetKeyCacheEntry(struct ath_hal *ah, uint16_t entry, extern uint32_t ar5416GetRxFilter(struct ath_hal *ah); extern void ar5416SetRxFilter(struct ath_hal *ah, uint32_t bits); extern HAL_BOOL ar5416StopDmaReceive(struct ath_hal *ah); -extern void ar5416StartPcuReceive(struct ath_hal *ah); +extern void ar5416StartPcuReceive(struct ath_hal *ah, HAL_BOOL); extern void ar5416StopPcuReceive(struct ath_hal *ah); extern HAL_BOOL ar5416SetupRxDesc(struct ath_hal *, struct ath_desc *, uint32_t size, u_int flags); @@ -306,7 +306,8 @@ extern HAL_BOOL ar5416PhyDisable(struct ath_hal *ah); extern HAL_RFGAIN ar5416GetRfgain(struct ath_hal *ah); extern HAL_BOOL ar5416Disable(struct ath_hal *ah); extern HAL_BOOL ar5416ChipReset(struct ath_hal *ah, - const struct ieee80211_channel *); + const struct ieee80211_channel *, + HAL_RESET_TYPE); extern int ar5416GetRegChainOffset(struct ath_hal *ah, int i); extern HAL_BOOL ar5416SetBoardValues(struct ath_hal *, const struct ieee80211_channel *); diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_ani.c b/sys/dev/ath/ath_hal/ar5416/ar5416_ani.c index a10d884aaaf8..340d67f2e52b 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_ani.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_ani.c @@ -223,7 +223,6 @@ ar5416AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param) return AH_FALSE; } - switch (cmd) { case HAL_ANI_NOISE_IMMUNITY_LEVEL: { u_int level = param; @@ -727,7 +726,7 @@ ar5416AniLowerImmunity(struct ath_hal *ah) struct ath_hal_5212 *ahp = AH5212(ah); struct ar5212AniState *aniState; const struct ar5212AniParams *params; - + HALASSERT(ANI_ENA(ah)); aniState = ahp->ah_curani; diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c b/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c index 8957dedb39dc..369e4b0bb551 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c @@ -376,7 +376,7 @@ ar5416Attach(uint16_t devid, HAL_SOFTC sc, if (ecode != HAL_OK) goto bad; - if (!ar5416ChipReset(ah, AH_NULL)) { /* reset chip */ + if (!ar5416ChipReset(ah, AH_NULL, HAL_RESET_NORMAL)) { /* reset chip */ HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); ecode = HAL_EIO; @@ -721,7 +721,6 @@ ar5416SpurMitigate(struct ath_hal *ah, const struct ieee80211_channel *chan) SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE)); OS_REG_WRITE(ah, AR_PHY_TIMING11, new); - /* * ============================================ * pilot mask 1 [31:0] = +6..-26, no 0 bin @@ -893,7 +892,7 @@ ar5416FillCapabilityInfo(struct ath_hal *ah) struct ath_hal_private *ahpriv = AH_PRIVATE(ah); HAL_CAPABILITIES *pCap = &ahpriv->ah_caps; uint16_t val; - + /* Construct wireless mode from EEPROM */ pCap->halWirelessModes = 0; if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) { diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_beacon.c b/sys/dev/ath/ath_hal/ar5416/ar5416_beacon.c index 7de707b3293c..e1b61bb3ccb4 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_beacon.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_beacon.c @@ -155,7 +155,7 @@ ar5416SetStaBeaconTimers(struct ath_hal *ah, const HAL_BEACON_STATE *bs) uint32_t nextTbtt, nextdtim,beaconintval, dtimperiod; HALASSERT(bs->bs_intval != 0); - + /* NB: no cfp setting since h/w automatically takes care */ OS_REG_WRITE(ah, AR_NEXT_TBTT, TU_TO_USEC(bs->bs_nexttbtt)); diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c b/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c index 106833fe6303..44b436c4f389 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c @@ -196,7 +196,6 @@ ar5416RunInitCals(struct ath_hal *ah, int init_cal_count) } #endif - /* * AGC calibration for the AR5416, AR9130, AR9160, AR9280. */ @@ -623,7 +622,6 @@ ar5416LoadNF(struct ath_hal *ah, const struct ieee80211_channel *chan) h = AH5416(ah)->ah_cal.nfCalHist; HALDEBUG(ah, HAL_DEBUG_NFCAL, "CCA: "); for (i = 0; i < AR5416_NUM_NF_READINGS; i ++) { - /* Don't write to EXT radio CCA registers unless in HT/40 mode */ /* XXX this check should really be cleaner! */ if (i > 2 && !IEEE80211_IS_CHAN_HT40(chan)) @@ -674,7 +672,6 @@ ar5416LoadNF(struct ath_hal *ah, const struct ieee80211_channel *chan) * of next noise floor calibration the baseband does. */ for (i = 0; i < AR5416_NUM_NF_READINGS; i ++) { - /* Don't write to EXT radio CCA registers unless in HT/40 mode */ /* XXX this check should really be cleaner! */ if (i > 2 && !IEEE80211_IS_CHAN_HT40(chan)) @@ -781,7 +778,6 @@ ar5416SanitizeNF(struct ath_hal *ah, int16_t *nf) } } - /* * Read the NF and check it against the noise floor threshold * diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_cal.h b/sys/dev/ath/ath_hal/ar5416/ar5416_cal.h index 5cf1ed0ef108..73a6a87499eb 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_cal.h +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_cal.h @@ -20,7 +20,7 @@ */ #ifndef _ATH_AR5416_CAL_H_ #define _ATH_AR5416_CAL_H_ - + typedef enum { ADC_DC_INIT_CAL = 0x1, ADC_GAIN_CAL = 0x2, diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_gpio.c b/sys/dev/ath/ath_hal/ar5416/ar5416_gpio.c index 1695eda2c5f6..e1d1320d0852 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_gpio.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_gpio.c @@ -131,7 +131,7 @@ ar5416GpioCfgOutput(struct ath_hal *ah, uint32_t gpio, HAL_GPIO_MUX_TYPE type) return AH_TRUE; #undef N } - + /* * Configure GPIO Input lines */ diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_power.c b/sys/dev/ath/ath_hal/ar5416/ar5416_power.c index bcd5fd9807a8..ac1366fedefa 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_power.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_power.c @@ -114,7 +114,7 @@ static void ar5416SetPowerModeNetworkSleep(struct ath_hal *ah, int setChip) { OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); - + if (setChip) OS_REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN); } diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_recv.c b/sys/dev/ath/ath_hal/ar5416/ar5416_recv.c index 372e2795dc20..f58f29a12602 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_recv.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_recv.c @@ -106,14 +106,14 @@ ar5416StopDmaReceive(struct ath_hal *ah) * Start receive at the PCU engine */ void -ar5416StartPcuReceive(struct ath_hal *ah) +ar5416StartPcuReceive(struct ath_hal *ah, HAL_BOOL is_scanning) { struct ath_hal_private *ahp = AH_PRIVATE(ah); HALDEBUG(ah, HAL_DEBUG_RX, "%s: Start PCU Receive \n", __func__); ar5212EnableMibCounters(ah); - /* NB: restore current settings */ - ar5416AniReset(ah, ahp->ah_curchan, ahp->ah_opmode, AH_TRUE); + /* NB: restore current settings if we're not scanning */ + ar5416AniReset(ah, ahp->ah_curchan, ahp->ah_opmode, ! is_scanning); /* * NB: must do after enabling phy errors to avoid rx * frames w/ corrupted descriptor status. @@ -183,8 +183,6 @@ ar5416ProcRxDesc(struct ath_hal *ah, struct ath_desc *ds, rs->rs_datalen = ads->ds_rxstatus1 & AR_DataLen; rs->rs_tstamp = ads->AR_RcvTimestamp; - /* XXX what about KeyCacheMiss? */ - rs->rs_rssi = MS(ads->ds_rxstatus4, AR_RxRSSICombined); rs->rs_rssi_ctl[0] = MS(ads->ds_rxstatus0, AR_RxRSSIAnt00); rs->rs_rssi_ctl[1] = MS(ads->ds_rxstatus0, AR_RxRSSIAnt01); @@ -277,5 +275,8 @@ ar5416ProcRxDesc(struct ath_hal *ah, struct ath_desc *ds, rs->rs_status |= HAL_RXERR_MIC; } + if (ads->ds_rxstatus8 & AR_KeyMiss) + rs->rs_status |= HAL_RXERR_KEYMISS; + return HAL_OK; } diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c b/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c index 6c5cf53c325b..f3d6fcab0d68 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c @@ -170,13 +170,15 @@ ar5416Reset(struct ath_hal *ah, HAL_OPMODE opmode, if (AR_SREV_HOWL(ah) || (AR_SREV_MERLIN(ah) && ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) || + (resetType == HAL_RESET_FORCE_COLD) || + (resetType == HAL_RESET_BBPANIC) || (ah->ah_config.ah_force_full_reset)) tsf = ar5416GetTsf64(ah); /* Mark PHY as inactive; marked active in ar5416InitBB() */ ar5416MarkPhyInactive(ah); - if (!ar5416ChipReset(ah, chan)) { + if (!ar5416ChipReset(ah, chan, resetType)) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); FAIL(HAL_EIO); } @@ -384,7 +386,6 @@ ar5416Reset(struct ath_hal *ah, HAL_OPMODE opmode, AR_PCU_MISC_MODE2_ENABLE_AGGWEP); } - /* * disable seq number generation in hw */ @@ -604,7 +605,7 @@ ar5416InitDMA(struct ath_hal *ah) * Setup receive FIFO threshold to hold off TX activities */ OS_REG_WRITE(ah, AR_RXFIFO_CFG, 0x200); - + /* * reduce the number of usable entries in PCU TXBUF to avoid * wrap around. @@ -643,7 +644,7 @@ ar5416InitBB(struct ath_hal *ah, const struct ieee80211_channel *chan) /* Activate the PHY (includes baseband activate and synthesizer on) */ OS_REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); - + /* * If the AP starts the calibration before the base band timeout * completes we could get rx_clear false triggering. Add an @@ -775,7 +776,8 @@ ar5416SetRfMode(struct ath_hal *ah, const struct ieee80211_channel *chan) * Places the hardware into reset and then pulls it out of reset */ HAL_BOOL -ar5416ChipReset(struct ath_hal *ah, const struct ieee80211_channel *chan) +ar5416ChipReset(struct ath_hal *ah, const struct ieee80211_channel *chan, + HAL_RESET_TYPE resetType) { OS_MARK(ah, AH_MARK_CHIPRESET, chan ? chan->ic_freq : 0); /* @@ -788,6 +790,13 @@ ar5416ChipReset(struct ath_hal *ah, const struct ieee80211_channel *chan) } else if (ah->ah_config.ah_force_full_reset) { if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) return AH_FALSE; + } else if ((resetType == HAL_RESET_FORCE_COLD) || + (resetType == HAL_RESET_BBPANIC)) { + HALDEBUG(ah, HAL_DEBUG_RESET, + "%s: full reset; resetType=%d\n", + __func__, resetType); + if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) + return AH_FALSE; } else { if (!ar5416SetResetReg(ah, HAL_RESET_WARM)) return AH_FALSE; @@ -1039,7 +1048,6 @@ ar5416WriteTxPowerRateRegisters(struct ath_hal *ah, #undef POW_SM } - /************************************************************** * ar5416SetTransmitPower * @@ -1086,7 +1094,7 @@ ar5416SetTransmitPower(struct ath_hal *ah, if (IS_EEP_MINOR_V2(ah)) { AH5416(ah)->ah_ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; } - + if (!ar5416SetPowerPerRateTable(ah, pEepData, chan, &AH5416(ah)->ah_ratesArray[0], cfgCtl, @@ -1515,7 +1523,7 @@ ar5416InitPLL(struct ath_hal *ah, const struct ieee80211_channel *chan) pll |= SM(0xb, AR_RTC_PLL_DIV); } else pll |= SM(0xb, AR_RTC_PLL_DIV); - + OS_REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll); /* TODO: @@ -1647,7 +1655,6 @@ ar5416SetBoardValues(struct ath_hal *ah, const struct ieee80211_channel *chan) if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) ar5416SetDefGainValues(ah, pModal, eep, txRxAttenLocal, regChainOffset, i); - } if (AR_SREV_MERLIN_10_OR_LATER(ah)) { @@ -2794,7 +2801,6 @@ ar5416MarkPhyInactive(struct ath_hal *ah) #define AR5416_HALF_RATE_USEC_44 21 /* ((44 / 2) - 1 ) */ #define AR5416_QUARTER_RATE_USEC_44 10 /* ((44 / 4) - 1 ) */ - /* XXX What should these be for 40/44MHz clocks (and half/quarter) ? */ #define AR5416_RX_NON_FULL_RATE_LATENCY 63 #define AR5416_TX_HALF_RATE_LATENCY 108 @@ -2893,4 +2899,3 @@ ar5416SetIFSTiming(struct ath_hal *ah, const struct ieee80211_channel *chan) OS_REG_RMW_FIELD(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_USEC_DURATION, init_usec); } - diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_spectral.c b/sys/dev/ath/ath_hal/ar5416/ar5416_spectral.c index a5f1251607a8..496abbf4e9b4 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_spectral.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_spectral.c @@ -243,4 +243,3 @@ ar5416RestoreSpectralConfig(struct ath_hal *ah, uint32_t restoreval) } return; } - diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c b/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c index 869d5fbea30a..e3330fe820b8 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c @@ -266,7 +266,6 @@ ar5416GetTxRatePower(struct ath_hal *ah, uint8_t rate, uint8_t tx_chainmask, */ if (AR_SREV_MERLIN_20_OR_LATER(ah) && ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) { - if (rate == 0x19 || rate == 0x1a || rate == 0x1b || rate == (0x19 | 0x04) || rate == (0x1a | 0x04) || rate == (0x1b | 0x04)) { @@ -543,7 +542,7 @@ ar5416ChainTxDesc(struct ath_hal *ah, struct ath_desc *ds, int isaggr = 0; uint32_t last_aggr = 0; - + (void) hdrLen; (void) ah; @@ -613,7 +612,7 @@ ar5416ChainTxDesc(struct ath_hal *ah, struct ath_desc *ds, } ds_txstatus[0] = ds_txstatus[1] = 0; ds_txstatus[9] &= ~AR_TxDone; - + return AH_TRUE; } @@ -631,7 +630,7 @@ ar5416SetupFirstTxDesc(struct ath_hal *ah, struct ath_desc *ds, HALASSERT(isValidTxRate(txRate0)); HALASSERT((flags & RTSCTS) != RTSCTS); /* XXX validate antMode */ - + txPower = (txPower + ahp->ah_txPowerIndexOffset ); if(txPower > 63) txPower=63; @@ -646,7 +645,7 @@ ar5416SetupFirstTxDesc(struct ath_hal *ah, struct ath_desc *ds, | SM(AH5416(ah)->ah_tx_chainmask, AR_ChainSel1) | SM(AH5416(ah)->ah_tx_chainmask, AR_ChainSel2) | SM(AH5416(ah)->ah_tx_chainmask, AR_ChainSel3); - + /* NB: no V1 WAR */ ads->ds_ctl8 = SM(0, AR_AntCtl0); ads->ds_ctl9 = SM(0, AR_AntCtl1) | SM(txPower, AR_XmitPower1); @@ -673,7 +672,7 @@ ar5416SetupFirstTxDesc(struct ath_hal *ah, struct ath_desc *ds, ads->ds_ctl10 = SM(0, AR_AntCtl2) | SM(0, AR_XmitPower2); ads->ds_ctl11 = SM(0, AR_AntCtl3) | SM(0, AR_XmitPower3); } - + return AH_TRUE; #undef RTSCTS } @@ -1114,7 +1113,6 @@ ar5416GetTxCompletionRates(struct ath_hal *ah, const struct ath_desc *ds0, int * return AH_TRUE; } - /* * TX queue management routines - AR5416 and later chipsets */ @@ -1326,7 +1324,7 @@ ar5416ResetTxQueue(struct ath_hal *ah, u_int q) SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_INT) | AR_Q_RDYTIMECFG_ENA); } - + OS_REG_WRITE(ah, AR_DCHNTIME(q), SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) | (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0)); @@ -1464,7 +1462,7 @@ ar5416ResetTxQueue(struct ath_hal *ah, u_int q) OS_REG_READ(ah, AR_Q0_MISC + 4*q) | AR_Q_MISC_QCU_COMP_EN); } - + /* * Always update the secondary interrupt mask registers - this * could be a new queue getting enabled in a running system or diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416desc.h b/sys/dev/ath/ath_hal/ar5416/ar5416desc.h index 0e58bc61eba8..efe56a11965f 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416desc.h +++ b/sys/dev/ath/ath_hal/ar5416/ar5416desc.h @@ -64,7 +64,6 @@ struct ar5416_rx_desc { /* rx desc has 2 control words + 9 status words */ uint32_t status8; }; - struct ar5416_desc { uint32_t ds_link; /* link pointer */ uint32_t ds_data; /* data buffer pointer */ diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416reg.h b/sys/dev/ath/ath_hal/ar5416/ar5416reg.h index ff4f558efa83..85c1d6454952 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416reg.h +++ b/sys/dev/ath/ath_hal/ar5416/ar5416reg.h @@ -669,7 +669,6 @@ #define AR_XSREV_VERSION_OWL_PCI 0x0D #define AR_XSREV_VERSION_OWL_PCIE 0x0C - /* * These are from ath9k/Atheros and assume an AR_SREV version mask * of 0x07, rather than 0x0F which is being used in the FreeBSD HAL. @@ -808,7 +807,6 @@ (AR_SREV_KIWI(_ah) && \ AH_PRIVATE((_ah))->ah_macRev >= AR_XSREV_REVISION_KIWI_13) - /* Not yet implemented chips */ #define AR_SREV_9271(_ah) 0 diff --git a/sys/dev/ath/ath_hal/ar9001/ar9130_attach.c b/sys/dev/ath/ath_hal/ar9001/ar9130_attach.c index 1d78b053c372..70277cc6ca2a 100644 --- a/sys/dev/ath/ath_hal/ar9001/ar9130_attach.c +++ b/sys/dev/ath/ath_hal/ar9001/ar9130_attach.c @@ -173,7 +173,7 @@ ar9130Attach(uint16_t devid, HAL_SOFTC sc, if (ecode != HAL_OK) goto bad; - if (!ar5416ChipReset(ah, AH_NULL)) { /* reset chip */ + if (!ar5416ChipReset(ah, AH_NULL, HAL_RESET_NORMAL)) { /* reset chip */ HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); ecode = HAL_EIO; goto bad; @@ -243,7 +243,6 @@ ar9130Attach(uint16_t devid, HAL_SOFTC sc, AH_PRIVATE(ah)->ah_currentRDext = ath_hal_eepromGet(ah, AR_EEP_REGDMN_1, AH_NULL); - /* * ah_miscMode is populated by ar5416FillCapabilityInfo() * starting from griffin. Set here to make sure that diff --git a/sys/dev/ath/ath_hal/ar9001/ar9160_attach.c b/sys/dev/ath/ath_hal/ar9001/ar9160_attach.c index f74da22d1e7c..b67699358aab 100644 --- a/sys/dev/ath/ath_hal/ar9001/ar9160_attach.c +++ b/sys/dev/ath/ath_hal/ar9001/ar9160_attach.c @@ -200,7 +200,7 @@ ar9160Attach(uint16_t devid, HAL_SOFTC sc, HAL_INI_INIT(&AH5416(ah)->ah_ini_pcieserdes, ar9160PciePhy, 2); ar5416AttachPCIE(ah); - if (!ar5416ChipReset(ah, AH_NULL)) { /* reset chip */ + if (!ar5416ChipReset(ah, AH_NULL, HAL_RESET_NORMAL)) { /* reset chip */ HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); ecode = HAL_EIO; goto bad; diff --git a/sys/dev/ath/ath_hal/ar9002/ar9280_attach.c b/sys/dev/ath/ath_hal/ar9002/ar9280_attach.c index 92479214e5a5..17604e720cef 100644 --- a/sys/dev/ath/ath_hal/ar9002/ar9280_attach.c +++ b/sys/dev/ath/ath_hal/ar9002/ar9280_attach.c @@ -259,7 +259,7 @@ ar9280Attach(uint16_t devid, HAL_SOFTC sc, if (ecode != HAL_OK) goto bad; - if (!ar5416ChipReset(ah, AH_NULL)) { /* reset chip */ + if (!ar5416ChipReset(ah, AH_NULL, HAL_RESET_NORMAL)) { /* reset chip */ HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); ecode = HAL_EIO; goto bad; @@ -434,7 +434,6 @@ ar9280ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore, HAL_BOOL power_off) OS_DELAY(1000); } - /* * Set PCIe workaround bits * diff --git a/sys/dev/ath/ath_hal/ar9002/ar9280_olc.c b/sys/dev/ath/ath_hal/ar9002/ar9280_olc.c index 5eeb420d5d3a..9d75e3b43131 100644 --- a/sys/dev/ath/ath_hal/ar9002/ar9280_olc.c +++ b/sys/dev/ath/ath_hal/ar9002/ar9280_olc.c @@ -171,7 +171,6 @@ ar9280olcTemperatureCompensation(struct ath_hal *ah) } } - static int16_t ar9280ChangeGainBoundarySettings(struct ath_hal *ah, uint16_t *gb, uint16_t numXpdGain, uint16_t pdGainOverlap_t2, int8_t pwr_table_offset, @@ -302,7 +301,6 @@ ar9280SetPowerCalTable(struct ath_hal *ah, struct ar5416eeprom *pEepData, (void) ath_hal_eepromGet(ah, AR_EEP_PWR_TABLE_OFFSET, &pwr_table_offset); - if (IS_EEP_MINOR_V2(ah)) { pdGainOverlap_t2 = pEepData->modalHeader[IEEE80211_IS_CHAN_2GHZ(chan)].pdGainOverlap; } else { diff --git a/sys/dev/ath/ath_hal/ar9002/ar9285.c b/sys/dev/ath/ath_hal/ar9002/ar9285.c index c4362637c173..0044f73a97c5 100644 --- a/sys/dev/ath/ath_hal/ar9002/ar9285.c +++ b/sys/dev/ath/ath_hal/ar9002/ar9285.c @@ -52,7 +52,6 @@ ar9285GetNoiseFloor(struct ath_hal *ah, int16_t nfarray[]) "NF calibrated [ctl] [chain 0] is %d\n", nf); nfarray[0] = nf; - nf = MS(OS_REG_READ(ah, AR_PHY_EXT_CCA), AR9280_PHY_EXT_MINCCA_PWR); if (nf & 0x100) nf = 0 - ((nf ^ 0x1ff) + 1); diff --git a/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c b/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c index 5c140b98dbb1..7fc6b96a25c9 100644 --- a/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c +++ b/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c @@ -196,7 +196,7 @@ ar9285Attach(uint16_t devid, HAL_SOFTC sc, AH5416(ah)->ah_writeIni = ar9285WriteIni; AH5416(ah)->ah_rx_chainmask = AR9285_DEFAULT_RXCHAINMASK; AH5416(ah)->ah_tx_chainmask = AR9285_DEFAULT_TXCHAINMASK; - + ahp->ah_maxTxTrigLev = MAX_TX_FIFO_THRESHOLD >> 1; if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) { @@ -249,7 +249,7 @@ ar9285Attach(uint16_t devid, HAL_SOFTC sc, if (ecode != HAL_OK) goto bad; - if (!ar5416ChipReset(ah, AH_NULL)) { /* reset chip */ + if (!ar5416ChipReset(ah, AH_NULL, HAL_RESET_NORMAL)) { /* reset chip */ HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); ecode = HAL_EIO; diff --git a/sys/dev/ath/ath_hal/ar9002/ar9285_btcoex.c b/sys/dev/ath/ath_hal/ar9002/ar9285_btcoex.c index 3a168ae45ead..0596f19c3b64 100644 --- a/sys/dev/ath/ath_hal/ar9002/ar9285_btcoex.c +++ b/sys/dev/ath/ath_hal/ar9002/ar9285_btcoex.c @@ -150,5 +150,3 @@ ar9285BTCoexSetParameter(struct ath_hal *ah, u_int32_t type, u_int32_t value) break; } } - - diff --git a/sys/dev/ath/ath_hal/ar9002/ar9285_diversity.c b/sys/dev/ath/ath_hal/ar9002/ar9285_diversity.c index 3da59311e5dc..25ae031da2af 100644 --- a/sys/dev/ath/ath_hal/ar9002/ar9285_diversity.c +++ b/sys/dev/ath/ath_hal/ar9002/ar9285_diversity.c @@ -77,7 +77,7 @@ ar9285SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings) /* Store settings */ AH5212(ah)->ah_antControl = settings; AH5212(ah)->ah_diversity = (settings == HAL_ANT_VARIABLE); - + /* XXX don't fiddle if the PHY is in sleep mode or ! chan */ /* Begin setting the relevant registers */ diff --git a/sys/dev/ath/ath_hal/ar9002/ar9285_reset.c b/sys/dev/ath/ath_hal/ar9002/ar9285_reset.c index 961e25e89efa..7b598a05720c 100644 --- a/sys/dev/ath/ath_hal/ar9002/ar9285_reset.c +++ b/sys/dev/ath/ath_hal/ar9002/ar9285_reset.c @@ -107,7 +107,7 @@ ar9285SetTransmitPower(struct ath_hal *ah, if (IS_EEP_MINOR_V2(ah)) { AH5416(ah)->ah_ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; } - + if (!ar9285SetPowerPerRateTable(ah, pEepData, chan, &AH5416(ah)->ah_ratesArray[0],cfgCtl, twiceAntennaReduction, diff --git a/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c b/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c index 8341535bdb97..3cd13f73b772 100644 --- a/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c +++ b/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c @@ -146,7 +146,6 @@ ar9287Attach(uint16_t devid, HAL_SOFTC sc, ah->ah_eepromdata = eepromdata; } - /* XXX override with 9280 specific state */ /* override 5416 methods for our needs */ AH5416(ah)->ah_initPLL = ar9280InitPLL; @@ -242,7 +241,7 @@ ar9287Attach(uint16_t devid, HAL_SOFTC sc, if (ecode != HAL_OK) goto bad; - if (!ar5416ChipReset(ah, AH_NULL)) { /* reset chip */ + if (!ar5416ChipReset(ah, AH_NULL, HAL_RESET_NORMAL)) { /* reset chip */ HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); ecode = HAL_EIO; goto bad; diff --git a/sys/dev/ath/ath_hal/ar9002/ar9287_cal.c b/sys/dev/ath/ath_hal/ar9002/ar9287_cal.c index 09940a187e7d..3bdb4c7f0810 100644 --- a/sys/dev/ath/ath_hal/ar9002/ar9287_cal.c +++ b/sys/dev/ath/ath_hal/ar9002/ar9287_cal.c @@ -41,7 +41,6 @@ #include "ar9002/ar9287_cal.h" - void ar9287PACal(struct ath_hal *ah, HAL_BOOL is_reset) { @@ -55,7 +54,7 @@ HAL_BOOL ar9287InitCalHardware(struct ath_hal *ah, const struct ieee80211_channel *chan) { OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); - + /* Calibrate the AGC */ OS_REG_WRITE(ah, AR_PHY_AGC_CONTROL, OS_REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_CAL); diff --git a/sys/dev/ath/ath_hal/ar9002/ar9287_reset.c b/sys/dev/ath/ath_hal/ar9002/ar9287_reset.c index 372d6c476d12..e4b6eed5bfec 100644 --- a/sys/dev/ath/ath_hal/ar9002/ar9287_reset.c +++ b/sys/dev/ath/ath_hal/ar9002/ar9287_reset.c @@ -113,7 +113,6 @@ ar9287SetPowerCalTable(struct ath_hal *ah, *pTxPowerIndexOffset = 0; } - /* XXX hard-coded values? */ #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 diff --git a/sys/dev/ath/ath_rate/amrr/amrr.c b/sys/dev/ath/ath_rate/amrr/amrr.c index 9a7518373c19..b04b728b2bc5 100644 --- a/sys/dev/ath/ath_rate/amrr/amrr.c +++ b/sys/dev/ath/ath_rate/amrr/amrr.c @@ -64,7 +64,7 @@ __FBSDID("$FreeBSD$"); #include <sys/bus.h> #include <sys/socket.h> - + #include <net/if.h> #include <net/if_media.h> #include <net/if_arp.h> @@ -104,8 +104,9 @@ ath_rate_node_cleanup(struct ath_softc *sc, struct ath_node *an) void ath_rate_findrate(struct ath_softc *sc, struct ath_node *an, - int shortPreamble, size_t frameLen, - u_int8_t *rix, int *try0, u_int8_t *txrate) + int shortPreamble, size_t frameLen, int tid, int is_aggr, + u_int8_t *rix, int *try0, u_int8_t *txrate, int *maxdur, + int *maxpktlen) { struct amrr_node *amn = ATH_NODE_AMRR(an); @@ -115,6 +116,8 @@ ath_rate_findrate(struct ath_softc *sc, struct ath_node *an, *txrate = amn->amn_tx_rate0sp; else *txrate = amn->amn_tx_rate0; + maxdur = -1; + maxpktlen = -1; } /* @@ -125,7 +128,7 @@ ath_rate_findrate(struct ath_softc *sc, struct ath_node *an, */ void ath_rate_getxtxrates(struct ath_softc *sc, struct ath_node *an, - uint8_t rix0, struct ath_rc_series *rc) + uint8_t rix0, int is_aggr, struct ath_rc_series *rc) { struct amrr_node *amn = ATH_NODE_AMRR(an); @@ -142,7 +145,6 @@ ath_rate_getxtxrates(struct ath_softc *sc, struct ath_node *an, rc[3].tries = amn->amn_tx_try3; } - void ath_rate_setupxtxdesc(struct ath_softc *sc, struct ath_node *an, struct ath_desc *ds, int shortPreamble, u_int8_t rix) @@ -159,7 +161,7 @@ ath_rate_setupxtxdesc(struct ath_softc *sc, struct ath_node *an, void ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an, const struct ath_rc_series *rc, const struct ath_tx_status *ts, - int frame_size, int nframes, int nbad) + int frame_size, int rc_framesize, int nframes, int nbad) { struct amrr_node *amn = ATH_NODE_AMRR(an); int sr = ts->ts_shortretry; @@ -196,6 +198,11 @@ ath_rate_newassoc(struct ath_softc *sc, struct ath_node *an, int isnew) ath_rate_ctl_start(sc, &an->an_node); } +void +ath_rate_update_rx_rssi(struct ath_softc *sc, struct ath_node *an, int rssi) +{ +} + static void node_reset(struct amrr_node *amn) { @@ -209,7 +216,6 @@ node_reset(struct amrr_node *amn) amn->amn_success_threshold = ath_rate_min_success_threshold; } - /** * The code below assumes that we are dealing with hardware multi rate retry * I have no idea what will happen if you try to use this module with another @@ -408,7 +414,6 @@ ath_rate_ctl(void *arg, struct ieee80211_node *ni) } else { amn->amn_recovery = 0; } - } if (is_enough (amn) || rix != amn->amn_rix) { /* reset counters. */ diff --git a/sys/dev/ath/ath_rate/onoe/onoe.c b/sys/dev/ath/ath_rate/onoe/onoe.c index 05604c08823c..5229feaeebfd 100644 --- a/sys/dev/ath/ath_rate/onoe/onoe.c +++ b/sys/dev/ath/ath_rate/onoe/onoe.c @@ -52,7 +52,7 @@ __FBSDID("$FreeBSD$"); #include <sys/bus.h> #include <sys/socket.h> - + #include <net/if.h> #include <net/if_media.h> #include <net/if_arp.h> @@ -112,8 +112,9 @@ ath_rate_node_cleanup(struct ath_softc *sc, struct ath_node *an) void ath_rate_findrate(struct ath_softc *sc, struct ath_node *an, - int shortPreamble, size_t frameLen, - u_int8_t *rix, int *try0, u_int8_t *txrate) + int shortPreamble, size_t frameLen, int tid, int is_aggr, + u_int8_t *rix, int *try0, u_int8_t *txrate, int *maxdur, + int *maxpktlen) { struct onoe_node *on = ATH_NODE_ONOE(an); @@ -123,6 +124,8 @@ ath_rate_findrate(struct ath_softc *sc, struct ath_node *an, *txrate = on->on_tx_rate0sp; else *txrate = on->on_tx_rate0; + *maxdur = -1; + *maxpktlen = -1; } /* @@ -133,7 +136,7 @@ ath_rate_findrate(struct ath_softc *sc, struct ath_node *an, */ void ath_rate_getxtxrates(struct ath_softc *sc, struct ath_node *an, - uint8_t rix0, struct ath_rc_series *rc) + uint8_t rix0, int is_aggr, struct ath_rc_series *rc) { struct onoe_node *on = ATH_NODE_ONOE(an); @@ -166,7 +169,7 @@ ath_rate_setupxtxdesc(struct ath_softc *sc, struct ath_node *an, void ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an, const struct ath_rc_series *rc, const struct ath_tx_status *ts, - int frame_size, int nframes, int nbad) + int frame_size, int rc_framesize, int nframes, int nbad) { struct onoe_node *on = ATH_NODE_ONOE(an); @@ -189,6 +192,11 @@ ath_rate_newassoc(struct ath_softc *sc, struct ath_node *an, int isnew) ath_rate_ctl_start(sc, &an->an_node); } +void +ath_rate_update_rx_rssi(struct ath_softc *sc, struct ath_node *an, int rssi) +{ +} + static void ath_rate_update(struct ath_softc *sc, struct ieee80211_node *ni, int rate) { @@ -218,7 +226,7 @@ ath_rate_update(struct ath_softc *sc, struct ieee80211_node *ni, int rate) ni->ni_txrate = ni->ni_rates.rs_rates[rate] & IEEE80211_RATE_VAL; on->on_tx_rix0 = sc->sc_rixmap[ni->ni_txrate]; on->on_tx_rate0 = rt->info[on->on_tx_rix0].rateCode; - + on->on_tx_rate0sp = on->on_tx_rate0 | rt->info[on->on_tx_rix0].shortPreamble; if (sc->sc_mrretry) { diff --git a/sys/dev/ath/ath_rate/sample/sample.c b/sys/dev/ath/ath_rate/sample/sample.c index 45fad2786849..31df8a60c976 100644 --- a/sys/dev/ath/ath_rate/sample/sample.c +++ b/sys/dev/ath/ath_rate/sample/sample.c @@ -62,7 +62,7 @@ __FBSDID("$FreeBSD$"); #include <sys/bus.h> #include <sys/socket.h> - + #include <net/if.h> #include <net/if_var.h> #include <net/if_media.h> @@ -107,6 +107,140 @@ __FBSDID("$FreeBSD$"); * a few different packet sizes independently for each link. */ +/* XXX TODO: move this into ath_hal/net80211 so it can be shared */ + +#define MCS_HT20 0 +#define MCS_HT20_SGI 1 +#define MCS_HT40 2 +#define MCS_HT40_SGI 3 + +/* + * This is currently a copy/paste from the 11n tx code. + * + * It's used to determine the maximum frame length allowed for the + * given rate. For now this ignores SGI/LGI and will assume long-GI. + * This only matters for lower rates that can't fill a full 64k A-MPDU. + * + * (But it's also important because right now rate control doesn't set + * flags like SGI/LGI, STBC, LDPC, TX power, etc.) + * + * When selecting a set of rates the rate control code will iterate + * over the HT20/HT40 max frame length and tell the caller the maximum + * length (@ LGI.) It will also choose a bucket that's the minimum + * of this value and the provided aggregate length. That way the + * rate selection will closely match what the eventual formed aggregate + * will be rather than "not at all". + */ + +static int ath_rate_sample_max_4ms_framelen[4][32] = { + [MCS_HT20] = { + 3212, 6432, 9648, 12864, 19300, 25736, 28952, 32172, + 6424, 12852, 19280, 25708, 38568, 51424, 57852, 64280, + 9628, 19260, 28896, 38528, 57792, 65532, 65532, 65532, + 12828, 25656, 38488, 51320, 65532, 65532, 65532, 65532, + }, + [MCS_HT20_SGI] = { + 3572, 7144, 10720, 14296, 21444, 28596, 32172, 35744, + 7140, 14284, 21428, 28568, 42856, 57144, 64288, 65532, + 10700, 21408, 32112, 42816, 64228, 65532, 65532, 65532, + 14256, 28516, 42780, 57040, 65532, 65532, 65532, 65532, + }, + [MCS_HT40] = { + 6680, 13360, 20044, 26724, 40092, 53456, 60140, 65532, + 13348, 26700, 40052, 53400, 65532, 65532, 65532, 65532, + 20004, 40008, 60016, 65532, 65532, 65532, 65532, 65532, + 26644, 53292, 65532, 65532, 65532, 65532, 65532, 65532, + }, + [MCS_HT40_SGI] = { + 7420, 14844, 22272, 29696, 44544, 59396, 65532, 65532, + 14832, 29668, 44504, 59340, 65532, 65532, 65532, 65532, + 22232, 44464, 65532, 65532, 65532, 65532, 65532, 65532, + 29616, 59232, 65532, 65532, 65532, 65532, 65532, 65532, + } +}; + +/* + * Given the (potentially MRR) transmit schedule, calculate the maximum + * allowed packet size for forming aggregates based on the lowest + * MCS rate in the transmit schedule. + * + * Returns -1 if it's a legacy rate or no MRR. + * + * XXX TODO: this needs to be limited by the RTS/CTS AR5416 8KB bug limit! + * (by checking rts/cts flags and applying sc_rts_aggr_limit) + * + * XXX TODO: apply per-node max-ampdu size and driver ampdu size limits too. + */ +static int +ath_rate_sample_find_min_pktlength(struct ath_softc *sc, + struct ath_node *an, uint8_t rix0, int is_aggr) +{ +#define MCS_IDX(ix) (rt->info[ix].dot11Rate) + const HAL_RATE_TABLE *rt = sc->sc_currates; + struct sample_node *sn = ATH_NODE_SAMPLE(an); + const struct txschedule *sched = &sn->sched[rix0]; + int max_pkt_length = 65530; // ATH_AGGR_MAXSIZE + // Note: this may not be true in all cases; need to check? + int is_ht40 = (an->an_node.ni_chw == 40); + // Note: not great, but good enough.. + int idx = is_ht40 ? MCS_HT40 : MCS_HT20; + + if (rt->info[rix0].phy != IEEE80211_T_HT) { + return -1; + } + + if (! sc->sc_mrretry) { + return -1; + } + + KASSERT(rix0 == sched->r0, ("rix0 (%x) != sched->r0 (%x)!\n", + rix0, sched->r0)); + + /* + * Update based on sched->r{0,1,2,3} if sched->t{0,1,2,3} + * is not zero. + * + * Note: assuming all four PHYs are HT! + * + * XXX TODO: right now I hardcode here and in getxtxrates() that + * rates 2 and 3 in the tx schedule are ignored. This is important + * for forming larger aggregates because right now (a) the tx schedule + * per rate is fixed, and (b) reliable packet transmission at those + * higher rates kinda needs a lower MCS rate in there somewhere. + * However, this means we can only form shorter aggregates. + * If we've negotiated aggregation then we can actually just + * rely on software retransmit rather than having things fall + * back to like MCS0/1 in hardware, and rate control will hopefully + * do the right thing. + * + * Once the whole rate schedule is passed into ath_rate_findrate(), + * the ath_rc_series is populated ,the fixed tx schedule stuff + * is removed AND getxtxrates() is removed then we can remove this + * check as it can just NOT populate t2/t3. It also means + * probing can actually use rix0 for probeing and rix1 for the + * current best rate.. + */ + if (sched->t0 != 0) { + max_pkt_length = MIN(max_pkt_length, + ath_rate_sample_max_4ms_framelen[idx][MCS_IDX(sched->r0)]); + } + if (sched->t1 != 0) { + max_pkt_length = MIN(max_pkt_length, + ath_rate_sample_max_4ms_framelen[idx][MCS_IDX(sched->r1)]); + } + if (sched->t2 != 0 && (! is_aggr)) { + max_pkt_length = MIN(max_pkt_length, + ath_rate_sample_max_4ms_framelen[idx][MCS_IDX(sched->r2)]); + } + if (sched->t3 != 0 && (! is_aggr)) { + max_pkt_length = MIN(max_pkt_length, + ath_rate_sample_max_4ms_framelen[idx][MCS_IDX(sched->r3)]); + } + + return max_pkt_length; +#undef MCS +} + static void ath_rate_ctl_reset(struct ath_softc *, struct ieee80211_node *); static __inline int @@ -125,6 +259,22 @@ size_to_bin(int size) return 2; #endif #if NUM_PACKET_SIZE_BINS > 4 + if (size <= packet_size_bins[3]) + return 3; +#endif +#if NUM_PACKET_SIZE_BINS > 5 + if (size <= packet_size_bins[4]) + return 4; +#endif +#if NUM_PACKET_SIZE_BINS > 6 + if (size <= packet_size_bins[5]) + return 5; +#endif +#if NUM_PACKET_SIZE_BINS > 7 + if (size <= packet_size_bins[6]) + return 6; +#endif +#if NUM_PACKET_SIZE_BINS > 8 #error "add support for more packet sizes" #endif return NUM_PACKET_SIZE_BINS-1; @@ -167,12 +317,12 @@ pick_best_rate(struct ath_node *an, const HAL_RATE_TABLE *rt, int size_bin, int require_acked_before) { struct sample_node *sn = ATH_NODE_SAMPLE(an); - int best_rate_rix, best_rate_tt, best_rate_pct; + int best_rate_rix, best_rate_tt, best_rate_pct; uint64_t mask; int rix, tt, pct; - best_rate_rix = 0; - best_rate_tt = 0; + best_rate_rix = 0; + best_rate_tt = 0; best_rate_pct = 0; for (mask = sn->ratemask, rix = 0; mask != 0; mask >>= 1, rix++) { if ((mask & 1) == 0) /* not a supported rate */ @@ -194,8 +344,7 @@ pick_best_rate(struct ath_node *an, const HAL_RATE_TABLE *rt, if (sn->stats[size_bin][rix].total_packets > 0) { pct = sn->stats[size_bin][rix].ewma_pct; } else { - /* XXX for now, assume 95% ok */ - pct = 95; + pct = -1; /* No percent yet to compare against! */ } /* don't use a bit-rate that has been failing */ @@ -203,18 +352,35 @@ pick_best_rate(struct ath_node *an, const HAL_RATE_TABLE *rt, continue; /* - * For HT, Don't use a bit rate that is much more - * lossy than the best. + * For HT, Don't use a bit rate that is more + * lossy than the best. Give a bit of leeway. * - * XXX this isn't optimal; it's just designed to - * eliminate rates that are going to be obviously - * worse. + * Don't consider best rates that we haven't seen + * packets for yet; let sampling start inflence that. */ if (an->an_node.ni_flags & IEEE80211_NODE_HT) { + if (pct == -1) + continue; +#if 0 + IEEE80211_NOTE(an->an_node.ni_vap, + IEEE80211_MSG_RATECTL, + &an->an_node, + "%s: size %d comparing best rate 0x%x pkts/ewma/tt (%ju/%d/%d) " + "to 0x%x pkts/ewma/tt (%ju/%d/%d)", + __func__, + bin_to_size(size_bin), + rt->info[best_rate_rix].dot11Rate, + sn->stats[size_bin][best_rate_rix].total_packets, + best_rate_pct, + best_rate_tt, + rt->info[rix].dot11Rate, + sn->stats[size_bin][rix].total_packets, + pct, + tt); +#endif if (best_rate_pct > (pct + 50)) continue; } - /* * For non-MCS rates, use the current average txtime for * comparison. @@ -228,19 +394,19 @@ pick_best_rate(struct ath_node *an, const HAL_RATE_TABLE *rt, } /* - * Since 2 stream rates have slightly higher TX times, + * Since 2 and 3 stream rates have slightly higher TX times, * allow a little bit of leeway. This should later * be abstracted out and properly handled. */ if (an->an_node.ni_flags & IEEE80211_NODE_HT) { - if (best_rate_tt == 0 || (tt * 8 <= best_rate_tt * 10)) { + if (best_rate_tt == 0 || ((tt * 10) <= (best_rate_tt * 10))) { best_rate_tt = tt; best_rate_rix = rix; best_rate_pct = pct; } } - } - return (best_rate_tt ? best_rate_rix : -1); + } + return (best_rate_tt ? best_rate_rix : -1); } /* @@ -256,11 +422,11 @@ pick_sample_rate(struct sample_softc *ssc , struct ath_node *an, int current_rix, rix; unsigned current_tt; uint64_t mask; - + current_rix = sn->current_rix[size_bin]; if (current_rix < 0) { /* no successes yet, send at the lowest bit-rate */ - /* XXX should return MCS0 if HT */ + /* XXX TODO should return MCS0 if HT */ return 0; } @@ -316,10 +482,22 @@ pick_sample_rate(struct sample_softc *ssc , struct ath_node *an, /* * For HT, only sample a few rates on either side of the * current rix; there's quite likely a lot of them. + * + * This is limited to testing rate indexes on either side of + * this MCS, but for all spatial streams. + * + * Otherwise we'll (a) never really sample higher MCS + * rates if we're stuck low, and we'll make weird moves + * like sample MCS8 if we're using MCS7. */ if (an->an_node.ni_flags & IEEE80211_NODE_HT) { - if (rix < (current_rix - 3) || - rix > (current_rix + 3)) { + uint8_t current_mcs, rix_mcs; + + current_mcs = MCS(current_rix) & 0x7; + rix_mcs = MCS(rix) & 0x7; + + if (rix_mcs < (current_mcs - 2) || + rix_mcs > (current_mcs + 2)) { mask &= ~((uint64_t) 1<<rix); goto nextrate; } @@ -459,11 +637,11 @@ ath_rate_pick_seed_rate_ht(struct ath_softc *sc, struct ath_node *an, continue; /* - * Pick a medium-speed rate regardless of stream count - * which has not seen any failures. Higher rates may fail; - * we'll try them later. + * Pick a medium-speed rate at 1 spatial stream + * which has not seen any failures. + * Higher rates may fail; we'll try them later. */ - if (((MCS(rix) & 0x7) <= 4) && + if (((MCS(rix)& 0x7f) <= 4) && sn->stats[size_bin][rix].successive_failures == 0) { break; } @@ -479,11 +657,11 @@ ath_rate_pick_seed_rate_ht(struct ath_softc *sc, struct ath_node *an, #undef DOT11RATE } - void ath_rate_findrate(struct ath_softc *sc, struct ath_node *an, - int shortPreamble, size_t frameLen, - u_int8_t *rix0, int *try0, u_int8_t *txrate) + int shortPreamble, size_t frameLen, int tid, + int is_aggr, u_int8_t *rix0, int *try0, + u_int8_t *txrate, int *maxdur, int *maxpktlen) { #define DOT11RATE(ix) (rt->info[ix].dot11Rate & IEEE80211_RATE_VAL) #define MCS(ix) (rt->info[ix].dot11Rate | IEEE80211_RATE_MCS) @@ -492,12 +670,22 @@ ath_rate_findrate(struct ath_softc *sc, struct ath_node *an, struct sample_softc *ssc = ATH_SOFTC_SAMPLE(sc); struct ieee80211com *ic = &sc->sc_ic; const HAL_RATE_TABLE *rt = sc->sc_currates; - const int size_bin = size_to_bin(frameLen); + int size_bin = size_to_bin(frameLen); int rix, mrr, best_rix, change_rates; unsigned average_tx_time; + int max_pkt_len; ath_rate_update_static_rix(sc, &an->an_node); + /* For now don't take TID, is_aggr into account */ + /* Also for now don't calculate a max duration; that'll come later */ + *maxdur = -1; + + /* + * For now just set it to the frame length; we'll optimise it later. + */ + *maxpktlen = frameLen; + if (sn->currates != sc->sc_currates) { device_printf(sc->sc_dev, "%s: currates != sc_currates!\n", __func__); @@ -509,28 +697,62 @@ ath_rate_findrate(struct ath_softc *sc, struct ath_node *an, if (sn->static_rix != -1) { rix = sn->static_rix; *try0 = ATH_TXMAXTRY; + + /* + * Ensure we limit max packet length here too! + */ + max_pkt_len = ath_rate_sample_find_min_pktlength(sc, an, + sn->static_rix, + is_aggr); + if (max_pkt_len > 0) { + *maxpktlen = frameLen = MIN(frameLen, max_pkt_len); + size_bin = size_to_bin(frameLen); + } goto done; } mrr = sc->sc_mrretry; /* XXX check HT protmode too */ + /* XXX turn into a cap; 11n MACs support MRR+RTSCTS */ if (mrr && (ic->ic_flags & IEEE80211_F_USEPROT && !sc->sc_mrrprot)) mrr = 0; best_rix = pick_best_rate(an, rt, size_bin, !mrr); + + /* + * At this point we've chosen the best rix, so now we + * need to potentially update our maximum packet length + * and size_bin if we're doing 11n rates. + */ + max_pkt_len = ath_rate_sample_find_min_pktlength(sc, an, best_rix, + is_aggr); + if (max_pkt_len > 0) { +#if 0 + device_printf(sc->sc_dev, + "Limiting maxpktlen from %d to %d bytes\n", + (int) frameLen, max_pkt_len); +#endif + *maxpktlen = frameLen = MIN(frameLen, max_pkt_len); + size_bin = size_to_bin(frameLen); + } + if (best_rix >= 0) { average_tx_time = sn->stats[size_bin][best_rix].average_tx_time; } else { average_tx_time = 0; } + /* * Limit the time measuring the performance of other tx * rates to sample_rate% of the total transmission time. */ - if (sn->sample_tt[size_bin] < average_tx_time * (sn->packets_since_sample[size_bin]*ssc->sample_rate/100)) { + if (sn->sample_tt[size_bin] < + average_tx_time * + (sn->packets_since_sample[size_bin]*ssc->sample_rate/100)) { rix = pick_sample_rate(ssc, an, rt, size_bin); IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL, - &an->an_node, "att %d sample_tt %d size %u sample rate %d %s current rate %d %s", + &an->an_node, "att %d sample_tt %d size %u " + "sample rate %d %s current rate %d %s", average_tx_time, sn->sample_tt[size_bin], bin_to_size(size_bin), @@ -581,9 +803,9 @@ ath_rate_findrate(struct ath_softc *sc, struct ath_node *an, int cur_rix = sn->current_rix[size_bin]; int cur_att = sn->stats[size_bin][cur_rix].average_tx_time; /* - * If the node is HT, upgrade it if the MCS rate is - * higher and the average tx time is within 20% of - * the current rate. It can fail a little. + * If the node is HT, it if the rate isn't the + * same and the average tx time is within 10% + * of the current rate. It can fail a little. * * This is likely not optimal! */ @@ -591,13 +813,16 @@ ath_rate_findrate(struct ath_softc *sc, struct ath_node *an, printf("cur rix/att %x/%d, best rix/att %x/%d\n", MCS(cur_rix), cur_att, MCS(best_rix), average_tx_time); #endif - if ((MCS(best_rix) > MCS(cur_rix)) && - (average_tx_time * 8) <= (cur_att * 10)) { + if ((best_rix != cur_rix) && + (average_tx_time * 9) <= (cur_att * 10)) { IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL, &an->an_node, - "%s: HT: best_rix 0x%d > cur_rix 0x%x, average_tx_time %d, cur_att %d", - __func__, - MCS(best_rix), MCS(cur_rix), average_tx_time, cur_att); + "%s: HT: size %d best_rix 0x%x > " + " cur_rix 0x%x, average_tx_time %d," + " cur_att %d", + __func__, bin_to_size(size_bin), + MCS(best_rix), MCS(cur_rix), + average_tx_time, cur_att); change_rates = 1; } } @@ -609,15 +834,19 @@ ath_rate_findrate(struct ath_softc *sc, struct ath_node *an, IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL, &an->an_node, -"%s: size %d switch rate %d (%d/%d) -> %d (%d/%d) after %d packets mrr %d", +"%s: size %d switch rate %d %s (%d/%d) EWMA %d -> %d %s (%d/%d) EWMA %d after %d packets mrr %d", __func__, bin_to_size(size_bin), - RATE(sn->current_rix[size_bin]), + dot11rate(rt, sn->current_rix[size_bin]), + dot11rate_label(rt, sn->current_rix[size_bin]), sn->stats[size_bin][sn->current_rix[size_bin]].average_tx_time, sn->stats[size_bin][sn->current_rix[size_bin]].perfect_tx_time, - RATE(best_rix), + sn->stats[size_bin][sn->current_rix[size_bin]].ewma_pct, + dot11rate(rt, best_rix), + dot11rate_label(rt, best_rix), sn->stats[size_bin][best_rix].average_tx_time, sn->stats[size_bin][best_rix].perfect_tx_time, + sn->stats[size_bin][best_rix].ewma_pct, sn->packets_since_switch[size_bin], mrr); } @@ -627,7 +856,9 @@ ath_rate_findrate(struct ath_softc *sc, struct ath_node *an, /* * Set the visible txrate for this node. */ - an->an_node.ni_txrate = (rt->info[best_rix].phy == IEEE80211_T_HT) ? MCS(best_rix) : DOT11RATE(best_rix); + an->an_node.ni_txrate = + (rt->info[best_rix].phy == IEEE80211_T_HT) ? + MCS(best_rix) : DOT11RATE(best_rix); } rix = sn->current_rix[size_bin]; sn->packets_since_switch[size_bin]++; @@ -654,6 +885,7 @@ done: *txrate = rt->info[rix].rateCode | (shortPreamble ? rt->info[rix].shortPreamble : 0); sn->packets_sent[size_bin]++; + #undef DOT11RATE #undef MCS #undef RATE @@ -665,7 +897,7 @@ done: */ void ath_rate_getxtxrates(struct ath_softc *sc, struct ath_node *an, - uint8_t rix0, struct ath_rc_series *rc) + uint8_t rix0, int is_aggr, struct ath_rc_series *rc) { struct sample_node *sn = ATH_NODE_SAMPLE(an); const struct txschedule *sched = &sn->sched[rix0]; @@ -682,8 +914,13 @@ ath_rate_getxtxrates(struct ath_softc *sc, struct ath_node *an, rc[0].tries = sched->t0; rc[1].tries = sched->t1; - rc[2].tries = sched->t2; - rc[3].tries = sched->t3; + + if (is_aggr) { + rc[2].tries = rc[3].tries = 0; + } else { + rc[2].tries = sched->t2; + rc[3].tries = sched->t3; + } } void @@ -711,13 +948,22 @@ ath_rate_setupxtxdesc(struct ath_softc *sc, struct ath_node *an, s3code, sched->t3); /* series 3 */ } +/* + * Update the current statistics. + * + * Note that status is for the FINAL transmit status, not this + * particular attempt. So, check if tries > tries0 and if so + * assume this status failed. + * + * This is important because some failures are due to both + * short AND long retries; if the final issue was a short + * retry failure then we still want to account for the + * bad long retry attempts. + */ static void update_stats(struct ath_softc *sc, struct ath_node *an, int frame_size, int rix0, int tries0, - int rix1, int tries1, - int rix2, int tries2, - int rix3, int tries3, int short_tries, int tries, int status, int nframes, int nbad) { @@ -728,38 +974,39 @@ update_stats(struct ath_softc *sc, struct ath_node *an, #endif const int size_bin = size_to_bin(frame_size); const int size = bin_to_size(size_bin); - int tt, tries_so_far; + int tt; int is_ht40 = (an->an_node.ni_chw == 40); int pct; if (!IS_RATE_DEFINED(sn, rix0)) return; - tt = calc_usecs_unicast_packet(sc, size, rix0, short_tries, - MIN(tries0, tries) - 1, is_ht40); - tries_so_far = tries0; - if (tries1 && tries_so_far < tries) { - if (!IS_RATE_DEFINED(sn, rix1)) - return; - tt += calc_usecs_unicast_packet(sc, size, rix1, short_tries, - MIN(tries1 + tries_so_far, tries) - tries_so_far - 1, is_ht40); - tries_so_far += tries1; + /* + * Treat long retries as us exceeding retries, even + * if the eventual attempt at some other MRR schedule + * succeeded. + */ + if (tries > tries0) { + status = HAL_TXERR_XRETRY; } - if (tries2 && tries_so_far < tries) { - if (!IS_RATE_DEFINED(sn, rix2)) - return; - tt += calc_usecs_unicast_packet(sc, size, rix2, short_tries, - MIN(tries2 + tries_so_far, tries) - tries_so_far - 1, is_ht40); - tries_so_far += tries2; - } + /* + * If status is FAIL then we treat all frames as bad. + * This better accurately tracks EWMA and average TX time + * because even if the eventual transmission succeeded, + * transmission at this rate did not. + */ + if (status != 0) + nbad = nframes; - if (tries3 && tries_so_far < tries) { - if (!IS_RATE_DEFINED(sn, rix3)) - return; - tt += calc_usecs_unicast_packet(sc, size, rix3, short_tries, - MIN(tries3 + tries_so_far, tries) - tries_so_far - 1, is_ht40); - } + /* + * Ignore short tries count as contributing to failure. + * Right now there's no way to know if it's part of any + * given rate attempt, and outside of the RTS/CTS management + * rate, it doesn't /really/ help. + */ + tt = calc_usecs_unicast_packet(sc, size, rix0, + 0 /* short_tries */, MIN(tries0, tries) - 1, is_ht40); if (sn->stats[size_bin][rix0].total_packets < ssc->smoothing_minpackets) { /* just average the first few packets */ @@ -772,34 +1019,9 @@ update_stats(struct ath_softc *sc, struct ath_node *an, ((sn->stats[size_bin][rix0].average_tx_time * ssc->smoothing_rate) + (tt * (100 - ssc->smoothing_rate))) / 100; } - - /* - * XXX Don't mark the higher bit rates as also having failed; as this - * unfortunately stops those rates from being tasted when trying to - * TX. This happens with 11n aggregation. - * - * This is valid for higher CCK rates, higher OFDM rates, and higher - * HT rates within the current number of streams (eg MCS0..7, 8..15, - * etc.) - */ + if (nframes == nbad) { -#if 0 - int y; -#endif sn->stats[size_bin][rix0].successive_failures += nbad; -#if 0 - for (y = size_bin+1; y < NUM_PACKET_SIZE_BINS; y++) { - /* - * Also say larger packets failed since we - * assume if a small packet fails at a - * bit-rate then a larger one will also. - */ - sn->stats[y][rix0].successive_failures += nbad; - sn->stats[y][rix0].last_tx = ticks; - sn->stats[y][rix0].tries += tries; - sn->stats[y][rix0].total_packets += nframes; - } -#endif } else { sn->stats[size_bin][rix0].packets_acked += (nframes - nbad); sn->stats[size_bin][rix0].successive_failures = 0; @@ -828,20 +1050,31 @@ update_stats(struct ath_softc *sc, struct ath_node *an, (pct * (100 - ssc->smoothing_rate))) / 100; } + /* + * Only update the sample time for the initial sample rix. + * We've updated the statistics on each of the other retries + * fine, but we should only update the sample_tt with what + * was actually sampled. + * + * However, to aide in debugging, log all the failures for + * each of the buckets + */ + IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL, + &an->an_node, + "%s: size %d %s %s rate %d %s tries (%d/%d) tt %d " + "avg_tt (%d/%d) nfrm %d nbad %d", + __func__, + size, + status ? "FAIL" : "OK", + rix0 == sn->current_sample_rix[size_bin] ? "sample" : "mrr", + dot11rate(rt, rix0), + dot11rate_label(rt, rix0), + short_tries, tries, tt, + sn->stats[size_bin][rix0].average_tx_time, + sn->stats[size_bin][rix0].perfect_tx_time, + nframes, nbad); if (rix0 == sn->current_sample_rix[size_bin]) { - IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL, - &an->an_node, -"%s: size %d %s sample rate %d %s tries (%d/%d) tt %d avg_tt (%d/%d) nfrm %d nbad %d", - __func__, - size, - status ? "FAIL" : "OK", - dot11rate(rt, rix0), - dot11rate_label(rt, rix0), - short_tries, tries, tt, - sn->stats[size_bin][rix0].average_tx_time, - sn->stats[size_bin][rix0].perfect_tx_time, - nframes, nbad); sn->sample_tt[size_bin] = tt; sn->current_sample_rix[size_bin] = -1; } @@ -859,7 +1092,7 @@ badrate(struct ath_softc *sc, int series, int hwrate, int tries, int status) void ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an, const struct ath_rc_series *rc, const struct ath_tx_status *ts, - int frame_size, int nframes, int nbad) + int frame_size, int rc_framesize, int nframes, int nbad) { struct ieee80211com *ic = &sc->sc_ic; struct sample_node *sn = ATH_NODE_SAMPLE(an); @@ -879,6 +1112,40 @@ ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an, if (frame_size == 0) /* NB: should not happen */ frame_size = 1500; + if (rc_framesize == 0) /* NB: should not happen */ + rc_framesize = 1500; + + /* + * There are still some places where what rate control set as + * a limit but the hardware decided, for some reason, to transmit + * at a smaller size that fell into a different bucket. + * + * The eternal question here is - which size_bin should it go in? + * The one that was requested, or the one that was transmitted? + * + * Here's the problem - if we use the one that was transmitted, + * we may continue to hit corner cases where we make a rate + * selection using a higher bin but only update the smaller bin; + * thus never really "adapting". + * + * If however we update the larger bin, we're not accurately + * representing the channel state at that frame/aggregate size. + * However if we keep hitting the larger request but completing + * a smaller size, we at least updates based on what the + * request was /for/. + * + * I'm going to err on the side of caution and choose the + * latter. + */ + if (size_to_bin(frame_size) != size_to_bin(rc_framesize)) { +#if 0 + device_printf(sc->sc_dev, + "%s: completed but frame size buckets mismatch " + "(completed %d tx'ed %d)\n", + __func__, frame_size, rc_framesize); +#endif + frame_size = rc_framesize; + } if (sn->ratemask == 0) { IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL, @@ -916,9 +1183,6 @@ ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an, short_tries, long_tries, nframes, nbad); update_stats(sc, an, frame_size, final_rix, long_tries, - 0, 0, - 0, 0, - 0, 0, short_tries, long_tries, status, nframes, nbad); @@ -957,20 +1221,15 @@ ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an, } /* - * NB: series > 0 are not penalized for failure - * based on the try counts under the assumption - * that losses are often bursty and since we - * sample higher rates 1 try at a time doing so - * may unfairly penalize them. + * This used to not penalise other tries because loss + * can be bursty, but it's then not accurately keeping + * the avg TX time and EWMA updated. */ if (rc[0].tries) { update_stats(sc, an, frame_size, rc[0].rix, rc[0].tries, - rc[1].rix, rc[1].tries, - rc[2].rix, rc[2].tries, - rc[3].rix, rc[3].tries, short_tries, long_tries, - long_tries > rc[0].tries, + status, nframes, nbad); long_tries -= rc[0].tries; } @@ -978,9 +1237,6 @@ ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an, if (rc[1].tries && finalTSIdx > 0) { update_stats(sc, an, frame_size, rc[1].rix, rc[1].tries, - rc[2].rix, rc[2].tries, - rc[3].rix, rc[3].tries, - 0, 0, short_tries, long_tries, status, nframes, nbad); @@ -990,9 +1246,6 @@ ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an, if (rc[2].tries && finalTSIdx > 1) { update_stats(sc, an, frame_size, rc[2].rix, rc[2].tries, - rc[3].rix, rc[3].tries, - 0, 0, - 0, 0, short_tries, long_tries, status, nframes, nbad); @@ -1002,9 +1255,6 @@ ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an, if (rc[3].tries && finalTSIdx > 2) { update_stats(sc, an, frame_size, rc[3].rix, rc[3].tries, - 0, 0, - 0, 0, - 0, 0, short_tries, long_tries, status, nframes, nbad); @@ -1019,6 +1269,11 @@ ath_rate_newassoc(struct ath_softc *sc, struct ath_node *an, int isnew) ath_rate_ctl_reset(sc, &an->an_node); } +void +ath_rate_update_rx_rssi(struct ath_softc *sc, struct ath_node *an, int rssi) +{ +} + static const struct txschedule *mrr_schedules[IEEE80211_MODE_MAX+2] = { NULL, /* IEEE80211_MODE_AUTO */ series_11a, /* IEEE80211_MODE_11A */ @@ -1375,7 +1630,7 @@ struct ath_ratectrl * ath_rate_attach(struct ath_softc *sc) { struct sample_softc *ssc; - + ssc = malloc(sizeof(struct sample_softc), M_DEVBUF, M_NOWAIT|M_ZERO); if (ssc == NULL) return NULL; @@ -1394,6 +1649,6 @@ void ath_rate_detach(struct ath_ratectrl *arc) { struct sample_softc *ssc = (struct sample_softc *) arc; - + free(ssc, M_DEVBUF); } diff --git a/sys/dev/ath/ath_rate/sample/sample.h b/sys/dev/ath/ath_rate/sample/sample.h index a4f471e1c188..3b6fe9f6fba2 100644 --- a/sys/dev/ath/ath_rate/sample/sample.h +++ b/sys/dev/ath/ath_rate/sample/sample.h @@ -76,12 +76,11 @@ struct txschedule { }; /* - * for now, we track performance for three different packet - * size buckets + * We track performance for eight different packet size buckets. */ -#define NUM_PACKET_SIZE_BINS 2 +#define NUM_PACKET_SIZE_BINS 7 -static const int packet_size_bins[NUM_PACKET_SIZE_BINS] = { 250, 1600 }; +static const int packet_size_bins[NUM_PACKET_SIZE_BINS] = { 250, 1600, 4096, 8192, 16384, 32768, 65536 }; static inline int bin_to_size(int index) @@ -106,7 +105,7 @@ struct sample_node { int current_rix[NUM_PACKET_SIZE_BINS]; int packets_since_switch[NUM_PACKET_SIZE_BINS]; - unsigned ticks_since_switch[NUM_PACKET_SIZE_BINS]; + int ticks_since_switch[NUM_PACKET_SIZE_BINS]; int packets_since_sample[NUM_PACKET_SIZE_BINS]; unsigned sample_tt[NUM_PACKET_SIZE_BINS]; @@ -138,7 +137,7 @@ static unsigned calc_usecs_unicast_packet(struct ath_softc *sc, const HAL_RATE_TABLE *rt = sc->sc_currates; struct ieee80211com *ic = &sc->sc_ic; int rts, cts; - + unsigned t_slot = 20; unsigned t_difs = 50; unsigned t_sifs = 10; @@ -146,7 +145,7 @@ static unsigned calc_usecs_unicast_packet(struct ath_softc *sc, int x = 0; int cw = WIFI_CW_MIN; int cix; - + KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode)); if (rix >= rt->rateCount) { diff --git a/sys/dev/ath/ath_rate/sample/tx_schedules.h b/sys/dev/ath/ath_rate/sample/tx_schedules.h index 02805bec6566..c89ba59f111b 100644 --- a/sys/dev/ath/ath_rate/sample/tx_schedules.h +++ b/sys/dev/ath/ath_rate/sample/tx_schedules.h @@ -172,30 +172,30 @@ static const struct txschedule series_11ng[] = { { 4,NG1( 26), 3,NG1(19.5), 4,NG1( 6.5), 2,NG1(6.5) }, /* 26Mb/s */ { 4,NG1( 39), 3,NG1( 26), 4,NG1(19.5), 2,NG1(6.5) }, /* 39Mb/s */ { 4,NG1( 52), 3,NG1( 39), 4,NG1( 26), 2,NG1(6.5) }, /* 52Mb/s */ - { 4,NG1(58.5), 3,NG1( 52), 4,NG1( 39), 2,NG1( 13) }, /*58.5Mb/s */ - { 4,NG1( 65), 3,NG1(58.5), 4,NG1( 52), 2,NG1( 13) }, /* 65Mb/s */ + { 4,NG1(58.5), 3,NG1( 52), 4,NG1( 39), 2,NG1(6.5) }, /*58.5Mb/s */ + { 4,NG1( 65), 3,NG1(58.5), 4,NG1( 52), 2,NG1(6.5) }, /* 65Mb/s */ /* 2 stream rates */ - { 3,NG2( 13), 3,NG2( 13), 0,NG2( 13), 0,NG2( 13) }, /* 13Mb/s */ - { 4,NG2( 26), 3,NG2( 13), 4,NG2( 13), 0,NG2( 13) }, /* 26Mb/s */ - { 4,NG2( 39), 3,NG2( 26), 4,NG2( 13), 2,NG2( 13) }, /* 39Mb/s */ - { 4,NG2( 52), 3,NG2( 39), 4,NG2( 26), 2,NG2( 13) }, /* 52Mb/s */ - { 4,NG2( 78), 3,NG2( 52), 4,NG2( 39), 2,NG2( 13) }, /* 78Mb/s */ - { 4,NG2( 104), 3,NG2( 78), 4,NG2( 52), 2,NG2( 13) }, /* 104Mb/s */ - { 4,NG2( 117), 3,NG2( 104), 4,NG2( 78), 2,NG2( 26) }, /* 117Mb/s */ - { 4,NG2( 130), 3,NG2( 117), 4,NG2( 104), 2,NG2( 26) }, /* 130Mb/s */ + { 3,NG2( 13), 3,NG1(6.5), 0,NG2( 13), 0,NG2( 13) }, /* 13Mb/s */ + { 4,NG2( 26), 3,NG2( 13), 4,NG1(6.5), 0,NG2( 13) }, /* 26Mb/s */ + { 4,NG2( 39), 3,NG2( 26), 4,NG2( 13), 2,NG1(6.5) }, /* 39Mb/s */ + { 4,NG2( 52), 3,NG2( 39), 4,NG2( 26), 2,NG1(6.5) }, /* 52Mb/s */ + { 4,NG2( 78), 3,NG2( 52), 4,NG2( 39), 2,NG1(6.5) }, /* 78Mb/s */ + { 4,NG2( 104), 3,NG2( 78), 4,NG2( 52), 2,NG1(6.5) }, /* 104Mb/s */ + { 4,NG2( 117), 3,NG2( 104), 4,NG2( 78), 2,NG1(6.5) }, /* 117Mb/s */ + { 4,NG2( 130), 3,NG2( 117), 4,NG2( 104), 2,NG1(6.5) }, /* 130Mb/s */ /* 3 stream rates */ - { 3,NG3(19.5), 3,NG3(19.5), 0,NG3(19.5), 0,NG3(19.5) }, /* 19Mb/s */ - { 3,NG3( 39), 3,NG3(19.5), 0,NG3(19.5), 0,NG3(19.5) }, /* 39Mb/s */ - { 3,NG3(58.5), 3,NG3( 39), 0,NG3(19.5), 0,NG3(19.5) }, /* 58Mb/s */ - { 3,NG3( 78), 3,NG3(58.5), 0,NG3( 39), 0,NG3(19.5) }, /* 78Mb/s */ - { 3,NG3( 117), 3,NG3( 78), 0,NG3(58.5), 0,NG3(19.5) }, /* 117Mb/s */ - { 3,NG3( 156), 3,NG3( 117), 0,NG3( 78), 0,NG3(19.5) }, /* 156Mb/s */ - { 3,NG3(175.5), 3,NG3( 156), 0,NG3( 117), 0,NG3( 39) }, /* 175Mb/s */ - { 3,NG3( 195), 3,NG3( 195), 0,NG3( 156), 0,NG3(58.5) }, /* 195Mb/s */ + { 3,NG3(19.5), 3,NG1(6.5), 0,NG3(19.5), 0,NG3(19.5) }, /* 19Mb/s */ + { 3,NG3( 39), 3,NG3(19.5), 4,NG1(6.5), 0,NG3(19.5) }, /* 39Mb/s */ + { 3,NG3(58.5), 3,NG3( 39), 4,NG1(6.5), 0,NG3(19.5) }, /* 58Mb/s */ + { 3,NG3( 78), 3,NG3(58.5), 4,NG1(6.5), 0,NG3(19.5) }, /* 78Mb/s */ + { 3,NG3( 117), 3,NG3( 78), 4,NG1(6.5), 0,NG3(19.5) }, /* 117Mb/s */ + { 3,NG3( 156), 3,NG3( 117), 4,NG1(6.5), 0,NG3(19.5) }, /* 156Mb/s */ + { 3,NG3(175.5), 3,NG3( 156), 4,NG1(6.5), 0,NG3( 39) }, /* 175Mb/s */ + { 3,NG3( 195), 3,NG3( 195), 4,NG1(6.5), 0,NG3(58.5) }, /* 195Mb/s */ }; #undef G diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index 7e6ab3c614b7..34a9311c834a 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -160,7 +160,6 @@ static int ath_init(struct ath_softc *); static void ath_stop(struct ath_softc *); static int ath_reset_vap(struct ieee80211vap *, u_long); static int ath_transmit(struct ieee80211com *, struct mbuf *); -static int ath_media_change(struct ifnet *); static void ath_watchdog(void *); static void ath_parent(struct ieee80211com *); static void ath_fatal_proc(void *, int); @@ -1221,7 +1220,6 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) IEEE80211_HTC_TXLDPC; } - device_printf(sc->sc_dev, "[HT] %d RX streams; %d TX streams\n", rxs, txs); } @@ -1767,8 +1765,8 @@ ath_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, ATH_UNLOCK(sc); /* complete setup */ - ieee80211_vap_attach(vap, ath_media_change, ieee80211_media_status, - mac); + ieee80211_vap_attach(vap, ieee80211_media_change, + ieee80211_media_status, mac); return vap; bad2: reclaim_address(sc, mac); @@ -1801,6 +1799,7 @@ ath_vap_delete(struct ieee80211vap *vap) ath_hal_intrset(ah, 0); /* disable interrupts */ /* XXX Do all frames from all vaps/nodes need draining here? */ ath_stoprecv(sc, 1); /* stop recv side */ + ath_rx_flush(sc); ath_draintxq(sc, ATH_RESET_DEFAULT); /* stop hw xmit side */ } @@ -2379,7 +2378,7 @@ ath_fatal_proc(void *arg, int pending) "0x%08x 0x%08x 0x%08x, 0x%08x 0x%08x 0x%08x\n", state[0], state[1] , state[2], state[3], state[4], state[5]); } - ath_reset(sc, ATH_RESET_NOLOSS); + ath_reset(sc, ATH_RESET_NOLOSS, HAL_RESET_FORCE_COLD); } static void @@ -2490,11 +2489,11 @@ ath_bmiss_proc(void *arg, int pending) * to clear. */ if (ath_hal_gethangstate(sc->sc_ah, 0xff, &hangs) && hangs != 0) { - ath_reset(sc, ATH_RESET_NOLOSS); + ath_reset(sc, ATH_RESET_NOLOSS, HAL_RESET_BBPANIC); device_printf(sc->sc_dev, "bb hang detected (0x%x), resetting\n", hangs); } else { - ath_reset(sc, ATH_RESET_NOLOSS); + ath_reset(sc, ATH_RESET_NOLOSS, HAL_RESET_FORCE_COLD); ieee80211_beacon_miss(&sc->sc_ic); } @@ -2893,7 +2892,8 @@ ath_reset_grablock(struct ath_softc *sc, int dowait) * to reset or reload hardware state. */ int -ath_reset(struct ath_softc *sc, ATH_RESET_TYPE reset_type) +ath_reset(struct ath_softc *sc, ATH_RESET_TYPE reset_type, + HAL_RESET_TYPE ah_reset_type) { struct ieee80211com *ic = &sc->sc_ic; struct ath_hal *ah = sc->sc_ah; @@ -2961,7 +2961,7 @@ ath_reset(struct ath_softc *sc, ATH_RESET_TYPE reset_type) ath_hal_setchainmasks(sc->sc_ah, sc->sc_cur_txchainmask, sc->sc_cur_rxchainmask); if (!ath_hal_reset(ah, sc->sc_opmode, ic->ic_curchan, AH_TRUE, - HAL_RESET_NORMAL, &status)) + ah_reset_type, &status)) device_printf(sc->sc_dev, "%s: unable to reset hardware; hal status %u\n", __func__, status); @@ -3097,7 +3097,7 @@ ath_reset_vap(struct ieee80211vap *vap, u_long cmd) return 0; } /* XXX? Full or NOLOSS? */ - return ath_reset(sc, ATH_RESET_FULL); + return ath_reset(sc, ATH_RESET_FULL, HAL_RESET_NORMAL); } struct ath_buf * @@ -3538,16 +3538,8 @@ finish: ATH_UNLOCK(sc); ATH_KTR(sc, ATH_KTR_TX, 0, "ath_transmit: finished"); - - return (retval); -} -static int -ath_media_change(struct ifnet *ifp) -{ - int error = ieee80211_media_change(ifp); - /* NB: only the fixed rate can change and that doesn't need a reset */ - return (error == ENETRESET ? 0 : error); + return (retval); } /* @@ -3591,6 +3583,25 @@ ath_update_promisc(struct ieee80211com *ic) DPRINTF(sc, ATH_DEBUG_MODE, "%s: RX filter 0x%x\n", __func__, rfilt); } +static u_int +ath_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt) +{ + uint32_t val, *mfilt = arg; + char *dl; + uint8_t pos; + + /* calculate XOR of eight 6bit values */ + dl = LLADDR(sdl); + val = le32dec(dl + 0); + pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; + val = le32dec(dl + 3); + pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; + pos &= 0x3f; + mfilt[pos / 32] |= (1 << (pos % 32)); + + return (1); +} + /* * Driver-internal mcast update call. * @@ -3605,35 +3616,13 @@ ath_update_mcast_hw(struct ath_softc *sc) /* calculate and install multicast filter */ if (ic->ic_allmulti == 0) { struct ieee80211vap *vap; - struct ifnet *ifp; - struct ifmultiaddr *ifma; /* * Merge multicast addresses to form the hardware filter. */ mfilt[0] = mfilt[1] = 0; - TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { - ifp = vap->iv_ifp; - if_maddr_rlock(ifp); - CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { - caddr_t dl; - uint32_t val; - uint8_t pos; - - /* calculate XOR of eight 6bit values */ - dl = LLADDR((struct sockaddr_dl *) - ifma->ifma_addr); - val = le32dec(dl + 0); - pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ - val; - val = le32dec(dl + 3); - pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ - val; - pos &= 0x3f; - mfilt[pos / 32] |= (1 << (pos % 32)); - } - if_maddr_runlock(ifp); - } + TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) + if_foreach_llmaddr(vap->iv_ifp, ath_hash_maddr, &mfilt); } else mfilt[0] = mfilt[1] = ~0; @@ -3780,7 +3769,7 @@ ath_reset_proc(void *arg, int pending) #if 0 device_printf(sc->sc_dev, "%s: resetting\n", __func__); #endif - ath_reset(sc, ATH_RESET_NOLOSS); + ath_reset(sc, ATH_RESET_NOLOSS, HAL_RESET_FORCE_COLD); } /* @@ -3807,7 +3796,7 @@ ath_bstuck_proc(void *arg, int pending) * This assumes that there's no simultaneous channel mode change * occurring. */ - ath_reset(sc, ATH_RESET_NOLOSS); + ath_reset(sc, ATH_RESET_NOLOSS, HAL_RESET_FORCE_COLD); } static int @@ -3882,6 +3871,10 @@ ath_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN]) /* XXX setup ath_tid */ ath_tx_tid_init(sc, an); + an->an_node_stats.ns_avgbrssi = ATH_RSSI_DUMMY_MARKER; + an->an_node_stats.ns_avgrssi = ATH_RSSI_DUMMY_MARKER; + an->an_node_stats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER; + DPRINTF(sc, ATH_DEBUG_NODE, "%s: %6D: an %p\n", __func__, mac, ":", an); return &an->an_node; } @@ -4300,7 +4293,7 @@ ath_tx_default_comp(struct ath_softc *sc, struct ath_buf *bf, int fail) void ath_tx_update_ratectrl(struct ath_softc *sc, struct ieee80211_node *ni, struct ath_rc_series *rc, struct ath_tx_status *ts, int frmlen, - int nframes, int nbad) + int rc_framelen, int nframes, int nbad) { struct ath_node *an; @@ -4311,9 +4304,16 @@ ath_tx_update_ratectrl(struct ath_softc *sc, struct ieee80211_node *ni, an = ATH_NODE(ni); ATH_NODE_UNLOCK_ASSERT(an); + /* + * XXX TODO: teach the rate control about TXERR_FILT and + * see about handling it (eg see how many attempts were + * made before it got filtered and account for that.) + */ + if ((ts->ts_status & HAL_TXERR_FILT) == 0) { ATH_NODE_LOCK(an); - ath_rate_tx_complete(sc, an, rc, ts, frmlen, nframes, nbad); + ath_rate_tx_complete(sc, an, rc, ts, frmlen, rc_framelen, + nframes, nbad); ATH_NODE_UNLOCK(an); } } @@ -4354,10 +4354,15 @@ ath_tx_process_buf_completion(struct ath_softc *sc, struct ath_txq *txq, /* * XXX assume this isn't an aggregate * frame. + * + * XXX TODO: also do this for filtered frames? + * Once rate control knows about them? */ ath_tx_update_ratectrl(sc, ni, bf->bf_state.bfs_rc, ts, - bf->bf_state.bfs_pktlen, 1, + bf->bf_state.bfs_pktlen, + bf->bf_state.bfs_pktlen, + 1, (ts->ts_status == 0 ? 0 : 1)); } ath_tx_default_comp(sc, bf, 0); @@ -4365,8 +4370,6 @@ ath_tx_process_buf_completion(struct ath_softc *sc, struct ath_txq *txq, bf->bf_comp(sc, bf, 0); } - - /* * Process completed xmit descriptors from the specified queue. * Kick the packet scheduler if needed. This can occur from this @@ -4493,6 +4496,8 @@ ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq, int dosched) sc->sc_stats.ast_tx_rssi = ts->ts_rssi; ATH_RSSI_LPF(sc->sc_halstats.ns_avgtxrssi, ts->ts_rssi); + ATH_RSSI_LPF(ATH_NODE(ni)->an_node_stats.ns_avgtxrssi, + ts->ts_rssi); } ATH_TXQ_UNLOCK(txq); @@ -5435,6 +5440,20 @@ ath_calibrate(void *arg) __func__, sc->sc_curchan->ic_freq); sc->sc_stats.ast_per_calfail++; } + /* + * XXX TODO: get the NF calibration results from the HAL. + * If we failed NF cal then schedule a hard reset to potentially + * un-freeze the PHY. + * + * Note we have to be careful here to not get stuck in an + * infinite NIC restart. Ideally we'd not restart if we + * failed the first NF cal - that /can/ fail sometimes in + * a noisy environment. + * + * Instead, we should likely temporarily shorten the longCal + * period to happen pretty quickly and if a subsequent one + * fails, do a full reset. + */ if (shortCal) sc->sc_lastshortcal = ticks; } @@ -6072,7 +6091,6 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) taskqueue_unblock(sc->sc_tq); } else if (nstate == IEEE80211_S_INIT) { - /* Quiet time handling - ensure we resync */ memset(&avp->quiet_ie, 0, sizeof(avp->quiet_ie)); @@ -6090,6 +6108,17 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) taskqueue_block(sc->sc_tq); sc->sc_beacons = 0; } + + /* + * For at least STA mode we likely should clear the ANI + * and NF calibration state and allow the NIC/HAL to figure + * out optimal parameters at runtime. Otherwise if we + * disassociate due to interference / deafness it may persist + * when we reconnect. + * + * Note: may need to do this for other states too, not just + * _S_INIT. + */ #ifdef IEEE80211_SUPPORT_TDMA ath_hal_setcca(ah, AH_TRUE); #endif @@ -6119,9 +6148,39 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) } ATH_UNLOCK(sc); } + + /* + * Note - the ANI/calibration timer isn't re-enabled during + * network sleep for now. One unfortunate side-effect is that + * the PHY/airtime statistics aren't gathered on the channel + * but I haven't yet tested to see if reading those registers + * CAN occur during network sleep. + * + * This should be revisited in a future commit, even if it's + * just to split out the airtime polling from ANI/calibration. + */ } else if (nstate == IEEE80211_S_SCAN) { /* Quiet time handling - ensure we resync */ memset(&avp->quiet_ie, 0, sizeof(avp->quiet_ie)); + + /* + * If we're in scan mode then startpcureceive() is + * hopefully being called with "reset ANI" for this channel; + * but once we attempt to reassociate we program in the previous + * ANI values and.. not do any calibration until we're running. + * This may mean we stay deaf unless we can associate successfully. + * + * So do kick off the cal timer to get NF/ANI going. + */ + ATH_LOCK(sc); + if (ath_longcalinterval != 0) { + /* start periodic recalibration timer */ + callout_reset(&sc->sc_cal_ch, 1, ath_calibrate, sc); + } else { + DPRINTF(sc, ATH_DEBUG_CALIBRATE, + "%s: calibration disabled\n", __func__); + } + ATH_UNLOCK(sc); } bad: ieee80211_free_node(ni); diff --git a/sys/dev/ath/if_ath_ahb.c b/sys/dev/ath/if_ath_ahb.c index 3c4c05e57846..ea329589f1ab 100644 --- a/sys/dev/ath/if_ath_ahb.c +++ b/sys/dev/ath/if_ath_ahb.c @@ -54,7 +54,7 @@ __FBSDID("$FreeBSD$"); #include <sys/rman.h> #include <sys/socket.h> - + #include <net/if.h> #include <net/if_media.h> #include <net/if_arp.h> @@ -336,7 +336,6 @@ static device_method_t ath_ahb_methods[] = { DEVMETHOD(device_shutdown, ath_ahb_shutdown), DEVMETHOD(device_suspend, ath_ahb_suspend), DEVMETHOD(device_resume, ath_ahb_resume), - { 0,0 } }; static driver_t ath_ahb_driver = { diff --git a/sys/dev/ath/if_ath_beacon.c b/sys/dev/ath/if_ath_beacon.c index 509e24caf601..ac1244c5f8e7 100644 --- a/sys/dev/ath/if_ath_beacon.c +++ b/sys/dev/ath/if_ath_beacon.c @@ -777,7 +777,6 @@ ath_beacon_generate(struct ath_softc *sc, struct ieee80211vap *vap) * insure cab frames are triggered by this beacon. */ if (vap->iv_bcn_off.bo_tim[4] & 1) { - /* NB: only at DTIM */ ATH_TXQ_LOCK(&avp->av_mcastq); if (nmcastq) { diff --git a/sys/dev/ath/if_ath_beacon.h b/sys/dev/ath/if_ath_beacon.h index e4a9e7918af2..cda145ba32e2 100644 --- a/sys/dev/ath/if_ath_beacon.h +++ b/sys/dev/ath/if_ath_beacon.h @@ -53,4 +53,3 @@ extern void ath_beacon_proc(void *arg, int pending); extern void ath_beacon_miss(struct ath_softc *sc); #endif - diff --git a/sys/dev/ath/if_ath_btcoex.c b/sys/dev/ath/if_ath_btcoex.c index 881a2c8acf95..1f0400b696f5 100644 --- a/sys/dev/ath/if_ath_btcoex.c +++ b/sys/dev/ath/if_ath_btcoex.c @@ -55,7 +55,7 @@ __FBSDID("$FreeBSD$"); #include <sys/bus.h> #include <sys/socket.h> - + #include <net/if.h> #include <net/if_var.h> #include <net/if_media.h> @@ -481,4 +481,3 @@ bad: free(outdata, M_TEMP); return (error); } - diff --git a/sys/dev/ath/if_ath_dfs.c b/sys/dev/ath/if_ath_dfs.c index 2078f154981c..8f1bc5b015ae 100644 --- a/sys/dev/ath/if_ath_dfs.c +++ b/sys/dev/ath/if_ath_dfs.c @@ -63,7 +63,6 @@ ath_dfs_modevent(module_t mod __unused, int type, void *data __unused) default: error = EOPNOTSUPP; break; - } return (error); } diff --git a/sys/dev/ath/if_ath_drv.c b/sys/dev/ath/if_ath_drv.c index cc7b9162fb2c..c4384cb73916 100644 --- a/sys/dev/ath/if_ath_drv.c +++ b/sys/dev/ath/if_ath_drv.c @@ -68,7 +68,6 @@ ath_modevent(module_t mod __unused, int type, void *data __unused) default: error = EOPNOTSUPP; break; - } return (error); } diff --git a/sys/dev/ath/if_ath_ioctl.c b/sys/dev/ath/if_ath_ioctl.c index 9601ba3456bb..f58742d6e5fb 100644 --- a/sys/dev/ath/if_ath_ioctl.c +++ b/sys/dev/ath/if_ath_ioctl.c @@ -204,7 +204,6 @@ ath_ioctl_diag(struct ath_softc *sc, struct ath_diag *ad) } } - ATH_LOCK(sc); if (id != HAL_DIAG_REGS) ath_power_set_power_state(sc, HAL_PM_AWAKE); @@ -306,4 +305,3 @@ ath_ioctl(struct ieee80211com *ic, u_long cmd, void *data) return (ENOTTY); } } - diff --git a/sys/dev/ath/if_ath_led.c b/sys/dev/ath/if_ath_led.c index 3cd519a8d198..8b4ac821f2be 100644 --- a/sys/dev/ath/if_ath_led.c +++ b/sys/dev/ath/if_ath_led.c @@ -112,7 +112,6 @@ __FBSDID("$FreeBSD$"); * XXX TODO: move the LED sysctls here. */ - /* * Configure the hardware for software and LED blinking. * The user may choose to configure part of each, depending upon the diff --git a/sys/dev/ath/if_ath_lna_div.c b/sys/dev/ath/if_ath_lna_div.c index 7b970285b9b7..c89a6b107749 100644 --- a/sys/dev/ath/if_ath_lna_div.c +++ b/sys/dev/ath/if_ath_lna_div.c @@ -55,7 +55,7 @@ __FBSDID("$FreeBSD$"); #include <sys/bus.h> #include <sys/socket.h> - + #include <net/if.h> #include <net/if_var.h> #include <net/if_media.h> @@ -1018,4 +1018,3 @@ div_comb_done: antcomb->main_recv_cnt = 0; antcomb->alt_recv_cnt = 0; } - diff --git a/sys/dev/ath/if_ath_misc.h b/sys/dev/ath/if_ath_misc.h index f34bbbfaeebc..b108c29bab4b 100644 --- a/sys/dev/ath/if_ath_misc.h +++ b/sys/dev/ath/if_ath_misc.h @@ -58,12 +58,14 @@ extern void ath_freebuf(struct ath_softc *sc, struct ath_buf *bf); extern void ath_returnbuf_head(struct ath_softc *sc, struct ath_buf *bf); extern void ath_returnbuf_tail(struct ath_softc *sc, struct ath_buf *bf); -extern int ath_reset(struct ath_softc *, ATH_RESET_TYPE); +extern int ath_reset(struct ath_softc *, ATH_RESET_TYPE, + HAL_RESET_TYPE ah_reset_type); extern void ath_tx_default_comp(struct ath_softc *sc, struct ath_buf *bf, int fail); extern void ath_tx_update_ratectrl(struct ath_softc *sc, struct ieee80211_node *ni, struct ath_rc_series *rc, - struct ath_tx_status *ts, int frmlen, int nframes, int nbad); + struct ath_tx_status *ts, int frmlen, int rc_framelen, + int nframes, int nbad); extern int ath_hal_gethangstate(struct ath_hal *ah, uint32_t mask, uint32_t *hangs); diff --git a/sys/dev/ath/if_ath_pci.c b/sys/dev/ath/if_ath_pci.c index 0b35e6670015..d3b130e091dc 100644 --- a/sys/dev/ath/if_ath_pci.c +++ b/sys/dev/ath/if_ath_pci.c @@ -52,7 +52,7 @@ __FBSDID("$FreeBSD$"); #include <sys/rman.h> #include <sys/socket.h> - + #include <net/if.h> #include <net/if_media.h> #include <net/if_arp.h> @@ -383,7 +383,6 @@ static device_method_t ath_pci_methods[] = { DEVMETHOD(device_shutdown, ath_pci_shutdown), DEVMETHOD(device_suspend, ath_pci_suspend), DEVMETHOD(device_resume, ath_pci_resume), - { 0,0 } }; static driver_t ath_pci_driver = { diff --git a/sys/dev/ath/if_ath_pci_devlist.h b/sys/dev/ath/if_ath_pci_devlist.h index dc49ab578d65..ec5bb1405553 100644 --- a/sys/dev/ath/if_ath_pci_devlist.h +++ b/sys/dev/ath/if_ath_pci_devlist.h @@ -663,7 +663,5 @@ static const struct pci_device_table ath_pci_id_table[] = { /* PCI-E AR9565 (WB335) */ { PCI_VDEVICE(PCI_VENDOR_ID_ATHEROS, 0x0036), .driver_data = ATH_PCI_BT_ANT_DIV }, - { 0 } }; - diff --git a/sys/dev/ath/if_ath_rate.c b/sys/dev/ath/if_ath_rate.c index 8eb7a518c2a4..ff2e0e1336f1 100644 --- a/sys/dev/ath/if_ath_rate.c +++ b/sys/dev/ath/if_ath_rate.c @@ -63,7 +63,6 @@ ath_rate_modevent(module_t mod __unused, int type, void *data __unused) default: error = EOPNOTSUPP; break; - } return (error); } diff --git a/sys/dev/ath/if_ath_rx.c b/sys/dev/ath/if_ath_rx.c index b06a3f797dde..141547dac424 100644 --- a/sys/dev/ath/if_ath_rx.c +++ b/sys/dev/ath/if_ath_rx.c @@ -363,6 +363,11 @@ ath_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m, ATH_VAP(vap)->av_recv_mgmt(ni, m, subtype, rxs, rssi, nf); switch (subtype) { case IEEE80211_FC0_SUBTYPE_BEACON: + /* + * Always update the per-node beacon RSSI if we're hearing + * beacons from that node. + */ + ATH_RSSI_LPF(ATH_NODE(ni)->an_node_stats.ns_avgbrssi, rssi); /* * Only do the following processing if it's for @@ -374,12 +379,12 @@ ath_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m, * trying to sync / merge to BSSes that aren't * actually us. */ - if (IEEE80211_ADDR_EQ(ni->ni_bssid, vap->iv_bss->ni_bssid)) { + if ((vap->iv_opmode != IEEE80211_M_HOSTAP) && + IEEE80211_ADDR_EQ(ni->ni_bssid, vap->iv_bss->ni_bssid)) { /* update rssi statistics for use by the hal */ /* XXX unlocked check against vap->iv_bss? */ ATH_RSSI_LPF(sc->sc_halstats.ns_avgbrssi, rssi); - tsf_beacon = ((uint64_t) le32dec(ni->ni_tstamp.data + 4)) << 32; tsf_beacon |= le32dec(ni->ni_tstamp.data); @@ -422,8 +427,9 @@ ath_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m, tsf_remainder = (tsf_beacon - tsf_beacon_old) % tsf_intval; } - DPRINTF(sc, ATH_DEBUG_BEACON, "%s: old_tsf=%llu (%u), new_tsf=%llu (%u), target_tsf=%llu (%u), delta=%lld, bmiss=%d, remainder=%d\n", + DPRINTF(sc, ATH_DEBUG_BEACON, "%s: %s: old_tsf=%llu (%u), new_tsf=%llu (%u), target_tsf=%llu (%u), delta=%lld, bmiss=%d, remainder=%d\n", __func__, + ieee80211_get_vap_ifname(vap), (unsigned long long) tsf_beacon_old, (unsigned int) (tsf_beacon_old >> 10), (unsigned long long) tsf_beacon, @@ -434,17 +440,28 @@ ath_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m, tsf_delta_bmiss, tsf_remainder); - DPRINTF(sc, ATH_DEBUG_BEACON, "%s: tsf=%llu (%u), nexttbtt=%llu (%u), delta=%d\n", + DPRINTF(sc, ATH_DEBUG_BEACON, "%s: %s: ni=%6D bssid=%6D tsf=%llu (%u), nexttbtt=%llu (%u), delta=%d\n", __func__, + ieee80211_get_vap_ifname(vap), + ni->ni_bssid, ":", + vap->iv_bss->ni_bssid, ":", (unsigned long long) tsf_beacon, (unsigned int) (tsf_beacon >> 10), (unsigned long long) nexttbtt, (unsigned int) (nexttbtt >> 10), (int32_t) tsf_beacon - (int32_t) nexttbtt + tsf_intval); - /* We only do syncbeacon on STA VAPs; not on IBSS */ + /* + * We only do syncbeacon on STA VAPs; not on IBSS; + * but don't do it with swbmiss enabled or we + * may end up overwriting AP mode beacon config. + * + * The driver (and net80211) should be smarter about + * this.. + */ if (vap->iv_opmode == IEEE80211_M_STA && sc->sc_syncbeacon && + (!sc->sc_swbmiss) && ni == vap->iv_bss && (vap->iv_state == IEEE80211_S_RUN || vap->iv_state == IEEE80211_S_SLEEP)) { DPRINTF(sc, ATH_DEBUG_BEACON, @@ -946,6 +963,21 @@ rx_accept: m->m_flags |= M_AMPDU; /* + * Inform rate control about the received RSSI. + * It can then use this information to potentially drastically + * alter the available rate based on the RSSI estimate. + * + * This is super important when associating to a far away station; + * you don't want to waste time trying higher rates at some low + * packet exchange rate (like during DHCP) just to establish + * that higher MCS rates aren't available. + */ + ATH_RSSI_LPF(ATH_NODE(ni)->an_node_stats.ns_avgrssi, + rs->rs_rssi); + ath_rate_update_rx_rssi(sc, ATH_NODE(ni), + ATH_RSSI(ATH_NODE(ni)->an_node_stats.ns_avgrssi)); + + /* * Sending station is known, dispatch directly. */ (void) ieee80211_add_rx_params(m, &rxs); @@ -973,7 +1005,7 @@ rx_accept: */ /* - * Track rx rssi and do any rx antenna management. + * Track legacy station RX rssi and do any rx antenna management. */ ATH_RSSI_LPF(sc->sc_halstats.ns_avgrssi, rs->rs_rssi); if (sc->sc_diversity) { @@ -1228,7 +1260,7 @@ rx_proc_next: ath_hal_putrxbuf(ah, bf->bf_daddr, HAL_RX_QUEUE_HP); ath_hal_rxena(ah); /* enable recv descriptors */ ath_mode_init(sc); /* set filters, etc. */ - ath_hal_startpcurecv(ah); /* re-enable PCU/DMA engine */ + ath_hal_startpcurecv(ah, (!! sc->sc_scanning)); /* re-enable PCU/DMA engine */ #endif ath_hal_intrset(ah, sc->sc_imask); @@ -1444,7 +1476,7 @@ ath_legacy_startrecv(struct ath_softc *sc) ath_hal_putrxbuf(ah, bf->bf_daddr, HAL_RX_QUEUE_HP); ath_hal_rxena(ah); /* enable recv descriptors */ ath_mode_init(sc); /* set filters, etc. */ - ath_hal_startpcurecv(ah); /* re-enable PCU/DMA engine */ + ath_hal_startpcurecv(ah, (!! sc->sc_scanning)); /* re-enable PCU/DMA engine */ ATH_RX_UNLOCK(sc); return 0; diff --git a/sys/dev/ath/if_ath_rx_edma.c b/sys/dev/ath/if_ath_rx_edma.c index 725447d61739..e528dc8d2e43 100644 --- a/sys/dev/ath/if_ath_rx_edma.c +++ b/sys/dev/ath/if_ath_rx_edma.c @@ -162,6 +162,9 @@ ath_edma_stoprecv(struct ath_softc *sc, int dodelay) { struct ath_hal *ah = sc->sc_ah; + DPRINTF(sc, ATH_DEBUG_EDMA_RX, "%s: called, dodelay=%d\n", + __func__, dodelay); + ATH_RX_LOCK(sc); ath_hal_stoppcurecv(ah); @@ -191,6 +194,8 @@ ath_edma_stoprecv(struct ath_softc *sc, int dodelay) sc->sc_rxedma[HAL_RX_QUEUE_LP].m_rxpending = NULL; } ATH_RX_UNLOCK(sc); + + DPRINTF(sc, ATH_DEBUG_EDMA_RX, "%s: done\n", __func__); } /* @@ -205,6 +210,8 @@ ath_edma_reinit_fifo(struct ath_softc *sc, HAL_RX_QUEUE qtype) struct ath_buf *bf; int i, j; + DPRINTF(sc, ATH_DEBUG_EDMA_RX, "%s: called\n", __func__); + ATH_RX_LOCK_ASSERT(sc); i = re->m_fifo_head; @@ -227,6 +234,7 @@ ath_edma_reinit_fifo(struct ath_softc *sc, HAL_RX_QUEUE qtype) i, re->m_fifo_tail); } + DPRINTF(sc, ATH_DEBUG_EDMA_RX, "%s: done\n", __func__); } /* @@ -237,6 +245,10 @@ ath_edma_startrecv(struct ath_softc *sc) { struct ath_hal *ah = sc->sc_ah; + DPRINTF(sc, ATH_DEBUG_EDMA_RX, + "%s: called; resetted=%d, stopped=%d\n", __func__, + sc->sc_rx_resetted, sc->sc_rx_stopped); + ATH_RX_LOCK(sc); /* @@ -252,7 +264,7 @@ ath_edma_startrecv(struct ath_softc *sc) /* * In theory the hardware has been initialised, right? */ - if (sc->sc_rx_resetted == 1) { + if (sc->sc_rx_resetted == 1 || sc->sc_rx_stopped == 1) { DPRINTF(sc, ATH_DEBUG_EDMA_RX, "%s: Re-initing HP FIFO\n", __func__); ath_edma_reinit_fifo(sc, HAL_RX_QUEUE_HP); @@ -262,8 +274,11 @@ ath_edma_startrecv(struct ath_softc *sc) sc->sc_rx_resetted = 0; } else { device_printf(sc->sc_dev, - "%s: called without resetting chip?\n", - __func__); + "%s: called without resetting chip? " + "resetted=%d, stopped=%d\n", + __func__, + sc->sc_rx_resetted, + sc->sc_rx_stopped); } /* Add up to m_fifolen entries in each queue */ @@ -282,7 +297,7 @@ ath_edma_startrecv(struct ath_softc *sc) sc->sc_rxedma[HAL_RX_QUEUE_LP].m_fifolen); ath_mode_init(sc); - ath_hal_startpcurecv(ah); + ath_hal_startpcurecv(ah, (!! sc->sc_scanning)); /* * We're now doing RX DMA! @@ -290,6 +305,7 @@ ath_edma_startrecv(struct ath_softc *sc) sc->sc_rx_stopped = 0; ATH_RX_UNLOCK(sc); + DPRINTF(sc, ATH_DEBUG_EDMA_RX, "%s: ready\n", __func__); return (0); } @@ -298,6 +314,8 @@ static void ath_edma_recv_sched_queue(struct ath_softc *sc, HAL_RX_QUEUE qtype, int dosched) { + DPRINTF(sc, ATH_DEBUG_EDMA_RX, "%s: called; qtype=%d, dosched=%d\n", + __func__, qtype, dosched); ATH_LOCK(sc); ath_power_set_power_state(sc, HAL_PM_AWAKE); @@ -309,13 +327,19 @@ ath_edma_recv_sched_queue(struct ath_softc *sc, HAL_RX_QUEUE qtype, ath_power_restore_power_state(sc); ATH_UNLOCK(sc); + /* XXX TODO: methodize */ taskqueue_enqueue(sc->sc_tq, &sc->sc_rxtask); + + DPRINTF(sc, ATH_DEBUG_EDMA_RX, "%s: done\n", __func__); } static void ath_edma_recv_sched(struct ath_softc *sc, int dosched) { + DPRINTF(sc, ATH_DEBUG_EDMA_RX, "%s: called; dosched=%d\n", + __func__, dosched); + ATH_LOCK(sc); ath_power_set_power_state(sc, HAL_PM_AWAKE); ATH_UNLOCK(sc); @@ -327,19 +351,27 @@ ath_edma_recv_sched(struct ath_softc *sc, int dosched) ath_power_restore_power_state(sc); ATH_UNLOCK(sc); + /* XXX TODO: methodize */ taskqueue_enqueue(sc->sc_tq, &sc->sc_rxtask); + + DPRINTF(sc, ATH_DEBUG_EDMA_RX, "%s: done\n", __func__); } static void ath_edma_recv_flush(struct ath_softc *sc) { - DPRINTF(sc, ATH_DEBUG_RECV, "%s: called\n", __func__); + DPRINTF(sc, ATH_DEBUG_RECV | ATH_DEBUG_EDMA_RX, "%s: called\n", __func__); ATH_PCU_LOCK(sc); sc->sc_rxproc_cnt++; ATH_PCU_UNLOCK(sc); + // XXX TODO: methodize; make it an RX stop/block + while (taskqueue_cancel(sc->sc_tq, &sc->sc_rxtask, NULL) != 0) { + taskqueue_drain(sc->sc_tq, &sc->sc_rxtask); + } + ATH_LOCK(sc); ath_power_set_power_state(sc, HAL_PM_AWAKE); ATH_UNLOCK(sc); @@ -368,6 +400,8 @@ ath_edma_recv_flush(struct ath_softc *sc) ATH_PCU_LOCK(sc); sc->sc_rxproc_cnt--; ATH_PCU_UNLOCK(sc); + + DPRINTF(sc, ATH_DEBUG_RECV | ATH_DEBUG_EDMA_RX, "%s: done\n", __func__); } /* @@ -391,6 +425,8 @@ ath_edma_recv_proc_queue(struct ath_softc *sc, HAL_RX_QUEUE qtype, nf = ath_hal_getchannoise(ah, sc->sc_curchan); sc->sc_stats.ast_rx_noise = nf; + DPRINTF(sc, ATH_DEBUG_EDMA_RX, "%s: called; qtype=%d, dosched=%d\n", __func__, qtype, dosched); + ATH_RX_LOCK(sc); #if 1 @@ -604,9 +640,6 @@ ath_edma_recv_tasklet(void *arg, int npending) ath_power_set_power_state(sc, HAL_PM_AWAKE); ATH_UNLOCK(sc); - ath_edma_recv_proc_queue(sc, HAL_RX_QUEUE_HP, 1); - ath_edma_recv_proc_queue(sc, HAL_RX_QUEUE_LP, 1); - ath_edma_recv_proc_deferred_queue(sc, HAL_RX_QUEUE_HP, 1); ath_edma_recv_proc_deferred_queue(sc, HAL_RX_QUEUE_LP, 1); @@ -628,6 +661,8 @@ ath_edma_recv_tasklet(void *arg, int npending) ATH_PCU_LOCK(sc); sc->sc_rxproc_cnt--; ATH_PCU_UNLOCK(sc); + + DPRINTF(sc, ATH_DEBUG_EDMA_RX, "%s: called; done!\n", __func__); } /* diff --git a/sys/dev/ath/if_ath_spectral.c b/sys/dev/ath/if_ath_spectral.c index eaf91b9b1cab..44d5064c182d 100644 --- a/sys/dev/ath/if_ath_spectral.c +++ b/sys/dev/ath/if_ath_spectral.c @@ -54,7 +54,7 @@ __FBSDID("$FreeBSD$"); #include <sys/bus.h> #include <sys/socket.h> - + #include <net/if.h> #include <net/if_var.h> #include <net/if_media.h> @@ -299,4 +299,3 @@ bad: return (error); } - diff --git a/sys/dev/ath/if_ath_sysctl.c b/sys/dev/ath/if_ath_sysctl.c index 3e4e47246357..fd43ba4f6083 100644 --- a/sys/dev/ath/if_ath_sysctl.c +++ b/sys/dev/ath/if_ath_sysctl.c @@ -382,7 +382,8 @@ ath_sysctl_tpscale(SYSCTL_HANDLER_ARGS) goto finish; error = !ath_hal_settpscale(sc->sc_ah, scale) ? EINVAL : - (sc->sc_running) ? ath_reset(sc, ATH_RESET_NOLOSS) : 0; + (sc->sc_running) ? ath_reset(sc, ATH_RESET_NOLOSS, + HAL_RESET_NORMAL) : 0; finish: ATH_LOCK(sc); @@ -443,7 +444,8 @@ ath_sysctl_rfkill(SYSCTL_HANDLER_ARGS) error = EINVAL; goto finish; } - error = sc->sc_running ? ath_reset(sc, ATH_RESET_FULL) : 0; + error = sc->sc_running ? ath_reset(sc, ATH_RESET_FULL, + HAL_RESET_NORMAL) : 0; finish: ATH_LOCK(sc); @@ -670,7 +672,7 @@ ath_sysctl_intmit(SYSCTL_HANDLER_ARGS) * things in an inconsistent state. */ if (sc->sc_running) - ath_reset(sc, ATH_RESET_NOLOSS); + ath_reset(sc, ATH_RESET_NOLOSS, HAL_RESET_NORMAL); error = 0; @@ -1062,7 +1064,7 @@ ath_sysctl_stats_attach(struct ath_softc *sc) struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev); struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev); struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree); - + /* Create "clear" node */ SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "clear_stats", CTLTYPE_INT | CTLFLAG_RW, sc, 0, @@ -1296,7 +1298,7 @@ ath_sysctl_stats_attach(struct ath_softc *sc) SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_ldpc", CTLFLAG_RD, &sc->sc_stats.ast_tx_ldpc, 0, "Number of LDPC frames transmitted"); - + /* Attach the RX phy error array */ ath_sysctl_stats_attach_rxphyerr(sc, child); diff --git a/sys/dev/ath/if_ath_tx.c b/sys/dev/ath/if_ath_tx.c index 8d90a5d27fb1..f8800fab04cd 100644 --- a/sys/dev/ath/if_ath_tx.c +++ b/sys/dev/ath/if_ath_tx.c @@ -363,7 +363,7 @@ ath_tx_dmasetup(struct ath_softc *sc, struct ath_buf *bf, struct mbuf *m0) */ static void ath_tx_chaindesclist(struct ath_softc *sc, struct ath_desc *ds0, - struct ath_buf *bf, int is_aggr, int is_first_subframe, + struct ath_buf *bf, bool is_aggr, int is_first_subframe, int is_last_subframe) { struct ath_hal *ah = sc->sc_ah; @@ -1307,7 +1307,7 @@ ath_tx_set_rtscts(struct ath_softc *sc, struct ath_buf *bf) /* Squirrel away in ath_buf */ bf->bf_state.bfs_ctsrate = ctsrate; bf->bf_state.bfs_ctsduration = ctsduration; - + /* * Must disable multi-rate retry when using RTS/CTS. */ @@ -1376,10 +1376,13 @@ ath_tx_setds(struct ath_softc *sc, struct ath_buf *bf) * as they may depend upon the rate chosen. */ static void -ath_tx_do_ratelookup(struct ath_softc *sc, struct ath_buf *bf) +ath_tx_do_ratelookup(struct ath_softc *sc, struct ath_buf *bf, int tid, + int pktlen, int is_aggr) { uint8_t rate, rix; int try0; + int maxdur; // Note: Unused for now + int maxpktlen; if (! bf->bf_state.bfs_doratelookup) return; @@ -1389,7 +1392,7 @@ ath_tx_do_ratelookup(struct ath_softc *sc, struct ath_buf *bf) ATH_NODE_LOCK(ATH_NODE(bf->bf_node)); ath_rate_findrate(sc, ATH_NODE(bf->bf_node), bf->bf_state.bfs_shpream, - bf->bf_state.bfs_pktlen, &rix, &try0, &rate); + pktlen, tid, is_aggr, &rix, &try0, &rate, &maxdur, &maxpktlen); /* In case MRR is disabled, make sure rc[0] is setup correctly */ bf->bf_state.bfs_rc[0].rix = rix; @@ -1398,13 +1401,14 @@ ath_tx_do_ratelookup(struct ath_softc *sc, struct ath_buf *bf) if (bf->bf_state.bfs_ismrr && try0 != ATH_TXMAXTRY) ath_rate_getxtxrates(sc, ATH_NODE(bf->bf_node), rix, - bf->bf_state.bfs_rc); + is_aggr, bf->bf_state.bfs_rc); ATH_NODE_UNLOCK(ATH_NODE(bf->bf_node)); sc->sc_txrix = rix; /* for LED blinking */ sc->sc_lastdatarix = rix; /* for fast frames */ bf->bf_state.bfs_try0 = try0; bf->bf_state.bfs_txrate0 = rate; + bf->bf_state.bfs_rc_maxpktlen = maxpktlen; } /* @@ -1482,7 +1486,6 @@ ath_tx_should_swq_frame(struct ath_softc *sc, struct ath_node *an, } } - /* * Transmit the given frame to the hardware. * @@ -1519,7 +1522,7 @@ ath_tx_xmit_normal(struct ath_softc *sc, struct ath_txq *txq, bf->bf_state.bfs_txflags |= HAL_TXDESC_CLRDMASK; /* Setup the descriptor before handoff */ - ath_tx_do_ratelookup(sc, bf); + ath_tx_do_ratelookup(sc, bf, tid->tid, bf->bf_state.bfs_pktlen, false); ath_tx_calc_duration(sc, bf); ath_tx_calc_protection(sc, bf); ath_tx_set_rtscts(sc, bf); @@ -2515,7 +2518,6 @@ ath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, sc->sc_txstart_cnt--; ATH_PCU_UNLOCK(sc); - /* Put the hardware back to sleep if required */ ATH_LOCK(sc); ath_power_restore_power_state(sc); @@ -2709,7 +2711,6 @@ ath_tx_addto_baw(struct ath_softc *sc, struct ath_node *an, tap->txa_start, tap->txa_wnd, index, cindex, tid->baw_head, tid->baw_tail); - #if 0 assert(tid->tx_buf[cindex] == NULL); #endif @@ -3094,7 +3095,8 @@ ath_tx_xmit_aggr(struct ath_softc *sc, struct ath_node *an, ath_tx_update_clrdmask(sc, tid, bf); /* Direct dispatch to hardware */ - ath_tx_do_ratelookup(sc, bf); + ath_tx_do_ratelookup(sc, bf, tid->tid, bf->bf_state.bfs_pktlen, + false); ath_tx_calc_duration(sc, bf); ath_tx_calc_protection(sc, bf); ath_tx_set_rtscts(sc, bf); @@ -3220,7 +3222,6 @@ ath_tx_swq(struct ath_softc *sc, struct ieee80211_node *ni, */ /* XXX TXQ locking */ if (txq->axq_depth + txq->fifo.axq_depth == 0) { - bf = ATH_TID_FIRST(atid); ATH_TID_REMOVE(atid, bf, bf_list); @@ -4257,7 +4258,9 @@ ath_tx_normal_comp(struct ath_softc *sc, struct ath_buf *bf, int fail) */ if (fail == 0 && ((bf->bf_state.bfs_txflags & HAL_TXDESC_NOACK) == 0)) ath_tx_update_ratectrl(sc, ni, bf->bf_state.bfs_rc, - ts, bf->bf_state.bfs_pktlen, + ts, + bf->bf_state.bfs_pktlen, + bf->bf_state.bfs_pktlen, 1, (ts->ts_status == 0) ? 0 : 1); ath_tx_default_comp(sc, bf, fail); @@ -4305,7 +4308,6 @@ ath_tx_comp_cleanup_unaggr(struct ath_softc *sc, struct ath_buf *bf) ath_tx_default_comp(sc, bf, 0); } - /* * This as it currently stands is a bit dumb. Ideally we'd just * fail the frame the normal way and have it permanently fail @@ -4686,13 +4688,11 @@ ath_tx_comp_aggr_error(struct ath_softc *sc, struct ath_buf *bf_first, /* * Update rate control - all frames have failed. - * - * XXX use the length in the first frame in the series; - * XXX just so things are consistent for now. */ ath_tx_update_ratectrl(sc, ni, bf_first->bf_state.bfs_rc, &bf_first->bf_status.ds_txstat, - bf_first->bf_state.bfs_pktlen, + bf_first->bf_state.bfs_al, + bf_first->bf_state.bfs_rc_maxpktlen, bf_first->bf_state.bfs_nframes, bf_first->bf_state.bfs_nframes); ATH_TX_LOCK(sc); @@ -4841,6 +4841,7 @@ ath_tx_aggr_comp_aggr(struct ath_softc *sc, struct ath_buf *bf_first, int drops = 0; int nframes = 0, nbad = 0, nf; int pktlen; + int agglen, rc_agglen; /* XXX there's too much on the stack? */ struct ath_rc_series rc[ATH_RC_NUM]; int txseq; @@ -4853,6 +4854,8 @@ ath_tx_aggr_comp_aggr(struct ath_softc *sc, struct ath_buf *bf_first, * has been completed and freed. */ ts = bf_first->bf_status.ds_txstat; + agglen = bf_first->bf_state.bfs_al; + rc_agglen = bf_first->bf_state.bfs_rc_maxpktlen; TAILQ_INIT(&bf_q); TAILQ_INIT(&bf_cq); @@ -5003,7 +5006,11 @@ ath_tx_aggr_comp_aggr(struct ath_softc *sc, struct ath_buf *bf_first, "%s: AR5416 bug: hasba=%d; txok=%d, isaggr=%d, " "seq_st=%d\n", __func__, hasba, tx_ok, isaggr, seq_st); - /* XXX TODO: schedule an interface reset */ + taskqueue_enqueue(sc->sc_tq, &sc->sc_fataltask); + /* And as we can't really trust the BA here .. */ + ba[0] = 0; + ba[1] = 0; + seq_st = 0; #ifdef ATH_DEBUG ath_printtxbuf(sc, bf_first, sc->sc_ac2q[atid->ac]->axq_qnum, 0, 0); @@ -5088,9 +5095,10 @@ ath_tx_aggr_comp_aggr(struct ath_softc *sc, struct ath_buf *bf_first, * Now we know how many frames were bad, call the rate * control code. */ - if (fail == 0) - ath_tx_update_ratectrl(sc, ni, rc, &ts, pktlen, nframes, - nbad); + if (fail == 0) { + ath_tx_update_ratectrl(sc, ni, rc, &ts, agglen, rc_agglen, + nframes, nbad); + } /* * send bar if we dropped any frames @@ -5181,6 +5189,7 @@ ath_tx_aggr_comp_unaggr(struct ath_softc *sc, struct ath_buf *bf, int fail) ath_tx_update_ratectrl(sc, ni, bf->bf_state.bfs_rc, &bf->bf_status.ds_txstat, bf->bf_state.bfs_pktlen, + bf->bf_state.bfs_pktlen, 1, (ts.ts_status == 0) ? 0 : 1); /* @@ -5353,6 +5362,65 @@ ath_tx_aggr_comp(struct ath_softc *sc, struct ath_buf *bf, int fail) } /* + * Grab the software queue depth that we COULD transmit. + * + * This includes checks if it's in the BAW, whether it's a frame + * that is supposed to be in the BAW. Other checks could be done; + * but for now let's try and avoid doing the whole of ath_tx_form_aggr() + * here. + */ +static int +ath_tx_tid_swq_depth_bytes(struct ath_softc *sc, struct ath_node *an, + struct ath_tid *tid) +{ + struct ath_buf *bf; + struct ieee80211_tx_ampdu *tap; + int nbytes = 0; + + ATH_TX_LOCK_ASSERT(sc); + + tap = ath_tx_get_tx_tid(an, tid->tid); + + /* + * Iterate over each buffer and sum the pkt_len. + * Bail if we exceed ATH_AGGR_MAXSIZE bytes; we won't + * ever queue more than that in a single frame. + */ + TAILQ_FOREACH(bf, &tid->tid_q, bf_list) { + /* + * TODO: I'm not sure if we're going to hit cases where + * no frames get sent because the list is empty. + */ + + /* Check if it's in the BAW */ + if (tap != NULL && (! BAW_WITHIN(tap->txa_start, tap->txa_wnd, + SEQNO(bf->bf_state.bfs_seqno)))) { + break; + } + + /* Check if it's even supposed to be in the BAW */ + if (! bf->bf_state.bfs_dobaw) { + break; + } + + nbytes += bf->bf_state.bfs_pktlen; + if (nbytes >= ATH_AGGR_MAXSIZE) + break; + + /* + * Check if we're likely going to leak a frame + * as part of a PSPOLL. Break out at this point; + * we're only going to send a single frame anyway. + */ + if (an->an_leak_count) { + break; + } + } + + return MIN(nbytes, ATH_AGGR_MAXSIZE); +} + +/* * Schedule some packets from the given node/TID to the hardware. * * This is the aggregate version. @@ -5366,6 +5434,7 @@ ath_tx_tid_hw_queue_aggr(struct ath_softc *sc, struct ath_node *an, struct ieee80211_tx_ampdu *tap; ATH_AGGR_STATUS status; ath_bufhead bf_q; + int swq_pktbytes; DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: tid=%d\n", __func__, tid->tid); ATH_TX_LOCK_ASSERT(sc); @@ -5429,7 +5498,8 @@ ath_tx_tid_hw_queue_aggr(struct ath_softc *sc, struct ath_node *an, /* Update CLRDMASK just before this frame is queued */ ath_tx_update_clrdmask(sc, tid, bf); - ath_tx_do_ratelookup(sc, bf); + ath_tx_do_ratelookup(sc, bf, tid->tid, + bf->bf_state.bfs_pktlen, false); ath_tx_calc_duration(sc, bf); ath_tx_calc_protection(sc, bf); ath_tx_set_rtscts(sc, bf); @@ -5446,17 +5516,18 @@ ath_tx_tid_hw_queue_aggr(struct ath_softc *sc, struct ath_node *an, TAILQ_INIT(&bf_q); /* - * Do a rate control lookup on the first frame in the - * list. The rate control code needs that to occur - * before it can determine whether to TX. - * It's inaccurate because the rate control code doesn't - * really "do" aggregate lookups, so it only considers - * the size of the first frame. + * Loop over the swq to find out how long + * each packet is (up until 64k) and provide that + * to the rate control lookup. */ - ath_tx_do_ratelookup(sc, bf); - bf->bf_state.bfs_rc[3].rix = 0; - bf->bf_state.bfs_rc[3].tries = 0; + swq_pktbytes = ath_tx_tid_swq_depth_bytes(sc, an, tid); + ath_tx_do_ratelookup(sc, bf, tid->tid, swq_pktbytes, true); + /* + * Note this only is used for the fragment paths and + * should really be rethought out if we want to do + * things like an RTS burst across >1 aggregate. + */ ath_tx_calc_duration(sc, bf); ath_tx_calc_protection(sc, bf); @@ -5535,7 +5606,6 @@ ath_tx_tid_hw_queue_aggr(struct ath_softc *sc, struct ath_node *an, * already points to the rest in the chain. */ ath_tx_setds_11n(sc, bf); - } queuepkt: /* Set completion handler, multi-frame aggregate or not */ @@ -5607,7 +5677,6 @@ ath_tx_tid_hw_queue_norm(struct ath_softc *sc, struct ath_node *an, __func__, tid->tid); for (;;) { - /* * If the upper layers have paused the TID, don't * queue any further packets. @@ -5644,7 +5713,8 @@ ath_tx_tid_hw_queue_norm(struct ath_softc *sc, struct ath_node *an, ath_tx_update_clrdmask(sc, tid, bf); /* Program descriptors + rate control */ - ath_tx_do_ratelookup(sc, bf); + ath_tx_do_ratelookup(sc, bf, tid->tid, + bf->bf_state.bfs_pktlen, false); ath_tx_calc_duration(sc, bf); ath_tx_calc_protection(sc, bf); ath_tx_set_rtscts(sc, bf); @@ -5838,7 +5908,6 @@ ath_tx_ampdu_pending(struct ath_softc *sc, struct ath_node *an, int tid) * Is AMPDU-TX pending for the given TID? */ - /* * Method to handle sending an ADDBA request. * @@ -5966,7 +6035,6 @@ ath_addba_response(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap, return r; } - /* * Stop ADDBA on a queue. * diff --git a/sys/dev/ath/if_ath_tx.h b/sys/dev/ath/if_ath_tx.h index 517007716e9f..2ad2f75e926d 100644 --- a/sys/dev/ath/if_ath_tx.h +++ b/sys/dev/ath/if_ath_tx.h @@ -71,7 +71,6 @@ #define ATH_BA_ISSET(_bm, _n) (((_n) < (WME_BA_BMP_SIZE)) && \ ((_bm)[(_n) >> 5] & (1 << ((_n) & 31)))) - /* extracting the seqno from buffer seqno */ #define SEQNO(_a) ((_a) >> IEEE80211_SEQ_SEQ_SHIFT) diff --git a/sys/dev/ath/if_ath_tx_edma.c b/sys/dev/ath/if_ath_tx_edma.c index 375c7ff4bbc8..4ec98b3382c9 100644 --- a/sys/dev/ath/if_ath_tx_edma.c +++ b/sys/dev/ath/if_ath_tx_edma.c @@ -654,7 +654,7 @@ ath_edma_setup_txfifo(struct ath_softc *sc, int qnum) * Set initial "empty" state. */ te->m_fifo_head = te->m_fifo_tail = te->m_fifo_depth = 0; - + return (0); } @@ -778,7 +778,6 @@ ath_edma_tx_proc(void *arg, int npending) #endif ath_edma_tx_processq(sc, 1); - ATH_PCU_LOCK(sc); sc->sc_txproc_cnt--; ATH_PCU_UNLOCK(sc); @@ -1012,6 +1011,8 @@ ath_edma_tx_processq(struct ath_softc *sc, int dosched) sc->sc_stats.ast_tx_rssi = ts.ts_rssi; ATH_RSSI_LPF(sc->sc_halstats.ns_avgtxrssi, ts.ts_rssi); + ATH_RSSI_LPF(ATH_NODE(ni)->an_node_stats.ns_avgtxrssi, + ts.ts_rssi); } /* Handle frame completion and rate control update */ diff --git a/sys/dev/ath/if_ath_tx_ht.c b/sys/dev/ath/if_ath_tx_ht.c index 249cbe23b538..c7fa41443d26 100644 --- a/sys/dev/ath/if_ath_tx_ht.c +++ b/sys/dev/ath/if_ath_tx_ht.c @@ -840,16 +840,25 @@ ath_tx_form_aggr(struct ath_softc *sc, struct ath_node *an, goto finish; } + /* + * Limit the maximum number of frames in this A-MPDU + * to half of the window size. This is done to prevent + * sending a LOT of frames that may fail in one batch + * when operating in higher MCS rates. If there are more + * frames available to send then up to two A-MPDUs will + * be queued per hardware queue, so we'll "just" get + * a second A-MPDU. + */ h_baw = tap->txa_wnd / 2; for (;;) { bf = ATH_TID_FIRST(tid); - if (bf_first == NULL) - bf_first = bf; if (bf == NULL) { status = ATH_AGGR_DONE; break; - } else { + } + if (bf_first == NULL) { + bf_first = bf; /* * It's the first frame; * set the aggregation limit based on the @@ -857,6 +866,10 @@ ath_tx_form_aggr(struct ath_softc *sc, struct ath_node *an, */ aggr_limit = ath_get_aggr_limit(sc, &an->an_node, bf_first); + if (bf_first->bf_state.bfs_rc_maxpktlen > 0) { + aggr_limit = MIN(aggr_limit, + bf_first->bf_state.bfs_rc_maxpktlen); + } } /* Set this early just so things don't get confused */ @@ -1013,7 +1026,6 @@ ath_tx_form_aggr(struct ath_softc *sc, struct ath_node *an, break; } #endif - } finish: @@ -1022,6 +1034,10 @@ finish: * dequeue a packet .. */ if (bf_first) { + DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR, + "%s: al=%d bytes; requested %d bytes\n", + __func__, al, bf_first->bf_state.bfs_rc_maxpktlen); + bf_first->bf_state.bfs_al = al; bf_first->bf_state.bfs_nframes = nframes; } diff --git a/sys/dev/ath/if_athioctl.h b/sys/dev/ath/if_athioctl.h index 82decdefe3d4..8367a3ebac18 100644 --- a/sys/dev/ath/if_athioctl.h +++ b/sys/dev/ath/if_athioctl.h @@ -193,7 +193,6 @@ struct ath_diag { #define SIOCGATHDIAG _IOWR('i', 138, struct ath_diag) #define SIOCGATHPHYERR _IOWR('i', 140, struct ath_diag) - /* * The rate control ioctl has to support multiple potential rate * control classes. For now, instead of trying to support an diff --git a/sys/dev/ath/if_athrate.h b/sys/dev/ath/if_athrate.h index 5aec9e6b3870..45711a1735bc 100644 --- a/sys/dev/ath/if_athrate.h +++ b/sys/dev/ath/if_athrate.h @@ -125,17 +125,23 @@ void ath_rate_newassoc(struct ath_softc *, struct ath_node *, * Return the four TX rate index and try counts for the current data packet. */ void ath_rate_getxtxrates(struct ath_softc *sc, struct ath_node *an, - uint8_t rix0, struct ath_rc_series *rc); + uint8_t rix0, int is_aggr, struct ath_rc_series *rc); /* * Return the transmit info for a data packet. If multi-rate state * is to be setup then try0 should contain a value other than ATH_TXMATRY * and ath_rate_setupxtxdesc will be called after deciding if the frame * can be transmitted with multi-rate retry. + * + * maxdur is an optional return value (or -1 if not set) that defines + * the maximum frame duration in microseconds. This allows the rate + * control selection to override the maximum duration (normally 4ms) + * that the packet aggregation logic makes. */ void ath_rate_findrate(struct ath_softc *, struct ath_node *, - int shortPreamble, size_t frameLen, - u_int8_t *rix, int *try0, u_int8_t *txrate); + int shortPreamble, size_t frameLen, int tid, int is_aggr, + u_int8_t *rix, int *try0, u_int8_t *txrate, int *maxdur, + int *maxpktlen); /* * Setup any extended (multi-rate) descriptor state for a data packet. * The rate index returned by ath_rate_findrate is passed back in. @@ -154,7 +160,13 @@ void ath_rate_setupxtxdesc(struct ath_softc *, struct ath_node *, struct ath_buf; void ath_rate_tx_complete(struct ath_softc *, struct ath_node *, const struct ath_rc_series *, const struct ath_tx_status *, - int pktlen, int nframes, int nbad); + int pktlen, int rc_framelen, int nframes, int nbad); + +/* + * Update rate control with a per-packet receive RSSI value. + */ +void ath_rate_update_rx_rssi(struct ath_softc *, struct ath_node *, + int rssi); /* * Fetch the global rate control statistics. diff --git a/sys/dev/ath/if_athvar.h b/sys/dev/ath/if_athvar.h index 96d22f511746..c789b2c459c1 100644 --- a/sys/dev/ath/if_athvar.h +++ b/sys/dev/ath/if_athvar.h @@ -204,6 +204,7 @@ struct ath_node { node */ int clrdmask; /* has clrdmask been set */ uint32_t an_leak_count; /* How many frames to leak during pause */ + HAL_NODE_STATS an_node_stats; /* HAL node stats for this node */ /* variable-length rate control state follows */ }; #define ATH_NODE(ni) ((struct ath_node *)(ni)) @@ -307,6 +308,7 @@ struct ath_buf { /* 16 bit? */ uint32_t bfs_ctsduration; /* CTS duration (pre-11n NICs) */ + int32_t bfs_rc_maxpktlen; /* max packet length/bucket from ratectrl or -1 */ struct ath_rc_series bfs_rc[ATH_RC_NUM]; /* non-11n TX series */ } bf_state; }; @@ -409,7 +411,6 @@ struct ath_txq { #define ATH_TXQ_UNLOCK_ASSERT(_tq) mtx_assert(&(_tq)->axq_lock, \ MA_NOTOWNED) - #define ATH_NODE_LOCK(_an) mtx_lock(&(_an)->an_mtx) #define ATH_NODE_UNLOCK(_an) mtx_unlock(&(_an)->an_mtx) #define ATH_NODE_LOCK_ASSERT(_an) mtx_assert(&(_an)->an_mtx, MA_OWNED) @@ -1155,8 +1156,8 @@ void ath_intr(void *); ((*(_ah)->ah_stopTxDma)((_ah), (_qnum))) #define ath_hal_stoppcurecv(_ah) \ ((*(_ah)->ah_stopPcuReceive)((_ah))) -#define ath_hal_startpcurecv(_ah) \ - ((*(_ah)->ah_startPcuReceive)((_ah))) +#define ath_hal_startpcurecv(_ah, _is_scanning) \ + ((*(_ah)->ah_startPcuReceive)((_ah), (_is_scanning))) #define ath_hal_stopdmarecv(_ah) \ ((*(_ah)->ah_stopDmaReceive)((_ah))) #define ath_hal_getdiagstate(_ah, _id, _indata, _insize, _outdata, _outsize) \ @@ -1352,7 +1353,7 @@ void ath_intr(void *); == HAL_OK) #define ath_hal_setrxbufsize(_ah, _req) \ (ath_hal_setcapability(_ah, HAL_CAP_RXBUFSIZE, 0, _req, NULL) \ - == HAL_OK) + == AH_TRUE) #define ath_hal_getchannoise(_ah, _c) \ ((*(_ah)->ah_getChanNoise)((_ah), (_c))) diff --git a/sys/dev/bwi/bwimac.c b/sys/dev/bwi/bwimac.c index f998873a713b..3e77e43004fa 100644 --- a/sys/dev/bwi/bwimac.c +++ b/sys/dev/bwi/bwimac.c @@ -57,7 +57,7 @@ __FBSDID("$FreeBSD$"); #include <sys/linker.h> #include <sys/firmware.h> - + #include <net/if.h> #include <net/if_var.h> #include <net/if_dl.h> diff --git a/sys/dev/bwi/bwiphy.c b/sys/dev/bwi/bwiphy.c index a17735590007..291e3253f502 100644 --- a/sys/dev/bwi/bwiphy.c +++ b/sys/dev/bwi/bwiphy.c @@ -53,7 +53,7 @@ __FBSDID("$FreeBSD$"); #include <sys/sockio.h> #include <sys/sysctl.h> #include <sys/systm.h> - + #include <net/if.h> #include <net/if_var.h> #include <net/if_dl.h> @@ -88,7 +88,6 @@ static void bwi_phy_config_agc(struct bwi_mac *); static void bwi_tbl_write_2(struct bwi_mac *mac, uint16_t, uint16_t); static void bwi_tbl_write_4(struct bwi_mac *mac, uint16_t, uint32_t); - #define SUP_BPHY(num) { .rev = num, .init = bwi_phy_init_11b_rev##num } static const struct { diff --git a/sys/dev/bwi/bwirf.c b/sys/dev/bwi/bwirf.c index dbf658d5caa7..1345c64d126a 100644 --- a/sys/dev/bwi/bwirf.c +++ b/sys/dev/bwi/bwirf.c @@ -54,7 +54,7 @@ __FBSDID("$FreeBSD$"); #include <sys/sockio.h> #include <sys/sysctl.h> #include <sys/systm.h> - + #include <net/if.h> #include <net/if_var.h> #include <net/if_dl.h> diff --git a/sys/dev/bwi/if_bwi.c b/sys/dev/bwi/if_bwi.c index feb522acfc3c..af1cbd41d883 100644 --- a/sys/dev/bwi/if_bwi.c +++ b/sys/dev/bwi/if_bwi.c @@ -55,7 +55,7 @@ __FBSDID("$FreeBSD$"); #include <sys/sysctl.h> #include <sys/systm.h> #include <sys/taskqueue.h> - + #include <net/if.h> #include <net/if_var.h> #include <net/if_dl.h> @@ -118,7 +118,6 @@ static void bwi_set_channel(struct ieee80211com *); static void bwi_scan_end(struct ieee80211com *); static int bwi_newstate(struct ieee80211vap *, enum ieee80211_state, int); static void bwi_updateslot(struct ieee80211com *); -static int bwi_media_change(struct ifnet *); static void bwi_calibrate(void *); @@ -607,8 +606,8 @@ bwi_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, ieee80211_ratectl_init(vap); /* complete setup */ - ieee80211_vap_attach(vap, bwi_media_change, ieee80211_media_status, - mac); + ieee80211_vap_attach(vap, ieee80211_media_change, + ieee80211_media_status, mac); ic->ic_opmode = opmode; return vap; } @@ -1807,14 +1806,6 @@ back: } static int -bwi_media_change(struct ifnet *ifp) -{ - int error = ieee80211_media_change(ifp); - /* NB: only the fixed rate can change and that doesn't need a reset */ - return (error == ENETRESET ? 0 : error); -} - -static int bwi_dma_alloc(struct bwi_softc *sc) { int error, i, has_txstats; diff --git a/sys/dev/bwi/if_bwi_pci.c b/sys/dev/bwi/if_bwi_pci.c index f95ef854ceaa..d82b7d4d60de 100644 --- a/sys/dev/bwi/if_bwi_pci.c +++ b/sys/dev/bwi/if_bwi_pci.c @@ -53,7 +53,7 @@ __FBSDID("$FreeBSD$"); #include <sys/rman.h> #include <sys/socket.h> - + #include <net/if.h> #include <net/if_var.h> #include <net/if_media.h> @@ -246,7 +246,6 @@ static device_method_t bwi_pci_methods[] = { DEVMETHOD(device_shutdown, bwi_pci_shutdown), DEVMETHOD(device_suspend, bwi_pci_suspend), DEVMETHOD(device_resume, bwi_pci_resume), - { 0,0 } }; static driver_t bwi_driver = { diff --git a/sys/dev/bwi/if_bwireg.h b/sys/dev/bwi/if_bwireg.h index 67c80cec9615..d1d37c491634 100644 --- a/sys/dev/bwi/if_bwireg.h +++ b/sys/dev/bwi/if_bwireg.h @@ -77,7 +77,6 @@ #define BWI_CONF_LO_REQTO_MASK __BITS(6, 4) /* request timeout */ #define BWI_CONF_LO_REQTO 3 - #define BWI_ID_LO 0xff8 #define BWI_ID_LO_BUSREV_MASK __BITS(31, 28) /* Bus revision */ diff --git a/sys/dev/bwn/if_bwn.c b/sys/dev/bwn/if_bwn.c index 067484acbaf3..b2ffe7b1f6ba 100644 --- a/sys/dev/bwn/if_bwn.c +++ b/sys/dev/bwn/if_bwn.c @@ -580,7 +580,7 @@ bwn_attach(device_t dev) device_printf(sc->sc_dev, "couldn't allocate registers\n"); return (error); } - + if ((error = bhnd_alloc_pmu(sc->sc_dev))) { bus_release_resource(sc->sc_dev, SYS_RES_MEMORY, sc->sc_mem_rid, sc->sc_mem_res); @@ -632,9 +632,10 @@ bwn_attach(device_t dev) goto fail; bhnd_format_chip_id(chip_name, sizeof(chip_name), sc->sc_cid.chip_id); - device_printf(sc->sc_dev, "WLAN (%s rev %u) " + device_printf(sc->sc_dev, "WLAN (%s rev %u sromrev %u) " "PHY (analog %d type %d rev %d) RADIO (manuf %#x ver %#x rev %d)\n", - chip_name, bhnd_get_hwrev(sc->sc_dev), mac->mac_phy.analog, + chip_name, bhnd_get_hwrev(sc->sc_dev), + sc->sc_board_info.board_srom_rev, mac->mac_phy.analog, mac->mac_phy.type, mac->mac_phy.rev, mac->mac_phy.rf_manuf, mac->mac_phy.rf_ver, mac->mac_phy.rf_rev); if (mac->mac_flags & BWN_MAC_FLAG_DMA) @@ -684,7 +685,7 @@ fail: free(mac, M_DEVBUF); bhnd_release_pmu(dev); bwn_release_bus_providers(sc); - + if (sc->sc_mem_res != NULL) { bus_release_resource(sc->sc_dev, SYS_RES_MEMORY, sc->sc_mem_rid, sc->sc_mem_res); @@ -1306,7 +1307,6 @@ bwn_attach_core(struct bwn_mac *mac) have_bg = 1; have_a = 1; } - #if 0 device_printf(sc->sc_dev, "%s: iost=0x%04hx, have_a=%d, have_bg=%d," @@ -3040,7 +3040,7 @@ bwn_dma_32_setdesc(struct bwn_dma_ring *dr, struct bhnd_dma_translation *dt; uint32_t addr, addrext, ctl; int slot; - + descbase = dr->dr_ring_descbase; dma = &dr->dr_mac->mac_method.dma; dt = &dma->translation; @@ -3136,8 +3136,7 @@ bwn_dma_64_setdesc(struct bwn_dma_ring *dr, uint32_t addrext; uint32_t ctl0, ctl1; int slot; - - + descbase = dr->dr_ring_descbase; dma = &dr->dr_mac->mac_method.dma; dt = &dma->translation; @@ -3685,7 +3684,6 @@ bwn_gpio_control(struct bwn_mac *mac, uint32_t pins) return (0); } - static int bwn_gpio_init(struct bwn_mac *mac) { @@ -4526,7 +4524,6 @@ bwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals, BWN_WRITE_4(mac, offset, be32toh(iv->data.d32)); iv = GET_NEXTIV32(iv); } else { - if (array_size < sizeof(iv->data.d16)) goto fail; array_size -= sizeof(iv->data.d16); @@ -6004,7 +6001,6 @@ bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr) break; } - phytype = chanstat & BWN_RX_CHAN_PHYTYPE; if (macstat & BWN_RX_MAC_FCSERR) @@ -7168,7 +7164,6 @@ bwn_dma_attach(struct bwn_mac *mac) return (ENXIO); } - /* Fetch our device->host DMA translation and tag */ error = bhnd_get_dma_translation(sc->sc_dev, addr_width, 0, &dmat, &dma_translation); diff --git a/sys/dev/bwn/if_bwn_pci.c b/sys/dev/bwn/if_bwn_pci.c index 610f8bdeb823..51ff56184f8a 100644 --- a/sys/dev/bwn/if_bwn_pci.c +++ b/sys/dev/bwn/if_bwn_pci.c @@ -90,7 +90,6 @@ static const struct bwn_pci_device siba_devices[] = { BWN_QUIRK_UNTESTED), BWN_BCM_DEV(BCM4328_D11G, "BCM4328/4312 802.11g", 0), - { 0, 0, NULL, 0 } }; @@ -102,7 +101,6 @@ static const struct bwn_pci_device bcma_devices[] = { BWN_BCM_DEV(BCM43224_D11N, "BCM43224 802.11n Dual-Band", 0), BWN_BCM_DEV(BCM43224_D11N_ID_VEN1, "BCM43224 802.11n Dual-Band",0), BWN_BCM_DEV(BCM43225_D11N2G, "BCM43225 802.11n 2GHz", 0), - { 0, 0, NULL, 0} }; diff --git a/sys/dev/bwn/if_bwn_pcivar.h b/sys/dev/bwn/if_bwn_pcivar.h index 06c781e557f6..2b134de07e26 100644 --- a/sys/dev/bwn/if_bwn_pcivar.h +++ b/sys/dev/bwn/if_bwn_pcivar.h @@ -91,7 +91,6 @@ struct bwn_pci_device { uint32_t quirks; }; - #define BWN_BCM_DEV(_devid, _desc, _quirks) \ { PCI_VENDOR_BROADCOM, PCI_DEVID_ ## _devid, \ "Broadcom " _desc " Wireless", _quirks } diff --git a/sys/dev/bwn/if_bwn_phy_g.c b/sys/dev/bwn/if_bwn_phy_g.c index fecb06109282..1659eb2a99bb 100644 --- a/sys/dev/bwn/if_bwn_phy_g.c +++ b/sys/dev/bwn/if_bwn_phy_g.c @@ -1689,7 +1689,6 @@ bwn_wa_grev1(struct bwn_mac *mac) bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i, bwn_tab_noise_g2[i]); - for (i = 0; i < N(bwn_tab_rotor); i++) bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ROTOR, i, bwn_tab_rotor[i]); diff --git a/sys/dev/bwn/if_bwnvar.h b/sys/dev/bwn/if_bwnvar.h index a97268de93d6..42930c20377a 100644 --- a/sys/dev/bwn/if_bwnvar.h +++ b/sys/dev/bwn/if_bwnvar.h @@ -161,7 +161,6 @@ struct bwn_mac; #define BWN_DMA_WRITE(dr, offset, value) \ (BWN_WRITE_4(dr->dr_mac, dr->dr_base + offset, value)) - typedef enum { BWN_PHY_BAND_2G = 0, BWN_PHY_BAND_5G_LO = 1, diff --git a/sys/dev/iwm/if_iwm.c b/sys/dev/iwm/if_iwm.c index e1bdb6d79b64..7657190e763e 100644 --- a/sys/dev/iwm/if_iwm.c +++ b/sys/dev/iwm/if_iwm.c @@ -4415,22 +4415,26 @@ iwm_setrates(struct iwm_softc *sc, struct iwm_node *in, int rix) static int iwm_media_change(struct ifnet *ifp) { +#if 0 struct ieee80211vap *vap = ifp->if_softc; struct ieee80211com *ic = vap->iv_ic; struct iwm_softc *sc = ic->ic_softc; +#endif int error; error = ieee80211_media_change(ifp); - if (error != ENETRESET) - return error; + if (error != 0) + return (error); +#if 0 IWM_LOCK(sc); if (ic->ic_nrunning > 0) { iwm_stop(sc); iwm_init(sc); } IWM_UNLOCK(sc); - return error; +#endif + return (0); } static void diff --git a/sys/dev/iwn/if_iwn.c b/sys/dev/iwn/if_iwn.c index e3b87f214ec2..2e576efc288c 100644 --- a/sys/dev/iwn/if_iwn.c +++ b/sys/dev/iwn/if_iwn.c @@ -194,7 +194,6 @@ static void iwn_read_eeprom_enhinfo(struct iwn_softc *); static struct ieee80211_node *iwn_node_alloc(struct ieee80211vap *, const uint8_t mac[IEEE80211_ADDR_LEN]); static void iwn_newassoc(struct ieee80211_node *, int); -static int iwn_media_change(struct ifnet *); static int iwn_newstate(struct ieee80211vap *, enum ieee80211_state, int); static void iwn_calib_timeout(void *); static void iwn_rx_phy(struct iwn_softc *, struct iwn_rx_desc *); @@ -1351,11 +1350,13 @@ iwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, ivp->iv_newstate = vap->iv_newstate; vap->iv_newstate = iwn_newstate; sc->ivap[IWN_RXON_BSS_CTX] = vap; + vap->iv_ampdu_rxmax = IEEE80211_HTCAP_MAXRXAMPDU_64K; + vap->iv_ampdu_density = IEEE80211_HTCAP_MPDUDENSITY_4; /* 4uS */ ieee80211_ratectl_init(vap); /* Complete setup. */ - ieee80211_vap_attach(vap, iwn_media_change, ieee80211_media_status, - mac); + ieee80211_vap_attach(vap, ieee80211_media_change, + ieee80211_media_status, mac); ic->ic_opmode = opmode; return vap; } @@ -2882,16 +2883,6 @@ iwn_newassoc(struct ieee80211_node *ni, int isnew) } static int -iwn_media_change(struct ifnet *ifp) -{ - int error; - - error = ieee80211_media_change(ifp); - /* NB: only the fixed rate can change and that doesn't need a reset */ - return (error == ENETRESET ? 0 : error); -} - -static int iwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) { struct iwn_vap *ivp = IWN_VAP(vap); diff --git a/sys/dev/mwl/if_mwl.c b/sys/dev/mwl/if_mwl.c index a33e49324968..be5d279f6e10 100644 --- a/sys/dev/mwl/if_mwl.c +++ b/sys/dev/mwl/if_mwl.c @@ -59,7 +59,7 @@ __FBSDID("$FreeBSD$"); #include <sys/taskqueue.h> #include <machine/bus.h> - + #include <net/if.h> #include <net/if_var.h> #include <net/if_dl.h> @@ -1470,16 +1470,17 @@ mwl_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, static int mwl_media_change(struct ifnet *ifp) { - struct ieee80211vap *vap = ifp->if_softc; + struct ieee80211vap *vap; int error; - error = ieee80211_media_change(ifp); /* NB: only the fixed rate can change and that doesn't need a reset */ - if (error == ENETRESET) { - mwl_setrates(vap); - error = 0; - } - return error; + error = ieee80211_media_change(ifp); + if (error != 0) + return (error); + + vap = ifp->if_softc; + mwl_setrates(vap); + return (0); } #ifdef MWL_DEBUG diff --git a/sys/dev/mwl/if_mwl_pci.c b/sys/dev/mwl/if_mwl_pci.c index 6dd521a6ed9a..bf17fe4750b1 100644 --- a/sys/dev/mwl/if_mwl_pci.c +++ b/sys/dev/mwl/if_mwl_pci.c @@ -55,7 +55,7 @@ __FBSDID("$FreeBSD$"); #include <sys/rman.h> #include <sys/socket.h> - + #include <net/ethernet.h> #include <net/if.h> #include <net/if_media.h> @@ -98,7 +98,6 @@ static const struct mwl_pci_ident mwl_pci_ids[] = { { 0x11ab, 0x2a0c, "Marvell 88W8363" }, { 0x11ab, 0x2a21, "Marvell 88W8363" }, { 0x11ab, 0x2a24, "Marvell 88W8363" }, - { 0, 0, NULL } }; @@ -280,7 +279,6 @@ static device_method_t mwl_pci_methods[] = { DEVMETHOD(device_shutdown, mwl_pci_shutdown), DEVMETHOD(device_suspend, mwl_pci_suspend), DEVMETHOD(device_resume, mwl_pci_resume), - { 0,0 } }; static driver_t mwl_pci_driver = { diff --git a/sys/dev/mwl/mwlreg.h b/sys/dev/mwl/mwlreg.h index 9b64dda9f83a..899b97c21cd0 100644 --- a/sys/dev/mwl/mwlreg.h +++ b/sys/dev/mwl/mwlreg.h @@ -57,7 +57,6 @@ #define MACREG_REG_A2H_INTERRUPT_CLEAR_SEL 0x00000C38 // (From ARM to host) #define MACREG_REG_A2H_INTERRUPT_STATUS_MASK 0x00000C3C // (From ARM to host) - // Map to 0x80000000 on BAR1 #define MACREG_REG_GEN_PTR 0x00000C10 #define MACREG_REG_INT_CODE 0x00000C14 @@ -101,7 +100,6 @@ #define MACREG_A2HRIC_BIT_MASK ISR_SRC_BITS - // Bit definitio for MACREG_REG_H2A_INTERRUPT_CAUSE (H2ARIC) #define MACREG_H2ARIC_BIT_PPA_READY 0x00000001 // bit 0 #define MACREG_H2ARIC_BIT_DOOR_BELL 0x00000002 // bit 1 @@ -341,7 +339,6 @@ struct mwl_rxdesc { #define HostCmd_RESULT_BUSY 0x0004 // System is busy (command ignored) #define HostCmd_RESULT_PARTIAL_DATA 0x0005 // Data buffer is not big enough - /* // Definition of action or option for each command // @@ -377,7 +374,6 @@ struct mwl_rxdesc { #define HostCmd_WEP_KEY_INDEX_MASK 0x3fffffff - // Define action or option for HostCmd_CMD_802_11_RESET #define HostCmd_ACT_HALT 0x0001 #define HostCmd_ACT_RESTART 0x0002 @@ -485,7 +481,6 @@ typedef struct { u_int32_t Enable; /* FALSE: Disable or TRUE: Enable */ } __packed HostCmd_DS_BSS_START; - typedef struct { u_int8_t ElemId; u_int8_t Len; @@ -704,7 +699,7 @@ typedef struct { uint32_t FixedRate; // legacy rate(not index) or an MCS code. uint32_t RetryCount; } __packed FIXED_RATE_ENTRY; - + typedef struct { FWCmdHdr CmdHdr; uint32_t Action; //HostCmd_ACT_GEN_GET 0x0000 @@ -723,7 +718,7 @@ typedef struct { uint32_t EntryCount; FIXED_RATE_ENTRY FixedRateTable[4]; } __packed USE_FIXED_RATE_INFO; - + typedef struct { FWCmdHdr CmdHdr; uint32_t Action; @@ -745,7 +740,6 @@ typedef struct { uint8_t Slot; // Slot=0 if regular, Slot=1 if short. } __packed HostCmd_FW_SET_SLOT; - // Define data structure for HostCmd_CMD_802_11_GET_STAT typedef struct { FWCmdHdr CmdHdr; @@ -778,7 +772,6 @@ typedef struct { uint32_t RxExcludedFrames; } __packed HostCmd_DS_802_11_GET_STAT; - // Define data structure for HostCmd_CMD_MAC_REG_ACCESS typedef struct { FWCmdHdr CmdHdr; @@ -806,7 +799,6 @@ typedef struct { uint8_t Reserverd[3]; } __packed HostCmd_DS_RF_REG_ACCESS; - // Define data structure for HostCmd_CMD_802_11_RADIO_CONTROL typedef struct { FWCmdHdr CmdHdr; @@ -815,7 +807,6 @@ typedef struct { uint16_t RadioOn; } __packed HostCmd_DS_802_11_RADIO_CONTROL; - #define TX_POWER_LEVEL_TOTAL 8 // Define data structure for HostCmd_CMD_802_11_RF_TX_POWER typedef struct { @@ -1141,7 +1132,6 @@ typedef struct { uint8_t ActionData[1]; } __packed HostCmd_FW_UPDATE_ENCRYPTION; - typedef struct { FWCmdHdr CmdHdr; uint32_t ActionType; // ENCR_ACTION_TYPE @@ -1272,8 +1262,6 @@ typedef struct { uint8_t Watchdogbitmap; // for SW/BA } __packed HostCmd_FW_GET_WATCHDOG_BITMAP; - - // Define data structure for HostCmd_CMD_SET_REGION_POWER typedef struct { FWCmdHdr CmdHdr; diff --git a/sys/dev/otus/if_otus.c b/sys/dev/otus/if_otus.c index 3ac3130e7791..df8199901c4f 100644 --- a/sys/dev/otus/if_otus.c +++ b/sys/dev/otus/if_otus.c @@ -90,6 +90,7 @@ SYSCTL_INT(_hw_usb_otus, OID_AUTO, debug, CTLFLAG_RWTUN, &otus_debug, 0, #define OTUS_DEBUG_REGIO 0x00000200 #define OTUS_DEBUG_IRQ 0x00000400 #define OTUS_DEBUG_TXCOMP 0x00000800 +#define OTUS_DEBUG_RX_BUFFER 0x00001000 #define OTUS_DEBUG_ANY 0xffffffff #define OTUS_DPRINTF(sc, dm, ...) \ @@ -130,7 +131,6 @@ static device_attach_t otus_attach; static device_detach_t otus_detach; static int otus_attachhook(struct otus_softc *); -void otus_get_chanlist(struct otus_softc *); static void otus_getradiocaps(struct ieee80211com *, int, int *, struct ieee80211_channel[]); int otus_load_firmware(struct otus_softc *, const char *, @@ -166,7 +166,6 @@ void otus_write(struct otus_softc *, uint32_t, uint32_t); int otus_write_barrier(struct otus_softc *); static struct ieee80211_node *otus_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN]); -int otus_media_change(struct ifnet *); int otus_read_eeprom(struct otus_softc *); void otus_newassoc(struct ieee80211_node *, int); void otus_cmd_rxeof(struct otus_softc *, uint8_t *, int); @@ -394,9 +393,8 @@ otus_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, uvp->newstate = vap->iv_newstate; vap->iv_newstate = otus_newstate; - /* XXX TODO: double-check */ - vap->iv_ampdu_density = IEEE80211_HTCAP_MPDUDENSITY_16; - vap->iv_ampdu_rxmax = IEEE80211_HTCAP_MAXRXAMPDU_32K; + vap->iv_ampdu_density = IEEE80211_HTCAP_MPDUDENSITY_8; + vap->iv_ampdu_rxmax = IEEE80211_HTCAP_MAXRXAMPDU_64K; ieee80211_ratectl_init(vap); @@ -698,6 +696,16 @@ otus_attachhook(struct otus_softc *sc) IEEE80211_ADDR_COPY(ic->ic_macaddr, sc->eeprom.baseEepHeader.macAddr); sc->sc_led_newstate = otus_led_newstate_type3; /* XXX */ + if (sc->txmask == 0x5) + ic->ic_txstream = 2; + else + ic->ic_txstream = 1; + + if (sc->rxmask == 0x5) + ic->ic_rxstream = 2; + else + ic->ic_rxstream = 1; + device_printf(sc->sc_dev, "MAC/BBP AR9170, RF AR%X, MIMO %dT%dR, address %s\n", (sc->capflags & AR5416_OPFLAGS_11A) ? @@ -720,33 +728,21 @@ otus_attachhook(struct otus_softc *sc) IEEE80211_C_WME | /* WME/QoS */ IEEE80211_C_SHSLOT | /* Short slot time supported. */ IEEE80211_C_FF | /* Atheros fast-frames supported. */ - IEEE80211_C_MONITOR | + IEEE80211_C_MONITOR | /* Enable monitor mode */ + IEEE80211_C_SWAMSDUTX | /* Do software A-MSDU TX */ IEEE80211_C_WPA; /* WPA/RSN. */ - /* XXX TODO: 11n */ - + ic->ic_htcaps = + IEEE80211_HTC_HT | #if 0 - if (sc->eeprom.baseEepHeader.opCapFlags & AR5416_OPFLAGS_11G) { - /* Set supported .11b and .11g rates. */ - ic->ic_sup_rates[IEEE80211_MODE_11B] = - ieee80211_std_rateset_11b; - ic->ic_sup_rates[IEEE80211_MODE_11G] = - ieee80211_std_rateset_11g; - } - if (sc->eeprom.baseEepHeader.opCapFlags & AR5416_OPFLAGS_11A) { - /* Set supported .11a rates. */ - ic->ic_sup_rates[IEEE80211_MODE_11A] = - ieee80211_std_rateset_11a; - } + IEEE80211_HTC_AMPDU | #endif + IEEE80211_HTC_AMSDU | + IEEE80211_HTCAP_MAXAMSDU_3839 | + IEEE80211_HTCAP_SMPS_OFF; -#if 0 - /* Build the list of supported channels. */ - otus_get_chanlist(sc); -#else otus_getradiocaps(ic, IEEE80211_CHAN_MAX, &ic->ic_nchans, ic->ic_channels); -#endif ieee80211_ifattach(ic); ic->ic_raw_xmit = otus_raw_xmit; @@ -779,38 +775,6 @@ otus_attachhook(struct otus_softc *sc) return (0); } -void -otus_get_chanlist(struct otus_softc *sc) -{ - struct ieee80211com *ic = &sc->sc_ic; - uint16_t domain; - uint8_t chan; - int i; - - /* XXX regulatory domain. */ - domain = le16toh(sc->eeprom.baseEepHeader.regDmn[0]); - OTUS_DPRINTF(sc, OTUS_DEBUG_RESET, "regdomain=0x%04x\n", domain); - - if (sc->eeprom.baseEepHeader.opCapFlags & AR5416_OPFLAGS_11G) { - for (i = 0; i < 14; i++) { - chan = ar_chans[i]; - ic->ic_channels[chan].ic_freq = - ieee80211_ieee2mhz(chan, IEEE80211_CHAN_2GHZ); - ic->ic_channels[chan].ic_flags = - IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM | - IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ; - } - } - if (sc->eeprom.baseEepHeader.opCapFlags & AR5416_OPFLAGS_11A) { - for (i = 14; i < nitems(ar_chans); i++) { - chan = ar_chans[i]; - ic->ic_channels[chan].ic_freq = - ieee80211_ieee2mhz(chan, IEEE80211_CHAN_5GHZ); - ic->ic_channels[chan].ic_flags = IEEE80211_CHAN_A; - } - } -} - static void otus_getradiocaps(struct ieee80211com *ic, int maxchans, int *nchans, struct ieee80211_channel chans[]) @@ -823,15 +787,13 @@ otus_getradiocaps(struct ieee80211com *ic, if (sc->eeprom.baseEepHeader.opCapFlags & AR5416_OPFLAGS_11G) { setbit(bands, IEEE80211_MODE_11B); setbit(bands, IEEE80211_MODE_11G); -#if 0 - if (sc->sc_ht) - setbit(bands, IEEE80211_MODE_11NG); -#endif + setbit(bands, IEEE80211_MODE_11NG); ieee80211_add_channel_list_2ghz(chans, maxchans, nchans, ar_chans, 14, bands, 0); } if (sc->eeprom.baseEepHeader.opCapFlags & AR5416_OPFLAGS_11A) { setbit(bands, IEEE80211_MODE_11A); + setbit(bands, IEEE80211_MODE_11NA); ieee80211_add_channel_list_5ghz(chans, maxchans, nchans, &ar_chans[14], nitems(ar_chans) - 14, bands, 0); } @@ -1375,35 +1337,6 @@ otus_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN]) M_NOWAIT | M_ZERO); } -#if 0 -int -otus_media_change(struct ifnet *ifp) -{ - struct otus_softc *sc = ifp->if_softc; - struct ieee80211com *ic = &sc->sc_ic; - uint8_t rate, ridx; - int error; - - error = ieee80211_media_change(ifp); - if (error != ENETRESET) - return error; - - if (ic->ic_fixed_rate != -1) { - rate = ic->ic_sup_rates[ic->ic_curmode]. - rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL; - for (ridx = 0; ridx <= OTUS_RIDX_MAX; ridx++) - if (otus_rates[ridx].rate == rate) - break; - sc->fixed_ridx = ridx; - } - - if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING)) - error = otus_init(sc); - - return error; -} -#endif - int otus_read_eeprom(struct otus_softc *sc) { @@ -1587,6 +1520,12 @@ otus_cmd_rxeof(struct otus_softc *sc, uint8_t *buf, int len) } } +/* + * Handle a single MPDU. + * + * This may be a single MPDU, or it may be a sub-frame from an A-MPDU. + * In the latter case some of the header details need to be adjusted. + */ void otus_sub_rxeof(struct otus_softc *sc, uint8_t *buf, int len, struct mbufq *rxq) { @@ -1595,41 +1534,126 @@ otus_sub_rxeof(struct otus_softc *sc, uint8_t *buf, int len, struct mbufq *rxq) #if 0 struct ieee80211_node *ni; #endif - struct ar_rx_tail *tail; + struct ar_rx_macstatus *mac_status = NULL; + struct ar_rx_phystatus *phy_status = NULL; struct ieee80211_frame *wh; struct mbuf *m; - uint8_t *plcp; // int s; - int mlen; - if (__predict_false(len < AR_PLCP_HDR_LEN)) { - OTUS_DPRINTF(sc, OTUS_DEBUG_RXDONE, - "sub-xfer too short %d\n", len); - return; + + if (otus_debug & OTUS_DEBUG_RX_BUFFER) { + device_printf(sc->sc_dev, "%s: %*D\n", + __func__, len, buf, "-"); } - plcp = buf; - /* All bits in the PLCP header are set to 1 for non-MPDU. */ - if (memcmp(plcp, AR_PLCP_HDR_INTR, AR_PLCP_HDR_LEN) == 0) { - otus_cmd_rxeof(sc, plcp + AR_PLCP_HDR_LEN, + /* + * Before any data path stuff - check to see if this is a command + * response. + * + * All bits in the PLCP header are set to 1 for non-MPDU. + */ + if ((len >= AR_PLCP_HDR_LEN) && + memcmp(buf, AR_PLCP_HDR_INTR, AR_PLCP_HDR_LEN) == 0) { + otus_cmd_rxeof(sc, buf + AR_PLCP_HDR_LEN, len - AR_PLCP_HDR_LEN); return; } - /* Received MPDU. */ - if (__predict_false(len < AR_PLCP_HDR_LEN + sizeof (*tail))) { - OTUS_DPRINTF(sc, OTUS_DEBUG_RXDONE, "MPDU too short %d\n", len); + /* + * First step - get the status for the given frame. + * This will tell us whether it's a single MPDU or + * an A-MPDU subframe. + */ + if (len < sizeof(*mac_status)) { + OTUS_DPRINTF(sc, OTUS_DEBUG_RXDONE, + "%s: sub-xfer too short (no mac_status) (len %d)\n", + __func__, len); counter_u64_add(ic->ic_ierrors, 1); return; } - tail = (struct ar_rx_tail *)(plcp + len - sizeof (*tail)); + /* + * Remove the mac_status from the payload length. + * + * Note: cheating, don't reallocate the buffer! + */ + mac_status = (struct ar_rx_macstatus *)(buf + len - sizeof(*mac_status)); + len -= sizeof(*mac_status); + + OTUS_DPRINTF(sc, OTUS_DEBUG_RXDONE, "%s: mac status=0x%x\n", + __func__, mac_status->status); + + /* + * Next - check the MAC status before doing anything else. + * Extract out the PLCP header for single and first frames; + * since there's a single RX path we can shove PLCP headers + * from both into sc->ar_last_rx_plcp[] so it can be reused. + */ + if (((mac_status->status & AR_RX_STATUS_MPDU_MASK) == AR_RX_STATUS_MPDU_SINGLE) || + ((mac_status->status & AR_RX_STATUS_MPDU_MASK) == AR_RX_STATUS_MPDU_FIRST)) { + /* + * Ok, we need to at least have a PLCP header at + * this point. + */ + if (len < AR_PLCP_HDR_LEN) { + OTUS_DPRINTF(sc, OTUS_DEBUG_RXDONE, + "%s sub-xfer too short (no mac+plcp) (len %d\n)", + __func__, len); + counter_u64_add(ic->ic_ierrors, 1); + return; + } + memcpy(sc->ar_last_rx_plcp, buf, AR_PLCP_HDR_LEN); + + /* + * At this point we can just consume the PLCP header. + * The beginning of the frame should thus be data. + */ + buf += AR_PLCP_HDR_LEN; + len -= AR_PLCP_HDR_LEN; + } - /* Discard error frames; don't discard BAD_RA (eg monitor mode); let net80211 do that */ - if (__predict_false((tail->error & ~AR_RX_ERROR_BAD_RA) != 0)) { - OTUS_DPRINTF(sc, OTUS_DEBUG_RXDONE, "error frame 0x%02x\n", tail->error); - if (tail->error & AR_RX_ERROR_FCS) { + /* + * Next - see if we have a PHY status. + * + * The PHY status is at the end of the final A-MPDU subframe + * or a single MPDU frame. + * + * We'll use this to tag frames with noise floor / RSSI + * if they have valid information. + */ + if (((mac_status->status & AR_RX_STATUS_MPDU_MASK) == AR_RX_STATUS_MPDU_SINGLE) || + ((mac_status->status & AR_RX_STATUS_MPDU_MASK) == AR_RX_STATUS_MPDU_LAST)) { + if (len < sizeof(*phy_status)) { + OTUS_DPRINTF(sc, OTUS_DEBUG_RXDONE, + "%s sub-xfer too short (no phy status) (len %d\n)", + __func__, len); + counter_u64_add(ic->ic_ierrors, 1); + return; + } + /* + * Take a pointer to the phy status and remove the length + * from the end of the buffer. + * + * Note: we're cheating here; don't reallocate the buffer! + */ + phy_status = (struct ar_rx_phystatus *) + (buf + len - sizeof(*phy_status)); + len -= sizeof(*phy_status); + } + + /* + * Middle frames just have a MAC status (stripped above.) + * No PHY status, and PLCP is from ar_last_rx_plcp. + */ + + /* + * Discard error frames; don't discard BAD_RA (eg monitor mode); + * let net80211 do that + */ + if (__predict_false((mac_status->error & ~AR_RX_ERROR_BAD_RA) != 0)) { + OTUS_DPRINTF(sc, OTUS_DEBUG_RXDONE, "error frame 0x%02x\n", mac_status->error); + if (mac_status->error & AR_RX_ERROR_FCS) { OTUS_DPRINTF(sc, OTUS_DEBUG_RXDONE, "bad FCS\n"); - } else if (tail->error & AR_RX_ERROR_MMIC) { + } else if (mac_status->error & AR_RX_ERROR_MMIC) { /* Report Michael MIC failures to net80211. */ #if 0 ieee80211_notify_michael_failure(ni->ni_vap, wh, keyidx); @@ -1639,77 +1663,75 @@ otus_sub_rxeof(struct otus_softc *sc, uint8_t *buf, int len, struct mbufq *rxq) counter_u64_add(ic->ic_ierrors, 1); return; } - /* Compute MPDU's length. */ - mlen = len - AR_PLCP_HDR_LEN - sizeof (*tail); - /* Make sure there's room for an 802.11 header + FCS. */ - if (__predict_false(mlen < IEEE80211_MIN_LEN)) { + + /* + * Make sure there's room for an 802.11 header + FCS. + * + * Note: a CTS/ACK is 14 bytes (FC, DUR, RA, FCS). + * Making it IEEE80211_MIN_LEN misses CTS/ACKs. + * + * This won't be tossed at this point; eventually once + * rx radiotap is implemented this will allow for + * CTS/ACK frames. Passing them up to net80211 will + * currently make it angry (too short packets.) + */ + if (len < 2 + 2 + IEEE80211_ADDR_LEN + IEEE80211_CRC_LEN) { + OTUS_DPRINTF(sc, OTUS_DEBUG_RXDONE, + "%s: too short for 802.11 (len %d)\n", + __func__, len); counter_u64_add(ic->ic_ierrors, 1); return; } - mlen -= IEEE80211_CRC_LEN; /* strip 802.11 FCS */ - wh = (struct ieee80211_frame *)(plcp + AR_PLCP_HDR_LEN); + len -= IEEE80211_CRC_LEN; /* strip 802.11 FCS */ + wh = (struct ieee80211_frame *) buf; /* - * TODO: I see > 2KiB buffers in this path; is it A-MSDU or something? + * The firmware does seem to spit out a bunch of frames + * with invalid frame control values here. Just toss them + * rather than letting net80211 get angry and log. */ - m = m_get2(mlen, M_NOWAIT, MT_DATA, M_PKTHDR); + if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) != + IEEE80211_FC0_VERSION_0) { + OTUS_DPRINTF(sc, OTUS_DEBUG_RXDONE, + "%s: invalid 802.11 fc version (firmware bug?)\n", + __func__); + counter_u64_add(ic->ic_ierrors, 1); + return; + } + + m = m_get2(len, M_NOWAIT, MT_DATA, M_PKTHDR); if (m == NULL) { - device_printf(sc->sc_dev, "%s: failed m_get2() (mlen=%d)\n", __func__, mlen); + device_printf(sc->sc_dev, "%s: failed m_get2() (len=%d)\n", + __func__, len); counter_u64_add(ic->ic_ierrors, 1); return; } /* Finalize mbuf. */ - memcpy(mtod(m, uint8_t *), wh, mlen); - m->m_pkthdr.len = m->m_len = mlen; + memcpy(mtod(m, uint8_t *), wh, len); + m->m_pkthdr.len = m->m_len = len; -#if 0 - if (__predict_false(sc->sc_drvbpf != NULL)) { - struct otus_rx_radiotap_header *tap = &sc->sc_rxtap; - struct mbuf mb; - - tap->wr_flags = 0; - tap->wr_antsignal = tail->rssi; - tap->wr_rate = 2; /* In case it can't be found below. */ - switch (tail->status & AR_RX_STATUS_MT_MASK) { - case AR_RX_STATUS_MT_CCK: - switch (plcp[0]) { - case 10: tap->wr_rate = 2; break; - case 20: tap->wr_rate = 4; break; - case 55: tap->wr_rate = 11; break; - case 110: tap->wr_rate = 22; break; - } - if (tail->status & AR_RX_STATUS_SHPREAMBLE) - tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; - break; - case AR_RX_STATUS_MT_OFDM: - switch (plcp[0] & 0xf) { - case 0xb: tap->wr_rate = 12; break; - case 0xf: tap->wr_rate = 18; break; - case 0xa: tap->wr_rate = 24; break; - case 0xe: tap->wr_rate = 36; break; - case 0x9: tap->wr_rate = 48; break; - case 0xd: tap->wr_rate = 72; break; - case 0x8: tap->wr_rate = 96; break; - case 0xc: tap->wr_rate = 108; break; - } - break; - } - mb.m_data = (caddr_t)tap; - mb.m_next = m; - mb.m_nextpkt = NULL; - mb.m_type = 0; - mb.m_flags = 0; - bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_IN); + /* XXX TODO: add setting rx radiotap fields here */ + + /* + * Ok, check the frame length and toss if it's too short + * for net80211. This will toss ACK/CTS. + */ + if (m->m_len < IEEE80211_MIN_LEN) { + /* XXX TODO: add radiotap receive here */ + m_free(m); m = NULL; + return; } -#endif - /* Add RSSI/NF to this mbuf */ + /* Add RSSI to this mbuf if we have a PHY header */ bzero(&rxs, sizeof(rxs)); - rxs.r_flags = IEEE80211_R_NF | IEEE80211_R_RSSI; + rxs.r_flags = IEEE80211_R_NF; rxs.c_nf = sc->sc_nf[0]; /* XXX chain 0 != combined rssi/nf */ - rxs.c_rssi = tail->rssi; + if (phy_status != NULL) { + rxs.r_flags |= IEEE80211_R_RSSI; + rxs.c_rssi = phy_status->rssi; + } /* XXX TODO: add MIMO RSSI/NF as well */ if (ieee80211_add_rx_params(m, &rxs) == 0) { counter_u64_add(ic->ic_ierrors, 1); @@ -1740,10 +1762,18 @@ otus_rxeof(struct usb_xfer *xfer, struct otus_data *data, struct mbufq *rxq) caddr_t buf = data->buf; struct ar_rx_head *head; uint16_t hlen; - int len; + int len, offset = 0; usbd_xfer_status(xfer, &len, NULL, NULL, NULL); + OTUS_DPRINTF(sc, OTUS_DEBUG_RXDONE, + "%s: transfer completed; len=%d\n", + __func__, len); + if (otus_debug & OTUS_DEBUG_RX_BUFFER) { + device_printf(sc->sc_dev, "%s: %*D\n", + __func__, len, buf, "-"); + } + while (len >= sizeof (*head)) { head = (struct ar_rx_head *)buf; if (__predict_false(head->tag != htole16(AR_RX_HEAD_TAG))) { @@ -1752,19 +1782,26 @@ otus_rxeof(struct usb_xfer *xfer, struct otus_data *data, struct mbufq *rxq) break; } hlen = le16toh(head->len); + OTUS_DPRINTF(sc, OTUS_DEBUG_RXDONE, "%s: hlen=%d\n", + __func__, hlen); if (__predict_false(sizeof (*head) + hlen > len)) { OTUS_DPRINTF(sc, OTUS_DEBUG_RXDONE, "xfer too short %d/%d\n", len, hlen); break; } /* Process sub-xfer. */ - otus_sub_rxeof(sc, (uint8_t *)&head[1], hlen, rxq); + otus_sub_rxeof(sc, (uint8_t *) (((uint8_t *) buf) + 4), hlen, rxq); /* Next sub-xfer is aligned on a 32-bit boundary. */ hlen = (sizeof (*head) + hlen + 3) & ~3; + offset += hlen; + OTUS_DPRINTF(sc, OTUS_DEBUG_RXDONE, + "%s: rounded size is %d, next packet starts at %d\n", + __func__, hlen, offset); buf += hlen; len -= hlen; } + OTUS_DPRINTF(sc, OTUS_DEBUG_RXDONE, "%s: done!\n", __func__); } static void @@ -2090,6 +2127,11 @@ otus_rate_to_hw_rate(struct otus_softc *sc, uint8_t rate) is_2ghz = !! (IEEE80211_IS_CHAN_2GHZ(sc->sc_ic.ic_curchan)); + /* MCS check */ + if (rate & 0x80) { + return rate; + } + switch (rate) { /* CCK */ case 2: @@ -2125,12 +2167,17 @@ otus_rate_to_hw_rate(struct otus_softc *sc, uint8_t rate) return (0x0); /* 1MB CCK */ else return (0xb); /* 6MB OFDM */ - - /* XXX TODO: HT */ } } static int +otus_hw_rate_is_ht(struct otus_softc *sc, uint8_t hw_rate) +{ + + return !! (hw_rate & 0x80); +} + +static int otus_hw_rate_is_ofdm(struct otus_softc *sc, uint8_t hw_rate) { @@ -2258,7 +2305,10 @@ otus_tx(struct otus_softc *sc, struct ieee80211_node *ni, struct mbuf *m, if (!ismcast) { if (m->m_pkthdr.len + IEEE80211_CRC_LEN >= vap->iv_rtsthreshold) macctl |= AR_TX_MAC_RTS; - else if (ic->ic_flags & IEEE80211_F_USEPROT) { + else if (otus_hw_rate_is_ht(sc, rate)) { + if (ic->ic_htprotmode == IEEE80211_PROT_RTSCTS) + macctl |= AR_TX_MAC_RTS; + } else if (ic->ic_flags & IEEE80211_F_USEPROT) { if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) macctl |= AR_TX_MAC_CTS; else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS) @@ -2266,8 +2316,15 @@ otus_tx(struct otus_softc *sc, struct ieee80211_node *ni, struct mbuf *m, } } - phyctl |= AR_TX_PHY_MCS(rate); - if (otus_hw_rate_is_ofdm(sc, rate)) { + phyctl |= AR_TX_PHY_MCS(rate & 0x7f); /* Note: MCS rates are 0x80 and above */ + if (otus_hw_rate_is_ht(sc, rate)) { + phyctl |= AR_TX_PHY_MT_HT; + /* Always use all tx antennas for now, just to be safe */ + phyctl |= AR_TX_PHY_ANTMSK(sc->txmask); + + /* Heavy clip */ + phyctl |= (rate & 0x7) << AR_TX_PHY_TX_HEAVY_CLIP_SHIFT; + } else if (otus_hw_rate_is_ofdm(sc, rate)) { phyctl |= AR_TX_PHY_MT_OFDM; /* Always use all tx antennas for now, just to be safe */ phyctl |= AR_TX_PHY_ANTMSK(sc->txmask); @@ -2283,7 +2340,6 @@ otus_tx(struct otus_softc *sc, struct ieee80211_node *ni, struct mbuf *m, if (!(macctl & AR_TX_MAC_NOACK)) OTUS_NODE(ni)->tx_done++; - /* Fill Tx descriptor. */ head = (struct ar_tx_head *)data->buf; head->len = htole16(m->m_pkthdr.len + IEEE80211_CRC_LEN); @@ -2308,63 +2364,63 @@ otus_tx(struct otus_softc *sc, struct ieee80211_node *ni, struct mbuf *m, return 0; } +static u_int +otus_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt) +{ + uint32_t val, *hashes = arg; + + val = le32dec(LLADDR(sdl) + 4); + /* Get address byte 5 */ + val = val & 0x0000ff00; + val = val >> 8; + + /* As per below, shift it >> 2 to get only 6 bits */ + val = val >> 2; + if (val < 32) + hashes[0] |= 1 << val; + else + hashes[1] |= 1 << (val - 32); + + return (1); +} + + int otus_set_multi(struct otus_softc *sc) { - uint32_t lo, hi; struct ieee80211com *ic = &sc->sc_ic; + uint32_t hashes[2]; int r; if (ic->ic_allmulti > 0 || ic->ic_promisc > 0 || ic->ic_opmode == IEEE80211_M_MONITOR) { - lo = 0xffffffff; - hi = 0xffffffff; + hashes[0] = 0xffffffff; + hashes[1] = 0xffffffff; } else { struct ieee80211vap *vap; - struct ifnet *ifp; - struct ifmultiaddr *ifma; - - lo = hi = 0; - TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { - ifp = vap->iv_ifp; - if_maddr_rlock(ifp); - CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { - caddr_t dl; - uint32_t val; - - dl = LLADDR((struct sockaddr_dl *) ifma->ifma_addr); - val = le32dec(dl + 4); - /* Get address byte 5 */ - val = val & 0x0000ff00; - val = val >> 8; - - /* As per below, shift it >> 2 to get only 6 bits */ - val = val >> 2; - if (val < 32) - lo |= 1 << val; - else - hi |= 1 << (val - 32); - } - if_maddr_runlock(ifp); - } + + hashes[0] = hashes[1] = 0; + TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) + if_foreach_llmaddr(vap->iv_ifp, otus_hash_maddr, + hashes); } #if 0 /* XXX openbsd code */ while (enm != NULL) { bit = enm->enm_addrlo[5] >> 2; if (bit < 32) - lo |= 1 << bit; + hashes[0] |= 1 << bit; else - hi |= 1 << (bit - 32); + hashes[1] |= 1 << (bit - 32); ETHER_NEXT_MULTI(step, enm); } #endif - hi |= 1U << 31; /* Make sure the broadcast bit is set. */ + hashes[1] |= 1U << 31; /* Make sure the broadcast bit is set. */ OTUS_LOCK(sc); - otus_write(sc, AR_MAC_REG_GROUP_HASH_TBL_L, lo); - otus_write(sc, AR_MAC_REG_GROUP_HASH_TBL_H, hi); + otus_write(sc, AR_MAC_REG_GROUP_HASH_TBL_L, hashes[0]); + otus_write(sc, AR_MAC_REG_GROUP_HASH_TBL_H, hashes[1]); r = otus_write_barrier(sc); /* XXX operating mode? filter? */ OTUS_UNLOCK(sc); @@ -2459,6 +2515,22 @@ otus_updateslot(struct otus_softc *sc) (void)otus_write_barrier(sc); } +/* + * Things to do based on 2GHz or 5GHz: + * + * + slottime + * + dyn_sifs_ack + * + rts_cts_rate + * + slot time + * + mac_rates + * + mac_tpc + * + * And in the transmit path + * + tpc: carl9170_tx_rate_tpc_chains + * + carl9170_tx_physet() + * + disable short premable tx + */ + int otus_init_mac(struct otus_softc *sc) { @@ -2637,10 +2709,17 @@ otus_program_phy(struct otus_softc *sc, struct ieee80211_channel *c) int error, i; /* Select PHY programming based on band and bandwidth. */ - if (IEEE80211_IS_CHAN_2GHZ(c)) - vals = ar5416_phy_vals_2ghz_20mhz; - else - vals = ar5416_phy_vals_5ghz_20mhz; + if (IEEE80211_IS_CHAN_2GHZ(c)) { + if (IEEE80211_IS_CHAN_HT40(c)) + vals = ar5416_phy_vals_2ghz_40mhz; + else + vals = ar5416_phy_vals_2ghz_20mhz; + } else { + if (IEEE80211_IS_CHAN_HT40(c)) + vals = ar5416_phy_vals_5ghz_40mhz; + else + vals = ar5416_phy_vals_5ghz_20mhz; + } for (i = 0; i < nitems(ar5416_phy_regs); i++) otus_write(sc, AR_PHY(ar5416_phy_regs[i]), vals[i]); sc->phy_vals = vals; diff --git a/sys/dev/otus/if_otusreg.h b/sys/dev/otus/if_otusreg.h index e5100841ad87..190bf19eb2ae 100644 --- a/sys/dev/otus/if_otusreg.h +++ b/sys/dev/otus/if_otusreg.h @@ -201,12 +201,17 @@ struct ar_tx_head { uint32_t phyctl; /* Modulation type. */ +#define AR_TX_PHY_MT_SHIFT 0 /* 0:1 - PHY mode */ #define AR_TX_PHY_MT_CCK 0 #define AR_TX_PHY_MT_OFDM 1 #define AR_TX_PHY_MT_HT 2 -#define AR_TX_PHY_GF (1 << 2) -#define AR_TX_PHY_BW_SHIFT 3 -#define AR_TX_PHY_TPC_SHIFT 9 +#define AR_TX_PHY_GF (1 << 2) /* 2 - greenfield */ +#define AR_TX_PHY_BW_SHIFT 3 /* 4:3 - bandwidth */ +#define AR_TX_PHY_BW_20MHZ 0 +#define AR_TX_PHY_BW_40MHZ 2 +#define AR_TX_PHY_BW_40MHZ_DUP 3 +#define AR_TX_PHY_TX_HEAVY_CLIP_SHIFT 6 /* 9:6 - heavy clip */ +#define AR_TX_PHY_TPC_SHIFT 9 /* 14:9 - TX power */ #define AR_TX_PHY_ANTMSK(msk) ((msk) << 15) #define AR_TX_PHY_MCS(mcs) ((mcs) << 18) #define AR_TX_PHY_SHGI (1U << 31) @@ -220,15 +225,11 @@ struct ar_rx_head { } __packed; /* Rx descriptor. */ -struct ar_rx_tail { - uint8_t rssi_ant[3]; - uint8_t rssi_ant_ext[3]; - uint8_t rssi; /* Combined RSSI. */ - uint8_t evm[2][6]; /* Error Vector Magnitude. */ - uint8_t phy_err; - uint8_t sa_idx; - uint8_t da_idx; - uint8_t error; + +struct ar_rx_macstatus { + uint8_t sa_idx; + uint8_t da_idx; + uint8_t error; #define AR_RX_ERROR_TIMEOUT (1 << 0) #define AR_RX_ERROR_OVERRUN (1 << 1) #define AR_RX_ERROR_DECRYPT (1 << 2) @@ -236,14 +237,26 @@ struct ar_rx_tail { #define AR_RX_ERROR_BAD_RA (1 << 4) #define AR_RX_ERROR_PLCP (1 << 5) #define AR_RX_ERROR_MMIC (1 << 6) - - uint8_t status; + uint8_t status; /* Modulation type (same as AR_TX_PHY_MT). */ #define AR_RX_STATUS_MT_MASK 0x3 #define AR_RX_STATUS_MT_CCK 0 #define AR_RX_STATUS_MT_OFDM 1 #define AR_RX_STATUS_MT_HT 2 #define AR_RX_STATUS_SHPREAMBLE (1 << 3) +#define AR_RX_STATUS_MPDU_MASK 0x30 +#define AR_RX_STATUS_MPDU_SINGLE 0x00 +#define AR_RX_STATUS_MPDU_LAST 0x10 +#define AR_RX_STATUS_MPDU_FIRST 0x20 +#define AR_RX_STATUS_MPDU_MIDDLE 0x30 +} __packed; + +struct ar_rx_phystatus { + uint8_t rssi_ant[3]; + uint8_t rssi_ant_ext[3]; + uint8_t rssi; /* Combined RSSI. */ + uint8_t evm[2][6]; /* Error Vector Magnitude. */ + uint8_t phy_err; } __packed; #define AR_PLCP_HDR_LEN 12 @@ -468,7 +481,6 @@ static const uint32_t ar5416_phy_vals_5ghz_20mhz[] = { 0x5fd80682, 0x7fe00482, 0x7f3c7bba, 0xf3307ff0 }; -#ifdef notyet static const uint32_t ar5416_phy_vals_5ghz_40mhz[] = { 0x00000007, 0x000003c4, 0x00000000, 0xad848e19, 0x7d14e000, 0x9c0a9f6b, 0x00000090, 0x00000000, 0x02020200, 0x00000e0e, @@ -537,9 +549,7 @@ static const uint32_t ar5416_phy_vals_5ghz_40mhz[] = { 0x17601685, 0x1f801104, 0x37a00c03, 0x3fc40883, 0x57c00803, 0x5fd80682, 0x7fe00482, 0x7f3c7bba, 0xf3307ff0 }; -#endif -#ifdef notyet static const uint32_t ar5416_phy_vals_2ghz_40mhz[] = { 0x00000007, 0x000003c4, 0x00000000, 0xad848e19, 0x7d14e000, 0x9c0a9f6b, 0x00000090, 0x00000000, 0x02020200, 0x00000e0e, @@ -608,7 +618,6 @@ static const uint32_t ar5416_phy_vals_2ghz_40mhz[] = { 0x17601685, 0x1f801104, 0x37a00c03, 0x3fc40883, 0x57c00803, 0x5fd80682, 0x7fe00482, 0x7f3c7bba, 0xf3307ff0 }; -#endif static const uint32_t ar5416_phy_vals_2ghz_20mhz[] = { 0x00000007, 0x00000300, 0x00000000, 0xad848e19, 0x7d14e000, @@ -1054,6 +1063,9 @@ struct otus_softc { struct usb_xfer *sc_xfer[OTUS_N_XFER]; + /* Last seen PLCP header; for A-MPDU decap */ + uint8_t ar_last_rx_plcp[AR_PLCP_HDR_LEN]; + STAILQ_HEAD(, otus_data) sc_rx_active; STAILQ_HEAD(, otus_data) sc_rx_inactive; STAILQ_HEAD(, otus_data) sc_tx_active[OTUS_N_XFER]; diff --git a/sys/dev/rtwn/if_rtwn.c b/sys/dev/rtwn/if_rtwn.c index e410010cc433..ae29ad700310 100644 --- a/sys/dev/rtwn/if_rtwn.c +++ b/sys/dev/rtwn/if_rtwn.c @@ -79,7 +79,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8192c/r92c_reg.h> - static void rtwn_radiotap_attach(struct rtwn_softc *); static void rtwn_vap_decrement_counters(struct rtwn_softc *, enum ieee80211_opmode, int); @@ -1525,14 +1524,17 @@ rtwn_getradiocaps(struct ieee80211com *ic, { struct rtwn_softc *sc = ic->ic_softc; uint8_t bands[IEEE80211_MODE_BYTES]; - int i; + int cbw_flags, i; + + cbw_flags = (ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40) ? + NET80211_CBW_FLAG_HT40 : 0; memset(bands, 0, sizeof(bands)); setbit(bands, IEEE80211_MODE_11B); setbit(bands, IEEE80211_MODE_11G); setbit(bands, IEEE80211_MODE_11NG); ieee80211_add_channels_default_2ghz(chans, maxchans, nchans, - bands, !!(ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40)); + bands, cbw_flags); /* XXX workaround add_channel_list() limitations */ setbit(bands, IEEE80211_MODE_11A); @@ -1543,7 +1545,7 @@ rtwn_getradiocaps(struct ieee80211com *ic, ieee80211_add_channel_list_5ghz(chans, maxchans, nchans, sc->chan_list_5ghz[i], sc->chan_num_5ghz[i], bands, - !!(ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40)); + cbw_flags); } } diff --git a/sys/dev/rtwn/if_rtwn_beacon.c b/sys/dev/rtwn/if_rtwn_beacon.c index 99a1ad80ff91..63eb7a00730a 100644 --- a/sys/dev/rtwn/if_rtwn_beacon.c +++ b/sys/dev/rtwn/if_rtwn_beacon.c @@ -47,7 +47,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8192c/r92c_reg.h> - static void rtwn_reset_beacon_valid(struct rtwn_softc *sc, int id) { diff --git a/sys/dev/rtwn/if_rtwn_calib.c b/sys/dev/rtwn/if_rtwn_calib.c index 5c3ed7e6491e..7eb7c5c021c1 100644 --- a/sys/dev/rtwn/if_rtwn_calib.c +++ b/sys/dev/rtwn/if_rtwn_calib.c @@ -49,7 +49,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/if_rtwn_debug.h> #include <dev/rtwn/if_rtwn_task.h> - static void rtwn_temp_calib(struct rtwn_softc *sc) { diff --git a/sys/dev/rtwn/if_rtwn_cam.c b/sys/dev/rtwn/if_rtwn_cam.c index 539fb411f770..6ee630533675 100644 --- a/sys/dev/rtwn/if_rtwn_cam.c +++ b/sys/dev/rtwn/if_rtwn_cam.c @@ -52,7 +52,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8192c/r92c_reg.h> - void rtwn_init_cam(struct rtwn_softc *sc) { diff --git a/sys/dev/rtwn/if_rtwn_efuse.c b/sys/dev/rtwn/if_rtwn_efuse.c index b14f97377dd4..b2ec82e37972 100644 --- a/sys/dev/rtwn/if_rtwn_efuse.c +++ b/sys/dev/rtwn/if_rtwn_efuse.c @@ -51,7 +51,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8192c/r92c_reg.h> - static int rtwn_efuse_switch_power(struct rtwn_softc *sc) { diff --git a/sys/dev/rtwn/if_rtwn_fw.c b/sys/dev/rtwn/if_rtwn_fw.c index 5cc71d2b8043..75ff59dd13e9 100644 --- a/sys/dev/rtwn/if_rtwn_fw.c +++ b/sys/dev/rtwn/if_rtwn_fw.c @@ -53,7 +53,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8192c/r92c_reg.h> - #ifndef RTWN_WITHOUT_UCODE static int rtwn_fw_loadpage(struct rtwn_softc *sc, int page, const uint8_t *buf, diff --git a/sys/dev/rtwn/if_rtwn_fw.h b/sys/dev/rtwn/if_rtwn_fw.h index 41e84ee82f17..50d2aa31b148 100644 --- a/sys/dev/rtwn/if_rtwn_fw.h +++ b/sys/dev/rtwn/if_rtwn_fw.h @@ -53,7 +53,6 @@ struct r92c_fw_hdr { uint32_t reserved5; } __packed; - int rtwn_load_firmware(struct rtwn_softc *); #endif /* IF_RTWN_FW_H */ diff --git a/sys/dev/rtwn/if_rtwn_ridx.h b/sys/dev/rtwn/if_rtwn_ridx.h index 2e6f8d98456f..902c470d25bc 100644 --- a/sys/dev/rtwn/if_rtwn_ridx.h +++ b/sys/dev/rtwn/if_rtwn_ridx.h @@ -47,7 +47,6 @@ #define RTWN_RATE_IS_OFDM(rate) \ ((rate) >= RTWN_RIDX_OFDM6 && (rate) != RTWN_RIDX_UNKNOWN) - static const uint8_t ridx2rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 }; diff --git a/sys/dev/rtwn/if_rtwn_rx.c b/sys/dev/rtwn/if_rtwn_rx.c index 21609e31515c..cc7d96151522 100644 --- a/sys/dev/rtwn/if_rtwn_rx.c +++ b/sys/dev/rtwn/if_rtwn_rx.c @@ -54,7 +54,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8192c/r92c_reg.h> - void rtwn_get_rates(struct rtwn_softc *sc, const struct ieee80211_rateset *rs, const struct ieee80211_htrateset *rs_ht, uint32_t *rates_p, @@ -366,6 +365,18 @@ rtwn_get_multi_pos(const uint8_t maddr[]) return (pos); } +static u_int +rtwm_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt) +{ + uint32_t *mfilt = arg; + uint8_t pos; + + pos = rtwn_get_multi_pos(LLADDR(sdl)); + mfilt[pos / 32] |= (1 << (pos % 32)); + + return (1); +} + void rtwn_set_multi(struct rtwn_softc *sc) { @@ -377,32 +388,16 @@ rtwn_set_multi(struct rtwn_softc *sc) /* general structure was copied from ath(4). */ if (ic->ic_allmulti == 0) { struct ieee80211vap *vap; - struct ifnet *ifp; - struct ifmultiaddr *ifma; /* * Merge multicast addresses to form the hardware filter. */ mfilt[0] = mfilt[1] = 0; - TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { - ifp = vap->iv_ifp; - if_maddr_rlock(ifp); - CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { - caddr_t dl; - uint8_t pos; - - dl = LLADDR((struct sockaddr_dl *) - ifma->ifma_addr); - pos = rtwn_get_multi_pos(dl); - - mfilt[pos / 32] |= (1 << (pos % 32)); - } - if_maddr_runlock(ifp); - } + TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) + if_foreach_llmaddr(vap->iv_ifp, rtwm_hash_maddr, mfilt); } else mfilt[0] = mfilt[1] = ~0; - rtwn_write_4(sc, R92C_MAR + 0, mfilt[0]); rtwn_write_4(sc, R92C_MAR + 4, mfilt[1]); diff --git a/sys/dev/rtwn/if_rtwn_rx.h b/sys/dev/rtwn/if_rtwn_rx.h index 49897eb956b9..ecfe2e0abdd3 100644 --- a/sys/dev/rtwn/if_rtwn_rx.h +++ b/sys/dev/rtwn/if_rtwn_rx.h @@ -21,7 +21,6 @@ #define RTWN_NOISE_FLOOR -95 - void rtwn_get_rates(struct rtwn_softc *, const struct ieee80211_rateset *, const struct ieee80211_htrateset *, uint32_t *, int *, int); void rtwn_set_basicrates(struct rtwn_softc *, uint32_t); diff --git a/sys/dev/rtwn/if_rtwn_task.c b/sys/dev/rtwn/if_rtwn_task.c index 87f695f1020c..89822cf2a25b 100644 --- a/sys/dev/rtwn/if_rtwn_task.c +++ b/sys/dev/rtwn/if_rtwn_task.c @@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/if_rtwn_task.h> - static void rtwn_cmdq_cb(void *arg, int pending) { diff --git a/sys/dev/rtwn/if_rtwn_tx.c b/sys/dev/rtwn/if_rtwn_tx.c index 69ce3ae7c495..32bdd1b6b3f0 100644 --- a/sys/dev/rtwn/if_rtwn_tx.c +++ b/sys/dev/rtwn/if_rtwn_tx.c @@ -56,7 +56,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/if_rtwn_ridx.h> #include <dev/rtwn/if_rtwn_tx.h> - void rtwn_drain_mbufq(struct rtwn_softc *sc) { diff --git a/sys/dev/rtwn/if_rtwnreg.h b/sys/dev/rtwn/if_rtwnreg.h index 00903d884bcb..b1eac291c49d 100644 --- a/sys/dev/rtwn/if_rtwnreg.h +++ b/sys/dev/rtwn/if_rtwnreg.h @@ -26,7 +26,6 @@ #define R92C_H2C_NBOX 4 - /* Common part of Tx descriptor (named only!). */ struct rtwn_tx_desc_common { uint16_t pktlen; @@ -115,7 +114,6 @@ struct rtwn_rx_stat_pci { #define RW(var, field, val) \ (((var) & ~field##_M) | SM(field, val)) - #define RTWN_MAX_CONDITIONS 3 /* @@ -155,7 +153,6 @@ struct rtwn_rf_prog { const struct rtwn_rf_prog *next; }; - /* XXX move to net80211. */ static __inline int rtwn_chan2centieee(const struct ieee80211_channel *c) diff --git a/sys/dev/rtwn/if_rtwnvar.h b/sys/dev/rtwn/if_rtwnvar.h index fe31aa5447cb..b63d4ddf2902 100644 --- a/sys/dev/rtwn/if_rtwnvar.h +++ b/sys/dev/rtwn/if_rtwnvar.h @@ -80,7 +80,6 @@ struct rtwn_tx_phystat { uint32_t phydw[RTWN_PHY_STATUS_SIZE / sizeof(uint32_t)]; }; - struct rtwn_softc; union sec_param { @@ -423,7 +422,6 @@ MALLOC_DECLARE(M_RTWN_PRIV); #define RTWN_NT_LOCK_INITIALIZED(sc) mtx_initialized(&(sc)->nt_mtx) #define RTWN_NT_LOCK_DESTROY(sc) mtx_destroy(&(sc)->nt_mtx) - void rtwn_sysctlattach(struct rtwn_softc *); int rtwn_attach(struct rtwn_softc *); @@ -431,7 +429,6 @@ void rtwn_detach(struct rtwn_softc *); void rtwn_resume(struct rtwn_softc *); void rtwn_suspend(struct rtwn_softc *); - /* Interface-specific. */ #define rtwn_write_1(_sc, _addr, _val) \ (((_sc)->sc_write_1)((_sc), (_addr), (_val))) @@ -591,7 +588,6 @@ void rtwn_suspend(struct rtwn_softc *); #define rtwn_init_bcnq1_boundary(_sc) \ (((_sc)->sc_init_bcnq1_boundary)((_sc))) - /* * Methods to access subfields in registers. */ diff --git a/sys/dev/rtwn/pci/rtwn_pci_attach.c b/sys/dev/rtwn/pci/rtwn_pci_attach.c index a7a6e849fa09..efa6bc01501e 100644 --- a/sys/dev/rtwn/pci/rtwn_pci_attach.c +++ b/sys/dev/rtwn/pci/rtwn_pci_attach.c @@ -63,7 +63,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8192c/pci/r92ce_reg.h> - static device_probe_t rtwn_pci_probe; static device_attach_t rtwn_pci_attach; static device_detach_t rtwn_pci_detach; @@ -92,7 +91,6 @@ static void rtwn_pci_beacon_update_end(struct rtwn_softc *, struct ieee80211vap *); static void rtwn_pci_attach_methods(struct rtwn_softc *); - static const struct rtwn_pci_ident * rtwn_pci_probe_sub(device_t dev) { diff --git a/sys/dev/rtwn/pci/rtwn_pci_reg.c b/sys/dev/rtwn/pci/rtwn_pci_reg.c index 6fe188c3f76d..0ee417acbd73 100644 --- a/sys/dev/rtwn/pci/rtwn_pci_reg.c +++ b/sys/dev/rtwn/pci/rtwn_pci_reg.c @@ -50,7 +50,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/pci/rtwn_pci_var.h> #include <dev/rtwn/pci/rtwn_pci_reg.h> - int rtwn_pci_write_1(struct rtwn_softc *sc, uint16_t addr, uint8_t val) { diff --git a/sys/dev/rtwn/pci/rtwn_pci_rx.c b/sys/dev/rtwn/pci/rtwn_pci_rx.c index 362856c4c35a..df95ec701b72 100644 --- a/sys/dev/rtwn/pci/rtwn_pci_rx.c +++ b/sys/dev/rtwn/pci/rtwn_pci_rx.c @@ -56,7 +56,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/pci/rtwn_pci_var.h> #include <dev/rtwn/pci/rtwn_pci_rx.h> - void rtwn_pci_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nsegs, int error) diff --git a/sys/dev/rtwn/pci/rtwn_pci_tx.c b/sys/dev/rtwn/pci/rtwn_pci_tx.c index 434e0488a9d1..6dd84f367212 100644 --- a/sys/dev/rtwn/pci/rtwn_pci_tx.c +++ b/sys/dev/rtwn/pci/rtwn_pci_tx.c @@ -57,7 +57,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8192c/pci/r92ce_reg.h> - static struct mbuf * rtwn_mbuf_defrag(struct mbuf *m0, int how) { diff --git a/sys/dev/rtwn/pci/rtwn_pci_var.h b/sys/dev/rtwn/pci/rtwn_pci_var.h index 95b2effe55d4..82541767edaf 100644 --- a/sys/dev/rtwn/pci/rtwn_pci_var.h +++ b/sys/dev/rtwn/pci/rtwn_pci_var.h @@ -101,7 +101,6 @@ enum { (RTWN_PCI_INTR_RX_ERROR | RTWN_PCI_INTR_RX_OVERFLOW | \ RTWN_PCI_INTR_RX_DESC_UNAVAIL | RTWN_PCI_INTR_RX_DONE) - struct rtwn_pci_softc { struct rtwn_softc pc_sc; /* must be the first */ diff --git a/sys/dev/rtwn/rtl8188e/pci/r88ee.h b/sys/dev/rtwn/rtl8188e/pci/r88ee.h index e011dc1edf7d..319d9c69952b 100644 --- a/sys/dev/rtwn/rtl8188e/pci/r88ee.h +++ b/sys/dev/rtwn/rtl8188e/pci/r88ee.h @@ -21,7 +21,6 @@ #include <dev/rtwn/rtl8188e/r88e.h> - /* * Global definitions. */ @@ -33,7 +32,6 @@ (R88EE_PUBQ_NPAGES + R88EE_HPQ_NPAGES + \ R88EE_NPQ_NPAGES + R88EE_LPQ_NPAGES) - /* * Function declarations. */ @@ -50,4 +48,3 @@ void r88ee_start_xfers(struct rtwn_softc *); void r88ee_post_init(struct rtwn_softc *); #endif /* RTL8188EE_H */ - diff --git a/sys/dev/rtwn/rtl8188e/pci/r88ee_reg.h b/sys/dev/rtwn/rtl8188e/pci/r88ee_reg.h index 96fbe888ac48..a6c743c6771c 100644 --- a/sys/dev/rtwn/rtl8188e/pci/r88ee_reg.h +++ b/sys/dev/rtwn/rtl8188e/pci/r88ee_reg.h @@ -23,4 +23,3 @@ #include <dev/rtwn/rtl8188e/r88e_reg.h> #endif /* R88EE_REG_H */ - diff --git a/sys/dev/rtwn/rtl8188e/r88e.h b/sys/dev/rtwn/rtl8188e/r88e.h index ce9fa19a87b5..b6cd6053d015 100644 --- a/sys/dev/rtwn/rtl8188e/r88e.h +++ b/sys/dev/rtwn/rtl8188e/r88e.h @@ -33,7 +33,6 @@ #define R88E_CALIB_THRESHOLD 4 - /* * Function declarations. */ diff --git a/sys/dev/rtwn/rtl8188e/r88e_beacon.c b/sys/dev/rtwn/rtl8188e/r88e_beacon.c index 4c29d37fab24..affc768ae035 100644 --- a/sys/dev/rtwn/rtl8188e/r88e_beacon.c +++ b/sys/dev/rtwn/rtl8188e/r88e_beacon.c @@ -45,7 +45,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8188e/r88e.h> #include <dev/rtwn/rtl8188e/r88e_reg.h> - void r88e_beacon_enable(struct rtwn_softc *sc, int id, int enable) { diff --git a/sys/dev/rtwn/rtl8188e/r88e_calib.c b/sys/dev/rtwn/rtl8188e/r88e_calib.c index 4d0dffa93910..b4de1138948e 100644 --- a/sys/dev/rtwn/rtl8188e/r88e_calib.c +++ b/sys/dev/rtwn/rtl8188e/r88e_calib.c @@ -47,7 +47,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8188e/r88e.h> #include <dev/rtwn/rtl8188e/r88e_reg.h> - /* Registers to save and restore during IQ calibration. */ struct r88e_iq_cal_reg_vals { uint32_t adda[16]; diff --git a/sys/dev/rtwn/rtl8188e/r88e_chan.c b/sys/dev/rtwn/rtl8188e/r88e_chan.c index 7e33fe887786..be2271c6f51c 100644 --- a/sys/dev/rtwn/rtl8188e/r88e_chan.c +++ b/sys/dev/rtwn/rtl8188e/r88e_chan.c @@ -56,7 +56,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8188e/r88e_priv.h> #include <dev/rtwn/rtl8188e/r88e_reg.h> - static int r88e_get_power_group(struct rtwn_softc *sc, struct ieee80211_channel *c) { diff --git a/sys/dev/rtwn/rtl8188e/r88e_fw.c b/sys/dev/rtwn/rtl8188e/r88e_fw.c index dbce406b8b90..ea74252fccb1 100644 --- a/sys/dev/rtwn/rtl8188e/r88e_fw.c +++ b/sys/dev/rtwn/rtl8188e/r88e_fw.c @@ -53,7 +53,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8188e/r88e_reg.h> #include <dev/rtwn/rtl8188e/r88e_fw_cmd.h> - #ifndef RTWN_WITHOUT_UCODE int r88e_fw_cmd(struct rtwn_softc *sc, uint8_t id, const void *buf, int len) diff --git a/sys/dev/rtwn/rtl8188e/r88e_init.c b/sys/dev/rtwn/rtl8188e/r88e_init.c index 99796c5f074a..8c13057e03bf 100644 --- a/sys/dev/rtwn/rtl8188e/r88e_init.c +++ b/sys/dev/rtwn/rtl8188e/r88e_init.c @@ -55,7 +55,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8188e/r88e.h> #include <dev/rtwn/rtl8188e/r88e_reg.h> - static void r88e_crystalcap_write(struct rtwn_softc *sc) { diff --git a/sys/dev/rtwn/rtl8188e/r88e_led.c b/sys/dev/rtwn/rtl8188e/r88e_led.c index 2bbcdb15cab6..3c93a2b78958 100644 --- a/sys/dev/rtwn/rtl8188e/r88e_led.c +++ b/sys/dev/rtwn/rtl8188e/r88e_led.c @@ -49,7 +49,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8188e/r88e.h> #include <dev/rtwn/rtl8188e/r88e_reg.h> - void r88e_set_led(struct rtwn_softc *sc, int led, int on) { diff --git a/sys/dev/rtwn/rtl8188e/r88e_priv.h b/sys/dev/rtwn/rtl8188e/r88e_priv.h index 8ec5502d846a..81d82c71d7b3 100644 --- a/sys/dev/rtwn/rtl8188e/r88e_priv.h +++ b/sys/dev/rtwn/rtl8188e/r88e_priv.h @@ -33,7 +33,6 @@ struct rtwn_r88e_txpwr { int8_t bw20_tx_pwr_diff; }; - /* * MAC initialization values. */ diff --git a/sys/dev/rtwn/rtl8188e/r88e_reg.h b/sys/dev/rtwn/rtl8188e/r88e_reg.h index 94b9a66053a1..d578373f7551 100644 --- a/sys/dev/rtwn/rtl8188e/r88e_reg.h +++ b/sys/dev/rtwn/rtl8188e/r88e_reg.h @@ -44,7 +44,6 @@ #define R88E_TX_RPT_TIME 0x4f0 #define R88E_SCH_TXCMD 0x5f8 - /* Bits for R88E_HIMR. */ #define R88E_HIMR_ROK 0x00000001 /* receive DMA OK */ #define R88E_HIMR_RDU 0x00000002 /* Rx descriptor unavailable */ @@ -100,7 +99,6 @@ /* Bits for R92C_SECCFG. */ #define R88E_SECCFG_CHK_KEYID 0x0100 - /* * Baseband registers. */ @@ -108,7 +106,6 @@ #define R88E_LSSI_PARAM_ADDR_M 0x0ff00000 #define R88E_LSSI_PARAM_ADDR_S 20 - /* * RF (6052) registers. */ diff --git a/sys/dev/rtwn/rtl8188e/r88e_rf.c b/sys/dev/rtwn/rtl8188e/r88e_rf.c index a836f138aeb5..e5966a4cc0a4 100644 --- a/sys/dev/rtwn/rtl8188e/r88e_rf.c +++ b/sys/dev/rtwn/rtl8188e/r88e_rf.c @@ -50,7 +50,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8188e/r88e.h> #include <dev/rtwn/rtl8188e/r88e_reg.h> - void r88e_rf_write(struct rtwn_softc *sc, int chain, uint8_t addr, uint32_t val) { diff --git a/sys/dev/rtwn/rtl8188e/r88e_rom.c b/sys/dev/rtwn/rtl8188e/r88e_rom.c index f1baf5ffc594..d84d1b8149d8 100644 --- a/sys/dev/rtwn/rtl8188e/r88e_rom.c +++ b/sys/dev/rtwn/rtl8188e/r88e_rom.c @@ -55,7 +55,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8188e/r88e_priv.h> #include <dev/rtwn/rtl8188e/r88e_rom_image.h> - void r88e_parse_rom(struct rtwn_softc *sc, uint8_t *buf) { diff --git a/sys/dev/rtwn/rtl8188e/r88e_rx.c b/sys/dev/rtwn/rtl8188e/r88e_rx.c index 29b76552bcbf..dad1bc56446a 100644 --- a/sys/dev/rtwn/rtl8188e/r88e_rx.c +++ b/sys/dev/rtwn/rtl8188e/r88e_rx.c @@ -55,7 +55,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8188e/r88e.h> #include <dev/rtwn/rtl8188e/r88e_rx_desc.h> - int r88e_classify_intr(struct rtwn_softc *sc, void *buf, int len) { diff --git a/sys/dev/rtwn/rtl8188e/r88e_tx.c b/sys/dev/rtwn/rtl8188e/r88e_tx.c index dd3aaecefa44..d9920f73e3cf 100644 --- a/sys/dev/rtwn/rtl8188e/r88e_tx.c +++ b/sys/dev/rtwn/rtl8188e/r88e_tx.c @@ -50,7 +50,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8188e/r88e.h> #include <dev/rtwn/rtl8188e/r88e_tx_desc.h> - void r88e_tx_enable_ampdu(void *buf, int enable) { diff --git a/sys/dev/rtwn/rtl8188e/usb/r88eu.h b/sys/dev/rtwn/rtl8188e/usb/r88eu.h index e79b1387c4c1..9b9198e0a8c0 100644 --- a/sys/dev/rtwn/rtl8188e/usb/r88eu.h +++ b/sys/dev/rtwn/rtl8188e/usb/r88eu.h @@ -23,14 +23,12 @@ #include <dev/rtwn/rtl8188e/r88e.h> - /* * Global definitions. */ #define R88EU_PUBQ_NPAGES 142 #define R88EU_TX_PAGE_COUNT 169 - /* * Function declarations. */ diff --git a/sys/dev/rtwn/rtl8188e/usb/r88eu_attach.c b/sys/dev/rtwn/rtl8188e/usb/r88eu_attach.c index 1ae0fc24c1e8..a264629a6057 100644 --- a/sys/dev/rtwn/rtl8188e/usb/r88eu_attach.c +++ b/sys/dev/rtwn/rtl8188e/usb/r88eu_attach.c @@ -61,7 +61,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8188e/usb/r88eu.h> - static struct rtwn_r88e_txpwr r88e_txpwr; void r88eu_attach(struct rtwn_usb_softc *); diff --git a/sys/dev/rtwn/rtl8188e/usb/r88eu_init.c b/sys/dev/rtwn/rtl8188e/usb/r88eu_init.c index 1fcecbd4d9a7..156f6ea79cdf 100644 --- a/sys/dev/rtwn/rtl8188e/usb/r88eu_init.c +++ b/sys/dev/rtwn/rtl8188e/usb/r88eu_init.c @@ -53,7 +53,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8188e/usb/r88eu.h> #include <dev/rtwn/rtl8188e/usb/r88eu_reg.h> - void r88eu_init_bb(struct rtwn_softc *sc) { diff --git a/sys/dev/rtwn/rtl8192c/pci/r92ce.h b/sys/dev/rtwn/rtl8192c/pci/r92ce.h index 5d13f1608dd3..39e08b4afb12 100644 --- a/sys/dev/rtwn/rtl8192c/pci/r92ce.h +++ b/sys/dev/rtwn/rtl8192c/pci/r92ce.h @@ -25,7 +25,6 @@ #include <dev/rtwn/rtl8192c/r92c.h> - /* * Global definitions. */ @@ -35,7 +34,6 @@ #define R92CE_TX_PAGE_COUNT \ (R92CE_PUBQ_NPAGES + R92CE_HPQ_NPAGES + R92CE_LPQ_NPAGES) - /* * Function declarations. */ diff --git a/sys/dev/rtwn/rtl8192c/pci/r92ce_attach.c b/sys/dev/rtwn/rtl8192c/pci/r92ce_attach.c index bff91b743383..d3f653741977 100644 --- a/sys/dev/rtwn/rtl8192c/pci/r92ce_attach.c +++ b/sys/dev/rtwn/rtl8192c/pci/r92ce_attach.c @@ -61,7 +61,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8192c/pci/r92ce_reg.h> #include <dev/rtwn/rtl8192c/pci/r92ce_tx_desc.h> - static struct rtwn_r92c_txpwr r92c_txpwr; void r92ce_attach(struct rtwn_pci_softc *); diff --git a/sys/dev/rtwn/rtl8192c/pci/r92ce_calib.c b/sys/dev/rtwn/rtl8192c/pci/r92ce_calib.c index aebf60ae62bc..f4e68e12af28 100644 --- a/sys/dev/rtwn/rtl8192c/pci/r92ce_calib.c +++ b/sys/dev/rtwn/rtl8192c/pci/r92ce_calib.c @@ -57,7 +57,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8192c/pci/r92ce.h> #include <dev/rtwn/rtl8192c/pci/r92ce_reg.h> - /* Registers to save and restore during IQ calibration. */ struct r92ce_iq_cal_reg_vals { uint32_t adda[16]; diff --git a/sys/dev/rtwn/rtl8192c/pci/r92ce_fw.c b/sys/dev/rtwn/rtl8192c/pci/r92ce_fw.c index b28104463b6c..b28f80ce0805 100644 --- a/sys/dev/rtwn/rtl8192c/pci/r92ce_fw.c +++ b/sys/dev/rtwn/rtl8192c/pci/r92ce_fw.c @@ -54,7 +54,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8192c/pci/r92ce.h> - #ifndef RTWN_WITHOUT_UCODE void r92ce_fw_reset(struct rtwn_softc *sc, int reason) diff --git a/sys/dev/rtwn/rtl8192c/pci/r92ce_init.c b/sys/dev/rtwn/rtl8192c/pci/r92ce_init.c index 5b7f9a0e1987..7b07f6cfc518 100644 --- a/sys/dev/rtwn/rtl8192c/pci/r92ce_init.c +++ b/sys/dev/rtwn/rtl8192c/pci/r92ce_init.c @@ -57,7 +57,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8192c/pci/r92ce.h> #include <dev/rtwn/rtl8192c/pci/r92ce_reg.h> - void r92ce_init_intr(struct rtwn_softc *sc) { diff --git a/sys/dev/rtwn/rtl8192c/pci/r92ce_priv.h b/sys/dev/rtwn/rtl8192c/pci/r92ce_priv.h index 7416516cd986..08172a607f27 100644 --- a/sys/dev/rtwn/rtl8192c/pci/r92ce_priv.h +++ b/sys/dev/rtwn/rtl8192c/pci/r92ce_priv.h @@ -25,7 +25,6 @@ #include <dev/rtwn/rtl8192c/r92c_priv.h> - /* * MAC initialization values. */ @@ -53,7 +52,6 @@ static const struct rtwn_mac_prog rtl8192ce_mac[] = { { 0x70b, 0x87 } }; - /* * Baseband initialization values. */ diff --git a/sys/dev/rtwn/rtl8192c/pci/r92ce_reg.h b/sys/dev/rtwn/rtl8192c/pci/r92ce_reg.h index 355d8f4622cd..d76cc64e2c7f 100644 --- a/sys/dev/rtwn/rtl8192c/pci/r92ce_reg.h +++ b/sys/dev/rtwn/rtl8192c/pci/r92ce_reg.h @@ -51,7 +51,6 @@ #define R92C_UART_TX_DES 0x370 #define R92C_UART_RX_DES 0x378 - /* Bits for R92C_GPIO_MUXCFG. */ #define R92C_GPIO_MUXCFG_RFKILL 0x0008 diff --git a/sys/dev/rtwn/rtl8192c/pci/r92ce_rx.c b/sys/dev/rtwn/rtl8192c/pci/r92ce_rx.c index d8b3c5e0b53e..7cd6283ea18a 100644 --- a/sys/dev/rtwn/rtl8192c/pci/r92ce_rx.c +++ b/sys/dev/rtwn/rtl8192c/pci/r92ce_rx.c @@ -56,7 +56,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8192c/pci/r92ce.h> #include <dev/rtwn/rtl8192c/pci/r92ce_reg.h> - int r92ce_get_intr_status(struct rtwn_pci_softc *pc, int *rings) { diff --git a/sys/dev/rtwn/rtl8192c/pci/r92ce_tx.c b/sys/dev/rtwn/rtl8192c/pci/r92ce_tx.c index 19de15b5a63e..ea6535f46b5f 100644 --- a/sys/dev/rtwn/rtl8192c/pci/r92ce_tx.c +++ b/sys/dev/rtwn/rtl8192c/pci/r92ce_tx.c @@ -56,7 +56,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8192c/pci/r92ce.h> #include <dev/rtwn/rtl8192c/pci/r92ce_tx_desc.h> - void r92ce_setup_tx_desc(struct rtwn_pci_softc *pc, void *desc, uint32_t next_desc_addr) diff --git a/sys/dev/rtwn/rtl8192c/r92c.h b/sys/dev/rtwn/rtl8192c/r92c.h index f215e34fd8ce..4d4307c786a4 100644 --- a/sys/dev/rtwn/rtl8192c/r92c.h +++ b/sys/dev/rtwn/rtl8192c/r92c.h @@ -35,7 +35,6 @@ #define R92C_CALIB_THRESHOLD 2 - /* * Function declarations. */ diff --git a/sys/dev/rtwn/rtl8192c/r92c_attach.c b/sys/dev/rtwn/rtl8192c/r92c_attach.c index a0df8ec7688d..d71a595dc6a7 100644 --- a/sys/dev/rtwn/rtl8192c/r92c_attach.c +++ b/sys/dev/rtwn/rtl8192c/r92c_attach.c @@ -51,7 +51,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8192c/r92c_reg.h> #include <dev/rtwn/rtl8192c/r92c_var.h> - void r92c_detach_private(struct rtwn_softc *sc) { diff --git a/sys/dev/rtwn/rtl8192c/r92c_beacon.c b/sys/dev/rtwn/rtl8192c/r92c_beacon.c index 15af77a06fea..477358bbf931 100644 --- a/sys/dev/rtwn/rtl8192c/r92c_beacon.c +++ b/sys/dev/rtwn/rtl8192c/r92c_beacon.c @@ -50,7 +50,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8192c/r92c_reg.h> #include <dev/rtwn/rtl8192c/r92c_tx_desc.h> - void r92c_beacon_init(struct rtwn_softc *sc, void *buf, int id) { diff --git a/sys/dev/rtwn/rtl8192c/r92c_calib.c b/sys/dev/rtwn/rtl8192c/r92c_calib.c index 7a2e998c1bfb..c340c816c727 100644 --- a/sys/dev/rtwn/rtl8192c/r92c_calib.c +++ b/sys/dev/rtwn/rtl8192c/r92c_calib.c @@ -51,7 +51,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8192c/r92c.h> #include <dev/rtwn/rtl8192c/r92c_reg.h> - /* Registers to save and restore during IQ calibration. */ struct r92c_iq_cal_reg_vals { uint32_t adda[16]; diff --git a/sys/dev/rtwn/rtl8192c/r92c_chan.c b/sys/dev/rtwn/rtl8192c/r92c_chan.c index 94a1284fed18..01e0cfb629f1 100644 --- a/sys/dev/rtwn/rtl8192c/r92c_chan.c +++ b/sys/dev/rtwn/rtl8192c/r92c_chan.c @@ -55,7 +55,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8192c/r92c_reg.h> #include <dev/rtwn/rtl8192c/r92c_var.h> - static int r92c_get_power_group(struct rtwn_softc *sc, struct ieee80211_channel *c) { diff --git a/sys/dev/rtwn/rtl8192c/r92c_fw.c b/sys/dev/rtwn/rtl8192c/r92c_fw.c index 0791990a0c00..7ad6d7d2dfe6 100644 --- a/sys/dev/rtwn/rtl8192c/r92c_fw.c +++ b/sys/dev/rtwn/rtl8192c/r92c_fw.c @@ -60,7 +60,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8192c/r92c_fw_cmd.h> #include <dev/rtwn/rtl8192c/r92c_tx_desc.h> - #ifndef RTWN_WITHOUT_UCODE static int r92c_fw_cmd(struct rtwn_softc *sc, uint8_t id, const void *buf, int len) diff --git a/sys/dev/rtwn/rtl8192c/r92c_init.c b/sys/dev/rtwn/rtl8192c/r92c_init.c index bf043b8e376f..4e29fe0b033c 100644 --- a/sys/dev/rtwn/rtl8192c/r92c_init.c +++ b/sys/dev/rtwn/rtl8192c/r92c_init.c @@ -53,7 +53,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8192c/r92c_reg.h> #include <dev/rtwn/rtl8192c/r92c_var.h> - int r92c_check_condition(struct rtwn_softc *sc, const uint8_t cond[]) { diff --git a/sys/dev/rtwn/rtl8192c/r92c_priv.h b/sys/dev/rtwn/rtl8192c/r92c_priv.h index 80f058284941..645f07a58704 100644 --- a/sys/dev/rtwn/rtl8192c/r92c_priv.h +++ b/sys/dev/rtwn/rtl8192c/r92c_priv.h @@ -36,7 +36,6 @@ struct rtwn_r92c_txpwr { int8_t ht20_max_pwr[R92C_MAX_CHAINS][R92C_GROUP_2G]; }; - /* * Baseband initialization values (shared parts). */ @@ -132,7 +131,6 @@ static const struct rtwn_agc_prog rtl8192ce_agc[] = { } }; - /* * RF initialization values. */ @@ -331,7 +329,6 @@ static const struct rtwn_rf_prog rtl8192c_rf[] = { { 0, NULL, NULL, { 0 }, NULL } }; - struct rtwn_r92c_txagc { uint8_t pwr[R92C_GROUP_2G][28]; /* RTWN_RIDX_HT_MCS(15) + 1 */ }; diff --git a/sys/dev/rtwn/rtl8192c/r92c_reg.h b/sys/dev/rtwn/rtl8192c/r92c_reg.h index c3def33e21bb..d01168fe395a 100644 --- a/sys/dev/rtwn/rtl8192c/r92c_reg.h +++ b/sys/dev/rtwn/rtl8192c/r92c_reg.h @@ -224,7 +224,6 @@ #define R92C_MACID1 0x700 #define R92C_BSSID1 0x708 - #define R92C_MACID(id) ((id) == 0 ? R92C_MACID0 : R92C_MACID1) #define R92C_BSSID(id) ((id) == 0 ? R92C_BSSID0 : R92C_BSSID1) @@ -628,7 +627,6 @@ #define R92C_CAMCMD_CLR 0x40000000 #define R92C_CAMCMD_POLLING 0x80000000 - /* * CAM entries. */ @@ -666,7 +664,6 @@ #define R92C_RXFLTMAP_SUBTYPE(subtype) \ (1 << ((subtype) >> IEEE80211_FC0_SUBTYPE_SHIFT)) - /* * Baseband registers. */ @@ -850,7 +847,6 @@ #define R92C_POWER_IQK_RESULT_S 16 #define R92C_POWER_IQK_RESULT_M 0x03ff0000 - /* * RF (6052) registers. */ diff --git a/sys/dev/rtwn/rtl8192c/r92c_rf.c b/sys/dev/rtwn/rtl8192c/r92c_rf.c index f36f035f2a9b..c547a06ea980 100644 --- a/sys/dev/rtwn/rtl8192c/r92c_rf.c +++ b/sys/dev/rtwn/rtl8192c/r92c_rf.c @@ -52,7 +52,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8192c/r92c_var.h> #include <dev/rtwn/rtl8192c/r92c_rom_defs.h> - uint32_t r92c_rf_read(struct rtwn_softc *sc, int chain, uint8_t addr) { diff --git a/sys/dev/rtwn/rtl8192c/r92c_rom.c b/sys/dev/rtwn/rtl8192c/r92c_rom.c index 0a85c817b2f8..ea3f3a253df0 100644 --- a/sys/dev/rtwn/rtl8192c/r92c_rom.c +++ b/sys/dev/rtwn/rtl8192c/r92c_rom.c @@ -55,7 +55,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8192c/r92c_var.h> #include <dev/rtwn/rtl8192c/r92c_rom_image.h> - static void r92c_set_chains(struct rtwn_softc *sc) { diff --git a/sys/dev/rtwn/rtl8192c/r92c_rx.c b/sys/dev/rtwn/rtl8192c/r92c_rx.c index 24759d1bb0f9..258b914d4465 100644 --- a/sys/dev/rtwn/rtl8192c/r92c_rx.c +++ b/sys/dev/rtwn/rtl8192c/r92c_rx.c @@ -51,7 +51,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8192c/r92c.h> #include <dev/rtwn/rtl8192c/r92c_rx_desc.h> - int r92c_classify_intr(struct rtwn_softc *sc, void *buf, int len) { diff --git a/sys/dev/rtwn/rtl8192c/r92c_tx.c b/sys/dev/rtwn/rtl8192c/r92c_tx.c index 07f787e75bab..ab2d05635358 100644 --- a/sys/dev/rtwn/rtl8192c/r92c_tx.c +++ b/sys/dev/rtwn/rtl8192c/r92c_tx.c @@ -54,7 +54,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8192c/r92c_var.h> #include <dev/rtwn/rtl8192c/r92c_tx_desc.h> - static int r92c_tx_get_sco(struct rtwn_softc *sc, struct ieee80211_channel *c) { diff --git a/sys/dev/rtwn/rtl8192c/r92c_tx_desc.h b/sys/dev/rtwn/rtl8192c/r92c_tx_desc.h index c3bc87caa31f..c65ece0e3c02 100644 --- a/sys/dev/rtwn/rtl8192c/r92c_tx_desc.h +++ b/sys/dev/rtwn/rtl8192c/r92c_tx_desc.h @@ -109,7 +109,6 @@ struct r92c_tx_desc { #define R92C_TXDW6_MAX_AGG_S 11 } __packed __attribute__((aligned(4))); - /* Rate adaptation modes. */ #define R92C_RAID_11BGN 0 #define R92C_RAID_11GN 1 diff --git a/sys/dev/rtwn/rtl8192c/usb/r92cu.h b/sys/dev/rtwn/rtl8192c/usb/r92cu.h index 4cc010494a18..f9b9861867bc 100644 --- a/sys/dev/rtwn/rtl8192c/usb/r92cu.h +++ b/sys/dev/rtwn/rtl8192c/usb/r92cu.h @@ -23,14 +23,12 @@ #include <dev/rtwn/rtl8192c/r92c.h> - /* * Global definitions. */ #define R92CU_PUBQ_NPAGES 231 #define R92CU_TX_PAGE_COUNT 248 - /* * Function declarations. */ diff --git a/sys/dev/rtwn/rtl8192c/usb/r92cu_attach.c b/sys/dev/rtwn/rtl8192c/usb/r92cu_attach.c index 4a7698410c56..ef436ee3ed01 100644 --- a/sys/dev/rtwn/rtl8192c/usb/r92cu_attach.c +++ b/sys/dev/rtwn/rtl8192c/usb/r92cu_attach.c @@ -57,7 +57,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8192c/usb/r92cu_reg.h> #include <dev/rtwn/rtl8192c/usb/r92cu_tx_desc.h> - static struct rtwn_r92c_txpwr r92c_txpwr; void r92cu_attach(struct rtwn_usb_softc *); diff --git a/sys/dev/rtwn/rtl8192c/usb/r92cu_init.c b/sys/dev/rtwn/rtl8192c/usb/r92cu_init.c index 13ccd50adbb8..94563fed635e 100644 --- a/sys/dev/rtwn/rtl8192c/usb/r92cu_init.c +++ b/sys/dev/rtwn/rtl8192c/usb/r92cu_init.c @@ -55,7 +55,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8192c/usb/r92cu.h> #include <dev/rtwn/rtl8192c/usb/r92cu_reg.h> - void r92cu_init_bb(struct rtwn_softc *sc) { diff --git a/sys/dev/rtwn/rtl8192c/usb/r92cu_led.c b/sys/dev/rtwn/rtl8192c/usb/r92cu_led.c index 724320946639..534987b6a1c0 100644 --- a/sys/dev/rtwn/rtl8192c/usb/r92cu_led.c +++ b/sys/dev/rtwn/rtl8192c/usb/r92cu_led.c @@ -50,7 +50,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8192c/usb/r92cu.h> - void r92cu_set_led(struct rtwn_softc *sc, int led, int on) { diff --git a/sys/dev/rtwn/rtl8192c/usb/r92cu_priv.h b/sys/dev/rtwn/rtl8192c/usb/r92cu_priv.h index 8e3203f082f3..a7f9e8d49596 100644 --- a/sys/dev/rtwn/rtl8192c/usb/r92cu_priv.h +++ b/sys/dev/rtwn/rtl8192c/usb/r92cu_priv.h @@ -23,7 +23,6 @@ #include <dev/rtwn/rtl8192c/r92c_priv.h> - /* * MAC initialization values. */ @@ -52,7 +51,6 @@ static const struct rtwn_mac_prog rtl8192cu_mac[] = { { 0x70a, 0x65 }, { 0x70b, 0x87 } }; - /* * Baseband initialization values. */ @@ -274,7 +272,6 @@ static const struct rtwn_bb_prog rtl8192cu_bb[] = { } }; - static const uint32_t rtl8188ru_agc_vals[] = { 0x7b000001, 0x7b010001, 0x7b020001, 0x7b030001, 0x7b040001, 0x7b050001, 0x7b060001, 0x7b070001, 0x7b080001, 0x7a090001, diff --git a/sys/dev/rtwn/rtl8192c/usb/r92cu_reg.h b/sys/dev/rtwn/rtl8192c/usb/r92cu_reg.h index a9db29ccbca4..f8ab133f5371 100644 --- a/sys/dev/rtwn/rtl8192c/usb/r92cu_reg.h +++ b/sys/dev/rtwn/rtl8192c/usb/r92cu_reg.h @@ -23,14 +23,12 @@ #include <dev/rtwn/rtl8192c/r92c_reg.h> - /* * MAC registers. */ /* System Configuration. */ #define R92C_USB_SIE_INTF 0x0e0 - /* * USB registers. */ diff --git a/sys/dev/rtwn/rtl8192c/usb/r92cu_rx.c b/sys/dev/rtwn/rtl8192c/usb/r92cu_rx.c index fcd760b6136b..6710b1a8fa3c 100644 --- a/sys/dev/rtwn/rtl8192c/usb/r92cu_rx.c +++ b/sys/dev/rtwn/rtl8192c/usb/r92cu_rx.c @@ -48,7 +48,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8192c/usb/r92cu.h> - int r92cu_align_rx(int totlen, int len) { diff --git a/sys/dev/rtwn/rtl8192c/usb/r92cu_tx.c b/sys/dev/rtwn/rtl8192c/usb/r92cu_tx.c index 04dbade0651a..a9e37ba819de 100644 --- a/sys/dev/rtwn/rtl8192c/usb/r92cu_tx.c +++ b/sys/dev/rtwn/rtl8192c/usb/r92cu_tx.c @@ -46,7 +46,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8192c/usb/r92cu.h> #include <dev/rtwn/rtl8192c/usb/r92cu_tx_desc.h> - void r92cu_dump_tx_desc(struct rtwn_softc *sc, const void *desc) { diff --git a/sys/dev/rtwn/rtl8192c/usb/r92cu_tx_desc.h b/sys/dev/rtwn/rtl8192c/usb/r92cu_tx_desc.h index 16c2d0587e4c..f160f1310913 100644 --- a/sys/dev/rtwn/rtl8192c/usb/r92cu_tx_desc.h +++ b/sys/dev/rtwn/rtl8192c/usb/r92cu_tx_desc.h @@ -42,4 +42,4 @@ struct r92cu_tx_desc { uint16_t pad; } __packed __attribute__((aligned(4))); -#endif /* R92CU_TX_DESC_H */
\ No newline at end of file +#endif /* R92CU_TX_DESC_H */ diff --git a/sys/dev/rtwn/rtl8192e/r92e.h b/sys/dev/rtwn/rtl8192e/r92e.h index a961236c062d..c4a60330259a 100644 --- a/sys/dev/rtwn/rtl8192e/r92e.h +++ b/sys/dev/rtwn/rtl8192e/r92e.h @@ -40,7 +40,6 @@ #define R92E_MAX_FW_SIZE 0x8000 - /* * Function declarations. */ diff --git a/sys/dev/rtwn/rtl8192e/r92e_chan.c b/sys/dev/rtwn/rtl8192e/r92e_chan.c index 7b3c5630dd18..0211e2883888 100644 --- a/sys/dev/rtwn/rtl8192e/r92e_chan.c +++ b/sys/dev/rtwn/rtl8192e/r92e_chan.c @@ -127,7 +127,6 @@ r92e_get_txpower(struct rtwn_softc *sc, int chain, struct ieee80211_channel *c, min_mcs = RTWN_RIDX_HT_MCS(i * 8); for (ridx = min_mcs; ridx <= max_mcs; ridx++) power[ridx] += pwr_diff; - } /* Apply max limit. */ diff --git a/sys/dev/rtwn/rtl8192e/r92e_priv.h b/sys/dev/rtwn/rtl8192e/r92e_priv.h index 1bcae4f9aafd..ddf8c48ca4e9 100644 --- a/sys/dev/rtwn/rtl8192e/r92e_priv.h +++ b/sys/dev/rtwn/rtl8192e/r92e_priv.h @@ -61,7 +61,6 @@ static const struct rtwn_mac_prog rtl8192eu_mac[] = { { 0x70b, 0x87 } }; - /* * Baseband initialization values. */ @@ -147,7 +146,6 @@ static const struct rtwn_bb_prog rtl8192eu_bb[] = { } }; - static const uint32_t rtl8192eu_agc_vals[] = { 0xfb000001, 0xfb010001, 0xfb020001, 0xfb030001, 0xfb040001, 0xfb050001, 0xfa060001, 0xf9070001, 0xf8080001, 0xf7090001, diff --git a/sys/dev/rtwn/rtl8192e/usb/r92eu.h b/sys/dev/rtwn/rtl8192e/usb/r92eu.h index a59ceb63be04..3ca6e067585b 100644 --- a/sys/dev/rtwn/rtl8192e/usb/r92eu.h +++ b/sys/dev/rtwn/rtl8192e/usb/r92eu.h @@ -26,7 +26,6 @@ * $FreeBSD$ */ - #ifndef RTL8192EU_H #define RTL8192EU_H diff --git a/sys/dev/rtwn/rtl8812a/r12a.h b/sys/dev/rtwn/rtl8812a/r12a.h index e8de45aa9da5..f3bbdf77360b 100644 --- a/sys/dev/rtwn/rtl8812a/r12a.h +++ b/sys/dev/rtwn/rtl8812a/r12a.h @@ -52,7 +52,6 @@ static const uint8_t r12a_chan_5ghz_1[] = static const uint8_t r12a_chan_5ghz_2[] = { 149, 153, 157, 161, 165, 169, 173, 177 }; - /* * Function declarations. */ diff --git a/sys/dev/rtwn/rtl8812a/r12a_beacon.c b/sys/dev/rtwn/rtl8812a/r12a_beacon.c index 7a3335e84f71..879d513eb66c 100644 --- a/sys/dev/rtwn/rtl8812a/r12a_beacon.c +++ b/sys/dev/rtwn/rtl8812a/r12a_beacon.c @@ -59,7 +59,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8812a/r12a_reg.h> #include <dev/rtwn/rtl8812a/r12a_tx_desc.h> - void r12a_beacon_init(struct rtwn_softc *sc, void *buf, int id) { diff --git a/sys/dev/rtwn/rtl8812a/r12a_calib.c b/sys/dev/rtwn/rtl8812a/r12a_calib.c index c87151b5355a..268e06b5ba20 100644 --- a/sys/dev/rtwn/rtl8812a/r12a_calib.c +++ b/sys/dev/rtwn/rtl8812a/r12a_calib.c @@ -60,7 +60,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8812a/r12a_reg.h> #include <dev/rtwn/rtl8812a/r12a_var.h> - void r12a_lc_calib(struct rtwn_softc *sc) { diff --git a/sys/dev/rtwn/rtl8812a/r12a_caps.c b/sys/dev/rtwn/rtl8812a/r12a_caps.c index aa1c755cb138..ab175b41ec70 100644 --- a/sys/dev/rtwn/rtl8812a/r12a_caps.c +++ b/sys/dev/rtwn/rtl8812a/r12a_caps.c @@ -59,7 +59,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8812a/r12a_reg.h> #include <dev/rtwn/rtl8812a/r12a_var.h> - int r12a_ioctl_net(struct ieee80211com *ic, u_long cmd, void *data) { diff --git a/sys/dev/rtwn/rtl8812a/r12a_chan.c b/sys/dev/rtwn/rtl8812a/r12a_chan.c index 9536c6db4a31..a1b39b97c67c 100644 --- a/sys/dev/rtwn/rtl8812a/r12a_chan.c +++ b/sys/dev/rtwn/rtl8812a/r12a_chan.c @@ -61,7 +61,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8812a/r12a_reg.h> #include <dev/rtwn/rtl8812a/r12a_var.h> - static void r12a_write_txpower(struct rtwn_softc *sc, int chain, struct ieee80211_channel *c, uint8_t power[RTWN_RIDX_COUNT]) diff --git a/sys/dev/rtwn/rtl8812a/r12a_fw.c b/sys/dev/rtwn/rtl8812a/r12a_fw.c index f7b88e42c4f8..08847d7fff07 100644 --- a/sys/dev/rtwn/rtl8812a/r12a_fw.c +++ b/sys/dev/rtwn/rtl8812a/r12a_fw.c @@ -62,7 +62,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8812a/r12a_var.h> #include <dev/rtwn/rtl8812a/r12a_fw_cmd.h> - #ifndef RTWN_WITHOUT_UCODE void r12a_fw_reset(struct rtwn_softc *sc, int reason) diff --git a/sys/dev/rtwn/rtl8812a/r12a_fw_cmd.h b/sys/dev/rtwn/rtl8812a/r12a_fw_cmd.h index 58b82ed14268..e50e918912ad 100644 --- a/sys/dev/rtwn/rtl8812a/r12a_fw_cmd.h +++ b/sys/dev/rtwn/rtl8812a/r12a_fw_cmd.h @@ -77,7 +77,6 @@ struct r12a_fw_cmd_iq_calib { #define RTWN_CMD_IQ_EXT_LNA_5G(lna) ((lna) << 1) } __packed; - /* * C2H event types. */ diff --git a/sys/dev/rtwn/rtl8812a/r12a_init.c b/sys/dev/rtwn/rtl8812a/r12a_init.c index 8ec401d9d0e4..af1a746b75a8 100644 --- a/sys/dev/rtwn/rtl8812a/r12a_init.c +++ b/sys/dev/rtwn/rtl8812a/r12a_init.c @@ -62,7 +62,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8812a/r12a_reg.h> #include <dev/rtwn/rtl8812a/r12a_var.h> - int r12a_check_condition(struct rtwn_softc *sc, const uint8_t cond[]) { diff --git a/sys/dev/rtwn/rtl8812a/r12a_led.c b/sys/dev/rtwn/rtl8812a/r12a_led.c index aa67c67b97a7..c2b76d1abdaf 100644 --- a/sys/dev/rtwn/rtl8812a/r12a_led.c +++ b/sys/dev/rtwn/rtl8812a/r12a_led.c @@ -55,7 +55,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8812a/r12a.h> #include <dev/rtwn/rtl8812a/r12a_reg.h> - void r12a_set_led(struct rtwn_softc *sc, int led, int on) { diff --git a/sys/dev/rtwn/rtl8812a/r12a_priv.h b/sys/dev/rtwn/rtl8812a/r12a_priv.h index e75e32fcf9ba..f770e3b0ac6a 100644 --- a/sys/dev/rtwn/rtl8812a/r12a_priv.h +++ b/sys/dev/rtwn/rtl8812a/r12a_priv.h @@ -73,7 +73,6 @@ static const struct rtwn_mac_prog rtl8812au_mac_no_ext_pa_lna[] = { RTL8812AU_MAC_PROG_END }; - /* * Baseband initialization values. */ @@ -212,7 +211,6 @@ static const struct rtwn_bb_prog rtl8812au_bb[] = { } }; - static const uint32_t rtl8812au_agc_vals0_lna_g0[] = { 0xfc000001, 0xfb020001, 0xfa040001, 0xf9060001, 0xf8080001, 0xf70a0001, 0xf60c0001, 0xf50e0001, 0xf4100001, 0xf3120001, @@ -832,7 +830,6 @@ static const struct rtwn_rf_prog rtl8812au_rf[] = { { 0, NULL, NULL, { 0 }, NULL } }; - /* * Registers to save before IQ calibration. */ diff --git a/sys/dev/rtwn/rtl8812a/r12a_reg.h b/sys/dev/rtwn/rtl8812a/r12a_reg.h index 581e7078138d..b6aa302e69d0 100644 --- a/sys/dev/rtwn/rtl8812a/r12a_reg.h +++ b/sys/dev/rtwn/rtl8812a/r12a_reg.h @@ -50,7 +50,6 @@ #define R12A_ARFR_2G(i) (0x48c + (i) * 8) #define R12A_HT_SINGLE_AMPDU 0x4c7 - /* Bits for R92C_MAC_PHY_CTRL. */ #define R12A_MAC_PHY_CRYSTALCAP_M 0x7ff80000 #define R12A_MAC_PHY_CRYSTALCAP_S 19 @@ -89,7 +88,6 @@ #define R12A_RCR_TCP_OFFLD_EN 0x02000000 #define R12A_RCR_VHT_ACK 0x04000000 - /* * Baseband registers. */ @@ -234,7 +232,6 @@ #define R12A_TXAGC_MCS15_M 0xff000000 #define R12A_TXAGC_MCS15_S 24 - /* * RF (6052) registers. */ diff --git a/sys/dev/rtwn/rtl8812a/r12a_rf.c b/sys/dev/rtwn/rtl8812a/r12a_rf.c index 43bd7b9ae608..a9936a1209a3 100644 --- a/sys/dev/rtwn/rtl8812a/r12a_rf.c +++ b/sys/dev/rtwn/rtl8812a/r12a_rf.c @@ -56,7 +56,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8812a/r12a.h> #include <dev/rtwn/rtl8812a/r12a_reg.h> - uint32_t r12a_rf_read(struct rtwn_softc *sc, int chain, uint8_t addr) { diff --git a/sys/dev/rtwn/rtl8812a/r12a_rom.c b/sys/dev/rtwn/rtl8812a/r12a_rom.c index f5d16a3ff718..9eaa03adf3d9 100644 --- a/sys/dev/rtwn/rtl8812a/r12a_rom.c +++ b/sys/dev/rtwn/rtl8812a/r12a_rom.c @@ -59,7 +59,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8812a/r12a_var.h> #include <dev/rtwn/rtl8812a/r12a_rom_image.h> - void r12a_parse_rom_common(struct rtwn_softc *sc, uint8_t *buf) { diff --git a/sys/dev/rtwn/rtl8812a/r12a_rx.c b/sys/dev/rtwn/rtl8812a/r12a_rx.c index 9fb410531711..d8dcb3de12c5 100644 --- a/sys/dev/rtwn/rtl8812a/r12a_rx.c +++ b/sys/dev/rtwn/rtl8812a/r12a_rx.c @@ -62,7 +62,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8812a/r12a_fw_cmd.h> #include <dev/rtwn/rtl8812a/r12a_rx_desc.h> - #ifndef RTWN_WITHOUT_UCODE void r12a_ratectl_tx_complete(struct rtwn_softc *sc, uint8_t *buf, int len) diff --git a/sys/dev/rtwn/rtl8812a/r12a_tx.c b/sys/dev/rtwn/rtl8812a/r12a_tx.c index 9c8b27b233f3..3ce171c82444 100644 --- a/sys/dev/rtwn/rtl8812a/r12a_tx.c +++ b/sys/dev/rtwn/rtl8812a/r12a_tx.c @@ -58,7 +58,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8812a/r12a.h> #include <dev/rtwn/rtl8812a/r12a_tx_desc.h> - static int r12a_get_primary_channel(struct rtwn_softc *sc, struct ieee80211_channel *c) { @@ -424,7 +423,6 @@ r12a_fill_tx_desc_null(struct rtwn_softc *sc, void *buf, int is11b, int qos, if (!qos) { txd->txdw8 = htole32(R12A_TXDW8_HWSEQ_EN); txd->txdw3 |= htole32(SM(R12A_TXDW3_SEQ_SEL, id)); - } } diff --git a/sys/dev/rtwn/rtl8812a/r12a_tx_desc.h b/sys/dev/rtwn/rtl8812a/r12a_tx_desc.h index 9d3ad8b18162..ad01b6829d57 100644 --- a/sys/dev/rtwn/rtl8812a/r12a_tx_desc.h +++ b/sys/dev/rtwn/rtl8812a/r12a_tx_desc.h @@ -130,7 +130,6 @@ struct r12a_tx_desc { #define R12A_TXDW9_SEQ_S 12 } __packed __attribute__((aligned(4))); - /* Rate adaptation modes. */ #define R12A_RAID_11BGN_2_40 0 #define R12A_RAID_11BGN_1_40 1 diff --git a/sys/dev/rtwn/rtl8812a/usb/r12au.h b/sys/dev/rtwn/rtl8812a/usb/r12au.h index 1ea08a2d94dd..bb4173d08abf 100644 --- a/sys/dev/rtwn/rtl8812a/usb/r12au.h +++ b/sys/dev/rtwn/rtl8812a/usb/r12au.h @@ -31,7 +31,6 @@ #include <dev/rtwn/rtl8812a/r12a.h> - /* * Function declarations. */ diff --git a/sys/dev/rtwn/rtl8812a/usb/r12au_attach.c b/sys/dev/rtwn/rtl8812a/usb/r12au_attach.c index 209e772a15a4..dd5223ce969b 100644 --- a/sys/dev/rtwn/rtl8812a/usb/r12au_attach.c +++ b/sys/dev/rtwn/rtl8812a/usb/r12au_attach.c @@ -72,7 +72,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8812a/usb/r12au.h> #include <dev/rtwn/rtl8812a/usb/r12au_tx_desc.h> - void r12au_attach(struct rtwn_usb_softc *); static void diff --git a/sys/dev/rtwn/rtl8812a/usb/r12au_init.c b/sys/dev/rtwn/rtl8812a/usb/r12au_init.c index 9a6bc2bb7c8e..109ae5cba180 100644 --- a/sys/dev/rtwn/rtl8812a/usb/r12au_init.c +++ b/sys/dev/rtwn/rtl8812a/usb/r12au_init.c @@ -58,7 +58,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8812a/usb/r12au.h> #include <dev/rtwn/rtl8812a/usb/r12au_reg.h> - void r12au_init_rx_agg(struct rtwn_softc *sc) { diff --git a/sys/dev/rtwn/rtl8812a/usb/r12au_rx.c b/sys/dev/rtwn/rtl8812a/usb/r12au_rx.c index a38fcd333287..de58a87354bd 100644 --- a/sys/dev/rtwn/rtl8812a/usb/r12au_rx.c +++ b/sys/dev/rtwn/rtl8812a/usb/r12au_rx.c @@ -58,7 +58,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8812a/usb/r12au.h> - int r12au_classify_intr(struct rtwn_softc *sc, void *buf, int len) { diff --git a/sys/dev/rtwn/rtl8812a/usb/r12au_tx.c b/sys/dev/rtwn/rtl8812a/usb/r12au_tx.c index 51496681591f..bc5f2ea9a02f 100644 --- a/sys/dev/rtwn/rtl8812a/usb/r12au_tx.c +++ b/sys/dev/rtwn/rtl8812a/usb/r12au_tx.c @@ -56,7 +56,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8812a/usb/r12au.h> #include <dev/rtwn/rtl8812a/usb/r12au_tx_desc.h> - void r12au_dump_tx_desc(struct rtwn_softc *sc, const void *desc) { diff --git a/sys/dev/rtwn/rtl8821a/r21a.h b/sys/dev/rtwn/rtl8821a/r21a.h index cfc99cb9fbb8..9491cf49615e 100644 --- a/sys/dev/rtwn/rtl8821a/r21a.h +++ b/sys/dev/rtwn/rtl8821a/r21a.h @@ -39,7 +39,6 @@ #define R21A_TX_PAGE_SIZE 256 - /* * Function declarations. */ diff --git a/sys/dev/rtwn/rtl8821a/r21a_beacon.c b/sys/dev/rtwn/rtl8821a/r21a_beacon.c index f88f6def1baf..29de33e53f29 100644 --- a/sys/dev/rtwn/rtl8821a/r21a_beacon.c +++ b/sys/dev/rtwn/rtl8821a/r21a_beacon.c @@ -59,7 +59,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8821a/r21a.h> #include <dev/rtwn/rtl8821a/r21a_reg.h> - void r21a_beacon_init(struct rtwn_softc *sc, void *buf, int id) { diff --git a/sys/dev/rtwn/rtl8821a/r21a_calib.c b/sys/dev/rtwn/rtl8821a/r21a_calib.c index e1f1522e9ae4..395231a37b2d 100644 --- a/sys/dev/rtwn/rtl8821a/r21a_calib.c +++ b/sys/dev/rtwn/rtl8821a/r21a_calib.c @@ -61,7 +61,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8821a/r21a_reg.h> #include <dev/rtwn/rtl8821a/r21a_priv.h> - #ifndef RTWN_WITHOUT_UCODE int r21a_iq_calib_fw_supported(struct rtwn_softc *sc) diff --git a/sys/dev/rtwn/rtl8821a/r21a_chan.c b/sys/dev/rtwn/rtl8821a/r21a_chan.c index 49305057d2c1..68b3ef986fe5 100644 --- a/sys/dev/rtwn/rtl8821a/r21a_chan.c +++ b/sys/dev/rtwn/rtl8821a/r21a_chan.c @@ -60,7 +60,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8821a/r21a.h> #include <dev/rtwn/rtl8821a/r21a_reg.h> - static void r21a_bypass_ext_lna_2ghz(struct rtwn_softc *sc) { diff --git a/sys/dev/rtwn/rtl8821a/r21a_fw.c b/sys/dev/rtwn/rtl8821a/r21a_fw.c index b0d0a5bcabbf..a512d8f4be49 100644 --- a/sys/dev/rtwn/rtl8821a/r21a_fw.c +++ b/sys/dev/rtwn/rtl8821a/r21a_fw.c @@ -55,7 +55,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8821a/r21a.h> #include <dev/rtwn/rtl8821a/r21a_reg.h> - #ifndef RTWN_WITHOUT_UCODE void r21a_fw_reset(struct rtwn_softc *sc, int reason) diff --git a/sys/dev/rtwn/rtl8821a/r21a_init.c b/sys/dev/rtwn/rtl8821a/r21a_init.c index d8a0b1264ec4..8dc4faafe8d2 100644 --- a/sys/dev/rtwn/rtl8821a/r21a_init.c +++ b/sys/dev/rtwn/rtl8821a/r21a_init.c @@ -61,7 +61,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8821a/r21a_priv.h> #include <dev/rtwn/rtl8821a/r21a_reg.h> - int r21a_power_on(struct rtwn_softc *sc) { diff --git a/sys/dev/rtwn/rtl8821a/r21a_led.c b/sys/dev/rtwn/rtl8821a/r21a_led.c index 3e682c2a5efd..af75d4078208 100644 --- a/sys/dev/rtwn/rtl8821a/r21a_led.c +++ b/sys/dev/rtwn/rtl8821a/r21a_led.c @@ -55,7 +55,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8821a/r21a.h> #include <dev/rtwn/rtl8821a/r21a_reg.h> - void r21a_set_led(struct rtwn_softc *sc, int led, int on) { diff --git a/sys/dev/rtwn/rtl8821a/r21a_priv.h b/sys/dev/rtwn/rtl8821a/r21a_priv.h index d4cfa46afecf..298dd36040ef 100644 --- a/sys/dev/rtwn/rtl8821a/r21a_priv.h +++ b/sys/dev/rtwn/rtl8821a/r21a_priv.h @@ -60,7 +60,6 @@ static const struct rtwn_mac_prog rtl8821au_mac[] = { { 0x70b, 0x87 }, { 0x718, 0x40 } }; - /* * Baseband initialization values. */ @@ -217,7 +216,6 @@ static const struct rtwn_agc_prog rtl8821au_agc[] = { } }; - /* * RF initialization values. */ @@ -445,7 +443,6 @@ static const struct rtwn_rf_prog rtl8821au_rf[] = { { 0, NULL, NULL, { 0 }, NULL } }; - /* * Registers to save before IQ calibration. */ diff --git a/sys/dev/rtwn/rtl8821a/r21a_reg.h b/sys/dev/rtwn/rtl8821a/r21a_reg.h index d13872d59cbc..287fcbd7f6f4 100644 --- a/sys/dev/rtwn/rtl8821a/r21a_reg.h +++ b/sys/dev/rtwn/rtl8821a/r21a_reg.h @@ -38,7 +38,6 @@ #define R21A_DWBCN0_CTRL R92C_TDECTRL #define R21A_DWBCN1_CTRL 0x228 - /* Bits for R92C_MAC_PHY_CTRL. */ #define R21A_MAC_PHY_CRYSTALCAP_M 0x00fff000 #define R21A_MAC_PHY_CRYSTALCAP_S 12 diff --git a/sys/dev/rtwn/rtl8821a/r21a_rom.c b/sys/dev/rtwn/rtl8821a/r21a_rom.c index cda5913e9a81..45642043c0fb 100644 --- a/sys/dev/rtwn/rtl8821a/r21a_rom.c +++ b/sys/dev/rtwn/rtl8821a/r21a_rom.c @@ -59,7 +59,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8821a/r21a.h> #include <dev/rtwn/rtl8821a/r21a_reg.h> - void r21a_parse_rom(struct rtwn_softc *sc, uint8_t *buf) { diff --git a/sys/dev/rtwn/rtl8821a/r21a_rx.c b/sys/dev/rtwn/rtl8821a/r21a_rx.c index bd0721b3edc7..5670c2bf70d3 100644 --- a/sys/dev/rtwn/rtl8821a/r21a_rx.c +++ b/sys/dev/rtwn/rtl8821a/r21a_rx.c @@ -56,7 +56,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8821a/r21a.h> - int8_t r21a_get_rssi_cck(struct rtwn_softc *sc, void *physt) { diff --git a/sys/dev/rtwn/rtl8821a/usb/r21au.h b/sys/dev/rtwn/rtl8821a/usb/r21au.h index a327d2ad7fa6..5e000446a997 100644 --- a/sys/dev/rtwn/rtl8821a/usb/r21au.h +++ b/sys/dev/rtwn/rtl8821a/usb/r21au.h @@ -31,7 +31,6 @@ #include <dev/rtwn/rtl8821a/r21a.h> - /* * Function declarations. */ diff --git a/sys/dev/rtwn/rtl8821a/usb/r21au_attach.c b/sys/dev/rtwn/rtl8821a/usb/r21au_attach.c index 89a5bb870f7d..463d4876ae82 100644 --- a/sys/dev/rtwn/rtl8821a/usb/r21au_attach.c +++ b/sys/dev/rtwn/rtl8821a/usb/r21au_attach.c @@ -70,7 +70,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8821a/usb/r21au.h> - void r21au_attach(struct rtwn_usb_softc *); static void diff --git a/sys/dev/rtwn/rtl8821a/usb/r21au_dfs.c b/sys/dev/rtwn/rtl8821a/usb/r21au_dfs.c index ef230c852561..d1940d23e883 100644 --- a/sys/dev/rtwn/rtl8821a/usb/r21au_dfs.c +++ b/sys/dev/rtwn/rtl8821a/usb/r21au_dfs.c @@ -60,7 +60,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8821a/usb/r21au.h> #include <dev/rtwn/rtl8821a/usb/r21au_reg.h> - #define R21AU_RADAR_CHECK_PERIOD (2 * hz) static void diff --git a/sys/dev/rtwn/rtl8821a/usb/r21au_init.c b/sys/dev/rtwn/rtl8821a/usb/r21au_init.c index 140c291473d9..5f092def29b7 100644 --- a/sys/dev/rtwn/rtl8821a/usb/r21au_init.c +++ b/sys/dev/rtwn/rtl8821a/usb/r21au_init.c @@ -59,7 +59,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8821a/usb/r21au.h> #include <dev/rtwn/rtl8821a/usb/r21au_reg.h> - void r21au_init_tx_agg(struct rtwn_softc *sc) { @@ -69,4 +68,3 @@ r21au_init_tx_agg(struct rtwn_softc *sc) rtwn_write_1(sc, R21A_DWBCN1_CTRL, uc->tx_agg_desc_num << 1); } - diff --git a/sys/dev/rtwn/usb/rtwn_usb_attach.c b/sys/dev/rtwn/usb/rtwn_usb_attach.c index bdd6de217079..cb775bae3188 100644 --- a/sys/dev/rtwn/usb/rtwn_usb_attach.c +++ b/sys/dev/rtwn/usb/rtwn_usb_attach.c @@ -88,7 +88,6 @@ static void rtwn_usb_sysctlattach(struct rtwn_softc *); #define RTWN_CONFIG_INDEX 0 - static int rtwn_usb_match(device_t self) { diff --git a/sys/dev/rtwn/usb/rtwn_usb_attach.h b/sys/dev/rtwn/usb/rtwn_usb_attach.h index 9efa9ae330e3..40076dbb941c 100644 --- a/sys/dev/rtwn/usb/rtwn_usb_attach.h +++ b/sys/dev/rtwn/usb/rtwn_usb_attach.h @@ -158,6 +158,7 @@ static const STRUCT_USB_HOST_ID rtwn_devs[] = { RTWN_RTL8821AU_DEV(DLINK, DWA172A1), RTWN_RTL8821AU_DEV(EDIMAX, EW7811UTC_1), RTWN_RTL8821AU_DEV(EDIMAX, EW7811UTC_2), + RTWN_RTL8821AU_DEV(ELECOM, WDB433SU2M2), RTWN_RTL8821AU_DEV(HAWKING, HD65U), RTWN_RTL8821AU_DEV(MELCO, WIU2433DM), RTWN_RTL8821AU_DEV(MELCO, WIU2433DHP), diff --git a/sys/dev/rtwn/usb/rtwn_usb_ep.c b/sys/dev/rtwn/usb/rtwn_usb_ep.c index 4cbb011a5b1c..b6658b6a03d1 100644 --- a/sys/dev/rtwn/usb/rtwn_usb_ep.c +++ b/sys/dev/rtwn/usb/rtwn_usb_ep.c @@ -57,7 +57,6 @@ __FBSDID("$FreeBSD$"); #include <dev/rtwn/rtl8192c/usb/r92cu_reg.h> - static const struct usb_config rtwn_config_common[RTWN_N_TRANSFER] = { [RTWN_BULK_RX] = { .type = UE_BULK, diff --git a/sys/dev/rtwn/usb/rtwn_usb_reg.c b/sys/dev/rtwn/usb/rtwn_usb_reg.c index c464b69d7ece..fad6d04ec5ff 100644 --- a/sys/dev/rtwn/usb/rtwn_usb_reg.c +++ b/sys/dev/rtwn/usb/rtwn_usb_reg.c @@ -58,7 +58,6 @@ static int rtwn_usb_read_region_1(struct rtwn_softc *, /* USB Requests. */ #define R92C_REQ_REGS 0x05 - static int rtwn_do_request(struct rtwn_softc *sc, struct usb_device_request *req, void *data) diff --git a/sys/dev/rtwn/usb/rtwn_usb_tx.c b/sys/dev/rtwn/usb/rtwn_usb_tx.c index 2c5d55d3a56b..9e36474f1eca 100644 --- a/sys/dev/rtwn/usb/rtwn_usb_tx.c +++ b/sys/dev/rtwn/usb/rtwn_usb_tx.c @@ -67,12 +67,10 @@ static struct rtwn_data * rtwn_usb_getbuf(struct rtwn_usb_softc *); static void rtwn_usb_txeof(struct rtwn_usb_softc *, struct rtwn_data *, int); - static const uint8_t wme2qid[] = { RTWN_BULK_TX_BE, RTWN_BULK_TX_BK, RTWN_BULK_TX_VI, RTWN_BULK_TX_VO }; - static struct rtwn_data * _rtwn_usb_getbuf(struct rtwn_usb_softc *uc) { diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs index 7d0cd9a33cc5..2df411739313 100644 --- a/sys/dev/usb/usbdevs +++ b/sys/dev/usb/usbdevs @@ -1860,6 +1860,7 @@ product ELECOM LDUSBTX1 0x4002 LD-USB/TX product ELECOM LDUSBLTX 0x4005 LD-USBL/TX product ELECOM WDC150SU2M 0x4008 WDC-150SU2M product ELECOM LDUSBTX2 0x400b LD-USB/TX +product ELECOM WDB433SU2M2 0x400f WDB-433SU2M2 product ELECOM LDUSB20 0x4010 LD-USB20 product ELECOM UCSGT 0x5003 UC-SGT product ELECOM UCSGT0 0x5004 UC-SGT diff --git a/sys/dev/usb/wlan/if_rsu.c b/sys/dev/usb/wlan/if_rsu.c index 30d1fa1120ed..27a6c2a0aaa0 100644 --- a/sys/dev/usb/wlan/if_rsu.c +++ b/sys/dev/usb/wlan/if_rsu.c @@ -778,7 +778,8 @@ rsu_getradiocaps(struct ieee80211com *ic, if (sc->sc_ht) setbit(bands, IEEE80211_MODE_11NG); ieee80211_add_channels_default_2ghz(chans, maxchans, nchans, - bands, (ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40) != 0); + bands, (ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40) ? + NET80211_CBW_FLAG_HT40 : 0); } static void @@ -857,6 +858,18 @@ rsu_get_multi_pos(const uint8_t maddr[]) return (pos); } +static u_int +rsu_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt) +{ + uint32_t *mfilt = arg; + uint8_t pos; + + pos = rsu_get_multi_pos(LLADDR(sdl)); + mfilt[pos / 32] |= (1 << (pos % 32)); + + return (1); +} + static void rsu_set_multi(struct rsu_softc *sc) { @@ -868,28 +881,13 @@ rsu_set_multi(struct rsu_softc *sc) /* general structure was copied from ath(4). */ if (ic->ic_allmulti == 0) { struct ieee80211vap *vap; - struct ifnet *ifp; - struct ifmultiaddr *ifma; /* * Merge multicast addresses to form the hardware filter. */ mfilt[0] = mfilt[1] = 0; - TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { - ifp = vap->iv_ifp; - if_maddr_rlock(ifp); - CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { - caddr_t dl; - uint8_t pos; - - dl = LLADDR((struct sockaddr_dl *) - ifma->ifma_addr); - pos = rsu_get_multi_pos(dl); - - mfilt[pos / 32] |= (1 << (pos % 32)); - } - if_maddr_runlock(ifp); - } + TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) + if_foreach_llmaddr(vap->iv_ifp, rsu_hash_maddr, &mfilt); } else mfilt[0] = mfilt[1] = ~0; @@ -1984,7 +1982,7 @@ rsu_join_bss(struct rsu_softc *sc, struct ieee80211_node *ni) frm = ieee80211_add_qos(frm, ni); if ((ic->ic_flags & IEEE80211_F_WME) && (ni->ni_ies.wme_ie != NULL)) - frm = ieee80211_add_wme_info(frm, &ic->ic_wme); + frm = ieee80211_add_wme_info(frm, &ic->ic_wme, ni); if (ni->ni_flags & IEEE80211_NODE_HT) { frm = ieee80211_add_htcap(frm, ni); frm = ieee80211_add_htinfo(frm, ni); diff --git a/sys/dev/usb/wlan/if_run.c b/sys/dev/usb/wlan/if_run.c index 7b2bd0d51f24..9eb261274b62 100644 --- a/sys/dev/usb/wlan/if_run.c +++ b/sys/dev/usb/wlan/if_run.c @@ -63,6 +63,9 @@ __FBSDID("$FreeBSD$"); #include <net80211/ieee80211_regdomain.h> #include <net80211/ieee80211_radiotap.h> #include <net80211/ieee80211_ratectl.h> +#ifdef IEEE80211_SUPPORT_SUPERG +#include <net80211/ieee80211_superg.h> +#endif #include <dev/usb/usb.h> #include <dev/usb/usbdi.h> @@ -493,6 +496,9 @@ static void run_adjust_freq_offset(struct run_softc *); static void run_init_locked(struct run_softc *); static void run_stop(void *); static void run_delay(struct run_softc *, u_int); +static void run_update_chw(struct ieee80211com *ic); +static int run_ampdu_enable(struct ieee80211_node *ni, + struct ieee80211_tx_ampdu *tap); static eventhandler_tag run_etag; @@ -504,10 +510,13 @@ static const struct rt2860_rate { uint16_t sp_ack_dur; uint16_t lp_ack_dur; } rt2860_rates[] = { + /* CCK rates (11b) */ { 2, 0, IEEE80211_T_DS, 0, 314, 314 }, { 4, 1, IEEE80211_T_DS, 1, 258, 162 }, { 11, 2, IEEE80211_T_DS, 2, 223, 127 }, { 22, 3, IEEE80211_T_DS, 3, 213, 117 }, + + /* OFDM rates (11a / 11g) */ { 12, 0, IEEE80211_T_OFDM, 4, 60, 60 }, { 18, 1, IEEE80211_T_OFDM, 4, 52, 52 }, { 24, 2, IEEE80211_T_OFDM, 6, 48, 48 }, @@ -515,9 +524,46 @@ static const struct rt2860_rate { { 48, 4, IEEE80211_T_OFDM, 8, 44, 44 }, { 72, 5, IEEE80211_T_OFDM, 8, 40, 40 }, { 96, 6, IEEE80211_T_OFDM, 8, 40, 40 }, - { 108, 7, IEEE80211_T_OFDM, 8, 40, 40 } + { 108, 7, IEEE80211_T_OFDM, 8, 40, 40 }, + + /* MCS - single stream */ + { 0x80, 0, IEEE80211_T_HT, 4, 60, 60 }, + { 0x81, 1, IEEE80211_T_HT, 4, 60, 60 }, + { 0x82, 2, IEEE80211_T_HT, 4, 60, 60 }, + { 0x83, 3, IEEE80211_T_HT, 4, 60, 60 }, + { 0x84, 4, IEEE80211_T_HT, 4, 60, 60 }, + { 0x85, 5, IEEE80211_T_HT, 4, 60, 60 }, + { 0x86, 6, IEEE80211_T_HT, 4, 60, 60 }, + { 0x87, 7, IEEE80211_T_HT, 4, 60, 60 }, + + /* MCS - 2 streams */ + { 0x88, 8, IEEE80211_T_HT, 4, 60, 60 }, + { 0x89, 9, IEEE80211_T_HT, 4, 60, 60 }, + { 0x8a, 10, IEEE80211_T_HT, 4, 60, 60 }, + { 0x8b, 11, IEEE80211_T_HT, 4, 60, 60 }, + { 0x8c, 12, IEEE80211_T_HT, 4, 60, 60 }, + { 0x8d, 13, IEEE80211_T_HT, 4, 60, 60 }, + { 0x8e, 14, IEEE80211_T_HT, 4, 60, 60 }, + { 0x8f, 15, IEEE80211_T_HT, 4, 60, 60 }, + + /* MCS - 3 streams */ + { 0x90, 16, IEEE80211_T_HT, 4, 60, 60 }, + { 0x91, 17, IEEE80211_T_HT, 4, 60, 60 }, + { 0x92, 18, IEEE80211_T_HT, 4, 60, 60 }, + { 0x93, 19, IEEE80211_T_HT, 4, 60, 60 }, + { 0x94, 20, IEEE80211_T_HT, 4, 60, 60 }, + { 0x95, 21, IEEE80211_T_HT, 4, 60, 60 }, + { 0x96, 22, IEEE80211_T_HT, 4, 60, 60 }, + { 0x97, 23, IEEE80211_T_HT, 4, 60, 60 }, }; +/* These are indexes into the above rt2860_rates[] array */ +#define RT2860_RIDX_CCK1 0 +#define RT2860_RIDX_CCK11 3 +#define RT2860_RIDX_OFDM6 4 +#define RT2860_RIDX_MCS0 12 +#define RT2860_RIDX_MAX 36 + static const struct { uint16_t reg; uint32_t val; @@ -805,9 +851,27 @@ run_attach(device_t self) IEEE80211_C_MBSS | IEEE80211_C_SHPREAMBLE | /* short preamble supported */ IEEE80211_C_SHSLOT | /* short slot time supported */ + IEEE80211_C_SWAMSDUTX | /* Do software A-MSDU TX */ + IEEE80211_C_FF | /* Atheros fast-frames */ IEEE80211_C_WME | /* WME */ IEEE80211_C_WPA; /* WPA1|WPA2(RSN) */ + /* + * RF2020 is not an 11n device. + */ + if (sc->rf_rev != RT3070_RF_2020) { + device_printf(sc->sc_dev, "[HT] Enabling 802.11n\n"); + ic->ic_htcaps = + IEEE80211_HTC_HT | + IEEE80211_HTC_AMPDU | + IEEE80211_HTC_AMSDU | + IEEE80211_HTCAP_MAXAMSDU_3839 | + IEEE80211_HTCAP_SMPS_OFF; + + ic->ic_rxstream = sc->nrxchains; + ic->ic_txstream = sc->ntxchains; + } + ic->ic_cryptocaps = IEEE80211_CRYPTO_WEP | IEEE80211_CRYPTO_AES_CCM | @@ -837,6 +901,8 @@ run_attach(device_t self) ic->ic_vap_delete = run_vap_delete; ic->ic_transmit = run_transmit; ic->ic_parent = run_parent; + ic->ic_update_chw = run_update_chw; + ic->ic_ampdu_enable = run_ampdu_enable; ieee80211_radiotap_attach(ic, &sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap), @@ -972,6 +1038,17 @@ run_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, vap->iv_update_beacon = run_update_beacon; vap->iv_max_aid = RT2870_WCID_MAX; + + /* + * The linux rt2800 driver limits 1 stream devices to a 32KB + * RX AMPDU. + */ + if (ic->ic_rxstream > 1) + vap->iv_ampdu_rxmax = IEEE80211_HTCAP_MAXRXAMPDU_64K; + else + vap->iv_ampdu_rxmax = IEEE80211_HTCAP_MAXRXAMPDU_32K; + vap->iv_ampdu_density = IEEE80211_HTCAP_MPDUDENSITY_2; /* 2uS */ + /* * To delete the right key from h/w, we need wcid. * Luckily, there is unused space in ieee80211_key{}, wk_pad, @@ -2047,7 +2124,7 @@ run_media_change(struct ifnet *ifp) RUN_LOCK(sc); error = ieee80211_media_change(ifp); - if (error != ENETRESET) { + if (error != 0) { RUN_UNLOCK(sc); return (error); } @@ -2057,11 +2134,13 @@ run_media_change(struct ifnet *ifp) struct ieee80211_node *ni; struct run_node *rn; + /* XXX TODO: methodize with MCS rates */ rate = ic->ic_sup_rates[ic->ic_curmode]. rs_rates[tp->ucastrate] & IEEE80211_RATE_VAL; for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++) if (rt2860_rates[ridx].rate == rate) break; + ni = ieee80211_ref_node(vap->iv_bss); rn = RUN_NODE(ni); rn->fix_ridx = ridx; @@ -2603,7 +2682,7 @@ run_iter_func(void *arg, struct ieee80211_node *ni) struct run_node *rn = RUN_NODE(ni); union run_stats sta[2]; uint16_t (*wstat)[3]; - int error; + int error, ridx; RUN_LOCK(sc); @@ -2654,12 +2733,17 @@ run_iter_func(void *arg, struct ieee80211_node *ni) } ieee80211_ratectl_tx_update(vap, txs); - rn->amrr_ridx = ieee80211_ratectl_rate(ni, NULL, 0); + ieee80211_ratectl_rate(ni, NULL, 0); + /* XXX TODO: methodize with MCS rates */ + for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++) + if (rt2860_rates[ridx].rate == ni->ni_txrate) + break; + rn->amrr_ridx = ridx; fail: RUN_UNLOCK(sc); - RUN_DPRINTF(sc, RUN_DEBUG_RATE, "ridx=%d\n", rn->amrr_ridx); + RUN_DPRINTF(sc, RUN_DEBUG_RATE, "rate=%d, ridx=%d\n", ni->ni_txrate, rn->amrr_ridx); } static void @@ -2682,14 +2766,12 @@ static void run_newassoc(struct ieee80211_node *ni, int isnew) { struct run_node *rn = RUN_NODE(ni); - struct ieee80211_rateset *rs = &ni->ni_rates; struct ieee80211vap *vap = ni->ni_vap; struct ieee80211com *ic = vap->iv_ic; struct run_softc *sc = ic->ic_softc; uint8_t rate; uint8_t ridx; uint8_t wcid; - int i, j; wcid = (vap->iv_opmode == IEEE80211_M_STA) ? 1 : RUN_AID2WCID(ni->ni_associd); @@ -2719,31 +2801,8 @@ run_newassoc(struct ieee80211_node *ni, int isnew) "new assoc isnew=%d associd=%x addr=%s\n", isnew, ni->ni_associd, ether_sprintf(ni->ni_macaddr)); - for (i = 0; i < rs->rs_nrates; i++) { - rate = rs->rs_rates[i] & IEEE80211_RATE_VAL; - /* convert 802.11 rate to hardware rate index */ - for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++) - if (rt2860_rates[ridx].rate == rate) - break; - rn->ridx[i] = ridx; - /* determine rate of control response frames */ - for (j = i; j >= 0; j--) { - if ((rs->rs_rates[j] & IEEE80211_RATE_BASIC) && - rt2860_rates[rn->ridx[i]].phy == - rt2860_rates[rn->ridx[j]].phy) - break; - } - if (j >= 0) { - rn->ctl_ridx[i] = rn->ridx[j]; - } else { - /* no basic rate found, use mandatory one */ - rn->ctl_ridx[i] = rt2860_rates[ridx].ctl_ridx; - } - RUN_DPRINTF(sc, RUN_DEBUG_STATE | RUN_DEBUG_RATE, - "rate=0x%02x ridx=%d ctl_ridx=%d\n", - rs->rs_rates[i], rn->ridx[i], rn->ctl_ridx[i]); - } rate = vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)].mgmtrate; + /* XXX TODO: methodize with MCS rates */ for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++) if (rt2860_rates[ridx].rate == rate) break; @@ -2873,6 +2932,10 @@ run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen) } else ni = NULL; + if(ni && ni->ni_flags & IEEE80211_NODE_HT) { + m->m_flags |= M_AMPDU; + } + if (__predict_false(flags & RT2860_RX_MICERR)) { /* report MIC failures to net80211 for TKIP */ if (ni != NULL) @@ -2982,10 +3045,11 @@ run_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error) tr_setup: if (sc->rx_m == NULL) { sc->rx_m = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, - MJUMPAGESIZE /* xfer can be bigger than MCLBYTES */); + RUN_MAX_RXSZ); } if (sc->rx_m == NULL) { - RUN_DPRINTF(sc, RUN_DEBUG_RECV | RUN_DEBUG_RECV_DESC, + RUN_DPRINTF(sc, RUN_DEBUG_RECV | + RUN_DEBUG_RECV_DESC | RUN_DEBUG_USB, "could not allocate mbuf - idle with stall\n"); counter_u64_add(ic->ic_ierrors, 1); usbd_xfer_set_stall(xfer); @@ -3084,6 +3148,9 @@ tr_setup: /* make sure we free the source buffer, if any */ m_freem(m); +#ifdef IEEE80211_SUPPORT_SUPERG + ieee80211_ff_age_all(ic, 100); +#endif RUN_LOCK(sc); } @@ -3229,6 +3296,15 @@ tr_setup: } break; } +#ifdef IEEE80211_SUPPORT_SUPERG + /* XXX TODO: make this deferred rather than unlock/relock */ + /* XXX TODO: should only do the QoS AC this belongs to */ + if (pq->tx_nfree >= RUN_TX_RING_COUNT) { + RUN_UNLOCK(sc); + ieee80211_ff_flush_all(ic); + RUN_LOCK(sc); + } +#endif } static void @@ -3313,15 +3389,21 @@ run_set_tx_desc(struct run_softc *sc, struct run_tx_data *data) if (ridx != RT2860_RIDX_CCK1 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE)) mcs |= RT2860_PHY_SHPRE; - } else + } else if (rt2860_rates[ridx].phy == IEEE80211_T_OFDM) { mcs |= RT2860_PHY_OFDM; + } else if (rt2860_rates[ridx].phy == IEEE80211_T_HT) { + /* XXX TODO: [adrian] set short preamble for MCS? */ + mcs |= RT2860_PHY_HT_MIX; /* Mixed, not greenfield */ + } txwi->phy = htole16(mcs); /* check if RTS/CTS or CTS-to-self protection is required */ if (!IEEE80211_IS_MULTICAST(wh->i_addr1) && - (m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold || + ((m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold) || ((ic->ic_flags & IEEE80211_F_USEPROT) && - rt2860_rates[ridx].phy == IEEE80211_T_OFDM))) + rt2860_rates[ridx].phy == IEEE80211_T_OFDM) || + ((ic->ic_htprotmode == IEEE80211_PROT_RTSCTS) && + rt2860_rates[ridx].phy == IEEE80211_T_HT))) txwi->txop |= RT2860_TX_TXOP_HT; else txwi->txop |= RT2860_TX_TXOP_BACKOFF; @@ -3385,7 +3467,8 @@ run_tx(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni) /* pickup a rate index */ if (IEEE80211_IS_MULTICAST(wh->i_addr1) || type != IEEE80211_FC0_TYPE_DATA || m->m_flags & M_EAPOL) { - ridx = (ic->ic_curmode == IEEE80211_MODE_11A) ? + /* XXX TODO: methodize for 11n; use MCS0 for 11NA/11NG */ + ridx = (ic->ic_curmode == IEEE80211_MODE_11A || ic->ic_curmode == IEEE80211_MODE_11NA) ? RT2860_RIDX_OFDM6 : RT2860_RIDX_CCK1; ctl_ridx = rt2860_rates[ridx].ctl_ridx; } else { @@ -3604,6 +3687,7 @@ run_sendprot(struct run_softc *sc, data->m = mprot; data->ni = ieee80211_ref_node(ni); + /* XXX TODO: methodize with MCS rates */ for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++) if (rt2860_rates[ridx].rate == protrate) break; @@ -3679,6 +3763,7 @@ run_tx_param(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni, data->m = m; data->ni = ni; + /* XXX TODO: methodize with MCS rates */ for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++) if (rt2860_rates[ridx].rate == rate) break; @@ -4851,12 +4936,19 @@ run_getradiocaps(struct ieee80211com *ic, memset(bands, 0, sizeof(bands)); setbit(bands, IEEE80211_MODE_11B); setbit(bands, IEEE80211_MODE_11G); + if (sc->rf_rev != RT3070_RF_2020) + setbit(bands, IEEE80211_MODE_11NG); + + /* Note: for now, only support HT20 channels */ ieee80211_add_channels_default_2ghz(chans, maxchans, nchans, bands, 0); if (sc->rf_rev == RT2860_RF_2750 || sc->rf_rev == RT2860_RF_2850 || sc->rf_rev == RT3070_RF_3052 || sc->rf_rev == RT3593_RF_3053 || sc->rf_rev == RT5592_RF_5592) { setbit(bands, IEEE80211_MODE_11A); + if (sc->rf_rev != RT3070_RF_2020) + setbit(bands, IEEE80211_MODE_11NA); + /* Note: for now, only support HT20 channels */ ieee80211_add_channel_list_5ghz(chans, maxchans, nchans, run_chan_5ghz, nitems(run_chan_5ghz), bands, 0); } @@ -6200,6 +6292,10 @@ run_init_locked(struct run_softc *sc) /* turn radio LED on */ run_set_leds(sc, RT2860_LED_RADIO); + /* Set up AUTO_RSP_CFG register for auto response */ + run_write(sc, RT2860_AUTO_RSP_CFG, RT2860_AUTO_RSP_EN | + RT2860_BAC_ACKPOLICY_EN | RT2860_CTS_40M_MODE_EN); + sc->sc_flags |= RUN_RUNNING; sc->cmdq_run = RUN_CMDQ_GO; @@ -6306,6 +6402,22 @@ run_delay(struct run_softc *sc, u_int ms) &sc->sc_mtx : NULL, USB_MS_TO_TICKS(ms)); } + +static void +run_update_chw(struct ieee80211com *ic) +{ + + printf("%s: TODO\n", __func__); +} + +static int +run_ampdu_enable(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap) +{ + + /* For now, no A-MPDU TX support in the driver */ + return (0); +} + static device_method_t run_methods[] = { /* Device interface */ DEVMETHOD(device_probe, run_match), diff --git a/sys/dev/usb/wlan/if_runreg.h b/sys/dev/usb/wlan/if_runreg.h index 8561d2c14947..ded41b62b3e5 100644 --- a/sys/dev/usb/wlan/if_runreg.h +++ b/sys/dev/usb/wlan/if_runreg.h @@ -781,7 +781,7 @@ struct rt2860_txwi { #define RT2860_PHY_MODE 0xc000 #define RT2860_PHY_CCK (0 << 14) #define RT2860_PHY_OFDM (1 << 14) -#define RT2860_PHY_HT (2 << 14) +#define RT2860_PHY_HT_MIX (2 << 14) #define RT2860_PHY_HT_GF (3 << 14) #define RT2860_PHY_SGI (1 << 8) #define RT2860_PHY_BW40 (1 << 7) @@ -955,11 +955,6 @@ struct rt2860_rxwi { #define RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH140_TO_CH165_5GHZ 0x14e #define RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH140_TO_CH165_5GHZ 0x14f -#define RT2860_RIDX_CCK1 0 -#define RT2860_RIDX_CCK11 3 -#define RT2860_RIDX_OFDM6 4 -#define RT2860_RIDX_MAX 12 - /* * EEPROM access macro. */ diff --git a/sys/dev/usb/wlan/if_runvar.h b/sys/dev/usb/wlan/if_runvar.h index a17d5b467d36..bb6231c3f947 100644 --- a/sys/dev/usb/wlan/if_runvar.h +++ b/sys/dev/usb/wlan/if_runvar.h @@ -23,14 +23,15 @@ #ifndef _IF_RUNVAR_H_ #define _IF_RUNVAR_H_ +/* Support up to 4KB frames - useful for A-MSDU/FF. */ #define RUN_MAX_RXSZ \ MIN(4096, MJUMPAGESIZE) -/* NB: "11" is the maximum number of padding bytes needed for Tx */ +/* Support up to 8KB frames - useful for A-MSDU/FF. */ #define RUN_MAX_TXSZ \ (sizeof (struct rt2870_txd) + \ sizeof (struct rt2860_txwi) + \ - MCLBYTES + 11) + 8192 + 11) #define RUN_TX_TIMEOUT 5000 /* ms */ @@ -97,8 +98,6 @@ STAILQ_HEAD(run_tx_data_head, run_tx_data); struct run_node { struct ieee80211_node ni; - uint8_t ridx[IEEE80211_RATE_MAXSIZE]; - uint8_t ctl_ridx[IEEE80211_RATE_MAXSIZE]; uint8_t amrr_ridx; uint8_t mgt_ridx; uint8_t fix_ridx; diff --git a/sys/dev/usb/wlan/if_zyd.c b/sys/dev/usb/wlan/if_zyd.c index 852587d417c5..d823034ea94f 100644 --- a/sys/dev/usb/wlan/if_zyd.c +++ b/sys/dev/usb/wlan/if_zyd.c @@ -1970,49 +1970,48 @@ fail: return (error); } +static u_int +zyd_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt) +{ + uint32_t *hash = arg; + uint8_t v; + + v = ((uint8_t *)LLADDR(sdl))[5] >> 2; + if (v < 32) + hash[0] |= 1 << v; + else + hash[1] |= 1 << (v - 32); + + return (1); +} + static void zyd_set_multi(struct zyd_softc *sc) { struct ieee80211com *ic = &sc->sc_ic; - uint32_t low, high; + uint32_t hash[2]; int error; if ((sc->sc_flags & ZYD_FLAG_RUNNING) == 0) return; - low = 0x00000000; - high = 0x80000000; + hash[0] = 0x00000000; + hash[1] = 0x80000000; if (ic->ic_opmode == IEEE80211_M_MONITOR || ic->ic_allmulti > 0 || ic->ic_promisc > 0) { - low = 0xffffffff; - high = 0xffffffff; + hash[0] = 0xffffffff; + hash[1] = 0xffffffff; } else { struct ieee80211vap *vap; - struct ifnet *ifp; - struct ifmultiaddr *ifma; - uint8_t v; - - TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { - ifp = vap->iv_ifp; - if_maddr_rlock(ifp); - CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { - if (ifma->ifma_addr->sa_family != AF_LINK) - continue; - v = ((uint8_t *)LLADDR((struct sockaddr_dl *) - ifma->ifma_addr))[5] >> 2; - if (v < 32) - low |= 1 << v; - else - high |= 1 << (v - 32); - } - if_maddr_runlock(ifp); - } + + TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) + if_foreach_llmaddr(vap->iv_ifp, zyd_hash_maddr, &hash); } /* reprogram multicast global hash table */ - zyd_write32_m(sc, ZYD_MAC_GHTBL, low); - zyd_write32_m(sc, ZYD_MAC_GHTBH, high); + zyd_write32_m(sc, ZYD_MAC_GHTBL, hash[0]); + zyd_write32_m(sc, ZYD_MAC_GHTBH, hash[1]); fail: if (error != 0) device_printf(sc->sc_dev, diff --git a/sys/dev/wi/if_wavelan_ieee.h b/sys/dev/wi/if_wavelan_ieee.h index dd8a9883eda3..27b7ed0f80bb 100644 --- a/sys/dev/wi/if_wavelan_ieee.h +++ b/sys/dev/wi/if_wavelan_ieee.h @@ -478,7 +478,6 @@ struct wi_rx_frame { #define WI_MGMT_HDRLEN 0x3C #define WI_CTL_HDRLEN 0x3C - /* * all data packets have a snap (sub-network access protocol) header that * isn't entirely definied, but added for ethernet compatibility. @@ -488,7 +487,6 @@ struct wi_snap_frame { u_int16_t wi_type; }; - /* * management frame headers * note: all management frames consist of a static header and variable length @@ -592,7 +590,6 @@ struct wi_mgmt_deauth_hdr { u_int16_t wi_reason; }; - /* * rid configuration register definitions */ @@ -602,7 +599,6 @@ struct wi_mgmt_deauth_hdr { #define WI_RID_PROCFRAME 0x3137 /* Return full frame information */ #define WI_RID_PRISM2 0x3138 /* tell if we're a prism2 card or not */ - /* * 802.11 definitions */ @@ -650,7 +646,6 @@ struct wi_mgmt_deauth_hdr { #define WI_FCS_LEN 0x4 /* checksum length */ - /* * management definitions */ @@ -693,7 +688,6 @@ struct wi_mgmt_deauth_hdr { #define WI_VAR_SRATES_MASK 0x7F - /* * control definitions */ @@ -704,7 +698,6 @@ struct wi_mgmt_deauth_hdr { #define WI_STYPE_CTL_CFEND 0x00E0 #define WI_STYPE_CTL_CFENDCFACK 0x00F0 - /* * ap scanning structures */ @@ -729,7 +722,6 @@ struct wi_scan_p2_hdr { }; #define WI_PRISM2_RES_SIZE 62 - /* * prism2 debug mode definitions */ diff --git a/sys/dev/wi/if_wi.c b/sys/dev/wi/if_wi.c index 35eb5343d7d7..96b16e6af1d9 100644 --- a/sys/dev/wi/if_wi.c +++ b/sys/dev/wi/if_wi.c @@ -162,7 +162,7 @@ static void wi_scan_end(struct ieee80211com *); static void wi_getradiocaps(struct ieee80211com *, int, int *, struct ieee80211_channel[]); static void wi_set_channel(struct ieee80211com *); - + static __inline int wi_write_val(struct wi_softc *sc, int rid, u_int16_t val) { @@ -1506,41 +1506,45 @@ finish: CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO); } +struct wi_mcast_ctx { + struct wi_mcast mlist; + int mcnt; +}; + +static u_int +wi_copy_mcast(void *arg, struct sockaddr_dl *sdl, u_int count) +{ + struct wi_mcast_ctx *ctx = arg; + + if (ctx->mcnt >= 16) + return (0); + IEEE80211_ADDR_COPY(&ctx->mlist.wi_mcast[ctx->mcnt++], LLADDR(sdl)); + + return (1); +} + static int wi_write_multi(struct wi_softc *sc) { struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap; - struct wi_mcast mlist; - int n; + struct wi_mcast_ctx ctx; if (ic->ic_allmulti > 0 || ic->ic_promisc > 0) { allmulti: - memset(&mlist, 0, sizeof(mlist)); - return wi_write_rid(sc, WI_RID_MCAST_LIST, &mlist, - sizeof(mlist)); + memset(&ctx.mlist, 0, sizeof(ctx.mlist)); + return wi_write_rid(sc, WI_RID_MCAST_LIST, &ctx.mlist, + sizeof(ctx.mlist)); } - n = 0; + ctx.mcnt = 0; TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { - struct ifnet *ifp; - struct ifmultiaddr *ifma; - - ifp = vap->iv_ifp; - if_maddr_rlock(ifp); - CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { - if (ifma->ifma_addr->sa_family != AF_LINK) - continue; - if (n >= 16) - goto allmulti; - IEEE80211_ADDR_COPY(&mlist.wi_mcast[n], - (LLADDR((struct sockaddr_dl *)ifma->ifma_addr))); - n++; - } - if_maddr_runlock(ifp); + if_foreach_llmaddr(vap->iv_ifp, wi_copy_mcast, &ctx); + if (ctx.mcnt >= 16) + goto allmulti; } - return wi_write_rid(sc, WI_RID_MCAST_LIST, &mlist, - IEEE80211_ADDR_LEN * n); + return wi_write_rid(sc, WI_RID_MCAST_LIST, &ctx.mlist, + IEEE80211_ADDR_LEN * ctx.mcnt); } static void diff --git a/sys/dev/wi/if_wi_macio.c b/sys/dev/wi/if_wi_macio.c index 438dde0fb994..42f86c91c60d 100644 --- a/sys/dev/wi/if_wi_macio.c +++ b/sys/dev/wi/if_wi_macio.c @@ -87,7 +87,6 @@ static device_method_t wi_macio_methods[] = { DEVMETHOD(device_attach, wi_macio_attach), DEVMETHOD(device_detach, wi_detach), DEVMETHOD(device_shutdown, wi_shutdown), - { 0, 0 } }; diff --git a/sys/dev/wi/if_wi_pccard.c b/sys/dev/wi/if_wi_pccard.c index 9c84c01c9b96..ef24271f4ab5 100644 --- a/sys/dev/wi/if_wi_pccard.c +++ b/sys/dev/wi/if_wi_pccard.c @@ -85,7 +85,6 @@ static device_method_t wi_pccard_methods[] = { DEVMETHOD(device_attach, wi_pccard_attach), DEVMETHOD(device_detach, wi_detach), DEVMETHOD(device_shutdown, wi_shutdown), - { 0, 0 } }; diff --git a/sys/dev/wi/if_wi_pci.c b/sys/dev/wi/if_wi_pci.c index c0431617d4be..e537239408a5 100644 --- a/sys/dev/wi/if_wi_pci.c +++ b/sys/dev/wi/if_wi_pci.c @@ -84,7 +84,6 @@ static device_method_t wi_pci_methods[] = { DEVMETHOD(device_shutdown, wi_shutdown), DEVMETHOD(device_suspend, wi_pci_suspend), DEVMETHOD(device_resume, wi_pci_resume), - { 0, 0 } }; @@ -246,7 +245,7 @@ wi_pci_suspend(device_t dev) WI_LOCK(sc); wi_stop(sc, 1); WI_UNLOCK(sc); - + return (0); } diff --git a/sys/dev/wpi/if_wpireg.h b/sys/dev/wpi/if_wpireg.h index b0154f22bc5e..04ef481fe08b 100644 --- a/sys/dev/wpi/if_wpireg.h +++ b/sys/dev/wpi/if_wpireg.h @@ -92,7 +92,6 @@ #define WPI_FH_MSG_CONFIG 0xe88 #define WPI_FH_TX_STATUS 0xe90 - /* * NIC internal memory offsets. */ @@ -119,7 +118,6 @@ #define WPI_BSM_DRAM_DATA_SIZE 0x349c #define WPI_BSM_SRAM_BASE 0x3800 - /* Possible flags for register WPI_HW_IF_CONFIG. */ #define WPI_HW_IF_CONFIG_ALM_MB (1 << 8) #define WPI_HW_IF_CONFIG_ALM_MM (1 << 9) @@ -558,7 +556,6 @@ struct wpi_beacon_missed { uint32_t received; } __packed; - /* Structure for command WPI_CMD_MRR_SETUP. */ #define WPI_RIDX_MAX 11 struct wpi_mrr_setup { @@ -806,7 +803,6 @@ struct wpi_stats { /* Possible flags for command WPI_CMD_GET_STATISTICS. */ #define WPI_STATISTICS_BEACON_DISABLE (1 << 1) - /* Firmware error dump entry. */ struct wpi_fw_dump { uint32_t desc; @@ -818,7 +814,6 @@ struct wpi_fw_dump { /* Firmware image file header. */ struct wpi_firmware_hdr { - #define WPI_FW_MINVERSION 2144 #define WPI_FW_NAME "wpifw" diff --git a/sys/dev/wtap/if_wtap.c b/sys/dev/wtap/if_wtap.c index 6129d9d879f3..8f50c00a1f11 100644 --- a/sys/dev/wtap/if_wtap.c +++ b/sys/dev/wtap/if_wtap.c @@ -149,16 +149,6 @@ wtap_medium_enqueue(struct wtap_vap *avp, struct mbuf *m) return medium_transmit(avp->av_md, avp->id, m); } -static int -wtap_media_change(struct ifnet *ifp) -{ - - DWTAP_PRINTF("%s\n", __func__); - int error = ieee80211_media_change(ifp); - /* NB: only the fixed rate can change and that doesn't need a reset */ - return (error == ENETRESET ? 0 : error); -} - /* * Intercept management frames to collect beacon rssi data * and to do ibss merges. @@ -351,8 +341,8 @@ wtap_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], vap->iv_bmiss = wtap_bmiss; /* complete setup */ - ieee80211_vap_attach(vap, wtap_media_change, ieee80211_media_status, - mac); + ieee80211_vap_attach(vap, ieee80211_media_change, + ieee80211_media_status, mac); avp->av_dev = make_dev(&wtap_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "%s", (const char *)sc->name); diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c index 8d3583673776..60cbea3c9849 100644 --- a/sys/kern/kern_jail.c +++ b/sys/kern/kern_jail.c @@ -3132,10 +3132,8 @@ prison_priv_check(struct ucred *cred, int priv) /* * 802.11-related privileges. */ - case PRIV_NET80211_GETKEY: -#ifdef notyet - case PRIV_NET80211_MANAGE: /* XXX-BZ discuss with sam@ */ -#endif + case PRIV_NET80211_VAP_GETKEY: + case PRIV_NET80211_VAP_MANAGE: #ifdef notyet /* diff --git a/sys/net80211/_ieee80211.h b/sys/net80211/_ieee80211.h index 354362fcf09e..38ab1acb1c65 100644 --- a/sys/net80211/_ieee80211.h +++ b/sys/net80211/_ieee80211.h @@ -157,7 +157,7 @@ struct ieee80211_channel { /* * Note: for VHT operation we will need significantly more than * IEEE80211_CHAN_MAX channels because of the combinations of - * VHT20, VHT40, VHT80, VHT80+80 and VHT160. + * VHT20, VHT40, VHT80, VHT160, and VHT80+80. */ #define IEEE80211_CHAN_MAX 1024 #define IEEE80211_CHAN_BYTES howmany(IEEE80211_CHAN_MAX, NBBY) @@ -194,8 +194,8 @@ struct ieee80211_channel { #define IEEE80211_CHAN_VHT40U 0x02000000 /* VHT40 channel, ext above */ #define IEEE80211_CHAN_VHT40D 0x04000000 /* VHT40 channel, ext below */ #define IEEE80211_CHAN_VHT80 0x08000000 /* VHT80 channel */ -#define IEEE80211_CHAN_VHT80_80 0x10000000 /* VHT80+80 channel */ -#define IEEE80211_CHAN_VHT160 0x20000000 /* VHT160 channel */ +#define IEEE80211_CHAN_VHT160 0x10000000 /* VHT160 channel */ +#define IEEE80211_CHAN_VHT80P80 0x20000000 /* VHT80+80 channel */ /* XXX note: 0x80000000 is used in src/sbin/ifconfig/ifieee80211.c :( */ #define IEEE80211_CHAN_HT40 (IEEE80211_CHAN_HT40U | IEEE80211_CHAN_HT40D) @@ -203,14 +203,14 @@ struct ieee80211_channel { #define IEEE80211_CHAN_VHT40 (IEEE80211_CHAN_VHT40U | IEEE80211_CHAN_VHT40D) #define IEEE80211_CHAN_VHT (IEEE80211_CHAN_VHT20 | IEEE80211_CHAN_VHT40 \ - | IEEE80211_CHAN_VHT80 | IEEE80211_CHAN_VHT80_80 \ - | IEEE80211_CHAN_VHT160) + | IEEE80211_CHAN_VHT80 | IEEE80211_CHAN_VHT160 \ + | IEEE80211_CHAN_VHT80P80) #define IEEE80211_CHAN_BITS \ "\20\1PRIV0\2PRIV2\3PRIV3\4PRIV4\5TURBO\6CCK\7OFDM\0102GHZ\0115GHZ" \ "\12PASSIVE\13DYN\14GFSK\15GSM\16STURBO\17HALF\20QUARTER\21HT20" \ "\22HT40U\23HT40D\24DFS\0254MSXMIT\26NOADHOC\27NOHOSTAP\03011D" \ - "\031VHT20\032VHT40U\033VHT40D\034VHT80\035VHT80_80\036VHT160" + "\031VHT20\032VHT40U\033VHT40D\034VHT80\035VHT160\036VHT80P80" /* * Useful combinations of channel characteristics. @@ -337,10 +337,10 @@ struct ieee80211_channel { ((_c)->ic_flags & IEEE80211_CHAN_VHT) != 0) #define IEEE80211_IS_CHAN_VHT80(_c) \ (((_c)->ic_flags & IEEE80211_CHAN_VHT80) != 0) -#define IEEE80211_IS_CHAN_VHT80_80(_c) \ - (((_c)->ic_flags & IEEE80211_CHAN_VHT80_80) != 0) #define IEEE80211_IS_CHAN_VHT160(_c) \ (((_c)->ic_flags & IEEE80211_CHAN_VHT160) != 0) +#define IEEE80211_IS_CHAN_VHT80P80(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_VHT80P80) != 0) #define IEEE80211_CHAN2IEEE(_c) (_c)->ic_ieee @@ -488,6 +488,7 @@ struct ieee80211_mimo_info { #define IEEE80211_C_MBSS 0x00040000 /* CAPABILITY: MBSS available */ #define IEEE80211_C_SWSLEEP 0x00080000 /* CAPABILITY: do sleep here */ #define IEEE80211_C_SWAMSDUTX 0x00100000 /* CAPABILITY: software A-MSDU TX */ +#define IEEE80211_C_UAPSD 0x00200000 /* CAPABILITY: U-APSD */ /* 0x7c0000 available */ #define IEEE80211_C_WPA1 0x00800000 /* CAPABILITY: WPA1 avail */ #define IEEE80211_C_WPA2 0x01000000 /* CAPABILITY: WPA2 avail */ @@ -529,10 +530,13 @@ struct ieee80211_mimo_info { #define IEEE80211_HTC_TXUNEQUAL 0x00800000 /* CAPABILITY: TX unequal MCS */ #define IEEE80211_HTC_TXMCS32 0x01000000 /* CAPABILITY: MCS32 support */ #define IEEE80211_HTC_TXLDPC 0x02000000 /* CAPABILITY: TX using LDPC */ +#define IEEE80211_HTC_RX_AMSDU_AMPDU 0x04000000 /* CAPABILITY: RX A-MSDU in A-MPDU */ +#define IEEE80211_HTC_TX_AMSDU_AMPDU 0x08000000 /* CAPABILITY: TX A-MSDU in A-MPDU */ #define IEEE80211_C_HTCAP_BITS \ "\20\1LDPC\2CHWIDTH40\5GREENFIELD\6SHORTGI20\7SHORTGI40\10TXSTBC" \ - "\21AMPDU\22AMSDU\23HT\24SMPS\25RIFS\32TXLDPC" + "\21AMPDU\22AMSDU\23HT\24SMPS\25RIFS\32TXLDPC\33RXAMSDUAMPDU" \ + "\34TXAMSDUAMPDU" /* * RX status notification - which fields are valid. diff --git a/sys/net80211/ieee80211.c b/sys/net80211/ieee80211.c index a36abf1aa0d9..68a13ec8b2f1 100644 --- a/sys/net80211/ieee80211.c +++ b/sys/net80211/ieee80211.c @@ -529,8 +529,7 @@ ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap, ifp = if_alloc(IFT_ETHER); if (ifp == NULL) { - ic_printf(ic, "%s: unable to allocate ifnet\n", - __func__); + ic_printf(ic, "%s: unable to allocate ifnet\n", __func__); return ENOMEM; } if_initname(ifp, name, unit); @@ -616,6 +615,12 @@ ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap, if (vap->iv_opmode == IEEE80211_M_HOSTAP && (vap->iv_caps & IEEE80211_C_DFS)) vap->iv_flags_ext |= IEEE80211_FEXT_DFS; + /* NB: only flip on U-APSD for hostap/sta for now */ + if ((vap->iv_opmode == IEEE80211_M_STA) + || (vap->iv_opmode == IEEE80211_M_HOSTAP)) { + if (vap->iv_caps & IEEE80211_C_UAPSD) + vap->iv_flags_ext |= IEEE80211_FEXT_UAPSD; + } vap->iv_des_chan = IEEE80211_CHAN_ANYC; /* any channel is ok */ vap->iv_bmissthreshold = IEEE80211_HWBMISS_DEFAULT; @@ -645,6 +650,7 @@ ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap, ieee80211_scan_vattach(vap); ieee80211_regdomain_vattach(vap); ieee80211_radiotap_vattach(vap); + ieee80211_vap_reset_erp(vap); ieee80211_ratectl_set(vap, IEEE80211_RATECTL_NONE); return 0; @@ -1162,23 +1168,17 @@ set_vht_extchan(struct ieee80211_channel *c) { int i; - if (! IEEE80211_IS_CHAN_VHT(c)) { + if (! IEEE80211_IS_CHAN_VHT(c)) return (0); - } - if (IEEE80211_IS_CHAN_VHT20(c)) { - c->ic_vht_ch_freq1 = c->ic_ieee; - return (1); + if (IEEE80211_IS_CHAN_VHT80P80(c)) { + printf("%s: TODO VHT80+80 channel (ieee=%d, flags=0x%08x)\n", + __func__, c->ic_ieee, c->ic_flags); } - if (IEEE80211_IS_CHAN_VHT40(c)) { - if (IEEE80211_IS_CHAN_HT40U(c)) - c->ic_vht_ch_freq1 = c->ic_ieee + 2; - else if (IEEE80211_IS_CHAN_HT40D(c)) - c->ic_vht_ch_freq1 = c->ic_ieee - 2; - else - return (0); - return (1); + if (IEEE80211_IS_CHAN_VHT160(c)) { + printf("%s: TODO VHT160 channel (ieee=%d, flags=0x%08x)\n", + __func__, c->ic_ieee, c->ic_flags); } if (IEEE80211_IS_CHAN_VHT80(c)) { @@ -1202,10 +1202,23 @@ set_vht_extchan(struct ieee80211_channel *c) return (0); } + if (IEEE80211_IS_CHAN_VHT40(c)) { + if (IEEE80211_IS_CHAN_HT40U(c)) + c->ic_vht_ch_freq1 = c->ic_ieee + 2; + else if (IEEE80211_IS_CHAN_HT40D(c)) + c->ic_vht_ch_freq1 = c->ic_ieee - 2; + else + return (0); + return (1); + } + + if (IEEE80211_IS_CHAN_VHT20(c)) { + c->ic_vht_ch_freq1 = c->ic_ieee; + return (1); + } + printf("%s: unknown VHT channel type (ieee=%d, flags=0x%08x)\n", - __func__, - c->ic_ieee, - c->ic_flags); + __func__, c->ic_ieee, c->ic_flags); return (0); } @@ -1240,11 +1253,7 @@ addchan(struct ieee80211_channel chans[], int maxchans, int *nchans, #if 0 printf("%s: %d: ieee=%d, freq=%d, flags=0x%08x\n", - __func__, - *nchans, - ieee, - freq, - flags); + __func__, *nchans, ieee, freq, flags); #endif c = &chans[(*nchans)++]; @@ -1274,9 +1283,7 @@ copychan_prev(struct ieee80211_channel chans[], int maxchans, int *nchans, #if 0 printf("%s: %d: flags=0x%08x\n", - __func__, - *nchans, - flags); + __func__, *nchans, flags); #endif c = &chans[(*nchans)++]; @@ -1294,7 +1301,7 @@ copychan_prev(struct ieee80211_channel chans[], int maxchans, int *nchans, * XXX VHT-2GHz */ static void -getflags_2ghz(const uint8_t bands[], uint32_t flags[], int ht40) +getflags_2ghz(const uint8_t bands[], uint32_t flags[], int cbw_flags) { int nmodes; @@ -1305,7 +1312,7 @@ getflags_2ghz(const uint8_t bands[], uint32_t flags[], int ht40) flags[nmodes++] = IEEE80211_CHAN_G; if (isset(bands, IEEE80211_MODE_11NG)) flags[nmodes++] = IEEE80211_CHAN_G | IEEE80211_CHAN_HT20; - if (ht40) { + if (cbw_flags & NET80211_CBW_FLAG_HT40) { flags[nmodes++] = IEEE80211_CHAN_G | IEEE80211_CHAN_HT40U; flags[nmodes++] = IEEE80211_CHAN_G | IEEE80211_CHAN_HT40D; } @@ -1313,12 +1320,12 @@ getflags_2ghz(const uint8_t bands[], uint32_t flags[], int ht40) } static void -getflags_5ghz(const uint8_t bands[], uint32_t flags[], int ht40, int vht80) +getflags_5ghz(const uint8_t bands[], uint32_t flags[], int cbw_flags) { int nmodes; /* - * the addchan_list function seems to expect the flags array to + * The addchan_list() function seems to expect the flags array to * be in channel width order, so the VHT bits are interspersed * as appropriate to maintain said order. * @@ -1337,36 +1344,51 @@ getflags_5ghz(const uint8_t bands[], uint32_t flags[], int ht40, int vht80) } /* 40MHz */ - if (ht40) { + if (cbw_flags & NET80211_CBW_FLAG_HT40) flags[nmodes++] = IEEE80211_CHAN_A | IEEE80211_CHAN_HT40U; - } - if (ht40 && isset(bands, IEEE80211_MODE_VHT_5GHZ)) { - flags[nmodes++] = IEEE80211_CHAN_A | IEEE80211_CHAN_HT40U - | IEEE80211_CHAN_VHT40U; - } - if (ht40) { + if ((cbw_flags & NET80211_CBW_FLAG_HT40) && + isset(bands, IEEE80211_MODE_VHT_5GHZ)) + flags[nmodes++] = IEEE80211_CHAN_A | IEEE80211_CHAN_HT40U | + IEEE80211_CHAN_VHT40U; + if (cbw_flags & NET80211_CBW_FLAG_HT40) flags[nmodes++] = IEEE80211_CHAN_A | IEEE80211_CHAN_HT40D; + if ((cbw_flags & NET80211_CBW_FLAG_HT40) && + isset(bands, IEEE80211_MODE_VHT_5GHZ)) + flags[nmodes++] = IEEE80211_CHAN_A | IEEE80211_CHAN_HT40D | + IEEE80211_CHAN_VHT40D; + + /* 80MHz */ + if ((cbw_flags & NET80211_CBW_FLAG_VHT80) && + isset(bands, IEEE80211_MODE_VHT_5GHZ)) { + flags[nmodes++] = IEEE80211_CHAN_A | IEEE80211_CHAN_HT40U | + IEEE80211_CHAN_VHT80; + flags[nmodes++] = IEEE80211_CHAN_A | IEEE80211_CHAN_HT40D | + IEEE80211_CHAN_VHT80; } - if (ht40 && isset(bands, IEEE80211_MODE_VHT_5GHZ)) { - flags[nmodes++] = IEEE80211_CHAN_A | IEEE80211_CHAN_HT40D - | IEEE80211_CHAN_VHT40D; + + /* VHT160 */ + if ((cbw_flags & NET80211_CBW_FLAG_VHT160) && + isset(bands, IEEE80211_MODE_VHT_5GHZ)) { + flags[nmodes++] = IEEE80211_CHAN_A | IEEE80211_CHAN_HT40U | + IEEE80211_CHAN_VHT160; + flags[nmodes++] = IEEE80211_CHAN_A | IEEE80211_CHAN_HT40D | + IEEE80211_CHAN_VHT160; } - /* 80MHz */ - if (vht80 && isset(bands, IEEE80211_MODE_VHT_5GHZ)) { - flags[nmodes++] = IEEE80211_CHAN_A | - IEEE80211_CHAN_HT40U | IEEE80211_CHAN_VHT80; - flags[nmodes++] = IEEE80211_CHAN_A | - IEEE80211_CHAN_HT40D | IEEE80211_CHAN_VHT80; + /* VHT80+80 */ + if ((cbw_flags & NET80211_CBW_FLAG_VHT80P80) && + isset(bands, IEEE80211_MODE_VHT_5GHZ)) { + flags[nmodes++] = IEEE80211_CHAN_A | IEEE80211_CHAN_HT40U | + IEEE80211_CHAN_VHT80P80; + flags[nmodes++] = IEEE80211_CHAN_A | IEEE80211_CHAN_HT40D | + IEEE80211_CHAN_VHT80P80; } - /* XXX VHT80+80 */ - /* XXX VHT160 */ flags[nmodes] = 0; } static void -getflags(const uint8_t bands[], uint32_t flags[], int ht40, int vht80) +getflags(const uint8_t bands[], uint32_t flags[], int cbw_flags) { flags[0] = 0; @@ -1379,15 +1401,16 @@ getflags(const uint8_t bands[], uint32_t flags[], int ht40, int vht80) isset(bands, IEEE80211_MODE_VHT_2GHZ)) return; - getflags_5ghz(bands, flags, ht40, vht80); + getflags_5ghz(bands, flags, cbw_flags); } else - getflags_2ghz(bands, flags, ht40); + getflags_2ghz(bands, flags, cbw_flags); } /* * Add one 20 MHz channel into specified channel list. * You MUST NOT mix bands when calling this. It will not add 5ghz * channels if you have any B/G/N band bit set. + * This also does not support 40/80/160/80+80. */ /* XXX VHT */ int @@ -1398,7 +1421,7 @@ ieee80211_add_channel(struct ieee80211_channel chans[], int maxchans, uint32_t flags[IEEE80211_MODE_MAX]; int i, error; - getflags(bands, flags, 0, 0); + getflags(bands, flags, 0); KASSERT(flags[0] != 0, ("%s: no correct mode provided\n", __func__)); error = addchan(chans, maxchans, nchans, ieee, freq, maxregpower, @@ -1549,6 +1572,9 @@ add_chanlist(struct ieee80211_channel chans[], int maxchans, int *nchans, */ is_vht = !! (flags[j] & IEEE80211_CHAN_VHT); + /* XXX TODO FIXME VHT80P80. */ + /* XXX TODO FIXME VHT160. */ + /* * Test for VHT80. * XXX This is all very broken right now. @@ -1622,12 +1648,12 @@ add_chanlist(struct ieee80211_channel chans[], int maxchans, int *nchans, int ieee80211_add_channel_list_2ghz(struct ieee80211_channel chans[], int maxchans, int *nchans, const uint8_t ieee[], int nieee, const uint8_t bands[], - int ht40) + int cbw_flags) { uint32_t flags[IEEE80211_MODE_MAX]; /* XXX no VHT for now */ - getflags_2ghz(bands, flags, ht40); + getflags_2ghz(bands, flags, cbw_flags); KASSERT(flags[0] != 0, ("%s: no correct mode provided\n", __func__)); return (add_chanlist(chans, maxchans, nchans, ieee, nieee, flags)); @@ -1635,30 +1661,27 @@ ieee80211_add_channel_list_2ghz(struct ieee80211_channel chans[], int maxchans, int ieee80211_add_channels_default_2ghz(struct ieee80211_channel chans[], - int maxchans, int *nchans, const uint8_t bands[], int ht40) + int maxchans, int *nchans, const uint8_t bands[], int cbw_flags) { const uint8_t default_chan_list[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }; return (ieee80211_add_channel_list_2ghz(chans, maxchans, nchans, - default_chan_list, nitems(default_chan_list), bands, ht40)); + default_chan_list, nitems(default_chan_list), bands, cbw_flags)); } int ieee80211_add_channel_list_5ghz(struct ieee80211_channel chans[], int maxchans, int *nchans, const uint8_t ieee[], int nieee, const uint8_t bands[], - int ht40) + int cbw_flags) { - uint32_t flags[IEEE80211_MODE_MAX]; - int vht80 = 0; - /* - * For now, assume VHT == VHT80 support as a minimum. + * XXX-BZ with HT and VHT there is no 1:1 mapping anymore. Review all + * uses of IEEE80211_MODE_MAX and add a new #define name for array size. */ - if (isset(bands, IEEE80211_MODE_VHT_5GHZ)) - vht80 = 1; + uint32_t flags[2 * IEEE80211_MODE_MAX]; - getflags_5ghz(bands, flags, ht40, vht80); + getflags_5ghz(bands, flags, cbw_flags); KASSERT(flags[0] != 0, ("%s: no correct mode provided\n", __func__)); return (add_chanlist(chans, maxchans, nchans, ieee, nieee, flags)); @@ -1769,11 +1792,7 @@ ieee80211_lookup_channel_rxstatus(struct ieee80211vap *vap, IEEE80211_DPRINTF(vap, IEEE80211_MSG_INPUT, "%s: freq=%d, ieee=%d, flags=0x%08x; c=%p\n", - __func__, - (int) rxs->c_freq, - (int) rxs->c_ieee, - flags, - c); + __func__, (int) rxs->c_freq, (int) rxs->c_ieee, flags, c); return (c); } @@ -1914,12 +1933,18 @@ ieee80211_media_setup(struct ieee80211com *ic, /* * Add VHT media. + * XXX-BZ skip "VHT_2GHZ" for now. */ - for (; mode <= IEEE80211_MODE_VHT_5GHZ; mode++) { + for (mode = IEEE80211_MODE_VHT_5GHZ; mode <= IEEE80211_MODE_VHT_5GHZ; + mode++) { if (isclr(ic->ic_modecaps, mode)) continue; addmedia(media, caps, addsta, mode, IFM_AUTO); addmedia(media, caps, addsta, mode, IFM_IEEE80211_VHT); + } + if (isset(ic->ic_modecaps, IEEE80211_MODE_VHT_5GHZ)) { + addmedia(media, caps, addsta, + IEEE80211_MODE_AUTO, IFM_IEEE80211_VHT); /* XXX TODO: VHT maxrate */ } @@ -2038,6 +2063,12 @@ media2mode(const struct ifmedia_entry *ime, uint32_t flags, uint16_t *mode) case IFM_IEEE80211_11NG: *mode = IEEE80211_MODE_11NG; break; + case IFM_IEEE80211_VHT2G: + *mode = IEEE80211_MODE_VHT_2GHZ; + break; + case IFM_IEEE80211_VHT5G: + *mode = IEEE80211_MODE_VHT_5GHZ; + break; case IFM_AUTO: *mode = IEEE80211_MODE_AUTO; break; @@ -2200,7 +2231,7 @@ ieee80211_setmode(struct ieee80211com *ic, enum ieee80211_phymode mode) ieee80211_setbasicrates(&ic->ic_sup_rates[mode], mode); ic->ic_curmode = mode; - ieee80211_reset_erp(ic); /* reset ERP state */ + ieee80211_reset_erp(ic); /* reset global ERP state */ return 0; } @@ -2381,12 +2412,36 @@ ieee80211_rate2media(struct ieee80211com *ic, int rate, enum ieee80211_phymode m { 75, IFM_IEEE80211_MCS }, { 76, IFM_IEEE80211_MCS }, }; + static const struct ratemedia vhtrates[] = { + { 0, IFM_IEEE80211_VHT }, + { 1, IFM_IEEE80211_VHT }, + { 2, IFM_IEEE80211_VHT }, + { 3, IFM_IEEE80211_VHT }, + { 4, IFM_IEEE80211_VHT }, + { 5, IFM_IEEE80211_VHT }, + { 6, IFM_IEEE80211_VHT }, + { 7, IFM_IEEE80211_VHT }, + { 8, IFM_IEEE80211_VHT }, /* Optional. */ + { 9, IFM_IEEE80211_VHT }, /* Optional. */ +#if 0 + /* Some QCA and BRCM seem to support this; offspec. */ + { 10, IFM_IEEE80211_VHT }, + { 11, IFM_IEEE80211_VHT }, +#endif + }; int m; /* - * Check 11n rates first for match as an MCS. + * Check 11ac/11n rates first for match as an MCS. */ - if (mode == IEEE80211_MODE_11NA) { + if (mode == IEEE80211_MODE_VHT_5GHZ) { + if (rate & IFM_IEEE80211_VHT) { + rate &= ~IFM_IEEE80211_VHT; + m = findmedia(vhtrates, nitems(vhtrates), rate); + if (m != IFM_AUTO) + return (m | IFM_IEEE80211_VHT); + } + } else if (mode == IEEE80211_MODE_11NA) { if (rate & IEEE80211_RATE_MCS) { rate &= ~IEEE80211_RATE_MCS; m = findmedia(htrates, nitems(htrates), rate); diff --git a/sys/net80211/ieee80211.h b/sys/net80211/ieee80211.h index 61389169bc47..62c40e263aba 100644 --- a/sys/net80211/ieee80211.h +++ b/sys/net80211/ieee80211.h @@ -430,6 +430,8 @@ struct ieee80211_action_ht_mimopowersave { #define IEEE80211_BAPS_TID_S 2 #define IEEE80211_BAPS_POLICY 0x0002 /* block ack policy */ #define IEEE80211_BAPS_POLICY_S 1 +#define IEEE80211_BAPS_AMSDU 0x0001 /* A-MSDU permitted */ +#define IEEE80211_BAPS_AMSDU_S 0 #define IEEE80211_BAPS_POLICY_DELAYED (0<<IEEE80211_BAPS_POLICY_S) #define IEEE80211_BAPS_POLICY_IMMEDIATE (1<<IEEE80211_BAPS_POLICY_S) diff --git a/sys/net80211/ieee80211_adhoc.c b/sys/net80211/ieee80211_adhoc.c index 24f6ba448e7b..ea1519b3381d 100644 --- a/sys/net80211/ieee80211_adhoc.c +++ b/sys/net80211/ieee80211_adhoc.c @@ -715,6 +715,15 @@ adhoc_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, wh = mtod(m0, struct ieee80211_frame *); frm = (uint8_t *)&wh[1]; efrm = mtod(m0, uint8_t *) + m0->m_len; + + IEEE80211_DPRINTF(vap, IEEE80211_MSG_INPUT | IEEE80211_MSG_DEBUG, + "%s: recv mgmt frame, addr2=%6D, ni=%p (%6D) fc=%.02x %.02x\n", + __func__, + wh->i_addr2, ":", + ni, + ni->ni_macaddr, ":", + wh->i_fc[0], + wh->i_fc[1]); switch (subtype) { case IEEE80211_FC0_SUBTYPE_PROBE_RESP: case IEEE80211_FC0_SUBTYPE_BEACON: { @@ -788,6 +797,20 @@ adhoc_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, } else ni = NULL; + /* + * Send a probe request so we announce 11n + * capabilities. + * + * Don't do this if we're scanning. + */ + if (! (ic->ic_flags & IEEE80211_F_SCAN)) + ieee80211_send_probereq(ni, /* node */ + vap->iv_myaddr, /* SA */ + ni->ni_macaddr, /* DA */ + vap->iv_bss->ni_bssid, /* BSSID */ + vap->iv_bss->ni_essid, + vap->iv_bss->ni_esslen); /* SSID */ + } else if (ni->ni_capinfo == 0) { /* * Update faked node created on transmit. @@ -936,11 +959,11 @@ adhoc_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, vap->iv_stats.is_rx_mgtdiscard++; } else if (!IEEE80211_ADDR_EQ(vap->iv_myaddr, wh->i_addr1) && !IEEE80211_IS_MULTICAST(wh->i_addr1)) { - IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT, + IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT | IEEE80211_MSG_DEBUG, wh, NULL, "%s", "not for us"); vap->iv_stats.is_rx_mgtdiscard++; } else if (vap->iv_state != IEEE80211_S_RUN) { - IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT, + IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT | IEEE80211_MSG_DEBUG, wh, NULL, "wrong state %s", ieee80211_state_name[vap->iv_state]); vap->iv_stats.is_rx_mgtdiscard++; diff --git a/sys/net80211/ieee80211_amrr.c b/sys/net80211/ieee80211_amrr.c index f686b83bf04c..384a5956fe4e 100644 --- a/sys/net80211/ieee80211_amrr.c +++ b/sys/net80211/ieee80211_amrr.c @@ -477,18 +477,12 @@ amrr_sysctlattach(struct ieee80211vap *vap, } static void -amrr_node_stats(struct ieee80211_node *ni, struct sbuf *s) +amrr_print_node_rate(struct ieee80211_amrr_node *amn, + struct ieee80211_node *ni, struct sbuf *s) { int rate; - struct ieee80211_amrr_node *amn = ni->ni_rctls; struct ieee80211_rateset *rs; - /* XXX TODO: check locking? */ - - if (!amn) - return; - - /* XXX TODO: this should be a method */ if (amrr_node_is_11n(ni)) { rs = (struct ieee80211_rateset *) &ni->ni_htrates; rate = rs->rs_rates[amn->amn_rix] & IEEE80211_RATE_VAL; @@ -498,7 +492,19 @@ amrr_node_stats(struct ieee80211_node *ni, struct sbuf *s) rate = rs->rs_rates[amn->amn_rix] & IEEE80211_RATE_VAL; sbuf_printf(s, "rate: %d Mbit\n", rate / 2); } +} + +static void +amrr_node_stats(struct ieee80211_node *ni, struct sbuf *s) +{ + struct ieee80211_amrr_node *amn = ni->ni_rctls; + + /* XXX TODO: check locking? */ + + if (!amn) + return; + amrr_print_node_rate(amn, ni, s); sbuf_printf(s, "ticks: %d\n", amn->amn_ticks); sbuf_printf(s, "txcnt: %u\n", amn->amn_txcnt); sbuf_printf(s, "success: %u\n", amn->amn_success); diff --git a/sys/net80211/ieee80211_ddb.c b/sys/net80211/ieee80211_ddb.c index f45bb471ef7a..272aaf988ba1 100644 --- a/sys/net80211/ieee80211_ddb.c +++ b/sys/net80211/ieee80211_ddb.c @@ -209,6 +209,7 @@ _db_show_txampdu(const char *sep, int ix, const struct ieee80211_tx_ampdu *tap) static void _db_show_rxampdu(const char *sep, int ix, const struct ieee80211_rx_ampdu *rap) { + struct mbuf *m; int i; db_printf("%srxampdu[%d]: %p flags 0x%x tid %u\n", @@ -219,10 +220,15 @@ _db_show_rxampdu(const char *sep, int ix, const struct ieee80211_rx_ampdu *rap) db_printf("%s age %d nframes %d\n", sep, rap->rxa_age, rap->rxa_nframes); for (i = 0; i < IEEE80211_AGGR_BAWMAX; i++) - if (rap->rxa_m[i] != NULL) - db_printf("%s m[%2u:%4u] %p\n", sep, i, - IEEE80211_SEQ_ADD(rap->rxa_start, i), - rap->rxa_m[i]); + if (mbufq_len(&rap->rxa_mq[i]) > 0) { + db_printf("%s m[%2u:%4u] ", sep, i, + IEEE80211_SEQ_ADD(rap->rxa_start, i)); + STAILQ_FOREACH(m, &rap->rxa_mq[i].mq_head, + m_stailqpkt) { + db_printf(" %p", m); + } + db_printf("\n"); + } } static void @@ -477,6 +483,17 @@ _db_show_vap(const struct ieee80211vap *vap, int showmesh, int showprocs) if (vap->iv_tdma != NULL) _db_show_tdma("\t", vap->iv_tdma, showprocs); #endif /* IEEE80211_SUPPORT_TDMA */ + + db_printf("\tsta_assoc %u", vap->iv_sta_assoc); + db_printf(" ht_sta_assoc %u", vap->iv_ht_sta_assoc); + db_printf(" ht40_sta_assoc %u", vap->iv_ht40_sta_assoc); + db_printf("\n"); + db_printf(" nonerpsta %u", vap->iv_nonerpsta); + db_printf(" longslotsta %u", vap->iv_longslotsta); + db_printf(" lastnonerp %d", vap->iv_lastnonerp); + db_printf(" lastnonht %d", vap->iv_lastnonht); + db_printf("\n"); + if (showprocs) { DB_PRINTSYM("\t", "iv_key_alloc", vap->iv_key_alloc); DB_PRINTSYM("\t", "iv_key_delete", vap->iv_key_delete); @@ -602,17 +619,8 @@ _db_show_com(const struct ieee80211com *ic, int showvaps, int showsta, _db_show_node_table("\t", &ic->ic_sta); db_printf("\tprotmode %d", ic->ic_protmode); - db_printf(" nonerpsta %u", ic->ic_nonerpsta); - db_printf(" longslotsta %u", ic->ic_longslotsta); - db_printf(" lastnonerp %d", ic->ic_lastnonerp); - db_printf("\n"); - db_printf("\tsta_assoc %u", ic->ic_sta_assoc); - db_printf(" ht_sta_assoc %u", ic->ic_ht_sta_assoc); - db_printf(" ht40_sta_assoc %u", ic->ic_ht40_sta_assoc); - db_printf("\n"); db_printf("\tcurhtprotmode 0x%x", ic->ic_curhtprotmode); db_printf(" htprotmode %d", ic->ic_htprotmode); - db_printf(" lastnonht %d", ic->ic_lastnonht); db_printf("\n"); db_printf("\tsuperg %p\n", ic->ic_superg); diff --git a/sys/net80211/ieee80211_freebsd.c b/sys/net80211/ieee80211_freebsd.c index dd710a8078f0..cb8c0a6a63e7 100644 --- a/sys/net80211/ieee80211_freebsd.c +++ b/sys/net80211/ieee80211_freebsd.c @@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$"); #include <sys/malloc.h> #include <sys/mbuf.h> #include <sys/module.h> +#include <sys/priv.h> #include <sys/proc.h> #include <sys/sysctl.h> @@ -79,6 +80,10 @@ wlan_clone_create(struct if_clone *ifc, int unit, caddr_t params) struct ieee80211com *ic; int error; + error = priv_check(curthread, PRIV_NET80211_CREATE_VAP); + if (error) + return error; + error = copyin(params, &cp, sizeof(cp)); if (error) return error; @@ -788,8 +793,11 @@ ieee80211_notify_replay_failure(struct ieee80211vap *vap, struct ifnet *ifp = vap->iv_ifp; IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2, - "%s replay detected tid %d <rsc %ju, csc %ju, keyix %u rxkeyix %u>", - k->wk_cipher->ic_name, tid, (intmax_t) rsc, + "%s replay detected tid %d <rsc %ju (%jx), csc %ju (%jx), keyix %u rxkeyix %u>", + k->wk_cipher->ic_name, tid, + (intmax_t) rsc, + (intmax_t) rsc, + (intmax_t) k->wk_keyrsc[tid], (intmax_t) k->wk_keyrsc[tid], k->wk_keyix, k->wk_rxkeyix); @@ -1030,6 +1038,20 @@ wlan_iflladdr(void *arg __unused, struct ifnet *ifp) } /* + * Fetch the VAP name. + * + * This returns a const char pointer suitable for debugging, + * but don't expect it to stick around for much longer. + */ +const char * +ieee80211_get_vap_ifname(struct ieee80211vap *vap) +{ + if (vap->iv_ifp == NULL) + return "(none)"; + return vap->iv_ifp->if_xname; +} + +/* * Module glue. * * NB: the module name is "wlan" for compatibility with NetBSD. diff --git a/sys/net80211/ieee80211_freebsd.h b/sys/net80211/ieee80211_freebsd.h index 4e06b76ad60a..19a8e45672a9 100644 --- a/sys/net80211/ieee80211_freebsd.h +++ b/sys/net80211/ieee80211_freebsd.h @@ -245,6 +245,7 @@ void ieee80211_drain_ifq(struct ifqueue *); void ieee80211_flush_ifq(struct ifqueue *, struct ieee80211vap *); void ieee80211_vap_destroy(struct ieee80211vap *); +const char * ieee80211_get_vap_ifname(struct ieee80211vap *); #define IFNET_IS_UP_RUNNING(_ifp) \ (((_ifp)->if_flags & IFF_UP) && \ @@ -254,9 +255,9 @@ void ieee80211_vap_destroy(struct ieee80211vap *); #define ticks_to_msecs(t) TICKS_2_MSEC(t) #define ticks_to_secs(t) ((t) / hz) -#define ieee80211_time_after(a,b) ((long)(b) - (long)(a) < 0) +#define ieee80211_time_after(a,b) ((int)(b) - (int)(a) < 0) #define ieee80211_time_before(a,b) ieee80211_time_after(b,a) -#define ieee80211_time_after_eq(a,b) ((long)(a) - (long)(b) >= 0) +#define ieee80211_time_after_eq(a,b) ((int)(a) - (int)(b) >= 0) #define ieee80211_time_before_eq(a,b) ieee80211_time_after_eq(b,a) struct mbuf *ieee80211_getmgtframe(uint8_t **frm, int headroom, int pktlen); diff --git a/sys/net80211/ieee80211_hostap.c b/sys/net80211/ieee80211_hostap.c index 263e0c3a2b67..6687276d0181 100644 --- a/sys/net80211/ieee80211_hostap.c +++ b/sys/net80211/ieee80211_hostap.c @@ -65,6 +65,7 @@ __FBSDID("$FreeBSD$"); #endif #include <net80211/ieee80211_wds.h> #include <net80211/ieee80211_vht.h> +#include <net80211/ieee80211_sta.h> /* for parse_wmeie */ #define IEEE80211_RATE2MBS(r) (((r) & IEEE80211_RATE_VAL) / 2) @@ -205,8 +206,9 @@ hostap_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) * state and the timeout routines check if the flag * is set before doing anything so this is sufficient. */ - ic->ic_flags_ext &= ~IEEE80211_FEXT_NONERP_PR; - ic->ic_flags_ht &= ~IEEE80211_FHT_NONHT_PR; + vap->iv_flags_ext &= ~IEEE80211_FEXT_NONERP_PR; + vap->iv_flags_ht &= ~IEEE80211_FHT_NONHT_PR; + /* XXX TODO: schedule deferred update? */ /* fall thru... */ case IEEE80211_S_CAC: /* @@ -1811,10 +1813,13 @@ hostap_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, scan.status == 0 && /* NB: on-channel */ ((scan.erp & 0x100) == 0 || /* NB: no ERP, 11b sta*/ (scan.erp & IEEE80211_ERP_NON_ERP_PRESENT))) { - ic->ic_lastnonerp = ticks; - ic->ic_flags_ext |= IEEE80211_FEXT_NONERP_PR; - if (ic->ic_protmode != IEEE80211_PROT_NONE && - (ic->ic_flags & IEEE80211_F_USEPROT) == 0) { + vap->iv_lastnonerp = ticks; + vap->iv_flags_ext |= IEEE80211_FEXT_NONERP_PR; + /* + * XXX TODO: this may need to check all VAPs? + */ + if (vap->iv_protmode != IEEE80211_PROT_NONE && + (vap->iv_flags & IEEE80211_F_USEPROT) == 0) { IEEE80211_NOTE_FRAME(vap, IEEE80211_MSG_ASSOC, wh, "non-ERP present on channel %d " @@ -1822,8 +1827,8 @@ hostap_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, "enable use of protection", ic->ic_curchan->ic_ieee, scan.erp, scan.chan); - ic->ic_flags |= IEEE80211_F_USEPROT; - ieee80211_notify_erp(ic); + vap->iv_flags |= IEEE80211_F_USEPROT; + ieee80211_vap_update_erp_protmode(vap); } } /* @@ -1843,12 +1848,12 @@ hostap_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, break; } if (scan.htinfo == NULL) { - ieee80211_htprot_update(ic, + ieee80211_htprot_update(vap, IEEE80211_HTINFO_OPMODE_PROTOPT | IEEE80211_HTINFO_NONHT_PRESENT); } else if (ishtmixed(scan.htinfo)) { /* XXX? take NONHT_PRESENT from beacon? */ - ieee80211_htprot_update(ic, + ieee80211_htprot_update(vap, IEEE80211_HTINFO_OPMODE_MIXED | IEEE80211_HTINFO_NONHT_PRESENT); } @@ -2253,8 +2258,18 @@ hostap_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, * Mark node as capable of QoS. */ ni->ni_flags |= IEEE80211_NODE_QOS; + if (ieee80211_parse_wmeie(wme, wh, ni) > 0) { + if (ni->ni_uapsd != 0) + ni->ni_flags |= + IEEE80211_NODE_UAPSD; + else + ni->ni_flags &= + ~IEEE80211_NODE_UAPSD; + } } else - ni->ni_flags &= ~IEEE80211_NODE_QOS; + ni->ni_flags &= + ~(IEEE80211_NODE_QOS | + IEEE80211_NODE_UAPSD); #ifdef IEEE80211_SUPPORT_SUPERG if (ath != NULL) { setie(ath_ie, ath - sfrm); @@ -2268,6 +2283,7 @@ hostap_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, #undef setie } else { ni->ni_flags &= ~IEEE80211_NODE_QOS; + ni->ni_flags &= ~IEEE80211_NODE_UAPSD; ni->ni_ath_flags = 0; } ieee80211_node_join(ni, resp); diff --git a/sys/net80211/ieee80211_ht.c b/sys/net80211/ieee80211_ht.c index d0c6e7a4f415..c17bfc89b716 100644 --- a/sys/net80211/ieee80211_ht.c +++ b/sys/net80211/ieee80211_ht.c @@ -267,6 +267,9 @@ ieee80211_ht_vattach(struct ieee80211vap *vap) vap->iv_ampdu_mintraffic[WME_AC_VO] = 32; vap->iv_ampdu_mintraffic[WME_AC_VI] = 32; + vap->iv_htprotmode = IEEE80211_PROT_RTSCTS; + vap->iv_curhtprotmode = IEEE80211_HTINFO_OPMODE_PURE; + if (vap->iv_htcaps & IEEE80211_HTC_HT) { /* * Device is HT capable; enable all HT-related @@ -514,6 +517,22 @@ ieee80211_decap_amsdu(struct ieee80211_node *ni, struct mbuf *m) return m; /* last delivered by caller */ } +static void +ampdu_rx_purge_slot(struct ieee80211_rx_ampdu *rap, int i) +{ + struct mbuf *m; + + /* Walk the queue, removing frames as appropriate */ + while (mbufq_len(&rap->rxa_mq[i]) != 0) { + m = mbufq_dequeue(&rap->rxa_mq[i]); + if (m == NULL) + break; + rap->rxa_qbytes -= m->m_pkthdr.len; + rap->rxa_qframes--; + m_freem(m); + } +} + /* * Add the given frame to the current RX reorder slot. * @@ -525,16 +544,94 @@ static int ampdu_rx_add_slot(struct ieee80211_rx_ampdu *rap, int off, int tid, ieee80211_seq rxseq, struct ieee80211_node *ni, - struct mbuf *m) + struct mbuf *m, + const struct ieee80211_rx_stats *rxs) { + const struct ieee80211_rx_stats *rxs_final = NULL; struct ieee80211vap *vap = ni->ni_vap; + int toss_dup; +#define PROCESS 0 /* caller should process frame */ +#define CONSUMED 1 /* frame consumed, caller does nothing */ - if (rap->rxa_m[off] == NULL) { - rap->rxa_m[off] = m; + /* + * Figure out if this is a duplicate frame for the given slot. + * + * We're assuming that the driver will hand us all the frames + * for a given AMSDU decap pass and if we get /a/ frame + * for an AMSDU decap then we'll get all of them. + * + * The tricksy bit is that we don't know when the /end/ of + * the decap pass is, because we aren't tracking state here + * per-slot to know that we've finished receiving the frame list. + * + * The driver sets RX_F_AMSDU and RX_F_AMSDU_MORE to tell us + * what's going on; so ideally we'd just check the frame at the + * end of the reassembly slot to see if its F_AMSDU w/ no F_AMSDU_MORE - + * that means we've received the whole AMSDU decap pass. + */ + + /* + * Get the rxs of the final mbuf in the slot, if one exists. + */ + if (mbufq_len(&rap->rxa_mq[off]) != 0) { + rxs_final = ieee80211_get_rx_params_ptr(mbufq_last(&rap->rxa_mq[off])); + } + + /* Default to tossing the duplicate frame */ + toss_dup = 1; + + /* + * Check to see if the final frame has F_AMSDU and F_AMSDU set, AND + * this frame has F_AMSDU set (MORE or otherwise.) That's a sign + * that more can come. + */ + + if ((rxs != NULL) && (rxs_final != NULL) && + ieee80211_check_rxseq_amsdu(rxs) && + ieee80211_check_rxseq_amsdu(rxs_final)) { + if (! ieee80211_check_rxseq_amsdu_more(rxs_final)) { + /* + * amsdu_more() returning 0 means "it's not the + * final frame" so we can append more + * frames here. + */ + toss_dup = 0; + } + } + + /* + * If the list is empty OR we have determined we can put more + * driver decap'ed AMSDU frames in here, then insert. + */ + if ((mbufq_len(&rap->rxa_mq[off]) == 0) || (toss_dup == 0)) { + if (mbufq_enqueue(&rap->rxa_mq[off], m) != 0) { + IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT | IEEE80211_MSG_11N, + ni->ni_macaddr, + "a-mpdu queue fail", + "seqno %u tid %u BA win <%u:%u> off=%d, qlen=%d, maxqlen=%d", + rxseq, tid, rap->rxa_start, + IEEE80211_SEQ_ADD(rap->rxa_start, rap->rxa_wnd-1), + off, + mbufq_len(&rap->rxa_mq[off]), + rap->rxa_mq[off].mq_maxlen); + /* XXX error count */ + m_freem(m); + return CONSUMED; + } rap->rxa_qframes++; rap->rxa_qbytes += m->m_pkthdr.len; vap->iv_stats.is_ampdu_rx_reorder++; - return (0); + /* + * Statistics for AMSDU decap. + */ + if (rxs != NULL && ieee80211_check_rxseq_amsdu(rxs)) { + if (ieee80211_check_rxseq_amsdu_more(rxs)) { + /* more=1, AMSDU, end of batch */ + IEEE80211_NODE_STAT(ni, rx_amsdu_more_end); + } else { + IEEE80211_NODE_STAT(ni, rx_amsdu_more); + } + } } else { IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT | IEEE80211_MSG_11N, @@ -542,26 +639,27 @@ ampdu_rx_add_slot(struct ieee80211_rx_ampdu *rap, int off, int tid, "seqno %u tid %u BA win <%u:%u>", rxseq, tid, rap->rxa_start, IEEE80211_SEQ_ADD(rap->rxa_start, rap->rxa_wnd-1)); + if (rxs != NULL) { + IEEE80211_DISCARD_MAC(vap, + IEEE80211_MSG_INPUT | IEEE80211_MSG_11N, + ni->ni_macaddr, "a-mpdu duplicate", + "seqno %d tid %u pktflags 0x%08x\n", + rxseq, tid, rxs->c_pktflags); + } + if (rxs_final != NULL) { + IEEE80211_DISCARD_MAC(vap, + IEEE80211_MSG_INPUT | IEEE80211_MSG_11N, + ni->ni_macaddr, "a-mpdu duplicate", + "final: pktflags 0x%08x\n", + rxs_final->c_pktflags); + } vap->iv_stats.is_rx_dup++; IEEE80211_NODE_STAT(ni, rx_dup); m_freem(m); - return (-1); } -} - -static void -ampdu_rx_purge_slot(struct ieee80211_rx_ampdu *rap, int i) -{ - struct mbuf *m; - - m = rap->rxa_m[i]; - if (m == NULL) - return; - - rap->rxa_m[i] = NULL; - rap->rxa_qbytes -= m->m_pkthdr.len; - rap->rxa_qframes--; - m_freem(m); + return CONSUMED; +#undef CONSUMED +#undef PROCESS } /* @@ -582,6 +680,18 @@ ampdu_rx_purge(struct ieee80211_rx_ampdu *rap) rap->rxa_qbytes, rap->rxa_qframes)); } +static void +ieee80211_ampdu_rx_init_rap(struct ieee80211_node *ni, + struct ieee80211_rx_ampdu *rap) +{ + int i; + + /* XXX TODO: ensure the queues are empty */ + memset(rap, 0, sizeof(*rap)); + for (i = 0; i < IEEE80211_AGGR_BAWMAX; i++) + mbufq_init(&rap->rxa_mq[i], 256); +} + /* * Start A-MPDU rx/re-order processing for the specified TID. */ @@ -589,6 +699,7 @@ static int ampdu_rx_start(struct ieee80211_node *ni, struct ieee80211_rx_ampdu *rap, int baparamset, int batimeout, int baseqctl) { + struct ieee80211vap *vap = ni->ni_vap; int bufsiz = MS(baparamset, IEEE80211_BAPS_BUFSIZ); if (rap->rxa_flags & IEEE80211_AGGR_RUNNING) { @@ -598,12 +709,19 @@ ampdu_rx_start(struct ieee80211_node *ni, struct ieee80211_rx_ampdu *rap, */ ampdu_rx_purge(rap); } - memset(rap, 0, sizeof(*rap)); + ieee80211_ampdu_rx_init_rap(ni, rap); rap->rxa_wnd = (bufsiz == 0) ? IEEE80211_AGGR_BAWMAX : min(bufsiz, IEEE80211_AGGR_BAWMAX); rap->rxa_start = MS(baseqctl, IEEE80211_BASEQ_START); rap->rxa_flags |= IEEE80211_AGGR_RUNNING | IEEE80211_AGGR_XCHGPEND; + /* XXX this should be a configuration flag */ + if ((vap->iv_htcaps & IEEE80211_HTC_RX_AMSDU_AMPDU) && + (MS(baparamset, IEEE80211_BAPS_AMSDU))) + rap->rxa_flags |= IEEE80211_AGGR_AMSDU; + else + rap->rxa_flags &= ~IEEE80211_AGGR_AMSDU; + return 0; } @@ -627,7 +745,8 @@ ieee80211_ampdu_rx_start_ext(struct ieee80211_node *ni, int tid, int seq, int ba ampdu_rx_purge(rap); } - memset(rap, 0, sizeof(*rap)); + ieee80211_ampdu_rx_init_rap(ni, rap); + rap->rxa_wnd = (baw== 0) ? IEEE80211_AGGR_BAWMAX : min(baw, IEEE80211_AGGR_BAWMAX); if (seq == -1) { @@ -639,6 +758,8 @@ ieee80211_ampdu_rx_start_ext(struct ieee80211_node *ni, int tid, int seq, int ba } rap->rxa_flags |= IEEE80211_AGGR_RUNNING | IEEE80211_AGGR_XCHGPEND; + /* XXX TODO: no amsdu flag */ + IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_11N, ni, "%s: tid=%d, start=%d, wnd=%d, flags=0x%08x", __func__, @@ -695,18 +816,20 @@ ampdu_dispatch_slot(struct ieee80211_rx_ampdu *rap, struct ieee80211_node *ni, int i) { struct mbuf *m; + int n = 0; - if (rap->rxa_m[i] == NULL) - return (0); - - m = rap->rxa_m[i]; - rap->rxa_m[i] = NULL; - rap->rxa_qbytes -= m->m_pkthdr.len; - rap->rxa_qframes--; + while (mbufq_len(&rap->rxa_mq[i]) != 0) { + m = mbufq_dequeue(&rap->rxa_mq[i]); + if (m == NULL) + break; + n++; - ampdu_dispatch(ni, m); + rap->rxa_qbytes -= m->m_pkthdr.len; + rap->rxa_qframes--; - return (1); + ampdu_dispatch(ni, m); + } + return (n); } static void @@ -715,22 +838,22 @@ ampdu_rx_moveup(struct ieee80211_rx_ampdu *rap, struct ieee80211_node *ni, { struct ieee80211vap *vap = ni->ni_vap; + /* + * If frames remain, copy the mbuf pointers down so + * they correspond to the offsets in the new window. + */ if (rap->rxa_qframes != 0) { int n = rap->rxa_qframes, j; - - if (winstart != -1) { + for (j = i+1; j < rap->rxa_wnd; j++) { /* - * NB: in window-sliding mode, loop assumes i > 0 - * and/or rxa_m[0] is NULL + * Concat the list contents over, which will + * blank the source list for us. */ - KASSERT(rap->rxa_m[0] == NULL, - ("%s: BA window slot 0 occupied", __func__)); - } - for (j = i+1; j < rap->rxa_wnd; j++) { - if (rap->rxa_m[j] != NULL) { - rap->rxa_m[j-i] = rap->rxa_m[j]; - rap->rxa_m[j] = NULL; - if (--n == 0) + if (mbufq_len(&rap->rxa_mq[j]) != 0) { + n = n - mbufq_len(&rap->rxa_mq[j]); + mbufq_concat(&rap->rxa_mq[j-i], &rap->rxa_mq[j]); + KASSERT(n >= 0, ("%s: n < 0 (%d)", __func__, n)); + if (n == 0) break; } } @@ -755,18 +878,18 @@ static void ampdu_rx_dispatch(struct ieee80211_rx_ampdu *rap, struct ieee80211_node *ni) { struct ieee80211vap *vap = ni->ni_vap; - int i; + int i, r, r2; /* flush run of frames */ + r2 = 0; for (i = 1; i < rap->rxa_wnd; i++) { - if (ampdu_dispatch_slot(rap, ni, i) == 0) + r = ampdu_dispatch_slot(rap, ni, i); + if (r == 0) break; + r2 += r; } - /* - * If frames remain, copy the mbuf pointers down so - * they correspond to the offsets in the new window. - */ + /* move up frames */ ampdu_rx_moveup(rap, ni, i, -1); /* @@ -774,7 +897,14 @@ ampdu_rx_dispatch(struct ieee80211_rx_ampdu *rap, struct ieee80211_node *ni) * reflect the frames just dispatched. */ rap->rxa_start = IEEE80211_SEQ_ADD(rap->rxa_start, i); - vap->iv_stats.is_ampdu_rx_oor += i; + vap->iv_stats.is_ampdu_rx_oor += r2; + + IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_11N, ni, + "%s: moved slot up %d slots to start at %d (%d frames)", + __func__, + i, + rap->rxa_start, + r2); } /* @@ -783,14 +913,20 @@ ampdu_rx_dispatch(struct ieee80211_rx_ampdu *rap, struct ieee80211_node *ni) static void ampdu_rx_flush(struct ieee80211_node *ni, struct ieee80211_rx_ampdu *rap) { - struct ieee80211vap *vap = ni->ni_vap; int i, r; for (i = 0; i < rap->rxa_wnd; i++) { r = ampdu_dispatch_slot(rap, ni, i); if (r == 0) continue; - vap->iv_stats.is_ampdu_rx_oor += r; + ni->ni_vap->iv_stats.is_ampdu_rx_oor += r; + + IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_11N, ni, + "%s: moved slot up %d slots to start at %d (%d frames)", + __func__, + 1, + rap->rxa_start, + r); if (rap->rxa_qframes == 0) break; @@ -819,14 +955,23 @@ ampdu_rx_flush_upto(struct ieee80211_node *ni, */ seqno = rap->rxa_start; for (i = 0; i < rap->rxa_wnd; i++) { - r = ampdu_dispatch_slot(rap, ni, i); - if (r == 0) { + if ((r = mbufq_len(&rap->rxa_mq[i])) != 0) { + (void) ampdu_dispatch_slot(rap, ni, i); + } else { if (!IEEE80211_SEQ_BA_BEFORE(seqno, winstart)) break; } vap->iv_stats.is_ampdu_rx_oor += r; seqno = IEEE80211_SEQ_INC(seqno); + + IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_11N, ni, + "%s: moved slot up %d slots to start at %d (%d frames)", + __func__, + 1, + seqno, + r); } + /* * If frames remain, copy the mbuf pointers down so * they correspond to the offsets in the new window. @@ -849,6 +994,10 @@ ampdu_rx_flush_upto(struct ieee80211_node *ni, * this frame completes a run, flush any pending frames. We * return 1 if the frame is consumed. A 0 is returned if * the frame should be processed normally by the caller. + * + * A-MSDU: handle hardware decap'ed A-MSDU frames that are + * pretending to be MPDU's. They're dispatched directly if + * able; or attempted to put into the receive reordering slot. */ int ieee80211_ampdu_reorder(struct ieee80211_node *ni, struct mbuf *m, @@ -862,6 +1011,8 @@ ieee80211_ampdu_reorder(struct ieee80211_node *ni, struct mbuf *m, ieee80211_seq rxseq; uint8_t tid; int off; + int amsdu = ieee80211_check_rxseq_amsdu(rxs); + int amsdu_end = ieee80211_check_rxseq_amsdu_more(rxs); KASSERT((m->m_flags & (M_AMPDU | M_AMPDU_MPDU)) == M_AMPDU, ("!a-mpdu or already re-ordered, flags 0x%x", m->m_flags)); @@ -930,16 +1081,25 @@ again: /* * Dispatch as many packets as we can. */ - KASSERT(rap->rxa_m[0] == NULL, ("unexpected dup")); + KASSERT((mbufq_len(&rap->rxa_mq[0]) == 0), ("unexpected dup")); ampdu_dispatch(ni, m); ampdu_rx_dispatch(rap, ni); return CONSUMED; } else { /* - * In order; advance window and notify + * In order; advance window if needed and notify * caller to dispatch directly. */ - rap->rxa_start = IEEE80211_SEQ_INC(rxseq); + if (amsdu) { + if (amsdu_end) { + rap->rxa_start = IEEE80211_SEQ_INC(rxseq); + IEEE80211_NODE_STAT(ni, rx_amsdu_more_end); + } else { + IEEE80211_NODE_STAT(ni, rx_amsdu_more); + } + } else { + rap->rxa_start = IEEE80211_SEQ_INC(rxseq); + } return PROCESS; } } @@ -983,7 +1143,24 @@ again: rap->rxa_qframes; ampdu_rx_flush(ni, rap); } - rap->rxa_start = IEEE80211_SEQ_INC(rxseq); + /* + * Advance the window if needed and notify + * the caller to dispatch directly. + */ + if (amsdu) { + if (amsdu_end) { + rap->rxa_start = + IEEE80211_SEQ_INC(rxseq); + IEEE80211_NODE_STAT(ni, + rx_amsdu_more_end); + } else { + IEEE80211_NODE_STAT(ni, + rx_amsdu_more); + } + } else { + rap->rxa_start = + IEEE80211_SEQ_INC(rxseq); + } return PROCESS; } } else { @@ -994,8 +1171,7 @@ again: } /* save packet - this consumes, no matter what */ - ampdu_rx_add_slot(rap, off, tid, rxseq, ni, m); - + ampdu_rx_add_slot(rap, off, tid, rxseq, ni, m, rxs); return CONSUMED; } if (off < IEEE80211_SEQ_BA_RANGE) { @@ -1159,8 +1335,10 @@ ieee80211_ht_node_init(struct ieee80211_node *ni) tap->txa_ni = ni; ieee80211_txampdu_init_pps(tap); /* NB: further initialization deferred */ + ieee80211_ampdu_rx_init_rap(ni, &ni->ni_rx_ampdu[tid]); } - ni->ni_flags |= IEEE80211_NODE_HT | IEEE80211_NODE_AMPDU; + ni->ni_flags |= IEEE80211_NODE_HT | IEEE80211_NODE_AMPDU | + IEEE80211_NODE_AMSDU; } /* @@ -1326,42 +1504,41 @@ ieee80211_ht_wds_init(struct ieee80211_node *ni) ieee80211_txampdu_init_pps(tap); } /* NB: AMPDU tx/rx governed by IEEE80211_FHT_AMPDU_{TX,RX} */ - ni->ni_flags |= IEEE80211_NODE_HT | IEEE80211_NODE_AMPDU; + ni->ni_flags |= IEEE80211_NODE_HT | IEEE80211_NODE_AMPDU | + IEEE80211_NODE_AMSDU; } /* - * Notify hostap vaps of a change in the HTINFO ie. + * Notify a VAP of a change in the HTINFO ie if it's a hostap VAP. + * + * This is to be called from the deferred HT protection update + * task once the flags are updated. */ -static void -htinfo_notify(struct ieee80211com *ic) +void +ieee80211_htinfo_notify(struct ieee80211vap *vap) { - struct ieee80211vap *vap; - int first = 1; - IEEE80211_LOCK_ASSERT(ic); + IEEE80211_LOCK_ASSERT(vap->iv_ic); - TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { - if (vap->iv_opmode != IEEE80211_M_HOSTAP) - continue; - if (vap->iv_state != IEEE80211_S_RUN || - !IEEE80211_IS_CHAN_HT(vap->iv_bss->ni_chan)) - continue; - if (first) { - IEEE80211_NOTE(vap, - IEEE80211_MSG_ASSOC | IEEE80211_MSG_11N, - vap->iv_bss, - "HT bss occupancy change: %d sta, %d ht, " - "%d ht40%s, HT protmode now 0x%x" - , ic->ic_sta_assoc - , ic->ic_ht_sta_assoc - , ic->ic_ht40_sta_assoc - , (ic->ic_flags_ht & IEEE80211_FHT_NONHT_PR) ? - ", non-HT sta present" : "" - , ic->ic_curhtprotmode); - first = 0; - } - ieee80211_beacon_notify(vap, IEEE80211_BEACON_HTINFO); - } + if (vap->iv_opmode != IEEE80211_M_HOSTAP) + return; + if (vap->iv_state != IEEE80211_S_RUN || + !IEEE80211_IS_CHAN_HT(vap->iv_bss->ni_chan)) + return; + + IEEE80211_NOTE(vap, + IEEE80211_MSG_ASSOC | IEEE80211_MSG_11N, + vap->iv_bss, + "HT bss occupancy change: %d sta, %d ht, " + "%d ht40%s, HT protmode now 0x%x" + , vap->iv_sta_assoc + , vap->iv_ht_sta_assoc + , vap->iv_ht40_sta_assoc + , (vap->iv_flags_ht & IEEE80211_FHT_NONHT_PR) ? + ", non-HT sta present" : "" + , vap->iv_curhtprotmode); + + ieee80211_beacon_notify(vap, IEEE80211_BEACON_HTINFO); } /* @@ -1369,26 +1546,28 @@ htinfo_notify(struct ieee80211com *ic) * state and handle updates. */ static void -htinfo_update(struct ieee80211com *ic) +htinfo_update(struct ieee80211vap *vap) { + struct ieee80211com *ic = vap->iv_ic; uint8_t protmode; - if (ic->ic_sta_assoc != ic->ic_ht_sta_assoc) { + if (vap->iv_sta_assoc != vap->iv_ht_sta_assoc) { protmode = IEEE80211_HTINFO_OPMODE_MIXED | IEEE80211_HTINFO_NONHT_PRESENT; - } else if (ic->ic_flags_ht & IEEE80211_FHT_NONHT_PR) { + } else if (vap->iv_flags_ht & IEEE80211_FHT_NONHT_PR) { protmode = IEEE80211_HTINFO_OPMODE_PROTOPT | IEEE80211_HTINFO_NONHT_PRESENT; } else if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && IEEE80211_IS_CHAN_HT40(ic->ic_bsschan) && - ic->ic_sta_assoc != ic->ic_ht40_sta_assoc) { + vap->iv_sta_assoc != vap->iv_ht40_sta_assoc) { protmode = IEEE80211_HTINFO_OPMODE_HT20PR; } else { protmode = IEEE80211_HTINFO_OPMODE_PURE; } - if (protmode != ic->ic_curhtprotmode) { - ic->ic_curhtprotmode = protmode; - htinfo_notify(ic); + if (protmode != vap->iv_curhtprotmode) { + vap->iv_curhtprotmode = protmode; + /* Update VAP with new protection mode */ + ieee80211_vap_update_ht_protmode(vap); } } @@ -1398,16 +1577,16 @@ htinfo_update(struct ieee80211com *ic) void ieee80211_ht_node_join(struct ieee80211_node *ni) { - struct ieee80211com *ic = ni->ni_ic; + struct ieee80211vap *vap = ni->ni_vap; - IEEE80211_LOCK_ASSERT(ic); + IEEE80211_LOCK_ASSERT(vap->iv_ic); if (ni->ni_flags & IEEE80211_NODE_HT) { - ic->ic_ht_sta_assoc++; + vap->iv_ht_sta_assoc++; if (ni->ni_chw == 40) - ic->ic_ht40_sta_assoc++; + vap->iv_ht40_sta_assoc++; } - htinfo_update(ic); + htinfo_update(vap); } /* @@ -1416,16 +1595,16 @@ ieee80211_ht_node_join(struct ieee80211_node *ni) void ieee80211_ht_node_leave(struct ieee80211_node *ni) { - struct ieee80211com *ic = ni->ni_ic; + struct ieee80211vap *vap = ni->ni_vap; - IEEE80211_LOCK_ASSERT(ic); + IEEE80211_LOCK_ASSERT(vap->iv_ic); if (ni->ni_flags & IEEE80211_NODE_HT) { - ic->ic_ht_sta_assoc--; + vap->iv_ht_sta_assoc--; if (ni->ni_chw == 40) - ic->ic_ht40_sta_assoc--; + vap->iv_ht40_sta_assoc--; } - htinfo_update(ic); + htinfo_update(vap); } /* @@ -1439,25 +1618,27 @@ ieee80211_ht_node_leave(struct ieee80211_node *ni) * a higher precedence than PROTOPT (i.e. we will not change * change PROTOPT -> MIXED; only MIXED -> PROTOPT). This * corresponds to how we handle things in htinfo_update. + * */ void -ieee80211_htprot_update(struct ieee80211com *ic, int protmode) +ieee80211_htprot_update(struct ieee80211vap *vap, int protmode) { + struct ieee80211com *ic = vap->iv_ic; #define OPMODE(x) SM(x, IEEE80211_HTINFO_OPMODE) IEEE80211_LOCK(ic); /* track non-HT station presence */ KASSERT(protmode & IEEE80211_HTINFO_NONHT_PRESENT, ("protmode 0x%x", protmode)); - ic->ic_flags_ht |= IEEE80211_FHT_NONHT_PR; - ic->ic_lastnonht = ticks; + vap->iv_flags_ht |= IEEE80211_FHT_NONHT_PR; + vap->iv_lastnonht = ticks; - if (protmode != ic->ic_curhtprotmode && - (OPMODE(ic->ic_curhtprotmode) != IEEE80211_HTINFO_OPMODE_MIXED || + if (protmode != vap->iv_curhtprotmode && + (OPMODE(vap->iv_curhtprotmode) != IEEE80211_HTINFO_OPMODE_MIXED || OPMODE(protmode) == IEEE80211_HTINFO_OPMODE_PROTOPT)) { - /* push beacon update */ - ic->ic_curhtprotmode = protmode; - htinfo_notify(ic); + vap->iv_curhtprotmode = protmode; + /* Update VAP with new protection mode */ + ieee80211_vap_update_ht_protmode(vap); } IEEE80211_UNLOCK(ic); #undef OPMODE @@ -1472,18 +1653,17 @@ ieee80211_htprot_update(struct ieee80211com *ic, int protmode) * gone we time out this condition. */ void -ieee80211_ht_timeout(struct ieee80211com *ic) +ieee80211_ht_timeout(struct ieee80211vap *vap) { - IEEE80211_LOCK_ASSERT(ic); - if ((ic->ic_flags_ht & IEEE80211_FHT_NONHT_PR) && - ieee80211_time_after(ticks, ic->ic_lastnonht + IEEE80211_NONHT_PRESENT_AGE)) { -#if 0 - IEEE80211_NOTE(vap, IEEE80211_MSG_11N, ni, + IEEE80211_LOCK_ASSERT(vap->iv_ic); + + if ((vap->iv_flags_ht & IEEE80211_FHT_NONHT_PR) && + ieee80211_time_after(ticks, vap->iv_lastnonht + IEEE80211_NONHT_PRESENT_AGE)) { + IEEE80211_DPRINTF(vap, IEEE80211_MSG_11N, "%s", "time out non-HT STA present on channel"); -#endif - ic->ic_flags_ht &= ~IEEE80211_FHT_NONHT_PR; - htinfo_update(ic); + vap->iv_flags_ht &= ~IEEE80211_FHT_NONHT_PR; + htinfo_update(vap); } } @@ -1774,7 +1954,7 @@ ieee80211_vht_get_vhtflags(struct ieee80211_node *ni, uint32_t htflags) (MS(vap->iv_vhtcaps, IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK) == 2) && (vap->iv_flags_vht & IEEE80211_FVHT_USEVHT80P80)) { - vhtflags = IEEE80211_CHAN_VHT80_80; + vhtflags = IEEE80211_CHAN_VHT80P80; /* Mirror the HT40 flags */ if (htflags == IEEE80211_CHAN_HT40U) { vhtflags |= IEEE80211_CHAN_HT40U; @@ -2170,6 +2350,7 @@ ieee80211_addba_response(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap, int status, int baparamset, int batimeout) { + struct ieee80211vap *vap = ni->ni_vap; int bufsiz, tid; /* XXX locking */ @@ -2179,10 +2360,16 @@ ieee80211_addba_response(struct ieee80211_node *ni, /* XXX override our request? */ tap->txa_wnd = (bufsiz == 0) ? IEEE80211_AGGR_BAWMAX : min(bufsiz, IEEE80211_AGGR_BAWMAX); - /* XXX AC/TID */ tid = MS(baparamset, IEEE80211_BAPS_TID); tap->txa_flags |= IEEE80211_AGGR_RUNNING; tap->txa_attempts = 0; + /* TODO: this should be a vap flag */ + if ((vap->iv_htcaps & IEEE80211_HTC_TX_AMSDU_AMPDU) && + (ni->ni_flags & IEEE80211_NODE_AMSDU_TX) && + (MS(baparamset, IEEE80211_BAPS_AMSDU))) + tap->txa_flags |= IEEE80211_AGGR_AMSDU; + else + tap->txa_flags &= ~IEEE80211_AGGR_AMSDU; } else { /* mark tid so we don't try again */ tap->txa_flags |= IEEE80211_AGGR_NAK; @@ -2201,7 +2388,7 @@ ieee80211_addba_stop(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap) addba_stop_timeout(tap); if (tap->txa_flags & IEEE80211_AGGR_RUNNING) { /* XXX clear aggregation queue */ - tap->txa_flags &= ~IEEE80211_AGGR_RUNNING; + tap->txa_flags &= ~(IEEE80211_AGGR_RUNNING | IEEE80211_AGGR_AMSDU); } tap->txa_attempts = 0; } @@ -2234,12 +2421,13 @@ ht_recv_action_ba_addba_request(struct ieee80211_node *ni, IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni, "recv ADDBA request: dialogtoken %u baparamset 0x%x " - "(tid %d bufsiz %d) batimeout %d baseqctl %d:%d", + "(tid %d bufsiz %d) batimeout %d baseqctl %d:%d amsdu %d", dialogtoken, baparamset, tid, MS(baparamset, IEEE80211_BAPS_BUFSIZ), batimeout, MS(baseqctl, IEEE80211_BASEQ_START), - MS(baseqctl, IEEE80211_BASEQ_FRAG)); + MS(baseqctl, IEEE80211_BASEQ_FRAG), + MS(baparamset, IEEE80211_BAPS_AMSDU)); rap = &ni->ni_rx_ampdu[tid]; @@ -2252,7 +2440,7 @@ ht_recv_action_ba_addba_request(struct ieee80211_node *ni, */ if ((ni->ni_flags & IEEE80211_NODE_AMPDU_RX) && (vap->iv_flags_ht & IEEE80211_FHT_AMPDU_RX)) { - /* XXX handle ampdu_rx_start failure */ + /* XXX TODO: handle ampdu_rx_start failure */ ic->ic_ampdu_rx_start(ni, rap, baparamset, batimeout, baseqctl); @@ -2271,6 +2459,16 @@ ht_recv_action_ba_addba_request(struct ieee80211_node *ni, | SM(tid, IEEE80211_BAPS_TID) | SM(rap->rxa_wnd, IEEE80211_BAPS_BUFSIZ) ; + + /* + * TODO: we're out of iv_flags_ht fields; once + * this is extended we should make this configurable. + */ + if ((baparamset & IEEE80211_BAPS_AMSDU) && + (ni->ni_flags & IEEE80211_NODE_AMSDU_RX) && + (vap->iv_htcaps & IEEE80211_HTC_RX_AMSDU_AMPDU)) + args[2] |= IEEE80211_BAPS_AMSDU; + args[3] = 0; args[4] = 0; ic->ic_send_action(ni, IEEE80211_ACTION_CAT_BA, @@ -2289,6 +2487,7 @@ ht_recv_action_ba_addba_response(struct ieee80211_node *ni, uint8_t dialogtoken, policy; uint16_t baparamset, batimeout, code; int tid, bufsiz; + int amsdu; dialogtoken = frm[2]; code = le16dec(frm+3); @@ -2296,6 +2495,7 @@ ht_recv_action_ba_addba_response(struct ieee80211_node *ni, tid = MS(baparamset, IEEE80211_BAPS_TID); bufsiz = MS(baparamset, IEEE80211_BAPS_BUFSIZ); policy = MS(baparamset, IEEE80211_BAPS_POLICY); + amsdu = !! MS(baparamset, IEEE80211_BAPS_AMSDU); batimeout = le16dec(frm+7); tap = &ni->ni_tx_ampdu[tid]; @@ -2343,10 +2543,13 @@ ht_recv_action_ba_addba_response(struct ieee80211_node *ni, return 0; } #endif + IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni, "recv ADDBA response: dialogtoken %u code %d " - "baparamset 0x%x (tid %d bufsiz %d) batimeout %d", - dialogtoken, code, baparamset, tid, bufsiz, + "baparamset 0x%x (tid %d bufsiz %d amsdu %d) batimeout %d", + dialogtoken, code, baparamset, tid, + bufsiz, + amsdu, batimeout); ic->ic_addba_response(ni, tap, code, baparamset, batimeout); return 0; @@ -2503,6 +2706,12 @@ ieee80211_ampdu_request(struct ieee80211_node *ni, | SM(tid, IEEE80211_BAPS_TID) | SM(IEEE80211_AGGR_BAWMAX, IEEE80211_BAPS_BUFSIZ) ; + + /* XXX TODO: this should be a flag, not iv_htcaps */ + if ((ni->ni_flags & IEEE80211_NODE_AMSDU_TX) && + (ni->ni_vap->iv_htcaps & IEEE80211_HTC_TX_AMSDU_AMPDU)) + args[2] |= IEEE80211_BAPS_AMSDU; + args[3] = 0; /* batimeout */ /* NB: do first so there's no race against reply */ if (!ic->ic_addba_request(ni, tap, dialogtoken, args[2], args[3])) { @@ -2834,11 +3043,11 @@ ht_send_action_ba_addba(struct ieee80211_node *ni, IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni, "send ADDBA %s: dialogtoken %d status %d " - "baparamset 0x%x (tid %d) batimeout 0x%x baseqctl 0x%x", + "baparamset 0x%x (tid %d amsdu %d) batimeout 0x%x baseqctl 0x%x", (action == IEEE80211_ACTION_BA_ADDBA_REQUEST) ? "request" : "response", args[0], args[1], args[2], MS(args[2], IEEE80211_BAPS_TID), - args[3], args[4]); + MS(args[2], IEEE80211_BAPS_AMSDU), args[3], args[4]); IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE, "ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n", __func__, __LINE__, @@ -3299,6 +3508,12 @@ ieee80211_ht_update_beacon(struct ieee80211vap *vap, ht->hi_byte1 |= IEEE80211_HTINFO_TXWIDTH_2040; /* protection mode */ + /* + * XXX TODO: this uses the global flag, not the per-VAP flag. + * Eventually (once the protection modes are done per-channel + * rather than per-VAP) we can flip this over to be per-VAP but + * using the channel protection mode. + */ ht->hi_byte2 = (ht->hi_byte2 &~ PROTMODE) | ic->ic_curhtprotmode; ieee80211_free_node(ni); @@ -3339,7 +3554,11 @@ ieee80211_add_htinfo_body(uint8_t *frm, struct ieee80211_node *ni) if (IEEE80211_IS_CHAN_HT40(ni->ni_chan)) frm[0] |= IEEE80211_HTINFO_TXWIDTH_2040; - frm[1] = ic->ic_curhtprotmode; + /* + * Add current protection mode. Unlike for beacons, + * this will respect the per-VAP flags. + */ + frm[1] = vap->iv_curhtprotmode; frm += 5; diff --git a/sys/net80211/ieee80211_ht.h b/sys/net80211/ieee80211_ht.h index 4e02cd3270ee..7f62b0f7c756 100644 --- a/sys/net80211/ieee80211_ht.h +++ b/sys/net80211/ieee80211_ht.h @@ -33,6 +33,8 @@ * 802.11n protocol implementation definitions. */ +#include <sys/mbuf.h> + #define IEEE80211_AGGR_BAWMAX 64 /* max block ack window size */ /* threshold for aging overlapping non-HT bss */ #define IEEE80211_NONHT_PRESENT_AGE msecs_to_ticks(60*1000) @@ -47,6 +49,7 @@ struct ieee80211_tx_ampdu { #define IEEE80211_AGGR_NAK 0x0010 /* peer NAK'd ADDBA request */ #define IEEE80211_AGGR_BARPEND 0x0020 /* BAR response pending */ #define IEEE80211_AGGR_WAITRX 0x0040 /* Wait for first RX frame to define BAW */ +#define IEEE80211_AGGR_AMSDU 0x0080 /* A-MSDU in A-MPDU TX allowed */ uint8_t txa_tid; uint8_t txa_token; /* dialog token */ int txa_lastsample; /* ticks @ last traffic sample */ @@ -68,6 +71,14 @@ struct ieee80211_tx_ampdu { #define IEEE80211_AMPDU_RUNNING(tap) \ (((tap)->txa_flags & IEEE80211_AGGR_RUNNING) != 0) +/* + * Return non-zero if AMPDU tx for the TID is running and we can do + * A-MSDU in A-MPDU + */ +#define IEEE80211_AMPDU_RUNNING_AMSDU(tap) \ + (((tap)->txa_flags & (IEEE80211_AGGR_RUNNING | IEEE80211_AGGR_AMSDU)) \ + == (IEEE80211_AGGR_RUNNING | IEEE80211_AGGR_AMSDU)) + /* return non-zero if AMPDU tx for the TID was NACKed */ #define IEEE80211_AMPDU_NACKED(tap)\ (!! ((tap)->txa_flags & IEEE80211_AGGR_NAK)) @@ -160,7 +171,7 @@ struct ieee80211_rx_ampdu { uint16_t rxa_wnd; /* BA window size */ int rxa_age; /* age of oldest frame in window */ int rxa_nframes; /* frames since ADDBA */ - struct mbuf *rxa_m[IEEE80211_AGGR_BAWMAX]; + struct mbufq rxa_mq[IEEE80211_AGGR_BAWMAX]; void *rxa_private; uint64_t rxa_pad[3]; }; @@ -199,8 +210,8 @@ struct ieee80211_channel *ieee80211_ht_adjust_channel(struct ieee80211com *, void ieee80211_ht_wds_init(struct ieee80211_node *); void ieee80211_ht_node_join(struct ieee80211_node *); void ieee80211_ht_node_leave(struct ieee80211_node *); -void ieee80211_htprot_update(struct ieee80211com *, int protmode); -void ieee80211_ht_timeout(struct ieee80211com *); +void ieee80211_htprot_update(struct ieee80211vap *, int protmode); +void ieee80211_ht_timeout(struct ieee80211vap *); void ieee80211_parse_htcap(struct ieee80211_node *, const uint8_t *); void ieee80211_parse_htinfo(struct ieee80211_node *, const uint8_t *); void ieee80211_ht_updateparams(struct ieee80211_node *, const uint8_t *, @@ -230,5 +241,6 @@ void ieee80211_ampdu_rx_stop_ext(struct ieee80211_node *ni, int tid); int ieee80211_ampdu_tx_request_ext(struct ieee80211_node *ni, int tid); int ieee80211_ampdu_tx_request_active_ext(struct ieee80211_node *ni, int tid, int status); +void ieee80211_htinfo_notify(struct ieee80211vap *vap); #endif /* _NET80211_IEEE80211_HT_H_ */ diff --git a/sys/net80211/ieee80211_input.h b/sys/net80211/ieee80211_input.h index 2f3afc3b7e41..810dcbde7978 100644 --- a/sys/net80211/ieee80211_input.h +++ b/sys/net80211/ieee80211_input.h @@ -136,7 +136,8 @@ ishtinfooui(const uint8_t *frm) static __inline int ieee80211_check_rxseq_amsdu(const struct ieee80211_rx_stats *rxs) { - + if (rxs == NULL) + return 0; return (!! (rxs->c_pktflags & IEEE80211_RX_F_AMSDU)); } diff --git a/sys/net80211/ieee80211_ioctl.c b/sys/net80211/ieee80211_ioctl.c index 6ef5f9fb2b75..b5e79f2ef07f 100644 --- a/sys/net80211/ieee80211_ioctl.c +++ b/sys/net80211/ieee80211_ioctl.c @@ -106,7 +106,8 @@ ieee80211_ioctl_getkey(struct ieee80211vap *vap, struct ieee80211req *ireq) ik.ik_flags = wk->wk_flags & (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV); if (wk->wk_keyix == vap->iv_def_txkey) ik.ik_flags |= IEEE80211_KEY_DEFAULT; - if (priv_check(curthread, PRIV_NET80211_GETKEY) == 0) { + /* XXX TODO: move priv check to ieee80211_freebsd.c */ + if (priv_check(curthread, PRIV_NET80211_VAP_GETKEY) == 0) { /* NB: only root can read key data */ ik.ik_keyrsc = wk->wk_keyrsc[IEEE80211_NONQOS_TID]; ik.ik_keytsc = wk->wk_keytsc; @@ -784,6 +785,13 @@ ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_long cmd, int error = 0; switch (ireq->i_type) { + case IEEE80211_IOC_IC_NAME: + len = strlen(ic->ic_name) + 1; + if (len > ireq->i_len) + return (EINVAL); + ireq->i_len = len; + error = copyout(ic->ic_name, ireq->i_data, ireq->i_len); + break; case IEEE80211_IOC_SSID: switch (vap->iv_state) { case IEEE80211_S_INIT: @@ -815,7 +823,8 @@ ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_long cmd, return EINVAL; len = (u_int) vap->iv_nw_keys[kid].wk_keylen; /* NB: only root can read WEP keys */ - if (priv_check(curthread, PRIV_NET80211_GETKEY) == 0) { + /* XXX TODO: move priv check to ieee80211_freebsd.c */ + if (priv_check(curthread, PRIV_NET80211_VAP_GETKEY) == 0) { bcopy(vap->iv_nw_keys[kid].wk_key, tmpkey, len); } else { bzero(tmpkey, len); @@ -851,7 +860,7 @@ ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_long cmd, ireq->i_val = vap->iv_rtsthreshold; break; case IEEE80211_IOC_PROTMODE: - ireq->i_val = ic->ic_protmode; + ireq->i_val = vap->iv_protmode; break; case IEEE80211_IOC_TXPOWER: /* @@ -1097,7 +1106,7 @@ ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_long cmd, error = ieee80211_ioctl_getdevcaps(ic, ireq); break; case IEEE80211_IOC_HTPROTMODE: - ireq->i_val = ic->ic_htprotmode; + ireq->i_val = vap->iv_htprotmode; break; case IEEE80211_IOC_HTCONF: if (vap->iv_flags_ht & IEEE80211_FHT_HT) { @@ -1145,22 +1154,14 @@ ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_long cmd, if (vap->iv_flags_ht & IEEE80211_FHT_LDPC_RX) ireq->i_val |= 2; break; - - /* VHT */ - case IEEE80211_IOC_VHTCONF: + case IEEE80211_IOC_UAPSD: ireq->i_val = 0; - if (vap->iv_flags_vht & IEEE80211_FVHT_VHT) - ireq->i_val |= 1; - if (vap->iv_flags_vht & IEEE80211_FVHT_USEVHT40) - ireq->i_val |= 2; - if (vap->iv_flags_vht & IEEE80211_FVHT_USEVHT80) - ireq->i_val |= 4; - if (vap->iv_flags_vht & IEEE80211_FVHT_USEVHT80P80) - ireq->i_val |= 8; - if (vap->iv_flags_vht & IEEE80211_FVHT_USEVHT160) - ireq->i_val |= 16; + if (vap->iv_flags_ext & IEEE80211_FEXT_UAPSD) + ireq->i_val = 1; + break; + case IEEE80211_IOC_VHTCONF: + ireq->i_val = vap->iv_flags_vht & IEEE80211_FVHT_MASK; break; - default: error = ieee80211_ioctl_getdefault(vap, ireq); break; @@ -2907,11 +2908,13 @@ ieee80211_ioctl_set80211(struct ieee80211vap *vap, u_long cmd, struct ieee80211r case IEEE80211_IOC_PROTMODE: if (ireq->i_val > IEEE80211_PROT_RTSCTS) return EINVAL; - ic->ic_protmode = (enum ieee80211_protmode)ireq->i_val; + vap->iv_protmode = (enum ieee80211_protmode)ireq->i_val; /* NB: if not operating in 11g this can wait */ if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan)) error = ERESTART; + /* driver callback for protection mode update */ + ieee80211_vap_update_erp_protmode(vap); break; case IEEE80211_IOC_TXPOWER: if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0) @@ -3379,11 +3382,13 @@ ieee80211_ioctl_set80211(struct ieee80211vap *vap, u_long cmd, struct ieee80211r case IEEE80211_IOC_HTPROTMODE: if (ireq->i_val > IEEE80211_PROT_RTSCTS) return EINVAL; - ic->ic_htprotmode = ireq->i_val ? + vap->iv_htprotmode = ireq->i_val ? IEEE80211_PROT_RTSCTS : IEEE80211_PROT_NONE; /* NB: if not operating in 11n this can wait */ if (isvapht(vap)) error = ERESTART; + /* Notify driver layer of HT protmode changes */ + ieee80211_vap_update_ht_protmode(vap); break; case IEEE80211_IOC_STA_VLAN: error = ieee80211_ioctl_setstavlan(vap, ireq); @@ -3462,34 +3467,44 @@ ieee80211_ioctl_set80211(struct ieee80211vap *vap, u_long cmd, struct ieee80211r if (isvapht(vap)) error = ERESTART; break; + case IEEE80211_IOC_UAPSD: + if ((vap->iv_caps & IEEE80211_C_UAPSD) == 0) + return EOPNOTSUPP; + if (ireq->i_val == 0) + vap->iv_flags_ext &= ~IEEE80211_FEXT_UAPSD; + else if (ireq->i_val == 1) + vap->iv_flags_ext |= IEEE80211_FEXT_UAPSD; + else + return EINVAL; + break; /* VHT */ case IEEE80211_IOC_VHTCONF: - if (ireq->i_val & 1) + if (ireq->i_val & IEEE80211_FVHT_VHT) ieee80211_syncflag_vht(vap, IEEE80211_FVHT_VHT); else ieee80211_syncflag_vht(vap, -IEEE80211_FVHT_VHT); - if (ireq->i_val & 2) + if (ireq->i_val & IEEE80211_FVHT_USEVHT40) ieee80211_syncflag_vht(vap, IEEE80211_FVHT_USEVHT40); else ieee80211_syncflag_vht(vap, -IEEE80211_FVHT_USEVHT40); - if (ireq->i_val & 4) + if (ireq->i_val & IEEE80211_FVHT_USEVHT80) ieee80211_syncflag_vht(vap, IEEE80211_FVHT_USEVHT80); else ieee80211_syncflag_vht(vap, -IEEE80211_FVHT_USEVHT80); - if (ireq->i_val & 8) - ieee80211_syncflag_vht(vap, IEEE80211_FVHT_USEVHT80P80); - else - ieee80211_syncflag_vht(vap, -IEEE80211_FVHT_USEVHT80P80); - - if (ireq->i_val & 16) + if (ireq->i_val & IEEE80211_FVHT_USEVHT160) ieee80211_syncflag_vht(vap, IEEE80211_FVHT_USEVHT160); else ieee80211_syncflag_vht(vap, -IEEE80211_FVHT_USEVHT160); + if (ireq->i_val & IEEE80211_FVHT_USEVHT80P80) + ieee80211_syncflag_vht(vap, IEEE80211_FVHT_USEVHT80P80); + else + ieee80211_syncflag_vht(vap, -IEEE80211_FVHT_USEVHT80P80); + error = ENETRESET; break; @@ -3615,7 +3630,8 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) (struct ieee80211req *) data); break; case SIOCS80211: - error = priv_check(curthread, PRIV_NET80211_MANAGE); + /* XXX TODO: move priv check to ieee80211_freebsd.c */ + error = priv_check(curthread, PRIV_NET80211_VAP_MANAGE); if (error == 0) error = ieee80211_ioctl_set80211(vap, cmd, (struct ieee80211req *) data); @@ -3660,6 +3676,12 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) break; } break; + case SIOCSIFLLADDR: + /* XXX TODO: move priv check to ieee80211_freebsd.c */ + error = priv_check(curthread, PRIV_NET80211_VAP_SETMAC); + if (error == 0) + break; + /* Fallthrough */ default: /* * Pass unknown ioctls first to the driver, and if it diff --git a/sys/net80211/ieee80211_ioctl.h b/sys/net80211/ieee80211_ioctl.h index 5021285bad1a..573661d5323d 100644 --- a/sys/net80211/ieee80211_ioctl.h +++ b/sys/net80211/ieee80211_ioctl.h @@ -710,6 +710,8 @@ struct ieee80211req { #define IEEE80211_IOC_GREENFIELD 112 /* Greenfield (on, off) */ #define IEEE80211_IOC_STBC 113 /* STBC Tx/RX (on, off) */ #define IEEE80211_IOC_LDPC 114 /* LDPC Tx/RX (on, off) */ +#define IEEE80211_IOC_UAPSD 115 /* UAPSD (on, off) */ +#define IEEE80211_IOC_UAPSD_INFO 116 /* UAPSD (SP, per-AC enable) */ /* VHT */ #define IEEE80211_IOC_VHTCONF 130 /* VHT config (off, on; widths) */ @@ -741,6 +743,9 @@ struct ieee80211req { #define IEEE80211_IOC_QUIET_OFFSET 207 /* Quiet Offset */ #define IEEE80211_IOC_QUIET_DUR 208 /* Quiet Duration */ #define IEEE80211_IOC_QUIET_COUNT 209 /* Quiet Count */ + +#define IEEE80211_IOC_IC_NAME 210 /* HW device name. */ + /* * Parameters for controlling a scan requested with * IEEE80211_IOC_SCAN_REQ. diff --git a/sys/net80211/ieee80211_node.c b/sys/net80211/ieee80211_node.c index a1415d73ec6d..9ee5b1b83cde 100644 --- a/sys/net80211/ieee80211_node.c +++ b/sys/net80211/ieee80211_node.c @@ -80,6 +80,7 @@ static int ieee80211_sta_join1(struct ieee80211_node *); static struct ieee80211_node *node_alloc(struct ieee80211vap *, const uint8_t [IEEE80211_ADDR_LEN]); +static int node_init(struct ieee80211_node *); static void node_cleanup(struct ieee80211_node *); static void node_free(struct ieee80211_node *); static void node_age(struct ieee80211_node *); @@ -98,7 +99,7 @@ static void ieee80211_node_table_init(struct ieee80211com *ic, static void ieee80211_node_table_reset(struct ieee80211_node_table *, struct ieee80211vap *); static void ieee80211_node_table_cleanup(struct ieee80211_node_table *nt); -static void ieee80211_erp_timeout(struct ieee80211com *); +static void ieee80211_vap_erp_timeout(struct ieee80211vap *); MALLOC_DEFINE(M_80211_NODE, "80211node", "802.11 node state"); MALLOC_DEFINE(M_80211_NODE_IE, "80211nodeie", "802.11 node ie"); @@ -116,6 +117,7 @@ ieee80211_node_attach(struct ieee80211com *ic) ieee80211_node_timeout, ic); ic->ic_node_alloc = node_alloc; + ic->ic_node_init = node_init; ic->ic_node_free = node_free; ic->ic_node_cleanup = node_cleanup; ic->ic_node_age = node_age; @@ -446,7 +448,7 @@ ieee80211_reset_bss(struct ieee80211vap *vap) ieee80211_node_table_reset(&ic->ic_sta, vap); /* XXX multi-bss: wrong */ - ieee80211_reset_erp(ic); + ieee80211_vap_reset_erp(vap); ni = ieee80211_alloc_node(&ic->ic_sta, vap, vap->iv_myaddr); KASSERT(ni != NULL, ("unable to setup initial BSS node")); @@ -672,7 +674,6 @@ ieee80211_ibss_merge(struct ieee80211_node *ni) { #ifdef IEEE80211_DEBUG struct ieee80211vap *vap = ni->ni_vap; - struct ieee80211com *ic = ni->ni_ic; #endif if (! ieee80211_ibss_merge_check(ni)) @@ -681,9 +682,9 @@ ieee80211_ibss_merge(struct ieee80211_node *ni) IEEE80211_DPRINTF(vap, IEEE80211_MSG_ASSOC, "%s: new bssid %s: %s preamble, %s slot time%s\n", __func__, ether_sprintf(ni->ni_bssid), - ic->ic_flags&IEEE80211_F_SHPREAMBLE ? "short" : "long", - ic->ic_flags&IEEE80211_F_SHSLOT ? "short" : "long", - ic->ic_flags&IEEE80211_F_USEPROT ? ", protection" : "" + vap->iv_flags&IEEE80211_F_SHPREAMBLE ? "short" : "long", + vap->iv_flags&IEEE80211_F_SHSLOT ? "short" : "long", + vap->iv_flags&IEEE80211_F_USEPROT ? ", protection" : "" ); return ieee80211_sta_join1(ieee80211_ref_node(ni)); } @@ -881,7 +882,7 @@ ieee80211_sta_join1(struct ieee80211_node *selbs) * the auto-select case; this should be redundant if the * mode is locked. */ - ieee80211_reset_erp(ic); + ieee80211_vap_reset_erp(vap); ieee80211_wme_initparams(vap); if (vap->iv_opmode == IEEE80211_M_STA) { @@ -1074,6 +1075,12 @@ node_alloc(struct ieee80211vap *vap, const uint8_t macaddr[IEEE80211_ADDR_LEN]) return ni; } +static int +node_init(struct ieee80211_node *ni) +{ + return 0; +} + /* * Initialize an ie blob with the specified data. If previous * data exists re-use the data block. As a side effect we clear @@ -1414,6 +1421,15 @@ ieee80211_alloc_node(struct ieee80211_node_table *nt, ni->ni_ic = ic; IEEE80211_NODE_UNLOCK(nt); + /* handle failure; free node state */ + if (ic->ic_node_init(ni) != 0) { + vap->iv_stats.is_rx_nodealloc++; + ieee80211_psq_cleanup(&ni->ni_psq); + ieee80211_ratectl_node_deinit(ni); + _ieee80211_free_node(ni); + return NULL; + } + IEEE80211_NOTE(vap, IEEE80211_MSG_INACT, ni, "%s: inact_reload %u", __func__, ni->ni_inact_reload); @@ -1456,6 +1472,16 @@ ieee80211_tmp_node(struct ieee80211vap *vap, ieee80211_psq_init(&ni->ni_psq, "unknown"); ieee80211_ratectl_node_init(ni); + + /* handle failure; free node state */ + if (ic->ic_node_init(ni) != 0) { + vap->iv_stats.is_rx_nodealloc++; + ieee80211_psq_cleanup(&ni->ni_psq); + ieee80211_ratectl_node_deinit(ni); + _ieee80211_free_node(ni); + return NULL; + } + } else { /* XXX msg */ vap->iv_stats.is_rx_nodealloc++; @@ -2481,12 +2507,27 @@ ieee80211_drain(struct ieee80211com *ic) } /* + * Per-ieee80211vap inactivity timer callback. + */ +static void +ieee80211_vap_timeout(struct ieee80211vap *vap) +{ + + IEEE80211_LOCK_ASSERT(vap->iv_ic); + + ieee80211_vap_erp_timeout(vap); + ieee80211_ht_timeout(vap); + ieee80211_vht_timeout(vap); +} + +/* * Per-ieee80211com inactivity timer callback. */ void ieee80211_node_timeout(void *arg) { struct ieee80211com *ic = arg; + struct ieee80211vap *vap; /* * Defer timeout processing if a channel switch is pending. @@ -2503,9 +2544,8 @@ ieee80211_node_timeout(void *arg) ieee80211_ageq_age(&ic->ic_stageq, IEEE80211_INACT_WAIT); IEEE80211_LOCK(ic); - ieee80211_erp_timeout(ic); - ieee80211_ht_timeout(ic); - ieee80211_vht_timeout(ic); + TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) + ieee80211_vap_timeout(vap); IEEE80211_UNLOCK(ic); } callout_reset(&ic->ic_inact, IEEE80211_INACT_WAIT*hz, @@ -2618,7 +2658,12 @@ ieee80211_dump_nodes(struct ieee80211_node_table *nt) (ieee80211_iter_func *) ieee80211_dump_node, nt); } -static void +/* + * Iterate over the VAPs and update their ERP beacon IEs. + * + * Note this must be called from the deferred ERP update task paths. + */ +void ieee80211_notify_erp_locked(struct ieee80211com *ic) { struct ieee80211vap *vap; @@ -2630,14 +2675,6 @@ ieee80211_notify_erp_locked(struct ieee80211com *ic) ieee80211_beacon_notify(vap, IEEE80211_BEACON_ERP); } -void -ieee80211_notify_erp(struct ieee80211com *ic) -{ - IEEE80211_LOCK(ic); - ieee80211_notify_erp_locked(ic); - IEEE80211_UNLOCK(ic); -} - /* * Handle a station joining an 11g network. */ @@ -2645,6 +2682,7 @@ static void ieee80211_node_join_11g(struct ieee80211_node *ni) { struct ieee80211com *ic = ni->ni_ic; + struct ieee80211vap *vap = ni->ni_vap; IEEE80211_LOCK_ASSERT(ic); @@ -2656,18 +2694,20 @@ ieee80211_node_join_11g(struct ieee80211_node *ni) * next beacon transmission (per sec. 7.3.1.4 of 11g). */ if ((ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME) == 0) { - ic->ic_longslotsta++; + vap->iv_longslotsta++; IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_ASSOC, ni, "station needs long slot time, count %d", - ic->ic_longslotsta); - /* XXX vap's w/ conflicting needs won't work */ + vap->iv_longslotsta); + /* + * XXX TODO: this may need all VAPs checked! + */ if (!IEEE80211_IS_CHAN_108G(ic->ic_bsschan)) { /* * Don't force slot time when switched to turbo * mode as non-ERP stations won't be present; this * need only be done when on the normal G channel. */ - ieee80211_set_shortslottime(ic, 0); + ieee80211_vap_set_shortslottime(vap, 0); } } /* @@ -2676,10 +2716,10 @@ ieee80211_node_join_11g(struct ieee80211_node *ni) * if configured. */ if (!ieee80211_iserp_rateset(&ni->ni_rates)) { - ic->ic_nonerpsta++; + vap->iv_nonerpsta++; IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_ASSOC, ni, "station is !ERP, %d non-ERP stations associated", - ic->ic_nonerpsta); + vap->iv_nonerpsta); /* * If station does not support short preamble * then we must enable use of Barker preamble. @@ -2687,20 +2727,21 @@ ieee80211_node_join_11g(struct ieee80211_node *ni) if ((ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE) == 0) { IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_ASSOC, ni, "%s", "station needs long preamble"); - ic->ic_flags |= IEEE80211_F_USEBARKER; - ic->ic_flags &= ~IEEE80211_F_SHPREAMBLE; + vap->iv_flags |= IEEE80211_F_USEBARKER; + vap->iv_flags &= ~IEEE80211_F_SHPREAMBLE; + ieee80211_vap_update_preamble(vap); } /* * If protection is configured and this is the first * indication we should use protection, enable it. */ - if (ic->ic_protmode != IEEE80211_PROT_NONE && - ic->ic_nonerpsta == 1 && - (ic->ic_flags_ext & IEEE80211_FEXT_NONERP_PR) == 0) { + if (vap->iv_protmode != IEEE80211_PROT_NONE && + vap->iv_nonerpsta == 1 && + (vap->iv_flags_ext & IEEE80211_FEXT_NONERP_PR) == 0) { IEEE80211_DPRINTF(ni->ni_vap, IEEE80211_MSG_ASSOC, "%s: enable use of protection\n", __func__); - ic->ic_flags |= IEEE80211_F_USEPROT; - ieee80211_notify_erp_locked(ic); + vap->iv_flags |= IEEE80211_F_USEPROT; + ieee80211_vap_update_erp_protmode(vap); } } else ni->ni_flags |= IEEE80211_NODE_ERP; @@ -2735,7 +2776,6 @@ ieee80211_node_join(struct ieee80211_node *ni, int resp) IEEE80211_LOCK(ic); IEEE80211_AID_SET(vap, ni->ni_associd); vap->iv_sta_assoc++; - ic->ic_sta_assoc++; if (IEEE80211_IS_CHAN_HT(ic->ic_bsschan)) ieee80211_ht_node_join(ni); @@ -2754,16 +2794,17 @@ ieee80211_node_join(struct ieee80211_node *ni, int resp) * XXX VHT - should log VHT channel width, etc */ IEEE80211_NOTE(vap, IEEE80211_MSG_ASSOC | IEEE80211_MSG_DEBUG, ni, - "station associated at aid %d: %s preamble, %s slot time%s%s%s%s%s%s%s%s", + "station associated at aid %d: %s preamble, %s slot time%s%s%s%s%s%s%s%s%s", IEEE80211_NODE_AID(ni), - ic->ic_flags & IEEE80211_F_SHPREAMBLE ? "short" : "long", - ic->ic_flags & IEEE80211_F_SHSLOT ? "short" : "long", - ic->ic_flags & IEEE80211_F_USEPROT ? ", protection" : "", + vap->iv_flags & IEEE80211_F_SHPREAMBLE ? "short" : "long", + vap->iv_flags & IEEE80211_F_SHSLOT ? "short" : "long", + vap->iv_flags & IEEE80211_F_USEPROT ? ", protection" : "", ni->ni_flags & IEEE80211_NODE_QOS ? ", QoS" : "", /* XXX update for VHT string */ ni->ni_flags & IEEE80211_NODE_HT ? (ni->ni_chw == 40 ? ", HT40" : ", HT20") : "", ni->ni_flags & IEEE80211_NODE_AMPDU ? " (+AMPDU)" : "", + ni->ni_flags & IEEE80211_NODE_AMSDU ? " (+AMSDU)" : "", ni->ni_flags & IEEE80211_NODE_MIMO_RTS ? " (+SMPS-DYN)" : ni->ni_flags & IEEE80211_NODE_MIMO_PS ? " (+SMPS)" : "", ni->ni_flags & IEEE80211_NODE_RIFS ? " (+RIFS)" : "", @@ -2787,20 +2828,23 @@ ieee80211_node_join(struct ieee80211_node *ni, int resp) } static void -disable_protection(struct ieee80211com *ic) +disable_protection(struct ieee80211vap *vap) { - KASSERT(ic->ic_nonerpsta == 0 && - (ic->ic_flags_ext & IEEE80211_FEXT_NONERP_PR) == 0, - ("%d non ERP stations, flags 0x%x", ic->ic_nonerpsta, - ic->ic_flags_ext)); + struct ieee80211com *ic = vap->iv_ic; - ic->ic_flags &= ~IEEE80211_F_USEPROT; + KASSERT(vap->iv_nonerpsta == 0 && + (vap->iv_flags_ext & IEEE80211_FEXT_NONERP_PR) == 0, + ("%d non ERP stations, flags 0x%x", vap->iv_nonerpsta, + vap->iv_flags_ext)); + + vap->iv_flags &= ~IEEE80211_F_USEPROT; /* XXX verify mode? */ if (ic->ic_caps & IEEE80211_C_SHPREAMBLE) { - ic->ic_flags |= IEEE80211_F_SHPREAMBLE; - ic->ic_flags &= ~IEEE80211_F_USEBARKER; + vap->iv_flags |= IEEE80211_F_SHPREAMBLE; + vap->iv_flags &= ~IEEE80211_F_USEBARKER; } - ieee80211_notify_erp_locked(ic); + ieee80211_vap_update_erp_protmode(vap); + ieee80211_vap_update_preamble(vap); } /* @@ -2810,6 +2854,7 @@ static void ieee80211_node_leave_11g(struct ieee80211_node *ni) { struct ieee80211com *ic = ni->ni_ic; + struct ieee80211vap *vap = ni->ni_vap; IEEE80211_LOCK_ASSERT(ic); @@ -2821,13 +2866,16 @@ ieee80211_node_leave_11g(struct ieee80211_node *ni) * If a long slot station do the slot time bookkeeping. */ if ((ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME) == 0) { - KASSERT(ic->ic_longslotsta > 0, - ("bogus long slot station count %d", ic->ic_longslotsta)); - ic->ic_longslotsta--; + KASSERT(vap->iv_longslotsta > 0, + ("bogus long slot station count %d", vap->iv_longslotsta)); + vap->iv_longslotsta--; IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_ASSOC, ni, "long slot time station leaves, count now %d", - ic->ic_longslotsta); - if (ic->ic_longslotsta == 0) { + vap->iv_longslotsta); + /* + * XXX TODO: this may need all VAPs checked! + */ + if (vap->iv_longslotsta == 0) { /* * Re-enable use of short slot time if supported * and not operating in IBSS mode (per spec). @@ -2838,7 +2886,7 @@ ieee80211_node_leave_11g(struct ieee80211_node *ni) IEEE80211_MSG_ASSOC, "%s: re-enable use of short slot time\n", __func__); - ieee80211_set_shortslottime(ic, 1); + ieee80211_vap_set_shortslottime(vap, 1); } } } @@ -2846,18 +2894,18 @@ ieee80211_node_leave_11g(struct ieee80211_node *ni) * If a non-ERP station do the protection-related bookkeeping. */ if ((ni->ni_flags & IEEE80211_NODE_ERP) == 0) { - KASSERT(ic->ic_nonerpsta > 0, - ("bogus non-ERP station count %d", ic->ic_nonerpsta)); - ic->ic_nonerpsta--; + KASSERT(vap->iv_nonerpsta > 0, + ("bogus non-ERP station count %d", vap->iv_nonerpsta)); + vap->iv_nonerpsta--; IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_ASSOC, ni, - "non-ERP station leaves, count now %d%s", ic->ic_nonerpsta, - (ic->ic_flags_ext & IEEE80211_FEXT_NONERP_PR) ? + "non-ERP station leaves, count now %d%s", vap->iv_nonerpsta, + (vap->iv_flags_ext & IEEE80211_FEXT_NONERP_PR) ? " (non-ERP sta present)" : ""); - if (ic->ic_nonerpsta == 0 && - (ic->ic_flags_ext & IEEE80211_FEXT_NONERP_PR) == 0) { + if (vap->iv_nonerpsta == 0 && + (vap->iv_flags_ext & IEEE80211_FEXT_NONERP_PR) == 0) { IEEE80211_DPRINTF(ni->ni_vap, IEEE80211_MSG_ASSOC, "%s: disable use of protection\n", __func__); - disable_protection(ic); + disable_protection(vap); } } } @@ -2871,20 +2919,18 @@ ieee80211_node_leave_11g(struct ieee80211_node *ni) * condition. */ static void -ieee80211_erp_timeout(struct ieee80211com *ic) +ieee80211_vap_erp_timeout(struct ieee80211vap *vap) { - IEEE80211_LOCK_ASSERT(ic); + IEEE80211_LOCK_ASSERT(vap->iv_ic); - if ((ic->ic_flags_ext & IEEE80211_FEXT_NONERP_PR) && - ieee80211_time_after(ticks, ic->ic_lastnonerp + IEEE80211_NONERP_PRESENT_AGE)) { -#if 0 - IEEE80211_NOTE(vap, IEEE80211_MSG_ASSOC, ni, + if ((vap->iv_flags_ext & IEEE80211_FEXT_NONERP_PR) && + ieee80211_time_after(ticks, vap->iv_lastnonerp + IEEE80211_NONERP_PRESENT_AGE)) { + IEEE80211_DPRINTF(vap, IEEE80211_MSG_ASSOC, "%s", "age out non-ERP sta present on channel"); -#endif - ic->ic_flags_ext &= ~IEEE80211_FEXT_NONERP_PR; - if (ic->ic_nonerpsta == 0) - disable_protection(ic); + vap->iv_flags_ext &= ~IEEE80211_FEXT_NONERP_PR; + if (vap->iv_nonerpsta == 0) + disable_protection(vap); } } @@ -2923,7 +2969,6 @@ ieee80211_node_leave(struct ieee80211_node *ni) IEEE80211_LOCK(ic); IEEE80211_AID_CLR(vap, ni->ni_associd); vap->iv_sta_assoc--; - ic->ic_sta_assoc--; if (IEEE80211_IS_CHAN_VHT(ic->ic_bsschan)) ieee80211_vht_node_leave(ni); diff --git a/sys/net80211/ieee80211_node.h b/sys/net80211/ieee80211_node.h index 3e21cdda2108..ff826d30ca72 100644 --- a/sys/net80211/ieee80211_node.h +++ b/sys/net80211/ieee80211_node.h @@ -146,6 +146,7 @@ struct ieee80211_node { #define IEEE80211_NODE_AMSDU_TX 0x080000 /* AMSDU tx enabled */ #define IEEE80211_NODE_VHT 0x100000 /* VHT enabled */ #define IEEE80211_NODE_LDPC 0x200000 /* LDPC enabled */ +#define IEEE80211_NODE_UAPSD 0x400000 /* U-APSD power save enabled */ uint16_t ni_associd; /* association ID */ uint16_t ni_vlan; /* vlan tag */ uint16_t ni_txpower; /* current transmit power */ @@ -256,6 +257,9 @@ struct ieee80211_node { uint32_t ni_quiet_ie_set; /* Quiet time IE was seen */ struct ieee80211_quiet_ie ni_quiet_ie; /* last seen quiet IE */ + /* U-APSD */ + uint8_t ni_uapsd; /* U-APSD per-node flags matching WMM STA QoS Info field */ + uint64_t ni_spare[3]; }; MALLOC_DECLARE(M_80211_NODE); @@ -475,7 +479,7 @@ int ieee80211_iterate_nodes_vap(struct ieee80211_node_table *, void ieee80211_iterate_nodes(struct ieee80211_node_table *, ieee80211_iter_func *, void *); -void ieee80211_notify_erp(struct ieee80211com *); +void ieee80211_notify_erp_locked(struct ieee80211com *); void ieee80211_dump_node(struct ieee80211_node_table *, struct ieee80211_node *); void ieee80211_dump_nodes(struct ieee80211_node_table *); diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c index 5187529029cb..dc28f0f41753 100644 --- a/sys/net80211/ieee80211_output.c +++ b/sys/net80211/ieee80211_output.c @@ -125,6 +125,11 @@ ieee80211_vap_pkt_send_dest(struct ieee80211vap *vap, struct mbuf *m, struct ieee80211com *ic = vap->iv_ic; struct ifnet *ifp = vap->iv_ifp; int mcast; + int do_ampdu = 0; + int do_amsdu = 0; + int do_ampdu_amsdu = 0; + int no_ampdu = 1; /* Will be set to 0 if ampdu is active */ + int do_ff = 0; if ((ni->ni_flags & IEEE80211_NODE_PWR_MGT) && (m->m_flags & M_PWR_SAV) == 0) { @@ -168,6 +173,27 @@ ieee80211_vap_pkt_send_dest(struct ieee80211vap *vap, struct mbuf *m, BPF_MTAP(ifp, m); /* 802.3 tx */ + + /* + * Figure out if we can do A-MPDU, A-MSDU or FF. + * + * A-MPDU depends upon vap/node config. + * A-MSDU depends upon vap/node config. + * FF depends upon vap config, IE and whether + * it's 11abg (and not 11n/11ac/etc.) + * + * Note that these flags indiciate whether we can do + * it at all, rather than the situation (eg traffic type.) + */ + do_ampdu = ((ni->ni_flags & IEEE80211_NODE_AMPDU_TX) && + (vap->iv_flags_ht & IEEE80211_FHT_AMPDU_TX)); + do_amsdu = ((ni->ni_flags & IEEE80211_NODE_AMSDU_TX) && + (vap->iv_flags_ht & IEEE80211_FHT_AMSDU_TX)); + do_ff = + ((ni->ni_flags & IEEE80211_NODE_HT) == 0) && + ((ni->ni_flags & IEEE80211_NODE_VHT) == 0) && + (IEEE80211_ATH_CAP(vap, ni, IEEE80211_NODE_FF)); + /* * Check if A-MPDU tx aggregation is setup or if we * should try to enable it. The sta must be associated @@ -185,8 +211,7 @@ ieee80211_vap_pkt_send_dest(struct ieee80211vap *vap, struct mbuf *m, * frames will always have sequence numbers allocated from the NON_QOS * TID. */ - if ((ni->ni_flags & IEEE80211_NODE_AMPDU_TX) && - (vap->iv_flags_ht & IEEE80211_FHT_AMPDU_TX)) { + if (do_ampdu) { if ((m->m_flags & M_EAPOL) == 0 && (! mcast)) { int tid = WME_AC_TO_TID(M_WME_GETAC(m)); struct ieee80211_tx_ampdu *tap = &ni->ni_tx_ampdu[tid]; @@ -207,6 +232,23 @@ ieee80211_vap_pkt_send_dest(struct ieee80211vap *vap, struct mbuf *m, ieee80211_ampdu_request(ni, tap); /* XXX hold frame for reply? */ } + /* + * Now update the no-ampdu flag. A-MPDU may have been + * started or administratively disabled above; so now we + * know whether we're running yet or not. + * + * This will let us know whether we should be doing A-MSDU + * at this point. We only do A-MSDU if we're either not + * doing A-MPDU, or A-MPDU is NACKed, or A-MPDU + A-MSDU + * is available. + * + * Whilst here, update the amsdu-ampdu flag. The above may + * have also set or cleared the amsdu-in-ampdu txa_flags + * combination so we can correctly do A-MPDU + A-MSDU. + */ + no_ampdu = (! IEEE80211_AMPDU_RUNNING(tap) + || (IEEE80211_AMPDU_NACKED(tap))); + do_ampdu_amsdu = IEEE80211_AMPDU_RUNNING_AMSDU(tap); } } @@ -221,15 +263,11 @@ ieee80211_vap_pkt_send_dest(struct ieee80211vap *vap, struct mbuf *m, * to really need to. For A-MSDU we'd have to set the * A-MSDU QoS bit in the wifi header, so we just plain * can't do it. - * - * Strictly speaking, we could actually /do/ A-MSDU / FF - * with A-MPDU together which for certain circumstances - * is beneficial (eg A-MSDU of TCK ACKs.) However, - * I'll ignore that for now so existing behaviour is maintained. - * Later on it would be good to make "amsdu + ampdu" configurable. */ - else if (__predict_true((vap->iv_caps & IEEE80211_C_8023ENCAP) == 0)) { - if ((! mcast) && ieee80211_amsdu_tx_ok(ni)) { + if (__predict_true((vap->iv_caps & IEEE80211_C_8023ENCAP) == 0)) { + if ((! mcast) && + (do_ampdu_amsdu || (no_ampdu && do_amsdu)) && + ieee80211_amsdu_tx_ok(ni)) { m = ieee80211_amsdu_check(ni, m); if (m == NULL) { /* NB: any ni ref held on stageq */ @@ -238,8 +276,7 @@ ieee80211_vap_pkt_send_dest(struct ieee80211vap *vap, struct mbuf *m, __func__); return (0); } - } else if ((! mcast) && IEEE80211_ATH_CAP(vap, ni, - IEEE80211_NODE_FF)) { + } else if ((! mcast) && do_ff) { m = ieee80211_ff_check(ni, m); if (m == NULL) { /* NB: any ni ref held on stageq */ @@ -1469,10 +1506,27 @@ ieee80211_encap(struct ieee80211vap *vap, struct ieee80211_node *ni, if (vap->iv_opmode == IEEE80211_M_STA || !IEEE80211_IS_MULTICAST(eh.ether_dhost) || (vap->iv_opmode == IEEE80211_M_WDS && - (vap->iv_flags_ext & IEEE80211_FEXT_WDSLEGACY))) + (vap->iv_flags_ext & IEEE80211_FEXT_WDSLEGACY))) { key = ieee80211_crypto_getucastkey(vap, ni); - else + } else if ((vap->iv_opmode == IEEE80211_M_WDS) && + (! (vap->iv_flags_ext & IEEE80211_FEXT_WDSLEGACY))) { + /* + * Use ucastkey for DWDS transmit nodes, multicast + * or otherwise. + * + * This is required to ensure that multicast frames + * from a DWDS AP to a DWDS STA is encrypted with + * a key that can actually work. + * + * There's no default key for multicast traffic + * on a DWDS WDS VAP node (note NOT the DWDS enabled + * AP VAP, the dynamically created per-STA WDS node) + * so encap fails and transmit fails. + */ + key = ieee80211_crypto_getucastkey(vap, ni); + } else { key = ieee80211_crypto_getmcastkey(vap, ni); + } if (key == NULL && (m->m_flags & M_EAPOL) == 0) { IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, eh.ether_dhost, @@ -2044,15 +2098,34 @@ ieee80211_add_ssid(uint8_t *frm, const uint8_t *ssid, u_int len) * Add an erp element to a frame. */ static uint8_t * -ieee80211_add_erp(uint8_t *frm, struct ieee80211com *ic) +ieee80211_add_erp(uint8_t *frm, struct ieee80211vap *vap) { + struct ieee80211com *ic = vap->iv_ic; uint8_t erp; *frm++ = IEEE80211_ELEMID_ERP; *frm++ = 1; erp = 0; - if (ic->ic_nonerpsta != 0) + + /* + * TODO: This uses the global flags for now because + * the per-VAP flags are fine for per-VAP, but don't + * take into account which VAPs share the same channel + * and which are on different channels. + * + * ERP and HT/VHT protection mode is a function of + * how many stations are on a channel, not specifically + * the VAP or global. But, until we grow that status, + * the global flag will have to do. + */ + if (ic->ic_flags_ext & IEEE80211_FEXT_NONERP_PR) erp |= IEEE80211_ERP_NON_ERP_PRESENT; + + /* + * TODO: same as above; these should be based not + * on the vap or ic flags, but instead on a combination + * of per-VAP and channels. + */ if (ic->ic_flags & IEEE80211_F_USEPROT) erp |= IEEE80211_ERP_USE_PROTECTION; if (ic->ic_flags & IEEE80211_F_USEBARKER) @@ -2100,26 +2173,48 @@ add_ie(uint8_t *frm, const uint8_t *ie) * Add a WME information element to a frame. */ uint8_t * -ieee80211_add_wme_info(uint8_t *frm, struct ieee80211_wme_state *wme) +ieee80211_add_wme_info(uint8_t *frm, struct ieee80211_wme_state *wme, + struct ieee80211_node *ni) { - static const struct ieee80211_wme_info info = { - .wme_id = IEEE80211_ELEMID_VENDOR, - .wme_len = sizeof(struct ieee80211_wme_info) - 2, - .wme_oui = { WME_OUI_BYTES }, - .wme_type = WME_OUI_TYPE, - .wme_subtype = WME_INFO_OUI_SUBTYPE, - .wme_version = WME_VERSION, - .wme_info = 0, - }; - memcpy(frm, &info, sizeof(info)); - return frm + sizeof(info); + static const uint8_t oui[4] = { WME_OUI_BYTES, WME_OUI_TYPE }; + struct ieee80211vap *vap = ni->ni_vap; + + *frm++ = IEEE80211_ELEMID_VENDOR; + *frm++ = sizeof(struct ieee80211_wme_info) - 2; + memcpy(frm, oui, sizeof(oui)); + frm += sizeof(oui); + *frm++ = WME_INFO_OUI_SUBTYPE; + *frm++ = WME_VERSION; + + /* QoS info field depends upon operating mode */ + switch (vap->iv_opmode) { + case IEEE80211_M_HOSTAP: + *frm = wme->wme_bssChanParams.cap_info; + if (vap->iv_flags_ext & IEEE80211_FEXT_UAPSD) + *frm |= WME_CAPINFO_UAPSD_EN; + frm++; + break; + case IEEE80211_M_STA: + /* + * NB: UAPSD drivers must set this up in their + * VAP creation method. + */ + *frm++ = vap->iv_uapsdinfo; + break; + default: + *frm++ = 0; + break; + } + + return frm; } /* * Add a WME parameters element to a frame. */ static uint8_t * -ieee80211_add_wme_param(uint8_t *frm, struct ieee80211_wme_state *wme) +ieee80211_add_wme_param(uint8_t *frm, struct ieee80211_wme_state *wme, + int uapsd_enable) { #define SM(_v, _f) (((_v) << _f##_S) & _f) #define ADDSHORT(frm, v) do { \ @@ -2139,8 +2234,12 @@ ieee80211_add_wme_param(uint8_t *frm, struct ieee80211_wme_state *wme) memcpy(frm, ¶m, sizeof(param)); frm += __offsetof(struct ieee80211_wme_info, wme_info); - *frm++ = wme->wme_bssChanParams.cap_info; /* AC info */ + *frm = wme->wme_bssChanParams.cap_info; /* AC info */ + if (uapsd_enable) + *frm |= WME_CAPINFO_UAPSD_EN; + frm++; *frm++ = 0; /* reserved field */ + /* XXX TODO - U-APSD bits - SP, flags below */ for (i = 0; i < WME_NUM_AC; i++) { const struct wmeParams *ac = &wme->wme_bssChanParams.cap_wmeParams[i]; @@ -2487,7 +2586,6 @@ ieee80211_send_probereq(struct ieee80211_node *ni, uint16_t ieee80211_getcapinfo(struct ieee80211vap *vap, struct ieee80211_channel *chan) { - struct ieee80211com *ic = vap->iv_ic; uint16_t capinfo; KASSERT(vap->iv_opmode != IEEE80211_M_STA, ("station mode")); @@ -2500,10 +2598,10 @@ ieee80211_getcapinfo(struct ieee80211vap *vap, struct ieee80211_channel *chan) capinfo = 0; if (vap->iv_flags & IEEE80211_F_PRIVACY) capinfo |= IEEE80211_CAPINFO_PRIVACY; - if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) && + if ((vap->iv_flags & IEEE80211_F_SHPREAMBLE) && IEEE80211_IS_CHAN_2GHZ(chan)) capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE; - if (ic->ic_flags & IEEE80211_F_SHSLOT) + if (vap->iv_flags & IEEE80211_F_SHSLOT) capinfo |= IEEE80211_CAPINFO_SHORT_SLOTTIME; if (IEEE80211_IS_CHAN_5GHZ(chan) && (vap->iv_flags & IEEE80211_F_DOTH)) capinfo |= IEEE80211_CAPINFO_SPECTRUM_MGMT; @@ -2679,7 +2777,7 @@ ieee80211_send_mgmt(struct ieee80211_node *ni, int type, int arg) * NB: Some 11a AP's reject the request when * short preamble is set. */ - if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) && + if ((vap->iv_flags & IEEE80211_F_SHPREAMBLE) && IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE; if (IEEE80211_IS_CHAN_ANYG(ic->ic_curchan) && @@ -2733,7 +2831,7 @@ ieee80211_send_mgmt(struct ieee80211_node *ni, int type, int arg) frm = ieee80211_add_wpa(frm, vap); if ((ic->ic_flags & IEEE80211_F_WME) && ni->ni_ies.wme_ie != NULL) - frm = ieee80211_add_wme_info(frm, &ic->ic_wme); + frm = ieee80211_add_wme_info(frm, &ic->ic_wme, ni); /* * Same deal - only send HT info if we're on an 11n @@ -2825,7 +2923,8 @@ ieee80211_send_mgmt(struct ieee80211_node *ni, int type, int arg) } if ((vap->iv_flags & IEEE80211_F_WME) && ni->ni_ies.wme_ie != NULL) - frm = ieee80211_add_wme_param(frm, &ic->ic_wme); + frm = ieee80211_add_wme_param(frm, &ic->ic_wme, + !! (vap->iv_flags_ext & IEEE80211_FEXT_UAPSD)); if ((ni->ni_flags & HTFLAGS) == HTFLAGS) { frm = ieee80211_add_htcap_vendor(frm, ni); frm = ieee80211_add_htinfo_vendor(frm, ni); @@ -3015,7 +3114,7 @@ ieee80211_alloc_proberesp(struct ieee80211_node *bss, int legacy) } } if (IEEE80211_IS_CHAN_ANYG(bss->ni_chan)) - frm = ieee80211_add_erp(frm, ic); + frm = ieee80211_add_erp(frm, vap); frm = ieee80211_add_xrates(frm, rs); frm = ieee80211_add_rsn(frm, vap); /* @@ -3036,7 +3135,8 @@ ieee80211_alloc_proberesp(struct ieee80211_node *bss, int legacy) } frm = ieee80211_add_wpa(frm, vap); if (vap->iv_flags & IEEE80211_F_WME) - frm = ieee80211_add_wme_param(frm, &ic->ic_wme); + frm = ieee80211_add_wme_param(frm, &ic->ic_wme, + !! (vap->iv_flags_ext & IEEE80211_FEXT_UAPSD)); if (IEEE80211_IS_CHAN_HT(bss->ni_chan) && (vap->iv_flags_ht & IEEE80211_FHT_HTCOMPAT) && legacy != IEEE80211_SEND_LEGACY_11B) { @@ -3184,6 +3284,7 @@ ieee80211_alloc_prot(struct ieee80211_node *ni, const struct mbuf *m, uint8_t rate, int prot) { struct ieee80211com *ic = ni->ni_ic; + struct ieee80211vap *vap = ni->ni_vap; const struct ieee80211_frame *wh; struct mbuf *mprot; uint16_t dur; @@ -3195,7 +3296,7 @@ ieee80211_alloc_prot(struct ieee80211_node *ni, const struct mbuf *m, wh = mtod(m, const struct ieee80211_frame *); pktlen = m->m_pkthdr.len + IEEE80211_CRC_LEN; - isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0; + isshort = (vap->iv_flags & IEEE80211_F_SHPREAMBLE) != 0; dur = ieee80211_compute_duration(ic->ic_rt, pktlen, rate, isshort) + ieee80211_ack_duration(ic->ic_rt, rate, isshort); @@ -3204,7 +3305,7 @@ ieee80211_alloc_prot(struct ieee80211_node *ni, const struct mbuf *m, dur += ieee80211_ack_duration(ic->ic_rt, rate, isshort); mprot = ieee80211_alloc_rts(ic, wh->i_addr1, wh->i_addr2, dur); } else - mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr, dur); + mprot = ieee80211_alloc_cts(ic, vap->iv_myaddr, dur); return (mprot); } @@ -3412,7 +3513,7 @@ ieee80211_beacon_construct(struct mbuf *m, uint8_t *frm, if (IEEE80211_IS_CHAN_ANYG(ni->ni_chan)) { bo->bo_erp = frm; - frm = ieee80211_add_erp(frm, ic); + frm = ieee80211_add_erp(frm, vap); } frm = ieee80211_add_xrates(frm, rs); frm = ieee80211_add_rsn(frm, vap); @@ -3434,7 +3535,8 @@ ieee80211_beacon_construct(struct mbuf *m, uint8_t *frm, frm = ieee80211_add_wpa(frm, vap); if (vap->iv_flags & IEEE80211_F_WME) { bo->bo_wme = frm; - frm = ieee80211_add_wme_param(frm, &ic->ic_wme); + frm = ieee80211_add_wme_param(frm, &ic->ic_wme, + !! (vap->iv_flags_ext & IEEE80211_FEXT_UAPSD)); } if (IEEE80211_IS_CHAN_HT(ni->ni_chan) && (vap->iv_flags_ht & IEEE80211_FHT_HTCOMPAT)) { @@ -3726,7 +3828,8 @@ ieee80211_beacon_update(struct ieee80211_node *ni, struct mbuf *m, int mcast) wme->wme_hipri_switch_hysteresis; } if (isset(bo->bo_flags, IEEE80211_BEACON_WME)) { - (void) ieee80211_add_wme_param(bo->bo_wme, wme); + (void) ieee80211_add_wme_param(bo->bo_wme, wme, + vap->iv_flags_ext & IEEE80211_FEXT_UAPSD); clrbit(bo->bo_flags, IEEE80211_BEACON_WME); } } @@ -3895,7 +3998,7 @@ ieee80211_beacon_update(struct ieee80211_node *ni, struct mbuf *m, int mcast) /* * ERP element needs updating. */ - (void) ieee80211_add_erp(bo->bo_erp, ic); + (void) ieee80211_add_erp(bo->bo_erp, vap); clrbit(bo->bo_flags, IEEE80211_BEACON_ERP); } #ifdef IEEE80211_SUPPORT_SUPERG diff --git a/sys/net80211/ieee80211_phy.h b/sys/net80211/ieee80211_phy.h index 1539e8793353..45ff6c6b6b03 100644 --- a/sys/net80211/ieee80211_phy.h +++ b/sys/net80211/ieee80211_phy.h @@ -55,11 +55,26 @@ #define IEEE80211_DUR_SHSLOT 9 /* ERP short slottime */ #define IEEE80211_DUR_OFDM_SLOT 9 /* OFDM slottime */ +/* + * For drivers that don't implement per-VAP slot time + * (ie, they rely on net80211 figuring out the union + * between VAPs to program a single radio) - return + * the current radio configured slot time. + */ #define IEEE80211_GET_SLOTTIME(ic) \ ((ic->ic_flags & IEEE80211_F_SHSLOT) ? \ IEEE80211_DUR_SHSLOT : IEEE80211_DUR_SLOT) /* + * For drivers that implement per-VAP slot time; look + * at the per-VAP flags to determine whether this VAP + * is in short or long slot time. + */ +#define IEEE80211_VAP_GET_SLOTTIME(vap) \ + ((vap->iv_flags & IEEE80211_F_SHSLOT) ? \ + IEEE80211_DUR_SHSLOT : IEEE80211_DUR_SLOT) + +/* * DIFS (microseconds). */ #define IEEE80211_DUR_DIFS(sifs, slot) ((sifs) + 2 * (slot)) diff --git a/sys/net80211/ieee80211_power.c b/sys/net80211/ieee80211_power.c index f38a5148fef2..75d2dbea92ce 100644 --- a/sys/net80211/ieee80211_power.c +++ b/sys/net80211/ieee80211_power.c @@ -335,7 +335,7 @@ ieee80211_pwrsave(struct ieee80211_node *ni, struct mbuf *m) if (psq->psq_len >= psq->psq_maxlen) { psq->psq_drops++; IEEE80211_PSQ_UNLOCK(psq); - IEEE80211_NOTE(vap, IEEE80211_MSG_ANY, ni, + IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni, "pwr save q overflow, drops %d (size %d)", psq->psq_drops, psq->psq_len); #ifdef IEEE80211_DEBUG diff --git a/sys/net80211/ieee80211_proto.c b/sys/net80211/ieee80211_proto.c index c70a159adad0..2f98deea88d9 100644 --- a/sys/net80211/ieee80211_proto.c +++ b/sys/net80211/ieee80211_proto.c @@ -244,7 +244,11 @@ static void update_promisc(void *, int); static void update_channel(void *, int); static void update_chw(void *, int); static void vap_update_wme(void *, int); +static void vap_update_slot(void *, int); static void restart_vaps(void *, int); +static void vap_update_erp_protmode(void *, int); +static void vap_update_preamble(void *, int); +static void vap_update_ht_protmode(void *, int); static void ieee80211_newstate_cb(void *, int); static int @@ -274,7 +278,7 @@ ieee80211_proto_attach(struct ieee80211com *ic) max_hdr = max_linkhdr + max_protohdr; max_datalen = MHLEN - max_hdr; } - ic->ic_protmode = IEEE80211_PROT_CTSONLY; + //ic->ic_protmode = IEEE80211_PROT_CTSONLY; TASK_INIT(&ic->ic_parent_task, 0, parent_updown, ic); TASK_INIT(&ic->ic_mcast_task, 0, update_mcast, ic); @@ -340,6 +344,10 @@ ieee80211_proto_vattach(struct ieee80211vap *vap) TASK_INIT(&vap->iv_nstate_task, 0, ieee80211_newstate_cb, vap); TASK_INIT(&vap->iv_swbmiss_task, 0, beacon_swmiss, vap); TASK_INIT(&vap->iv_wme_task, 0, vap_update_wme, vap); + TASK_INIT(&vap->iv_slot_task, 0, vap_update_slot, vap); + TASK_INIT(&vap->iv_erp_protmode_task, 0, vap_update_erp_protmode, vap); + TASK_INIT(&vap->iv_ht_protmode_task, 0, vap_update_ht_protmode, vap); + TASK_INIT(&vap->iv_preamble_task, 0, vap_update_preamble, vap); /* * Install default tx rate handling: no fixed rate, lowest * supported rate for mgmt and multicast frames. Default @@ -386,6 +394,7 @@ ieee80211_proto_vattach(struct ieee80211vap *vap) vap->iv_update_beacon = null_update_beacon; vap->iv_deliver_data = ieee80211_deliver_data; + vap->iv_protmode = IEEE80211_PROT_CTSONLY; /* attach support for operating mode */ ic->ic_vattach[vap->iv_opmode](vap); @@ -750,24 +759,57 @@ ieee80211_fix_rate(struct ieee80211_node *ni, /* * Reset 11g-related state. + * + * This is for per-VAP ERP/11g state. + * + * Eventually everything in ieee80211_reset_erp() will be + * per-VAP and in here. */ void -ieee80211_reset_erp(struct ieee80211com *ic) +ieee80211_vap_reset_erp(struct ieee80211vap *vap) { - ic->ic_flags &= ~IEEE80211_F_USEPROT; - ic->ic_nonerpsta = 0; - ic->ic_longslotsta = 0; + struct ieee80211com *ic = vap->iv_ic; + + vap->iv_nonerpsta = 0; + vap->iv_longslotsta = 0; + + vap->iv_flags &= ~IEEE80211_F_USEPROT; + /* + * Set short preamble and ERP barker-preamble flags. + */ + if (IEEE80211_IS_CHAN_A(ic->ic_curchan) || + (vap->iv_caps & IEEE80211_C_SHPREAMBLE)) { + vap->iv_flags |= IEEE80211_F_SHPREAMBLE; + vap->iv_flags &= ~IEEE80211_F_USEBARKER; + } else { + vap->iv_flags &= ~IEEE80211_F_SHPREAMBLE; + vap->iv_flags |= IEEE80211_F_USEBARKER; + } + /* * Short slot time is enabled only when operating in 11g * and not in an IBSS. We must also honor whether or not * the driver is capable of doing it. */ - ieee80211_set_shortslottime(ic, + ieee80211_vap_set_shortslottime(vap, IEEE80211_IS_CHAN_A(ic->ic_curchan) || IEEE80211_IS_CHAN_HT(ic->ic_curchan) || (IEEE80211_IS_CHAN_ANYG(ic->ic_curchan) && - ic->ic_opmode == IEEE80211_M_HOSTAP && + vap->iv_opmode == IEEE80211_M_HOSTAP && (ic->ic_caps & IEEE80211_C_SHSLOT))); +} + +/* + * Reset 11g-related state. + * + * Note this resets the global state and a caller should schedule + * a re-check of all the VAPs after setup to update said state. + */ +void +ieee80211_reset_erp(struct ieee80211com *ic) +{ +#if 0 + ic->ic_flags &= ~IEEE80211_F_USEPROT; /* * Set short preamble and ERP barker-preamble flags. */ @@ -779,21 +821,450 @@ ieee80211_reset_erp(struct ieee80211com *ic) ic->ic_flags &= ~IEEE80211_F_SHPREAMBLE; ic->ic_flags |= IEEE80211_F_USEBARKER; } +#endif + /* XXX TODO: schedule a new per-VAP ERP calculation */ +} + +/* + * Deferred slot time update. + * + * For per-VAP slot time configuration, call the VAP + * method if the VAP requires it. Otherwise, just call the + * older global method. + * + * If the per-VAP method is called then it's expected that + * the driver/firmware will take care of turning the per-VAP + * flags into slot time configuration. + * + * If the per-VAP method is not called then the global flags will be + * flipped into sync with the VAPs; ic_flags IEEE80211_F_SHSLOT will + * be set only if all of the vaps will have it set. + * + * Look at the comments for vap_update_erp_protmode() for more + * background; this assumes all VAPs are on the same channel. + */ +static void +vap_update_slot(void *arg, int npending) +{ + struct ieee80211vap *vap = arg; + struct ieee80211com *ic = vap->iv_ic; + struct ieee80211vap *iv; + int num_shslot = 0, num_lgslot = 0; + + /* + * Per-VAP path - we've already had the flags updated; + * so just notify the driver and move on. + */ + if (vap->iv_updateslot != NULL) { + vap->iv_updateslot(vap); + return; + } + + /* + * Iterate over all of the VAP flags to update the + * global flag. + * + * If all vaps have short slot enabled then flip on + * short slot. If any vap has it disabled then + * we leave it globally disabled. This should provide + * correct behaviour in a multi-BSS scenario where + * at least one VAP has short slot disabled for some + * reason. + */ + IEEE80211_LOCK(ic); + TAILQ_FOREACH(iv, &ic->ic_vaps, iv_next) { + if (iv->iv_flags & IEEE80211_F_SHSLOT) + num_shslot++; + else + num_lgslot++; + } + + /* + * It looks backwards but - if the number of short slot VAPs + * is zero then we're not short slot. Else, we have one + * or more short slot VAPs and we're checking to see if ANY + * of them have short slot disabled. + */ + if (num_shslot == 0) + ic->ic_flags &= ~IEEE80211_F_SHSLOT; + else if (num_lgslot == 0) + ic->ic_flags |= IEEE80211_F_SHSLOT; + IEEE80211_UNLOCK(ic); + + /* + * Call the driver with our new global slot time flags. + */ + if (ic->ic_updateslot != NULL) + ic->ic_updateslot(ic); +} + +/* + * Deferred ERP protmode update. + * + * This currently calculates the global ERP protection mode flag + * based on each of the VAPs. Any VAP with it enabled is enough + * for the global flag to be enabled. All VAPs with it disabled + * is enough for it to be disabled. + * + * This may make sense right now for the supported hardware where + * net80211 is controlling the single channel configuration, but + * offload firmware that's doing channel changes (eg off-channel + * TDLS, off-channel STA, off-channel P2P STA/AP) may get some + * silly looking flag updates. + * + * Ideally the protection mode calculation is done based on the + * channel, and all VAPs using that channel will inherit it. + * But until that's what net80211 does, this wil have to do. + */ +static void +vap_update_erp_protmode(void *arg, int npending) +{ + struct ieee80211vap *vap = arg; + struct ieee80211com *ic = vap->iv_ic; + struct ieee80211vap *iv; + int enable_protmode = 0; + int non_erp_present = 0; + + /* + * Iterate over all of the VAPs to calculate the overlapping + * ERP protection mode configuration and ERP present math. + * + * For now we assume that if a driver can handle this per-VAP + * then it'll ignore the ic->ic_protmode variant and instead + * will look at the vap related flags. + */ + IEEE80211_LOCK(ic); + TAILQ_FOREACH(iv, &ic->ic_vaps, iv_next) { + if (iv->iv_flags & IEEE80211_F_USEPROT) + enable_protmode = 1; + if (iv->iv_flags_ext & IEEE80211_FEXT_NONERP_PR) + non_erp_present = 1; + } + + if (enable_protmode) + ic->ic_flags |= IEEE80211_F_USEPROT; + else + ic->ic_flags &= ~IEEE80211_F_USEPROT; + + if (non_erp_present) + ic->ic_flags_ext |= IEEE80211_FEXT_NONERP_PR; + else + ic->ic_flags_ext &= ~IEEE80211_FEXT_NONERP_PR; + + /* Beacon update on all VAPs */ + ieee80211_notify_erp_locked(ic); + + IEEE80211_UNLOCK(ic); + + IEEE80211_DPRINTF(vap, IEEE80211_MSG_DEBUG, + "%s: called; enable_protmode=%d, non_erp_present=%d\n", + __func__, enable_protmode, non_erp_present); + + /* + * Now that the global configuration flags are calculated, + * notify the VAP about its configuration. + * + * The global flags will be used when assembling ERP IEs + * for multi-VAP operation, even if it's on a different + * channel. Yes, that's going to need fixing in the + * future. + */ + if (vap->iv_erp_protmode_update != NULL) + vap->iv_erp_protmode_update(vap); +} + +/* + * Deferred ERP short preamble/barker update. + * + * All VAPs need to use short preamble for it to be globally + * enabled or not. + * + * Look at the comments for vap_update_erp_protmode() for more + * background; this assumes all VAPs are on the same channel. + */ +static void +vap_update_preamble(void *arg, int npending) +{ + struct ieee80211vap *vap = arg; + struct ieee80211com *ic = vap->iv_ic; + struct ieee80211vap *iv; + int barker_count = 0, short_preamble_count = 0, count = 0; + + /* + * Iterate over all of the VAPs to calculate the overlapping + * short or long preamble configuration. + * + * For now we assume that if a driver can handle this per-VAP + * then it'll ignore the ic->ic_flags variant and instead + * will look at the vap related flags. + */ + IEEE80211_LOCK(ic); + TAILQ_FOREACH(iv, &ic->ic_vaps, iv_next) { + if (iv->iv_flags & IEEE80211_F_USEBARKER) + barker_count++; + if (iv->iv_flags & IEEE80211_F_SHPREAMBLE) + short_preamble_count++; + count++; + } + + /* + * As with vap_update_erp_protmode(), the global flags are + * currently used for beacon IEs. + */ + IEEE80211_DPRINTF(vap, IEEE80211_MSG_DEBUG, + "%s: called; barker_count=%d, short_preamble_count=%d\n", + __func__, barker_count, short_preamble_count); + + /* + * Only flip on short preamble if all of the VAPs support + * it. + */ + if (barker_count == 0 && short_preamble_count == count) { + ic->ic_flags |= IEEE80211_F_SHPREAMBLE; + ic->ic_flags &= ~IEEE80211_F_USEBARKER; + } else { + ic->ic_flags &= ~IEEE80211_F_SHPREAMBLE; + ic->ic_flags |= IEEE80211_F_USEBARKER; + } + IEEE80211_DPRINTF(vap, IEEE80211_MSG_DEBUG, + "%s: global barker=%d preamble=%d\n", + __func__, + !! (ic->ic_flags & IEEE80211_F_USEBARKER), + !! (ic->ic_flags & IEEE80211_F_SHPREAMBLE)); + + /* Beacon update on all VAPs */ + ieee80211_notify_erp_locked(ic); + + IEEE80211_UNLOCK(ic); + + /* Driver notification */ + if (vap->iv_erp_protmode_update != NULL) + vap->iv_preamble_update(vap); +} + +/* + * Deferred HT protmode update and beacon update. + * + * Look at the comments for vap_update_erp_protmode() for more + * background; this assumes all VAPs are on the same channel. + */ +static void +vap_update_ht_protmode(void *arg, int npending) +{ + struct ieee80211vap *vap = arg; + struct ieee80211vap *iv; + struct ieee80211com *ic = vap->iv_ic; + int num_vaps = 0, num_pure = 0, num_mixed = 0; + int num_optional = 0, num_ht2040 = 0, num_nonht = 0; + int num_ht_sta = 0, num_ht40_sta = 0, num_sta = 0; + int num_nonhtpr = 0; + + /* + * Iterate over all of the VAPs to calculate everything. + * + * There are a few different flags to calculate: + * + * + whether there's HT only or HT+legacy stations; + * + whether there's HT20, HT40, or HT20+HT40 stations; + * + whether the desired protection mode is mixed, pure or + * one of the two above. + * + * For now we assume that if a driver can handle this per-VAP + * then it'll ignore the ic->ic_htprotmode / ic->ic_curhtprotmode + * variant and instead will look at the vap related variables. + * + * XXX TODO: non-greenfield STAs present (IEEE80211_HTINFO_NONGF_PRESENT) ! + */ + + IEEE80211_LOCK(ic); + TAILQ_FOREACH(iv, &ic->ic_vaps, iv_next) { + num_vaps++; + /* overlapping BSSes advertising non-HT status present */ + if (iv->iv_flags_ht & IEEE80211_FHT_NONHT_PR) + num_nonht++; + /* Operating mode flags */ + if (iv->iv_curhtprotmode & IEEE80211_HTINFO_NONHT_PRESENT) + num_nonhtpr++; + switch (iv->iv_curhtprotmode & IEEE80211_HTINFO_OPMODE) { + case IEEE80211_HTINFO_OPMODE_PURE: + num_pure++; + break; + case IEEE80211_HTINFO_OPMODE_PROTOPT: + num_optional++; + break; + case IEEE80211_HTINFO_OPMODE_HT20PR: + num_ht2040++; + break; + case IEEE80211_HTINFO_OPMODE_MIXED: + num_mixed++; + break; + } + + IEEE80211_DPRINTF(vap, IEEE80211_MSG_11N, + "%s: vap %s: nonht_pr=%d, curhtprotmode=0x%02x\n", + __func__, + ieee80211_get_vap_ifname(iv), + !! (iv->iv_flags_ht & IEEE80211_FHT_NONHT_PR), + iv->iv_curhtprotmode); + + num_ht_sta += iv->iv_ht_sta_assoc; + num_ht40_sta += iv->iv_ht40_sta_assoc; + num_sta += iv->iv_sta_assoc; + } + + /* + * Step 1 - if any VAPs indicate NONHT_PR set (overlapping BSS + * non-HT present), set it here. This shouldn't be used by + * anything but the old overlapping BSS logic so if any drivers + * consume it, it's up to date. + */ + if (num_nonht > 0) + ic->ic_flags_ht |= IEEE80211_FHT_NONHT_PR; + else + ic->ic_flags_ht &= ~IEEE80211_FHT_NONHT_PR; + + /* + * Step 2 - default HT protection mode to MIXED (802.11-2016 10.26.3.1.) + * + * + If all VAPs are PURE, we can stay PURE. + * + If all VAPs are PROTOPT, we can go to PROTOPT. + * + If any VAP has HT20PR then it sees at least a HT40+HT20 station. + * Note that we may have a VAP with one HT20 and a VAP with one HT40; + * So we look at the sum ht and sum ht40 sta counts; if we have a + * HT station and the HT20 != HT40 count, we have to do HT20PR here. + * Note all stations need to be HT for this to be an option. + * + The fall-through is MIXED, because it means we have some odd + * non HT40-involved combination of opmode and this is the most + * sensible default. + */ + ic->ic_curhtprotmode = IEEE80211_HTINFO_OPMODE_MIXED; + + if (num_pure == num_vaps) + ic->ic_curhtprotmode = IEEE80211_HTINFO_OPMODE_PURE; + + if (num_optional == num_vaps) + ic->ic_curhtprotmode = IEEE80211_HTINFO_OPMODE_PROTOPT; + + /* + * Note: we need /a/ HT40 station somewhere for this to + * be a possibility. + */ + if ((num_ht2040 > 0) || + ((num_ht_sta > 0) && (num_ht40_sta > 0) && + (num_ht_sta != num_ht40_sta))) + ic->ic_curhtprotmode = IEEE80211_HTINFO_OPMODE_HT20PR; + + /* + * Step 3 - if any of the stations across the VAPs are + * non-HT then this needs to be flipped back to MIXED. + */ + if (num_ht_sta != num_sta) + ic->ic_curhtprotmode = IEEE80211_HTINFO_OPMODE_MIXED; + + /* + * Step 4 - If we see any overlapping BSS non-HT stations + * via beacons then flip on NONHT_PRESENT. + */ + if (num_nonhtpr > 0) + ic->ic_curhtprotmode |= IEEE80211_HTINFO_NONHT_PRESENT; + + /* Notify all VAPs to potentially update their beacons */ + TAILQ_FOREACH(iv, &ic->ic_vaps, iv_next) + ieee80211_htinfo_notify(iv); + + IEEE80211_UNLOCK(ic); + + IEEE80211_DPRINTF(vap, IEEE80211_MSG_11N, + "%s: global: nonht_pr=%d ht_opmode=0x%02x\n", + __func__, + !! (ic->ic_flags_ht & IEEE80211_FHT_NONHT_PR), + ic->ic_curhtprotmode); + + /* Driver update */ + if (vap->iv_erp_protmode_update != NULL) + vap->iv_ht_protmode_update(vap); } /* * Set the short slot time state and notify the driver. + * + * This is the per-VAP slot time state. */ void -ieee80211_set_shortslottime(struct ieee80211com *ic, int onoff) +ieee80211_vap_set_shortslottime(struct ieee80211vap *vap, int onoff) { + struct ieee80211com *ic = vap->iv_ic; + + /* XXX lock? */ + + /* + * Only modify the per-VAP slot time. + */ if (onoff) - ic->ic_flags |= IEEE80211_F_SHSLOT; + vap->iv_flags |= IEEE80211_F_SHSLOT; else - ic->ic_flags &= ~IEEE80211_F_SHSLOT; - /* notify driver */ - if (ic->ic_updateslot != NULL) - ic->ic_updateslot(ic); + vap->iv_flags &= ~IEEE80211_F_SHSLOT; + + IEEE80211_DPRINTF(vap, IEEE80211_MSG_DEBUG, + "%s: called; onoff=%d\n", __func__, onoff); + /* schedule the deferred slot flag update and update */ + ieee80211_runtask(ic, &vap->iv_slot_task); +} + +/* + * Update the VAP short /long / barker preamble state and + * update beacon state if needed. + * + * For now it simply copies the global flags into the per-vap + * flags and schedules the callback. Later this will support + * both global and per-VAP flags, especially useful for + * and STA+STA multi-channel operation (eg p2p). + */ +void +ieee80211_vap_update_preamble(struct ieee80211vap *vap) +{ + struct ieee80211com *ic = vap->iv_ic; + + /* XXX lock? */ + + IEEE80211_DPRINTF(vap, IEEE80211_MSG_DEBUG, + "%s: called\n", __func__); + /* schedule the deferred slot flag update and update */ + ieee80211_runtask(ic, &vap->iv_preamble_task); +} + +/* + * Update the VAP 11g protection mode and update beacon state + * if needed. + */ +void +ieee80211_vap_update_erp_protmode(struct ieee80211vap *vap) +{ + struct ieee80211com *ic = vap->iv_ic; + + /* XXX lock? */ + + IEEE80211_DPRINTF(vap, IEEE80211_MSG_DEBUG, + "%s: called\n", __func__); + /* schedule the deferred slot flag update and update */ + ieee80211_runtask(ic, &vap->iv_erp_protmode_task); +} + +/* + * Update the VAP 11n protection mode and update beacon state + * if needed. + */ +void +ieee80211_vap_update_ht_protmode(struct ieee80211vap *vap) +{ + struct ieee80211com *ic = vap->iv_ic; + + /* XXX lock? */ + + IEEE80211_DPRINTF(vap, IEEE80211_MSG_DEBUG, + "%s: called\n", __func__); + /* schedule the deferred protmode update */ + ieee80211_runtask(ic, &vap->iv_ht_protmode_task); } /* @@ -1053,8 +1524,11 @@ ieee80211_wme_initparams_locked(struct ieee80211vap *vap) * field and updates hardware when said field changes. * Otherwise the hardware is programmed with defaults, not what * the beacon actually announces. + * + * Note that we can't ever have 0xff as an actual value; + * the only valid values are 0..15. */ - wme->wme_wmeChanParams.cap_info = 0; + wme->wme_wmeChanParams.cap_info = 0xfe; /* * Select mode; we can be called early in which case we @@ -1247,7 +1721,7 @@ ieee80211_wme_updateparams_locked(struct ieee80211vap *vap) * further. */ if (vap->iv_opmode == IEEE80211_M_HOSTAP && - ic->ic_sta_assoc < 2 && (wme->wme_flags & WME_F_AGGRMODE) != 0) { + vap->iv_sta_assoc < 2 && (wme->wme_flags & WME_F_AGGRMODE) != 0) { static const uint8_t logCwMin[IEEE80211_MODE_MAX] = { [IEEE80211_MODE_AUTO] = 3, [IEEE80211_MODE_11A] = 3, @@ -1273,22 +1747,6 @@ ieee80211_wme_updateparams_locked(struct ieee80211vap *vap) ieee80211_wme_acnames[WME_AC_BE], chanp->wmep_logcwmin); } - /* - * Arrange for the beacon update. - * - * XXX what about MBSS, WDS? - */ - if (vap->iv_opmode == IEEE80211_M_HOSTAP - || vap->iv_opmode == IEEE80211_M_IBSS) { - /* - * Arrange for a beacon update and bump the parameter - * set number so associated stations load the new values. - */ - wme->wme_bssChanParams.cap_info = - (wme->wme_bssChanParams.cap_info+1) & WME_QOSINFO_COUNT; - ieee80211_beacon_notify(vap, IEEE80211_BEACON_WME); - } - /* schedule the deferred WME update */ ieee80211_runtask(ic, &vap->iv_wme_task); @@ -1402,7 +1860,7 @@ update_chw(void *arg, int npending) } /* - * Deferred WME update. + * Deferred WME parameter and beacon update. * * In preparation for per-VAP WME configuration, call the VAP * method if the VAP requires it. Otherwise, just call the @@ -1414,12 +1872,32 @@ vap_update_wme(void *arg, int npending) { struct ieee80211vap *vap = arg; struct ieee80211com *ic = vap->iv_ic; + struct ieee80211_wme_state *wme = &ic->ic_wme; + /* Driver update */ if (vap->iv_wme_update != NULL) vap->iv_wme_update(vap, ic->ic_wme.wme_chanParams.cap_wmeParams); else ic->ic_wme.wme_update(ic); + + IEEE80211_LOCK(ic); + /* + * Arrange for the beacon update. + * + * XXX what about MBSS, WDS? + */ + if (vap->iv_opmode == IEEE80211_M_HOSTAP + || vap->iv_opmode == IEEE80211_M_IBSS) { + /* + * Arrange for a beacon update and bump the parameter + * set number so associated stations load the new values. + */ + wme->wme_bssChanParams.cap_info = + (wme->wme_bssChanParams.cap_info+1) & WME_QOSINFO_COUNT; + ieee80211_beacon_notify(vap, IEEE80211_BEACON_WME); + } + IEEE80211_UNLOCK(ic); } static void diff --git a/sys/net80211/ieee80211_proto.h b/sys/net80211/ieee80211_proto.h index 9d224b1f5c18..fafedf46cab5 100644 --- a/sys/net80211/ieee80211_proto.h +++ b/sys/net80211/ieee80211_proto.h @@ -152,10 +152,12 @@ uint8_t *ieee80211_add_qos(uint8_t *, const struct ieee80211_node *); uint16_t ieee80211_getcapinfo(struct ieee80211vap *, struct ieee80211_channel *); struct ieee80211_wme_state; -uint8_t * ieee80211_add_wme_info(uint8_t *frm, struct ieee80211_wme_state *wme); +uint8_t * ieee80211_add_wme_info(uint8_t *frm, struct ieee80211_wme_state *wme, + struct ieee80211_node *ni); +void ieee80211_vap_reset_erp(struct ieee80211vap *); void ieee80211_reset_erp(struct ieee80211com *); -void ieee80211_set_shortslottime(struct ieee80211com *, int onoff); +void ieee80211_vap_set_shortslottime(struct ieee80211vap *, int onoff); int ieee80211_iserp_rateset(const struct ieee80211_rateset *); void ieee80211_setbasicrates(struct ieee80211_rateset *, enum ieee80211_phymode); @@ -284,7 +286,7 @@ struct ieee80211_wme_state { u_int wme_hipri_switch_thresh;/* aggressive mode switch thresh */ u_int wme_hipri_switch_hysteresis;/* aggressive mode switch hysteresis */ - struct wmeParams wme_params[4]; /* from assoc resp for each AC*/ + struct wmeParams wme_params[WME_NUM_AC]; /* from assoc resp for each AC */ struct chanAccParams wme_wmeChanParams; /* WME params applied to self */ struct chanAccParams wme_wmeBssChanParams;/* WME params bcast to stations */ struct chanAccParams wme_chanParams; /* params applied to self */ @@ -301,6 +303,9 @@ void ieee80211_wme_vap_getparams(struct ieee80211vap *vap, void ieee80211_wme_ic_getparams(struct ieee80211com *ic, struct chanAccParams *); int ieee80211_wme_vap_ac_is_noack(struct ieee80211vap *vap, int ac); +void ieee80211_vap_update_preamble(struct ieee80211vap *vap); +void ieee80211_vap_update_erp_protmode(struct ieee80211vap *vap); +void ieee80211_vap_update_ht_protmode(struct ieee80211vap *vap); /* * Return pointer to the QoS field from a Qos frame. diff --git a/sys/net80211/ieee80211_regdomain.c b/sys/net80211/ieee80211_regdomain.c index b3c0302a5645..095d7941bb15 100644 --- a/sys/net80211/ieee80211_regdomain.c +++ b/sys/net80211/ieee80211_regdomain.c @@ -118,10 +118,11 @@ ieee80211_init_channels(struct ieee80211com *ic, { struct ieee80211_channel *chans = ic->ic_channels; int *nchans = &ic->ic_nchans; - int ht40; + int cbw_flags; /* XXX just do something for now */ - ht40 = !!(ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40); + cbw_flags = (ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40) ? + NET80211_CBW_FLAG_HT40 : 0; *nchans = 0; if (isset(bands, IEEE80211_MODE_11B) || isset(bands, IEEE80211_MODE_11G) || @@ -131,19 +132,40 @@ ieee80211_init_channels(struct ieee80211com *ic, nchan -= 3; ieee80211_add_channel_list_2ghz(chans, IEEE80211_CHAN_MAX, - nchans, def_chan_2ghz, nchan, bands, ht40); + nchans, def_chan_2ghz, nchan, bands, cbw_flags); } + /* XXX IEEE80211_MODE_VHT_2GHZ if we really want to. */ + if (isset(bands, IEEE80211_MODE_11A) || isset(bands, IEEE80211_MODE_11NA)) { ieee80211_add_channel_list_5ghz(chans, IEEE80211_CHAN_MAX, nchans, def_chan_5ghz_band1, nitems(def_chan_5ghz_band1), - bands, ht40); + bands, cbw_flags); + ieee80211_add_channel_list_5ghz(chans, IEEE80211_CHAN_MAX, + nchans, def_chan_5ghz_band2, nitems(def_chan_5ghz_band2), + bands, cbw_flags); + ieee80211_add_channel_list_5ghz(chans, IEEE80211_CHAN_MAX, + nchans, def_chan_5ghz_band3, nitems(def_chan_5ghz_band3), + bands, cbw_flags); + } + if (isset(bands, IEEE80211_MODE_VHT_5GHZ)) { + cbw_flags |= NET80211_CBW_FLAG_HT40; /* Make sure this is set; or assert? */ + cbw_flags |= NET80211_CBW_FLAG_VHT80; +#define MS(_v, _f) (((_v) & _f) >> _f##_S) + if (MS(ic->ic_vhtcaps, IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK) >= 1) + cbw_flags |= NET80211_CBW_FLAG_VHT160; + if (MS(ic->ic_vhtcaps, IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK) == 2) + cbw_flags |= NET80211_CBW_FLAG_VHT80P80; +#undef MS + ieee80211_add_channel_list_5ghz(chans, IEEE80211_CHAN_MAX, + nchans, def_chan_5ghz_band1, nitems(def_chan_5ghz_band1), + bands, cbw_flags); ieee80211_add_channel_list_5ghz(chans, IEEE80211_CHAN_MAX, nchans, def_chan_5ghz_band2, nitems(def_chan_5ghz_band2), - bands, ht40); + bands, cbw_flags); ieee80211_add_channel_list_5ghz(chans, IEEE80211_CHAN_MAX, nchans, def_chan_5ghz_band3, nitems(def_chan_5ghz_band3), - bands, ht40); + bands, cbw_flags); } if (rd != NULL) ic->ic_regdomain = *rd; diff --git a/sys/net80211/ieee80211_scan_sta.c b/sys/net80211/ieee80211_scan_sta.c index ecfdcd03c7c4..ea75504a7235 100644 --- a/sys/net80211/ieee80211_scan_sta.c +++ b/sys/net80211/ieee80211_scan_sta.c @@ -1276,6 +1276,8 @@ sta_pick_bss(struct ieee80211_scan_state *ss, struct ieee80211vap *vap) * handle notification that this has completed. */ ss->ss_flags &= ~IEEE80211_SCAN_NOPICK; + IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, + "%s: nopick; return 1\n", __func__); return 1; } /* @@ -1285,7 +1287,9 @@ sta_pick_bss(struct ieee80211_scan_state *ss, struct ieee80211vap *vap) /* NB: unlocked read should be ok */ if (TAILQ_FIRST(&st->st_entry) == NULL) { IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, - "%s: no scan candidate\n", __func__); + "%s: no scan candidate, join=%d, return 0\n", + __func__, + !! (ss->ss_flags & IEEE80211_SCAN_NOJOIN)); if (ss->ss_flags & IEEE80211_SCAN_NOJOIN) return 0; notfound: @@ -1310,6 +1314,8 @@ notfound: chan = demote11b(vap, chan); if (!ieee80211_sta_join(vap, chan, &selbs->base)) goto notfound; + IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, + "%s: terminate scan; return 1\n", __func__); return 1; /* terminate scan */ } diff --git a/sys/net80211/ieee80211_scan_sw.c b/sys/net80211/ieee80211_scan_sw.c index 33e28868f97d..4fcd26db61b1 100644 --- a/sys/net80211/ieee80211_scan_sw.c +++ b/sys/net80211/ieee80211_scan_sw.c @@ -298,6 +298,11 @@ ieee80211_swscan_check_scan(const struct ieee80211_scanner *scan, * use. Also discard any frames that might come * in while temporarily marked as scanning. */ + IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, + "cache hot; ic_lastscan=%d, scanvalid=%d, ticks=%d\n", + ic->ic_lastscan, + vap->iv_scanvalid, + ticks); SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_DISCARD; ic->ic_flags |= IEEE80211_F_SCAN; @@ -307,6 +312,8 @@ ieee80211_swscan_check_scan(const struct ieee80211_scanner *scan, ic->ic_flags &= ~IEEE80211_F_SCAN; SCAN_PRIVATE(ss)->ss_iflags &= ~ISCAN_DISCARD; + IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, + "%s: scan_end returned %d\n", __func__, result); if (result) { ieee80211_notify_scan_done(vap); return 1; @@ -675,19 +682,32 @@ scan_curchan_task(void *arg, int pending) struct ieee80211com *ic = ss->ss_ic; struct ieee80211_channel *chan; unsigned long maxdwell; - int scandone; + int scandone, scanstop; IEEE80211_LOCK(ic); end: + /* + * Note: only /end/ the scan if we're CANCEL rather than + * CANCEL+INTERRUPT (ie, 'PAUSE'). + * + * We can stop the scan if we hit cancel, but we shouldn't + * call scan_end(ss, 1) if we're just PAUSEing the scan. + */ scandone = (ss->ss_next >= ss->ss_last) || - (ss_priv->ss_iflags & ISCAN_CANCEL) != 0; + ((ss_priv->ss_iflags & ISCAN_PAUSE) == ISCAN_CANCEL); + scanstop = (ss->ss_next >= ss->ss_last) || + ((ss_priv->ss_iflags & ISCAN_CANCEL) != 0); IEEE80211_DPRINTF(ss->ss_vap, IEEE80211_MSG_SCAN, - "%s: loop start; scandone=%d\n", + "%s: loop start; scandone=%d, scanstop=%d, ss_iflags=0x%x, ss_next=%u, ss_last=%u\n", __func__, - scandone); + scandone, + scanstop, + (uint32_t) ss_priv->ss_iflags, + (uint32_t) ss->ss_next, + (uint32_t) ss->ss_last); - if (scandone || (ss->ss_flags & IEEE80211_SCAN_GOTPICK) || + if (scanstop || (ss->ss_flags & IEEE80211_SCAN_GOTPICK) || (ss_priv->ss_iflags & ISCAN_ABORT) || ieee80211_time_after(ticks + ss->ss_mindwell, ss_priv->ss_scanend)) { ss_priv->ss_iflags &= ~ISCAN_RUNNING; @@ -787,11 +807,12 @@ scan_end(struct ieee80211_scan_state *ss, int scandone) * Since a cancellation may have occurred during one of the * driver calls (whilst unlocked), update scandone. */ - if (scandone == 0 && (ss_priv->ss_iflags & ISCAN_CANCEL) != 0) { + if ((scandone == 0) && ((ss_priv->ss_iflags & ISCAN_PAUSE) == ISCAN_CANCEL)) { /* XXX printf? */ if_printf(vap->iv_ifp, - "%s: OOPS! scan cancelled during driver call (1)!\n", - __func__); + "%s: OOPS! scan cancelled during driver call (1) (ss_iflags=0x%x)!\n", + __func__, + ss_priv->ss_iflags); scandone = 1; } @@ -856,11 +877,12 @@ scan_end(struct ieee80211_scan_state *ss, int scandone) * Since a cancellation may have occurred during one of the * driver calls (whilst unlocked), update scandone. */ - if (scandone == 0 && (ss_priv->ss_iflags & ISCAN_CANCEL) != 0) { + if (scandone == 0 && (ss_priv->ss_iflags & ISCAN_PAUSE) == ISCAN_CANCEL) { /* XXX printf? */ if_printf(vap->iv_ifp, - "%s: OOPS! scan cancelled during driver call (2)!\n", - __func__); + "%s: OOPS! scan cancelled during driver call (2) (ss_iflags=0x%x)!\n", + __func__, + ss_priv->ss_iflags); scandone = 1; } @@ -900,11 +922,18 @@ scan_done(struct ieee80211_scan_state *ss, int scandone) */ if ((vap->iv_flags_ext & IEEE80211_FEXT_SCAN_OFFLOAD) == 0) vap->iv_sta_ps(vap, 0); - if (ss->ss_next >= ss->ss_last) + if (ss->ss_next >= ss->ss_last) { + IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, + "%s: Dropping out of scan; ss_next=%u, ss_last=%u\n", + __func__, + (uint32_t) ss->ss_next, + (uint32_t) ss->ss_last); ic->ic_flags_ext &= ~IEEE80211_FEXT_BGSCAN; + } /* send 'scan done' event if not interrupted due to traffic. */ - if (!(ss_priv->ss_iflags & ISCAN_INTERRUPT)) + if (!(ss_priv->ss_iflags & ISCAN_INTERRUPT) || + (ss->ss_next >= ss->ss_last)) ieee80211_notify_scan_done(vap); } ss_priv->ss_iflags &= ~(ISCAN_PAUSE | ISCAN_ABORT); diff --git a/sys/net80211/ieee80211_sta.c b/sys/net80211/ieee80211_sta.c index 46ba73a9ecd8..f852c4b88b58 100644 --- a/sys/net80211/ieee80211_sta.c +++ b/sys/net80211/ieee80211_sta.c @@ -1129,25 +1129,56 @@ bad: IEEE80211_SCAN_FAIL_STATUS); } +/* + * Parse the WME IE for QoS and U-APSD information. + * + * Returns -1 if the IE isn't found, 1 if it's found. + */ +int +ieee80211_parse_wmeie(uint8_t *frm, const struct ieee80211_frame *wh, + struct ieee80211_node *ni) +{ + u_int len = frm[1]; + + ni->ni_uapsd = 0; + + if (len < sizeof(struct ieee80211_wme_param)-2) { + IEEE80211_DISCARD_IE(ni->ni_vap, + IEEE80211_MSG_ELEMID | IEEE80211_MSG_WME, + wh, "WME", "too short, len %u", len); + return -1; + } + + ni->ni_uapsd = frm[WME_CAPINFO_IE_OFFSET]; + + IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_POWER | IEEE80211_MSG_ASSOC, + ni, "U-APSD settings from STA: 0x%02x", ni->ni_uapsd); + + return 1; +} + int ieee80211_parse_wmeparams(struct ieee80211vap *vap, uint8_t *frm, - const struct ieee80211_frame *wh) + const struct ieee80211_frame *wh, uint8_t *qosinfo) { #define MS(_v, _f) (((_v) & _f) >> _f##_S) struct ieee80211_wme_state *wme = &vap->iv_ic->ic_wme; - u_int len = frm[1], qosinfo; + u_int len = frm[1], qosinfo_count; int i; + *qosinfo = 0; + if (len < sizeof(struct ieee80211_wme_param)-2) { IEEE80211_DISCARD_IE(vap, IEEE80211_MSG_ELEMID | IEEE80211_MSG_WME, wh, "WME", "too short, len %u", len); return -1; } - qosinfo = frm[__offsetof(struct ieee80211_wme_param, param_qosInfo)]; - qosinfo &= WME_QOSINFO_COUNT; + *qosinfo = frm[__offsetof(struct ieee80211_wme_param, param_qosInfo)]; + qosinfo_count = *qosinfo & WME_QOSINFO_COUNT; + /* XXX do proper check for wraparound */ - if (qosinfo == wme->wme_wmeChanParams.cap_info) + if (qosinfo_count == wme->wme_wmeChanParams.cap_info) return 0; frm += __offsetof(struct ieee80211_wme_param, params_acParams); for (i = 0; i < WME_NUM_AC; i++) { @@ -1159,9 +1190,18 @@ ieee80211_parse_wmeparams(struct ieee80211vap *vap, uint8_t *frm, wmep->wmep_logcwmin = MS(frm[1], WME_PARAM_LOGCWMIN); wmep->wmep_logcwmax = MS(frm[1], WME_PARAM_LOGCWMAX); wmep->wmep_txopLimit = le16dec(frm+2); + IEEE80211_DPRINTF(vap, IEEE80211_MSG_WME, + "%s: WME: %d: acm=%d aifsn=%d logcwmin=%d logcwmax=%d txopLimit=%d\n", + __func__, + i, + wmep->wmep_acm, + wmep->wmep_aifsn, + wmep->wmep_logcwmin, + wmep->wmep_logcwmax, + wmep->wmep_txopLimit); frm += 4; } - wme->wme_wmeChanParams.cap_info = qosinfo; + wme->wme_wmeChanParams.cap_info = qosinfo_count; return 1; #undef MS } @@ -1350,11 +1390,12 @@ sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, int subtype, struct ieee80211com *ic = ni->ni_ic; struct ieee80211_channel *rxchan = ic->ic_curchan; struct ieee80211_frame *wh; + int ht_state_change = 0, do_ht = 0; uint8_t *frm, *efrm; uint8_t *rates, *xrates, *wme, *htcap, *htinfo; uint8_t *vhtcap, *vhtopmode; uint8_t rate; - int ht_state_change = 0, do_ht = 0; + uint8_t qosinfo; wh = mtod(m0, struct ieee80211_frame *); frm = (uint8_t *)&wh[1]; @@ -1419,12 +1460,13 @@ sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, int subtype, ni->ni_erp, scan.erp); if (IEEE80211_IS_CHAN_ANYG(ic->ic_curchan) && (ni->ni_erp & IEEE80211_ERP_USE_PROTECTION)) - ic->ic_flags |= IEEE80211_F_USEPROT; + vap->iv_flags |= IEEE80211_F_USEPROT; else - ic->ic_flags &= ~IEEE80211_F_USEPROT; + vap->iv_flags &= ~IEEE80211_F_USEPROT; ni->ni_erp = scan.erp; /* XXX statistic */ - /* XXX driver notification */ + /* driver notification */ + ieee80211_vap_update_erp_protmode(vap); } if ((ni->ni_capinfo ^ scan.capinfo) & IEEE80211_CAPINFO_SHORT_SLOTTIME) { IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_ASSOC, @@ -1435,7 +1477,7 @@ sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, int subtype, * NB: we assume short preamble doesn't * change dynamically */ - ieee80211_set_shortslottime(ic, + ieee80211_vap_set_shortslottime(vap, IEEE80211_IS_CHAN_A(ic->ic_bsschan) || (scan.capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME)); ni->ni_capinfo = (ni->ni_capinfo &~ IEEE80211_CAPINFO_SHORT_SLOTTIME) @@ -1443,9 +1485,18 @@ sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, int subtype, /* XXX statistic */ } if (scan.wme != NULL && - (ni->ni_flags & IEEE80211_NODE_QOS) && - ieee80211_parse_wmeparams(vap, scan.wme, wh) > 0) - ieee80211_wme_updateparams(vap); + (ni->ni_flags & IEEE80211_NODE_QOS)) { + int _retval; + if ((_retval = ieee80211_parse_wmeparams(vap, + scan.wme, wh, &qosinfo)) >= 0) { + if (qosinfo & WME_CAPINFO_UAPSD_EN) + ni->ni_flags |= + IEEE80211_NODE_UAPSD; + if (_retval > 0) + ieee80211_wme_updateparams(vap); + } + } else + ni->ni_flags &= ~IEEE80211_NODE_UAPSD; #ifdef IEEE80211_SUPPORT_SUPERG if (scan.ath != NULL) ieee80211_parse_athparams(ni, scan.ath, wh); @@ -1782,7 +1833,7 @@ sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, int subtype, if (ni->ni_jointime == 0) ni->ni_jointime = time_uptime; if (wme != NULL && - ieee80211_parse_wmeparams(vap, wme, wh) >= 0) { + ieee80211_parse_wmeparams(vap, wme, wh, &qosinfo) >= 0) { ni->ni_flags |= IEEE80211_NODE_QOS; ieee80211_wme_updateparams(vap); } else @@ -1841,15 +1892,16 @@ sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, int subtype, */ if (IEEE80211_IS_CHAN_A(ic->ic_curchan) || (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE)) { - ic->ic_flags |= IEEE80211_F_SHPREAMBLE; - ic->ic_flags &= ~IEEE80211_F_USEBARKER; + vap->iv_flags |= IEEE80211_F_SHPREAMBLE; + vap->iv_flags &= ~IEEE80211_F_USEBARKER; } else { - ic->ic_flags &= ~IEEE80211_F_SHPREAMBLE; - ic->ic_flags |= IEEE80211_F_USEBARKER; + vap->iv_flags &= ~IEEE80211_F_SHPREAMBLE; + vap->iv_flags |= IEEE80211_F_USEBARKER; } - ieee80211_set_shortslottime(ic, + ieee80211_vap_set_shortslottime(vap, IEEE80211_IS_CHAN_A(ic->ic_curchan) || (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME)); + ieee80211_vap_update_preamble(vap); /* * Honor ERP protection. * @@ -1857,21 +1909,23 @@ sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, int subtype, */ if (IEEE80211_IS_CHAN_ANYG(ic->ic_curchan) && (ni->ni_erp & IEEE80211_ERP_USE_PROTECTION)) - ic->ic_flags |= IEEE80211_F_USEPROT; + vap->iv_flags |= IEEE80211_F_USEPROT; else - ic->ic_flags &= ~IEEE80211_F_USEPROT; + vap->iv_flags &= ~IEEE80211_F_USEPROT; + ieee80211_vap_update_erp_protmode(vap); IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_ASSOC | IEEE80211_MSG_DEBUG, wh->i_addr2, - "%sassoc success at aid %d: %s preamble, %s slot time%s%s%s%s%s%s%s%s", + "%sassoc success at aid %d: %s preamble, %s slot time%s%s%s%s%s%s%s%s%s", ISREASSOC(subtype) ? "re" : "", IEEE80211_NODE_AID(ni), - ic->ic_flags&IEEE80211_F_SHPREAMBLE ? "short" : "long", - ic->ic_flags&IEEE80211_F_SHSLOT ? "short" : "long", - ic->ic_flags&IEEE80211_F_USEPROT ? ", protection" : "", + vap->iv_flags&IEEE80211_F_SHPREAMBLE ? "short" : "long", + vap->iv_flags&IEEE80211_F_SHSLOT ? "short" : "long", + vap->iv_flags&IEEE80211_F_USEPROT ? ", protection" : "", ni->ni_flags & IEEE80211_NODE_QOS ? ", QoS" : "", ni->ni_flags & IEEE80211_NODE_HT ? (ni->ni_chw == 40 ? ", HT40" : ", HT20") : "", ni->ni_flags & IEEE80211_NODE_AMPDU ? " (+AMPDU)" : "", + ni->ni_flags & IEEE80211_NODE_AMSDU ? " (+AMSDU)" : "", ni->ni_flags & IEEE80211_NODE_MIMO_RTS ? " (+SMPS-DYN)" : ni->ni_flags & IEEE80211_NODE_MIMO_PS ? " (+SMPS)" : "", ni->ni_flags & IEEE80211_NODE_RIFS ? " (+RIFS)" : "", diff --git a/sys/net80211/ieee80211_sta.h b/sys/net80211/ieee80211_sta.h index 79c576d140ba..5f953c7a4dd3 100644 --- a/sys/net80211/ieee80211_sta.h +++ b/sys/net80211/ieee80211_sta.h @@ -40,5 +40,12 @@ void ieee80211_sta_vattach(struct ieee80211vap *); * Used by the adhoc/mesh/tdma paths. */ extern int ieee80211_parse_wmeparams(struct ieee80211vap *vap, uint8_t *frm, - const struct ieee80211_frame *wh); + const struct ieee80211_frame *wh, uint8_t *qosinfo); + +/* + * Used in the hostap path. + */ +extern int ieee80211_parse_wmeie(uint8_t *frm, + const struct ieee80211_frame *wh, struct ieee80211_node *ni); + #endif /* !_NET80211_IEEE80211_STA_H_ */ diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h index 8fe8f01c751a..dd469b6a7c1d 100644 --- a/sys/net80211/ieee80211_var.h +++ b/sys/net80211/ieee80211_var.h @@ -231,17 +231,11 @@ struct ieee80211com { /* XXX multi-bss: split out common/vap parts */ struct ieee80211_wme_state ic_wme; /* WME/WMM state */ - /* XXX multi-bss: can per-vap be done/make sense? */ + /* Protection mode for net80211 driven channel NICs */ enum ieee80211_protmode ic_protmode; /* 802.11g protection mode */ - uint16_t ic_nonerpsta; /* # non-ERP stations */ - uint16_t ic_longslotsta; /* # long slot time stations */ - uint16_t ic_sta_assoc; /* stations associated */ - uint16_t ic_ht_sta_assoc;/* HT stations associated */ - uint16_t ic_ht40_sta_assoc;/* HT40 stations associated */ - uint8_t ic_curhtprotmode;/* HTINFO bss state */ enum ieee80211_protmode ic_htprotmode; /* HT protection mode */ - int ic_lastnonerp; /* last time non-ERP sta noted*/ - int ic_lastnonht; /* last time non-HT sta noted */ + uint8_t ic_curhtprotmode;/* HTINFO bss state */ + uint8_t ic_rxstream; /* # RX streams */ uint8_t ic_txstream; /* # TX streams */ @@ -308,11 +302,22 @@ struct ieee80211com { /* TDMA update notification */ void (*ic_tdma_update)(struct ieee80211_node *, const struct ieee80211_tdma_param *, int); - /* node state management */ + + /* Node state management */ + + /* Allocate a new node */ struct ieee80211_node* (*ic_node_alloc)(struct ieee80211vap *, const uint8_t [IEEE80211_ADDR_LEN]); + + /* Driver node initialisation after net80211 setup */ + int (*ic_node_init)(struct ieee80211_node *); + + /* Driver node deallocation */ void (*ic_node_free)(struct ieee80211_node *); + + /* Driver node state cleanup before deallocation */ void (*ic_node_cleanup)(struct ieee80211_node *); + void (*ic_node_age)(struct ieee80211_node *); void (*ic_node_drain)(struct ieee80211_node *); int8_t (*ic_node_getrssi)(const struct ieee80211_node*); @@ -377,6 +382,8 @@ struct ieee80211_aclator; struct ieee80211_tdma_state; struct ieee80211_mesh_state; struct ieee80211_hwmp_state; +struct ieee80211_rx_histogram; +struct ieee80211_tx_histogram; struct ieee80211vap { struct ifmedia iv_media; /* interface media config */ @@ -562,6 +569,38 @@ struct ieee80211vap { const struct wmeParams *wme_params); struct task iv_wme_task; /* deferred VAP WME update */ + /* associated state; protection mode */ + enum ieee80211_protmode iv_protmode; /* 802.11g protection mode */ + enum ieee80211_protmode iv_htprotmode; /* HT protection mode */ + uint8_t iv_curhtprotmode;/* HTINFO bss state */ + + uint16_t iv_nonerpsta; /* # non-ERP stations */ + uint16_t iv_longslotsta; /* # long slot time stations */ + uint16_t iv_ht_sta_assoc;/* HT stations associated */ + uint16_t iv_ht40_sta_assoc;/* HT40 stations associated */ + int iv_lastnonerp; /* last time non-ERP sta noted*/ + int iv_lastnonht; /* last time non-HT sta noted */ + + /* update device state for 802.11 slot time change */ + void (*iv_updateslot)(struct ieee80211vap *); + struct task iv_slot_task; /* deferred slot time update */ + + struct task iv_erp_protmode_task; /* deferred ERP protmode update */ + void (*iv_erp_protmode_update)(struct ieee80211vap *); + + struct task iv_preamble_task; /* deferred short/barker preamble update */ + void (*iv_preamble_update)(struct ieee80211vap *); + + struct task iv_ht_protmode_task; /* deferred HT protmode update */ + void (*iv_ht_protmode_update)(struct ieee80211vap *); + + /* per-vap U-APSD state */ + uint8_t iv_uapsdinfo; /* sta mode QoS Info flags */ + + /* Optional transmit/receive histogram statistics */ + struct ieee80211_rx_histogram *rx_histogram; + struct ieee80211_tx_histogram *tx_histogram; + uint64_t iv_spare[5]; uint32_t iv_com_state; /* com usage / detached flag */ uint32_t iv_spare1; @@ -645,6 +684,7 @@ MALLOC_DECLARE(M_80211_VAP); #define IEEE80211_FEXT_FRAG_OFFLOAD 0x00200000 /* CONF: hardware does 802.11 fragmentation + assignment */ #define IEEE80211_FEXT_VHT 0x00400000 /* CONF: VHT support */ #define IEEE80211_FEXT_QUIET_IE 0x00800000 /* STATUS: quiet IE in a beacon has been added */ +#define IEEE80211_FEXT_UAPSD 0x01000000 /* CONF: enable U-APSD */ #define IEEE80211_FEXT_BITS \ "\20\2INACT\3SCANWAIT\4BGSCAN\5WPS\6TSN\7SCANREQ\10RESUME" \ @@ -682,10 +722,14 @@ MALLOC_DECLARE(M_80211_VAP); #define IEEE80211_FVHT_VHT 0x000000001 /* CONF: VHT supported */ #define IEEE80211_FVHT_USEVHT40 0x000000002 /* CONF: Use VHT40 */ #define IEEE80211_FVHT_USEVHT80 0x000000004 /* CONF: Use VHT80 */ -#define IEEE80211_FVHT_USEVHT80P80 0x000000008 /* CONF: Use VHT 80+80 */ -#define IEEE80211_FVHT_USEVHT160 0x000000010 /* CONF: Use VHT160 */ +#define IEEE80211_FVHT_USEVHT160 0x000000008 /* CONF: Use VHT160 */ +#define IEEE80211_FVHT_USEVHT80P80 0x000000010 /* CONF: Use VHT 80+80 */ +#define IEEE80211_FVHT_MASK \ + (IEEE80211_FVHT_VHT | IEEE80211_FVHT_USEVHT40 | \ + IEEE80211_FVHT_USEVHT80 | IEEE80211_FVHT_USEVHT160 | \ + IEEE80211_FVHT_USEVHT80P80) #define IEEE80211_VFHT_BITS \ - "\20\1VHT\2VHT40\3VHT80\4VHT80P80\5VHT160" + "\20\1VHT\2VHT40\3VHT80\4VHT160\5VHT80P80" #define IEEE80211_COM_DETACHED 0x00000001 /* ieee80211_ifdetach called */ #define IEEE80211_COM_REF_ADD 0x00000002 /* add / remove reference */ @@ -733,6 +777,10 @@ int ieee80211_add_channel_ht40(struct ieee80211_channel[], int, int *, uint32_t ieee80211_get_channel_center_freq(const struct ieee80211_channel *); uint32_t ieee80211_get_channel_center_freq1(const struct ieee80211_channel *); uint32_t ieee80211_get_channel_center_freq2(const struct ieee80211_channel *); +#define NET80211_CBW_FLAG_HT40 0x01 +#define NET80211_CBW_FLAG_VHT80 0x02 +#define NET80211_CBW_FLAG_VHT160 0x04 +#define NET80211_CBW_FLAG_VHT80P80 0x08 int ieee80211_add_channel_list_2ghz(struct ieee80211_channel[], int, int *, const uint8_t[], int, const uint8_t[], int); int ieee80211_add_channels_default_2ghz(struct ieee80211_channel[], int, @@ -878,10 +926,10 @@ static __inline int ieee80211_vhtchanflags(const struct ieee80211_channel *c) { + if (IEEE80211_IS_CHAN_VHT80P80(c)) + return IEEE80211_FVHT_USEVHT80P80; if (IEEE80211_IS_CHAN_VHT160(c)) return IEEE80211_FVHT_USEVHT160; - if (IEEE80211_IS_CHAN_VHT80_80(c)) - return IEEE80211_FVHT_USEVHT80P80; if (IEEE80211_IS_CHAN_VHT80(c)) return IEEE80211_FVHT_USEVHT80; if (IEEE80211_IS_CHAN_VHT40(c)) diff --git a/sys/net80211/ieee80211_vht.c b/sys/net80211/ieee80211_vht.c index e50c11c5edcd..dbf9f9f69b4b 100644 --- a/sys/net80211/ieee80211_vht.c +++ b/sys/net80211/ieee80211_vht.c @@ -93,9 +93,7 @@ vht_recv_action_placeholder(struct ieee80211_node *ni, #ifdef IEEE80211_DEBUG ieee80211_note(ni->ni_vap, "%s: called; fc=0x%.2x/0x%.2x", - __func__, - wh->i_fc[0], - wh->i_fc[1]); + __func__, wh->i_fc[0], wh->i_fc[1]); #endif return (0); } @@ -107,9 +105,7 @@ vht_send_action_placeholder(struct ieee80211_node *ni, #ifdef IEEE80211_DEBUG ieee80211_note(ni->ni_vap, "%s: called; category=%d, action=%d", - __func__, - category, - action); + __func__, category, action); #endif return (EINVAL); } @@ -161,7 +157,13 @@ ieee80211_vht_vattach(struct ieee80211vap *vap) IEEE80211_FVHT_VHT | IEEE80211_FVHT_USEVHT40 | IEEE80211_FVHT_USEVHT80; +#if 0 /* XXX TODO: enable VHT80+80, VHT160 capabilities */ + if (XXX TODO FIXME) + vap->iv_flags_vht |= IEEE80211_FVHT_USEVHT160; + if (XXX TODO FIXME) + vap->iv_flags_vht |= IEEE80211_FVHT_USEVHT80P80; +#endif memcpy(&vap->iv_vht_mcsinfo, &ic->ic_vht_mcsinfo, sizeof(struct ieee80211_vht_mcs_info)); @@ -205,10 +207,10 @@ ieee80211_vht_announce(struct ieee80211com *ic) /* Channel width */ ic_printf(ic, "[VHT] Channel Widths: 20MHz, 40MHz, 80MHz"); - if (MS(ic->ic_vhtcaps, IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK) == 2) - printf(" 80+80MHz"); if (MS(ic->ic_vhtcaps, IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK) >= 1) printf(" 160MHz"); + if (MS(ic->ic_vhtcaps, IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK) == 2) + printf(" 80+80MHz"); printf("\n"); /* Features */ @@ -216,16 +218,14 @@ ieee80211_vht_announce(struct ieee80211com *ic) IEEE80211_VHTCAP_BITS); /* For now, just 5GHz VHT. Worry about 2GHz VHT later */ - for (i = 0; i < 7; i++) { + for (i = 0; i < 8; i++) { /* Each stream is 2 bits */ tx = (ic->ic_vht_mcsinfo.tx_mcs_map >> (2*i)) & 0x3; rx = (ic->ic_vht_mcsinfo.rx_mcs_map >> (2*i)) & 0x3; if (tx == 3 && rx == 3) continue; ic_printf(ic, "[VHT] NSS %d: TX MCS 0..%d, RX MCS 0..%d\n", - i + 1, - vht_mcs_to_num(tx), - vht_mcs_to_num(rx)); + i + 1, vht_mcs_to_num(tx), vht_mcs_to_num(rx)); } } @@ -263,10 +263,7 @@ ieee80211_parse_vhtopmode(struct ieee80211_node *ni, const uint8_t *ie) #if 0 printf("%s: chan1=%d, chan2=%d, chanwidth=%d, basicmcs=0x%04x\n", - __func__, - ni->ni_vht_chan1, - ni->ni_vht_chan2, - ni->ni_vht_chanwidth, + __func__, ni->ni_vht_chan1, ni->ni_vht_chan2, ni->ni_vht_chanwidth, ni->ni_vht_basicmcs); #endif } @@ -312,7 +309,7 @@ ieee80211_setup_vht_rates(struct ieee80211_node *ni, } void -ieee80211_vht_timeout(struct ieee80211com *ic) +ieee80211_vht_timeout(struct ieee80211vap *vap) { } @@ -696,27 +693,20 @@ ieee80211_vht_get_chwidth_ie(struct ieee80211_channel *c) * well? */ - if (IEEE80211_IS_CHAN_VHT160(c)) { - return IEEE80211_VHT_CHANWIDTH_160MHZ; - } - if (IEEE80211_IS_CHAN_VHT80_80(c)) { + if (IEEE80211_IS_CHAN_VHT80P80(c)) return IEEE80211_VHT_CHANWIDTH_80P80MHZ; - } - if (IEEE80211_IS_CHAN_VHT80(c)) { + if (IEEE80211_IS_CHAN_VHT160(c)) + return IEEE80211_VHT_CHANWIDTH_160MHZ; + if (IEEE80211_IS_CHAN_VHT80(c)) return IEEE80211_VHT_CHANWIDTH_80MHZ; - } - if (IEEE80211_IS_CHAN_VHT40(c)) { + if (IEEE80211_IS_CHAN_VHT40(c)) return IEEE80211_VHT_CHANWIDTH_USE_HT; - } - if (IEEE80211_IS_CHAN_VHT20(c)) { + if (IEEE80211_IS_CHAN_VHT20(c)) return IEEE80211_VHT_CHANWIDTH_USE_HT; - } /* We shouldn't get here */ printf("%s: called on a non-VHT channel (freq=%d, flags=0x%08x\n", - __func__, - (int) c->ic_freq, - c->ic_flags); + __func__, (int) c->ic_freq, c->ic_flags); return IEEE80211_VHT_CHANWIDTH_USE_HT; } @@ -811,7 +801,7 @@ ieee80211_vht_adjust_channel(struct ieee80211com *ic, c = findvhtchan(ic, chan, IEEE80211_CHAN_VHT80); if ((c == NULL) && (flags & IEEE80211_FVHT_USEVHT80P80)) - c = findvhtchan(ic, chan, IEEE80211_CHAN_VHT80_80); + c = findvhtchan(ic, chan, IEEE80211_CHAN_VHT80P80); if ((c == NULL) && (flags & IEEE80211_FVHT_USEVHT80)) c = findvhtchan(ic, chan, IEEE80211_CHAN_VHT80); diff --git a/sys/net80211/ieee80211_vht.h b/sys/net80211/ieee80211_vht.h index 791762b14a31..cbbd5a4c9dba 100644 --- a/sys/net80211/ieee80211_vht.h +++ b/sys/net80211/ieee80211_vht.h @@ -45,7 +45,7 @@ int ieee80211_vht_updateparams(struct ieee80211_node *, void ieee80211_setup_vht_rates(struct ieee80211_node *, const uint8_t *, const uint8_t *); -void ieee80211_vht_timeout(struct ieee80211com *ic); +void ieee80211_vht_timeout(struct ieee80211vap *vap); void ieee80211_vht_node_join(struct ieee80211_node *ni); void ieee80211_vht_node_leave(struct ieee80211_node *ni); diff --git a/sys/sys/priv.h b/sys/sys/priv.h index 9c9964eaa180..948a6c28bb69 100644 --- a/sys/sys/priv.h +++ b/sys/sys/priv.h @@ -350,8 +350,10 @@ /* * 802.11-related privileges. */ -#define PRIV_NET80211_GETKEY 440 /* Query 802.11 keys. */ -#define PRIV_NET80211_MANAGE 441 /* Administer 802.11. */ +#define PRIV_NET80211_VAP_GETKEY 440 /* Query VAP 802.11 keys. */ +#define PRIV_NET80211_VAP_MANAGE 441 /* Administer 802.11 VAP */ +#define PRIV_NET80211_VAP_SETMAC 442 /* Set VAP MAC address */ +#define PRIV_NET80211_CREATE_VAP 443 /* Create a new VAP */ /* * Placeholder for AppleTalk privileges, not supported anymore. diff --git a/tools/tools/ath/Makefile b/tools/tools/ath/Makefile index b17f4c4b2dcc..1b5543909b63 100644 --- a/tools/tools/ath/Makefile +++ b/tools/tools/ath/Makefile @@ -3,6 +3,6 @@ SUBDIR= arcode athdebug athdecode athkey athpoke athprom athrd athregs athalq SUBDIR+= athstats ath_prom_read athradar athaggrstats SUBDIR+= ath_ee_v14_print ath_ee_v4k_print ath_ee_9287_print ath_ee_9300_print -SUBDIR+= athsurvey athratestats athspectral +SUBDIR+= athsurvey athratestats athspectral athani .include <bsd.subdir.mk> diff --git a/tools/tools/ath/ath_ee_9300_print/main.c b/tools/tools/ath/ath_ee_9300_print/main.c index df278e18f888..38dd879b55a1 100644 --- a/tools/tools/ath/ath_ee_9300_print/main.c +++ b/tools/tools/ath/ath_ee_9300_print/main.c @@ -37,6 +37,34 @@ struct ath_hal; #include "ar9300/ar9300eep.h" +static const char * +eeprom_9300_ctl_idx_to_mode(uint8_t idx) +{ + switch (idx & 0xf) { + /* 2G CTLs */ + case 1: return "CCK"; + case 2: return "OFDM"; + case 5: return "HT20"; + case 7: return "HT40"; + /* 5G CTLs */ + case 0: return "OFDM"; + case 6: return "HT20"; + case 8: return "HT40"; + default: return ""; + } +} + +static const char * +eeprom_9300_ctl_idx_to_regdomain(uint8_t idx) +{ + switch (idx & 0xf0) { + case 0x10: return "FCC"; + case 0x30: return "ETSI"; + case 0x40: return "JP"; + default: return ""; + } +} + static void eeprom_9300_hdr_print(const uint16_t *buf) { @@ -156,6 +184,246 @@ eeprom_9300_modal_print(const OSPREY_MODAL_EEP_HEADER *m) } static void +eeprom_9300_print_2g_target_cck(const ar9300_eeprom_t *ee) +{ + int i; + + for (i = 0; i < OSPREY_NUM_2G_CCK_TARGET_POWERS; i++) { + printf("| Freq %u CCK: pow2x 1/5L %u 5S %u 11L %u 11S %u\n", + FBIN2FREQ(ee->cal_target_freqbin_cck[i], 1), + ee->cal_target_power_cck[i].t_pow2x[LEGACY_TARGET_RATE_1L_5L], + ee->cal_target_power_cck[i].t_pow2x[LEGACY_TARGET_RATE_5S], + ee->cal_target_power_cck[i].t_pow2x[LEGACY_TARGET_RATE_11L], + ee->cal_target_power_cck[i].t_pow2x[LEGACY_TARGET_RATE_11S]); + } +} + +static void +eeprom_9300_print_2g_target_ofdm(const ar9300_eeprom_t *ee) +{ + int i; + + for (i = 0; i < OSPREY_NUM_2G_20_TARGET_POWERS; i++) { + printf("| Freq %u OFDM: pow2x 6/12/18/24M %u 36M %u 48M %u 54M %u\n", + FBIN2FREQ(ee->cal_target_freqbin_2g[i], 1), + ee->cal_target_power_2g[i].t_pow2x[LEGACY_TARGET_RATE_6_24], + ee->cal_target_power_2g[i].t_pow2x[LEGACY_TARGET_RATE_36], + ee->cal_target_power_2g[i].t_pow2x[LEGACY_TARGET_RATE_48], + ee->cal_target_power_2g[i].t_pow2x[LEGACY_TARGET_RATE_54]); + } +} + +static void +eeprom_9300_print_2g_target_ht20(const ar9300_eeprom_t *ee) +{ + int i; + + for (i = 0; i < OSPREY_NUM_2G_20_TARGET_POWERS; i++) { + printf("| Freq %u HT20 MCS0-7 pow2x %u %u %u %u %u %u %u %u\n", + FBIN2FREQ(ee->cal_target_freqbin_2g_ht20[i], 1), + ee->cal_target_power_2g_ht20[i].t_pow2x[HT_TARGET_RATE_0_8_16], + ee->cal_target_power_2g_ht20[i].t_pow2x[HT_TARGET_RATE_1_3_9_11_17_19], + ee->cal_target_power_2g_ht20[i].t_pow2x[HT_TARGET_RATE_1_3_9_11_17_19], + ee->cal_target_power_2g_ht20[i].t_pow2x[HT_TARGET_RATE_1_3_9_11_17_19], + ee->cal_target_power_2g_ht20[i].t_pow2x[HT_TARGET_RATE_4], + ee->cal_target_power_2g_ht20[i].t_pow2x[HT_TARGET_RATE_5], + ee->cal_target_power_2g_ht20[i].t_pow2x[HT_TARGET_RATE_6], + ee->cal_target_power_2g_ht20[i].t_pow2x[HT_TARGET_RATE_7]); + printf("| Freq %u HT20 MCS8-15 pow2x %u %u %u %u %u %u %u %u\n", + FBIN2FREQ(ee->cal_target_freqbin_2g_ht20[i], 1), + ee->cal_target_power_2g_ht20[i].t_pow2x[HT_TARGET_RATE_0_8_16], + ee->cal_target_power_2g_ht20[i].t_pow2x[HT_TARGET_RATE_1_3_9_11_17_19], + ee->cal_target_power_2g_ht20[i].t_pow2x[HT_TARGET_RATE_1_3_9_11_17_19], + ee->cal_target_power_2g_ht20[i].t_pow2x[HT_TARGET_RATE_1_3_9_11_17_19], + ee->cal_target_power_2g_ht20[i].t_pow2x[HT_TARGET_RATE_12], + ee->cal_target_power_2g_ht20[i].t_pow2x[HT_TARGET_RATE_13], + ee->cal_target_power_2g_ht20[i].t_pow2x[HT_TARGET_RATE_14], + ee->cal_target_power_2g_ht20[i].t_pow2x[HT_TARGET_RATE_15]); + printf("| Freq %u HT20 MCS16-23 pow2x %u %u %u %u %u %u %u %u\n", + FBIN2FREQ(ee->cal_target_freqbin_2g_ht20[i], 1), + ee->cal_target_power_2g_ht20[i].t_pow2x[HT_TARGET_RATE_0_8_16], + ee->cal_target_power_2g_ht20[i].t_pow2x[HT_TARGET_RATE_1_3_9_11_17_19], + ee->cal_target_power_2g_ht20[i].t_pow2x[HT_TARGET_RATE_1_3_9_11_17_19], + ee->cal_target_power_2g_ht20[i].t_pow2x[HT_TARGET_RATE_1_3_9_11_17_19], + ee->cal_target_power_2g_ht20[i].t_pow2x[HT_TARGET_RATE_20], + ee->cal_target_power_2g_ht20[i].t_pow2x[HT_TARGET_RATE_21], + ee->cal_target_power_2g_ht20[i].t_pow2x[HT_TARGET_RATE_22], + ee->cal_target_power_2g_ht20[i].t_pow2x[HT_TARGET_RATE_23]); + } +} + +static void +eeprom_9300_print_2g_target_ht40(const ar9300_eeprom_t *ee) +{ + int i; + + for (i = 0; i < OSPREY_NUM_2G_40_TARGET_POWERS; i++) { + printf("| Freq %u HT40 MCS0-7 pow2x %u %u %u %u %u %u %u %u\n", + FBIN2FREQ(ee->cal_target_freqbin_2g_ht40[i], 1), + ee->cal_target_power_2g_ht40[i].t_pow2x[HT_TARGET_RATE_0_8_16], + ee->cal_target_power_2g_ht40[i].t_pow2x[HT_TARGET_RATE_1_3_9_11_17_19], + ee->cal_target_power_2g_ht40[i].t_pow2x[HT_TARGET_RATE_1_3_9_11_17_19], + ee->cal_target_power_2g_ht40[i].t_pow2x[HT_TARGET_RATE_1_3_9_11_17_19], + ee->cal_target_power_2g_ht40[i].t_pow2x[HT_TARGET_RATE_4], + ee->cal_target_power_2g_ht40[i].t_pow2x[HT_TARGET_RATE_5], + ee->cal_target_power_2g_ht40[i].t_pow2x[HT_TARGET_RATE_6], + ee->cal_target_power_2g_ht40[i].t_pow2x[HT_TARGET_RATE_7]); + printf("| Freq %u HT40 MCS8-15 pow2x %u %u %u %u %u %u %u %u\n", + FBIN2FREQ(ee->cal_target_freqbin_2g_ht40[i], 1), + ee->cal_target_power_2g_ht40[i].t_pow2x[HT_TARGET_RATE_0_8_16], + ee->cal_target_power_2g_ht40[i].t_pow2x[HT_TARGET_RATE_1_3_9_11_17_19], + ee->cal_target_power_2g_ht40[i].t_pow2x[HT_TARGET_RATE_1_3_9_11_17_19], + ee->cal_target_power_2g_ht40[i].t_pow2x[HT_TARGET_RATE_1_3_9_11_17_19], + ee->cal_target_power_2g_ht40[i].t_pow2x[HT_TARGET_RATE_12], + ee->cal_target_power_2g_ht40[i].t_pow2x[HT_TARGET_RATE_13], + ee->cal_target_power_2g_ht40[i].t_pow2x[HT_TARGET_RATE_14], + ee->cal_target_power_2g_ht40[i].t_pow2x[HT_TARGET_RATE_15]); + printf("| Freq %u HT40 MCS16-23 pow2x %u %u %u %u %u %u %u %u\n", + FBIN2FREQ(ee->cal_target_freqbin_2g_ht40[i], 1), + ee->cal_target_power_2g_ht40[i].t_pow2x[HT_TARGET_RATE_0_8_16], + ee->cal_target_power_2g_ht40[i].t_pow2x[HT_TARGET_RATE_1_3_9_11_17_19], + ee->cal_target_power_2g_ht40[i].t_pow2x[HT_TARGET_RATE_1_3_9_11_17_19], + ee->cal_target_power_2g_ht40[i].t_pow2x[HT_TARGET_RATE_1_3_9_11_17_19], + ee->cal_target_power_2g_ht40[i].t_pow2x[HT_TARGET_RATE_20], + ee->cal_target_power_2g_ht40[i].t_pow2x[HT_TARGET_RATE_21], + ee->cal_target_power_2g_ht40[i].t_pow2x[HT_TARGET_RATE_22], + ee->cal_target_power_2g_ht40[i].t_pow2x[HT_TARGET_RATE_23]); + } +} + +static void +eeprom_9300_print_2g_ctls(const ar9300_eeprom_t *ee) +{ + int i, j; + + for (i = 0; i < OSPREY_NUM_CTLS_2G; i++) { + printf("| CTL index 0x%.02x (%s %s)\n", + ee->ctl_index_2g[i], + eeprom_9300_ctl_idx_to_regdomain(ee->ctl_index_2g[i]), + eeprom_9300_ctl_idx_to_mode(ee->ctl_index_2g[i])); + for (j = 0; j < OSPREY_NUM_BAND_EDGES_2G; j++) { + printf("| Freq %u pow2x %u flags 0x%x\n", + FBIN2FREQ(ee->ctl_freqbin_2G[i][j], 1), + ee->ctl_power_data_2g[i].ctl_edges[j].t_power, + ee->ctl_power_data_2g[i].ctl_edges[j].flag); + } + printf("\n"); + } +} + +static void +eeprom_9300_print_5g_target_ofdm(const ar9300_eeprom_t *ee) +{ + int i; + + for (i = 0; i < OSPREY_NUM_5G_20_TARGET_POWERS; i++) { + printf("| Freq %u OFDM: pow2x 6/12/18/24M %u 36M %u 48M %u 54M %u\n", + FBIN2FREQ(ee->cal_target_freqbin_5g[i], 0), + ee->cal_target_power_5g[i].t_pow2x[LEGACY_TARGET_RATE_6_24], + ee->cal_target_power_5g[i].t_pow2x[LEGACY_TARGET_RATE_36], + ee->cal_target_power_5g[i].t_pow2x[LEGACY_TARGET_RATE_48], + ee->cal_target_power_5g[i].t_pow2x[LEGACY_TARGET_RATE_54]); + } +} + +static void +eeprom_9300_print_5g_target_ht20(const ar9300_eeprom_t *ee) +{ + int i; + + for (i = 0; i < OSPREY_NUM_5G_20_TARGET_POWERS; i++) { + printf("| Freq %u HT20 MCS0-7 pow2x %u %u %u %u %u %u %u %u\n", + FBIN2FREQ(ee->cal_target_freqbin_5g_ht20[i], 0), + ee->cal_target_power_5g_ht20[i].t_pow2x[HT_TARGET_RATE_0_8_16], + ee->cal_target_power_5g_ht20[i].t_pow2x[HT_TARGET_RATE_1_3_9_11_17_19], + ee->cal_target_power_5g_ht20[i].t_pow2x[HT_TARGET_RATE_1_3_9_11_17_19], + ee->cal_target_power_5g_ht20[i].t_pow2x[HT_TARGET_RATE_1_3_9_11_17_19], + ee->cal_target_power_5g_ht20[i].t_pow2x[HT_TARGET_RATE_4], + ee->cal_target_power_5g_ht20[i].t_pow2x[HT_TARGET_RATE_5], + ee->cal_target_power_5g_ht20[i].t_pow2x[HT_TARGET_RATE_6], + ee->cal_target_power_5g_ht20[i].t_pow2x[HT_TARGET_RATE_7]); + printf("| Freq %u HT20 MCS8-15 pow2x %u %u %u %u %u %u %u %u\n", + FBIN2FREQ(ee->cal_target_freqbin_5g_ht20[i], 0), + ee->cal_target_power_5g_ht20[i].t_pow2x[HT_TARGET_RATE_0_8_16], + ee->cal_target_power_5g_ht20[i].t_pow2x[HT_TARGET_RATE_1_3_9_11_17_19], + ee->cal_target_power_5g_ht20[i].t_pow2x[HT_TARGET_RATE_1_3_9_11_17_19], + ee->cal_target_power_5g_ht20[i].t_pow2x[HT_TARGET_RATE_1_3_9_11_17_19], + ee->cal_target_power_5g_ht20[i].t_pow2x[HT_TARGET_RATE_12], + ee->cal_target_power_5g_ht20[i].t_pow2x[HT_TARGET_RATE_13], + ee->cal_target_power_5g_ht20[i].t_pow2x[HT_TARGET_RATE_14], + ee->cal_target_power_5g_ht20[i].t_pow2x[HT_TARGET_RATE_15]); + printf("| Freq %u HT20 MCS16-23 pow2x %u %u %u %u %u %u %u %u\n", + FBIN2FREQ(ee->cal_target_freqbin_5g_ht20[i], 0), + ee->cal_target_power_5g_ht20[i].t_pow2x[HT_TARGET_RATE_0_8_16], + ee->cal_target_power_5g_ht20[i].t_pow2x[HT_TARGET_RATE_1_3_9_11_17_19], + ee->cal_target_power_5g_ht20[i].t_pow2x[HT_TARGET_RATE_1_3_9_11_17_19], + ee->cal_target_power_5g_ht20[i].t_pow2x[HT_TARGET_RATE_1_3_9_11_17_19], + ee->cal_target_power_5g_ht20[i].t_pow2x[HT_TARGET_RATE_20], + ee->cal_target_power_5g_ht20[i].t_pow2x[HT_TARGET_RATE_21], + ee->cal_target_power_5g_ht20[i].t_pow2x[HT_TARGET_RATE_22], + ee->cal_target_power_5g_ht20[i].t_pow2x[HT_TARGET_RATE_23]); + } +} + +static void +eeprom_9300_print_5g_target_ht40(const ar9300_eeprom_t *ee) +{ + int i; + + for (i = 0; i < OSPREY_NUM_5G_40_TARGET_POWERS; i++) { + printf("| Freq %u HT40 MCS0-7 pow2x %u %u %u %u %u %u %u %u\n", + FBIN2FREQ(ee->cal_target_freqbin_5g_ht40[i], 0), + ee->cal_target_power_5g_ht40[i].t_pow2x[HT_TARGET_RATE_0_8_16], + ee->cal_target_power_5g_ht40[i].t_pow2x[HT_TARGET_RATE_1_3_9_11_17_19], + ee->cal_target_power_5g_ht40[i].t_pow2x[HT_TARGET_RATE_1_3_9_11_17_19], + ee->cal_target_power_5g_ht40[i].t_pow2x[HT_TARGET_RATE_1_3_9_11_17_19], + ee->cal_target_power_5g_ht40[i].t_pow2x[HT_TARGET_RATE_4], + ee->cal_target_power_5g_ht40[i].t_pow2x[HT_TARGET_RATE_5], + ee->cal_target_power_5g_ht40[i].t_pow2x[HT_TARGET_RATE_6], + ee->cal_target_power_5g_ht40[i].t_pow2x[HT_TARGET_RATE_7]); + printf("| Freq %u HT40 MCS8-15 pow2x %u %u %u %u %u %u %u %u\n", + FBIN2FREQ(ee->cal_target_freqbin_5g_ht40[i], 0), + ee->cal_target_power_5g_ht40[i].t_pow2x[HT_TARGET_RATE_0_8_16], + ee->cal_target_power_5g_ht40[i].t_pow2x[HT_TARGET_RATE_1_3_9_11_17_19], + ee->cal_target_power_5g_ht40[i].t_pow2x[HT_TARGET_RATE_1_3_9_11_17_19], + ee->cal_target_power_5g_ht40[i].t_pow2x[HT_TARGET_RATE_1_3_9_11_17_19], + ee->cal_target_power_5g_ht40[i].t_pow2x[HT_TARGET_RATE_12], + ee->cal_target_power_5g_ht40[i].t_pow2x[HT_TARGET_RATE_13], + ee->cal_target_power_5g_ht40[i].t_pow2x[HT_TARGET_RATE_14], + ee->cal_target_power_5g_ht40[i].t_pow2x[HT_TARGET_RATE_15]); + printf("| Freq %u HT40 MCS16-23 pow2x %u %u %u %u %u %u %u %u\n", + FBIN2FREQ(ee->cal_target_freqbin_5g_ht40[i], 0), + ee->cal_target_power_5g_ht40[i].t_pow2x[HT_TARGET_RATE_0_8_16], + ee->cal_target_power_5g_ht40[i].t_pow2x[HT_TARGET_RATE_1_3_9_11_17_19], + ee->cal_target_power_5g_ht40[i].t_pow2x[HT_TARGET_RATE_1_3_9_11_17_19], + ee->cal_target_power_5g_ht40[i].t_pow2x[HT_TARGET_RATE_1_3_9_11_17_19], + ee->cal_target_power_5g_ht40[i].t_pow2x[HT_TARGET_RATE_20], + ee->cal_target_power_5g_ht40[i].t_pow2x[HT_TARGET_RATE_21], + ee->cal_target_power_5g_ht40[i].t_pow2x[HT_TARGET_RATE_22], + ee->cal_target_power_5g_ht40[i].t_pow2x[HT_TARGET_RATE_23]); + } +} + +static void +eeprom_9300_print_5g_ctls(const ar9300_eeprom_t *ee) +{ + int i, j; + + for (i = 0; i < OSPREY_NUM_CTLS_5G; i++) { + printf("| CTL index 0x%.02x (%s %s)\n", ee->ctl_index_5g[i], + eeprom_9300_ctl_idx_to_regdomain(ee->ctl_index_5g[i]), + eeprom_9300_ctl_idx_to_mode(ee->ctl_index_5g[i])); + for (j = 0; j < OSPREY_NUM_BAND_EDGES_5G; j++) { + printf("| Freq %u pow2x %u Flags 0x%x\n", + FBIN2FREQ(ee->ctl_freqbin_5G[i][j], 0), + ee->ctl_power_data_5g[i].ctl_edges[j].t_power, + ee->ctl_power_data_5g[i].ctl_edges[j].flag); + } + printf("\n"); + } +} + +static void load_eeprom_dump(const char *file, uint16_t *buf) { unsigned int r[8]; @@ -222,9 +490,19 @@ main(int argc, char *argv[]) printf("\n2GHz modal:\n"); eeprom_9300_modal_print(&ee->modal_header_2g); + // TODO: open-loop calibration + eeprom_9300_print_2g_target_cck(ee); + eeprom_9300_print_2g_target_ofdm(ee); + eeprom_9300_print_2g_target_ht20(ee); + eeprom_9300_print_2g_target_ht40(ee); + eeprom_9300_print_2g_ctls(ee); printf("\n5GHz modal:\n"); eeprom_9300_modal_print(&ee->modal_header_5g); + eeprom_9300_print_5g_target_ofdm(ee); + eeprom_9300_print_5g_target_ht20(ee); + eeprom_9300_print_5g_target_ht40(ee); + eeprom_9300_print_5g_ctls(ee); free(eep); exit(0); diff --git a/tools/tools/ath/athani/Makefile b/tools/tools/ath/athani/Makefile new file mode 100644 index 000000000000..b475a6b0ed63 --- /dev/null +++ b/tools/tools/ath/athani/Makefile @@ -0,0 +1,23 @@ +# $FreeBSD$ + +PROG= athani +MAN= + +CFLAGS+= -I../../../../sys/contrib + +SRCS= main.c + +.include <../Makefile.inc> + +CFLAGS+= -I${.CURDIR}/../common/ +.PATH.c: ${.CURDIR}/../common/ +SRCS+= ctrl.c + +CLEANFILES+= opt_ah.h + +opt_ah.h: + echo "#define AH_DEBUG 1" > opt_ah.h + echo "#define AH_DEBUG_COUNTRY 1" >> opt_ah.h + echo "#define AH_SUPPORT_AR5416 1" >> opt_ah.h + +.include <bsd.prog.mk> diff --git a/tools/tools/ath/athani/main.c b/tools/tools/ath/athani/main.c new file mode 100644 index 000000000000..e2147091780d --- /dev/null +++ b/tools/tools/ath/athani/main.c @@ -0,0 +1,226 @@ +/*- + * Copyright (c) 2019 Adrian Chadd <adrian@FreeBSD.org>. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + * + * $FreeBSD$ + */ +#include "diag.h" + +#include "ah.h" +#include "ah_internal.h" + +#include <getopt.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <err.h> + +#include "../common/ctrl.h" + +/* + * This is a simple wrapper program around the ANI diagnostic interface. + * It is for fetching and setting the live ANI configuration when trying + * to diagnose a noisy environment. + */ + +/* + * HAL_DIAG_ANI_CMD is used to set the ANI configuration. + * HAL_DIAG_ANI_CURRENT is used to fetch the current ANI configuration. + */ + +struct ani_var { + const char *name; + int id; +}; + +static struct ani_var ani_labels[] = { + { "ofdm_noise_immunity_level", 1, }, + { "noise_immunity_level", 1, }, + { "ofdm_weak_signal_detect", 2, }, + { "cck_weak_signal_threshold", 3, }, + { "firstep_level", 4, }, + { "spur_immunity_level", 5, }, + { "mrc_cck", 8, }, + { "cck_noise_immunity_level", 9, }, + { NULL, -1, }, +}; + +static void +usage(void) +{ + fprintf(stderr, "usage: athani [-i interface] [-l]\n"); + fprintf(stderr, " -i: interface\n"); + fprintf(stderr, " -l: list ANI labels\n"); + fprintf(stderr, " If no args are given after flags, the ANI state will be listed.\n"); + fprintf(stderr, " To set, use '<label> <value>' to set the state\n"); + exit(-1); +} + +static void +list_labels(void) +{ + int i; + + for (i = 0; ani_labels[i].name != NULL; i++) { + printf("%s (%d)\n", ani_labels[i].name, ani_labels[i].id); + } +} + +static int +ani_write_state(struct ath_driver_req *req, const char *ifname, + const char *label, const char *value) +{ + struct ath_diag atd; + uint32_t args[2]; + uint32_t cmd, val; + size_t sl; + int i; + + /* Find the label */ + sl = strlen(label); + for (i = 0; ani_labels[i].name != NULL; i++) { + if ((strlen(ani_labels[i].name) == sl) && + (strcmp(label, ani_labels[i].name) == 0)) { + cmd = ani_labels[i].id; + break; + } + } + if (ani_labels[i].name == NULL) { + fprintf(stderr, "%s: couldn't find ANI label (%s)\n", + __func__, label); + return (-1); + } + + val = strtoul(value, NULL, 0); + + /* + * Whilst we're doing the ath_diag pieces, we have to set this + * ourselves. + */ + strncpy(atd.ad_name, ifname, sizeof (atd.ad_name)); + + /* + * Populate HAL_DIAG_ANI_CMD fields. + */ + args[0] = cmd; + args[1] = val; + + atd.ad_id = HAL_DIAG_ANI_CMD | ATH_DIAG_IN; + atd.ad_out_data = NULL; + atd.ad_out_size = 0; + atd.ad_in_data = (void *) &args; + atd.ad_in_size = sizeof(args); + + if (ath_driver_req_fetch_diag(req, SIOCGATHDIAG, &atd) < 0) { + warn("SIOCGATHDIAG HAL_DIAG_ANI_CMD (%s)", atd.ad_name); + return (-1); + } + + return (0); +} + +static void +ani_read_state(struct ath_driver_req *req, const char *ifname) +{ + struct ath_diag atd; + HAL_ANI_STATE state; + + /* + * Whilst we're doing the ath_diag pieces, we have to set this + * ourselves. + */ + strncpy(atd.ad_name, ifname, sizeof (atd.ad_name)); + + atd.ad_id = HAL_DIAG_ANI_CURRENT; /* XXX | DIAG_DYN? */ + atd.ad_out_data = (caddr_t) &state; + atd.ad_out_size = sizeof(state); + + if (ath_driver_req_fetch_diag(req, SIOCGATHDIAG, &atd) < 0) + err(1, "%s", atd.ad_name); + + + printf(" ofdm_noise_immunity_level=%d\n", state.noiseImmunityLevel); + printf(" cck_noise_immunity_level=%d\n", state.cckNoiseImmunityLevel); + printf(" spur_immunity_level=%d\n", state.spurImmunityLevel); + printf(" firstep_level=%d\n", state.firstepLevel); + printf(" ofdm_weak_signal_detect=%d\n", state.ofdmWeakSigDetectOff); + printf(" cck_weak_signal_threshold=%d\n", state.cckWeakSigThreshold); + printf(" mrc_cck=%d\n", state.mrcCckOff); + /* XXX TODO: cycle counts? */ +} + +int +main(int argc, char *argv[]) +{ + struct ath_diag atd; + const char *ifname; + struct ath_driver_req req; + int what, c; + + ath_driver_req_init(&req); + + ifname = getenv("ATH"); + if (!ifname) + ifname = ATH_DEFAULT; + + what = 0; + while ((c = getopt(argc, argv, "i:l")) != -1) + switch (c) { + case 'i': + ifname = optarg; + break; + case 'l': + list_labels(); + exit(0); + default: + usage(); + /*NOTREACHED*/ + } + + /* Initialise the driver interface */ + if (ath_driver_req_open(&req, ifname) < 0) { + exit(127); + } + + argc -= optind; + argv += optind; + + if (argc == 0) { + ani_read_state(&req, ifname); + exit(0); + } + + if (argc < 2) { + usage(); + /*NOTREACHED*/ + } + + if (ani_write_state(&req, ifname, argv[0], argv[1]) != 0) + exit(1); + + exit(0); +} diff --git a/tools/tools/ath/athratestats/main.c b/tools/tools/ath/athratestats/main.c index b3f85f758577..317b025c1854 100644 --- a/tools/tools/ath/athratestats/main.c +++ b/tools/tools/ath/athratestats/main.c @@ -64,7 +64,7 @@ static int do_loop = 0; * This needs to be big enough to fit the two TLVs, the rate table * and the rate statistics table for a single node. */ -#define STATS_BUF_SIZE 8192 +#define STATS_BUF_SIZE 65536 #define PRINTMSG(...) do { \ if (do_loop == 0) \ @@ -122,53 +122,53 @@ ath_sample_stats(struct ath_ratestats *r, struct ath_rateioctl_rt *rt, (long long) sn->ratemask); for (y = 0; y < NUM_PACKET_SIZE_BINS; y++) { - PRINTATTR_ON(COLOR_PAIR(y+4) | A_BOLD); + PRINTATTR_ON(COLOR_PAIR(2 + (y % 4)) | A_BOLD); PRINTMSG("[%4u] cur rate %d %s since switch: " - "packets %d ticks %u\n", + "packets %d ticks %u ", bin_to_size(y), dot11rate(rt, sn->current_rix[y]), dot11str(rt, sn->current_rix[y]), sn->packets_since_switch[y], sn->ticks_since_switch[y]); - PRINTMSG("[%4u] last sample (%d %s) cur sample (%d %s) " - "packets sent %d\n", - bin_to_size(y), + PRINTMSG("last sample (%d %s) cur sample (%d %s) " + "packets sent %d ", dot11rate(rt, sn->last_sample_rix[y]), dot11str(rt, sn->last_sample_rix[y]), dot11rate(rt, sn->current_sample_rix[y]), dot11str(rt, sn->current_sample_rix[y]), sn->packets_sent[y]); - PRINTATTR_OFF(COLOR_PAIR(y+4) | A_BOLD); + PRINTATTR_OFF(COLOR_PAIR(2 + (y % 4)) | A_BOLD); - PRINTATTR_ON(COLOR_PAIR(3) | A_BOLD); - PRINTMSG("[%4u] packets since sample %d sample tt %u\n", - bin_to_size(y), + PRINTATTR_ON(COLOR_PAIR(1) | A_BOLD); + PRINTMSG("packets since sample %d sample tt %u\n", sn->packets_since_sample[y], sn->sample_tt[y]); PRINTATTR_OFF(COLOR_PAIR(3) | A_BOLD); - PRINTMSG("\n"); } - PRINTMSG(" TX Rate TXTOTAL:TXOK EWMA T/ F" + PRINTMSG(" TX Rate TXTOTAL:TXOK EWMA T/ F" + " avg last xmit "); + PRINTMSG(" TX Rate TXTOTAL:TXOK EWMA T/ F" " avg last xmit\n"); for (mask = sn->ratemask, rix = 0; mask != 0; mask >>= 1, rix++) { + int c = 0; if ((mask & 1) == 0) continue; for (y = 0; y < NUM_PACKET_SIZE_BINS; y++) { if (sn->stats[y][rix].total_packets == 0) continue; if (rix == sn->current_rix[y]) - PRINTATTR_ON(COLOR_PAIR(y+4) | A_BOLD); + PRINTATTR_ON(COLOR_PAIR(2 + (y % 4)) | A_BOLD); else if (rix == sn->last_sample_rix[y]) - PRINTATTR_ON(COLOR_PAIR(3) | A_BOLD); + PRINTATTR_ON(COLOR_PAIR(1) | A_BOLD); #if 0 else if (sn->stats[y][rix].ewma_pct / 10 < 50) PRINTATTR_ON(COLOR_PAIR(2) | A_BOLD); else if (sn->stats[y][rix].ewma_pct / 10 < 75) PRINTATTR_ON(COLOR_PAIR(1) | A_BOLD); #endif - PRINTMSG("[%2u %s:%4u] %8ju:%-8ju " - "(%3d.%1d%%) %8ju/%4d %5uuS %u\n", + PRINTMSG("[%2u %s:%5u] %8ju:%-8ju " + "(%3d.%1d%%) %8ju/%4d %5uuS %u ", dot11rate(rt, rix), dot11str(rt, rix), bin_to_size(y), @@ -181,16 +181,23 @@ ath_sample_stats(struct ath_ratestats *r, struct ath_rateioctl_rt *rt, sn->stats[y][rix].average_tx_time, sn->stats[y][rix].last_tx); if (rix == sn->current_rix[y]) - PRINTATTR_OFF(COLOR_PAIR(y+4) | A_BOLD); + PRINTATTR_OFF(COLOR_PAIR(2 + (y % 4)) | A_BOLD); else if (rix == sn->last_sample_rix[y]) - PRINTATTR_OFF(COLOR_PAIR(3) | A_BOLD); + PRINTATTR_OFF(COLOR_PAIR(1) | A_BOLD); #if 0 else if (sn->stats[y][rix].ewma_pct / 10 < 50) PRINTATTR_OFF(COLOR_PAIR(2) | A_BOLD); else if (sn->stats[y][rix].ewma_pct / 10 < 75) PRINTATTR_OFF(COLOR_PAIR(1) | A_BOLD); #endif + c++; + if (c == 2) { + PRINTMSG("\n"); + c = 0; + } } + if (c != 0) + PRINTMSG("\n"); } } diff --git a/tools/tools/net80211/wlanstats/main.c b/tools/tools/net80211/wlanstats/main.c index 38dd10eda1b2..bd73053be976 100644 --- a/tools/tools/net80211/wlanstats/main.c +++ b/tools/tools/net80211/wlanstats/main.c @@ -63,7 +63,7 @@ static struct { }, { "amsdu", - "input,output,amsdu_tooshort,amsdu_split,amsdu_decap,amsdu_encap,rssi,rate" + "input,output,amsdu_tooshort,amsdu_split,amsdu_decap,amsdu_encap,rx_amsdu_more,rx_amsdu_more_end,rssi,rate" }, }; diff --git a/tools/tools/net80211/wlanstats/wlanstats.c b/tools/tools/net80211/wlanstats/wlanstats.c index 0e5556848dae..b42d7312e519 100644 --- a/tools/tools/net80211/wlanstats/wlanstats.c +++ b/tools/tools/net80211/wlanstats/wlanstats.c @@ -276,7 +276,11 @@ static const struct fmt wlanstats[] = { { 8, "amsdu_decap", "decap", "A-MSDU frames received" }, #define S_AMSDU_ENCAP AFTER(S_AMSDU_DECAP) { 8, "amsdu_encap", "encap", "A-MSDU frames transmitted" }, -#define S_AMPDU_REORDER AFTER(S_AMSDU_ENCAP) +#define S_AMSDU_RX_MORE AFTER(S_AMSDU_ENCAP) + { 13, "rx_amsdu_more", "rx_amsdu_more", "A-MSDU HW intermediary decap'ed received" }, +#define S_AMSDU_RX_MORE_END AFTER(S_AMSDU_RX_MORE) + { 17, "rx_amsdu_more_end", "rx_amsdu_more_end", "A-MSDU HW end decap'ed received" }, +#define S_AMPDU_REORDER AFTER(S_AMSDU_RX_MORE_END) { 8, "ampdu_reorder", "reorder","A-MPDU frames held in reorder q" }, #define S_AMPDU_FLUSH AFTER(S_AMPDU_REORDER) { 8, "ampdu_flush", "flush", "A-MPDU frames sent up from reorder q" }, @@ -778,6 +782,8 @@ wlan_get_curstat(struct bsdstat *sf, int s, char b[], size_t bs) case S_AMSDU_SPLIT: STAT(amsdu_split); case S_AMSDU_DECAP: STAT(amsdu_decap); case S_AMSDU_ENCAP: STAT(amsdu_encap); + case S_AMSDU_RX_MORE: NSTAT(rx_amsdu_more); + case S_AMSDU_RX_MORE_END: NSTAT(rx_amsdu_more_end); case S_AMPDU_REORDER: STAT(ampdu_rx_reorder); case S_AMPDU_FLUSH: STAT(ampdu_rx_flush); case S_AMPDU_BARBAD: STAT(ampdu_bar_bad); @@ -941,6 +947,8 @@ wlan_get_totstat(struct bsdstat *sf, int s, char b[], size_t bs) case S_AMSDU_SPLIT: STAT(amsdu_split); case S_AMSDU_DECAP: STAT(amsdu_decap); case S_AMSDU_ENCAP: STAT(amsdu_encap); + case S_AMSDU_RX_MORE: NSTAT(rx_amsdu_more); + case S_AMSDU_RX_MORE_END: NSTAT(rx_amsdu_more_end); case S_AMPDU_REORDER: STAT(ampdu_rx_reorder); case S_AMPDU_FLUSH: STAT(ampdu_rx_flush); case S_AMPDU_BARBAD: STAT(ampdu_bar_bad); |