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