1 /* 2 * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org> 3 * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 * 17 */ 18 19 /********************************************\ 20 Queue Control Unit, DFS Control Unit Functions 21 \********************************************/ 22 23 #include "ath5k.h" 24 #include "reg.h" 25 #include "debug.h" 26 27 28 /******************\ 29 * Helper functions * 30 \******************/ 31 32 /* 33 * Get number of pending frames 34 * for a specific queue [5211+] 35 */ 36 u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) 37 { 38 u32 pending; 39 AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); 40 41 /* Return if queue is declared inactive */ 42 if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) 43 return false; 44 45 /* XXX: How about AR5K_CFG_TXCNT ? */ 46 if (ah->ah_version == AR5K_AR5210) 47 return false; 48 49 pending = ath5k_hw_reg_read(ah, AR5K_QUEUE_STATUS(queue)); 50 pending &= AR5K_QCU_STS_FRMPENDCNT; 51 52 /* It's possible to have no frames pending even if TXE 53 * is set. To indicate that q has not stopped return 54 * true */ 55 if (!pending && AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue)) 56 return true; 57 58 return pending; 59 } 60 61 /* 62 * Set a transmit queue inactive 63 */ 64 void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue) 65 { 66 if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num)) 67 return; 68 69 /* This queue will be skipped in further operations */ 70 ah->ah_txq[queue].tqi_type = AR5K_TX_QUEUE_INACTIVE; 71 /*For SIMR setup*/ 72 AR5K_Q_DISABLE_BITS(ah->ah_txq_status, queue); 73 } 74 75 /* 76 * Make sure cw is a power of 2 minus 1 and smaller than 1024 77 */ 78 static u16 ath5k_cw_validate(u16 cw_req) 79 { 80 u32 cw = 1; 81 cw_req = min(cw_req, (u16)1023); 82 83 while (cw < cw_req) 84 cw = (cw << 1) | 1; 85 86 return cw; 87 } 88 89 /* 90 * Get properties for a transmit queue 91 */ 92 int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, 93 struct ath5k_txq_info *queue_info) 94 { 95 memcpy(queue_info, &ah->ah_txq[queue], sizeof(struct ath5k_txq_info)); 96 return 0; 97 } 98 99 /* 100 * Set properties for a transmit queue 101 */ 102 int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue, 103 const struct ath5k_txq_info *qinfo) 104 { 105 struct ath5k_txq_info *qi; 106 107 AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); 108 109 qi = &ah->ah_txq[queue]; 110 111 if (qi->tqi_type == AR5K_TX_QUEUE_INACTIVE) 112 return -EIO; 113 114 /* copy and validate values */ 115 qi->tqi_type = qinfo->tqi_type; 116 qi->tqi_subtype = qinfo->tqi_subtype; 117 qi->tqi_flags = qinfo->tqi_flags; 118 /* 119 * According to the docs: Although the AIFS field is 8 bit wide, 120 * the maximum supported value is 0xFC. Setting it higher than that 121 * will cause the DCU to hang. 122 */ 123 qi->tqi_aifs = min(qinfo->tqi_aifs, (u8)0xFC); 124 qi->tqi_cw_min = ath5k_cw_validate(qinfo->tqi_cw_min); 125 qi->tqi_cw_max = ath5k_cw_validate(qinfo->tqi_cw_max); 126 qi->tqi_cbr_period = qinfo->tqi_cbr_period; 127 qi->tqi_cbr_overflow_limit = qinfo->tqi_cbr_overflow_limit; 128 qi->tqi_burst_time = qinfo->tqi_burst_time; 129 qi->tqi_ready_time = qinfo->tqi_ready_time; 130 131 /*XXX: Is this supported on 5210 ?*/ 132 /*XXX: Is this correct for AR5K_WME_AC_VI,VO ???*/ 133 if ((qinfo->tqi_type == AR5K_TX_QUEUE_DATA && 134 ((qinfo->tqi_subtype == AR5K_WME_AC_VI) || 135 (qinfo->tqi_subtype == AR5K_WME_AC_VO))) || 136 qinfo->tqi_type == AR5K_TX_QUEUE_UAPSD) 137 qi->tqi_flags |= AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS; 138 139 return 0; 140 } 141 142 /* 143 * Initialize a transmit queue 144 */ 145 int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type, 146 struct ath5k_txq_info *queue_info) 147 { 148 unsigned int queue; 149 int ret; 150 151 /* 152 * Get queue by type 153 */ 154 /* 5210 only has 2 queues */ 155 if (ah->ah_capabilities.cap_queues.q_tx_num == 2) { 156 switch (queue_type) { 157 case AR5K_TX_QUEUE_DATA: 158 queue = AR5K_TX_QUEUE_ID_NOQCU_DATA; 159 break; 160 case AR5K_TX_QUEUE_BEACON: 161 case AR5K_TX_QUEUE_CAB: 162 queue = AR5K_TX_QUEUE_ID_NOQCU_BEACON; 163 break; 164 default: 165 return -EINVAL; 166 } 167 } else { 168 switch (queue_type) { 169 case AR5K_TX_QUEUE_DATA: 170 for (queue = AR5K_TX_QUEUE_ID_DATA_MIN; 171 ah->ah_txq[queue].tqi_type != 172 AR5K_TX_QUEUE_INACTIVE; queue++) { 173 174 if (queue > AR5K_TX_QUEUE_ID_DATA_MAX) 175 return -EINVAL; 176 } 177 break; 178 case AR5K_TX_QUEUE_UAPSD: 179 queue = AR5K_TX_QUEUE_ID_UAPSD; 180 break; 181 case AR5K_TX_QUEUE_BEACON: 182 queue = AR5K_TX_QUEUE_ID_BEACON; 183 break; 184 case AR5K_TX_QUEUE_CAB: 185 queue = AR5K_TX_QUEUE_ID_CAB; 186 break; 187 default: 188 return -EINVAL; 189 } 190 } 191 192 /* 193 * Setup internal queue structure 194 */ 195 memset(&ah->ah_txq[queue], 0, sizeof(struct ath5k_txq_info)); 196 ah->ah_txq[queue].tqi_type = queue_type; 197 198 if (queue_info != NULL) { 199 queue_info->tqi_type = queue_type; 200 ret = ath5k_hw_set_tx_queueprops(ah, queue, queue_info); 201 if (ret) 202 return ret; 203 } 204 205 /* 206 * We use ah_txq_status to hold a temp value for 207 * the Secondary interrupt mask registers on 5211+ 208 * check out ath5k_hw_reset_tx_queue 209 */ 210 AR5K_Q_ENABLE_BITS(ah->ah_txq_status, queue); 211 212 return queue; 213 } 214 215 216 /*******************************\ 217 * Single QCU/DCU initialization * 218 \*******************************/ 219 220 /* 221 * Set tx retry limits on DCU 222 */ 223 void ath5k_hw_set_tx_retry_limits(struct ath5k_hw *ah, 224 unsigned int queue) 225 { 226 /* Single data queue on AR5210 */ 227 if (ah->ah_version == AR5K_AR5210) { 228 struct ath5k_txq_info *tq = &ah->ah_txq[queue]; 229 230 if (queue > 0) 231 return; 232 233 ath5k_hw_reg_write(ah, 234 (tq->tqi_cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S) 235 | AR5K_REG_SM(ah->ah_retry_long, 236 AR5K_NODCU_RETRY_LMT_SLG_RETRY) 237 | AR5K_REG_SM(ah->ah_retry_short, 238 AR5K_NODCU_RETRY_LMT_SSH_RETRY) 239 | AR5K_REG_SM(ah->ah_retry_long, 240 AR5K_NODCU_RETRY_LMT_LG_RETRY) 241 | AR5K_REG_SM(ah->ah_retry_short, 242 AR5K_NODCU_RETRY_LMT_SH_RETRY), 243 AR5K_NODCU_RETRY_LMT); 244 /* DCU on AR5211+ */ 245 } else { 246 ath5k_hw_reg_write(ah, 247 AR5K_REG_SM(ah->ah_retry_long, 248 AR5K_DCU_RETRY_LMT_RTS) 249 | AR5K_REG_SM(ah->ah_retry_long, 250 AR5K_DCU_RETRY_LMT_STA_RTS) 251 | AR5K_REG_SM(max(ah->ah_retry_long, ah->ah_retry_short), 252 AR5K_DCU_RETRY_LMT_STA_DATA), 253 AR5K_QUEUE_DFS_RETRY_LIMIT(queue)); 254 } 255 } 256 257 /** 258 * ath5k_hw_reset_tx_queue - Initialize a single hw queue 259 * 260 * @ah The &struct ath5k_hw 261 * @queue The hw queue number 262 * 263 * Set DFS properties for the given transmit queue on DCU 264 * and configures all queue-specific parameters. 265 */ 266 int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) 267 { 268 struct ath5k_txq_info *tq = &ah->ah_txq[queue]; 269 270 AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); 271 272 tq = &ah->ah_txq[queue]; 273 274 /* Skip if queue inactive or if we are on AR5210 275 * that doesn't have QCU/DCU */ 276 if ((ah->ah_version == AR5K_AR5210) || 277 (tq->tqi_type == AR5K_TX_QUEUE_INACTIVE)) 278 return 0; 279 280 /* 281 * Set contention window (cw_min/cw_max) 282 * and arbitrated interframe space (aifs)... 283 */ 284 ath5k_hw_reg_write(ah, 285 AR5K_REG_SM(tq->tqi_cw_min, AR5K_DCU_LCL_IFS_CW_MIN) | 286 AR5K_REG_SM(tq->tqi_cw_max, AR5K_DCU_LCL_IFS_CW_MAX) | 287 AR5K_REG_SM(tq->tqi_aifs, AR5K_DCU_LCL_IFS_AIFS), 288 AR5K_QUEUE_DFS_LOCAL_IFS(queue)); 289 290 /* 291 * Set tx retry limits for this queue 292 */ 293 ath5k_hw_set_tx_retry_limits(ah, queue); 294 295 296 /* 297 * Set misc registers 298 */ 299 300 /* Enable DCU to wait for next fragment from QCU */ 301 AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), 302 AR5K_DCU_MISC_FRAG_WAIT); 303 304 /* On Maui and Spirit use the global seqnum on DCU */ 305 if (ah->ah_mac_version < AR5K_SREV_AR5211) 306 AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), 307 AR5K_DCU_MISC_SEQNUM_CTL); 308 309 /* Constant bit rate period */ 310 if (tq->tqi_cbr_period) { 311 ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period, 312 AR5K_QCU_CBRCFG_INTVAL) | 313 AR5K_REG_SM(tq->tqi_cbr_overflow_limit, 314 AR5K_QCU_CBRCFG_ORN_THRES), 315 AR5K_QUEUE_CBRCFG(queue)); 316 317 AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), 318 AR5K_QCU_MISC_FRSHED_CBR); 319 320 if (tq->tqi_cbr_overflow_limit) 321 AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), 322 AR5K_QCU_MISC_CBR_THRES_ENABLE); 323 } 324 325 /* Ready time interval */ 326 if (tq->tqi_ready_time && (tq->tqi_type != AR5K_TX_QUEUE_CAB)) 327 ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time, 328 AR5K_QCU_RDYTIMECFG_INTVAL) | 329 AR5K_QCU_RDYTIMECFG_ENABLE, 330 AR5K_QUEUE_RDYTIMECFG(queue)); 331 332 if (tq->tqi_burst_time) { 333 ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_burst_time, 334 AR5K_DCU_CHAN_TIME_DUR) | 335 AR5K_DCU_CHAN_TIME_ENABLE, 336 AR5K_QUEUE_DFS_CHANNEL_TIME(queue)); 337 338 if (tq->tqi_flags & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE) 339 AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), 340 AR5K_QCU_MISC_RDY_VEOL_POLICY); 341 } 342 343 /* Enable/disable Post frame backoff */ 344 if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE) 345 ath5k_hw_reg_write(ah, AR5K_DCU_MISC_POST_FR_BKOFF_DIS, 346 AR5K_QUEUE_DFS_MISC(queue)); 347 348 /* Enable/disable fragmentation burst backoff */ 349 if (tq->tqi_flags & AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) 350 ath5k_hw_reg_write(ah, AR5K_DCU_MISC_BACKOFF_FRAG, 351 AR5K_QUEUE_DFS_MISC(queue)); 352 353 /* 354 * Set registers by queue type 355 */ 356 switch (tq->tqi_type) { 357 case AR5K_TX_QUEUE_BEACON: 358 AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), 359 AR5K_QCU_MISC_FRSHED_DBA_GT | 360 AR5K_QCU_MISC_CBREXP_BCN_DIS | 361 AR5K_QCU_MISC_BCN_ENABLE); 362 363 AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), 364 (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL << 365 AR5K_DCU_MISC_ARBLOCK_CTL_S) | 366 AR5K_DCU_MISC_ARBLOCK_IGNORE | 367 AR5K_DCU_MISC_POST_FR_BKOFF_DIS | 368 AR5K_DCU_MISC_BCN_ENABLE); 369 break; 370 371 case AR5K_TX_QUEUE_CAB: 372 /* XXX: use BCN_SENT_GT, if we can figure out how */ 373 AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), 374 AR5K_QCU_MISC_FRSHED_DBA_GT | 375 AR5K_QCU_MISC_CBREXP_DIS | 376 AR5K_QCU_MISC_CBREXP_BCN_DIS); 377 378 ath5k_hw_reg_write(ah, ((tq->tqi_ready_time - 379 (AR5K_TUNE_SW_BEACON_RESP - 380 AR5K_TUNE_DMA_BEACON_RESP) - 381 AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) | 382 AR5K_QCU_RDYTIMECFG_ENABLE, 383 AR5K_QUEUE_RDYTIMECFG(queue)); 384 385 AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), 386 (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL << 387 AR5K_DCU_MISC_ARBLOCK_CTL_S)); 388 break; 389 390 case AR5K_TX_QUEUE_UAPSD: 391 AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), 392 AR5K_QCU_MISC_CBREXP_DIS); 393 break; 394 395 case AR5K_TX_QUEUE_DATA: 396 default: 397 break; 398 } 399 400 /* TODO: Handle frame compression */ 401 402 /* 403 * Enable interrupts for this tx queue 404 * in the secondary interrupt mask registers 405 */ 406 if (tq->tqi_flags & AR5K_TXQ_FLAG_TXOKINT_ENABLE) 407 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txok, queue); 408 409 if (tq->tqi_flags & AR5K_TXQ_FLAG_TXERRINT_ENABLE) 410 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txerr, queue); 411 412 if (tq->tqi_flags & AR5K_TXQ_FLAG_TXURNINT_ENABLE) 413 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txurn, queue); 414 415 if (tq->tqi_flags & AR5K_TXQ_FLAG_TXDESCINT_ENABLE) 416 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txdesc, queue); 417 418 if (tq->tqi_flags & AR5K_TXQ_FLAG_TXEOLINT_ENABLE) 419 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txeol, queue); 420 421 if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRORNINT_ENABLE) 422 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrorn, queue); 423 424 if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRURNINT_ENABLE) 425 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrurn, queue); 426 427 if (tq->tqi_flags & AR5K_TXQ_FLAG_QTRIGINT_ENABLE) 428 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_qtrig, queue); 429 430 if (tq->tqi_flags & AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE) 431 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_nofrm, queue); 432 433 /* Update secondary interrupt mask registers */ 434 435 /* Filter out inactive queues */ 436 ah->ah_txq_imr_txok &= ah->ah_txq_status; 437 ah->ah_txq_imr_txerr &= ah->ah_txq_status; 438 ah->ah_txq_imr_txurn &= ah->ah_txq_status; 439 ah->ah_txq_imr_txdesc &= ah->ah_txq_status; 440 ah->ah_txq_imr_txeol &= ah->ah_txq_status; 441 ah->ah_txq_imr_cbrorn &= ah->ah_txq_status; 442 ah->ah_txq_imr_cbrurn &= ah->ah_txq_status; 443 ah->ah_txq_imr_qtrig &= ah->ah_txq_status; 444 ah->ah_txq_imr_nofrm &= ah->ah_txq_status; 445 446 ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txok, 447 AR5K_SIMR0_QCU_TXOK) | 448 AR5K_REG_SM(ah->ah_txq_imr_txdesc, 449 AR5K_SIMR0_QCU_TXDESC), 450 AR5K_SIMR0); 451 452 ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txerr, 453 AR5K_SIMR1_QCU_TXERR) | 454 AR5K_REG_SM(ah->ah_txq_imr_txeol, 455 AR5K_SIMR1_QCU_TXEOL), 456 AR5K_SIMR1); 457 458 /* Update SIMR2 but don't overwrite rest simr2 settings */ 459 AR5K_REG_DISABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_QCU_TXURN); 460 AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2, 461 AR5K_REG_SM(ah->ah_txq_imr_txurn, 462 AR5K_SIMR2_QCU_TXURN)); 463 464 ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_cbrorn, 465 AR5K_SIMR3_QCBRORN) | 466 AR5K_REG_SM(ah->ah_txq_imr_cbrurn, 467 AR5K_SIMR3_QCBRURN), 468 AR5K_SIMR3); 469 470 ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_qtrig, 471 AR5K_SIMR4_QTRIG), AR5K_SIMR4); 472 473 /* Set TXNOFRM_QCU for the queues with TXNOFRM enabled */ 474 ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_nofrm, 475 AR5K_TXNOFRM_QCU), AR5K_TXNOFRM); 476 477 /* No queue has TXNOFRM enabled, disable the interrupt 478 * by setting AR5K_TXNOFRM to zero */ 479 if (ah->ah_txq_imr_nofrm == 0) 480 ath5k_hw_reg_write(ah, 0, AR5K_TXNOFRM); 481 482 /* Set QCU mask for this DCU to save power */ 483 AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(queue), queue); 484 485 return 0; 486 } 487 488 489 /**************************\ 490 * Global QCU/DCU functions * 491 \**************************/ 492 493 /** 494 * ath5k_hw_set_ifs_intervals - Set global inter-frame spaces on DCU 495 * 496 * @ah The &struct ath5k_hw 497 * @slot_time Slot time in us 498 * 499 * Sets the global IFS intervals on DCU (also works on AR5210) for 500 * the given slot time and the current bwmode. 501 */ 502 int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time) 503 { 504 struct ieee80211_channel *channel = ah->ah_current_channel; 505 struct ieee80211_rate *rate; 506 u32 ack_tx_time, eifs, eifs_clock, sifs, sifs_clock; 507 u32 slot_time_clock = ath5k_hw_htoclock(ah, slot_time); 508 509 if (slot_time < 6 || slot_time_clock > AR5K_SLOT_TIME_MAX) 510 return -EINVAL; 511 512 sifs = ath5k_hw_get_default_sifs(ah); 513 sifs_clock = ath5k_hw_htoclock(ah, sifs - 2); 514 515 /* EIFS 516 * Txtime of ack at lowest rate + SIFS + DIFS 517 * (DIFS = SIFS + 2 * Slot time) 518 * 519 * Note: HAL has some predefined values for EIFS 520 * Turbo: (37 + 2 * 6) 521 * Default: (74 + 2 * 9) 522 * Half: (149 + 2 * 13) 523 * Quarter: (298 + 2 * 21) 524 * 525 * (74 + 2 * 6) for AR5210 default and turbo ! 526 * 527 * According to the formula we have 528 * ack_tx_time = 25 for turbo and 529 * ack_tx_time = 42.5 * clock multiplier 530 * for default/half/quarter. 531 * 532 * This can't be right, 42 is what we would get 533 * from ath5k_hw_get_frame_dur_for_bwmode or 534 * ieee80211_generic_frame_duration for zero frame 535 * length and without SIFS ! 536 * 537 * Also we have different lowest rate for 802.11a 538 */ 539 if (channel->band == IEEE80211_BAND_5GHZ) 540 rate = &ah->sbands[IEEE80211_BAND_5GHZ].bitrates[0]; 541 else 542 rate = &ah->sbands[IEEE80211_BAND_2GHZ].bitrates[0]; 543 544 ack_tx_time = ath5k_hw_get_frame_duration(ah, 10, rate, false); 545 546 /* ack_tx_time includes an SIFS already */ 547 eifs = ack_tx_time + sifs + 2 * slot_time; 548 eifs_clock = ath5k_hw_htoclock(ah, eifs); 549 550 /* Set IFS settings on AR5210 */ 551 if (ah->ah_version == AR5K_AR5210) { 552 u32 pifs, pifs_clock, difs, difs_clock; 553 554 /* Set slot time */ 555 ath5k_hw_reg_write(ah, slot_time_clock, AR5K_SLOT_TIME); 556 557 /* Set EIFS */ 558 eifs_clock = AR5K_REG_SM(eifs_clock, AR5K_IFS1_EIFS); 559 560 /* PIFS = Slot time + SIFS */ 561 pifs = slot_time + sifs; 562 pifs_clock = ath5k_hw_htoclock(ah, pifs); 563 pifs_clock = AR5K_REG_SM(pifs_clock, AR5K_IFS1_PIFS); 564 565 /* DIFS = SIFS + 2 * Slot time */ 566 difs = sifs + 2 * slot_time; 567 difs_clock = ath5k_hw_htoclock(ah, difs); 568 569 /* Set SIFS/DIFS */ 570 ath5k_hw_reg_write(ah, (difs_clock << 571 AR5K_IFS0_DIFS_S) | sifs_clock, 572 AR5K_IFS0); 573 574 /* Set PIFS/EIFS and preserve AR5K_INIT_CARR_SENSE_EN */ 575 ath5k_hw_reg_write(ah, pifs_clock | eifs_clock | 576 (AR5K_INIT_CARR_SENSE_EN << AR5K_IFS1_CS_EN_S), 577 AR5K_IFS1); 578 579 return 0; 580 } 581 582 /* Set IFS slot time */ 583 ath5k_hw_reg_write(ah, slot_time_clock, AR5K_DCU_GBL_IFS_SLOT); 584 585 /* Set EIFS interval */ 586 ath5k_hw_reg_write(ah, eifs_clock, AR5K_DCU_GBL_IFS_EIFS); 587 588 /* Set SIFS interval in usecs */ 589 AR5K_REG_WRITE_BITS(ah, AR5K_DCU_GBL_IFS_MISC, 590 AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC, 591 sifs); 592 593 /* Set SIFS interval in clock cycles */ 594 ath5k_hw_reg_write(ah, sifs_clock, AR5K_DCU_GBL_IFS_SIFS); 595 596 return 0; 597 } 598 599 600 int ath5k_hw_init_queues(struct ath5k_hw *ah) 601 { 602 int i, ret; 603 604 /* TODO: HW Compression support for data queues */ 605 /* TODO: Burst prefetch for data queues */ 606 607 /* 608 * Reset queues and start beacon timers at the end of the reset routine 609 * This also sets QCU mask on each DCU for 1:1 qcu to dcu mapping 610 * Note: If we want we can assign multiple qcus on one dcu. 611 */ 612 if (ah->ah_version != AR5K_AR5210) 613 for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) { 614 ret = ath5k_hw_reset_tx_queue(ah, i); 615 if (ret) { 616 ATH5K_ERR(ah, 617 "failed to reset TX queue #%d\n", i); 618 return ret; 619 } 620 } 621 else 622 /* No QCU/DCU on AR5210, just set tx 623 * retry limits. We set IFS parameters 624 * on ath5k_hw_set_ifs_intervals */ 625 ath5k_hw_set_tx_retry_limits(ah, 0); 626 627 /* Set the turbo flag when operating on 40MHz */ 628 if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) 629 AR5K_REG_ENABLE_BITS(ah, AR5K_DCU_GBL_IFS_MISC, 630 AR5K_DCU_GBL_IFS_MISC_TURBO_MODE); 631 632 /* If we didn't set IFS timings through 633 * ath5k_hw_set_coverage_class make sure 634 * we set them here */ 635 if (!ah->ah_coverage_class) { 636 unsigned int slot_time = ath5k_hw_get_default_slottime(ah); 637 ath5k_hw_set_ifs_intervals(ah, slot_time); 638 } 639 640 return 0; 641 } 642