From owner-p4-projects@FreeBSD.ORG Mon Feb 11 10:43:12 2008 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 24BD616A49C; Mon, 11 Feb 2008 10:43:12 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id D61EA16A420 for ; Mon, 11 Feb 2008 10:43:11 +0000 (UTC) (envelope-from sephe@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id BD79913C4CE for ; Mon, 11 Feb 2008 10:43:11 +0000 (UTC) (envelope-from sephe@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.1/8.14.1) with ESMTP id m1BAhBZl081079 for ; Mon, 11 Feb 2008 10:43:11 GMT (envelope-from sephe@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.1/8.14.1/Submit) id m1BAhBmG081075 for perforce@freebsd.org; Mon, 11 Feb 2008 10:43:11 GMT (envelope-from sephe@FreeBSD.org) Date: Mon, 11 Feb 2008 10:43:11 GMT Message-Id: <200802111043.m1BAhBmG081075@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to sephe@FreeBSD.org using -f From: Sepherosa Ziehau To: Perforce Change Reviews Cc: Subject: PERFORCE change 135207 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 11 Feb 2008 10:43:12 -0000 http://perforce.freebsd.org/chv.cgi?CH=135207 Change 135207 by sephe@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 #include +#include #include @@ -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 /* XXX for ether_sprintf */ #include +#include /* 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 *);