diff options
author | Nick Kossifidis <mickflemm@gmail.com> | 2010-11-23 14:12:23 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-11-30 13:53:21 -0500 |
commit | 61cde037234c4b8e6497a23f5f236c64cbf9d41d (patch) | |
tree | ca988a018dc9d9e4f433f273d48d4ebe517eeec0 /drivers/net | |
parent | 3017fcab416d8d1ee48ca16aa9a3062f600dab8e (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.h | 12 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/base.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/pcu.c | 159 |
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); | |||
1248 | void ath5k_hw_reset_tsf(struct ath5k_hw *ah); | 1258 | void ath5k_hw_reset_tsf(struct ath5k_hw *ah); |
1249 | void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval); | 1259 | void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval); |
1250 | bool ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval); | 1260 | bool ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval); |
1251 | /* ACK bit rate */ | ||
1252 | void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high); | ||
1253 | /* Init function */ | 1261 | /* Init function */ |
1254 | void ath5k_hw_pcu_init(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | 1262 | void 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 | */ | ||
47 | static 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 | */ | ||
77 | int 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 | */ | ||
135 | void 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 | */ | ||
157 | static 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 | */ |
179 | static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah, | 235 | static 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 | } |