diff options
author | David S. Miller <davem@davemloft.net> | 2010-01-19 14:43:42 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-01-19 14:43:42 -0500 |
commit | 6373464288cab09bc641be301d8d30fc9f64ba71 (patch) | |
tree | c1bc92dc630aa15da2e12bc0d09c92169817a702 /drivers/net/wireless/ath/ath5k | |
parent | 6d955180b2f9ccff444df06265160868cabb289a (diff) | |
parent | 730dd70549e0ec755dd55615ba5cfc38a482a947 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Conflicts:
drivers/net/wireless/iwlwifi/iwl-core.h
Diffstat (limited to 'drivers/net/wireless/ath/ath5k')
-rw-r--r-- | drivers/net/wireless/ath/ath5k/ath5k.h | 24 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/base.c | 22 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/eeprom.c | 32 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/eeprom.h | 8 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/pcu.c | 121 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/qcu.c | 20 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/reset.c | 9 |
7 files changed, 195 insertions, 41 deletions
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 6a2a96761111..66bcb506a112 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h | |||
@@ -1063,6 +1063,7 @@ struct ath5k_hw { | |||
1063 | u32 ah_cw_min; | 1063 | u32 ah_cw_min; |
1064 | u32 ah_cw_max; | 1064 | u32 ah_cw_max; |
1065 | u32 ah_limit_tx_retries; | 1065 | u32 ah_limit_tx_retries; |
1066 | u8 ah_coverage_class; | ||
1066 | 1067 | ||
1067 | /* Antenna Control */ | 1068 | /* Antenna Control */ |
1068 | u32 ah_ant_ctl[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; | 1069 | u32 ah_ant_ctl[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; |
@@ -1200,6 +1201,7 @@ extern bool ath5k_eeprom_is_hb63(struct ath5k_hw *ah); | |||
1200 | 1201 | ||
1201 | /* Protocol Control Unit Functions */ | 1202 | /* Protocol Control Unit Functions */ |
1202 | extern int ath5k_hw_set_opmode(struct ath5k_hw *ah); | 1203 | extern int ath5k_hw_set_opmode(struct ath5k_hw *ah); |
1204 | extern void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class); | ||
1203 | /* BSSID Functions */ | 1205 | /* BSSID Functions */ |
1204 | extern int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac); | 1206 | extern int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac); |
1205 | extern void ath5k_hw_set_associd(struct ath5k_hw *ah); | 1207 | extern void ath5k_hw_set_associd(struct ath5k_hw *ah); |
@@ -1231,6 +1233,10 @@ extern int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout); | |||
1231 | extern unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah); | 1233 | extern unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah); |
1232 | extern int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout); | 1234 | extern int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout); |
1233 | extern unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah); | 1235 | extern unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah); |
1236 | /* Clock rate related functions */ | ||
1237 | unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec); | ||
1238 | unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock); | ||
1239 | unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah); | ||
1234 | /* Key table (WEP) functions */ | 1240 | /* Key table (WEP) functions */ |
1235 | extern int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry); | 1241 | extern int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry); |
1236 | extern int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry); | 1242 | extern int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry); |
@@ -1310,24 +1316,6 @@ extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower); | |||
1310 | * Functions used internaly | 1316 | * Functions used internaly |
1311 | */ | 1317 | */ |
1312 | 1318 | ||
1313 | /* | ||
1314 | * Translate usec to hw clock units | ||
1315 | * TODO: Half/quarter rate | ||
1316 | */ | ||
1317 | static inline unsigned int ath5k_hw_htoclock(unsigned int usec, bool turbo) | ||
1318 | { | ||
1319 | return turbo ? (usec * 80) : (usec * 40); | ||
1320 | } | ||
1321 | |||
1322 | /* | ||
1323 | * Translate hw clock units to usec | ||
1324 | * TODO: Half/quarter rate | ||
1325 | */ | ||
1326 | static inline unsigned int ath5k_hw_clocktoh(unsigned int clock, bool turbo) | ||
1327 | { | ||
1328 | return turbo ? (clock / 80) : (clock / 40); | ||
1329 | } | ||
1330 | |||
1331 | static inline struct ath_common *ath5k_hw_common(struct ath5k_hw *ah) | 1319 | static inline struct ath_common *ath5k_hw_common(struct ath5k_hw *ah) |
1332 | { | 1320 | { |
1333 | return &ah->common; | 1321 | return &ah->common; |
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 72e5ed51c0af..5577bcc80eac 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -254,6 +254,8 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw, | |||
254 | u32 changes); | 254 | u32 changes); |
255 | static void ath5k_sw_scan_start(struct ieee80211_hw *hw); | 255 | static void ath5k_sw_scan_start(struct ieee80211_hw *hw); |
256 | static void ath5k_sw_scan_complete(struct ieee80211_hw *hw); | 256 | static void ath5k_sw_scan_complete(struct ieee80211_hw *hw); |
257 | static void ath5k_set_coverage_class(struct ieee80211_hw *hw, | ||
258 | u8 coverage_class); | ||
257 | 259 | ||
258 | static const struct ieee80211_ops ath5k_hw_ops = { | 260 | static const struct ieee80211_ops ath5k_hw_ops = { |
259 | .tx = ath5k_tx, | 261 | .tx = ath5k_tx, |
@@ -274,6 +276,7 @@ static const struct ieee80211_ops ath5k_hw_ops = { | |||
274 | .bss_info_changed = ath5k_bss_info_changed, | 276 | .bss_info_changed = ath5k_bss_info_changed, |
275 | .sw_scan_start = ath5k_sw_scan_start, | 277 | .sw_scan_start = ath5k_sw_scan_start, |
276 | .sw_scan_complete = ath5k_sw_scan_complete, | 278 | .sw_scan_complete = ath5k_sw_scan_complete, |
279 | .set_coverage_class = ath5k_set_coverage_class, | ||
277 | }; | 280 | }; |
278 | 281 | ||
279 | /* | 282 | /* |
@@ -3262,3 +3265,22 @@ static void ath5k_sw_scan_complete(struct ieee80211_hw *hw) | |||
3262 | ath5k_hw_set_ledstate(sc->ah, sc->assoc ? | 3265 | ath5k_hw_set_ledstate(sc->ah, sc->assoc ? |
3263 | AR5K_LED_ASSOC : AR5K_LED_INIT); | 3266 | AR5K_LED_ASSOC : AR5K_LED_INIT); |
3264 | } | 3267 | } |
3268 | |||
3269 | /** | ||
3270 | * ath5k_set_coverage_class - Set IEEE 802.11 coverage class | ||
3271 | * | ||
3272 | * @hw: struct ieee80211_hw pointer | ||
3273 | * @coverage_class: IEEE 802.11 coverage class number | ||
3274 | * | ||
3275 | * Mac80211 callback. Sets slot time, ACK timeout and CTS timeout for given | ||
3276 | * coverage class. The values are persistent, they are restored after device | ||
3277 | * reset. | ||
3278 | */ | ||
3279 | static void ath5k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class) | ||
3280 | { | ||
3281 | struct ath5k_softc *sc = hw->priv; | ||
3282 | |||
3283 | mutex_lock(&sc->lock); | ||
3284 | ath5k_hw_set_coverage_class(sc->ah, coverage_class); | ||
3285 | mutex_unlock(&sc->lock); | ||
3286 | } | ||
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index 5d1c8677f180..6a3f4da7fb48 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c | |||
@@ -97,7 +97,7 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah) | |||
97 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | 97 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; |
98 | int ret; | 98 | int ret; |
99 | u16 val; | 99 | u16 val; |
100 | u32 cksum, offset; | 100 | u32 cksum, offset, eep_max = AR5K_EEPROM_INFO_MAX; |
101 | 101 | ||
102 | /* | 102 | /* |
103 | * Read values from EEPROM and store them in the capability structure | 103 | * Read values from EEPROM and store them in the capability structure |
@@ -116,12 +116,38 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah) | |||
116 | * Validate the checksum of the EEPROM date. There are some | 116 | * Validate the checksum of the EEPROM date. There are some |
117 | * devices with invalid EEPROMs. | 117 | * devices with invalid EEPROMs. |
118 | */ | 118 | */ |
119 | for (cksum = 0, offset = 0; offset < AR5K_EEPROM_INFO_MAX; offset++) { | 119 | AR5K_EEPROM_READ(AR5K_EEPROM_SIZE_UPPER, val); |
120 | if (val) { | ||
121 | eep_max = (val & AR5K_EEPROM_SIZE_UPPER_MASK) << | ||
122 | AR5K_EEPROM_SIZE_ENDLOC_SHIFT; | ||
123 | AR5K_EEPROM_READ(AR5K_EEPROM_SIZE_LOWER, val); | ||
124 | eep_max = (eep_max | val) - AR5K_EEPROM_INFO_BASE; | ||
125 | |||
126 | /* | ||
127 | * Fail safe check to prevent stupid loops due | ||
128 | * to busted EEPROMs. XXX: This value is likely too | ||
129 | * big still, waiting on a better value. | ||
130 | */ | ||
131 | if (eep_max > (3 * AR5K_EEPROM_INFO_MAX)) { | ||
132 | ATH5K_ERR(ah->ah_sc, "Invalid max custom EEPROM size: " | ||
133 | "%d (0x%04x) max expected: %d (0x%04x)\n", | ||
134 | eep_max, eep_max, | ||
135 | 3 * AR5K_EEPROM_INFO_MAX, | ||
136 | 3 * AR5K_EEPROM_INFO_MAX); | ||
137 | return -EIO; | ||
138 | } | ||
139 | } | ||
140 | |||
141 | for (cksum = 0, offset = 0; offset < eep_max; offset++) { | ||
120 | AR5K_EEPROM_READ(AR5K_EEPROM_INFO(offset), val); | 142 | AR5K_EEPROM_READ(AR5K_EEPROM_INFO(offset), val); |
121 | cksum ^= val; | 143 | cksum ^= val; |
122 | } | 144 | } |
123 | if (cksum != AR5K_EEPROM_INFO_CKSUM) { | 145 | if (cksum != AR5K_EEPROM_INFO_CKSUM) { |
124 | ATH5K_ERR(ah->ah_sc, "Invalid EEPROM checksum 0x%04x\n", cksum); | 146 | ATH5K_ERR(ah->ah_sc, "Invalid EEPROM " |
147 | "checksum: 0x%04x eep_max: 0x%04x (%s)\n", | ||
148 | cksum, eep_max, | ||
149 | eep_max == AR5K_EEPROM_INFO_MAX ? | ||
150 | "default size" : "custom size"); | ||
125 | return -EIO; | 151 | return -EIO; |
126 | } | 152 | } |
127 | 153 | ||
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.h b/drivers/net/wireless/ath/ath5k/eeprom.h index 0123f3521a0b..473a483bb9c3 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.h +++ b/drivers/net/wireless/ath/ath5k/eeprom.h | |||
@@ -37,6 +37,14 @@ | |||
37 | #define AR5K_EEPROM_RFKILL_POLARITY_S 1 | 37 | #define AR5K_EEPROM_RFKILL_POLARITY_S 1 |
38 | 38 | ||
39 | #define AR5K_EEPROM_REG_DOMAIN 0x00bf /* EEPROM regdom */ | 39 | #define AR5K_EEPROM_REG_DOMAIN 0x00bf /* EEPROM regdom */ |
40 | |||
41 | /* FLASH(EEPROM) Defines for AR531X chips */ | ||
42 | #define AR5K_EEPROM_SIZE_LOWER 0x1b /* size info -- lower */ | ||
43 | #define AR5K_EEPROM_SIZE_UPPER 0x1c /* size info -- upper */ | ||
44 | #define AR5K_EEPROM_SIZE_UPPER_MASK 0xfff0 | ||
45 | #define AR5K_EEPROM_SIZE_UPPER_SHIFT 4 | ||
46 | #define AR5K_EEPROM_SIZE_ENDLOC_SHIFT 12 | ||
47 | |||
40 | #define AR5K_EEPROM_CHECKSUM 0x00c0 /* EEPROM checksum */ | 48 | #define AR5K_EEPROM_CHECKSUM 0x00c0 /* EEPROM checksum */ |
41 | #define AR5K_EEPROM_INFO_BASE 0x00c0 /* EEPROM header */ | 49 | #define AR5K_EEPROM_INFO_BASE 0x00c0 /* EEPROM header */ |
42 | #define AR5K_EEPROM_INFO_MAX (0x400 - AR5K_EEPROM_INFO_BASE) | 50 | #define AR5K_EEPROM_INFO_MAX (0x400 - AR5K_EEPROM_INFO_BASE) |
diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index 64fc1eb9b6d9..aefe84f9c04b 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c | |||
@@ -187,8 +187,8 @@ unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah) | |||
187 | { | 187 | { |
188 | ATH5K_TRACE(ah->ah_sc); | 188 | ATH5K_TRACE(ah->ah_sc); |
189 | 189 | ||
190 | return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah, | 190 | return ath5k_hw_clocktoh(ah, AR5K_REG_MS(ath5k_hw_reg_read(ah, |
191 | AR5K_TIME_OUT), AR5K_TIME_OUT_ACK), ah->ah_turbo); | 191 | AR5K_TIME_OUT), AR5K_TIME_OUT_ACK)); |
192 | } | 192 | } |
193 | 193 | ||
194 | /** | 194 | /** |
@@ -200,12 +200,12 @@ unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah) | |||
200 | int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) | 200 | int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) |
201 | { | 201 | { |
202 | ATH5K_TRACE(ah->ah_sc); | 202 | ATH5K_TRACE(ah->ah_sc); |
203 | if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK), | 203 | if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK)) |
204 | ah->ah_turbo) <= timeout) | 204 | <= timeout) |
205 | return -EINVAL; | 205 | return -EINVAL; |
206 | 206 | ||
207 | AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_ACK, | 207 | AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_ACK, |
208 | ath5k_hw_htoclock(timeout, ah->ah_turbo)); | 208 | ath5k_hw_htoclock(ah, timeout)); |
209 | 209 | ||
210 | return 0; | 210 | return 0; |
211 | } | 211 | } |
@@ -218,8 +218,8 @@ int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) | |||
218 | unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah) | 218 | unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah) |
219 | { | 219 | { |
220 | ATH5K_TRACE(ah->ah_sc); | 220 | ATH5K_TRACE(ah->ah_sc); |
221 | return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah, | 221 | return ath5k_hw_clocktoh(ah, AR5K_REG_MS(ath5k_hw_reg_read(ah, |
222 | AR5K_TIME_OUT), AR5K_TIME_OUT_CTS), ah->ah_turbo); | 222 | AR5K_TIME_OUT), AR5K_TIME_OUT_CTS)); |
223 | } | 223 | } |
224 | 224 | ||
225 | /** | 225 | /** |
@@ -231,17 +231,97 @@ unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah) | |||
231 | int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout) | 231 | int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout) |
232 | { | 232 | { |
233 | ATH5K_TRACE(ah->ah_sc); | 233 | ATH5K_TRACE(ah->ah_sc); |
234 | if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS), | 234 | if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS)) |
235 | ah->ah_turbo) <= timeout) | 235 | <= timeout) |
236 | return -EINVAL; | 236 | return -EINVAL; |
237 | 237 | ||
238 | AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_CTS, | 238 | AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_CTS, |
239 | ath5k_hw_htoclock(timeout, ah->ah_turbo)); | 239 | ath5k_hw_htoclock(ah, timeout)); |
240 | 240 | ||
241 | return 0; | 241 | return 0; |
242 | } | 242 | } |
243 | 243 | ||
244 | /** | 244 | /** |
245 | * ath5k_hw_htoclock - Translate usec to hw clock units | ||
246 | * | ||
247 | * @ah: The &struct ath5k_hw | ||
248 | * @usec: value in microseconds | ||
249 | */ | ||
250 | unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec) | ||
251 | { | ||
252 | return usec * ath5k_hw_get_clockrate(ah); | ||
253 | } | ||
254 | |||
255 | /** | ||
256 | * ath5k_hw_clocktoh - Translate hw clock units to usec | ||
257 | * @clock: value in hw clock units | ||
258 | */ | ||
259 | unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock) | ||
260 | { | ||
261 | return clock / ath5k_hw_get_clockrate(ah); | ||
262 | } | ||
263 | |||
264 | /** | ||
265 | * ath5k_hw_get_clockrate - Get the clock rate for current mode | ||
266 | * | ||
267 | * @ah: The &struct ath5k_hw | ||
268 | */ | ||
269 | unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah) | ||
270 | { | ||
271 | struct ieee80211_channel *channel = ah->ah_current_channel; | ||
272 | int clock; | ||
273 | |||
274 | if (channel->hw_value & CHANNEL_5GHZ) | ||
275 | clock = 40; /* 802.11a */ | ||
276 | else if (channel->hw_value & CHANNEL_CCK) | ||
277 | clock = 22; /* 802.11b */ | ||
278 | else | ||
279 | clock = 44; /* 802.11g */ | ||
280 | |||
281 | /* Clock rate in turbo modes is twice the normal rate */ | ||
282 | if (channel->hw_value & CHANNEL_TURBO) | ||
283 | clock *= 2; | ||
284 | |||
285 | return clock; | ||
286 | } | ||
287 | |||
288 | /** | ||
289 | * ath5k_hw_get_default_slottime - Get the default slot time for current mode | ||
290 | * | ||
291 | * @ah: The &struct ath5k_hw | ||
292 | */ | ||
293 | unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah) | ||
294 | { | ||
295 | struct ieee80211_channel *channel = ah->ah_current_channel; | ||
296 | |||
297 | if (channel->hw_value & CHANNEL_TURBO) | ||
298 | return 6; /* both turbo modes */ | ||
299 | |||
300 | if (channel->hw_value & CHANNEL_CCK) | ||
301 | return 20; /* 802.11b */ | ||
302 | |||
303 | return 9; /* 802.11 a/g */ | ||
304 | } | ||
305 | |||
306 | /** | ||
307 | * ath5k_hw_get_default_sifs - Get the default SIFS for current mode | ||
308 | * | ||
309 | * @ah: The &struct ath5k_hw | ||
310 | */ | ||
311 | unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah) | ||
312 | { | ||
313 | struct ieee80211_channel *channel = ah->ah_current_channel; | ||
314 | |||
315 | if (channel->hw_value & CHANNEL_TURBO) | ||
316 | return 8; /* both turbo modes */ | ||
317 | |||
318 | if (channel->hw_value & CHANNEL_5GHZ) | ||
319 | return 16; /* 802.11a */ | ||
320 | |||
321 | return 10; /* 802.11 b/g */ | ||
322 | } | ||
323 | |||
324 | /** | ||
245 | * ath5k_hw_set_lladdr - Set station id | 325 | * ath5k_hw_set_lladdr - Set station id |
246 | * | 326 | * |
247 | * @ah: The &struct ath5k_hw | 327 | * @ah: The &struct ath5k_hw |
@@ -1050,3 +1130,24 @@ int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac) | |||
1050 | return 0; | 1130 | return 0; |
1051 | } | 1131 | } |
1052 | 1132 | ||
1133 | /** | ||
1134 | * ath5k_hw_set_coverage_class - Set IEEE 802.11 coverage class | ||
1135 | * | ||
1136 | * @ah: The &struct ath5k_hw | ||
1137 | * @coverage_class: IEEE 802.11 coverage class number | ||
1138 | * | ||
1139 | * Sets slot time, ACK timeout and CTS timeout for given coverage class. | ||
1140 | */ | ||
1141 | void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class) | ||
1142 | { | ||
1143 | /* As defined by IEEE 802.11-2007 17.3.8.6 */ | ||
1144 | int slot_time = ath5k_hw_get_default_slottime(ah) + 3 * coverage_class; | ||
1145 | int ack_timeout = ath5k_hw_get_default_sifs(ah) + slot_time; | ||
1146 | int cts_timeout = ack_timeout; | ||
1147 | |||
1148 | ath5k_hw_set_slot_time(ah, slot_time); | ||
1149 | ath5k_hw_set_ack_timeout(ah, ack_timeout); | ||
1150 | ath5k_hw_set_cts_timeout(ah, cts_timeout); | ||
1151 | |||
1152 | ah->ah_coverage_class = coverage_class; | ||
1153 | } | ||
diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c index eeebb9aef206..abe36c0d139c 100644 --- a/drivers/net/wireless/ath/ath5k/qcu.c +++ b/drivers/net/wireless/ath/ath5k/qcu.c | |||
@@ -520,12 +520,16 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | |||
520 | */ | 520 | */ |
521 | unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah) | 521 | unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah) |
522 | { | 522 | { |
523 | unsigned int slot_time_clock; | ||
524 | |||
523 | ATH5K_TRACE(ah->ah_sc); | 525 | ATH5K_TRACE(ah->ah_sc); |
526 | |||
524 | if (ah->ah_version == AR5K_AR5210) | 527 | if (ah->ah_version == AR5K_AR5210) |
525 | return ath5k_hw_clocktoh(ath5k_hw_reg_read(ah, | 528 | slot_time_clock = ath5k_hw_reg_read(ah, AR5K_SLOT_TIME); |
526 | AR5K_SLOT_TIME) & 0xffff, ah->ah_turbo); | ||
527 | else | 529 | else |
528 | return ath5k_hw_reg_read(ah, AR5K_DCU_GBL_IFS_SLOT) & 0xffff; | 530 | slot_time_clock = ath5k_hw_reg_read(ah, AR5K_DCU_GBL_IFS_SLOT); |
531 | |||
532 | return ath5k_hw_clocktoh(ah, slot_time_clock & 0xffff); | ||
529 | } | 533 | } |
530 | 534 | ||
531 | /* | 535 | /* |
@@ -533,15 +537,17 @@ unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah) | |||
533 | */ | 537 | */ |
534 | int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time) | 538 | int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time) |
535 | { | 539 | { |
540 | u32 slot_time_clock = ath5k_hw_htoclock(ah, slot_time); | ||
541 | |||
536 | ATH5K_TRACE(ah->ah_sc); | 542 | ATH5K_TRACE(ah->ah_sc); |
537 | if (slot_time < AR5K_SLOT_TIME_9 || slot_time > AR5K_SLOT_TIME_MAX) | 543 | |
544 | if (slot_time < 6 || slot_time_clock > AR5K_SLOT_TIME_MAX) | ||
538 | return -EINVAL; | 545 | return -EINVAL; |
539 | 546 | ||
540 | if (ah->ah_version == AR5K_AR5210) | 547 | if (ah->ah_version == AR5K_AR5210) |
541 | ath5k_hw_reg_write(ah, ath5k_hw_htoclock(slot_time, | 548 | ath5k_hw_reg_write(ah, slot_time_clock, AR5K_SLOT_TIME); |
542 | ah->ah_turbo), AR5K_SLOT_TIME); | ||
543 | else | 549 | else |
544 | ath5k_hw_reg_write(ah, slot_time, AR5K_DCU_GBL_IFS_SLOT); | 550 | ath5k_hw_reg_write(ah, slot_time_clock, AR5K_DCU_GBL_IFS_SLOT); |
545 | 551 | ||
546 | return 0; | 552 | return 0; |
547 | } | 553 | } |
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index 62954fc77869..6690923fd78c 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c | |||
@@ -60,12 +60,11 @@ static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah, | |||
60 | !(channel->hw_value & CHANNEL_OFDM)); | 60 | !(channel->hw_value & CHANNEL_OFDM)); |
61 | 61 | ||
62 | /* Get coefficient | 62 | /* Get coefficient |
63 | * ALGO: coef = (5 * clock * carrier_freq) / 2) | 63 | * ALGO: coef = (5 * clock / carrier_freq) / 2 |
64 | * we scale coef by shifting clock value by 24 for | 64 | * we scale coef by shifting clock value by 24 for |
65 | * better precision since we use integers */ | 65 | * better precision since we use integers */ |
66 | /* TODO: Half/quarter rate */ | 66 | /* TODO: Half/quarter rate */ |
67 | clock = ath5k_hw_htoclock(1, channel->hw_value & CHANNEL_TURBO); | 67 | clock = (channel->hw_value & CHANNEL_TURBO) ? 80 : 40; |
68 | |||
69 | coef_scaled = ((5 * (clock << 24)) / 2) / channel->center_freq; | 68 | coef_scaled = ((5 * (clock << 24)) / 2) / channel->center_freq; |
70 | 69 | ||
71 | /* Get exponent | 70 | /* Get exponent |
@@ -1317,6 +1316,10 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1317 | /* Restore antenna mode */ | 1316 | /* Restore antenna mode */ |
1318 | ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode); | 1317 | ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode); |
1319 | 1318 | ||
1319 | /* Restore slot time and ACK timeouts */ | ||
1320 | if (ah->ah_coverage_class > 0) | ||
1321 | ath5k_hw_set_coverage_class(ah, ah->ah_coverage_class); | ||
1322 | |||
1320 | /* | 1323 | /* |
1321 | * Configure QCUs/DCUs | 1324 | * Configure QCUs/DCUs |
1322 | */ | 1325 | */ |