PERFORCE change 135207 for review
Sepherosa Ziehau
sephe at FreeBSD.org
Mon Feb 11 02:43:12 PST 2008
http://perforce.freebsd.org/chv.cgi?CH=135207
Change 135207 by sephe at sephe_zealot:sam_wifi on 2008/02/11 10:43:04
- Build rate table when STA is going to associate BSS, the
calculation is according to the BSS's basic rate set.
- Set ic_currates to ic_dynrates if operating as STA and 802.11
state machine has ticked to RUN.
How to handle rate table when NIC operates in IBSS mode is not
clear to me yet (starter of IBSS does not need to calculate rate
table dynamicly, while as a member of IBSS, dynamic calculation
should be done)
HT, half and quarter dynamic rate table setting up need more work,
now default HT, half and quarter rate tables are simply duplicated.
Affected files ...
.. //depot/projects/wifi/sys/net80211/ieee80211.c#64 edit
.. //depot/projects/wifi/sys/net80211/ieee80211_ioctl.c#91 edit
.. //depot/projects/wifi/sys/net80211/ieee80211_node.c#100 edit
.. //depot/projects/wifi/sys/net80211/ieee80211_phy.c#9 edit
.. //depot/projects/wifi/sys/net80211/ieee80211_phy.h#5 edit
.. //depot/projects/wifi/sys/net80211/ieee80211_proto.c#66 edit
.. //depot/projects/wifi/sys/net80211/ieee80211_scan.c#21 edit
.. //depot/projects/wifi/sys/net80211/ieee80211_var.h#66 edit
Differences ...
==== //depot/projects/wifi/sys/net80211/ieee80211.c#64 (text+ko) ====
@@ -295,6 +295,7 @@
ieee80211_crypto_detach(ic);
ieee80211_power_detach(ic);
ieee80211_node_detach(ic);
+ ieee80211_phy_detach(ic);
ifmedia_removeall(&ic->ic_media);
IEEE80211_LOCK_DESTROY(ic);
@@ -1234,8 +1235,11 @@
}
void
-ieee80211_set_channel(struct ieee80211com *ic, struct ieee80211_channel *c)
+ieee80211_set_channel(struct ieee80211com *ic, struct ieee80211_channel *c,
+ int dynrt)
{
ieee80211_update_curchan(ic, c);
+ if (dynrt && ic->ic_dynrates != NULL)
+ ic->ic_currates = ic->ic_dynrates;
ic->ic_set_channel(ic);
}
==== //depot/projects/wifi/sys/net80211/ieee80211_ioctl.c#91 (text+ko) ====
@@ -1758,7 +1758,7 @@
* Monitor and wds modes can switch directly.
*/
if (ic->ic_state == IEEE80211_S_RUN)
- ieee80211_set_channel(ic, ic->ic_des_chan);
+ ieee80211_set_channel(ic, ic->ic_des_chan, 0);
else
ieee80211_update_curchan(ic, ic->ic_des_chan);
} else {
==== //depot/projects/wifi/sys/net80211/ieee80211_node.c#100 (text+ko) ====
@@ -40,6 +40,7 @@
#include <net/ethernet.h>
#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_phy.h>
#include <net/bpf.h>
@@ -541,9 +542,17 @@
void
ieee80211_setbsschan(struct ieee80211com *ic, struct ieee80211_channel *c)
{
+ int dynrt = 0;
+
ic->ic_bsschan = c;
ic->ic_curmode = ieee80211_chan2mode(ic->ic_bsschan);
- ieee80211_set_channel(ic, ic->ic_bsschan);
+
+ ieee80211_free_dynratetable(ic);
+ if (ic->ic_opmode == IEEE80211_M_STA /* XXX IBSS */) {
+ ieee80211_set_dynratetable(ic, ic->ic_bsschan);
+ dynrt = 1;
+ }
+ ieee80211_set_channel(ic, ic->ic_bsschan, dynrt);
}
/*
==== //depot/projects/wifi/sys/net80211/ieee80211_phy.c#9 (text+ko) ====
@@ -552,3 +552,131 @@
}
return txTime;
}
+
+void
+ieee80211_free_dynratetable(struct ieee80211com *ic)
+{
+ if (ic->ic_dynrates != NULL) {
+ if (ic->ic_currates == ic->ic_dynrates) {
+ /*
+ * If ic_currates shadows ic_dynrates,
+ * reset it to the default rate table
+ * of the current channel.
+ */
+ ic->ic_currates =
+ ieee80211_get_ratetable(ic->ic_curchan);
+ }
+
+ free(ic->ic_dynrates, M_DEVBUF /* XXX */);
+ ic->ic_dynrates = NULL;
+ }
+}
+
+/* XXX */
+#define IEEE80211_T_PBCC (IEEE80211_T_HT + 1)
+
+void
+ieee80211_set_dynratetable(struct ieee80211com *ic,
+ const struct ieee80211_channel *c)
+{
+ const struct ieee80211_rate_table *rt0;
+ const struct ieee80211_rateset *rs;
+ struct ieee80211_rate_table *rt;
+ int i, cck = -1, ofdm = -1;
+
+ ieee80211_free_dynratetable(ic);
+
+ rt = malloc(sizeof(*rt), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (rt == NULL)
+ return;
+ ic->ic_dynrates = rt;
+
+ /* XXX HT, half and quarter */
+ rt0 = NULL;
+ if (IEEE80211_IS_CHAN_HALF(c))
+ rt0 = &ieee80211_half_table;
+ else if (IEEE80211_IS_CHAN_QUARTER(c))
+ rt0 = &ieee80211_quarter_table;
+ else if (IEEE80211_IS_CHAN_HTA(c))
+ rt0 = &ieee80211_11a_table;
+ else if (IEEE80211_IS_CHAN_HTG(c))
+ rt0 = &ieee80211_11g_table;
+ if (rt0 != NULL) {
+ bcopy(rt0, rt, sizeof(rt));
+ return;
+ }
+
+ rs = &ic->ic_bss->ni_rates;
+ rt->rateCount = rs->rs_nrates;
+ KASSERT(rt->rateCount <= (sizeof(rt->info) / sizeof(rt->info[0])),
+ ("oversized rate table\n"));
+ for (i = 0; i < rs->rs_nrates; ++i) {
+ uint8_t rate = rs->rs_rates[i] & IEEE80211_RATE_VAL;
+ int j;
+
+ if (rate == 44)
+ rt->info[i].phy = IEEE80211_T_PBCC;
+ else if (rate == 22 || rate < 12) {
+ rt->info[i].phy = IEEE80211_T_CCK;
+ if (rate != 2) {
+ /*
+ * DS 1Mbps does not support
+ * short preamble.
+ */
+ rt->info[i].shortPreamble = 0x04;
+ }
+ /* All DS/CCK rates are considered mandatory */
+ cck = i;
+ } else {
+ rt->info[i].phy = IEEE80211_T_OFDM;
+
+ /* 6/12/24Mbps are OFDM mandatory rates */
+ if (rate == 12 || rate == 24 || rate == 48)
+ ofdm = i;
+ }
+
+ rt->info[i].dot11Rate = rs->rs_rates[i];
+ rt->info[i].rateKbps = rate * 500;
+
+ for (j = i; j >= 0; --j)
+ if (rt->info[j].phy == rt->info[i].phy &&
+ (rt->info[j].dot11Rate & IEEE80211_RATE_BASIC)) {
+ /*
+ * Basic rate and same PHY type
+ */
+ rt->info[i].ctlRateIndex = j;
+ break;
+ }
+ if (j < 0) {
+ switch (rt->info[i].phy) {
+ case IEEE80211_T_CCK:
+ rt->info[i].ctlRateIndex = i;
+ break;
+ case IEEE80211_T_PBCC:
+ rt->info[i].ctlRateIndex = cck < 0 ? i : cck;
+ break;
+ case IEEE80211_T_OFDM:
+ rt->info[i].ctlRateIndex = ofdm < 0 ? i : ofdm;
+ break;
+ default:
+ panic("unknown phy %d\n", rt->info[i].phy);
+ break;
+ }
+ }
+ }
+ ieee80211_setup_ratetable(rt);
+
+ for (i = 0; i < rt->rateCount; ++i) {
+ printf("phy %d, rate 0x%02x %u, ctlIdx %d\n",
+ rt->info[i].phy,
+ rt->info[i].dot11Rate, rt->info[i].rateKbps,
+ rt->info[i].ctlRateIndex);
+ }
+}
+
+void
+ieee80211_phy_detach(struct ieee80211com *ic)
+{
+ ic->ic_currates = NULL;
+ ieee80211_free_dynratetable(ic);
+}
==== //depot/projects/wifi/sys/net80211/ieee80211_phy.h#5 (text+ko) ====
@@ -30,14 +30,17 @@
#ifdef _KERNEL
+struct ieee80211com;
struct ieee80211_channel;
struct ieee80211_rate_table;
-/* Initialization functions */
void ieee80211_phy_init(void);
+void ieee80211_phy_detach(struct ieee80211com *);
const struct ieee80211_rate_table *ieee80211_get_ratetable(
const struct ieee80211_channel *);
-
+void ieee80211_free_dynratetable(struct ieee80211com *);
+void ieee80211_set_dynratetable(struct ieee80211com *,
+ const struct ieee80211_channel *);
uint16_t ieee80211_ack_duration(const struct ieee80211_rate_table *,
uint8_t, int);
uint16_t ieee80211_compute_duration(const struct ieee80211_rate_table *,
==== //depot/projects/wifi/sys/net80211/ieee80211_proto.c#66 (text+ko) ====
@@ -44,6 +44,7 @@
#include <net/ethernet.h> /* XXX for ether_sprintf */
#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_phy.h>
/* XXX tunables */
#define AGGRESSIVE_MODE_SWITCH_HYSTERESIS 3 /* pkts / 100ms */
@@ -937,6 +938,10 @@
{
struct ieee80211_channel *chan;
+ KASSERT(ic->ic_opmode == IEEE80211_M_STA,
+ ("dynamic turbo switching in non-STA opmode(%d)\n",
+ ic->ic_opmode));
+
chan = ieee80211_find_channel(ic, ic->ic_bsschan->ic_freq, newflags);
if (chan == NULL) { /* XXX should not happen */
IEEE80211_DPRINTF(ic, IEEE80211_MSG_SUPERG,
@@ -953,7 +958,9 @@
ic->ic_bsschan = chan;
ic->ic_prevchan = ic->ic_curchan;
- ieee80211_set_channel(ic, chan);
+ ieee80211_free_dynratetable(ic);
+ ieee80211_set_dynratetable(ic, chan);
+ ieee80211_set_channel(ic, chan, 1);
/* NB: do not need to reset ERP state 'cuz we're in sta mode */
}
==== //depot/projects/wifi/sys/net80211/ieee80211_scan.c#21 (text+ko) ====
@@ -734,7 +734,7 @@
/*
* Potentially change channel and phy mode.
*/
- ieee80211_set_channel(ic, chan);
+ ieee80211_set_channel(ic, chan, 0);
/*
* Scan curchan. Drivers for "intelligent hardware"
@@ -759,8 +759,11 @@
ic->ic_lastscan = ticks;
/* return to the bss channel */
if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
- ic->ic_curchan != ic->ic_bsschan)
- ieee80211_set_channel(ic, ic->ic_bsschan);
+ ic->ic_curchan != ic->ic_bsschan) {
+ ieee80211_set_channel(ic, ic->ic_bsschan,
+ ic->ic_opmode == IEEE80211_M_STA &&
+ ic->ic_state == IEEE80211_S_RUN);
+ }
/* clear internal flags and any indication of a pick */
SCAN_PRIVATE(ss)->ss_iflags &= ~ISCAN_REP;
ss->ss_flags &= ~IEEE80211_SCAN_GOTPICK;
==== //depot/projects/wifi/sys/net80211/ieee80211_var.h#66 (text+ko) ====
@@ -148,6 +148,8 @@
uint8_t ic_chan_scan[IEEE80211_CHAN_BYTES];
/* current channel ratetable */
const struct ieee80211_rate_table *ic_currates;
+ /* negociated rate table */
+ struct ieee80211_rate_table *ic_dynrates;
struct ieee80211_channel *ic_curchan; /* current channel */
struct ieee80211_channel *ic_bsschan; /* bss channel */
struct ieee80211_channel *ic_prevchan; /* previous channel */
@@ -432,7 +434,7 @@
int ieee80211_setmode(struct ieee80211com *, enum ieee80211_phymode);
enum ieee80211_phymode ieee80211_chan2mode(const struct ieee80211_channel *);
void ieee80211_set_channel(struct ieee80211com *,
- struct ieee80211_channel *);
+ struct ieee80211_channel *, int);
void ieee80211_update_curchan(struct ieee80211com *,
struct ieee80211_channel *);
More information about the p4-projects
mailing list