aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorNick Kossifidis <mickflemm@gmail.com>2010-11-23 14:12:23 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-11-30 13:53:21 -0500
commit61cde037234c4b8e6497a23f5f236c64cbf9d41d (patch)
treeca988a018dc9d9e4f433f273d48d4ebe517eeec0 /drivers/net
parent3017fcab416d8d1ee48ca16aa9a3062f600dab8e (diff)
ath5k: Extend rate_duration
* Extend ieee80211_generic_frame_duration to support the various bwmodes. * Better document what's going on with ack bitrates and update write_rate_duration to support the standard ack bitrates (when we don't set the high bit). * Get rid of set_ack_bitrate_high and introduce a flag on ath5k_hw for this (we only called the function on init anyway so there is no difference). Signed-off-by: Nick Kossifidis <mickflemm@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/ath/ath5k/ath5k.h12
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c4
-rw-r--r--drivers/net/wireless/ath/ath5k/pcu.c159
3 files changed, 129 insertions, 46 deletions
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
index e11fc8f3919..7df5b46ab69 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -267,6 +267,15 @@
267#define AR5K_INIT_SIFS_HALF_RATE 32 267#define AR5K_INIT_SIFS_HALF_RATE 32
268#define AR5K_INIT_SIFS_QUARTER_RATE 64 268#define AR5K_INIT_SIFS_QUARTER_RATE 64
269 269
270/* Used to calculate tx time for non 5/10/40MHz
271 * operation */
272/* It's preamble time + signal time (16 + 4) */
273#define AR5K_INIT_OFDM_PREAMPLE_TIME 20
274/* Preamble time for 40MHz (turbo) operation (min ?) */
275#define AR5K_INIT_OFDM_PREAMBLE_TIME_MIN 14
276#define AR5K_INIT_OFDM_SYMBOL_TIME 4
277#define AR5K_INIT_OFDM_PLCP_BITS 22
278
270/* Rx latency for 5 and 10MHz operation (max ?) */ 279/* Rx latency for 5 and 10MHz operation (max ?) */
271#define AR5K_INIT_RX_LAT_MAX 63 280#define AR5K_INIT_RX_LAT_MAX 63
272/* Tx latencies from initvals (5212 only but no problem 281/* Tx latencies from initvals (5212 only but no problem
@@ -1083,6 +1092,7 @@ struct ath5k_hw {
1083 1092
1084 u32 ah_limit_tx_retries; 1093 u32 ah_limit_tx_retries;
1085 u8 ah_coverage_class; 1094 u8 ah_coverage_class;
1095 bool ah_ack_bitrate_high;
1086 u8 ah_bwmode; 1096 u8 ah_bwmode;
1087 1097
1088 /* Antenna Control */ 1098 /* Antenna Control */
@@ -1248,8 +1258,6 @@ void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64);
1248void ath5k_hw_reset_tsf(struct ath5k_hw *ah); 1258void ath5k_hw_reset_tsf(struct ath5k_hw *ah);
1249void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval); 1259void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval);
1250bool ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval); 1260bool ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval);
1251/* ACK bit rate */
1252void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high);
1253/* Init function */ 1261/* Init function */
1254void ath5k_hw_pcu_init(struct ath5k_hw *ah, enum nl80211_iftype op_mode, 1262void ath5k_hw_pcu_init(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
1255 u8 mode); 1263 u8 mode);
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 9af7e461a23..526d8bc412c 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -2420,7 +2420,9 @@ ath5k_init(struct ath5k_softc *sc)
2420 for (i = 0; i < common->keymax; i++) 2420 for (i = 0; i < common->keymax; i++)
2421 ath_hw_keyreset(common, (u16) i); 2421 ath_hw_keyreset(common, (u16) i);
2422 2422
2423 ath5k_hw_set_ack_bitrate_high(ah, true); 2423 /* Use higher rates for acks instead of base
2424 * rate */
2425 ah->ah_ack_bitrate_high = true;
2424 2426
2425 for (i = 0; i < ARRAY_SIZE(sc->bslot); i++) 2427 for (i = 0; i < ARRAY_SIZE(sc->bslot); i++)
2426 sc->bslot[i] = NULL; 2428 sc->bslot[i] = NULL;
diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c
index 2118f7048f3..e7f6be9cdf1 100644
--- a/drivers/net/wireless/ath/ath5k/pcu.c
+++ b/drivers/net/wireless/ath/ath5k/pcu.c
@@ -31,11 +31,100 @@
31#include "debug.h" 31#include "debug.h"
32#include "base.h" 32#include "base.h"
33 33
34/*
35 * AR5212+ can use higher rates for ack transmition
36 * based on current tx rate instead of the base rate.
37 * It does this to better utilize channel usage.
38 * This is a mapping between G rates (that cover both
39 * CCK and OFDM) and ack rates that we use when setting
40 * rate -> duration table. This mapping is hw-based so
41 * don't change anything.
42 *
43 * To enable this functionality we must set
44 * ah->ah_ack_bitrate_high to true else base rate is
45 * used (1Mb for CCK, 6Mb for OFDM).
46 */
47static const unsigned int ack_rates_high[] =
48/* Tx -> ACK */
49/* 1Mb -> 1Mb */ { 0,
50/* 2MB -> 2Mb */ 1,
51/* 5.5Mb -> 2Mb */ 1,
52/* 11Mb -> 2Mb */ 1,
53/* 6Mb -> 6Mb */ 4,
54/* 9Mb -> 6Mb */ 4,
55/* 12Mb -> 12Mb */ 6,
56/* 18Mb -> 12Mb */ 6,
57/* 24Mb -> 24Mb */ 8,
58/* 36Mb -> 24Mb */ 8,
59/* 48Mb -> 24Mb */ 8,
60/* 54Mb -> 24Mb */ 8 };
61
34/*******************\ 62/*******************\
35* Helper functions * 63* Helper functions *
36\*******************/ 64\*******************/
37 65
38/** 66/**
67 * ath5k_hw_get_frame_duration - Get tx time of a frame
68 *
69 * @ah: The &struct ath5k_hw
70 * @len: Frame's length in bytes
71 * @rate: The @struct ieee80211_rate
72 *
73 * Calculate tx duration of a frame given it's rate and length
74 * It extends ieee80211_generic_frame_duration for non standard
75 * bwmodes.
76 */
77int ath5k_hw_get_frame_duration(struct ath5k_hw *ah,
78 int len, struct ieee80211_rate *rate)
79{
80 struct ath5k_softc *sc = ah->ah_sc;
81 int sifs, preamble, plcp_bits, sym_time;
82 int bitrate, bits, symbols, symbol_bits;
83 int dur;
84
85 /* Fallback */
86 if (!ah->ah_bwmode) {
87 dur = ieee80211_generic_frame_duration(sc->hw,
88 NULL, len, rate);
89 return dur;
90 }
91
92 bitrate = rate->bitrate;
93 preamble = AR5K_INIT_OFDM_PREAMPLE_TIME;
94 plcp_bits = AR5K_INIT_OFDM_PLCP_BITS;
95 sym_time = AR5K_INIT_OFDM_SYMBOL_TIME;
96
97 switch (ah->ah_bwmode) {
98 case AR5K_BWMODE_40MHZ:
99 sifs = AR5K_INIT_SIFS_TURBO;
100 preamble = AR5K_INIT_OFDM_PREAMBLE_TIME_MIN;
101 break;
102 case AR5K_BWMODE_10MHZ:
103 sifs = AR5K_INIT_SIFS_HALF_RATE;
104 preamble *= 2;
105 sym_time *= 2;
106 break;
107 case AR5K_BWMODE_5MHZ:
108 sifs = AR5K_INIT_SIFS_QUARTER_RATE;
109 preamble *= 4;
110 sym_time *= 4;
111 break;
112 default:
113 sifs = AR5K_INIT_SIFS_DEFAULT_BG;
114 break;
115 }
116
117 bits = plcp_bits + (len << 3);
118 /* Bit rate is in 100Kbits */
119 symbol_bits = bitrate * sym_time;
120 symbols = DIV_ROUND_UP(bits * 10, symbol_bits);
121
122 dur = sifs + preamble + (sym_time * symbols);
123
124 return dur;
125}
126
127/**
39 * ath5k_hw_get_default_slottime - Get the default slot time for current mode 128 * ath5k_hw_get_default_slottime - Get the default slot time for current mode
40 * 129 *
41 * @ah: The &struct ath5k_hw 130 * @ah: The &struct ath5k_hw
@@ -120,43 +209,11 @@ void ath5k_hw_update_mib_counters(struct ath5k_hw *ah)
120 stats->beacons += ath5k_hw_reg_read(ah, AR5K_BEACON_CNT); 209 stats->beacons += ath5k_hw_reg_read(ah, AR5K_BEACON_CNT);
121} 210}
122 211
123/**
124 * ath5k_hw_set_ack_bitrate - set bitrate for ACKs
125 *
126 * @ah: The &struct ath5k_hw
127 * @high: Flag to determine if we want to use high transmission rate
128 * for ACKs or not
129 *
130 * If high flag is set, we tell hw to use a set of control rates based on
131 * the current transmission rate (check out control_rates array inside reset.c).
132 * If not hw just uses the lowest rate available for the current modulation
133 * scheme being used (1Mbit for CCK and 6Mbits for OFDM).
134 */
135void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high)
136{
137 if (ah->ah_version != AR5K_AR5212)
138 return;
139 else {
140 u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB;
141 if (high)
142 AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val);
143 else
144 AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val);
145 }
146}
147
148 212
149/******************\ 213/******************\
150* ACK/CTS Timeouts * 214* ACK/CTS Timeouts *
151\******************/ 215\******************/
152 216
153/*
154 * index into rates for control rates, we can set it up like this because
155 * this is only used for AR5212 and we know it supports G mode
156 */
157static const unsigned int control_rates[] =
158 { 0, 1, 1, 1, 4, 4, 6, 6, 8, 8, 8, 8 };
159
160/** 217/**
161 * ath5k_hw_write_rate_duration - fill rate code to duration table 218 * ath5k_hw_write_rate_duration - fill rate code to duration table
162 * 219 *
@@ -164,7 +221,7 @@ static const unsigned int control_rates[] =
164 * @mode: one of enum ath5k_driver_mode 221 * @mode: one of enum ath5k_driver_mode
165 * 222 *
166 * Write the rate code to duration table upon hw reset. This is a helper for 223 * Write the rate code to duration table upon hw reset. This is a helper for
167 * ath5k_hw_reset(). It seems all this is doing is setting an ACK timeout on 224 * ath5k_hw_pcu_init(). It seems all this is doing is setting an ACK timeout on
168 * the hardware, based on current mode, for each rate. The rates which are 225 * the hardware, based on current mode, for each rate. The rates which are
169 * capable of short preamble (802.11b rates 2Mbps, 5.5Mbps, and 11Mbps) have 226 * capable of short preamble (802.11b rates 2Mbps, 5.5Mbps, and 11Mbps) have
170 * different rate code so we write their value twice (one for long preamble 227 * different rate code so we write their value twice (one for long preamble
@@ -172,23 +229,30 @@ static const unsigned int control_rates[] =
172 * 229 *
173 * Note: Band doesn't matter here, if we set the values for OFDM it works 230 * Note: Band doesn't matter here, if we set the values for OFDM it works
174 * on both a and g modes. So all we have to do is set values for all g rates 231 * on both a and g modes. So all we have to do is set values for all g rates
175 * that include all OFDM and CCK rates. If we operate in turbo or xr/half/ 232 * that include all OFDM and CCK rates.
176 * quarter rate mode, we need to use another set of bitrates (that's why we 233 *
177 * need the mode parameter) but we don't handle these proprietary modes yet.
178 */ 234 */
179static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah, 235static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah)
180 unsigned int mode)
181{ 236{
182 struct ath5k_softc *sc = ah->ah_sc; 237 struct ath5k_softc *sc = ah->ah_sc;
183 struct ieee80211_rate *rate; 238 struct ieee80211_rate *rate;
184 unsigned int i; 239 unsigned int i;
240 /* 802.11g covers both OFDM and CCK */
241 u8 band = IEEE80211_BAND_2GHZ;
185 242
186 /* Write rate duration table */ 243 /* Write rate duration table */
187 for (i = 0; i < sc->sbands[IEEE80211_BAND_2GHZ].n_bitrates; i++) { 244 for (i = 0; i < sc->sbands[band].n_bitrates; i++) {
188 u32 reg; 245 u32 reg;
189 u16 tx_time; 246 u16 tx_time;
190 247
191 rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[control_rates[i]]; 248 if (ah->ah_ack_bitrate_high)
249 rate = &sc->sbands[band].bitrates[ack_rates_high[i]];
250 /* CCK -> 1Mb */
251 else if (i < 4)
252 rate = &sc->sbands[band].bitrates[0];
253 /* OFDM -> 6Mb */
254 else
255 rate = &sc->sbands[band].bitrates[4];
192 256
193 /* Set ACK timeout */ 257 /* Set ACK timeout */
194 reg = AR5K_RATE_DUR(rate->hw_value); 258 reg = AR5K_RATE_DUR(rate->hw_value);
@@ -199,8 +263,9 @@ static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah,
199 * actual rate for this rate. See mac80211 tx.c 263 * actual rate for this rate. See mac80211 tx.c
200 * ieee80211_duration() for a brief description of 264 * ieee80211_duration() for a brief description of
201 * what rate we should choose to TX ACKs. */ 265 * what rate we should choose to TX ACKs. */
202 tx_time = le16_to_cpu(ieee80211_generic_frame_duration(sc->hw, 266 tx_time = ath5k_hw_get_frame_duration(ah, 10, rate);
203 NULL, 10, rate)); 267
268 tx_time = le16_to_cpu(tx_time);
204 269
205 ath5k_hw_reg_write(ah, tx_time, reg); 270 ath5k_hw_reg_write(ah, tx_time, reg);
206 271
@@ -835,7 +900,7 @@ void ath5k_hw_pcu_init(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
835 * mac80211 are integrated */ 900 * mac80211 are integrated */
836 if (ah->ah_version == AR5K_AR5212 && 901 if (ah->ah_version == AR5K_AR5212 &&
837 ah->ah_sc->nvifs) 902 ah->ah_sc->nvifs)
838 ath5k_hw_write_rate_duration(ah, mode); 903 ath5k_hw_write_rate_duration(ah);
839 904
840 /* Set RSSI/BRSSI thresholds 905 /* Set RSSI/BRSSI thresholds
841 * 906 *
@@ -869,5 +934,13 @@ void ath5k_hw_pcu_init(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
869 if (ah->ah_coverage_class > 0) 934 if (ah->ah_coverage_class > 0)
870 ath5k_hw_set_coverage_class(ah, ah->ah_coverage_class); 935 ath5k_hw_set_coverage_class(ah, ah->ah_coverage_class);
871 936
937 /* Set ACK bitrate mode (see ack_rates_high) */
938 if (ah->ah_version == AR5K_AR5212) {
939 u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB;
940 if (ah->ah_ack_bitrate_high)
941 AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val);
942 else
943 AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val);
944 }
872 return; 945 return;
873} 946}