blob: 0e900a4acead480070ac89bfe7d9530c8f780e81 [file] [log] [blame]
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001/******************************************************************************
2 *
3 * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
4 *
5 * Portions of this file are derived from the ipw3945 project, as well
6 * as portions of the ieee80211 subsystem header files.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of version 2 of the GNU General Public License as
10 * published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
20 *
21 * The full GNU General Public License is included in this distribution in the
22 * file called LICENSE.
23 *
24 * Contact Information:
25 * Intel Linux Wireless <ilw@linux.intel.com>
26 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
27 *
28 *****************************************************************************/
29
30#include <linux/etherdevice.h>
31#include <linux/sched.h>
32#include <linux/slab.h>
33#include <net/mac80211.h>
34#include "iwl-eeprom.h"
35#include "iwl-dev.h"
36#include "iwl-core.h"
37#include "iwl-sta.h"
38#include "iwl-io.h"
39#include "iwl-helpers.h"
40
41/**
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +020042 * il_txq_update_write_ptr - Send new write index to hardware
Wey-Yi Guybe663ab2011-02-21 11:27:26 -080043 */
44void
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +020045il_txq_update_write_ptr(struct il_priv *il, struct il_tx_queue *txq)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -080046{
47 u32 reg = 0;
48 int txq_id = txq->q.id;
49
50 if (txq->need_update == 0)
51 return;
52
53 /* if we're trying to save power */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +020054 if (test_bit(STATUS_POWER_PMI, &il->status)) {
Wey-Yi Guybe663ab2011-02-21 11:27:26 -080055 /* wake up nic if it's powered down ...
56 * uCode will wake up, and interrupt us again, so next
57 * time we'll skip this part. */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +020058 reg = _il_rd(il, CSR_UCODE_DRV_GP1);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -080059
60 if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +010061 D_INFO(
Wey-Yi Guybe663ab2011-02-21 11:27:26 -080062 "Tx queue %d requesting wakeup,"
63 " GP1 = 0x%x\n", txq_id, reg);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +020064 il_set_bit(il, CSR_GP_CNTRL,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -080065 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
66 return;
67 }
68
Stanislaw Gruszka0c1a94e2011-08-24 17:37:16 +020069 il_wr(il, HBUS_TARG_WRPTR,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -080070 txq->q.write_ptr | (txq_id << 8));
71
72 /*
73 * else not in power-save mode,
74 * uCode will never sleep when we're
75 * trying to tx (during RFKILL, we're not trying to tx).
76 */
77 } else
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +020078 _il_wr(il, HBUS_TARG_WRPTR,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -080079 txq->q.write_ptr | (txq_id << 8));
80 txq->need_update = 0;
81}
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +020082EXPORT_SYMBOL(il_txq_update_write_ptr);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -080083
84/**
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +020085 * il_tx_queue_unmap - Unmap any remaining DMA mappings and free skb's
Stanislaw Gruszka8a032c12011-02-28 14:33:14 +010086 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +020087void il_tx_queue_unmap(struct il_priv *il, int txq_id)
Stanislaw Gruszka8a032c12011-02-28 14:33:14 +010088{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +020089 struct il_tx_queue *txq = &il->txq[txq_id];
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +020090 struct il_queue *q = &txq->q;
Stanislaw Gruszka8a032c12011-02-28 14:33:14 +010091
92 if (q->n_bd == 0)
93 return;
94
95 while (q->write_ptr != q->read_ptr) {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +020096 il->cfg->ops->lib->txq_free_tfd(il, txq);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +020097 q->read_ptr = il_queue_inc_wrap(q->read_ptr, q->n_bd);
Stanislaw Gruszka8a032c12011-02-28 14:33:14 +010098 }
99}
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200100EXPORT_SYMBOL(il_tx_queue_unmap);
Stanislaw Gruszka8a032c12011-02-28 14:33:14 +0100101
102/**
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200103 * il_tx_queue_free - Deallocate DMA queue.
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800104 * @txq: Transmit queue to deallocate.
105 *
106 * Empty queue by removing and destroying all BD's.
107 * Free all buffers.
108 * 0-fill, but do not free "txq" descriptor structure.
109 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200110void il_tx_queue_free(struct il_priv *il, int txq_id)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800111{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200112 struct il_tx_queue *txq = &il->txq[txq_id];
113 struct device *dev = &il->pci_dev->dev;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800114 int i;
115
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200116 il_tx_queue_unmap(il, txq_id);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800117
118 /* De-alloc array of command/tx buffers */
119 for (i = 0; i < TFD_TX_CMD_SLOTS; i++)
120 kfree(txq->cmd[i]);
121
122 /* De-alloc circular buffer of TFDs */
123 if (txq->q.n_bd)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200124 dma_free_coherent(dev, il->hw_params.tfd_size *
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800125 txq->q.n_bd, txq->tfds, txq->q.dma_addr);
126
127 /* De-alloc array of per-TFD driver data */
128 kfree(txq->txb);
129 txq->txb = NULL;
130
131 /* deallocate arrays */
132 kfree(txq->cmd);
133 kfree(txq->meta);
134 txq->cmd = NULL;
135 txq->meta = NULL;
136
137 /* 0-fill queue descriptor structure */
138 memset(txq, 0, sizeof(*txq));
139}
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200140EXPORT_SYMBOL(il_tx_queue_free);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800141
142/**
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200143 * il_cmd_queue_unmap - Unmap any remaining DMA mappings from command queue
Stanislaw Gruszka8a032c12011-02-28 14:33:14 +0100144 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200145void il_cmd_queue_unmap(struct il_priv *il)
Stanislaw Gruszka8a032c12011-02-28 14:33:14 +0100146{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200147 struct il_tx_queue *txq = &il->txq[il->cmd_queue];
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200148 struct il_queue *q = &txq->q;
Stanislaw Gruszka8a032c12011-02-28 14:33:14 +0100149 int i;
150
151 if (q->n_bd == 0)
152 return;
153
154 while (q->read_ptr != q->write_ptr) {
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200155 i = il_get_cmd_index(q, q->read_ptr, 0);
Stanislaw Gruszka8a032c12011-02-28 14:33:14 +0100156
Stanislaw Gruszka81e63262011-04-28 11:51:31 +0200157 if (txq->meta[i].flags & CMD_MAPPED) {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200158 pci_unmap_single(il->pci_dev,
Stanislaw Gruszka8a032c12011-02-28 14:33:14 +0100159 dma_unmap_addr(&txq->meta[i], mapping),
160 dma_unmap_len(&txq->meta[i], len),
161 PCI_DMA_BIDIRECTIONAL);
Stanislaw Gruszka81e63262011-04-28 11:51:31 +0200162 txq->meta[i].flags = 0;
163 }
Stanislaw Gruszka8a032c12011-02-28 14:33:14 +0100164
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200165 q->read_ptr = il_queue_inc_wrap(q->read_ptr, q->n_bd);
Stanislaw Gruszka8a032c12011-02-28 14:33:14 +0100166 }
167
Stanislaw Gruszka81e63262011-04-28 11:51:31 +0200168 i = q->n_window;
169 if (txq->meta[i].flags & CMD_MAPPED) {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200170 pci_unmap_single(il->pci_dev,
Stanislaw Gruszka8a032c12011-02-28 14:33:14 +0100171 dma_unmap_addr(&txq->meta[i], mapping),
172 dma_unmap_len(&txq->meta[i], len),
173 PCI_DMA_BIDIRECTIONAL);
Stanislaw Gruszka81e63262011-04-28 11:51:31 +0200174 txq->meta[i].flags = 0;
Stanislaw Gruszka8a032c12011-02-28 14:33:14 +0100175 }
176}
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200177EXPORT_SYMBOL(il_cmd_queue_unmap);
Stanislaw Gruszka8a032c12011-02-28 14:33:14 +0100178
179/**
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200180 * il_cmd_queue_free - Deallocate DMA queue.
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800181 * @txq: Transmit queue to deallocate.
182 *
183 * Empty queue by removing and destroying all BD's.
184 * Free all buffers.
185 * 0-fill, but do not free "txq" descriptor structure.
186 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200187void il_cmd_queue_free(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800188{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200189 struct il_tx_queue *txq = &il->txq[il->cmd_queue];
190 struct device *dev = &il->pci_dev->dev;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800191 int i;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800192
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200193 il_cmd_queue_unmap(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800194
195 /* De-alloc array of command/tx buffers */
196 for (i = 0; i <= TFD_CMD_SLOTS; i++)
197 kfree(txq->cmd[i]);
198
199 /* De-alloc circular buffer of TFDs */
200 if (txq->q.n_bd)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200201 dma_free_coherent(dev, il->hw_params.tfd_size * txq->q.n_bd,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800202 txq->tfds, txq->q.dma_addr);
203
204 /* deallocate arrays */
205 kfree(txq->cmd);
206 kfree(txq->meta);
207 txq->cmd = NULL;
208 txq->meta = NULL;
209
210 /* 0-fill queue descriptor structure */
211 memset(txq, 0, sizeof(*txq));
212}
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200213EXPORT_SYMBOL(il_cmd_queue_free);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800214
215/*************** DMA-QUEUE-GENERAL-FUNCTIONS *****
216 * DMA services
217 *
218 * Theory of operation
219 *
220 * A Tx or Rx queue resides in host DRAM, and is comprised of a circular buffer
221 * of buffer descriptors, each of which points to one or more data buffers for
222 * the device to read from or fill. Driver and device exchange status of each
223 * queue via "read" and "write" pointers. Driver keeps minimum of 2 empty
224 * entries in each circular buffer, to protect against confusing empty and full
225 * queue states.
226 *
227 * The device reads or writes the data in the queues via the device's several
228 * DMA/FIFO channels. Each queue is mapped to a single DMA channel.
229 *
230 * For Tx queue, there are low mark and high mark limits. If, after queuing
231 * the packet for Tx, free space become < low mark, Tx queue stopped. When
232 * reclaiming packets (on 'tx done IRQ), if free space become > high mark,
233 * Tx queue resumed.
234 *
235 * See more detailed info in iwl-4965-hw.h.
236 ***************************************************/
237
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200238int il_queue_space(const struct il_queue *q)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800239{
240 int s = q->read_ptr - q->write_ptr;
241
242 if (q->read_ptr > q->write_ptr)
243 s -= q->n_bd;
244
245 if (s <= 0)
246 s += q->n_window;
247 /* keep some reserve to not confuse empty and full situations */
248 s -= 2;
249 if (s < 0)
250 s = 0;
251 return s;
252}
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200253EXPORT_SYMBOL(il_queue_space);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800254
255
256/**
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200257 * il_queue_init - Initialize queue's high/low-water and read/write indexes
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800258 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200259static int il_queue_init(struct il_priv *il, struct il_queue *q,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800260 int count, int slots_num, u32 id)
261{
262 q->n_bd = count;
263 q->n_window = slots_num;
264 q->id = id;
265
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200266 /* count must be power-of-two size, otherwise il_queue_inc_wrap
267 * and il_queue_dec_wrap are broken. */
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800268 BUG_ON(!is_power_of_2(count));
269
270 /* slots_num must be power-of-two size, otherwise
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200271 * il_get_cmd_index is broken. */
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800272 BUG_ON(!is_power_of_2(slots_num));
273
274 q->low_mark = q->n_window / 4;
275 if (q->low_mark < 4)
276 q->low_mark = 4;
277
278 q->high_mark = q->n_window / 8;
279 if (q->high_mark < 2)
280 q->high_mark = 2;
281
282 q->write_ptr = q->read_ptr = 0;
283
284 return 0;
285}
286
287/**
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200288 * il_tx_queue_alloc - Alloc driver data and TFD CB for one Tx/cmd queue
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800289 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200290static int il_tx_queue_alloc(struct il_priv *il,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200291 struct il_tx_queue *txq, u32 id)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800292{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200293 struct device *dev = &il->pci_dev->dev;
294 size_t tfd_sz = il->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800295
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200296 /* Driver ilate data, only for Tx (not command) queues,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800297 * not shared with device. */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200298 if (id != il->cmd_queue) {
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800299 txq->txb = kzalloc(sizeof(txq->txb[0]) *
300 TFD_QUEUE_SIZE_MAX, GFP_KERNEL);
301 if (!txq->txb) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +0200302 IL_ERR("kmalloc for auxiliary BD "
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800303 "structures failed\n");
304 goto error;
305 }
306 } else {
307 txq->txb = NULL;
308 }
309
310 /* Circular buffer of transmit frame descriptors (TFDs),
311 * shared with device */
312 txq->tfds = dma_alloc_coherent(dev, tfd_sz, &txq->q.dma_addr,
313 GFP_KERNEL);
314 if (!txq->tfds) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +0200315 IL_ERR("pci_alloc_consistent(%zd) failed\n", tfd_sz);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800316 goto error;
317 }
318 txq->q.id = id;
319
320 return 0;
321
322 error:
323 kfree(txq->txb);
324 txq->txb = NULL;
325
326 return -ENOMEM;
327}
328
329/**
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200330 * il_tx_queue_init - Allocate and initialize one tx/cmd queue
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800331 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200332int il_tx_queue_init(struct il_priv *il, struct il_tx_queue *txq,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800333 int slots_num, u32 txq_id)
334{
335 int i, len;
336 int ret;
337 int actual_slots = slots_num;
338
339 /*
340 * Alloc buffer array for commands (Tx or other types of commands).
341 * For the command queue (#4/#9), allocate command space + one big
342 * command for scan, since scan command is very huge; the system will
343 * not have two scans at the same time, so only one is needed.
344 * For normal Tx queues (all other queues), no super-size command
345 * space is needed.
346 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200347 if (txq_id == il->cmd_queue)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800348 actual_slots++;
349
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200350 txq->meta = kzalloc(sizeof(struct il_cmd_meta) * actual_slots,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800351 GFP_KERNEL);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200352 txq->cmd = kzalloc(sizeof(struct il_device_cmd *) * actual_slots,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800353 GFP_KERNEL);
354
355 if (!txq->meta || !txq->cmd)
356 goto out_free_arrays;
357
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200358 len = sizeof(struct il_device_cmd);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800359 for (i = 0; i < actual_slots; i++) {
360 /* only happens for cmd queue */
361 if (i == slots_num)
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200362 len = IL_MAX_CMD_SIZE;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800363
364 txq->cmd[i] = kmalloc(len, GFP_KERNEL);
365 if (!txq->cmd[i])
366 goto err;
367 }
368
369 /* Alloc driver data array and TFD circular buffer */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200370 ret = il_tx_queue_alloc(il, txq, txq_id);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800371 if (ret)
372 goto err;
373
374 txq->need_update = 0;
375
376 /*
377 * For the default queues 0-3, set up the swq_id
378 * already -- all others need to get one later
379 * (if they need one at all).
380 */
381 if (txq_id < 4)
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200382 il_set_swq_id(txq, txq_id, txq_id);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800383
384 /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200385 * il_queue_inc_wrap and il_queue_dec_wrap are broken. */
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800386 BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));
387
388 /* Initialize queue's high/low-water marks, and head/tail indexes */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200389 il_queue_init(il, &txq->q,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800390 TFD_QUEUE_SIZE_MAX, slots_num, txq_id);
391
392 /* Tell device where to find queue */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200393 il->cfg->ops->lib->txq_init(il, txq);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800394
395 return 0;
396err:
397 for (i = 0; i < actual_slots; i++)
398 kfree(txq->cmd[i]);
399out_free_arrays:
400 kfree(txq->meta);
401 kfree(txq->cmd);
402
403 return -ENOMEM;
404}
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200405EXPORT_SYMBOL(il_tx_queue_init);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800406
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200407void il_tx_queue_reset(struct il_priv *il, struct il_tx_queue *txq,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800408 int slots_num, u32 txq_id)
409{
410 int actual_slots = slots_num;
411
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200412 if (txq_id == il->cmd_queue)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800413 actual_slots++;
414
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200415 memset(txq->meta, 0, sizeof(struct il_cmd_meta) * actual_slots);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800416
417 txq->need_update = 0;
418
419 /* Initialize queue's high/low-water marks, and head/tail indexes */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200420 il_queue_init(il, &txq->q,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800421 TFD_QUEUE_SIZE_MAX, slots_num, txq_id);
422
423 /* Tell device where to find queue */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200424 il->cfg->ops->lib->txq_init(il, txq);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800425}
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200426EXPORT_SYMBOL(il_tx_queue_reset);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800427
428/*************** HOST COMMAND QUEUE FUNCTIONS *****/
429
430/**
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200431 * il_enqueue_hcmd - enqueue a uCode command
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200432 * @il: device ilate data point
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800433 * @cmd: a point to the ucode command structure
434 *
435 * The function returns < 0 values to indicate the operation is
436 * failed. On success, it turns the index (> 0) of command in the
437 * command queue.
438 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200439int il_enqueue_hcmd(struct il_priv *il, struct il_host_cmd *cmd)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800440{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200441 struct il_tx_queue *txq = &il->txq[il->cmd_queue];
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200442 struct il_queue *q = &txq->q;
443 struct il_device_cmd *out_cmd;
444 struct il_cmd_meta *out_meta;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800445 dma_addr_t phys_addr;
446 unsigned long flags;
447 int len;
448 u32 idx;
449 u16 fix_size;
450
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200451 cmd->len = il->cfg->ops->utils->get_hcmd_size(cmd->id, cmd->len);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800452 fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr));
453
454 /* If any of the command structures end up being larger than
455 * the TFD_MAX_PAYLOAD_SIZE, and it sent as a 'small' command then
456 * we will need to increase the size of the TFD entries
457 * Also, check to see if command buffer should not exceed the size
458 * of device_cmd and max_cmd_size. */
459 BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) &&
460 !(cmd->flags & CMD_SIZE_HUGE));
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200461 BUG_ON(fix_size > IL_MAX_CMD_SIZE);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800462
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200463 if (il_is_rfkill(il) || il_is_ctkill(il)) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +0200464 IL_WARN("Not sending command - %s KILL\n",
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200465 il_is_rfkill(il) ? "RF" : "CT");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800466 return -EIO;
467 }
468
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200469 spin_lock_irqsave(&il->hcmd_lock, flags);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800470
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200471 if (il_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200472 spin_unlock_irqrestore(&il->hcmd_lock, flags);
Stanislaw Gruszka81e63262011-04-28 11:51:31 +0200473
Stanislaw Gruszka9406f792011-08-18 22:07:57 +0200474 IL_ERR("Restarting adapter due to command queue full\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200475 queue_work(il->workqueue, &il->restart);
Stanislaw Gruszka81e63262011-04-28 11:51:31 +0200476 return -ENOSPC;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800477 }
478
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200479 idx = il_get_cmd_index(q, q->write_ptr, cmd->flags & CMD_SIZE_HUGE);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800480 out_cmd = txq->cmd[idx];
481 out_meta = &txq->meta[idx];
482
Stanislaw Gruszka81e63262011-04-28 11:51:31 +0200483 if (WARN_ON(out_meta->flags & CMD_MAPPED)) {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200484 spin_unlock_irqrestore(&il->hcmd_lock, flags);
Stanislaw Gruszka81e63262011-04-28 11:51:31 +0200485 return -ENOSPC;
486 }
487
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800488 memset(out_meta, 0, sizeof(*out_meta)); /* re-initialize to NULL */
Stanislaw Gruszka81e63262011-04-28 11:51:31 +0200489 out_meta->flags = cmd->flags | CMD_MAPPED;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800490 if (cmd->flags & CMD_WANT_SKB)
491 out_meta->source = cmd;
492 if (cmd->flags & CMD_ASYNC)
493 out_meta->callback = cmd->callback;
494
495 out_cmd->hdr.cmd = cmd->id;
496 memcpy(&out_cmd->cmd.payload, cmd->data, cmd->len);
497
498 /* At this point, the out_cmd now has all of the incoming cmd
499 * information */
500
501 out_cmd->hdr.flags = 0;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200502 out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(il->cmd_queue) |
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800503 INDEX_TO_SEQ(q->write_ptr));
504 if (cmd->flags & CMD_SIZE_HUGE)
505 out_cmd->hdr.sequence |= SEQ_HUGE_FRAME;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200506 len = sizeof(struct il_device_cmd);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800507 if (idx == TFD_CMD_SLOTS)
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200508 len = IL_MAX_CMD_SIZE;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800509
Stanislaw Gruszkad3175162011-11-15 11:25:42 +0100510#ifdef CONFIG_IWLEGACY_DEBUG
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800511 switch (out_cmd->hdr.cmd) {
512 case REPLY_TX_LINK_QUALITY_CMD:
513 case SENSITIVITY_CMD:
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +0100514 D_HC_DUMP(
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800515 "Sending command %s (#%x), seq: 0x%04X, "
516 "%d bytes at %d[%d]:%d\n",
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200517 il_get_cmd_string(out_cmd->hdr.cmd),
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800518 out_cmd->hdr.cmd,
519 le16_to_cpu(out_cmd->hdr.sequence), fix_size,
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200520 q->write_ptr, idx, il->cmd_queue);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800521 break;
522 default:
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +0100523 D_HC("Sending command %s (#%x), seq: 0x%04X, "
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800524 "%d bytes at %d[%d]:%d\n",
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200525 il_get_cmd_string(out_cmd->hdr.cmd),
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800526 out_cmd->hdr.cmd,
527 le16_to_cpu(out_cmd->hdr.sequence), fix_size,
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200528 q->write_ptr, idx, il->cmd_queue);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800529 }
530#endif
531 txq->need_update = 1;
532
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200533 if (il->cfg->ops->lib->txq_update_byte_cnt_tbl)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800534 /* Set up entry in queue's byte count circular buffer */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200535 il->cfg->ops->lib->txq_update_byte_cnt_tbl(il, txq, 0);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800536
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200537 phys_addr = pci_map_single(il->pci_dev, &out_cmd->hdr,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800538 fix_size, PCI_DMA_BIDIRECTIONAL);
539 dma_unmap_addr_set(out_meta, mapping, phys_addr);
540 dma_unmap_len_set(out_meta, len, fix_size);
541
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200542 il->cfg->ops->lib->txq_attach_buf_to_tfd(il, txq,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800543 phys_addr, fix_size, 1,
544 U32_PAD(cmd->len));
545
546 /* Increment and update queue's write index */
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200547 q->write_ptr = il_queue_inc_wrap(q->write_ptr, q->n_bd);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200548 il_txq_update_write_ptr(il, txq);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800549
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200550 spin_unlock_irqrestore(&il->hcmd_lock, flags);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800551 return idx;
552}
553
554/**
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200555 * il_hcmd_queue_reclaim - Reclaim TX command queue entries already Tx'd
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800556 *
557 * When FW advances 'R' index, all entries between old and new 'R' index
558 * need to be reclaimed. As result, some free space forms. If there is
559 * enough free space (> low mark), wake the stack that feeds us.
560 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200561static void il_hcmd_queue_reclaim(struct il_priv *il, int txq_id,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800562 int idx, int cmd_idx)
563{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200564 struct il_tx_queue *txq = &il->txq[txq_id];
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200565 struct il_queue *q = &txq->q;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800566 int nfreed = 0;
567
Stanislaw Gruszka232913b2011-08-26 10:45:16 +0200568 if (idx >= q->n_bd || il_queue_used(q, idx) == 0) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +0200569 IL_ERR("Read index for DMA queue txq id (%d), index %d, "
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800570 "is out of range [0-%d] %d %d.\n", txq_id,
571 idx, q->n_bd, q->write_ptr, q->read_ptr);
572 return;
573 }
574
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200575 for (idx = il_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx;
576 q->read_ptr = il_queue_inc_wrap(q->read_ptr, q->n_bd)) {
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800577
578 if (nfreed++ > 0) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +0200579 IL_ERR("HCMD skipped: index (%d) %d %d\n", idx,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800580 q->write_ptr, q->read_ptr);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200581 queue_work(il->workqueue, &il->restart);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800582 }
583
584 }
585}
586
587/**
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200588 * il_tx_cmd_complete - Pull unused buffers off the queue and reclaim them
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800589 * @rxb: Rx buffer to reclaim
590 *
591 * If an Rx buffer has an async callback associated with it the callback
592 * will be executed. The attached skb (if present) will only be freed
593 * if the callback returns 1
594 */
595void
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200596il_tx_cmd_complete(struct il_priv *il, struct il_rx_mem_buffer *rxb)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800597{
Stanislaw Gruszkadcae1c62011-08-26 14:36:21 +0200598 struct il_rx_pkt *pkt = rxb_addr(rxb);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800599 u16 sequence = le16_to_cpu(pkt->hdr.sequence);
600 int txq_id = SEQ_TO_QUEUE(sequence);
601 int index = SEQ_TO_INDEX(sequence);
602 int cmd_index;
603 bool huge = !!(pkt->hdr.sequence & SEQ_HUGE_FRAME);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200604 struct il_device_cmd *cmd;
605 struct il_cmd_meta *meta;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200606 struct il_tx_queue *txq = &il->txq[il->cmd_queue];
Stanislaw Gruszka81e63262011-04-28 11:51:31 +0200607 unsigned long flags;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800608
609 /* If a Tx command is being handled and it isn't in the actual
610 * command queue then there a command routing bug has been introduced
611 * in the queue management code. */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200612 if (WARN(txq_id != il->cmd_queue,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800613 "wrong command queue %d (should be %d), sequence 0x%X readp=%d writep=%d\n",
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200614 txq_id, il->cmd_queue, sequence,
615 il->txq[il->cmd_queue].q.read_ptr,
616 il->txq[il->cmd_queue].q.write_ptr)) {
617 il_print_hex_error(il, pkt, 32);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800618 return;
619 }
620
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200621 cmd_index = il_get_cmd_index(&txq->q, index, huge);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800622 cmd = txq->cmd[cmd_index];
623 meta = &txq->meta[cmd_index];
624
Stanislaw Gruszka2e2a41d2011-09-20 16:46:36 +0200625 txq->time_stamp = jiffies;
626
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200627 pci_unmap_single(il->pci_dev,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800628 dma_unmap_addr(meta, mapping),
629 dma_unmap_len(meta, len),
630 PCI_DMA_BIDIRECTIONAL);
631
632 /* Input error checking is done when commands are added to queue. */
633 if (meta->flags & CMD_WANT_SKB) {
634 meta->source->reply_page = (unsigned long)rxb_addr(rxb);
635 rxb->page = NULL;
636 } else if (meta->callback)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200637 meta->callback(il, cmd, pkt);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800638
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200639 spin_lock_irqsave(&il->hcmd_lock, flags);
Stanislaw Gruszka81e63262011-04-28 11:51:31 +0200640
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200641 il_hcmd_queue_reclaim(il, txq_id, index, cmd_index);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800642
643 if (!(meta->flags & CMD_ASYNC)) {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200644 clear_bit(STATUS_HCMD_ACTIVE, &il->status);
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +0100645 D_INFO("Clearing HCMD_ACTIVE for command %s\n",
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200646 il_get_cmd_string(cmd->hdr.cmd));
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200647 wake_up(&il->wait_command_queue);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800648 }
Stanislaw Gruszka81e63262011-04-28 11:51:31 +0200649
650 /* Mark as unmapped */
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800651 meta->flags = 0;
Stanislaw Gruszka81e63262011-04-28 11:51:31 +0200652
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200653 spin_unlock_irqrestore(&il->hcmd_lock, flags);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800654}
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200655EXPORT_SYMBOL(il_tx_cmd_complete);