aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath5k/qcu.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/ath5k/qcu.c')
-rw-r--r--drivers/net/wireless/ath/ath5k/qcu.c99
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 */
41static 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 */
41int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue, 55int 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 */
187int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) 221int 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 /*