aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath5k/pcu.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/ath5k/pcu.c')
-rw-r--r--drivers/net/wireless/ath/ath5k/pcu.c829
1 files changed, 454 insertions, 375 deletions
diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c
index 86fdb6ddfaaa..712a9ac4000e 100644
--- a/drivers/net/wireless/ath/ath5k/pcu.c
+++ b/drivers/net/wireless/ath/ath5k/pcu.c
@@ -31,87 +31,169 @@
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* Generic functions * 63* Helper functions *
36\*******************/ 64\*******************/
37 65
38/** 66/**
39 * ath5k_hw_set_opmode - Set PCU operating mode 67 * ath5k_hw_get_frame_duration - Get tx time of a frame
40 * 68 *
41 * @ah: The &struct ath5k_hw 69 * @ah: The &struct ath5k_hw
42 * @op_mode: &enum nl80211_iftype operating mode 70 * @len: Frame's length in bytes
71 * @rate: The @struct ieee80211_rate
43 * 72 *
44 * Initialize PCU for the various operating modes (AP/STA etc) 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.
45 */ 76 */
46int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode) 77int ath5k_hw_get_frame_duration(struct ath5k_hw *ah,
78 int len, struct ieee80211_rate *rate, bool shortpre)
47{ 79{
48 struct ath_common *common = ath5k_hw_common(ah); 80 struct ath5k_softc *sc = ah->ah_sc;
49 u32 pcu_reg, beacon_reg, low_id, high_id; 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 __le16 raw_dur = ieee80211_generic_frame_duration(sc->hw,
88 NULL, len, rate);
89
90 /* subtract difference between long and short preamble */
91 dur = le16_to_cpu(raw_dur);
92 if (shortpre)
93 dur -= 96;
94
95 return dur;
96 }
50 97
51 ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_MODE, "mode %d\n", op_mode); 98 bitrate = rate->bitrate;
99 preamble = AR5K_INIT_OFDM_PREAMPLE_TIME;
100 plcp_bits = AR5K_INIT_OFDM_PLCP_BITS;
101 sym_time = AR5K_INIT_OFDM_SYMBOL_TIME;
52 102
53 /* Preserve rest settings */ 103 switch (ah->ah_bwmode) {
54 pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000; 104 case AR5K_BWMODE_40MHZ:
55 pcu_reg &= ~(AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_AP 105 sifs = AR5K_INIT_SIFS_TURBO;
56 | AR5K_STA_ID1_KEYSRCH_MODE 106 preamble = AR5K_INIT_OFDM_PREAMBLE_TIME_MIN;
57 | (ah->ah_version == AR5K_AR5210 ? 107 break;
58 (AR5K_STA_ID1_PWR_SV | AR5K_STA_ID1_NO_PSPOLL) : 0)); 108 case AR5K_BWMODE_10MHZ:
109 sifs = AR5K_INIT_SIFS_HALF_RATE;
110 preamble *= 2;
111 sym_time *= 2;
112 break;
113 case AR5K_BWMODE_5MHZ:
114 sifs = AR5K_INIT_SIFS_QUARTER_RATE;
115 preamble *= 4;
116 sym_time *= 4;
117 break;
118 default:
119 sifs = AR5K_INIT_SIFS_DEFAULT_BG;
120 break;
121 }
59 122
60 beacon_reg = 0; 123 bits = plcp_bits + (len << 3);
124 /* Bit rate is in 100Kbits */
125 symbol_bits = bitrate * sym_time;
126 symbols = DIV_ROUND_UP(bits * 10, symbol_bits);
61 127
62 switch (op_mode) { 128 dur = sifs + preamble + (sym_time * symbols);
63 case NL80211_IFTYPE_ADHOC:
64 pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE;
65 beacon_reg |= AR5K_BCR_ADHOC;
66 if (ah->ah_version == AR5K_AR5210)
67 pcu_reg |= AR5K_STA_ID1_NO_PSPOLL;
68 else
69 AR5K_REG_ENABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS);
70 break;
71 129
72 case NL80211_IFTYPE_AP: 130 return dur;
73 case NL80211_IFTYPE_MESH_POINT: 131}
74 pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_KEYSRCH_MODE;
75 beacon_reg |= AR5K_BCR_AP;
76 if (ah->ah_version == AR5K_AR5210)
77 pcu_reg |= AR5K_STA_ID1_NO_PSPOLL;
78 else
79 AR5K_REG_DISABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS);
80 break;
81 132
82 case NL80211_IFTYPE_STATION: 133/**
83 pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE 134 * ath5k_hw_get_default_slottime - Get the default slot time for current mode
84 | (ah->ah_version == AR5K_AR5210 ? 135 *
85 AR5K_STA_ID1_PWR_SV : 0); 136 * @ah: The &struct ath5k_hw
86 case NL80211_IFTYPE_MONITOR: 137 */
87 pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE 138unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah)
88 | (ah->ah_version == AR5K_AR5210 ? 139{
89 AR5K_STA_ID1_NO_PSPOLL : 0); 140 struct ieee80211_channel *channel = ah->ah_current_channel;
90 break; 141 unsigned int slot_time;
91 142
143 switch (ah->ah_bwmode) {
144 case AR5K_BWMODE_40MHZ:
145 slot_time = AR5K_INIT_SLOT_TIME_TURBO;
146 break;
147 case AR5K_BWMODE_10MHZ:
148 slot_time = AR5K_INIT_SLOT_TIME_HALF_RATE;
149 break;
150 case AR5K_BWMODE_5MHZ:
151 slot_time = AR5K_INIT_SLOT_TIME_QUARTER_RATE;
152 break;
153 case AR5K_BWMODE_DEFAULT:
92 default: 154 default:
93 return -EINVAL; 155 slot_time = AR5K_INIT_SLOT_TIME_DEFAULT;
156 if ((channel->hw_value & CHANNEL_CCK) && !ah->ah_short_slot)
157 slot_time = AR5K_INIT_SLOT_TIME_B;
158 break;
94 } 159 }
95 160
96 /* 161 return slot_time;
97 * Set PCU registers 162}
98 */
99 low_id = get_unaligned_le32(common->macaddr);
100 high_id = get_unaligned_le16(common->macaddr + 4);
101 ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0);
102 ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1);
103 163
104 /* 164/**
105 * Set Beacon Control Register on 5210 165 * ath5k_hw_get_default_sifs - Get the default SIFS for current mode
106 */ 166 *
107 if (ah->ah_version == AR5K_AR5210) 167 * @ah: The &struct ath5k_hw
108 ath5k_hw_reg_write(ah, beacon_reg, AR5K_BCR); 168 */
169unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah)
170{
171 struct ieee80211_channel *channel = ah->ah_current_channel;
172 unsigned int sifs;
109 173
110 return 0; 174 switch (ah->ah_bwmode) {
175 case AR5K_BWMODE_40MHZ:
176 sifs = AR5K_INIT_SIFS_TURBO;
177 break;
178 case AR5K_BWMODE_10MHZ:
179 sifs = AR5K_INIT_SIFS_HALF_RATE;
180 break;
181 case AR5K_BWMODE_5MHZ:
182 sifs = AR5K_INIT_SIFS_QUARTER_RATE;
183 break;
184 case AR5K_BWMODE_DEFAULT:
185 sifs = AR5K_INIT_SIFS_DEFAULT_BG;
186 default:
187 if (channel->hw_value & CHANNEL_5GHZ)
188 sifs = AR5K_INIT_SIFS_DEFAULT_A;
189 break;
190 }
191
192 return sifs;
111} 193}
112 194
113/** 195/**
114 * ath5k_hw_update - Update MIB counters (mac layer statistics) 196 * ath5k_hw_update_mib_counters - Update MIB counters (mac layer statistics)
115 * 197 *
116 * @ah: The &struct ath5k_hw 198 * @ah: The &struct ath5k_hw
117 * 199 *
@@ -133,35 +215,72 @@ void ath5k_hw_update_mib_counters(struct ath5k_hw *ah)
133 stats->beacons += ath5k_hw_reg_read(ah, AR5K_BEACON_CNT); 215 stats->beacons += ath5k_hw_reg_read(ah, AR5K_BEACON_CNT);
134} 216}
135 217
218
219/******************\
220* ACK/CTS Timeouts *
221\******************/
222
136/** 223/**
137 * ath5k_hw_set_ack_bitrate - set bitrate for ACKs 224 * ath5k_hw_write_rate_duration - fill rate code to duration table
138 * 225 *
139 * @ah: The &struct ath5k_hw 226 * @ah: the &struct ath5k_hw
140 * @high: Flag to determine if we want to use high transmition rate 227 * @mode: one of enum ath5k_driver_mode
141 * for ACKs or not 228 *
229 * Write the rate code to duration table upon hw reset. This is a helper for
230 * ath5k_hw_pcu_init(). It seems all this is doing is setting an ACK timeout on
231 * the hardware, based on current mode, for each rate. The rates which are
232 * capable of short preamble (802.11b rates 2Mbps, 5.5Mbps, and 11Mbps) have
233 * different rate code so we write their value twice (one for long preamble
234 * and one for short).
235 *
236 * Note: Band doesn't matter here, if we set the values for OFDM it works
237 * on both a and g modes. So all we have to do is set values for all g rates
238 * that include all OFDM and CCK rates.
142 * 239 *
143 * If high flag is set, we tell hw to use a set of control rates based on
144 * the current transmition rate (check out control_rates array inside reset.c).
145 * If not hw just uses the lowest rate available for the current modulation
146 * scheme being used (1Mbit for CCK and 6Mbits for OFDM).
147 */ 240 */
148void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high) 241static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah)
149{ 242{
150 if (ah->ah_version != AR5K_AR5212) 243 struct ath5k_softc *sc = ah->ah_sc;
151 return; 244 struct ieee80211_rate *rate;
152 else { 245 unsigned int i;
153 u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB; 246 /* 802.11g covers both OFDM and CCK */
154 if (high) 247 u8 band = IEEE80211_BAND_2GHZ;
155 AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val); 248
249 /* Write rate duration table */
250 for (i = 0; i < sc->sbands[band].n_bitrates; i++) {
251 u32 reg;
252 u16 tx_time;
253
254 if (ah->ah_ack_bitrate_high)
255 rate = &sc->sbands[band].bitrates[ack_rates_high[i]];
256 /* CCK -> 1Mb */
257 else if (i < 4)
258 rate = &sc->sbands[band].bitrates[0];
259 /* OFDM -> 6Mb */
156 else 260 else
157 AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val); 261 rate = &sc->sbands[band].bitrates[4];
158 }
159}
160 262
263 /* Set ACK timeout */
264 reg = AR5K_RATE_DUR(rate->hw_value);
161 265
162/******************\ 266 /* An ACK frame consists of 10 bytes. If you add the FCS,
163* ACK/CTS Timeouts * 267 * which ieee80211_generic_frame_duration() adds,
164\******************/ 268 * its 14 bytes. Note we use the control rate and not the
269 * actual rate for this rate. See mac80211 tx.c
270 * ieee80211_duration() for a brief description of
271 * what rate we should choose to TX ACKs. */
272 tx_time = ath5k_hw_get_frame_duration(ah, 10, rate, false);
273
274 ath5k_hw_reg_write(ah, tx_time, reg);
275
276 if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE))
277 continue;
278
279 tx_time = ath5k_hw_get_frame_duration(ah, 10, rate, true);
280 ath5k_hw_reg_write(ah, tx_time,
281 reg + (AR5K_SET_SHORT_PREAMBLE << 2));
282 }
283}
165 284
166/** 285/**
167 * ath5k_hw_set_ack_timeout - Set ACK timeout on PCU 286 * ath5k_hw_set_ack_timeout - Set ACK timeout on PCU
@@ -199,85 +318,10 @@ static int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout)
199 return 0; 318 return 0;
200} 319}
201 320
202/**
203 * ath5k_hw_htoclock - Translate usec to hw clock units
204 *
205 * @ah: The &struct ath5k_hw
206 * @usec: value in microseconds
207 */
208unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec)
209{
210 return usec * ath5k_hw_get_clockrate(ah);
211}
212
213/**
214 * ath5k_hw_clocktoh - Translate hw clock units to usec
215 * @clock: value in hw clock units
216 */
217unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock)
218{
219 return clock / ath5k_hw_get_clockrate(ah);
220}
221
222/**
223 * ath5k_hw_get_clockrate - Get the clock rate for current mode
224 *
225 * @ah: The &struct ath5k_hw
226 */
227unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah)
228{
229 struct ieee80211_channel *channel = ah->ah_current_channel;
230 int clock;
231
232 if (channel->hw_value & CHANNEL_5GHZ)
233 clock = 40; /* 802.11a */
234 else if (channel->hw_value & CHANNEL_CCK)
235 clock = 22; /* 802.11b */
236 else
237 clock = 44; /* 802.11g */
238
239 /* Clock rate in turbo modes is twice the normal rate */
240 if (channel->hw_value & CHANNEL_TURBO)
241 clock *= 2;
242
243 return clock;
244}
245 321
246/** 322/*******************\
247 * ath5k_hw_get_default_slottime - Get the default slot time for current mode 323* RX filter Control *
248 * 324\*******************/
249 * @ah: The &struct ath5k_hw
250 */
251static unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah)
252{
253 struct ieee80211_channel *channel = ah->ah_current_channel;
254
255 if (channel->hw_value & CHANNEL_TURBO)
256 return 6; /* both turbo modes */
257
258 if (channel->hw_value & CHANNEL_CCK)
259 return 20; /* 802.11b */
260
261 return 9; /* 802.11 a/g */
262}
263
264/**
265 * ath5k_hw_get_default_sifs - Get the default SIFS for current mode
266 *
267 * @ah: The &struct ath5k_hw
268 */
269static unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah)
270{
271 struct ieee80211_channel *channel = ah->ah_current_channel;
272
273 if (channel->hw_value & CHANNEL_TURBO)
274 return 8; /* both turbo modes */
275
276 if (channel->hw_value & CHANNEL_5GHZ)
277 return 16; /* 802.11a */
278
279 return 10; /* 802.11 b/g */
280}
281 325
282/** 326/**
283 * ath5k_hw_set_lladdr - Set station id 327 * ath5k_hw_set_lladdr - Set station id
@@ -308,27 +352,26 @@ int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac)
308} 352}
309 353
310/** 354/**
311 * ath5k_hw_set_associd - Set BSSID for association 355 * ath5k_hw_set_bssid - Set current BSSID on hw
312 * 356 *
313 * @ah: The &struct ath5k_hw 357 * @ah: The &struct ath5k_hw
314 * @bssid: BSSID
315 * @assoc_id: Assoc id
316 * 358 *
317 * Sets the BSSID which trigers the "SME Join" operation 359 * Sets the current BSSID and BSSID mask we have from the
360 * common struct into the hardware
318 */ 361 */
319void ath5k_hw_set_associd(struct ath5k_hw *ah) 362void ath5k_hw_set_bssid(struct ath5k_hw *ah)
320{ 363{
321 struct ath_common *common = ath5k_hw_common(ah); 364 struct ath_common *common = ath5k_hw_common(ah);
322 u16 tim_offset = 0; 365 u16 tim_offset = 0;
323 366
324 /* 367 /*
325 * Set simple BSSID mask on 5212 368 * Set BSSID mask on 5212
326 */ 369 */
327 if (ah->ah_version == AR5K_AR5212) 370 if (ah->ah_version == AR5K_AR5212)
328 ath_hw_setbssidmask(common); 371 ath_hw_setbssidmask(common);
329 372
330 /* 373 /*
331 * Set BSSID which triggers the "SME Join" operation 374 * Set BSSID
332 */ 375 */
333 ath5k_hw_reg_write(ah, 376 ath5k_hw_reg_write(ah,
334 get_unaligned_le32(common->curbssid), 377 get_unaligned_le32(common->curbssid),
@@ -360,39 +403,6 @@ void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask)
360 ath_hw_setbssidmask(common); 403 ath_hw_setbssidmask(common);
361} 404}
362 405
363/************\
364* RX Control *
365\************/
366
367/**
368 * ath5k_hw_start_rx_pcu - Start RX engine
369 *
370 * @ah: The &struct ath5k_hw
371 *
372 * Starts RX engine on PCU so that hw can process RXed frames
373 * (ACK etc).
374 *
375 * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma
376 */
377void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah)
378{
379 AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
380}
381
382/**
383 * at5k_hw_stop_rx_pcu - Stop RX engine
384 *
385 * @ah: The &struct ath5k_hw
386 *
387 * Stops RX engine on PCU
388 *
389 * TODO: Detach ANI here
390 */
391void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah)
392{
393 AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
394}
395
396/* 406/*
397 * Set multicast filter 407 * Set multicast filter
398 */ 408 */
@@ -455,7 +465,7 @@ void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter)
455 } 465 }
456 466
457 /* 467 /*
458 * The AR5210 uses promiscous mode to detect radar activity 468 * The AR5210 uses promiscuous mode to detect radar activity
459 */ 469 */
460 if (ah->ah_version == AR5K_AR5210 && 470 if (ah->ah_version == AR5K_AR5210 &&
461 (filter & AR5K_RX_FILTER_RADARERR)) { 471 (filter & AR5K_RX_FILTER_RADARERR)) {
@@ -496,6 +506,10 @@ u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah)
496{ 506{
497 u32 tsf_lower, tsf_upper1, tsf_upper2; 507 u32 tsf_lower, tsf_upper1, tsf_upper2;
498 int i; 508 int i;
509 unsigned long flags;
510
511 /* This code is time critical - we don't want to be interrupted here */
512 local_irq_save(flags);
499 513
500 /* 514 /*
501 * While reading TSF upper and then lower part, the clock is still 515 * While reading TSF upper and then lower part, the clock is still
@@ -518,6 +532,8 @@ u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah)
518 tsf_upper1 = tsf_upper2; 532 tsf_upper1 = tsf_upper2;
519 } 533 }
520 534
535 local_irq_restore(flags);
536
521 WARN_ON( i == ATH5K_MAX_TSF_READ ); 537 WARN_ON( i == ATH5K_MAX_TSF_READ );
522 538
523 return (((u64)tsf_upper1 << 32) | tsf_lower); 539 return (((u64)tsf_upper1 << 32) | tsf_lower);
@@ -601,7 +617,7 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval)
601 /* Timer3 marks the end of our ATIM window 617 /* Timer3 marks the end of our ATIM window
602 * a zero length window is not allowed because 618 * a zero length window is not allowed because
603 * we 'll get no beacons */ 619 * we 'll get no beacons */
604 timer3 = next_beacon + (ah->ah_atim_window ? ah->ah_atim_window : 1); 620 timer3 = next_beacon + 1;
605 621
606 /* 622 /*
607 * Set the beacon register and enable all timers. 623 * Set the beacon register and enable all timers.
@@ -641,218 +657,281 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval)
641 657
642} 658}
643 659
660/**
661 * ath5k_check_timer_win - Check if timer B is timer A + window
662 *
663 * @a: timer a (before b)
664 * @b: timer b (after a)
665 * @window: difference between a and b
666 * @intval: timers are increased by this interval
667 *
668 * This helper function checks if timer B is timer A + window and covers
669 * cases where timer A or B might have already been updated or wrapped
670 * around (Timers are 16 bit).
671 *
672 * Returns true if O.K.
673 */
674static inline bool
675ath5k_check_timer_win(int a, int b, int window, int intval)
676{
677 /*
678 * 1.) usually B should be A + window
679 * 2.) A already updated, B not updated yet
680 * 3.) A already updated and has wrapped around
681 * 4.) B has wrapped around
682 */
683 if ((b - a == window) || /* 1.) */
684 (a - b == intval - window) || /* 2.) */
685 ((a | 0x10000) - b == intval - window) || /* 3.) */
686 ((b | 0x10000) - a == window)) /* 4.) */
687 return true; /* O.K. */
688 return false;
689}
644 690
645/*********************\ 691/**
646* Key table functions * 692 * ath5k_hw_check_beacon_timers - Check if the beacon timers are correct
647\*********************/ 693 *
648 694 * @ah: The &struct ath5k_hw
649/* 695 * @intval: beacon interval
650 * Reset a key entry on the table 696 *
697 * This is a workaround for IBSS mode:
698 *
699 * The need for this function arises from the fact that we have 4 separate
700 * HW timer registers (TIMER0 - TIMER3), which are closely related to the
701 * next beacon target time (NBTT), and that the HW updates these timers
702 * separately based on the current TSF value. The hardware increments each
703 * timer by the beacon interval, when the local TSF converted to TU is equal
704 * to the value stored in the timer.
705 *
706 * The reception of a beacon with the same BSSID can update the local HW TSF
707 * at any time - this is something we can't avoid. If the TSF jumps to a
708 * time which is later than the time stored in a timer, this timer will not
709 * be updated until the TSF in TU wraps around at 16 bit (the size of the
710 * timers) and reaches the time which is stored in the timer.
711 *
712 * The problem is that these timers are closely related to TIMER0 (NBTT) and
713 * that they define a time "window". When the TSF jumps between two timers
714 * (e.g. ATIM and NBTT), the one in the past will be left behind (not
715 * updated), while the one in the future will be updated every beacon
716 * interval. This causes the window to get larger, until the TSF wraps
717 * around as described above and the timer which was left behind gets
718 * updated again. But - because the beacon interval is usually not an exact
719 * divisor of the size of the timers (16 bit), an unwanted "window" between
720 * these timers has developed!
721 *
722 * This is especially important with the ATIM window, because during
723 * the ATIM window only ATIM frames and no data frames are allowed to be
724 * sent, which creates transmission pauses after each beacon. This symptom
725 * has been described as "ramping ping" because ping times increase linearly
726 * for some time and then drop down again. A wrong window on the DMA beacon
727 * timer has the same effect, so we check for these two conditions.
728 *
729 * Returns true if O.K.
651 */ 730 */
652int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry) 731bool
732ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval)
653{ 733{
654 unsigned int i, type; 734 unsigned int nbtt, atim, dma;
655 u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET;
656 735
657 AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); 736 nbtt = ath5k_hw_reg_read(ah, AR5K_TIMER0);
737 atim = ath5k_hw_reg_read(ah, AR5K_TIMER3);
738 dma = ath5k_hw_reg_read(ah, AR5K_TIMER1) >> 3;
658 739
659 type = ath5k_hw_reg_read(ah, AR5K_KEYTABLE_TYPE(entry)); 740 /* NOTE: SWBA is different. Having a wrong window there does not
741 * stop us from sending data and this condition is catched thru
742 * other means (SWBA interrupt) */
660 743
661 for (i = 0; i < AR5K_KEYCACHE_SIZE; i++) 744 if (ath5k_check_timer_win(nbtt, atim, 1, intval) &&
662 ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_OFF(entry, i)); 745 ath5k_check_timer_win(dma, nbtt, AR5K_TUNE_DMA_BEACON_RESP,
746 intval))
747 return true; /* O.K. */
748 return false;
749}
663 750
664 /* Reset associated MIC entry if TKIP 751/**
665 * is enabled located at offset (entry + 64) */ 752 * ath5k_hw_set_coverage_class - Set IEEE 802.11 coverage class
666 if (type == AR5K_KEYTABLE_TYPE_TKIP) { 753 *
667 AR5K_ASSERT_ENTRY(micentry, AR5K_KEYTABLE_SIZE); 754 * @ah: The &struct ath5k_hw
668 for (i = 0; i < AR5K_KEYCACHE_SIZE / 2 ; i++) 755 * @coverage_class: IEEE 802.11 coverage class number
669 ath5k_hw_reg_write(ah, 0, 756 *
670 AR5K_KEYTABLE_OFF(micentry, i)); 757 * Sets IFS intervals and ACK/CTS timeouts for given coverage class.
671 } 758 */
759void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class)
760{
761 /* As defined by IEEE 802.11-2007 17.3.8.6 */
762 int slot_time = ath5k_hw_get_default_slottime(ah) + 3 * coverage_class;
763 int ack_timeout = ath5k_hw_get_default_sifs(ah) + slot_time;
764 int cts_timeout = ack_timeout;
672 765
673 /* 766 ath5k_hw_set_ifs_intervals(ah, slot_time);
674 * Set NULL encryption on AR5212+ 767 ath5k_hw_set_ack_timeout(ah, ack_timeout);
675 * 768 ath5k_hw_set_cts_timeout(ah, cts_timeout);
676 * Note: AR5K_KEYTABLE_TYPE -> AR5K_KEYTABLE_OFF(entry, 5)
677 * AR5K_KEYTABLE_TYPE_NULL -> 0x00000007
678 *
679 * Note2: Windows driver (ndiswrapper) sets this to
680 * 0x00000714 instead of 0x00000007
681 */
682 if (ah->ah_version >= AR5K_AR5211) {
683 ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
684 AR5K_KEYTABLE_TYPE(entry));
685 769
686 if (type == AR5K_KEYTABLE_TYPE_TKIP) { 770 ah->ah_coverage_class = coverage_class;
687 ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL, 771}
688 AR5K_KEYTABLE_TYPE(micentry));
689 }
690 }
691 772
692 return 0; 773/***************************\
774* Init/Start/Stop functions *
775\***************************/
776
777/**
778 * ath5k_hw_start_rx_pcu - Start RX engine
779 *
780 * @ah: The &struct ath5k_hw
781 *
782 * Starts RX engine on PCU so that hw can process RXed frames
783 * (ACK etc).
784 *
785 * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma
786 */
787void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah)
788{
789 AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
693} 790}
694 791
695static 792/**
696int ath5k_keycache_type(const struct ieee80211_key_conf *key) 793 * at5k_hw_stop_rx_pcu - Stop RX engine
794 *
795 * @ah: The &struct ath5k_hw
796 *
797 * Stops RX engine on PCU
798 */
799void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah)
697{ 800{
698 switch (key->alg) { 801 AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
699 case ALG_TKIP:
700 return AR5K_KEYTABLE_TYPE_TKIP;
701 case ALG_CCMP:
702 return AR5K_KEYTABLE_TYPE_CCM;
703 case ALG_WEP:
704 if (key->keylen == WLAN_KEY_LEN_WEP40)
705 return AR5K_KEYTABLE_TYPE_40;
706 else if (key->keylen == WLAN_KEY_LEN_WEP104)
707 return AR5K_KEYTABLE_TYPE_104;
708 return -EINVAL;
709 default:
710 return -EINVAL;
711 }
712 return -EINVAL;
713} 802}
714 803
715/* 804/**
716 * Set a key entry on the table 805 * ath5k_hw_set_opmode - Set PCU operating mode
806 *
807 * @ah: The &struct ath5k_hw
808 * @op_mode: &enum nl80211_iftype operating mode
809 *
810 * Configure PCU for the various operating modes (AP/STA etc)
717 */ 811 */
718int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, 812int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode)
719 const struct ieee80211_key_conf *key, const u8 *mac)
720{ 813{
721 unsigned int i; 814 struct ath_common *common = ath5k_hw_common(ah);
722 int keylen; 815 u32 pcu_reg, beacon_reg, low_id, high_id;
723 __le32 key_v[5] = {};
724 __le32 key0 = 0, key1 = 0;
725 __le32 *rxmic, *txmic;
726 int keytype;
727 u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET;
728 bool is_tkip;
729 const u8 *key_ptr;
730 816
731 is_tkip = (key->alg == ALG_TKIP); 817 ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_MODE, "mode %d\n", op_mode);
732 818
733 /* 819 /* Preserve rest settings */
734 * key->keylen comes in from mac80211 in bytes. 820 pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000;
735 * TKIP is 128 bit + 128 bit mic 821 pcu_reg &= ~(AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_AP
736 */ 822 | AR5K_STA_ID1_KEYSRCH_MODE
737 keylen = (is_tkip) ? (128 / 8) : key->keylen; 823 | (ah->ah_version == AR5K_AR5210 ?
824 (AR5K_STA_ID1_PWR_SV | AR5K_STA_ID1_NO_PSPOLL) : 0));
738 825
739 if (entry > AR5K_KEYTABLE_SIZE || 826 beacon_reg = 0;
740 (is_tkip && micentry > AR5K_KEYTABLE_SIZE))
741 return -EOPNOTSUPP;
742 827
743 if (unlikely(keylen > 16)) 828 switch (op_mode) {
744 return -EOPNOTSUPP; 829 case NL80211_IFTYPE_ADHOC:
830 pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE;
831 beacon_reg |= AR5K_BCR_ADHOC;
832 if (ah->ah_version == AR5K_AR5210)
833 pcu_reg |= AR5K_STA_ID1_NO_PSPOLL;
834 else
835 AR5K_REG_ENABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS);
836 break;
745 837
746 keytype = ath5k_keycache_type(key); 838 case NL80211_IFTYPE_AP:
747 if (keytype < 0) 839 case NL80211_IFTYPE_MESH_POINT:
748 return keytype; 840 pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_KEYSRCH_MODE;
841 beacon_reg |= AR5K_BCR_AP;
842 if (ah->ah_version == AR5K_AR5210)
843 pcu_reg |= AR5K_STA_ID1_NO_PSPOLL;
844 else
845 AR5K_REG_DISABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS);
846 break;
749 847
750 /* 848 case NL80211_IFTYPE_STATION:
751 * each key block is 6 bytes wide, written as pairs of 849 pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE
752 * alternating 32 and 16 bit le values. 850 | (ah->ah_version == AR5K_AR5210 ?
753 */ 851 AR5K_STA_ID1_PWR_SV : 0);
754 key_ptr = key->key; 852 case NL80211_IFTYPE_MONITOR:
755 for (i = 0; keylen >= 6; keylen -= 6) { 853 pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE
756 memcpy(&key_v[i], key_ptr, 6); 854 | (ah->ah_version == AR5K_AR5210 ?
757 i += 2; 855 AR5K_STA_ID1_NO_PSPOLL : 0);
758 key_ptr += 6; 856 break;
759 }
760 if (keylen)
761 memcpy(&key_v[i], key_ptr, keylen);
762 857
763 /* intentionally corrupt key until mic is installed */ 858 default:
764 if (is_tkip) { 859 return -EINVAL;
765 key0 = key_v[0] = ~key_v[0];
766 key1 = key_v[1] = ~key_v[1];
767 } 860 }
768 861
769 for (i = 0; i < ARRAY_SIZE(key_v); i++) 862 /*
770 ath5k_hw_reg_write(ah, le32_to_cpu(key_v[i]), 863 * Set PCU registers
771 AR5K_KEYTABLE_OFF(entry, i)); 864 */
772 865 low_id = get_unaligned_le32(common->macaddr);
773 ath5k_hw_reg_write(ah, keytype, AR5K_KEYTABLE_TYPE(entry)); 866 high_id = get_unaligned_le16(common->macaddr + 4);
774 867 ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0);
775 if (is_tkip) { 868 ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1);
776 /* Install rx/tx MIC */
777 rxmic = (__le32 *) &key->key[16];
778 txmic = (__le32 *) &key->key[24];
779 869
780 if (ah->ah_combined_mic) { 870 /*
781 key_v[0] = rxmic[0]; 871 * Set Beacon Control Register on 5210
782 key_v[1] = cpu_to_le32(le32_to_cpu(txmic[0]) >> 16); 872 */
783 key_v[2] = rxmic[1]; 873 if (ah->ah_version == AR5K_AR5210)
784 key_v[3] = cpu_to_le32(le32_to_cpu(txmic[0]) & 0xffff); 874 ath5k_hw_reg_write(ah, beacon_reg, AR5K_BCR);
785 key_v[4] = txmic[1];
786 } else {
787 key_v[0] = rxmic[0];
788 key_v[1] = 0;
789 key_v[2] = rxmic[1];
790 key_v[3] = 0;
791 key_v[4] = 0;
792 }
793 for (i = 0; i < ARRAY_SIZE(key_v); i++)
794 ath5k_hw_reg_write(ah, le32_to_cpu(key_v[i]),
795 AR5K_KEYTABLE_OFF(micentry, i));
796
797 ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
798 AR5K_KEYTABLE_TYPE(micentry));
799 ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_MAC0(micentry));
800 ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_MAC1(micentry));
801
802 /* restore first 2 words of key */
803 ath5k_hw_reg_write(ah, le32_to_cpu(~key0),
804 AR5K_KEYTABLE_OFF(entry, 0));
805 ath5k_hw_reg_write(ah, le32_to_cpu(~key1),
806 AR5K_KEYTABLE_OFF(entry, 1));
807 }
808 875
809 return ath5k_hw_set_key_lladdr(ah, entry, mac); 876 return 0;
810} 877}
811 878
812int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac) 879void ath5k_hw_pcu_init(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
880 u8 mode)
813{ 881{
814 u32 low_id, high_id; 882 /* Set bssid and bssid mask */
815 883 ath5k_hw_set_bssid(ah);
816 /* Invalid entry (key table overflow) */
817 AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE);
818 884
819 /* 885 /* Set PCU config */
820 * MAC may be NULL if it's a broadcast key. In this case no need to 886 ath5k_hw_set_opmode(ah, op_mode);
821 * to compute get_unaligned_le32 and get_unaligned_le16 as we
822 * already know it.
823 */
824 if (!mac) {
825 low_id = 0xffffffff;
826 high_id = 0xffff | AR5K_KEYTABLE_VALID;
827 } else {
828 low_id = get_unaligned_le32(mac);
829 high_id = get_unaligned_le16(mac + 4) | AR5K_KEYTABLE_VALID;
830 }
831 887
832 ath5k_hw_reg_write(ah, low_id, AR5K_KEYTABLE_MAC0(entry)); 888 /* Write rate duration table only on AR5212 and if
833 ath5k_hw_reg_write(ah, high_id, AR5K_KEYTABLE_MAC1(entry)); 889 * virtual interface has already been brought up
890 * XXX: rethink this after new mode changes to
891 * mac80211 are integrated */
892 if (ah->ah_version == AR5K_AR5212 &&
893 ah->ah_sc->nvifs)
894 ath5k_hw_write_rate_duration(ah);
834 895
835 return 0; 896 /* Set RSSI/BRSSI thresholds
836} 897 *
898 * Note: If we decide to set this value
899 * dynamicaly, have in mind that when AR5K_RSSI_THR
900 * register is read it might return 0x40 if we haven't
901 * wrote anything to it plus BMISS RSSI threshold is zeroed.
902 * So doing a save/restore procedure here isn't the right
903 * choice. Instead store it on ath5k_hw */
904 ath5k_hw_reg_write(ah, (AR5K_TUNE_RSSI_THRES |
905 AR5K_TUNE_BMISS_THRES <<
906 AR5K_RSSI_THR_BMISS_S),
907 AR5K_RSSI_THR);
908
909 /* MIC QoS support */
910 if (ah->ah_mac_srev >= AR5K_SREV_AR2413) {
911 ath5k_hw_reg_write(ah, 0x000100aa, AR5K_MIC_QOS_CTL);
912 ath5k_hw_reg_write(ah, 0x00003210, AR5K_MIC_QOS_SEL);
913 }
837 914
838/** 915 /* QoS NOACK Policy */
839 * ath5k_hw_set_coverage_class - Set IEEE 802.11 coverage class 916 if (ah->ah_version == AR5K_AR5212) {
840 * 917 ath5k_hw_reg_write(ah,
841 * @ah: The &struct ath5k_hw 918 AR5K_REG_SM(2, AR5K_QOS_NOACK_2BIT_VALUES) |
842 * @coverage_class: IEEE 802.11 coverage class number 919 AR5K_REG_SM(5, AR5K_QOS_NOACK_BIT_OFFSET) |
843 * 920 AR5K_REG_SM(0, AR5K_QOS_NOACK_BYTE_OFFSET),
844 * Sets slot time, ACK timeout and CTS timeout for given coverage class. 921 AR5K_QOS_NOACK);
845 */ 922 }
846void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class)
847{
848 /* As defined by IEEE 802.11-2007 17.3.8.6 */
849 int slot_time = ath5k_hw_get_default_slottime(ah) + 3 * coverage_class;
850 int ack_timeout = ath5k_hw_get_default_sifs(ah) + slot_time;
851 int cts_timeout = ack_timeout;
852 923
853 ath5k_hw_set_slot_time(ah, slot_time); 924 /* Restore slot time and ACK timeouts */
854 ath5k_hw_set_ack_timeout(ah, ack_timeout); 925 if (ah->ah_coverage_class > 0)
855 ath5k_hw_set_cts_timeout(ah, cts_timeout); 926 ath5k_hw_set_coverage_class(ah, ah->ah_coverage_class);
856 927
857 ah->ah_coverage_class = coverage_class; 928 /* Set ACK bitrate mode (see ack_rates_high) */
929 if (ah->ah_version == AR5K_AR5212) {
930 u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB;
931 if (ah->ah_ack_bitrate_high)
932 AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val);
933 else
934 AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val);
935 }
936 return;
858} 937}