1c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis/* 2c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org> 3c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com> 4c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * 5c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * Permission to use, copy, modify, and distribute this software for any 6c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * purpose with or without fee is hereby granted, provided that the above 7c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * copyright notice and this permission notice appear in all copies. 8c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * 9c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * 17c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 18c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 19c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis/*************************************\ 20c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis* DMA and interrupt masking functions * 21c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis\*************************************/ 22c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 23c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis/** 24c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * DOC: DMA and interrupt masking functions 25c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * 26c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * Here we setup descriptor pointers (rxdp/txdp) start/stop dma engine and 27c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * handle queue setup for 5210 chipset (rest are handled on qcu.c). 286a2a0e738225fc9ec063f84b79f0adf5c0ed176cPavel Roskin * Also we setup interrupt mask register (IMR) and read the various interrupt 29c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * status registers (ISR). 30c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 31c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 32c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis#include "ath5k.h" 33c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis#include "reg.h" 34c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis#include "debug.h" 35c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 369320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis 37c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis/*********\ 38c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis* Receive * 39c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis\*********/ 40c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 41c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis/** 42c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * ath5k_hw_start_rx_dma() - Start DMA receive 43c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * @ah: The &struct ath5k_hw 44c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 45c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisvoid 46c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisath5k_hw_start_rx_dma(struct ath5k_hw *ah) 47c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis{ 48c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis ath5k_hw_reg_write(ah, AR5K_CR_RXE, AR5K_CR); 49c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis ath5k_hw_reg_read(ah, AR5K_CR); 50c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis} 51c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 52c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis/** 53c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * ath5k_hw_stop_rx_dma() - Stop DMA receive 54c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * @ah: The &struct ath5k_hw 55c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 56c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisstatic int 57c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisath5k_hw_stop_rx_dma(struct ath5k_hw *ah) 58c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis{ 59c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis unsigned int i; 60c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 61c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis ath5k_hw_reg_write(ah, AR5K_CR_RXD, AR5K_CR); 62c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 63c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis /* 64c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * It may take some time to disable the DMA receive unit 65c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 66509a106e68aa42acc1a0c44ab365d0de6869bd9eNick Kossifidis for (i = 1000; i > 0 && 67c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) != 0; 68c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis i--) 69b3a28e68d5c8d788a4e538a119a5d326545add8aNick Kossifidis udelay(100); 70b3a28e68d5c8d788a4e538a119a5d326545add8aNick Kossifidis 71f0e134a53ad95ba7a393b299ae56c9bdcaed8aecNick Kossifidis if (!i) 72e0d687bd9df218ba3d97aac15919d30816d72dcbPavel Roskin ATH5K_DBG(ah, ATH5K_DEBUG_DMA, 73b3a28e68d5c8d788a4e538a119a5d326545add8aNick Kossifidis "failed to stop RX DMA !\n"); 74c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 75c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis return i ? 0 : -EBUSY; 76c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis} 77c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 78c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis/** 79c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * ath5k_hw_get_rxdp() - Get RX Descriptor's address 80c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * @ah: The &struct ath5k_hw 81c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 82c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisu32 83c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisath5k_hw_get_rxdp(struct ath5k_hw *ah) 84c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis{ 85c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis return ath5k_hw_reg_read(ah, AR5K_RXDP); 86c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis} 87c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 88c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis/** 89c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * ath5k_hw_set_rxdp() - Set RX Descriptor's address 90c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * @ah: The &struct ath5k_hw 91c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * @phys_addr: RX descriptor address 92c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * 93e8325ed87457e07b9ceeb1e7a31df787dd7ee106Nick Kossifidis * Returns -EIO if rx is active 94c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 95c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisint 96c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr) 97c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis{ 98e8325ed87457e07b9ceeb1e7a31df787dd7ee106Nick Kossifidis if (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) { 99e0d687bd9df218ba3d97aac15919d30816d72dcbPavel Roskin ATH5K_DBG(ah, ATH5K_DEBUG_DMA, 100e8325ed87457e07b9ceeb1e7a31df787dd7ee106Nick Kossifidis "tried to set RXDP while rx was active !\n"); 101e8325ed87457e07b9ceeb1e7a31df787dd7ee106Nick Kossifidis return -EIO; 102e8325ed87457e07b9ceeb1e7a31df787dd7ee106Nick Kossifidis } 103e8325ed87457e07b9ceeb1e7a31df787dd7ee106Nick Kossifidis 104c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis ath5k_hw_reg_write(ah, phys_addr, AR5K_RXDP); 105e8325ed87457e07b9ceeb1e7a31df787dd7ee106Nick Kossifidis return 0; 106c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis} 107c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 108c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 109c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis/**********\ 110c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis* Transmit * 111c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis\**********/ 112c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 113c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis/** 114c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * ath5k_hw_start_tx_dma() - Start DMA transmit for a specific queue 115c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * @ah: The &struct ath5k_hw 116c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * @queue: The hw queue number 117c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * 118c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * Start DMA transmit for a specific queue and since 5210 doesn't have 119c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * QCU/DCU, set up queue parameters for 5210 here based on queue type (one 120c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * queue for normal data and one queue for beacons). For queue setup 121c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * on newer chips check out qcu.c. Returns -EINVAL if queue number is out 122c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * of range or if queue is already disabled. 123c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * 124c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * NOTE: Must be called after setting up tx control descriptor for that 125c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * queue (see below). 126c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 127c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisint 128c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue) 129c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis{ 130c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis u32 tx_queue; 131c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 132c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); 133c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 134c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis /* Return if queue is declared inactive */ 135c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) 136d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis return -EINVAL; 137c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 138c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis if (ah->ah_version == AR5K_AR5210) { 139c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis tx_queue = ath5k_hw_reg_read(ah, AR5K_CR); 140c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 141c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis /* 142c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * Set the queue by type on 5210 143c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 144c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis switch (ah->ah_txq[queue].tqi_type) { 145c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis case AR5K_TX_QUEUE_DATA: 146c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis tx_queue |= AR5K_CR_TXE0 & ~AR5K_CR_TXD0; 147c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis break; 148c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis case AR5K_TX_QUEUE_BEACON: 149c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis tx_queue |= AR5K_CR_TXE1 & ~AR5K_CR_TXD1; 150c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis ath5k_hw_reg_write(ah, AR5K_BCR_TQ1V | AR5K_BCR_BDMAE, 151c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis AR5K_BSR); 152c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis break; 153c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis case AR5K_TX_QUEUE_CAB: 154c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis tx_queue |= AR5K_CR_TXE1 & ~AR5K_CR_TXD1; 155c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis ath5k_hw_reg_write(ah, AR5K_BCR_TQ1FV | AR5K_BCR_TQ1V | 156c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis AR5K_BCR_BDMAE, AR5K_BSR); 157c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis break; 158c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis default: 159c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis return -EINVAL; 160c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis } 161c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis /* Start queue */ 162c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis ath5k_hw_reg_write(ah, tx_queue, AR5K_CR); 163c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis ath5k_hw_reg_read(ah, AR5K_CR); 164c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis } else { 165c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis /* Return if queue is disabled */ 166c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXD, queue)) 167c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis return -EIO; 168c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 169c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis /* Start queue */ 170c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXE, queue); 171c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis } 172c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 173c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis return 0; 174c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis} 175c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 176c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis/** 177c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * ath5k_hw_stop_tx_dma() - Stop DMA transmit on a specific queue 178c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * @ah: The &struct ath5k_hw 179c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * @queue: The hw queue number 180c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * 181c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * Stop DMA transmit on a specific hw queue and drain queue so we don't 182c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * have any pending frames. Returns -EBUSY if we still have pending frames, 183d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis * -EINVAL if queue number is out of range or inactive. 184c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 185c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisstatic int 186c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) 187c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis{ 188509a106e68aa42acc1a0c44ab365d0de6869bd9eNick Kossifidis unsigned int i = 40; 189c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis u32 tx_queue, pending; 190c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 191c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); 192c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 193c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis /* Return if queue is declared inactive */ 194c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) 195d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis return -EINVAL; 196c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 197c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis if (ah->ah_version == AR5K_AR5210) { 198c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis tx_queue = ath5k_hw_reg_read(ah, AR5K_CR); 199c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 200c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis /* 201c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * Set by queue type 202c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 203c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis switch (ah->ah_txq[queue].tqi_type) { 204c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis case AR5K_TX_QUEUE_DATA: 205c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis tx_queue |= AR5K_CR_TXD0 & ~AR5K_CR_TXE0; 206c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis break; 207c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis case AR5K_TX_QUEUE_BEACON: 208c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis case AR5K_TX_QUEUE_CAB: 209c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis /* XXX Fix me... */ 210c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis tx_queue |= AR5K_CR_TXD1 & ~AR5K_CR_TXD1; 211c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis ath5k_hw_reg_write(ah, 0, AR5K_BSR); 212c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis break; 213c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis default: 214c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis return -EINVAL; 215c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis } 216c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 217c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis /* Stop queue */ 218c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis ath5k_hw_reg_write(ah, tx_queue, AR5K_CR); 219c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis ath5k_hw_reg_read(ah, AR5K_CR); 220c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis } else { 221f7317ba2d669c1b54fb31ed7834361a700a79217Nick Kossifidis 222f7317ba2d669c1b54fb31ed7834361a700a79217Nick Kossifidis /* 223f7317ba2d669c1b54fb31ed7834361a700a79217Nick Kossifidis * Enable DCU early termination to quickly 224f7317ba2d669c1b54fb31ed7834361a700a79217Nick Kossifidis * flush any pending frames from QCU 225f7317ba2d669c1b54fb31ed7834361a700a79217Nick Kossifidis */ 226f7317ba2d669c1b54fb31ed7834361a700a79217Nick Kossifidis AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), 227f7317ba2d669c1b54fb31ed7834361a700a79217Nick Kossifidis AR5K_QCU_MISC_DCU_EARLY); 228f7317ba2d669c1b54fb31ed7834361a700a79217Nick Kossifidis 229c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis /* 230c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * Schedule TX disable and wait until queue is empty 231c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 232c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXD, queue); 233c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 234b3a28e68d5c8d788a4e538a119a5d326545add8aNick Kossifidis /* Wait for queue to stop */ 235b3a28e68d5c8d788a4e538a119a5d326545add8aNick Kossifidis for (i = 1000; i > 0 && 236b3a28e68d5c8d788a4e538a119a5d326545add8aNick Kossifidis (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue) != 0); 237b3a28e68d5c8d788a4e538a119a5d326545add8aNick Kossifidis i--) 238b3a28e68d5c8d788a4e538a119a5d326545add8aNick Kossifidis udelay(100); 239b3a28e68d5c8d788a4e538a119a5d326545add8aNick Kossifidis 240b3a28e68d5c8d788a4e538a119a5d326545add8aNick Kossifidis if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue)) 241e0d687bd9df218ba3d97aac15919d30816d72dcbPavel Roskin ATH5K_DBG(ah, ATH5K_DEBUG_DMA, 242b3a28e68d5c8d788a4e538a119a5d326545add8aNick Kossifidis "queue %i didn't stop !\n", queue); 243b3a28e68d5c8d788a4e538a119a5d326545add8aNick Kossifidis 244b3a28e68d5c8d788a4e538a119a5d326545add8aNick Kossifidis /* Check for pending frames */ 245b3a28e68d5c8d788a4e538a119a5d326545add8aNick Kossifidis i = 1000; 246c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis do { 247c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis pending = ath5k_hw_reg_read(ah, 248c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis AR5K_QUEUE_STATUS(queue)) & 249c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis AR5K_QCU_STS_FRMPENDCNT; 250c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis udelay(100); 251c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis } while (--i && pending); 252c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 253509a106e68aa42acc1a0c44ab365d0de6869bd9eNick Kossifidis /* For 2413+ order PCU to drop packets using 254509a106e68aa42acc1a0c44ab365d0de6869bd9eNick Kossifidis * QUIET mechanism */ 255509a106e68aa42acc1a0c44ab365d0de6869bd9eNick Kossifidis if (ah->ah_mac_version >= (AR5K_SREV_AR2414 >> 4) && 256e4bbf2f541501dcde47ce687ffc6d238bd2f7813Pavel Roskin pending) { 257509a106e68aa42acc1a0c44ab365d0de6869bd9eNick Kossifidis /* Set periodicity and duration */ 258509a106e68aa42acc1a0c44ab365d0de6869bd9eNick Kossifidis ath5k_hw_reg_write(ah, 259509a106e68aa42acc1a0c44ab365d0de6869bd9eNick Kossifidis AR5K_REG_SM(100, AR5K_QUIET_CTL2_QT_PER)| 260509a106e68aa42acc1a0c44ab365d0de6869bd9eNick Kossifidis AR5K_REG_SM(10, AR5K_QUIET_CTL2_QT_DUR), 261509a106e68aa42acc1a0c44ab365d0de6869bd9eNick Kossifidis AR5K_QUIET_CTL2); 262509a106e68aa42acc1a0c44ab365d0de6869bd9eNick Kossifidis 263509a106e68aa42acc1a0c44ab365d0de6869bd9eNick Kossifidis /* Enable quiet period for current TSF */ 264509a106e68aa42acc1a0c44ab365d0de6869bd9eNick Kossifidis ath5k_hw_reg_write(ah, 265509a106e68aa42acc1a0c44ab365d0de6869bd9eNick Kossifidis AR5K_QUIET_CTL1_QT_EN | 266509a106e68aa42acc1a0c44ab365d0de6869bd9eNick Kossifidis AR5K_REG_SM(ath5k_hw_reg_read(ah, 267509a106e68aa42acc1a0c44ab365d0de6869bd9eNick Kossifidis AR5K_TSF_L32_5211) >> 10, 268509a106e68aa42acc1a0c44ab365d0de6869bd9eNick Kossifidis AR5K_QUIET_CTL1_NEXT_QT_TSF), 269509a106e68aa42acc1a0c44ab365d0de6869bd9eNick Kossifidis AR5K_QUIET_CTL1); 270509a106e68aa42acc1a0c44ab365d0de6869bd9eNick Kossifidis 271509a106e68aa42acc1a0c44ab365d0de6869bd9eNick Kossifidis /* Force channel idle high */ 272509a106e68aa42acc1a0c44ab365d0de6869bd9eNick Kossifidis AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211, 273eada7cad6005006b457f10a4c3e1881ff99d03a4Bruno Randolf AR5K_DIAG_SW_CHANNEL_IDLE_HIGH); 274509a106e68aa42acc1a0c44ab365d0de6869bd9eNick Kossifidis 275509a106e68aa42acc1a0c44ab365d0de6869bd9eNick Kossifidis /* Wait a while and disable mechanism */ 276b3a28e68d5c8d788a4e538a119a5d326545add8aNick Kossifidis udelay(400); 277509a106e68aa42acc1a0c44ab365d0de6869bd9eNick Kossifidis AR5K_REG_DISABLE_BITS(ah, AR5K_QUIET_CTL1, 278509a106e68aa42acc1a0c44ab365d0de6869bd9eNick Kossifidis AR5K_QUIET_CTL1_QT_EN); 279509a106e68aa42acc1a0c44ab365d0de6869bd9eNick Kossifidis 280509a106e68aa42acc1a0c44ab365d0de6869bd9eNick Kossifidis /* Re-check for pending frames */ 281b3a28e68d5c8d788a4e538a119a5d326545add8aNick Kossifidis i = 100; 282509a106e68aa42acc1a0c44ab365d0de6869bd9eNick Kossifidis do { 283509a106e68aa42acc1a0c44ab365d0de6869bd9eNick Kossifidis pending = ath5k_hw_reg_read(ah, 284509a106e68aa42acc1a0c44ab365d0de6869bd9eNick Kossifidis AR5K_QUEUE_STATUS(queue)) & 285509a106e68aa42acc1a0c44ab365d0de6869bd9eNick Kossifidis AR5K_QCU_STS_FRMPENDCNT; 286509a106e68aa42acc1a0c44ab365d0de6869bd9eNick Kossifidis udelay(100); 287509a106e68aa42acc1a0c44ab365d0de6869bd9eNick Kossifidis } while (--i && pending); 288509a106e68aa42acc1a0c44ab365d0de6869bd9eNick Kossifidis 289509a106e68aa42acc1a0c44ab365d0de6869bd9eNick Kossifidis AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5211, 290eada7cad6005006b457f10a4c3e1881ff99d03a4Bruno Randolf AR5K_DIAG_SW_CHANNEL_IDLE_HIGH); 291b3a28e68d5c8d788a4e538a119a5d326545add8aNick Kossifidis 292b3a28e68d5c8d788a4e538a119a5d326545add8aNick Kossifidis if (pending) 293e0d687bd9df218ba3d97aac15919d30816d72dcbPavel Roskin ATH5K_DBG(ah, ATH5K_DEBUG_DMA, 294b3a28e68d5c8d788a4e538a119a5d326545add8aNick Kossifidis "quiet mechanism didn't work q:%i !\n", 295b3a28e68d5c8d788a4e538a119a5d326545add8aNick Kossifidis queue); 296509a106e68aa42acc1a0c44ab365d0de6869bd9eNick Kossifidis } 297509a106e68aa42acc1a0c44ab365d0de6869bd9eNick Kossifidis 298f7317ba2d669c1b54fb31ed7834361a700a79217Nick Kossifidis /* 299f7317ba2d669c1b54fb31ed7834361a700a79217Nick Kossifidis * Disable DCU early termination 300f7317ba2d669c1b54fb31ed7834361a700a79217Nick Kossifidis */ 301f7317ba2d669c1b54fb31ed7834361a700a79217Nick Kossifidis AR5K_REG_DISABLE_BITS(ah, AR5K_QUEUE_MISC(queue), 302f7317ba2d669c1b54fb31ed7834361a700a79217Nick Kossifidis AR5K_QCU_MISC_DCU_EARLY); 303f7317ba2d669c1b54fb31ed7834361a700a79217Nick Kossifidis 304c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis /* Clear register */ 305c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis ath5k_hw_reg_write(ah, 0, AR5K_QCU_TXD); 306b3a28e68d5c8d788a4e538a119a5d326545add8aNick Kossifidis if (pending) { 307e0d687bd9df218ba3d97aac15919d30816d72dcbPavel Roskin ATH5K_DBG(ah, ATH5K_DEBUG_DMA, 308b3a28e68d5c8d788a4e538a119a5d326545add8aNick Kossifidis "tx dma didn't stop (q:%i, frm:%i) !\n", 309b3a28e68d5c8d788a4e538a119a5d326545add8aNick Kossifidis queue, pending); 310c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis return -EBUSY; 311b3a28e68d5c8d788a4e538a119a5d326545add8aNick Kossifidis } 312c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis } 313c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 314509a106e68aa42acc1a0c44ab365d0de6869bd9eNick Kossifidis /* TODO: Check for success on 5210 else return error */ 315c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis return 0; 316c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis} 317c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 318c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis/** 319c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * ath5k_hw_stop_beacon_queue() - Stop beacon queue 320c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * @ah: The &struct ath5k_hw 321c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * @queue: The queue number 32214fae2d4b61b890cea58d63091406b86ec9bafcdNick Kossifidis * 32314fae2d4b61b890cea58d63091406b86ec9bafcdNick Kossifidis * Returns -EIO if queue didn't stop 32414fae2d4b61b890cea58d63091406b86ec9bafcdNick Kossifidis */ 325c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisint 326c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisath5k_hw_stop_beacon_queue(struct ath5k_hw *ah, unsigned int queue) 32714fae2d4b61b890cea58d63091406b86ec9bafcdNick Kossifidis{ 32814fae2d4b61b890cea58d63091406b86ec9bafcdNick Kossifidis int ret; 32914fae2d4b61b890cea58d63091406b86ec9bafcdNick Kossifidis ret = ath5k_hw_stop_tx_dma(ah, queue); 33014fae2d4b61b890cea58d63091406b86ec9bafcdNick Kossifidis if (ret) { 331e0d687bd9df218ba3d97aac15919d30816d72dcbPavel Roskin ATH5K_DBG(ah, ATH5K_DEBUG_DMA, 33214fae2d4b61b890cea58d63091406b86ec9bafcdNick Kossifidis "beacon queue didn't stop !\n"); 33314fae2d4b61b890cea58d63091406b86ec9bafcdNick Kossifidis return -EIO; 33414fae2d4b61b890cea58d63091406b86ec9bafcdNick Kossifidis } 33514fae2d4b61b890cea58d63091406b86ec9bafcdNick Kossifidis return 0; 33614fae2d4b61b890cea58d63091406b86ec9bafcdNick Kossifidis} 33714fae2d4b61b890cea58d63091406b86ec9bafcdNick Kossifidis 33814fae2d4b61b890cea58d63091406b86ec9bafcdNick Kossifidis/** 339c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * ath5k_hw_get_txdp() - Get TX Descriptor's address for a specific queue 340c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * @ah: The &struct ath5k_hw 341c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * @queue: The hw queue number 342c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * 343c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * Get TX descriptor's address for a specific queue. For 5210 we ignore 344c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * the queue number and use tx queue type since we only have 2 queues. 345c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * We use TXDP0 for normal data queue and TXDP1 for beacon queue. 346c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * For newer chips with QCU/DCU we just read the corresponding TXDP register. 347c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * 348c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * XXX: Is TXDP read and clear ? 349c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 350c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisu32 351c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue) 352c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis{ 353c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis u16 tx_reg; 354c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 355c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); 356c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 357c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis /* 358c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * Get the transmit queue descriptor pointer from the selected queue 359c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 360c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis /*5210 doesn't have QCU*/ 361c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis if (ah->ah_version == AR5K_AR5210) { 362c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis switch (ah->ah_txq[queue].tqi_type) { 363c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis case AR5K_TX_QUEUE_DATA: 364c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis tx_reg = AR5K_NOQCU_TXDP0; 365c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis break; 366c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis case AR5K_TX_QUEUE_BEACON: 367c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis case AR5K_TX_QUEUE_CAB: 368c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis tx_reg = AR5K_NOQCU_TXDP1; 369c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis break; 370c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis default: 371c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis return 0xffffffff; 372c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis } 373c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis } else { 374c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis tx_reg = AR5K_QUEUE_TXDP(queue); 375c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis } 376c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 377c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis return ath5k_hw_reg_read(ah, tx_reg); 378c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis} 379c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 380c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis/** 381c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * ath5k_hw_set_txdp() - Set TX Descriptor's address for a specific queue 382c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * @ah: The &struct ath5k_hw 383c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * @queue: The hw queue number 384c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * @phys_addr: The physical address 385c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * 386c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * Set TX descriptor's address for a specific queue. For 5210 we ignore 387c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * the queue number and we use tx queue type since we only have 2 queues 388c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * so as above we use TXDP0 for normal data queue and TXDP1 for beacon queue. 389c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * For newer chips with QCU/DCU we just set the corresponding TXDP register. 390c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * Returns -EINVAL if queue type is invalid for 5210 and -EIO if queue is still 391c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * active. 392c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 393c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisint 394c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr) 395c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis{ 396c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis u16 tx_reg; 397c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 398c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); 399c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 400c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis /* 401c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * Set the transmit queue descriptor pointer register by type 402c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * on 5210 403c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 404c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis if (ah->ah_version == AR5K_AR5210) { 405c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis switch (ah->ah_txq[queue].tqi_type) { 406c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis case AR5K_TX_QUEUE_DATA: 407c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis tx_reg = AR5K_NOQCU_TXDP0; 408c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis break; 409c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis case AR5K_TX_QUEUE_BEACON: 410c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis case AR5K_TX_QUEUE_CAB: 411c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis tx_reg = AR5K_NOQCU_TXDP1; 412c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis break; 413c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis default: 414c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis return -EINVAL; 415c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis } 416c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis } else { 417c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis /* 418c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * Set the transmit queue descriptor pointer for 419c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * the selected queue on QCU for 5211+ 420c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * (this won't work if the queue is still active) 421c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 422c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue)) 423c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis return -EIO; 424c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 425c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis tx_reg = AR5K_QUEUE_TXDP(queue); 426c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis } 427c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 428c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis /* Set descriptor pointer */ 429c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis ath5k_hw_reg_write(ah, phys_addr, tx_reg); 430c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 431c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis return 0; 432c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis} 433c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 434c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis/** 435c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * ath5k_hw_update_tx_triglevel() - Update tx trigger level 436c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * @ah: The &struct ath5k_hw 437c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * @increase: Flag to force increase of trigger level 438c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * 439c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * This function increases/decreases the tx trigger level for the tx fifo 440c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * buffer (aka FIFO threshold) that is used to indicate when PCU flushes 441a180a13081708b78d42232c6d922ce3de63f12e0Bob Copeland * the buffer and transmits its data. Lowering this results sending small 442c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * frames more quickly but can lead to tx underruns, raising it a lot can 443c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * result other problems. Right now we start with the lowest possible 444c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * (64Bytes) and if we get tx underrun we increase it using the increase 445c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * flag. Returns -EIO if we have reached maximum/minimum. 446c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * 447c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * XXX: Link this with tx DMA size ? 448c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * XXX2: Use it to save interrupts ? 449c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 450c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisint 451c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase) 452c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis{ 453c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis u32 trigger_level, imr; 454c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis int ret = -EIO; 455c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 456c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis /* 457c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * Disable interrupts by setting the mask 458c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 459c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis imr = ath5k_hw_set_imr(ah, ah->ah_imr & ~AR5K_INT_GLOBAL); 460c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 461c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis trigger_level = AR5K_REG_MS(ath5k_hw_reg_read(ah, AR5K_TXCFG), 462c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis AR5K_TXCFG_TXFULL); 463c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 464c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis if (!increase) { 465c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis if (--trigger_level < AR5K_TUNE_MIN_TX_FIFO_THRES) 466c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis goto done; 467c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis } else 468c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis trigger_level += 469c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis ((AR5K_TUNE_MAX_TX_FIFO_THRES - trigger_level) / 2); 470c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 471c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis /* 472c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * Update trigger level on success 473c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 474c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis if (ah->ah_version == AR5K_AR5210) 475c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis ath5k_hw_reg_write(ah, trigger_level, AR5K_TRIG_LVL); 476c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis else 477c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, 478c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis AR5K_TXCFG_TXFULL, trigger_level); 479c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 480c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis ret = 0; 481c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 482c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidisdone: 483c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis /* 484c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * Restore interrupt mask 485c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 486c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis ath5k_hw_set_imr(ah, imr); 487c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 488c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis return ret; 489c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis} 490c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 4919320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis 492c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis/*******************\ 493c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis* Interrupt masking * 494c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis\*******************/ 495c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 496c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis/** 497c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * ath5k_hw_is_intr_pending() - Check if we have pending interrupts 498c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * @ah: The &struct ath5k_hw 499c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * 500c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * Check if we have pending interrupts to process. Returns 1 if we 501c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * have pending interrupts and 0 if we haven't. 502c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 503c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisbool 504c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisath5k_hw_is_intr_pending(struct ath5k_hw *ah) 505c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis{ 506509a106e68aa42acc1a0c44ab365d0de6869bd9eNick Kossifidis return ath5k_hw_reg_read(ah, AR5K_INTPEND) == 1 ? 1 : 0; 507c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis} 508c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 509c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis/** 510c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * ath5k_hw_get_isr() - Get interrupt status 511c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * @ah: The @struct ath5k_hw 512c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * @interrupt_mask: Driver's interrupt mask used to filter out 513c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * interrupts in sw. 514c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * 515c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * This function is used inside our interrupt handler to determine the reason 516c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * for the interrupt by reading Primary Interrupt Status Register. Returns an 517c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * abstract interrupt status mask which is mostly ISR with some uncommon bits 518c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * being mapped on some standard non hw-specific positions 519c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * (check out &ath5k_int). 520c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * 5217ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * NOTE: We do write-to-clear, so the active PISR/SISR bits at the time this 5227ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * function gets called are cleared on return. 523c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 524c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisint 525c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask) 526c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis{ 5277ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis u32 data = 0; 528c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 529c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis /* 5307ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * Read interrupt status from Primary Interrupt 5317ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * Register. 5327ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * 5337ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * Note: PISR/SISR Not available on 5210 534c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 535c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis if (ah->ah_version == AR5K_AR5210) { 5367ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis u32 isr = 0; 5377ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis isr = ath5k_hw_reg_read(ah, AR5K_ISR); 5387ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis if (unlikely(isr == AR5K_INT_NOCARD)) { 5397ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis *interrupt_mask = isr; 540c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis return -ENODEV; 541c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis } 5427ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis 543c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis /* 5447ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * Filter out the non-common bits from the interrupt 5457ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * status. 5467ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis */ 5477ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis *interrupt_mask = (isr & AR5K_INT_COMMON) & ah->ah_imr; 5487ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis 5497ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis /* Hanlde INT_FATAL */ 5507ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis if (unlikely(isr & (AR5K_ISR_SSERR | AR5K_ISR_MCABT 5517ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis | AR5K_ISR_DPERR))) 5527ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis *interrupt_mask |= AR5K_INT_FATAL; 5537ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis 5547ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis /* 5557ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * XXX: BMISS interrupts may occur after association. 5567ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * I found this on 5210 code but it needs testing. If this is 5577ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * true we should disable them before assoc and re-enable them 5587ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * after a successful assoc + some jiffies. 5597ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis interrupt_mask &= ~AR5K_INT_BMISS; 560c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 5617ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis 5627ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis data = isr; 5637ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis } else { 5647ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis u32 pisr = 0; 5657ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis u32 pisr_clear = 0; 5667ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis u32 sisr0 = 0; 5677ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis u32 sisr1 = 0; 5687ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis u32 sisr2 = 0; 5697ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis u32 sisr3 = 0; 5707ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis u32 sisr4 = 0; 5717ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis 5727ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis /* Read PISR and SISRs... */ 5737ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis pisr = ath5k_hw_reg_read(ah, AR5K_PISR); 5747ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis if (unlikely(pisr == AR5K_INT_NOCARD)) { 5757ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis *interrupt_mask = pisr; 5764c674c60bd567597f1224973712b352f4f474890Nick Kossifidis return -ENODEV; 5774c674c60bd567597f1224973712b352f4f474890Nick Kossifidis } 578c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 5797ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis sisr0 = ath5k_hw_reg_read(ah, AR5K_SISR0); 5807ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis sisr1 = ath5k_hw_reg_read(ah, AR5K_SISR1); 5817ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis sisr2 = ath5k_hw_reg_read(ah, AR5K_SISR2); 5827ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis sisr3 = ath5k_hw_reg_read(ah, AR5K_SISR3); 5837ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis sisr4 = ath5k_hw_reg_read(ah, AR5K_SISR4); 584c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 5857ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis /* 5867ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * PISR holds the logical OR of interrupt bits 5877ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * from SISR registers: 5887ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * 5897ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * TXOK and TXDESC -> Logical OR of TXOK and TXDESC 5907ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * per-queue bits on SISR0 5917ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * 5927ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * TXERR and TXEOL -> Logical OR of TXERR and TXEOL 5937ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * per-queue bits on SISR1 5947ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * 5957ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * TXURN -> Logical OR of TXURN per-queue bits on SISR2 5967ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * 5977ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * HIUERR -> Logical OR of MCABT, SSERR and DPER bits on SISR2 5987ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * 5997ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * BCNMISC -> Logical OR of TIM, CAB_END, DTIM_SYNC 6007ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * BCN_TIMEOUT, CAB_TIMEOUT and DTIM 6017ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * (and TSFOOR ?) bits on SISR2 6027ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * 6037ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * QCBRORN and QCBRURN -> Logical OR of QCBRORN and 6047ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * QCBRURN per-queue bits on SISR3 6057ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * QTRIG -> Logical OR of QTRIG per-queue bits on SISR4 6067ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * 6077ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * If we clean these bits on PISR we 'll also clear all 6087ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * related bits from SISRs, e.g. if we write the TXOK bit on 6097ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * PISR we 'll clean all TXOK bits from SISR0 so if a new TXOK 6107ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * interrupt got fired for another queue while we were reading 6117ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * the interrupt registers and we write back the TXOK bit on 6127ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * PISR we 'll lose it. So make sure that we don't write back 6137ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * on PISR any bits that come from SISRs. Clearing them from 6147ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * SISRs will also clear PISR so no need to worry here. 6157ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis */ 6164c674c60bd567597f1224973712b352f4f474890Nick Kossifidis 6177ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis pisr_clear = pisr & ~AR5K_ISR_BITS_FROM_SISRS; 618c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 6197ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis /* 6207ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * Write to clear them... 6217ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * Note: This means that each bit we write back 6227ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * to the registers will get cleared, leaving the 6237ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * rest unaffected. So this won't affect new interrupts 6247ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * we didn't catch while reading/processing, we 'll get 6257ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * them next time get_isr gets called. 6267ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis */ 6277ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis ath5k_hw_reg_write(ah, sisr0, AR5K_SISR0); 6287ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis ath5k_hw_reg_write(ah, sisr1, AR5K_SISR1); 6297ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis ath5k_hw_reg_write(ah, sisr2, AR5K_SISR2); 6307ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis ath5k_hw_reg_write(ah, sisr3, AR5K_SISR3); 6317ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis ath5k_hw_reg_write(ah, sisr4, AR5K_SISR4); 6327ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis ath5k_hw_reg_write(ah, pisr_clear, AR5K_PISR); 6337ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis /* Flush previous write */ 6347ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis ath5k_hw_reg_read(ah, AR5K_PISR); 635c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 6367ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis /* 6377ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * Filter out the non-common bits from the interrupt 6387ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * status. 6397ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis */ 6407ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis *interrupt_mask = (pisr & AR5K_INT_COMMON) & ah->ah_imr; 6417ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis 6427ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis 6437ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis /* We treat TXOK,TXDESC, TXERR and TXEOL 6447ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * the same way (schedule the tx tasklet) 6457ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * so we track them all together per queue */ 6467ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis if (pisr & AR5K_ISR_TXOK) 6477ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis ah->ah_txq_isr_txok_all |= AR5K_REG_MS(sisr0, 6487ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis AR5K_SISR0_QCU_TXOK); 6497ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis 6507ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis if (pisr & AR5K_ISR_TXDESC) 6517ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis ah->ah_txq_isr_txok_all |= AR5K_REG_MS(sisr0, 6527ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis AR5K_SISR0_QCU_TXDESC); 6537ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis 6547ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis if (pisr & AR5K_ISR_TXERR) 6557ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis ah->ah_txq_isr_txok_all |= AR5K_REG_MS(sisr1, 6567ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis AR5K_SISR1_QCU_TXERR); 6574c674c60bd567597f1224973712b352f4f474890Nick Kossifidis 6587ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis if (pisr & AR5K_ISR_TXEOL) 6597ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis ah->ah_txq_isr_txok_all |= AR5K_REG_MS(sisr1, 6607ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis AR5K_SISR1_QCU_TXEOL); 6617ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis 6627ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis /* Currently this is not much usefull since we treat 6637ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * all queues the same way if we get a TXURN (update 6647ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * tx trigger level) but we might need it later on*/ 6657ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis if (pisr & AR5K_ISR_TXURN) 6667ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis ah->ah_txq_isr_txurn |= AR5K_REG_MS(sisr2, 6677ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis AR5K_SISR2_QCU_TXURN); 6687ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis 6697ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis /* Misc Beacon related interrupts */ 6707ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis 6717ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis /* For AR5211 */ 6727ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis if (pisr & AR5K_ISR_TIM) 6734c674c60bd567597f1224973712b352f4f474890Nick Kossifidis *interrupt_mask |= AR5K_INT_TIM; 6744c674c60bd567597f1224973712b352f4f474890Nick Kossifidis 6757ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis /* For AR5212+ */ 6767ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis if (pisr & AR5K_ISR_BCNMISC) { 6774c674c60bd567597f1224973712b352f4f474890Nick Kossifidis if (sisr2 & AR5K_SISR2_TIM) 6784c674c60bd567597f1224973712b352f4f474890Nick Kossifidis *interrupt_mask |= AR5K_INT_TIM; 6794c674c60bd567597f1224973712b352f4f474890Nick Kossifidis if (sisr2 & AR5K_SISR2_DTIM) 6804c674c60bd567597f1224973712b352f4f474890Nick Kossifidis *interrupt_mask |= AR5K_INT_DTIM; 6814c674c60bd567597f1224973712b352f4f474890Nick Kossifidis if (sisr2 & AR5K_SISR2_DTIM_SYNC) 6824c674c60bd567597f1224973712b352f4f474890Nick Kossifidis *interrupt_mask |= AR5K_INT_DTIM_SYNC; 6834c674c60bd567597f1224973712b352f4f474890Nick Kossifidis if (sisr2 & AR5K_SISR2_BCN_TIMEOUT) 6844c674c60bd567597f1224973712b352f4f474890Nick Kossifidis *interrupt_mask |= AR5K_INT_BCN_TIMEOUT; 6854c674c60bd567597f1224973712b352f4f474890Nick Kossifidis if (sisr2 & AR5K_SISR2_CAB_TIMEOUT) 6864c674c60bd567597f1224973712b352f4f474890Nick Kossifidis *interrupt_mask |= AR5K_INT_CAB_TIMEOUT; 6874c674c60bd567597f1224973712b352f4f474890Nick Kossifidis } 6884c674c60bd567597f1224973712b352f4f474890Nick Kossifidis 6897ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis /* Below interrupts are unlikely to happen */ 6907ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis 6917ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis /* HIU = Host Interface Unit (PCI etc) 6927ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis * Can be one of MCABT, SSERR, DPERR from SISR2 */ 6937ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis if (unlikely(pisr & (AR5K_ISR_HIUERR))) 6947ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis *interrupt_mask |= AR5K_INT_FATAL; 6957ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis 6967ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis /*Beacon Not Ready*/ 6977ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis if (unlikely(pisr & (AR5K_ISR_BNR))) 6987ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis *interrupt_mask |= AR5K_INT_BNR; 6997ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis 70034ce644aa8342f95eb1e187178f83febade4af37Nick Kossifidis /* A queue got CBR overrun */ 7017ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis if (unlikely(pisr & (AR5K_ISR_QCBRORN))) { 7024c674c60bd567597f1224973712b352f4f474890Nick Kossifidis *interrupt_mask |= AR5K_INT_QCBRORN; 7037ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis ah->ah_txq_isr_qcborn |= AR5K_REG_MS(sisr3, 7047ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis AR5K_SISR3_QCBRORN); 7054c674c60bd567597f1224973712b352f4f474890Nick Kossifidis } 7067ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis 70734ce644aa8342f95eb1e187178f83febade4af37Nick Kossifidis /* A queue got CBR underrun */ 7087ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis if (unlikely(pisr & (AR5K_ISR_QCBRURN))) { 7094c674c60bd567597f1224973712b352f4f474890Nick Kossifidis *interrupt_mask |= AR5K_INT_QCBRURN; 7107ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis ah->ah_txq_isr_qcburn |= AR5K_REG_MS(sisr3, 7117ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis AR5K_SISR3_QCBRURN); 7124c674c60bd567597f1224973712b352f4f474890Nick Kossifidis } 7137ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis 71434ce644aa8342f95eb1e187178f83febade4af37Nick Kossifidis /* A queue got triggered */ 7157ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis if (unlikely(pisr & (AR5K_ISR_QTRIG))) { 7164c674c60bd567597f1224973712b352f4f474890Nick Kossifidis *interrupt_mask |= AR5K_INT_QTRIG; 7177ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis ah->ah_txq_isr_qtrig |= AR5K_REG_MS(sisr4, 7187ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis AR5K_SISR4_QTRIG); 7194c674c60bd567597f1224973712b352f4f474890Nick Kossifidis } 7204c674c60bd567597f1224973712b352f4f474890Nick Kossifidis 7217ff7c82ee4339af277cface9071f81c5c10a9283Nick Kossifidis data = pisr; 7224c674c60bd567597f1224973712b352f4f474890Nick Kossifidis } 723c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 724c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis /* 725c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * In case we didn't handle anything, 726c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * print the register value. 727c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 728c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis if (unlikely(*interrupt_mask == 0 && net_ratelimit())) 7294c674c60bd567597f1224973712b352f4f474890Nick Kossifidis ATH5K_PRINTF("ISR: 0x%08x IMR: 0x%08x\n", data, ah->ah_imr); 730c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 731c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis return 0; 732c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis} 733c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 734c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis/** 735c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * ath5k_hw_set_imr() - Set interrupt mask 736c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * @ah: The &struct ath5k_hw 737c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * @new_mask: The new interrupt mask to be set 738c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * 739c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * Set the interrupt mask in hw to save interrupts. We do that by mapping 740c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * ath5k_int bits to hw-specific bits to remove abstraction and writing 741c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * Interrupt Mask Register. 742c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 743c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisenum ath5k_int 744c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask) 745c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis{ 746c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis enum ath5k_int old_mask, int_mask; 747c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 7484c674c60bd567597f1224973712b352f4f474890Nick Kossifidis old_mask = ah->ah_imr; 7494c674c60bd567597f1224973712b352f4f474890Nick Kossifidis 750c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis /* 751c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * Disable card interrupts to prevent any race conditions 7524c674c60bd567597f1224973712b352f4f474890Nick Kossifidis * (they will be re-enabled afterwards if AR5K_INT GLOBAL 7534c674c60bd567597f1224973712b352f4f474890Nick Kossifidis * is set again on the new mask). 754c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 7554c674c60bd567597f1224973712b352f4f474890Nick Kossifidis if (old_mask & AR5K_INT_GLOBAL) { 7564c674c60bd567597f1224973712b352f4f474890Nick Kossifidis ath5k_hw_reg_write(ah, AR5K_IER_DISABLE, AR5K_IER); 7574c674c60bd567597f1224973712b352f4f474890Nick Kossifidis ath5k_hw_reg_read(ah, AR5K_IER); 7584c674c60bd567597f1224973712b352f4f474890Nick Kossifidis } 759c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 760c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis /* 761c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * Add additional, chipset-dependent interrupt mask flags 762c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * and write them to the IMR (interrupt mask register). 763c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 764c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis int_mask = new_mask & AR5K_INT_COMMON; 765c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 766c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis if (ah->ah_version != AR5K_AR5210) { 7674c674c60bd567597f1224973712b352f4f474890Nick Kossifidis /* Preserve per queue TXURN interrupt mask */ 7684c674c60bd567597f1224973712b352f4f474890Nick Kossifidis u32 simr2 = ath5k_hw_reg_read(ah, AR5K_SIMR2) 7694c674c60bd567597f1224973712b352f4f474890Nick Kossifidis & AR5K_SIMR2_QCU_TXURN; 7704c674c60bd567597f1224973712b352f4f474890Nick Kossifidis 77134ce644aa8342f95eb1e187178f83febade4af37Nick Kossifidis /* Fatal interrupt abstraction for 5211+ */ 772c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis if (new_mask & AR5K_INT_FATAL) { 773c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis int_mask |= AR5K_IMR_HIUERR; 7744c674c60bd567597f1224973712b352f4f474890Nick Kossifidis simr2 |= (AR5K_SIMR2_MCABT | AR5K_SIMR2_SSERR 7754c674c60bd567597f1224973712b352f4f474890Nick Kossifidis | AR5K_SIMR2_DPERR); 776c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis } 7774c674c60bd567597f1224973712b352f4f474890Nick Kossifidis 77834ce644aa8342f95eb1e187178f83febade4af37Nick Kossifidis /* Misc beacon related interrupts */ 7794c674c60bd567597f1224973712b352f4f474890Nick Kossifidis if (new_mask & AR5K_INT_TIM) 7804c674c60bd567597f1224973712b352f4f474890Nick Kossifidis int_mask |= AR5K_IMR_TIM; 7814c674c60bd567597f1224973712b352f4f474890Nick Kossifidis 7824c674c60bd567597f1224973712b352f4f474890Nick Kossifidis if (new_mask & AR5K_INT_TIM) 7834c674c60bd567597f1224973712b352f4f474890Nick Kossifidis simr2 |= AR5K_SISR2_TIM; 7844c674c60bd567597f1224973712b352f4f474890Nick Kossifidis if (new_mask & AR5K_INT_DTIM) 7854c674c60bd567597f1224973712b352f4f474890Nick Kossifidis simr2 |= AR5K_SISR2_DTIM; 7864c674c60bd567597f1224973712b352f4f474890Nick Kossifidis if (new_mask & AR5K_INT_DTIM_SYNC) 7874c674c60bd567597f1224973712b352f4f474890Nick Kossifidis simr2 |= AR5K_SISR2_DTIM_SYNC; 7884c674c60bd567597f1224973712b352f4f474890Nick Kossifidis if (new_mask & AR5K_INT_BCN_TIMEOUT) 7894c674c60bd567597f1224973712b352f4f474890Nick Kossifidis simr2 |= AR5K_SISR2_BCN_TIMEOUT; 7904c674c60bd567597f1224973712b352f4f474890Nick Kossifidis if (new_mask & AR5K_INT_CAB_TIMEOUT) 7914c674c60bd567597f1224973712b352f4f474890Nick Kossifidis simr2 |= AR5K_SISR2_CAB_TIMEOUT; 7924c674c60bd567597f1224973712b352f4f474890Nick Kossifidis 79334ce644aa8342f95eb1e187178f83febade4af37Nick Kossifidis /*Beacon Not Ready*/ 79434ce644aa8342f95eb1e187178f83febade4af37Nick Kossifidis if (new_mask & AR5K_INT_BNR) 79534ce644aa8342f95eb1e187178f83febade4af37Nick Kossifidis int_mask |= AR5K_INT_BNR; 79634ce644aa8342f95eb1e187178f83febade4af37Nick Kossifidis 7974c674c60bd567597f1224973712b352f4f474890Nick Kossifidis /* Note: Per queue interrupt masks 7986a2a0e738225fc9ec063f84b79f0adf5c0ed176cPavel Roskin * are set via ath5k_hw_reset_tx_queue() (qcu.c) */ 7994c674c60bd567597f1224973712b352f4f474890Nick Kossifidis ath5k_hw_reg_write(ah, int_mask, AR5K_PIMR); 8004c674c60bd567597f1224973712b352f4f474890Nick Kossifidis ath5k_hw_reg_write(ah, simr2, AR5K_SIMR2); 8014c674c60bd567597f1224973712b352f4f474890Nick Kossifidis 8024c674c60bd567597f1224973712b352f4f474890Nick Kossifidis } else { 80334ce644aa8342f95eb1e187178f83febade4af37Nick Kossifidis /* Fatal interrupt abstraction for 5210 */ 8044c674c60bd567597f1224973712b352f4f474890Nick Kossifidis if (new_mask & AR5K_INT_FATAL) 8054c674c60bd567597f1224973712b352f4f474890Nick Kossifidis int_mask |= (AR5K_IMR_SSERR | AR5K_IMR_MCABT 8064c674c60bd567597f1224973712b352f4f474890Nick Kossifidis | AR5K_IMR_HIUERR | AR5K_IMR_DPERR); 8074c674c60bd567597f1224973712b352f4f474890Nick Kossifidis 80834ce644aa8342f95eb1e187178f83febade4af37Nick Kossifidis /* Only common interrupts left for 5210 (no SIMRs) */ 8094c674c60bd567597f1224973712b352f4f474890Nick Kossifidis ath5k_hw_reg_write(ah, int_mask, AR5K_IMR); 810c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis } 811c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 8124c674c60bd567597f1224973712b352f4f474890Nick Kossifidis /* If RXNOFRM interrupt is masked disable it 8134c674c60bd567597f1224973712b352f4f474890Nick Kossifidis * by setting AR5K_RXNOFRM to zero */ 8144c674c60bd567597f1224973712b352f4f474890Nick Kossifidis if (!(new_mask & AR5K_INT_RXNOFRM)) 8154c674c60bd567597f1224973712b352f4f474890Nick Kossifidis ath5k_hw_reg_write(ah, 0, AR5K_RXNOFRM); 816c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 817c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis /* Store new interrupt mask */ 818c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis ah->ah_imr = new_mask; 819c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 8204c674c60bd567597f1224973712b352f4f474890Nick Kossifidis /* ..re-enable interrupts if AR5K_INT_GLOBAL is set */ 8214c674c60bd567597f1224973712b352f4f474890Nick Kossifidis if (new_mask & AR5K_INT_GLOBAL) { 8224c674c60bd567597f1224973712b352f4f474890Nick Kossifidis ath5k_hw_reg_write(ah, AR5K_IER_ENABLE, AR5K_IER); 8234c674c60bd567597f1224973712b352f4f474890Nick Kossifidis ath5k_hw_reg_read(ah, AR5K_IER); 8244c674c60bd567597f1224973712b352f4f474890Nick Kossifidis } 825c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 826c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis return old_mask; 827c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis} 828c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 8299320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis 8309320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis/********************\ 8319320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis Init/Stop functions 8329320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis\********************/ 8339320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis 8349320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis/** 835c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * ath5k_hw_dma_init() - Initialize DMA unit 8369320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * @ah: The &struct ath5k_hw 8379320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * 8389320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * Set DMA size and pre-enable interrupts 8399320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * (driver handles tx/rx buffer setup and 8409320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * dma start/stop) 8419320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * 8429320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * XXX: Save/restore RXDP/TXDP registers ? 8439320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis */ 844c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisvoid 845c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisath5k_hw_dma_init(struct ath5k_hw *ah) 8469320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis{ 8479320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis /* 8489320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * Set Rx/Tx DMA Configuration 8499320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * 8509320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * Set standard DMA size (128). Note that 8519320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * a DMA size of 512 causes rx overruns and tx errors 8529320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * on pci-e cards (tested on 5424 but since rx overruns 8539320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * also occur on 5416/5418 with madwifi we set 128 8549320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * for all PCI-E cards to be safe). 8559320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * 8569320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * XXX: need to check 5210 for this 8576a2a0e738225fc9ec063f84b79f0adf5c0ed176cPavel Roskin * TODO: Check out tx trigger level, it's always 64 on dumps but I 8589320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * guess we can tweak it and see how it goes ;-) 8599320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis */ 8609320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis if (ah->ah_version != AR5K_AR5210) { 8619320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, 8629320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B); 8639320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG, 8649320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_128B); 8659320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis } 8669320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis 8679320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis /* Pre-enable interrupts on 5211/5212*/ 8689320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis if (ah->ah_version != AR5K_AR5210) 8699320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis ath5k_hw_set_imr(ah, ah->ah_imr); 8709320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis 8719320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis} 872d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis 873d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis/** 874c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * ath5k_hw_dma_stop() - stop DMA unit 875d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis * @ah: The &struct ath5k_hw 876d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis * 877d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis * Stop tx/rx DMA and interrupts. Returns 878d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis * -EBUSY if tx or rx dma failed to stop. 879d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis * 880d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis * XXX: Sometimes DMA unit hangs and we have 881d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis * stuck frames on tx queues, only a reset 882d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis * can fix that. 883d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis */ 884c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisint 885c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisath5k_hw_dma_stop(struct ath5k_hw *ah) 886d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis{ 887d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis int i, qmax, err; 888d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis err = 0; 889d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis 890d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis /* Disable interrupts */ 891d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis ath5k_hw_set_imr(ah, 0); 892d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis 893d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis /* Stop rx dma */ 894d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis err = ath5k_hw_stop_rx_dma(ah); 895d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis if (err) 896d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis return err; 897d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis 898d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis /* Clear any pending interrupts 899d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis * and disable tx dma */ 900d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis if (ah->ah_version != AR5K_AR5210) { 901d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis ath5k_hw_reg_write(ah, 0xffffffff, AR5K_PISR); 902d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis qmax = AR5K_NUM_TX_QUEUES; 903d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis } else { 904d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis /* PISR/SISR Not available on 5210 */ 905d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis ath5k_hw_reg_read(ah, AR5K_ISR); 906d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis qmax = AR5K_NUM_TX_QUEUES_NOQCU; 907d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis } 908d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis 909d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis for (i = 0; i < qmax; i++) { 910d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis err = ath5k_hw_stop_tx_dma(ah, i); 911d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis /* -EINVAL -> queue inactive */ 91215411c27d203e363592d30ab00803254ebe77b90Bob Copeland if (err && err != -EINVAL) 913d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis return err; 914d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis } 915d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis 91615411c27d203e363592d30ab00803254ebe77b90Bob Copeland return 0; 917d41174fabdae348c6583cf05aeb329da232c342cNick Kossifidis} 918