qcu.c (d4bbf7e7759afc172e2bfbc5c416324590049cdd) | qcu.c (c47faa364cfb249d5d7670fb7293a6f9acd8aa9e) |
---|---|
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/********************************************\ | 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/********************************************\ |
20Queue Control Unit, DFS Control Unit Functions | 20Queue Control Unit, DCF Control Unit Functions |
21\********************************************/ 22 23#include "ath5k.h" 24#include "reg.h" 25#include "debug.h" 26 | 21\********************************************/ 22 23#include "ath5k.h" 24#include "reg.h" 25#include "debug.h" 26 |
27/** 28 * DOC: Queue Control Unit (QCU)/DCF Control Unit (DCU) functions 29 * 30 * Here we setup parameters for the 12 available TX queues. Note that 31 * on the various registers we can usually only map the first 10 of them so 32 * basically we have 10 queues to play with. Each queue has a matching 33 * QCU that controls when the queue will get triggered and multiple QCUs 34 * can be mapped to a single DCU that controls the various DFS parameters 35 * for the various queues. In our setup we have a 1:1 mapping between QCUs 36 * and DCUs allowing us to have different DFS settings for each queue. 37 * 38 * When a frame goes into a TX queue, QCU decides when it'll trigger a 39 * transmission based on various criteria (such as how many data we have inside 40 * it's buffer or -if it's a beacon queue- if it's time to fire up the queue 41 * based on TSF etc), DCU adds backoff, IFSes etc and then a scheduler 42 * (arbitrator) decides the priority of each QCU based on it's configuration 43 * (e.g. beacons are always transmitted when they leave DCU bypassing all other 44 * frames from other queues waiting to be transmitted). After a frame leaves 45 * the DCU it goes to PCU for further processing and then to PHY for 46 * the actual transmission. 47 */ |
|
27 | 48 |
49 |
|
28/******************\ 29* Helper functions * 30\******************/ 31 | 50/******************\ 51* Helper functions * 52\******************/ 53 |
32/* 33 * Get number of pending frames 34 * for a specific queue [5211+] | 54/** 55 * ath5k_hw_num_tx_pending() - Get number of pending frames for a given queue 56 * @ah: The &struct ath5k_hw 57 * @queue: The hw queue number |
35 */ | 58 */ |
36u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) | 59u32 60ath5k_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 --- 8 unchanged lines hidden (view full) --- 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 u32 pending; 63 AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); 64 65 /* Return if queue is declared inactive */ 66 if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) 67 return false; 68 --- 8 unchanged lines hidden (view full) --- 77 * is set. To indicate that q has not stopped return 78 * true */ 79 if (!pending && AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue)) 80 return true; 81 82 return pending; 83} 84 |
61/* 62 * Set a transmit queue inactive | 85/** 86 * ath5k_hw_release_tx_queue() - Set a transmit queue inactive 87 * @ah: The &struct ath5k_hw 88 * @queue: The hw queue number |
63 */ | 89 */ |
64void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue) | 90void 91ath5k_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 | 92{ 93 if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num)) 94 return; 95 96 /* This queue will be skipped in further operations */ 97 ah->ah_txq[queue].tqi_type = AR5K_TX_QUEUE_INACTIVE; 98 /*For SIMR setup*/ 99 AR5K_Q_DISABLE_BITS(ah->ah_txq_status, queue); 100} 101 |
75/* | 102/** 103 * ath5k_cw_validate() - Make sure the given cw is valid 104 * @cw_req: The contention window value to check 105 * |
76 * Make sure cw is a power of 2 minus 1 and smaller than 1024 77 */ | 106 * Make sure cw is a power of 2 minus 1 and smaller than 1024 107 */ |
78static u16 ath5k_cw_validate(u16 cw_req) | 108static u16 109ath5k_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 | 110{ 111 u32 cw = 1; 112 cw_req = min(cw_req, (u16)1023); 113 114 while (cw < cw_req) 115 cw = (cw << 1) | 1; 116 117 return cw; 118} 119 |
89/* 90 * Get properties for a transmit queue | 120/** 121 * ath5k_hw_get_tx_queueprops() - Get properties for a transmit queue 122 * @ah: The &struct ath5k_hw 123 * @queue: The hw queue number 124 * @queue_info: The &struct ath5k_txq_info to fill |
91 */ | 125 */ |
92int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, | 126int 127ath5k_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 | 128 struct ath5k_txq_info *queue_info) 129{ 130 memcpy(queue_info, &ah->ah_txq[queue], sizeof(struct ath5k_txq_info)); 131 return 0; 132} 133 |
99/* 100 * Set properties for a transmit queue | 134/** 135 * ath5k_hw_set_tx_queueprops() - Set properties for a transmit queue 136 * @ah: The &struct ath5k_hw 137 * @queue: The hw queue number 138 * @qinfo: The &struct ath5k_txq_info to use 139 * 140 * Returns 0 on success or -EIO if queue is inactive |
101 */ | 141 */ |
102int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue, | 142int 143ath5k_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 --- 23 unchanged lines hidden (view full) --- 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 | 144 const struct ath5k_txq_info *qinfo) 145{ 146 struct ath5k_txq_info *qi; 147 148 AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); 149 150 qi = &ah->ah_txq[queue]; 151 --- 23 unchanged lines hidden (view full) --- 175 ((qinfo->tqi_subtype == AR5K_WME_AC_VI) || 176 (qinfo->tqi_subtype == AR5K_WME_AC_VO))) || 177 qinfo->tqi_type == AR5K_TX_QUEUE_UAPSD) 178 qi->tqi_flags |= AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS; 179 180 return 0; 181} 182 |
142/* 143 * Initialize a transmit queue | 183/** 184 * ath5k_hw_setup_tx_queue() - Initialize a transmit queue 185 * @ah: The &struct ath5k_hw 186 * @queue_type: One of enum ath5k_tx_queue 187 * @queue_info: The &struct ath5k_txq_info to use 188 * 189 * Returns 0 on success, -EINVAL on invalid arguments |
144 */ | 190 */ |
145int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type, | 191int 192ath5k_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 */ --- 58 unchanged lines hidden (view full) --- 212 return queue; 213} 214 215 216/*******************************\ 217* Single QCU/DCU initialization * 218\*******************************/ 219 | 193 struct ath5k_txq_info *queue_info) 194{ 195 unsigned int queue; 196 int ret; 197 198 /* 199 * Get queue by type 200 */ --- 58 unchanged lines hidden (view full) --- 259 return queue; 260} 261 262 263/*******************************\ 264* Single QCU/DCU initialization * 265\*******************************/ 266 |
220/* 221 * Set tx retry limits on DCU | 267/** 268 * ath5k_hw_set_tx_retry_limits() - Set tx retry limits on DCU 269 * @ah: The &struct ath5k_hw 270 * @queue: The hw queue number 271 * 272 * This function is used when initializing a queue, to set 273 * retry limits based on ah->ah_retry_* and the chipset used. |
222 */ | 274 */ |
223void ath5k_hw_set_tx_retry_limits(struct ath5k_hw *ah, | 275void 276ath5k_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; --- 18 unchanged lines hidden (view full) --- 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/** | 277 unsigned int queue) 278{ 279 /* Single data queue on AR5210 */ 280 if (ah->ah_version == AR5K_AR5210) { 281 struct ath5k_txq_info *tq = &ah->ah_txq[queue]; 282 283 if (queue > 0) 284 return; --- 18 unchanged lines hidden (view full) --- 303 AR5K_DCU_RETRY_LMT_STA_RTS) 304 | AR5K_REG_SM(max(ah->ah_retry_long, ah->ah_retry_short), 305 AR5K_DCU_RETRY_LMT_STA_DATA), 306 AR5K_QUEUE_DFS_RETRY_LIMIT(queue)); 307 } 308} 309 310/** |
258 * ath5k_hw_reset_tx_queue - Initialize a single hw queue | 311 * ath5k_hw_reset_tx_queue() - Initialize a single hw queue 312 * @ah: The &struct ath5k_hw 313 * @queue: The hw queue number |
259 * | 314 * |
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 */ | 315 * Set DFS properties for the given transmit queue on DCU 316 * and configures all queue-specific parameters. 317 */ |
266int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | 318int 319ath5k_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 --- 211 unchanged lines hidden (view full) --- 486} 487 488 489/**************************\ 490* Global QCU/DCU functions * 491\**************************/ 492 493/** | 320{ 321 struct ath5k_txq_info *tq = &ah->ah_txq[queue]; 322 323 AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); 324 325 tq = &ah->ah_txq[queue]; 326 327 /* Skip if queue inactive or if we are on AR5210 --- 211 unchanged lines hidden (view full) --- 539} 540 541 542/**************************\ 543* Global QCU/DCU functions * 544\**************************/ 545 546/** |
494 * ath5k_hw_set_ifs_intervals - Set global inter-frame spaces on DCU | 547 * ath5k_hw_set_ifs_intervals() - Set global inter-frame spaces on DCU 548 * @ah: The &struct ath5k_hw 549 * @slot_time: Slot time in us |
495 * | 550 * |
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 */ 502int 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; --- 85 unchanged lines hidden (view full) --- 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 | 551 * Sets the global IFS intervals on DCU (also works on AR5210) for 552 * the given slot time and the current bwmode. 553 */ 554int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time) 555{ 556 struct ieee80211_channel *channel = ah->ah_current_channel; 557 struct ieee80211_rate *rate; 558 u32 ack_tx_time, eifs, eifs_clock, sifs, sifs_clock; --- 85 unchanged lines hidden (view full) --- 644 645 /* Set SIFS interval in clock cycles */ 646 ath5k_hw_reg_write(ah, sifs_clock, AR5K_DCU_GBL_IFS_SIFS); 647 648 return 0; 649} 650 651 |
600int ath5k_hw_init_queues(struct ath5k_hw *ah) | 652/** 653 * ath5k_hw_init_queues() - Initialize tx queues 654 * @ah: The &struct ath5k_hw 655 * 656 * Initializes all tx queues based on information on 657 * ah->ah_txq* set by the driver 658 */ 659int 660ath5k_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 --- 33 unchanged lines hidden --- | 661{ 662 int i, ret; 663 664 /* TODO: HW Compression support for data queues */ 665 /* TODO: Burst prefetch for data queues */ 666 667 /* 668 * Reset queues and start beacon timers at the end of the reset routine --- 33 unchanged lines hidden --- |