diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath5k/qcu.c')
-rw-r--r-- | drivers/net/wireless/ath/ath5k/qcu.c | 99 |
1 files changed, 51 insertions, 48 deletions
diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c index 4186ff4c6e9c..84c717ded1c5 100644 --- a/drivers/net/wireless/ath/ath5k/qcu.c +++ b/drivers/net/wireless/ath/ath5k/qcu.c | |||
@@ -36,24 +36,58 @@ int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, | |||
36 | } | 36 | } |
37 | 37 | ||
38 | /* | 38 | /* |
39 | * Make sure cw is a power of 2 minus 1 and smaller than 1024 | ||
40 | */ | ||
41 | static u16 ath5k_cw_validate(u16 cw_req) | ||
42 | { | ||
43 | u32 cw = 1; | ||
44 | cw_req = min(cw_req, (u16)1023); | ||
45 | |||
46 | while (cw < cw_req) | ||
47 | cw = (cw << 1) | 1; | ||
48 | |||
49 | return cw; | ||
50 | } | ||
51 | |||
52 | /* | ||
39 | * Set properties for a transmit queue | 53 | * Set properties for a transmit queue |
40 | */ | 54 | */ |
41 | int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue, | 55 | int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue, |
42 | const struct ath5k_txq_info *queue_info) | 56 | const struct ath5k_txq_info *qinfo) |
43 | { | 57 | { |
58 | struct ath5k_txq_info *qi; | ||
59 | |||
44 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); | 60 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); |
45 | 61 | ||
46 | if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) | 62 | qi = &ah->ah_txq[queue]; |
63 | |||
64 | if (qi->tqi_type == AR5K_TX_QUEUE_INACTIVE) | ||
47 | return -EIO; | 65 | return -EIO; |
48 | 66 | ||
49 | memcpy(&ah->ah_txq[queue], queue_info, sizeof(struct ath5k_txq_info)); | 67 | /* copy and validate values */ |
68 | qi->tqi_type = qinfo->tqi_type; | ||
69 | qi->tqi_subtype = qinfo->tqi_subtype; | ||
70 | qi->tqi_flags = qinfo->tqi_flags; | ||
71 | /* | ||
72 | * According to the docs: Although the AIFS field is 8 bit wide, | ||
73 | * the maximum supported value is 0xFC. Setting it higher than that | ||
74 | * will cause the DCU to hang. | ||
75 | */ | ||
76 | qi->tqi_aifs = min(qinfo->tqi_aifs, (u8)0xFC); | ||
77 | qi->tqi_cw_min = ath5k_cw_validate(qinfo->tqi_cw_min); | ||
78 | qi->tqi_cw_max = ath5k_cw_validate(qinfo->tqi_cw_max); | ||
79 | qi->tqi_cbr_period = qinfo->tqi_cbr_period; | ||
80 | qi->tqi_cbr_overflow_limit = qinfo->tqi_cbr_overflow_limit; | ||
81 | qi->tqi_burst_time = qinfo->tqi_burst_time; | ||
82 | qi->tqi_ready_time = qinfo->tqi_ready_time; | ||
50 | 83 | ||
51 | /*XXX: Is this supported on 5210 ?*/ | 84 | /*XXX: Is this supported on 5210 ?*/ |
52 | if ((queue_info->tqi_type == AR5K_TX_QUEUE_DATA && | 85 | /*XXX: Is this correct for AR5K_WME_AC_VI,VO ???*/ |
53 | ((queue_info->tqi_subtype == AR5K_WME_AC_VI) || | 86 | if ((qinfo->tqi_type == AR5K_TX_QUEUE_DATA && |
54 | (queue_info->tqi_subtype == AR5K_WME_AC_VO))) || | 87 | ((qinfo->tqi_subtype == AR5K_WME_AC_VI) || |
55 | queue_info->tqi_type == AR5K_TX_QUEUE_UAPSD) | 88 | (qinfo->tqi_subtype == AR5K_WME_AC_VO))) || |
56 | ah->ah_txq[queue].tqi_flags |= AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS; | 89 | qinfo->tqi_type == AR5K_TX_QUEUE_UAPSD) |
90 | qi->tqi_flags |= AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS; | ||
57 | 91 | ||
58 | return 0; | 92 | return 0; |
59 | } | 93 | } |
@@ -186,7 +220,7 @@ void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue) | |||
186 | */ | 220 | */ |
187 | int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | 221 | int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) |
188 | { | 222 | { |
189 | u32 cw_min, cw_max, retry_lg, retry_sh; | 223 | u32 retry_lg, retry_sh; |
190 | struct ath5k_txq_info *tq = &ah->ah_txq[queue]; | 224 | struct ath5k_txq_info *tq = &ah->ah_txq[queue]; |
191 | 225 | ||
192 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); | 226 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); |
@@ -217,14 +251,13 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | |||
217 | /* Set IFS0 */ | 251 | /* Set IFS0 */ |
218 | if (ah->ah_turbo) { | 252 | if (ah->ah_turbo) { |
219 | ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS_TURBO + | 253 | ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS_TURBO + |
220 | (ah->ah_aifs + tq->tqi_aifs) * | 254 | tq->tqi_aifs * AR5K_INIT_SLOT_TIME_TURBO) << |
221 | AR5K_INIT_SLOT_TIME_TURBO) << | ||
222 | AR5K_IFS0_DIFS_S) | AR5K_INIT_SIFS_TURBO, | 255 | AR5K_IFS0_DIFS_S) | AR5K_INIT_SIFS_TURBO, |
223 | AR5K_IFS0); | 256 | AR5K_IFS0); |
224 | } else { | 257 | } else { |
225 | ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS + | 258 | ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS + |
226 | (ah->ah_aifs + tq->tqi_aifs) * | 259 | tq->tqi_aifs * AR5K_INIT_SLOT_TIME) << |
227 | AR5K_INIT_SLOT_TIME) << AR5K_IFS0_DIFS_S) | | 260 | AR5K_IFS0_DIFS_S) | |
228 | AR5K_INIT_SIFS, AR5K_IFS0); | 261 | AR5K_INIT_SIFS, AR5K_IFS0); |
229 | } | 262 | } |
230 | 263 | ||
@@ -248,35 +281,6 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | |||
248 | } | 281 | } |
249 | 282 | ||
250 | /* | 283 | /* |
251 | * Calculate cwmin/max by channel mode | ||
252 | */ | ||
253 | cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN; | ||
254 | cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX; | ||
255 | ah->ah_aifs = AR5K_TUNE_AIFS; | ||
256 | /*XR is only supported on 5212*/ | ||
257 | if (IS_CHAN_XR(ah->ah_current_channel) && | ||
258 | ah->ah_version == AR5K_AR5212) { | ||
259 | cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_XR; | ||
260 | cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_XR; | ||
261 | ah->ah_aifs = AR5K_TUNE_AIFS_XR; | ||
262 | /*B mode is not supported on 5210*/ | ||
263 | } else if (IS_CHAN_B(ah->ah_current_channel) && | ||
264 | ah->ah_version != AR5K_AR5210) { | ||
265 | cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_11B; | ||
266 | cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_11B; | ||
267 | ah->ah_aifs = AR5K_TUNE_AIFS_11B; | ||
268 | } | ||
269 | |||
270 | cw_min = 1; | ||
271 | while (cw_min < ah->ah_cw_min) | ||
272 | cw_min = (cw_min << 1) | 1; | ||
273 | |||
274 | cw_min = tq->tqi_cw_min < 0 ? (cw_min >> (-tq->tqi_cw_min)) : | ||
275 | ((cw_min << tq->tqi_cw_min) + (1 << tq->tqi_cw_min) - 1); | ||
276 | cw_max = tq->tqi_cw_max < 0 ? (cw_max >> (-tq->tqi_cw_max)) : | ||
277 | ((cw_max << tq->tqi_cw_max) + (1 << tq->tqi_cw_max) - 1); | ||
278 | |||
279 | /* | ||
280 | * Calculate and set retry limits | 284 | * Calculate and set retry limits |
281 | */ | 285 | */ |
282 | if (ah->ah_software_retry) { | 286 | if (ah->ah_software_retry) { |
@@ -292,7 +296,7 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | |||
292 | /*No QCU/DCU [5210]*/ | 296 | /*No QCU/DCU [5210]*/ |
293 | if (ah->ah_version == AR5K_AR5210) { | 297 | if (ah->ah_version == AR5K_AR5210) { |
294 | ath5k_hw_reg_write(ah, | 298 | ath5k_hw_reg_write(ah, |
295 | (cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S) | 299 | (tq->tqi_cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S) |
296 | | AR5K_REG_SM(AR5K_INIT_SLG_RETRY, | 300 | | AR5K_REG_SM(AR5K_INIT_SLG_RETRY, |
297 | AR5K_NODCU_RETRY_LMT_SLG_RETRY) | 301 | AR5K_NODCU_RETRY_LMT_SLG_RETRY) |
298 | | AR5K_REG_SM(AR5K_INIT_SSH_RETRY, | 302 | | AR5K_REG_SM(AR5K_INIT_SSH_RETRY, |
@@ -314,14 +318,13 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | |||
314 | /*===Rest is also for QCU/DCU only [5211+]===*/ | 318 | /*===Rest is also for QCU/DCU only [5211+]===*/ |
315 | 319 | ||
316 | /* | 320 | /* |
317 | * Set initial content window (cw_min/cw_max) | 321 | * Set contention window (cw_min/cw_max) |
318 | * and arbitrated interframe space (aifs)... | 322 | * and arbitrated interframe space (aifs)... |
319 | */ | 323 | */ |
320 | ath5k_hw_reg_write(ah, | 324 | ath5k_hw_reg_write(ah, |
321 | AR5K_REG_SM(cw_min, AR5K_DCU_LCL_IFS_CW_MIN) | | 325 | AR5K_REG_SM(tq->tqi_cw_min, AR5K_DCU_LCL_IFS_CW_MIN) | |
322 | AR5K_REG_SM(cw_max, AR5K_DCU_LCL_IFS_CW_MAX) | | 326 | AR5K_REG_SM(tq->tqi_cw_max, AR5K_DCU_LCL_IFS_CW_MAX) | |
323 | AR5K_REG_SM(ah->ah_aifs + tq->tqi_aifs, | 327 | AR5K_REG_SM(tq->tqi_aifs, AR5K_DCU_LCL_IFS_AIFS), |
324 | AR5K_DCU_LCL_IFS_AIFS), | ||
325 | AR5K_QUEUE_DFS_LOCAL_IFS(queue)); | 328 | AR5K_QUEUE_DFS_LOCAL_IFS(queue)); |
326 | 329 | ||
327 | /* | 330 | /* |