#include <unistd.h>#include "ath5k.h"#include "reg.h"#include "base.h"Go to the source code of this file.
Functions | |
| FILE_LICENCE (MIT) | |
| void | ath5k_hw_start_rx_dma (struct ath5k_hw *ah) |
| ath5k_hw_start_rx_dma - Start DMA receive | |
| int | ath5k_hw_stop_rx_dma (struct ath5k_hw *ah) |
| ath5k_hw_stop_rx_dma - Stop DMA receive | |
| u32 | ath5k_hw_get_rxdp (struct ath5k_hw *ah) |
| ath5k_hw_get_rxdp - Get RX Descriptor's address | |
| void | ath5k_hw_set_rxdp (struct ath5k_hw *ah, u32 phys_addr) |
| ath5k_hw_set_rxdp - Set RX Descriptor's address | |
| int | ath5k_hw_start_tx_dma (struct ath5k_hw *ah, unsigned int queue) |
| ath5k_hw_start_tx_dma - Start DMA transmit for a specific queue | |
| int | ath5k_hw_stop_tx_dma (struct ath5k_hw *ah, unsigned int queue) |
| ath5k_hw_stop_tx_dma - Stop DMA transmit on a specific queue | |
| u32 | ath5k_hw_get_txdp (struct ath5k_hw *ah, unsigned int queue) |
| ath5k_hw_get_txdp - Get TX Descriptor's address for a specific queue | |
| int | ath5k_hw_set_txdp (struct ath5k_hw *ah, unsigned int queue, u32 phys_addr) |
| ath5k_hw_set_txdp - Set TX Descriptor's address for a specific queue | |
| int | ath5k_hw_update_tx_triglevel (struct ath5k_hw *ah, int increase) |
| ath5k_hw_update_tx_triglevel - Update tx trigger level | |
| int | ath5k_hw_is_intr_pending (struct ath5k_hw *ah) |
| ath5k_hw_is_intr_pending - Check if we have pending interrupts | |
| int | ath5k_hw_get_isr (struct ath5k_hw *ah, enum ath5k_int *interrupt_mask) |
| enum ath5k_int | ath5k_hw_set_imr (struct ath5k_hw *ah, enum ath5k_int new_mask) |
| ath5k_hw_set_imr - Set interrupt mask | |
| FILE_LICENCE | ( | MIT | ) |
| void ath5k_hw_start_rx_dma | ( | struct ath5k_hw * | ah | ) |
ath5k_hw_start_rx_dma - Start DMA receive
: The &struct ath5k_hw
Definition at line 54 of file ath5k_dma.c.
References AR5K_CR, AR5K_CR_RXE, ath5k_hw_reg_read(), and ath5k_hw_reg_write().
Referenced by ath5k_rx_start().
00055 { 00056 ath5k_hw_reg_write(ah, AR5K_CR_RXE, AR5K_CR); 00057 ath5k_hw_reg_read(ah, AR5K_CR); 00058 }
| int ath5k_hw_stop_rx_dma | ( | struct ath5k_hw * | ah | ) |
ath5k_hw_stop_rx_dma - Stop DMA receive
: The &struct ath5k_hw
Definition at line 65 of file ath5k_dma.c.
References AR5K_CR, AR5K_CR_RXD, AR5K_CR_RXE, ath5k_hw_reg_read(), ath5k_hw_reg_write(), EBUSY, and udelay().
Referenced by ath5k_rx_stop().
00066 { 00067 unsigned int i; 00068 00069 ath5k_hw_reg_write(ah, AR5K_CR_RXD, AR5K_CR); 00070 00071 /* 00072 * It may take some time to disable the DMA receive unit 00073 */ 00074 for (i = 1000; i > 0 && 00075 (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) != 0; 00076 i--) 00077 udelay(10); 00078 00079 return i ? 0 : -EBUSY; 00080 }
ath5k_hw_get_rxdp - Get RX Descriptor's address
: The &struct ath5k_hw
XXX: Is RXDP read and clear ?
Definition at line 89 of file ath5k_dma.c.
References AR5K_RXDP, and ath5k_hw_reg_read().
00090 { 00091 return ath5k_hw_reg_read(ah, AR5K_RXDP); 00092 }
ath5k_hw_set_rxdp - Set RX Descriptor's address
: The &struct ath5k_hw : RX descriptor address
XXX: Should we check if rx is enabled before setting rxdp ?
Definition at line 102 of file ath5k_dma.c.
References AR5K_RXDP, and ath5k_hw_reg_write().
Referenced by ath5k_rx_start().
00103 { 00104 ath5k_hw_reg_write(ah, phys_addr, AR5K_RXDP); 00105 }
| int ath5k_hw_start_tx_dma | ( | struct ath5k_hw * | ah, | |
| unsigned int | queue | |||
| ) |
ath5k_hw_start_tx_dma - Start DMA transmit for a specific queue
: The &struct ath5k_hw : The hw queue number
Start DMA transmit for a specific queue and since 5210 doesn't have QCU/DCU, set up queue parameters for 5210 here based on queue type (one queue for normal data and one queue for beacons). For queue setup on newer chips check out qcu.c. Returns -EINVAL if queue number is out of range or if queue is already disabled.
NOTE: Must be called after setting up tx control descriptor for that queue (see below).
Definition at line 127 of file ath5k_dma.c.
References ath5k_hw::ah_txq, ath5k_hw::ah_version, AR5K_AR5210, AR5K_CR, AR5K_CR_TXD0, AR5K_CR_TXE0, AR5K_QCU_TXD, AR5K_QCU_TXE, AR5K_REG_READ_Q, AR5K_REG_WRITE_Q, AR5K_TX_QUEUE_INACTIVE, ath5k_hw_reg_read(), ath5k_hw_reg_write(), EIO, ath5k_txq_info::tqi_type, and u32.
Referenced by ath5k_txbuf_setup().
00128 { 00129 u32 tx_queue; 00130 00131 /* Return if queue is declared inactive */ 00132 if (ah->ah_txq.tqi_type == AR5K_TX_QUEUE_INACTIVE) 00133 return -EIO; 00134 00135 if (ah->ah_version == AR5K_AR5210) { 00136 tx_queue = ath5k_hw_reg_read(ah, AR5K_CR); 00137 00138 /* Assume always a data queue */ 00139 tx_queue |= AR5K_CR_TXE0 & ~AR5K_CR_TXD0; 00140 00141 /* Start queue */ 00142 ath5k_hw_reg_write(ah, tx_queue, AR5K_CR); 00143 ath5k_hw_reg_read(ah, AR5K_CR); 00144 } else { 00145 /* Return if queue is disabled */ 00146 if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXD, queue)) 00147 return -EIO; 00148 00149 /* Start queue */ 00150 AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXE, queue); 00151 } 00152 00153 return 0; 00154 }
| int ath5k_hw_stop_tx_dma | ( | struct ath5k_hw * | ah, | |
| unsigned int | queue | |||
| ) |
ath5k_hw_stop_tx_dma - Stop DMA transmit on a specific queue
: The &struct ath5k_hw : The hw queue number
Stop DMA transmit on a specific hw queue and drain queue so we don't have any pending frames. Returns -EBUSY if we still have pending frames, -EINVAL if queue number is out of range.
Definition at line 167 of file ath5k_dma.c.
References ath5k_hw::ah_mac_version, ath5k_hw::ah_txq, ath5k_hw::ah_version, AR5K_AR5210, AR5K_CR, AR5K_CR_TXD0, AR5K_CR_TXE0, AR5K_DIAG_SW_5211, AR5K_DIAG_SW_CHANEL_IDLE_HIGH, AR5K_QCU_STS_FRMPENDCNT, AR5K_QCU_TXD, AR5K_QUEUE_STATUS, AR5K_QUIET_CTL1, AR5K_QUIET_CTL1_NEXT_QT_TSF, AR5K_QUIET_CTL1_QT_EN, AR5K_QUIET_CTL2, AR5K_QUIET_CTL2_QT_DUR, AR5K_QUIET_CTL2_QT_PER, AR5K_REG_DISABLE_BITS, AR5K_REG_ENABLE_BITS, AR5K_REG_SM, AR5K_REG_WRITE_Q, AR5K_SREV_AR2414, AR5K_TSF_L32_5211, AR5K_TX_QUEUE_INACTIVE, ath5k_hw_reg_read(), ath5k_hw_reg_write(), EBUSY, EIO, ath5k_txq_info::tqi_type, u32, and udelay().
Referenced by ath5k_txq_cleanup().
00168 { 00169 unsigned int i = 40; 00170 u32 tx_queue, pending; 00171 00172 /* Return if queue is declared inactive */ 00173 if (ah->ah_txq.tqi_type == AR5K_TX_QUEUE_INACTIVE) 00174 return -EIO; 00175 00176 if (ah->ah_version == AR5K_AR5210) { 00177 tx_queue = ath5k_hw_reg_read(ah, AR5K_CR); 00178 00179 /* Assume a data queue */ 00180 tx_queue |= AR5K_CR_TXD0 & ~AR5K_CR_TXE0; 00181 00182 /* Stop queue */ 00183 ath5k_hw_reg_write(ah, tx_queue, AR5K_CR); 00184 ath5k_hw_reg_read(ah, AR5K_CR); 00185 } else { 00186 /* 00187 * Schedule TX disable and wait until queue is empty 00188 */ 00189 AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXD, queue); 00190 00191 /*Check for pending frames*/ 00192 do { 00193 pending = ath5k_hw_reg_read(ah, 00194 AR5K_QUEUE_STATUS(queue)) & 00195 AR5K_QCU_STS_FRMPENDCNT; 00196 udelay(100); 00197 } while (--i && pending); 00198 00199 /* For 2413+ order PCU to drop packets using 00200 * QUIET mechanism */ 00201 if (ah->ah_mac_version >= (AR5K_SREV_AR2414 >> 4) && pending) { 00202 /* Set periodicity and duration */ 00203 ath5k_hw_reg_write(ah, 00204 AR5K_REG_SM(100, AR5K_QUIET_CTL2_QT_PER)| 00205 AR5K_REG_SM(10, AR5K_QUIET_CTL2_QT_DUR), 00206 AR5K_QUIET_CTL2); 00207 00208 /* Enable quiet period for current TSF */ 00209 ath5k_hw_reg_write(ah, 00210 AR5K_QUIET_CTL1_QT_EN | 00211 AR5K_REG_SM(ath5k_hw_reg_read(ah, 00212 AR5K_TSF_L32_5211) >> 10, 00213 AR5K_QUIET_CTL1_NEXT_QT_TSF), 00214 AR5K_QUIET_CTL1); 00215 00216 /* Force channel idle high */ 00217 AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211, 00218 AR5K_DIAG_SW_CHANEL_IDLE_HIGH); 00219 00220 /* Wait a while and disable mechanism */ 00221 udelay(200); 00222 AR5K_REG_DISABLE_BITS(ah, AR5K_QUIET_CTL1, 00223 AR5K_QUIET_CTL1_QT_EN); 00224 00225 /* Re-check for pending frames */ 00226 i = 40; 00227 do { 00228 pending = ath5k_hw_reg_read(ah, 00229 AR5K_QUEUE_STATUS(queue)) & 00230 AR5K_QCU_STS_FRMPENDCNT; 00231 udelay(100); 00232 } while (--i && pending); 00233 00234 AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5211, 00235 AR5K_DIAG_SW_CHANEL_IDLE_HIGH); 00236 } 00237 00238 /* Clear register */ 00239 ath5k_hw_reg_write(ah, 0, AR5K_QCU_TXD); 00240 if (pending) 00241 return -EBUSY; 00242 } 00243 00244 /* TODO: Check for success on 5210 else return error */ 00245 return 0; 00246 }
ath5k_hw_get_txdp - Get TX Descriptor's address for a specific queue
: The &struct ath5k_hw : The hw queue number
Get TX descriptor's address for a specific queue. For 5210 we ignore the queue number and use tx queue type since we only have 2 queues. We use TXDP0 for normal data queue and TXDP1 for beacon queue. For newer chips with QCU/DCU we just read the corresponding TXDP register.
XXX: Is TXDP read and clear ?
Definition at line 261 of file ath5k_dma.c.
References ath5k_hw::ah_version, AR5K_AR5210, AR5K_NOQCU_TXDP0, AR5K_QUEUE_TXDP, ath5k_hw_reg_read(), and u16.
Referenced by ath5k_txq_cleanup().
00262 { 00263 u16 tx_reg; 00264 00265 /* 00266 * Get the transmit queue descriptor pointer from the selected queue 00267 */ 00268 /*5210 doesn't have QCU*/ 00269 if (ah->ah_version == AR5K_AR5210) { 00270 /* Assume a data queue */ 00271 tx_reg = AR5K_NOQCU_TXDP0; 00272 } else { 00273 tx_reg = AR5K_QUEUE_TXDP(queue); 00274 } 00275 00276 return ath5k_hw_reg_read(ah, tx_reg); 00277 }
ath5k_hw_set_txdp - Set TX Descriptor's address for a specific queue
: The &struct ath5k_hw : The hw queue number
Set TX descriptor's address for a specific queue. For 5210 we ignore the queue number and we use tx queue type since we only have 2 queues so as above we use TXDP0 for normal data queue and TXDP1 for beacon queue. For newer chips with QCU/DCU we just set the corresponding TXDP register. Returns -EINVAL if queue type is invalid for 5210 and -EIO if queue is still active.
Definition at line 292 of file ath5k_dma.c.
References ath5k_hw::ah_version, AR5K_AR5210, AR5K_NOQCU_TXDP0, AR5K_QCU_TXE, AR5K_QUEUE_TXDP, AR5K_REG_READ_Q, ath5k_hw_reg_write(), EIO, and u16.
Referenced by ath5k_txbuf_setup().
00293 { 00294 u16 tx_reg; 00295 00296 /* 00297 * Set the transmit queue descriptor pointer register by type 00298 * on 5210 00299 */ 00300 if (ah->ah_version == AR5K_AR5210) { 00301 /* Assume a data queue */ 00302 tx_reg = AR5K_NOQCU_TXDP0; 00303 } else { 00304 /* 00305 * Set the transmit queue descriptor pointer for 00306 * the selected queue on QCU for 5211+ 00307 * (this won't work if the queue is still active) 00308 */ 00309 if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue)) 00310 return -EIO; 00311 00312 tx_reg = AR5K_QUEUE_TXDP(queue); 00313 } 00314 00315 /* Set descriptor pointer */ 00316 ath5k_hw_reg_write(ah, phys_addr, tx_reg); 00317 00318 return 0; 00319 }
| int ath5k_hw_update_tx_triglevel | ( | struct ath5k_hw * | ah, | |
| int | increase | |||
| ) |
ath5k_hw_update_tx_triglevel - Update tx trigger level
: The &struct ath5k_hw : Flag to force increase of trigger level
This function increases/decreases the tx trigger level for the tx fifo buffer (aka FIFO threshold) that is used to indicate when PCU flushes the buffer and transmits it's data. Lowering this results sending small frames more quickly but can lead to tx underruns, raising it a lot can result other problems (i think bmiss is related). Right now we start with the lowest possible (64Bytes) and if we get tx underrun we increase it using the increase flag. Returns -EIO if we have have reached maximum/minimum.
XXX: Link this with tx DMA size ? XXX: Use it to save interrupts ? TODO: Needs testing, i think it's related to bmiss...
Definition at line 339 of file ath5k_dma.c.
References ath5k_hw::ah_imr, ath5k_hw::ah_version, AR5K_AR5210, AR5K_INT_GLOBAL, AR5K_REG_MS, AR5K_REG_WRITE_BITS, AR5K_TRIG_LVL, AR5K_TUNE_MAX_TX_FIFO_THRES, AR5K_TUNE_MIN_TX_FIFO_THRES, AR5K_TXCFG, AR5K_TXCFG_TXFULL, ath5k_hw_reg_read(), ath5k_hw_reg_write(), ath5k_hw_set_imr(), EIO, imr, and u32.
Referenced by ath5k_poll().
00340 { 00341 u32 trigger_level, imr; 00342 int ret = -EIO; 00343 00344 /* 00345 * Disable interrupts by setting the mask 00346 */ 00347 imr = ath5k_hw_set_imr(ah, ah->ah_imr & ~AR5K_INT_GLOBAL); 00348 00349 trigger_level = AR5K_REG_MS(ath5k_hw_reg_read(ah, AR5K_TXCFG), 00350 AR5K_TXCFG_TXFULL); 00351 00352 if (!increase) { 00353 if (--trigger_level < AR5K_TUNE_MIN_TX_FIFO_THRES) 00354 goto done; 00355 } else 00356 trigger_level += 00357 ((AR5K_TUNE_MAX_TX_FIFO_THRES - trigger_level) / 2); 00358 00359 /* 00360 * Update trigger level on success 00361 */ 00362 if (ah->ah_version == AR5K_AR5210) 00363 ath5k_hw_reg_write(ah, trigger_level, AR5K_TRIG_LVL); 00364 else 00365 AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, 00366 AR5K_TXCFG_TXFULL, trigger_level); 00367 00368 ret = 0; 00369 00370 done: 00371 /* 00372 * Restore interrupt mask 00373 */ 00374 ath5k_hw_set_imr(ah, imr); 00375 00376 return ret; 00377 }
| int ath5k_hw_is_intr_pending | ( | struct ath5k_hw * | ah | ) |
ath5k_hw_is_intr_pending - Check if we have pending interrupts
: The &struct ath5k_hw
Check if we have pending interrupts to process. Returns 1 if we have pending interrupts and 0 if we haven't.
Definition at line 391 of file ath5k_dma.c.
References AR5K_INTPEND, and ath5k_hw_reg_read().
Referenced by ath5k_poll().
00392 { 00393 return ath5k_hw_reg_read(ah, AR5K_INTPEND) == 1 ? 1 : 0; 00394 }
Definition at line 412 of file ath5k_dma.c.
References ath5k_hw::ah_imr, ath5k_hw::ah_txq_isr, ath5k_hw::ah_version, AR5K_AR5210, AR5K_INT_BCN_TIMEOUT, AR5K_INT_BNR, AR5K_INT_CAB_TIMEOUT, AR5K_INT_COMMON, AR5K_INT_DTIM, AR5K_INT_DTIM_SYNC, AR5K_INT_FATAL, AR5K_INT_NOCARD, AR5K_INT_QCBRORN, AR5K_INT_QCBRURN, AR5K_INT_QTRIG, AR5K_INT_RX_DOPPLER, AR5K_INT_TIM, AR5K_ISR, AR5K_ISR_BCNMISC, AR5K_ISR_BNR, AR5K_ISR_DPERR, AR5K_ISR_HIUERR, AR5K_ISR_MCABT, AR5K_ISR_QCBRORN, AR5K_ISR_QCBRURN, AR5K_ISR_QTRIG, AR5K_ISR_RXDOPPLER, AR5K_ISR_SSERR, AR5K_ISR_TIM, AR5K_ISR_TXDESC, AR5K_ISR_TXEOL, AR5K_ISR_TXERR, AR5K_ISR_TXOK, AR5K_ISR_TXURN, AR5K_RAC_PISR, AR5K_RAC_SISR0, AR5K_RAC_SISR1, AR5K_RAC_SISR2, AR5K_RAC_SISR3, AR5K_RAC_SISR4, AR5K_REG_MS, AR5K_SISR0_QCU_TXDESC, AR5K_SISR0_QCU_TXOK, AR5K_SISR1_QCU_TXEOL, AR5K_SISR1_QCU_TXERR, AR5K_SISR2_BCN_TIMEOUT, AR5K_SISR2_CAB_TIMEOUT, AR5K_SISR2_DPERR, AR5K_SISR2_DTIM, AR5K_SISR2_DTIM_SYNC, AR5K_SISR2_MCABT, AR5K_SISR2_QCU_TXURN, AR5K_SISR2_SSERR, AR5K_SISR2_TIM, AR5K_SISR3_QCBRORN, AR5K_SISR3_QCBRURN, AR5K_SISR4_QTRIG, ath5k_hw_reg_read(), ENODEV, and u32.
Referenced by ath5k_poll().
00413 { 00414 u32 data; 00415 00416 /* 00417 * Read interrupt status from the Interrupt Status register 00418 * on 5210 00419 */ 00420 if (ah->ah_version == AR5K_AR5210) { 00421 data = ath5k_hw_reg_read(ah, AR5K_ISR); 00422 if (data == AR5K_INT_NOCARD) { 00423 *interrupt_mask = data; 00424 return -ENODEV; 00425 } 00426 } else { 00427 /* 00428 * Read interrupt status from Interrupt 00429 * Status Register shadow copy (Read And Clear) 00430 * 00431 * Note: PISR/SISR Not available on 5210 00432 */ 00433 data = ath5k_hw_reg_read(ah, AR5K_RAC_PISR); 00434 if (data == AR5K_INT_NOCARD) { 00435 *interrupt_mask = data; 00436 return -ENODEV; 00437 } 00438 } 00439 00440 /* 00441 * Get abstract interrupt mask (driver-compatible) 00442 */ 00443 *interrupt_mask = (data & AR5K_INT_COMMON) & ah->ah_imr; 00444 00445 if (ah->ah_version != AR5K_AR5210) { 00446 u32 sisr2 = ath5k_hw_reg_read(ah, AR5K_RAC_SISR2); 00447 00448 /*HIU = Host Interface Unit (PCI etc)*/ 00449 if (data & (AR5K_ISR_HIUERR)) 00450 *interrupt_mask |= AR5K_INT_FATAL; 00451 00452 /*Beacon Not Ready*/ 00453 if (data & (AR5K_ISR_BNR)) 00454 *interrupt_mask |= AR5K_INT_BNR; 00455 00456 if (sisr2 & (AR5K_SISR2_SSERR | AR5K_SISR2_DPERR | 00457 AR5K_SISR2_MCABT)) 00458 *interrupt_mask |= AR5K_INT_FATAL; 00459 00460 if (data & AR5K_ISR_TIM) 00461 *interrupt_mask |= AR5K_INT_TIM; 00462 00463 if (data & AR5K_ISR_BCNMISC) { 00464 if (sisr2 & AR5K_SISR2_TIM) 00465 *interrupt_mask |= AR5K_INT_TIM; 00466 if (sisr2 & AR5K_SISR2_DTIM) 00467 *interrupt_mask |= AR5K_INT_DTIM; 00468 if (sisr2 & AR5K_SISR2_DTIM_SYNC) 00469 *interrupt_mask |= AR5K_INT_DTIM_SYNC; 00470 if (sisr2 & AR5K_SISR2_BCN_TIMEOUT) 00471 *interrupt_mask |= AR5K_INT_BCN_TIMEOUT; 00472 if (sisr2 & AR5K_SISR2_CAB_TIMEOUT) 00473 *interrupt_mask |= AR5K_INT_CAB_TIMEOUT; 00474 } 00475 00476 if (data & AR5K_ISR_RXDOPPLER) 00477 *interrupt_mask |= AR5K_INT_RX_DOPPLER; 00478 if (data & AR5K_ISR_QCBRORN) { 00479 *interrupt_mask |= AR5K_INT_QCBRORN; 00480 ah->ah_txq_isr |= AR5K_REG_MS( 00481 ath5k_hw_reg_read(ah, AR5K_RAC_SISR3), 00482 AR5K_SISR3_QCBRORN); 00483 } 00484 if (data & AR5K_ISR_QCBRURN) { 00485 *interrupt_mask |= AR5K_INT_QCBRURN; 00486 ah->ah_txq_isr |= AR5K_REG_MS( 00487 ath5k_hw_reg_read(ah, AR5K_RAC_SISR3), 00488 AR5K_SISR3_QCBRURN); 00489 } 00490 if (data & AR5K_ISR_QTRIG) { 00491 *interrupt_mask |= AR5K_INT_QTRIG; 00492 ah->ah_txq_isr |= AR5K_REG_MS( 00493 ath5k_hw_reg_read(ah, AR5K_RAC_SISR4), 00494 AR5K_SISR4_QTRIG); 00495 } 00496 00497 if (data & AR5K_ISR_TXOK) 00498 ah->ah_txq_isr |= AR5K_REG_MS( 00499 ath5k_hw_reg_read(ah, AR5K_RAC_SISR0), 00500 AR5K_SISR0_QCU_TXOK); 00501 00502 if (data & AR5K_ISR_TXDESC) 00503 ah->ah_txq_isr |= AR5K_REG_MS( 00504 ath5k_hw_reg_read(ah, AR5K_RAC_SISR0), 00505 AR5K_SISR0_QCU_TXDESC); 00506 00507 if (data & AR5K_ISR_TXERR) 00508 ah->ah_txq_isr |= AR5K_REG_MS( 00509 ath5k_hw_reg_read(ah, AR5K_RAC_SISR1), 00510 AR5K_SISR1_QCU_TXERR); 00511 00512 if (data & AR5K_ISR_TXEOL) 00513 ah->ah_txq_isr |= AR5K_REG_MS( 00514 ath5k_hw_reg_read(ah, AR5K_RAC_SISR1), 00515 AR5K_SISR1_QCU_TXEOL); 00516 00517 if (data & AR5K_ISR_TXURN) 00518 ah->ah_txq_isr |= AR5K_REG_MS( 00519 ath5k_hw_reg_read(ah, AR5K_RAC_SISR2), 00520 AR5K_SISR2_QCU_TXURN); 00521 } else { 00522 if (data & (AR5K_ISR_SSERR | AR5K_ISR_MCABT | 00523 AR5K_ISR_HIUERR | AR5K_ISR_DPERR)) 00524 *interrupt_mask |= AR5K_INT_FATAL; 00525 00526 /* 00527 * XXX: BMISS interrupts may occur after association. 00528 * I found this on 5210 code but it needs testing. If this is 00529 * true we should disable them before assoc and re-enable them 00530 * after a successful assoc + some jiffies. 00531 interrupt_mask &= ~AR5K_INT_BMISS; 00532 */ 00533 } 00534 00535 return 0; 00536 }
ath5k_hw_set_imr - Set interrupt mask
: The &struct ath5k_hw : The new interrupt mask to be set
Set the interrupt mask in hw to save interrupts. We do that by mapping ath5k_int bits to hw-specific bits to remove abstraction and writing Interrupt Mask Register.
Definition at line 548 of file ath5k_dma.c.
References ath5k_hw::ah_ier, ath5k_hw::ah_imr, ath5k_hw::ah_version, AR5K_AR5210, AR5K_IER, AR5K_IER_DISABLE, AR5K_IMR, AR5K_IMR_DPERR, AR5K_IMR_HIUERR, AR5K_IMR_MCABT, AR5K_IMR_RXDOPPLER, AR5K_IMR_SSERR, AR5K_IMR_TIM, AR5K_INT_BCN_TIMEOUT, AR5K_INT_BNR, AR5K_INT_CAB_TIMEOUT, AR5K_INT_COMMON, AR5K_INT_DTIM, AR5K_INT_DTIM_SYNC, AR5K_INT_FATAL, AR5K_INT_GLOBAL, AR5K_INT_RX_DOPPLER, AR5K_INT_RXNOFRM, AR5K_INT_TIM, AR5K_PIMR, AR5K_RXNOFRM, AR5K_SIMR2, AR5K_SIMR2_DPERR, AR5K_SIMR2_MCABT, AR5K_SIMR2_QCU_TXURN, AR5K_SIMR2_SSERR, AR5K_SISR2_BCN_TIMEOUT, AR5K_SISR2_CAB_TIMEOUT, AR5K_SISR2_DTIM, AR5K_SISR2_DTIM_SYNC, AR5K_SISR2_TIM, ath5k_hw_reg_read(), ath5k_hw_reg_write(), and u32.
Referenced by ath5k_hw_reset(), ath5k_hw_update_tx_triglevel(), ath5k_irq(), ath5k_reset(), and ath5k_stop_hw().
00549 { 00550 enum ath5k_int old_mask, int_mask; 00551 00552 old_mask = ah->ah_imr; 00553 00554 /* 00555 * Disable card interrupts to prevent any race conditions 00556 * (they will be re-enabled afterwards if AR5K_INT GLOBAL 00557 * is set again on the new mask). 00558 */ 00559 if (old_mask & AR5K_INT_GLOBAL) { 00560 ath5k_hw_reg_write(ah, AR5K_IER_DISABLE, AR5K_IER); 00561 ath5k_hw_reg_read(ah, AR5K_IER); 00562 } 00563 00564 /* 00565 * Add additional, chipset-dependent interrupt mask flags 00566 * and write them to the IMR (interrupt mask register). 00567 */ 00568 int_mask = new_mask & AR5K_INT_COMMON; 00569 00570 if (ah->ah_version != AR5K_AR5210) { 00571 /* Preserve per queue TXURN interrupt mask */ 00572 u32 simr2 = ath5k_hw_reg_read(ah, AR5K_SIMR2) 00573 & AR5K_SIMR2_QCU_TXURN; 00574 00575 if (new_mask & AR5K_INT_FATAL) { 00576 int_mask |= AR5K_IMR_HIUERR; 00577 simr2 |= (AR5K_SIMR2_MCABT | AR5K_SIMR2_SSERR 00578 | AR5K_SIMR2_DPERR); 00579 } 00580 00581 /*Beacon Not Ready*/ 00582 if (new_mask & AR5K_INT_BNR) 00583 int_mask |= AR5K_INT_BNR; 00584 00585 if (new_mask & AR5K_INT_TIM) 00586 int_mask |= AR5K_IMR_TIM; 00587 00588 if (new_mask & AR5K_INT_TIM) 00589 simr2 |= AR5K_SISR2_TIM; 00590 if (new_mask & AR5K_INT_DTIM) 00591 simr2 |= AR5K_SISR2_DTIM; 00592 if (new_mask & AR5K_INT_DTIM_SYNC) 00593 simr2 |= AR5K_SISR2_DTIM_SYNC; 00594 if (new_mask & AR5K_INT_BCN_TIMEOUT) 00595 simr2 |= AR5K_SISR2_BCN_TIMEOUT; 00596 if (new_mask & AR5K_INT_CAB_TIMEOUT) 00597 simr2 |= AR5K_SISR2_CAB_TIMEOUT; 00598 00599 if (new_mask & AR5K_INT_RX_DOPPLER) 00600 int_mask |= AR5K_IMR_RXDOPPLER; 00601 00602 /* Note: Per queue interrupt masks 00603 * are set via reset_tx_queue (qcu.c) */ 00604 ath5k_hw_reg_write(ah, int_mask, AR5K_PIMR); 00605 ath5k_hw_reg_write(ah, simr2, AR5K_SIMR2); 00606 00607 } else { 00608 if (new_mask & AR5K_INT_FATAL) 00609 int_mask |= (AR5K_IMR_SSERR | AR5K_IMR_MCABT 00610 | AR5K_IMR_HIUERR | AR5K_IMR_DPERR); 00611 00612 ath5k_hw_reg_write(ah, int_mask, AR5K_IMR); 00613 } 00614 00615 /* If RXNOFRM interrupt is masked disable it 00616 * by setting AR5K_RXNOFRM to zero */ 00617 if (!(new_mask & AR5K_INT_RXNOFRM)) 00618 ath5k_hw_reg_write(ah, 0, AR5K_RXNOFRM); 00619 00620 /* Store new interrupt mask */ 00621 ah->ah_imr = new_mask; 00622 00623 /* ..re-enable interrupts if AR5K_INT_GLOBAL is set */ 00624 if (new_mask & AR5K_INT_GLOBAL) { 00625 ath5k_hw_reg_write(ah, ah->ah_ier, AR5K_IER); 00626 ath5k_hw_reg_read(ah, AR5K_IER); 00627 } 00628 00629 return old_mask; 00630 }
1.5.7.1