blob: 21a1381c9748c0f523cf18c552f4a876b68af137 [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#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
31
32#include <linux/kernel.h>
33#include <linux/module.h>
34#include <linux/init.h>
35#include <linux/pci.h>
36#include <linux/pci-aspm.h>
37#include <linux/slab.h>
38#include <linux/dma-mapping.h>
39#include <linux/delay.h>
40#include <linux/sched.h>
41#include <linux/skbuff.h>
42#include <linux/netdevice.h>
Wey-Yi Guybe663ab2011-02-21 11:27:26 -080043#include <linux/firmware.h>
44#include <linux/etherdevice.h>
45#include <linux/if_arp.h>
46
47#include <net/mac80211.h>
48
49#include <asm/div64.h>
50
51#define DRV_NAME "iwl4965"
52
Stanislaw Gruszka98613be2011-11-15 14:19:34 +010053#include "common.h"
Stanislaw Gruszkaaf038f42011-08-30 13:58:27 +020054#include "4965.h"
Wey-Yi Guybe663ab2011-02-21 11:27:26 -080055
Wey-Yi Guybe663ab2011-02-21 11:27:26 -080056/******************************************************************************
57 *
58 * module boiler plate
59 *
60 ******************************************************************************/
61
62/*
63 * module name, copyright, version, etc.
64 */
65#define DRV_DESCRIPTION "Intel(R) Wireless WiFi 4965 driver for Linux"
66
Stanislaw Gruszkad3175162011-11-15 11:25:42 +010067#ifdef CONFIG_IWLEGACY_DEBUG
Wey-Yi Guybe663ab2011-02-21 11:27:26 -080068#define VD "d"
69#else
70#define VD
71#endif
72
73#define DRV_VERSION IWLWIFI_VERSION VD
74
Wey-Yi Guybe663ab2011-02-21 11:27:26 -080075MODULE_DESCRIPTION(DRV_DESCRIPTION);
76MODULE_VERSION(DRV_VERSION);
77MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
78MODULE_LICENSE("GPL");
79MODULE_ALIAS("iwl4965");
80
Stanislaw Gruszkae7392362011-11-15 14:45:59 +010081void
82il4965_check_abort_status(struct il_priv *il, u8 frame_count, u32 status)
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +020083{
84 if (frame_count == 1 && status == TX_STATUS_FAIL_RFKILL_FLUSH) {
85 IL_ERR("Tx flush command to flush out all frames\n");
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +010086 if (!test_bit(S_EXIT_PENDING, &il->status))
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +020087 queue_work(il->workqueue, &il->tx_flush);
88 }
89}
90
91/*
92 * EEPROM
93 */
94struct il_mod_params il4965_mod_params = {
95 .amsdu_size_8K = 1,
96 .restart_fw = 1,
97 /* the rest are 0 by default */
98};
99
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100100void
101il4965_rx_queue_reset(struct il_priv *il, struct il_rx_queue *rxq)
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200102{
103 unsigned long flags;
104 int i;
105 spin_lock_irqsave(&rxq->lock, flags);
106 INIT_LIST_HEAD(&rxq->rx_free);
107 INIT_LIST_HEAD(&rxq->rx_used);
108 /* Fill the rx_used queue with _all_ of the Rx buffers */
109 for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
110 /* In the reset function, these buffers may have been allocated
111 * to an SKB, so we need to unmap and free potential storage */
112 if (rxq->pool[i].page != NULL) {
113 pci_unmap_page(il->pci_dev, rxq->pool[i].page_dma,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100114 PAGE_SIZE << il->hw_params.rx_page_order,
115 PCI_DMA_FROMDEVICE);
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200116 __il_free_pages(il, rxq->pool[i].page);
117 rxq->pool[i].page = NULL;
118 }
119 list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
120 }
121
122 for (i = 0; i < RX_QUEUE_SIZE; i++)
123 rxq->queue[i] = NULL;
124
125 /* Set us so that we have processed and used all buffers, but have
126 * not restocked the Rx queue with fresh buffers */
127 rxq->read = rxq->write = 0;
128 rxq->write_actual = 0;
129 rxq->free_count = 0;
130 spin_unlock_irqrestore(&rxq->lock, flags);
131}
132
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100133int
134il4965_rx_init(struct il_priv *il, struct il_rx_queue *rxq)
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200135{
136 u32 rb_size;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100137 const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200138 u32 rb_timeout = 0;
139
140 if (il->cfg->mod_params->amsdu_size_8K)
Stanislaw Gruszka9a95b372011-08-31 14:20:23 +0200141 rb_size = FH49_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K;
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200142 else
Stanislaw Gruszka9a95b372011-08-31 14:20:23 +0200143 rb_size = FH49_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K;
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200144
145 /* Stop Rx DMA */
Stanislaw Gruszka9a95b372011-08-31 14:20:23 +0200146 il_wr(il, FH49_MEM_RCSR_CHNL0_CONFIG_REG, 0);
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200147
148 /* Reset driver's Rx queue write idx */
Stanislaw Gruszka9a95b372011-08-31 14:20:23 +0200149 il_wr(il, FH49_RSCSR_CHNL0_RBDCB_WPTR_REG, 0);
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200150
151 /* Tell device where to find RBD circular buffer in DRAM */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100152 il_wr(il, FH49_RSCSR_CHNL0_RBDCB_BASE_REG, (u32) (rxq->bd_dma >> 8));
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200153
154 /* Tell device where in DRAM to update its Rx status */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100155 il_wr(il, FH49_RSCSR_CHNL0_STTS_WPTR_REG, rxq->rb_stts_dma >> 4);
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200156
157 /* Enable Rx DMA
158 * Direct rx interrupts to hosts
159 * Rx buffer size 4 or 8k
160 * RB timeout 0x10
161 * 256 RBDs
162 */
Stanislaw Gruszka9a95b372011-08-31 14:20:23 +0200163 il_wr(il, FH49_MEM_RCSR_CHNL0_CONFIG_REG,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100164 FH49_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
165 FH49_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
Stanislaw Gruszka1722f8e2011-11-15 14:51:01 +0100166 FH49_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK |
167 rb_size |
168 (rb_timeout << FH49_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS) |
169 (rfdnlog << FH49_RCSR_RX_CONFIG_RBDCB_SIZE_POS));
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200170
171 /* Set interrupt coalescing timer to default (2048 usecs) */
172 il_write8(il, CSR_INT_COALESCING, IL_HOST_INT_TIMEOUT_DEF);
173
174 return 0;
175}
176
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100177static void
178il4965_set_pwr_vmain(struct il_priv *il)
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200179{
180/*
181 * (for documentation purposes)
182 * to set power to V_AUX, do:
183
184 if (pci_pme_capable(il->pci_dev, PCI_D3cold))
185 il_set_bits_mask_prph(il, APMG_PS_CTRL_REG,
186 APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
187 ~APMG_PS_CTRL_MSK_PWR_SRC);
188 */
189
190 il_set_bits_mask_prph(il, APMG_PS_CTRL_REG,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100191 APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
192 ~APMG_PS_CTRL_MSK_PWR_SRC);
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200193}
194
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100195int
196il4965_hw_nic_init(struct il_priv *il)
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200197{
198 unsigned long flags;
199 struct il_rx_queue *rxq = &il->rxq;
200 int ret;
201
202 /* nic_init */
203 spin_lock_irqsave(&il->lock, flags);
204 il->cfg->ops->lib->apm_ops.init(il);
205
206 /* Set interrupt coalescing calibration timer to default (512 usecs) */
207 il_write8(il, CSR_INT_COALESCING, IL_HOST_INT_CALIB_TIMEOUT_DEF);
208
209 spin_unlock_irqrestore(&il->lock, flags);
210
211 il4965_set_pwr_vmain(il);
212
213 il->cfg->ops->lib->apm_ops.config(il);
214
215 /* Allocate the RX queue, or reset if it is already allocated */
216 if (!rxq->bd) {
217 ret = il_rx_queue_alloc(il);
218 if (ret) {
219 IL_ERR("Unable to initialize Rx queue\n");
220 return -ENOMEM;
221 }
222 } else
223 il4965_rx_queue_reset(il, rxq);
224
225 il4965_rx_replenish(il);
226
227 il4965_rx_init(il, rxq);
228
229 spin_lock_irqsave(&il->lock, flags);
230
231 rxq->need_update = 1;
232 il_rx_queue_update_write_ptr(il, rxq);
233
234 spin_unlock_irqrestore(&il->lock, flags);
235
236 /* Allocate or reset and init all Tx and Command queues */
237 if (!il->txq) {
238 ret = il4965_txq_ctx_alloc(il);
239 if (ret)
240 return ret;
241 } else
242 il4965_txq_ctx_reset(il);
243
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +0100244 set_bit(S_INIT, &il->status);
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200245
246 return 0;
247}
248
249/**
250 * il4965_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr
251 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100252static inline __le32
253il4965_dma_addr2rbd_ptr(struct il_priv *il, dma_addr_t dma_addr)
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200254{
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100255 return cpu_to_le32((u32) (dma_addr >> 8));
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200256}
257
258/**
259 * il4965_rx_queue_restock - refill RX queue from pre-allocated pool
260 *
261 * If there are slots in the RX queue that need to be restocked,
262 * and we have free pre-allocated buffers, fill the ranks as much
263 * as we can, pulling from rx_free.
264 *
265 * This moves the 'write' idx forward to catch up with 'processed', and
266 * also updates the memory address in the firmware to reference the new
267 * target buffer.
268 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100269void
270il4965_rx_queue_restock(struct il_priv *il)
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200271{
272 struct il_rx_queue *rxq = &il->rxq;
273 struct list_head *element;
274 struct il_rx_buf *rxb;
275 unsigned long flags;
276
277 spin_lock_irqsave(&rxq->lock, flags);
278 while (il_rx_queue_space(rxq) > 0 && rxq->free_count) {
279 /* The overwritten rxb must be a used one */
280 rxb = rxq->queue[rxq->write];
281 BUG_ON(rxb && rxb->page);
282
283 /* Get next free Rx buffer, remove from free list */
284 element = rxq->rx_free.next;
285 rxb = list_entry(element, struct il_rx_buf, list);
286 list_del(element);
287
288 /* Point to Rx buffer via next RBD in circular buffer */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100289 rxq->bd[rxq->write] =
290 il4965_dma_addr2rbd_ptr(il, rxb->page_dma);
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200291 rxq->queue[rxq->write] = rxb;
292 rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
293 rxq->free_count--;
294 }
295 spin_unlock_irqrestore(&rxq->lock, flags);
296 /* If the pre-allocated buffer pool is dropping low, schedule to
297 * refill it */
298 if (rxq->free_count <= RX_LOW_WATERMARK)
299 queue_work(il->workqueue, &il->rx_replenish);
300
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200301 /* If we've added more space for the firmware to place data, tell it.
302 * Increment device's write pointer in multiples of 8. */
303 if (rxq->write_actual != (rxq->write & ~0x7)) {
304 spin_lock_irqsave(&rxq->lock, flags);
305 rxq->need_update = 1;
306 spin_unlock_irqrestore(&rxq->lock, flags);
307 il_rx_queue_update_write_ptr(il, rxq);
308 }
309}
310
311/**
312 * il4965_rx_replenish - Move all used packet from rx_used to rx_free
313 *
314 * When moving to rx_free an SKB is allocated for the slot.
315 *
316 * Also restock the Rx queue via il_rx_queue_restock.
317 * This is called as a scheduled work item (except for during initialization)
318 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100319static void
320il4965_rx_allocate(struct il_priv *il, gfp_t priority)
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200321{
322 struct il_rx_queue *rxq = &il->rxq;
323 struct list_head *element;
324 struct il_rx_buf *rxb;
325 struct page *page;
326 unsigned long flags;
327 gfp_t gfp_mask = priority;
328
329 while (1) {
330 spin_lock_irqsave(&rxq->lock, flags);
331 if (list_empty(&rxq->rx_used)) {
332 spin_unlock_irqrestore(&rxq->lock, flags);
333 return;
334 }
335 spin_unlock_irqrestore(&rxq->lock, flags);
336
337 if (rxq->free_count > RX_LOW_WATERMARK)
338 gfp_mask |= __GFP_NOWARN;
339
340 if (il->hw_params.rx_page_order > 0)
341 gfp_mask |= __GFP_COMP;
342
343 /* Alloc a new receive buffer */
344 page = alloc_pages(gfp_mask, il->hw_params.rx_page_order);
345 if (!page) {
346 if (net_ratelimit())
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100347 D_INFO("alloc_pages failed, " "order: %d\n",
348 il->hw_params.rx_page_order);
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200349
350 if (rxq->free_count <= RX_LOW_WATERMARK &&
351 net_ratelimit())
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100352 IL_ERR("Failed to alloc_pages with %s. "
353 "Only %u free buffers remaining.\n",
354 priority ==
355 GFP_ATOMIC ? "GFP_ATOMIC" : "GFP_KERNEL",
356 rxq->free_count);
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200357 /* We don't reschedule replenish work here -- we will
358 * call the restock method and if it still needs
359 * more buffers it will schedule replenish */
360 return;
361 }
362
363 spin_lock_irqsave(&rxq->lock, flags);
364
365 if (list_empty(&rxq->rx_used)) {
366 spin_unlock_irqrestore(&rxq->lock, flags);
367 __free_pages(page, il->hw_params.rx_page_order);
368 return;
369 }
370 element = rxq->rx_used.next;
371 rxb = list_entry(element, struct il_rx_buf, list);
372 list_del(element);
373
374 spin_unlock_irqrestore(&rxq->lock, flags);
375
376 BUG_ON(rxb->page);
377 rxb->page = page;
378 /* Get physical address of the RB */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100379 rxb->page_dma =
380 pci_map_page(il->pci_dev, page, 0,
381 PAGE_SIZE << il->hw_params.rx_page_order,
382 PCI_DMA_FROMDEVICE);
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200383 /* dma address must be no more than 36 bits */
384 BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36));
385 /* and also 256 byte aligned! */
386 BUG_ON(rxb->page_dma & DMA_BIT_MASK(8));
387
388 spin_lock_irqsave(&rxq->lock, flags);
389
390 list_add_tail(&rxb->list, &rxq->rx_free);
391 rxq->free_count++;
392 il->alloc_rxb_page++;
393
394 spin_unlock_irqrestore(&rxq->lock, flags);
395 }
396}
397
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100398void
399il4965_rx_replenish(struct il_priv *il)
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200400{
401 unsigned long flags;
402
403 il4965_rx_allocate(il, GFP_KERNEL);
404
405 spin_lock_irqsave(&il->lock, flags);
406 il4965_rx_queue_restock(il);
407 spin_unlock_irqrestore(&il->lock, flags);
408}
409
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100410void
411il4965_rx_replenish_now(struct il_priv *il)
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200412{
413 il4965_rx_allocate(il, GFP_ATOMIC);
414
415 il4965_rx_queue_restock(il);
416}
417
418/* Assumes that the skb field of the buffers in 'pool' is kept accurate.
419 * If an SKB has been detached, the POOL needs to have its SKB set to NULL
420 * This free routine walks the list of POOL entries and if SKB is set to
421 * non NULL it is unmapped and freed
422 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100423void
424il4965_rx_queue_free(struct il_priv *il, struct il_rx_queue *rxq)
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200425{
426 int i;
427 for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
428 if (rxq->pool[i].page != NULL) {
429 pci_unmap_page(il->pci_dev, rxq->pool[i].page_dma,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100430 PAGE_SIZE << il->hw_params.rx_page_order,
431 PCI_DMA_FROMDEVICE);
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200432 __il_free_pages(il, rxq->pool[i].page);
433 rxq->pool[i].page = NULL;
434 }
435 }
436
437 dma_free_coherent(&il->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
438 rxq->bd_dma);
439 dma_free_coherent(&il->pci_dev->dev, sizeof(struct il_rb_status),
440 rxq->rb_stts, rxq->rb_stts_dma);
441 rxq->bd = NULL;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100442 rxq->rb_stts = NULL;
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200443}
444
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100445int
446il4965_rxq_stop(struct il_priv *il)
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200447{
448
449 /* stop Rx DMA */
Stanislaw Gruszka9a95b372011-08-31 14:20:23 +0200450 il_wr(il, FH49_MEM_RCSR_CHNL0_CONFIG_REG, 0);
451 il_poll_bit(il, FH49_MEM_RSSR_RX_STATUS_REG,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100452 FH49_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000);
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200453
454 return 0;
455}
456
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100457int
458il4965_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band)
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200459{
460 int idx = 0;
461 int band_offset = 0;
462
463 /* HT rate format: mac80211 wants an MCS number, which is just LSB */
464 if (rate_n_flags & RATE_MCS_HT_MSK) {
465 idx = (rate_n_flags & 0xff);
466 return idx;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100467 /* Legacy rate format, search for match in table */
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200468 } else {
469 if (band == IEEE80211_BAND_5GHZ)
470 band_offset = IL_FIRST_OFDM_RATE;
471 for (idx = band_offset; idx < RATE_COUNT_LEGACY; idx++)
472 if (il_rates[idx].plcp == (rate_n_flags & 0xFF))
473 return idx - band_offset;
474 }
475
476 return -1;
477}
478
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100479static int
480il4965_calc_rssi(struct il_priv *il, struct il_rx_phy_res *rx_resp)
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200481{
482 /* data from PHY/DSP regarding signal strength, etc.,
483 * contents are always there, not configurable by host. */
484 struct il4965_rx_non_cfg_phy *ncphy =
485 (struct il4965_rx_non_cfg_phy *)rx_resp->non_cfg_phy_buf;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100486 u32 agc =
487 (le16_to_cpu(ncphy->agc_info) & IL49_AGC_DB_MASK) >>
488 IL49_AGC_DB_POS;
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200489
490 u32 valid_antennae =
491 (le16_to_cpu(rx_resp->phy_flags) & IL49_RX_PHY_FLAGS_ANTENNAE_MASK)
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100492 >> IL49_RX_PHY_FLAGS_ANTENNAE_OFFSET;
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200493 u8 max_rssi = 0;
494 u32 i;
495
496 /* Find max rssi among 3 possible receivers.
497 * These values are measured by the digital signal processor (DSP).
498 * They should stay fairly constant even as the signal strength varies,
499 * if the radio's automatic gain control (AGC) is working right.
500 * AGC value (see below) will provide the "interesting" info. */
501 for (i = 0; i < 3; i++)
502 if (valid_antennae & (1 << i))
503 max_rssi = max(ncphy->rssi_info[i << 1], max_rssi);
504
505 D_STATS("Rssi In A %d B %d C %d Max %d AGC dB %d\n",
506 ncphy->rssi_info[0], ncphy->rssi_info[2], ncphy->rssi_info[4],
507 max_rssi, agc);
508
509 /* dBm = max_rssi dB - agc dB - constant.
510 * Higher AGC (higher radio gain) means lower signal. */
511 return max_rssi - agc - IL4965_RSSI_OFFSET;
512}
513
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100514static u32
515il4965_translate_rx_status(struct il_priv *il, u32 decrypt_in)
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200516{
517 u32 decrypt_out = 0;
518
519 if ((decrypt_in & RX_RES_STATUS_STATION_FOUND) ==
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100520 RX_RES_STATUS_STATION_FOUND)
521 decrypt_out |=
522 (RX_RES_STATUS_STATION_FOUND |
523 RX_RES_STATUS_NO_STATION_INFO_MISMATCH);
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200524
525 decrypt_out |= (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK);
526
527 /* packet was not encrypted */
528 if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) ==
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100529 RX_RES_STATUS_SEC_TYPE_NONE)
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200530 return decrypt_out;
531
532 /* packet was encrypted with unknown alg */
533 if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) ==
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100534 RX_RES_STATUS_SEC_TYPE_ERR)
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200535 return decrypt_out;
536
537 /* decryption was not done in HW */
538 if ((decrypt_in & RX_MPDU_RES_STATUS_DEC_DONE_MSK) !=
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100539 RX_MPDU_RES_STATUS_DEC_DONE_MSK)
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200540 return decrypt_out;
541
542 switch (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) {
543
544 case RX_RES_STATUS_SEC_TYPE_CCMP:
545 /* alg is CCM: check MIC only */
546 if (!(decrypt_in & RX_MPDU_RES_STATUS_MIC_OK))
547 /* Bad MIC */
548 decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC;
549 else
550 decrypt_out |= RX_RES_STATUS_DECRYPT_OK;
551
552 break;
553
554 case RX_RES_STATUS_SEC_TYPE_TKIP:
555 if (!(decrypt_in & RX_MPDU_RES_STATUS_TTAK_OK)) {
556 /* Bad TTAK */
557 decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK;
558 break;
559 }
560 /* fall through if TTAK OK */
561 default:
562 if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK))
563 decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC;
564 else
565 decrypt_out |= RX_RES_STATUS_DECRYPT_OK;
566 break;
567 }
568
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100569 D_RX("decrypt_in:0x%x decrypt_out = 0x%x\n", decrypt_in, decrypt_out);
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200570
571 return decrypt_out;
572}
573
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100574static void
575il4965_pass_packet_to_mac80211(struct il_priv *il, struct ieee80211_hdr *hdr,
576 u16 len, u32 ampdu_status, struct il_rx_buf *rxb,
577 struct ieee80211_rx_status *stats)
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200578{
579 struct sk_buff *skb;
580 __le16 fc = hdr->frame_control;
581
582 /* We only process data packets if the interface is open */
583 if (unlikely(!il->is_open)) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100584 D_DROP("Dropping packet while interface is not open.\n");
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200585 return;
586 }
587
588 /* In case of HW accelerated crypto and bad decryption, drop */
589 if (!il->cfg->mod_params->sw_crypto &&
590 il_set_decrypted_flag(il, hdr, ampdu_status, stats))
591 return;
592
593 skb = dev_alloc_skb(128);
594 if (!skb) {
595 IL_ERR("dev_alloc_skb failed\n");
596 return;
597 }
598
599 skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len);
600
601 il_update_stats(il, false, fc, len);
602 memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
603
604 ieee80211_rx(il->hw, skb);
605 il->alloc_rxb_page--;
606 rxb->page = NULL;
607}
608
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +0200609/* Called for N_RX (legacy ABG frames), or
610 * N_RX_MPDU (HT high-throughput N frames). */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100611void
612il4965_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb)
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200613{
614 struct ieee80211_hdr *header;
615 struct ieee80211_rx_status rx_status;
616 struct il_rx_pkt *pkt = rxb_addr(rxb);
617 struct il_rx_phy_res *phy_res;
618 __le32 rx_pkt_status;
619 struct il_rx_mpdu_res_start *amsdu;
620 u32 len;
621 u32 ampdu_status;
622 u32 rate_n_flags;
623
624 /**
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +0200625 * N_RX and N_RX_MPDU are handled differently.
626 * N_RX: physical layer info is in this buffer
627 * N_RX_MPDU: physical layer info was sent in separate
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200628 * command and cached in il->last_phy_res
629 *
630 * Here we set up local variables depending on which command is
631 * received.
632 */
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +0200633 if (pkt->hdr.cmd == N_RX) {
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200634 phy_res = (struct il_rx_phy_res *)pkt->u.raw;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100635 header =
636 (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*phy_res) +
637 phy_res->cfg_phy_cnt);
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200638
639 len = le16_to_cpu(phy_res->byte_count);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100640 rx_pkt_status =
641 *(__le32 *) (pkt->u.raw + sizeof(*phy_res) +
642 phy_res->cfg_phy_cnt + len);
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200643 ampdu_status = le32_to_cpu(rx_pkt_status);
644 } else {
645 if (!il->_4965.last_phy_res_valid) {
646 IL_ERR("MPDU frame without cached PHY data\n");
647 return;
648 }
649 phy_res = &il->_4965.last_phy_res;
650 amsdu = (struct il_rx_mpdu_res_start *)pkt->u.raw;
651 header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu));
652 len = le16_to_cpu(amsdu->byte_count);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100653 rx_pkt_status = *(__le32 *) (pkt->u.raw + sizeof(*amsdu) + len);
654 ampdu_status =
655 il4965_translate_rx_status(il, le32_to_cpu(rx_pkt_status));
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200656 }
657
658 if ((unlikely(phy_res->cfg_phy_cnt > 20))) {
659 D_DROP("dsp size out of range [0,20]: %d/n",
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100660 phy_res->cfg_phy_cnt);
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200661 return;
662 }
663
664 if (!(rx_pkt_status & RX_RES_STATUS_NO_CRC32_ERROR) ||
665 !(rx_pkt_status & RX_RES_STATUS_NO_RXE_OVERFLOW)) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100666 D_RX("Bad CRC or FIFO: 0x%08X.\n", le32_to_cpu(rx_pkt_status));
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200667 return;
668 }
669
670 /* This will be used in several places later */
671 rate_n_flags = le32_to_cpu(phy_res->rate_n_flags);
672
673 /* rx_status carries information about the packet to mac80211 */
674 rx_status.mactime = le64_to_cpu(phy_res->timestamp);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100675 rx_status.band =
676 (phy_res->
677 phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? IEEE80211_BAND_2GHZ :
678 IEEE80211_BAND_5GHZ;
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200679 rx_status.freq =
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100680 ieee80211_channel_to_frequency(le16_to_cpu(phy_res->channel),
681 rx_status.band);
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200682 rx_status.rate_idx =
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100683 il4965_hwrate_to_mac80211_idx(rate_n_flags, rx_status.band);
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200684 rx_status.flag = 0;
685
686 /* TSF isn't reliable. In order to allow smooth user experience,
687 * this W/A doesn't propagate it to the mac80211 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100688 /*rx_status.flag |= RX_FLAG_MACTIME_MPDU; */
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200689
690 il->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp);
691
692 /* Find max signal strength (dBm) among 3 antenna/receiver chains */
693 rx_status.signal = il4965_calc_rssi(il, phy_res);
694
695 il_dbg_log_rx_data_frame(il, len, header);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100696 D_STATS("Rssi %d, TSF %llu\n", rx_status.signal,
697 (unsigned long long)rx_status.mactime);
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200698
699 /*
700 * "antenna number"
701 *
702 * It seems that the antenna field in the phy flags value
703 * is actually a bit field. This is undefined by radiotap,
704 * it wants an actual antenna number but I always get "7"
705 * for most legacy frames I receive indicating that the
706 * same frame was received on all three RX chains.
707 *
708 * I think this field should be removed in favor of a
709 * new 802.11n radiotap field "RX chains" that is defined
710 * as a bitmask.
711 */
712 rx_status.antenna =
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100713 (le16_to_cpu(phy_res->phy_flags) & RX_RES_PHY_FLAGS_ANTENNA_MSK) >>
714 RX_RES_PHY_FLAGS_ANTENNA_POS;
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200715
716 /* set the preamble flag if appropriate */
717 if (phy_res->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
718 rx_status.flag |= RX_FLAG_SHORTPRE;
719
720 /* Set up the HT phy flags */
721 if (rate_n_flags & RATE_MCS_HT_MSK)
722 rx_status.flag |= RX_FLAG_HT;
723 if (rate_n_flags & RATE_MCS_HT40_MSK)
724 rx_status.flag |= RX_FLAG_40MHZ;
725 if (rate_n_flags & RATE_MCS_SGI_MSK)
726 rx_status.flag |= RX_FLAG_SHORT_GI;
727
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100728 il4965_pass_packet_to_mac80211(il, header, len, ampdu_status, rxb,
729 &rx_status);
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200730}
731
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +0200732/* Cache phy data (Rx signal strength, etc) for HT frame (N_RX_PHY).
Stanislaw Gruszka6e9848b42011-08-30 15:45:31 +0200733 * This will be used later in il_hdl_rx() for N_RX_MPDU. */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100734void
735il4965_hdl_rx_phy(struct il_priv *il, struct il_rx_buf *rxb)
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200736{
737 struct il_rx_pkt *pkt = rxb_addr(rxb);
738 il->_4965.last_phy_res_valid = true;
739 memcpy(&il->_4965.last_phy_res, pkt->u.raw,
740 sizeof(struct il_rx_phy_res));
741}
742
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100743static int
744il4965_get_channels_for_scan(struct il_priv *il, struct ieee80211_vif *vif,
745 enum ieee80211_band band, u8 is_active,
746 u8 n_probes, struct il_scan_channel *scan_ch)
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200747{
748 struct ieee80211_channel *chan;
749 const struct ieee80211_supported_band *sband;
750 const struct il_channel_info *ch_info;
751 u16 passive_dwell = 0;
752 u16 active_dwell = 0;
753 int added, i;
754 u16 channel;
755
756 sband = il_get_hw_mode(il, band);
757 if (!sband)
758 return 0;
759
760 active_dwell = il_get_active_dwell_time(il, band, n_probes);
761 passive_dwell = il_get_passive_dwell_time(il, band, vif);
762
763 if (passive_dwell <= active_dwell)
764 passive_dwell = active_dwell + 1;
765
766 for (i = 0, added = 0; i < il->scan_request->n_channels; i++) {
767 chan = il->scan_request->channels[i];
768
769 if (chan->band != band)
770 continue;
771
772 channel = chan->hw_value;
773 scan_ch->channel = cpu_to_le16(channel);
774
775 ch_info = il_get_channel_info(il, band, channel);
776 if (!il_is_channel_valid(ch_info)) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100777 D_SCAN("Channel %d is INVALID for this band.\n",
778 channel);
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200779 continue;
780 }
781
782 if (!is_active || il_is_channel_passive(ch_info) ||
783 (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN))
784 scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
785 else
786 scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE;
787
788 if (n_probes)
789 scan_ch->type |= IL_SCAN_PROBE_MASK(n_probes);
790
791 scan_ch->active_dwell = cpu_to_le16(active_dwell);
792 scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
793
794 /* Set txpower levels to defaults */
795 scan_ch->dsp_atten = 110;
796
797 /* NOTE: if we were doing 6Mb OFDM for scans we'd use
798 * power level:
799 * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3;
800 */
801 if (band == IEEE80211_BAND_5GHZ)
802 scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
803 else
804 scan_ch->tx_gain = ((1 << 5) | (5 << 3));
805
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100806 D_SCAN("Scanning ch=%d prob=0x%X [%s %d]\n", channel,
807 le32_to_cpu(scan_ch->type),
808 (scan_ch->
809 type & SCAN_CHANNEL_TYPE_ACTIVE) ? "ACTIVE" : "PASSIVE",
810 (scan_ch->
811 type & SCAN_CHANNEL_TYPE_ACTIVE) ? active_dwell :
812 passive_dwell);
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200813
814 scan_ch++;
815 added++;
816 }
817
818 D_SCAN("total channels to scan %d\n", added);
819 return added;
820}
821
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100822static inline u32
823il4965_ant_idx_to_flags(u8 ant_idx)
Stanislaw Gruszkaaf038f42011-08-30 13:58:27 +0200824{
825 return BIT(ant_idx) << RATE_MCS_ANT_POS;
826}
827
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100828int
829il4965_request_scan(struct il_priv *il, struct ieee80211_vif *vif)
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200830{
831 struct il_host_cmd cmd = {
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +0200832 .id = C_SCAN,
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200833 .len = sizeof(struct il_scan_cmd),
834 .flags = CMD_SIZE_HUGE,
835 };
836 struct il_scan_cmd *scan;
837 struct il_rxon_context *ctx = &il->ctx;
838 u32 rate_flags = 0;
839 u16 cmd_len;
840 u16 rx_chain = 0;
841 enum ieee80211_band band;
842 u8 n_probes = 0;
843 u8 rx_ant = il->hw_params.valid_rx_ant;
844 u8 rate;
845 bool is_active = false;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100846 int chan_mod;
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200847 u8 active_chains;
848 u8 scan_tx_antennas = il->hw_params.valid_tx_ant;
849 int ret;
850
851 lockdep_assert_held(&il->mutex);
852
853 if (vif)
854 ctx = il_rxon_ctx_from_vif(vif);
855
856 if (!il->scan_cmd) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100857 il->scan_cmd =
858 kmalloc(sizeof(struct il_scan_cmd) + IL_MAX_SCAN_SIZE,
859 GFP_KERNEL);
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200860 if (!il->scan_cmd) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100861 D_SCAN("fail to allocate memory for scan\n");
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200862 return -ENOMEM;
863 }
864 }
865 scan = il->scan_cmd;
866 memset(scan, 0, sizeof(struct il_scan_cmd) + IL_MAX_SCAN_SIZE);
867
868 scan->quiet_plcp_th = IL_PLCP_QUIET_THRESH;
869 scan->quiet_time = IL_ACTIVE_QUIET_TIME;
870
871 if (il_is_any_associated(il)) {
872 u16 interval;
873 u32 extra;
874 u32 suspend_time = 100;
875 u32 scan_suspend_time = 100;
876
877 D_INFO("Scanning while associated...\n");
878 interval = vif->bss_conf.beacon_int;
879
880 scan->suspend_time = 0;
881 scan->max_out_time = cpu_to_le32(200 * 1024);
882 if (!interval)
883 interval = suspend_time;
884
885 extra = (suspend_time / interval) << 22;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100886 scan_suspend_time =
887 (extra | ((suspend_time % interval) * 1024));
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200888 scan->suspend_time = cpu_to_le32(scan_suspend_time);
889 D_SCAN("suspend_time 0x%X beacon interval %d\n",
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100890 scan_suspend_time, interval);
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200891 }
892
893 if (il->scan_request->n_ssids) {
894 int i, p = 0;
895 D_SCAN("Kicking off active scan\n");
896 for (i = 0; i < il->scan_request->n_ssids; i++) {
897 /* always does wildcard anyway */
898 if (!il->scan_request->ssids[i].ssid_len)
899 continue;
900 scan->direct_scan[p].id = WLAN_EID_SSID;
901 scan->direct_scan[p].len =
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100902 il->scan_request->ssids[i].ssid_len;
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200903 memcpy(scan->direct_scan[p].ssid,
904 il->scan_request->ssids[i].ssid,
905 il->scan_request->ssids[i].ssid_len);
906 n_probes++;
907 p++;
908 }
909 is_active = true;
910 } else
911 D_SCAN("Start passive scan.\n");
912
913 scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
914 scan->tx_cmd.sta_id = ctx->bcast_sta_id;
915 scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
916
917 switch (il->scan_band) {
918 case IEEE80211_BAND_2GHZ:
919 scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100920 chan_mod =
921 le32_to_cpu(il->ctx.active.
922 flags & RXON_FLG_CHANNEL_MODE_MSK) >>
923 RXON_FLG_CHANNEL_MODE_POS;
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200924 if (chan_mod == CHANNEL_MODE_PURE_40) {
925 rate = RATE_6M_PLCP;
926 } else {
927 rate = RATE_1M_PLCP;
928 rate_flags = RATE_MCS_CCK_MSK;
929 }
930 break;
931 case IEEE80211_BAND_5GHZ:
932 rate = RATE_6M_PLCP;
933 break;
934 default:
935 IL_WARN("Invalid scan band\n");
936 return -EIO;
937 }
938
939 /*
940 * If active scanning is requested but a certain channel is
941 * marked passive, we can do active scanning if we detect
942 * transmissions.
943 *
944 * There is an issue with some firmware versions that triggers
945 * a sysassert on a "good CRC threshold" of zero (== disabled),
946 * on a radar channel even though this means that we should NOT
947 * send probes.
948 *
949 * The "good CRC threshold" is the number of frames that we
950 * need to receive during our dwell time on a channel before
951 * sending out probes -- setting this to a huge value will
952 * mean we never reach it, but at the same time work around
953 * the aforementioned issue. Thus use IL_GOOD_CRC_TH_NEVER
954 * here instead of IL_GOOD_CRC_TH_DISABLED.
955 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100956 scan->good_CRC_th =
957 is_active ? IL_GOOD_CRC_TH_DEFAULT : IL_GOOD_CRC_TH_NEVER;
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200958
959 band = il->scan_band;
960
961 if (il->cfg->scan_rx_antennas[band])
962 rx_ant = il->cfg->scan_rx_antennas[band];
963
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100964 il->scan_tx_ant[band] =
965 il4965_toggle_tx_ant(il, il->scan_tx_ant[band], scan_tx_antennas);
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200966 rate_flags |= il4965_ant_idx_to_flags(il->scan_tx_ant[band]);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100967 scan->tx_cmd.rate_n_flags =
968 il4965_hw_set_rate_n_flags(rate, rate_flags);
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200969
970 /* In power save mode use one chain, otherwise use all chains */
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +0100971 if (test_bit(S_POWER_PMI, &il->status)) {
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200972 /* rx_ant has been set to all valid chains previously */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100973 active_chains =
974 rx_ant & ((u8) (il->chain_noise_data.active_chains));
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200975 if (!active_chains)
976 active_chains = rx_ant;
977
978 D_SCAN("chain_noise_data.active_chains: %u\n",
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100979 il->chain_noise_data.active_chains);
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200980
981 rx_ant = il4965_first_antenna(active_chains);
982 }
983
984 /* MIMO is not used here, but value is required */
985 rx_chain |= il->hw_params.valid_rx_ant << RXON_RX_CHAIN_VALID_POS;
986 rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS;
987 rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS;
988 rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS;
989 scan->rx_chain = cpu_to_le16(rx_chain);
990
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100991 cmd_len =
992 il_fill_probe_req(il, (struct ieee80211_mgmt *)scan->data,
993 vif->addr, il->scan_request->ie,
994 il->scan_request->ie_len,
995 IL_MAX_SCAN_SIZE - sizeof(*scan));
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +0200996 scan->tx_cmd.len = cpu_to_le16(cmd_len);
997
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100998 scan->filter_flags |=
999 (RXON_FILTER_ACCEPT_GRP_MSK | RXON_FILTER_BCON_AWARE_MSK);
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +02001000
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001001 scan->channel_count =
1002 il4965_get_channels_for_scan(il, vif, band, is_active, n_probes,
1003 (void *)&scan->data[cmd_len]);
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +02001004 if (scan->channel_count == 0) {
1005 D_SCAN("channel count %d\n", scan->channel_count);
1006 return -EIO;
1007 }
1008
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001009 cmd.len +=
1010 le16_to_cpu(scan->tx_cmd.len) +
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +02001011 scan->channel_count * sizeof(struct il_scan_channel);
1012 cmd.data = scan;
1013 scan->len = cpu_to_le16(cmd.len);
1014
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01001015 set_bit(S_SCAN_HW, &il->status);
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +02001016
1017 ret = il_send_cmd_sync(il, &cmd);
1018 if (ret)
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01001019 clear_bit(S_SCAN_HW, &il->status);
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +02001020
1021 return ret;
1022}
1023
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001024int
1025il4965_manage_ibss_station(struct il_priv *il, struct ieee80211_vif *vif,
1026 bool add)
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +02001027{
1028 struct il_vif_priv *vif_priv = (void *)vif->drv_priv;
1029
1030 if (add)
1031 return il4965_add_bssid_station(il, vif_priv->ctx,
1032 vif->bss_conf.bssid,
1033 &vif_priv->ibss_bssid_sta_id);
1034 return il_remove_station(il, vif_priv->ibss_bssid_sta_id,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001035 vif->bss_conf.bssid);
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +02001036}
1037
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001038void
1039il4965_free_tfds_in_queue(struct il_priv *il, int sta_id, int tid, int freed)
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +02001040{
1041 lockdep_assert_held(&il->sta_lock);
1042
1043 if (il->stations[sta_id].tid[tid].tfds_in_queue >= freed)
1044 il->stations[sta_id].tid[tid].tfds_in_queue -= freed;
1045 else {
1046 D_TX("free more than tfds_in_queue (%u:%d)\n",
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001047 il->stations[sta_id].tid[tid].tfds_in_queue, freed);
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +02001048 il->stations[sta_id].tid[tid].tfds_in_queue = 0;
1049 }
1050}
1051
1052#define IL_TX_QUEUE_MSK 0xfffff
1053
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001054static bool
1055il4965_is_single_rx_stream(struct il_priv *il)
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +02001056{
1057 return il->current_ht_config.smps == IEEE80211_SMPS_STATIC ||
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001058 il->current_ht_config.single_chain_sufficient;
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +02001059}
1060
1061#define IL_NUM_RX_CHAINS_MULTIPLE 3
1062#define IL_NUM_RX_CHAINS_SINGLE 2
1063#define IL_NUM_IDLE_CHAINS_DUAL 2
1064#define IL_NUM_IDLE_CHAINS_SINGLE 1
1065
1066/*
1067 * Determine how many receiver/antenna chains to use.
1068 *
1069 * More provides better reception via diversity. Fewer saves power
1070 * at the expense of throughput, but only when not in powersave to
1071 * start with.
1072 *
1073 * MIMO (dual stream) requires at least 2, but works better with 3.
1074 * This does not determine *which* chains to use, just how many.
1075 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001076static int
1077il4965_get_active_rx_chain_count(struct il_priv *il)
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +02001078{
1079 /* # of Rx chains to use when expecting MIMO. */
1080 if (il4965_is_single_rx_stream(il))
1081 return IL_NUM_RX_CHAINS_SINGLE;
1082 else
1083 return IL_NUM_RX_CHAINS_MULTIPLE;
1084}
1085
1086/*
1087 * When we are in power saving mode, unless device support spatial
1088 * multiplexing power save, use the active count for rx chain count.
1089 */
1090static int
1091il4965_get_idle_rx_chain_count(struct il_priv *il, int active_cnt)
1092{
1093 /* # Rx chains when idling, depending on SMPS mode */
1094 switch (il->current_ht_config.smps) {
1095 case IEEE80211_SMPS_STATIC:
1096 case IEEE80211_SMPS_DYNAMIC:
1097 return IL_NUM_IDLE_CHAINS_SINGLE;
1098 case IEEE80211_SMPS_OFF:
1099 return active_cnt;
1100 default:
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001101 WARN(1, "invalid SMPS mode %d", il->current_ht_config.smps);
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +02001102 return active_cnt;
1103 }
1104}
1105
1106/* up to 4 chains */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001107static u8
1108il4965_count_chain_bitmap(u32 chain_bitmap)
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +02001109{
1110 u8 res;
1111 res = (chain_bitmap & BIT(0)) >> 0;
1112 res += (chain_bitmap & BIT(1)) >> 1;
1113 res += (chain_bitmap & BIT(2)) >> 2;
1114 res += (chain_bitmap & BIT(3)) >> 3;
1115 return res;
1116}
1117
1118/**
1119 * il4965_set_rxon_chain - Set up Rx chain usage in "staging" RXON image
1120 *
1121 * Selects how many and which Rx receivers/antennas/chains to use.
1122 * This should not be used for scan command ... it puts data in wrong place.
1123 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001124void
1125il4965_set_rxon_chain(struct il_priv *il, struct il_rxon_context *ctx)
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +02001126{
1127 bool is_single = il4965_is_single_rx_stream(il);
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01001128 bool is_cam = !test_bit(S_POWER_PMI, &il->status);
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +02001129 u8 idle_rx_cnt, active_rx_cnt, valid_rx_cnt;
1130 u32 active_chains;
1131 u16 rx_chain;
1132
1133 /* Tell uCode which antennas are actually connected.
1134 * Before first association, we assume all antennas are connected.
1135 * Just after first association, il4965_chain_noise_calibration()
1136 * checks which antennas actually *are* connected. */
1137 if (il->chain_noise_data.active_chains)
1138 active_chains = il->chain_noise_data.active_chains;
1139 else
1140 active_chains = il->hw_params.valid_rx_ant;
1141
1142 rx_chain = active_chains << RXON_RX_CHAIN_VALID_POS;
1143
1144 /* How many receivers should we use? */
1145 active_rx_cnt = il4965_get_active_rx_chain_count(il);
1146 idle_rx_cnt = il4965_get_idle_rx_chain_count(il, active_rx_cnt);
1147
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +02001148 /* correct rx chain count according hw settings
1149 * and chain noise calibration
1150 */
1151 valid_rx_cnt = il4965_count_chain_bitmap(active_chains);
1152 if (valid_rx_cnt < active_rx_cnt)
1153 active_rx_cnt = valid_rx_cnt;
1154
1155 if (valid_rx_cnt < idle_rx_cnt)
1156 idle_rx_cnt = valid_rx_cnt;
1157
1158 rx_chain |= active_rx_cnt << RXON_RX_CHAIN_MIMO_CNT_POS;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001159 rx_chain |= idle_rx_cnt << RXON_RX_CHAIN_CNT_POS;
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +02001160
1161 ctx->staging.rx_chain = cpu_to_le16(rx_chain);
1162
1163 if (!is_single && active_rx_cnt >= IL_NUM_RX_CHAINS_SINGLE && is_cam)
1164 ctx->staging.rx_chain |= RXON_RX_CHAIN_MIMO_FORCE_MSK;
1165 else
1166 ctx->staging.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK;
1167
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001168 D_ASSOC("rx_chain=0x%X active=%d idle=%d\n", ctx->staging.rx_chain,
1169 active_rx_cnt, idle_rx_cnt);
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +02001170
1171 WARN_ON(active_rx_cnt == 0 || idle_rx_cnt == 0 ||
1172 active_rx_cnt < idle_rx_cnt);
1173}
1174
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001175u8
1176il4965_toggle_tx_ant(struct il_priv *il, u8 ant, u8 valid)
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +02001177{
1178 int i;
1179 u8 ind = ant;
1180
1181 for (i = 0; i < RATE_ANT_NUM - 1; i++) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001182 ind = (ind + 1) < RATE_ANT_NUM ? ind + 1 : 0;
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +02001183 if (valid & BIT(ind))
1184 return ind;
1185 }
1186 return ant;
1187}
1188
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001189static const char *
1190il4965_get_fh_string(int cmd)
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +02001191{
1192 switch (cmd) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001193 IL_CMD(FH49_RSCSR_CHNL0_STTS_WPTR_REG);
1194 IL_CMD(FH49_RSCSR_CHNL0_RBDCB_BASE_REG);
1195 IL_CMD(FH49_RSCSR_CHNL0_WPTR);
1196 IL_CMD(FH49_MEM_RCSR_CHNL0_CONFIG_REG);
1197 IL_CMD(FH49_MEM_RSSR_SHARED_CTRL_REG);
1198 IL_CMD(FH49_MEM_RSSR_RX_STATUS_REG);
1199 IL_CMD(FH49_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV);
1200 IL_CMD(FH49_TSSR_TX_STATUS_REG);
1201 IL_CMD(FH49_TSSR_TX_ERROR_REG);
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +02001202 default:
1203 return "UNKNOWN";
1204 }
1205}
1206
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001207int
1208il4965_dump_fh(struct il_priv *il, char **buf, bool display)
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +02001209{
1210 int i;
1211#ifdef CONFIG_IWLEGACY_DEBUG
1212 int pos = 0;
1213 size_t bufsz = 0;
1214#endif
1215 static const u32 fh_tbl[] = {
Stanislaw Gruszka9a95b372011-08-31 14:20:23 +02001216 FH49_RSCSR_CHNL0_STTS_WPTR_REG,
1217 FH49_RSCSR_CHNL0_RBDCB_BASE_REG,
1218 FH49_RSCSR_CHNL0_WPTR,
1219 FH49_MEM_RCSR_CHNL0_CONFIG_REG,
1220 FH49_MEM_RSSR_SHARED_CTRL_REG,
1221 FH49_MEM_RSSR_RX_STATUS_REG,
1222 FH49_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV,
1223 FH49_TSSR_TX_STATUS_REG,
1224 FH49_TSSR_TX_ERROR_REG
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +02001225 };
1226#ifdef CONFIG_IWLEGACY_DEBUG
1227 if (display) {
1228 bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40;
1229 *buf = kmalloc(bufsz, GFP_KERNEL);
1230 if (!*buf)
1231 return -ENOMEM;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001232 pos +=
1233 scnprintf(*buf + pos, bufsz - pos, "FH register values:\n");
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +02001234 for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001235 pos +=
1236 scnprintf(*buf + pos, bufsz - pos,
1237 " %34s: 0X%08x\n",
Stanislaw Gruszka1722f8e2011-11-15 14:51:01 +01001238 il4965_get_fh_string(fh_tbl[i]),
1239 il_rd(il, fh_tbl[i]));
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +02001240 }
1241 return pos;
1242 }
1243#endif
1244 IL_ERR("FH register values:\n");
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001245 for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) {
1246 IL_ERR(" %34s: 0X%08x\n", il4965_get_fh_string(fh_tbl[i]),
1247 il_rd(il, fh_tbl[i]));
Stanislaw Gruszkafcb74582011-08-30 13:06:03 +02001248 }
1249 return 0;
1250}
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001251
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001252void
1253il4965_hdl_missed_beacon(struct il_priv *il, struct il_rx_buf *rxb)
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001254{
1255 struct il_rx_pkt *pkt = rxb_addr(rxb);
1256 struct il_missed_beacon_notif *missed_beacon;
1257
1258 missed_beacon = &pkt->u.missed_beacon;
1259 if (le32_to_cpu(missed_beacon->consecutive_missed_beacons) >
1260 il->missed_beacon_threshold) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001261 D_CALIB("missed bcn cnsq %d totl %d rcd %d expctd %d\n",
1262 le32_to_cpu(missed_beacon->consecutive_missed_beacons),
1263 le32_to_cpu(missed_beacon->total_missed_becons),
1264 le32_to_cpu(missed_beacon->num_recvd_beacons),
1265 le32_to_cpu(missed_beacon->num_expected_beacons));
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01001266 if (!test_bit(S_SCANNING, &il->status))
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001267 il4965_init_sensitivity(il);
1268 }
1269}
1270
1271/* Calculate noise level, based on measurements during network silence just
1272 * before arriving beacon. This measurement can be done only if we know
1273 * exactly when to expect beacons, therefore only when we're associated. */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001274static void
1275il4965_rx_calc_noise(struct il_priv *il)
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001276{
1277 struct stats_rx_non_phy *rx_info;
1278 int num_active_rx = 0;
1279 int total_silence = 0;
1280 int bcn_silence_a, bcn_silence_b, bcn_silence_c;
1281 int last_rx_noise;
1282
1283 rx_info = &(il->_4965.stats.rx.general);
1284 bcn_silence_a =
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001285 le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER;
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001286 bcn_silence_b =
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001287 le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER;
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001288 bcn_silence_c =
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001289 le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER;
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001290
1291 if (bcn_silence_a) {
1292 total_silence += bcn_silence_a;
1293 num_active_rx++;
1294 }
1295 if (bcn_silence_b) {
1296 total_silence += bcn_silence_b;
1297 num_active_rx++;
1298 }
1299 if (bcn_silence_c) {
1300 total_silence += bcn_silence_c;
1301 num_active_rx++;
1302 }
1303
1304 /* Average among active antennas */
1305 if (num_active_rx)
1306 last_rx_noise = (total_silence / num_active_rx) - 107;
1307 else
1308 last_rx_noise = IL_NOISE_MEAS_NOT_AVAILABLE;
1309
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001310 D_CALIB("inband silence a %u, b %u, c %u, dBm %d\n", bcn_silence_a,
1311 bcn_silence_b, bcn_silence_c, last_rx_noise);
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001312}
1313
1314#ifdef CONFIG_IWLEGACY_DEBUGFS
1315/*
1316 * based on the assumption of all stats counter are in DWORD
1317 * FIXME: This function is for debugging, do not deal with
1318 * the case of counters roll-over.
1319 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001320static void
1321il4965_accumulative_stats(struct il_priv *il, __le32 * stats)
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001322{
1323 int i, size;
1324 __le32 *prev_stats;
1325 u32 *accum_stats;
1326 u32 *delta, *max_delta;
1327 struct stats_general_common *general, *accum_general;
1328 struct stats_tx *tx, *accum_tx;
1329
Stanislaw Gruszka1722f8e2011-11-15 14:51:01 +01001330 prev_stats = (__le32 *) &il->_4965.stats;
1331 accum_stats = (u32 *) &il->_4965.accum_stats;
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001332 size = sizeof(struct il_notif_stats);
1333 general = &il->_4965.stats.general.common;
1334 accum_general = &il->_4965.accum_stats.general.common;
1335 tx = &il->_4965.stats.tx;
1336 accum_tx = &il->_4965.accum_stats.tx;
Stanislaw Gruszka1722f8e2011-11-15 14:51:01 +01001337 delta = (u32 *) &il->_4965.delta_stats;
1338 max_delta = (u32 *) &il->_4965.max_delta;
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001339
1340 for (i = sizeof(__le32); i < size;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001341 i +=
1342 sizeof(__le32), stats++, prev_stats++, delta++, max_delta++,
1343 accum_stats++) {
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001344 if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001345 *delta =
1346 (le32_to_cpu(*stats) - le32_to_cpu(*prev_stats));
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001347 *accum_stats += *delta;
1348 if (*delta > *max_delta)
1349 *max_delta = *delta;
1350 }
1351 }
1352
1353 /* reset accumulative stats for "no-counter" type stats */
1354 accum_general->temperature = general->temperature;
1355 accum_general->ttl_timestamp = general->ttl_timestamp;
1356}
1357#endif
1358
1359#define REG_RECALIB_PERIOD (60)
1360
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001361void
1362il4965_hdl_stats(struct il_priv *il, struct il_rx_buf *rxb)
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001363{
1364 int change;
1365 struct il_rx_pkt *pkt = rxb_addr(rxb);
1366
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001367 D_RX("Statistics notification received (%d vs %d).\n",
1368 (int)sizeof(struct il_notif_stats),
1369 le32_to_cpu(pkt->len_n_flags) & IL_RX_FRAME_SIZE_MSK);
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001370
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001371 change =
1372 ((il->_4965.stats.general.common.temperature !=
1373 pkt->u.stats.general.common.temperature) ||
1374 ((il->_4965.stats.flag & STATS_REPLY_FLG_HT40_MODE_MSK) !=
1375 (pkt->u.stats.flag & STATS_REPLY_FLG_HT40_MODE_MSK)));
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001376#ifdef CONFIG_IWLEGACY_DEBUGFS
Stanislaw Gruszka1722f8e2011-11-15 14:51:01 +01001377 il4965_accumulative_stats(il, (__le32 *) &pkt->u.stats);
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001378#endif
1379
1380 /* TODO: reading some of stats is unneeded */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001381 memcpy(&il->_4965.stats, &pkt->u.stats, sizeof(il->_4965.stats));
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001382
Stanislaw Gruszkadb7746f2011-11-15 13:11:50 +01001383 set_bit(S_STATS, &il->status);
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001384
1385 /* Reschedule the stats timer to occur in
1386 * REG_RECALIB_PERIOD seconds to ensure we get a
1387 * thermal update even if the uCode doesn't give
1388 * us one */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001389 mod_timer(&il->stats_periodic,
1390 jiffies + msecs_to_jiffies(REG_RECALIB_PERIOD * 1000));
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001391
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01001392 if (unlikely(!test_bit(S_SCANNING, &il->status)) &&
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +02001393 (pkt->hdr.cmd == N_STATS)) {
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001394 il4965_rx_calc_noise(il);
1395 queue_work(il->workqueue, &il->run_time_calib_work);
1396 }
1397 if (il->cfg->ops->lib->temp_ops.temperature && change)
1398 il->cfg->ops->lib->temp_ops.temperature(il);
1399}
1400
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001401void
1402il4965_hdl_c_stats(struct il_priv *il, struct il_rx_buf *rxb)
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001403{
1404 struct il_rx_pkt *pkt = rxb_addr(rxb);
1405
Stanislaw Gruszkadb7746f2011-11-15 13:11:50 +01001406 if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATS_CLEAR_MSK) {
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001407#ifdef CONFIG_IWLEGACY_DEBUGFS
1408 memset(&il->_4965.accum_stats, 0,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001409 sizeof(struct il_notif_stats));
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001410 memset(&il->_4965.delta_stats, 0,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001411 sizeof(struct il_notif_stats));
1412 memset(&il->_4965.max_delta, 0, sizeof(struct il_notif_stats));
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001413#endif
1414 D_RX("Statistics have been cleared\n");
1415 }
Stanislaw Gruszkad2dfb332011-11-15 13:16:38 +01001416 il4965_hdl_stats(il, rxb);
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001417}
1418
Stanislaw Gruszka8f29b452011-11-15 12:57:25 +01001419
1420/*
1421 * mac80211 queues, ACs, hardware queues, FIFOs.
1422 *
1423 * Cf. http://wireless.kernel.org/en/developers/Documentation/mac80211/queues
1424 *
1425 * Mac80211 uses the following numbers, which we get as from it
1426 * by way of skb_get_queue_mapping(skb):
1427 *
1428 * VO 0
1429 * VI 1
1430 * BE 2
1431 * BK 3
1432 *
1433 *
1434 * Regular (not A-MPDU) frames are put into hardware queues corresponding
1435 * to the FIFOs, see comments in iwl-prph.h. Aggregated frames get their
1436 * own queue per aggregation session (RA/TID combination), such queues are
1437 * set up to map into FIFOs too, for which we need an AC->FIFO mapping. In
1438 * order to map frames to the right queue, we also need an AC->hw queue
1439 * mapping. This is implemented here.
1440 *
1441 * Due to the way hw queues are set up (by the hw specific modules like
Stanislaw Gruszkaaf038f42011-08-30 13:58:27 +02001442 * 4965.c), the AC->hw queue mapping is the identity
Stanislaw Gruszka8f29b452011-11-15 12:57:25 +01001443 * mapping.
1444 */
1445
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001446static const u8 tid_to_ac[] = {
1447 IEEE80211_AC_BE,
1448 IEEE80211_AC_BK,
1449 IEEE80211_AC_BK,
1450 IEEE80211_AC_BE,
1451 IEEE80211_AC_VI,
1452 IEEE80211_AC_VI,
1453 IEEE80211_AC_VO,
1454 IEEE80211_AC_VO
1455};
1456
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001457static inline int
1458il4965_get_ac_from_tid(u16 tid)
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001459{
1460 if (likely(tid < ARRAY_SIZE(tid_to_ac)))
1461 return tid_to_ac[tid];
1462
1463 /* no support for TIDs 8-15 yet */
1464 return -EINVAL;
1465}
1466
1467static inline int
1468il4965_get_fifo_from_tid(struct il_rxon_context *ctx, u16 tid)
1469{
1470 if (likely(tid < ARRAY_SIZE(tid_to_ac)))
1471 return ctx->ac_to_fifo[tid_to_ac[tid]];
1472
1473 /* no support for TIDs 8-15 yet */
1474 return -EINVAL;
1475}
1476
1477/*
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +02001478 * handle build C_TX command notification.
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001479 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001480static void
1481il4965_tx_cmd_build_basic(struct il_priv *il, struct sk_buff *skb,
1482 struct il_tx_cmd *tx_cmd,
1483 struct ieee80211_tx_info *info,
1484 struct ieee80211_hdr *hdr, u8 std_id)
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001485{
1486 __le16 fc = hdr->frame_control;
1487 __le32 tx_flags = tx_cmd->tx_flags;
1488
1489 tx_cmd->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
1490 if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
1491 tx_flags |= TX_CMD_FLG_ACK_MSK;
1492 if (ieee80211_is_mgmt(fc))
1493 tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
1494 if (ieee80211_is_probe_resp(fc) &&
1495 !(le16_to_cpu(hdr->seq_ctrl) & 0xf))
1496 tx_flags |= TX_CMD_FLG_TSF_MSK;
1497 } else {
1498 tx_flags &= (~TX_CMD_FLG_ACK_MSK);
1499 tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
1500 }
1501
1502 if (ieee80211_is_back_req(fc))
1503 tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK;
1504
1505 tx_cmd->sta_id = std_id;
1506 if (ieee80211_has_morefrags(fc))
1507 tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK;
1508
1509 if (ieee80211_is_data_qos(fc)) {
1510 u8 *qc = ieee80211_get_qos_ctl(hdr);
1511 tx_cmd->tid_tspec = qc[0] & 0xf;
1512 tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK;
1513 } else {
1514 tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
1515 }
1516
1517 il_tx_cmd_protection(il, info, fc, &tx_flags);
1518
1519 tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK);
1520 if (ieee80211_is_mgmt(fc)) {
1521 if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc))
1522 tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(3);
1523 else
1524 tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(2);
1525 } else {
1526 tx_cmd->timeout.pm_frame_timeout = 0;
1527 }
1528
1529 tx_cmd->driver_txop = 0;
1530 tx_cmd->tx_flags = tx_flags;
1531 tx_cmd->next_frame_len = 0;
1532}
1533
1534#define RTS_DFAULT_RETRY_LIMIT 60
1535
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001536static void
1537il4965_tx_cmd_build_rate(struct il_priv *il, struct il_tx_cmd *tx_cmd,
1538 struct ieee80211_tx_info *info, __le16 fc)
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001539{
1540 u32 rate_flags;
1541 int rate_idx;
1542 u8 rts_retry_limit;
1543 u8 data_retry_limit;
1544 u8 rate_plcp;
1545
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001546 /* Set retry limit on DATA packets and Probe Responses */
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001547 if (ieee80211_is_probe_resp(fc))
1548 data_retry_limit = 3;
1549 else
1550 data_retry_limit = IL4965_DEFAULT_TX_RETRY;
1551 tx_cmd->data_retry_limit = data_retry_limit;
1552
1553 /* Set retry limit on RTS packets */
1554 rts_retry_limit = RTS_DFAULT_RETRY_LIMIT;
1555 if (data_retry_limit < rts_retry_limit)
1556 rts_retry_limit = data_retry_limit;
1557 tx_cmd->rts_retry_limit = rts_retry_limit;
1558
1559 /* DATA packets will use the uCode station table for rate/antenna
1560 * selection */
1561 if (ieee80211_is_data(fc)) {
1562 tx_cmd->initial_rate_idx = 0;
1563 tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK;
1564 return;
1565 }
1566
1567 /**
1568 * If the current TX rate stored in mac80211 has the MCS bit set, it's
1569 * not really a TX rate. Thus, we use the lowest supported rate for
1570 * this band. Also use the lowest supported rate if the stored rate
1571 * idx is invalid.
1572 */
1573 rate_idx = info->control.rates[0].idx;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001574 if ((info->control.rates[0].flags & IEEE80211_TX_RC_MCS) || rate_idx < 0
1575 || rate_idx > RATE_COUNT_LEGACY)
1576 rate_idx =
1577 rate_lowest_index(&il->bands[info->band],
1578 info->control.sta);
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001579 /* For 5 GHZ band, remap mac80211 rate indices into driver indices */
1580 if (info->band == IEEE80211_BAND_5GHZ)
1581 rate_idx += IL_FIRST_OFDM_RATE;
1582 /* Get PLCP rate for tx_cmd->rate_n_flags */
1583 rate_plcp = il_rates[rate_idx].plcp;
1584 /* Zero out flags for this packet */
1585 rate_flags = 0;
1586
1587 /* Set CCK flag as needed */
1588 if (rate_idx >= IL_FIRST_CCK_RATE && rate_idx <= IL_LAST_CCK_RATE)
1589 rate_flags |= RATE_MCS_CCK_MSK;
1590
1591 /* Set up antennas */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001592 il->mgmt_tx_ant =
1593 il4965_toggle_tx_ant(il, il->mgmt_tx_ant,
1594 il->hw_params.valid_tx_ant);
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001595
1596 rate_flags |= il4965_ant_idx_to_flags(il->mgmt_tx_ant);
1597
1598 /* Set the rate in the TX cmd */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001599 tx_cmd->rate_n_flags =
1600 il4965_hw_set_rate_n_flags(rate_plcp, rate_flags);
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001601}
1602
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001603static void
1604il4965_tx_cmd_build_hwcrypto(struct il_priv *il, struct ieee80211_tx_info *info,
1605 struct il_tx_cmd *tx_cmd, struct sk_buff *skb_frag,
1606 int sta_id)
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001607{
1608 struct ieee80211_key_conf *keyconf = info->control.hw_key;
1609
1610 switch (keyconf->cipher) {
1611 case WLAN_CIPHER_SUITE_CCMP:
1612 tx_cmd->sec_ctl = TX_CMD_SEC_CCM;
1613 memcpy(tx_cmd->key, keyconf->key, keyconf->keylen);
1614 if (info->flags & IEEE80211_TX_CTL_AMPDU)
1615 tx_cmd->tx_flags |= TX_CMD_FLG_AGG_CCMP_MSK;
1616 D_TX("tx_cmd with AES hwcrypto\n");
1617 break;
1618
1619 case WLAN_CIPHER_SUITE_TKIP:
1620 tx_cmd->sec_ctl = TX_CMD_SEC_TKIP;
1621 ieee80211_get_tkip_p2k(keyconf, skb_frag, tx_cmd->key);
1622 D_TX("tx_cmd with tkip hwcrypto\n");
1623 break;
1624
1625 case WLAN_CIPHER_SUITE_WEP104:
1626 tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128;
1627 /* fall through */
1628 case WLAN_CIPHER_SUITE_WEP40:
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001629 tx_cmd->sec_ctl |=
1630 (TX_CMD_SEC_WEP | (keyconf->keyidx & TX_CMD_SEC_MSK) <<
1631 TX_CMD_SEC_SHIFT);
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001632
1633 memcpy(&tx_cmd->key[3], keyconf->key, keyconf->keylen);
1634
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001635 D_TX("Configuring packet for WEP encryption " "with key %d\n",
1636 keyconf->keyidx);
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001637 break;
1638
1639 default:
1640 IL_ERR("Unknown encode cipher %x\n", keyconf->cipher);
1641 break;
1642 }
1643}
1644
1645/*
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +02001646 * start C_TX command process
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001647 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001648int
1649il4965_tx_skb(struct il_priv *il, struct sk_buff *skb)
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001650{
1651 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
1652 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
1653 struct ieee80211_sta *sta = info->control.sta;
1654 struct il_station_priv *sta_priv = NULL;
1655 struct il_tx_queue *txq;
1656 struct il_queue *q;
1657 struct il_device_cmd *out_cmd;
1658 struct il_cmd_meta *out_meta;
1659 struct il_tx_cmd *tx_cmd;
1660 struct il_rxon_context *ctx = &il->ctx;
1661 int txq_id;
1662 dma_addr_t phys_addr;
1663 dma_addr_t txcmd_phys;
1664 dma_addr_t scratch_phys;
1665 u16 len, firstlen, secondlen;
1666 u16 seq_number = 0;
1667 __le16 fc;
1668 u8 hdr_len;
1669 u8 sta_id;
1670 u8 wait_write_ptr = 0;
1671 u8 tid = 0;
1672 u8 *qc = NULL;
1673 unsigned long flags;
1674 bool is_agg = false;
1675
1676 if (info->control.vif)
1677 ctx = il_rxon_ctx_from_vif(info->control.vif);
1678
1679 spin_lock_irqsave(&il->lock, flags);
1680 if (il_is_rfkill(il)) {
1681 D_DROP("Dropping - RF KILL\n");
1682 goto drop_unlock;
1683 }
1684
1685 fc = hdr->frame_control;
1686
1687#ifdef CONFIG_IWLEGACY_DEBUG
1688 if (ieee80211_is_auth(fc))
1689 D_TX("Sending AUTH frame\n");
1690 else if (ieee80211_is_assoc_req(fc))
1691 D_TX("Sending ASSOC frame\n");
1692 else if (ieee80211_is_reassoc_req(fc))
1693 D_TX("Sending REASSOC frame\n");
1694#endif
1695
1696 hdr_len = ieee80211_hdrlen(fc);
1697
1698 /* For management frames use broadcast id to do not break aggregation */
1699 if (!ieee80211_is_data(fc))
1700 sta_id = ctx->bcast_sta_id;
1701 else {
1702 /* Find idx into station table for destination station */
1703 sta_id = il_sta_id_or_broadcast(il, ctx, info->control.sta);
1704
1705 if (sta_id == IL_INVALID_STATION) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001706 D_DROP("Dropping - INVALID STATION: %pM\n", hdr->addr1);
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001707 goto drop_unlock;
1708 }
1709 }
1710
1711 D_TX("station Id %d\n", sta_id);
1712
1713 if (sta)
1714 sta_priv = (void *)sta->drv_priv;
1715
1716 if (sta_priv && sta_priv->asleep &&
1717 (info->flags & IEEE80211_TX_CTL_POLL_RESPONSE)) {
1718 /*
1719 * This sends an asynchronous command to the device,
1720 * but we can rely on it being processed before the
1721 * next frame is processed -- and the next frame to
1722 * this station is the one that will consume this
1723 * counter.
1724 * For now set the counter to just 1 since we do not
1725 * support uAPSD yet.
1726 */
1727 il4965_sta_modify_sleep_tx_count(il, sta_id, 1);
1728 }
1729
1730 /*
1731 * Send this frame after DTIM -- there's a special queue
1732 * reserved for this for contexts that support AP mode.
1733 */
1734 if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) {
1735 txq_id = ctx->mcast_queue;
1736 /*
1737 * The microcode will clear the more data
1738 * bit in the last frame it transmits.
1739 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001740 hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001741 } else
1742 txq_id = ctx->ac_to_queue[skb_get_queue_mapping(skb)];
1743
1744 /* irqs already disabled/saved above when locking il->lock */
1745 spin_lock(&il->sta_lock);
1746
1747 if (ieee80211_is_data_qos(fc)) {
1748 qc = ieee80211_get_qos_ctl(hdr);
1749 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
1750 if (WARN_ON_ONCE(tid >= MAX_TID_COUNT)) {
1751 spin_unlock(&il->sta_lock);
1752 goto drop_unlock;
1753 }
1754 seq_number = il->stations[sta_id].tid[tid].seq_number;
1755 seq_number &= IEEE80211_SCTL_SEQ;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001756 hdr->seq_ctrl =
1757 hdr->seq_ctrl & cpu_to_le16(IEEE80211_SCTL_FRAG);
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001758 hdr->seq_ctrl |= cpu_to_le16(seq_number);
1759 seq_number += 0x10;
1760 /* aggregation is on for this <sta,tid> */
1761 if (info->flags & IEEE80211_TX_CTL_AMPDU &&
1762 il->stations[sta_id].tid[tid].agg.state == IL_AGG_ON) {
1763 txq_id = il->stations[sta_id].tid[tid].agg.txq_id;
1764 is_agg = true;
1765 }
1766 }
1767
1768 txq = &il->txq[txq_id];
1769 q = &txq->q;
1770
1771 if (unlikely(il_queue_space(q) < q->high_mark)) {
1772 spin_unlock(&il->sta_lock);
1773 goto drop_unlock;
1774 }
1775
1776 if (ieee80211_is_data_qos(fc)) {
1777 il->stations[sta_id].tid[tid].tfds_in_queue++;
1778 if (!ieee80211_has_morefrags(fc))
1779 il->stations[sta_id].tid[tid].seq_number = seq_number;
1780 }
1781
1782 spin_unlock(&il->sta_lock);
1783
1784 /* Set up driver data for this TFD */
1785 memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct il_tx_info));
1786 txq->txb[q->write_ptr].skb = skb;
1787 txq->txb[q->write_ptr].ctx = ctx;
1788
1789 /* Set up first empty entry in queue's array of Tx/cmd buffers */
1790 out_cmd = txq->cmd[q->write_ptr];
1791 out_meta = &txq->meta[q->write_ptr];
1792 tx_cmd = &out_cmd->cmd.tx;
1793 memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr));
1794 memset(tx_cmd, 0, sizeof(struct il_tx_cmd));
1795
1796 /*
1797 * Set up the Tx-command (not MAC!) header.
1798 * Store the chosen Tx queue and TFD idx within the sequence field;
1799 * after Tx, uCode's Tx response will return this value so driver can
1800 * locate the frame within the tx queue and do post-tx processing.
1801 */
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +02001802 out_cmd->hdr.cmd = C_TX;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001803 out_cmd->hdr.sequence =
1804 cpu_to_le16((u16)
1805 (QUEUE_TO_SEQ(txq_id) | IDX_TO_SEQ(q->write_ptr)));
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001806
1807 /* Copy MAC header from skb into command buffer */
1808 memcpy(tx_cmd->hdr, hdr, hdr_len);
1809
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001810 /* Total # bytes to be transmitted */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001811 len = (u16) skb->len;
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001812 tx_cmd->len = cpu_to_le16(len);
1813
1814 if (info->control.hw_key)
1815 il4965_tx_cmd_build_hwcrypto(il, info, tx_cmd, skb, sta_id);
1816
1817 /* TODO need this for burst mode later on */
1818 il4965_tx_cmd_build_basic(il, skb, tx_cmd, info, hdr, sta_id);
1819 il_dbg_log_tx_data_frame(il, len, hdr);
1820
1821 il4965_tx_cmd_build_rate(il, tx_cmd, info, fc);
1822
1823 il_update_stats(il, true, fc, len);
1824 /*
1825 * Use the first empty entry in this queue's command buffer array
1826 * to contain the Tx command and MAC header concatenated together
1827 * (payload data will be in another buffer).
1828 * Size of this varies, due to varying MAC header length.
1829 * If end is not dword aligned, we'll have 2 extra bytes at the end
1830 * of the MAC header (device reads on dword boundaries).
1831 * We'll tell device about this padding later.
1832 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001833 len = sizeof(struct il_tx_cmd) + sizeof(struct il_cmd_header) + hdr_len;
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001834 firstlen = (len + 3) & ~3;
1835
1836 /* Tell NIC about any 2-byte padding after MAC header */
1837 if (firstlen != len)
1838 tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK;
1839
1840 /* Physical address of this Tx command's header (not MAC header!),
1841 * within command buffer array. */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001842 txcmd_phys =
1843 pci_map_single(il->pci_dev, &out_cmd->hdr, firstlen,
1844 PCI_DMA_BIDIRECTIONAL);
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001845 dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
1846 dma_unmap_len_set(out_meta, len, firstlen);
1847 /* Add buffer containing Tx command and MAC(!) header to TFD's
1848 * first entry */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001849 il->cfg->ops->lib->txq_attach_buf_to_tfd(il, txq, txcmd_phys, firstlen,
1850 1, 0);
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001851
1852 if (!ieee80211_has_morefrags(hdr->frame_control)) {
1853 txq->need_update = 1;
1854 } else {
1855 wait_write_ptr = 1;
1856 txq->need_update = 0;
1857 }
1858
1859 /* Set up TFD's 2nd entry to point directly to remainder of skb,
1860 * if any (802.11 null frames have no payload). */
1861 secondlen = skb->len - hdr_len;
1862 if (secondlen > 0) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001863 phys_addr =
1864 pci_map_single(il->pci_dev, skb->data + hdr_len, secondlen,
1865 PCI_DMA_TODEVICE);
1866 il->cfg->ops->lib->txq_attach_buf_to_tfd(il, txq, phys_addr,
1867 secondlen, 0, 0);
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001868 }
1869
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001870 scratch_phys =
1871 txcmd_phys + sizeof(struct il_cmd_header) +
1872 offsetof(struct il_tx_cmd, scratch);
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001873
1874 /* take back ownership of DMA buffer to enable update */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001875 pci_dma_sync_single_for_cpu(il->pci_dev, txcmd_phys, firstlen,
1876 PCI_DMA_BIDIRECTIONAL);
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001877 tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys);
1878 tx_cmd->dram_msb_ptr = il_get_dma_hi_addr(scratch_phys);
1879
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001880 D_TX("sequence nr = 0X%x\n", le16_to_cpu(out_cmd->hdr.sequence));
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001881 D_TX("tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags));
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001882 il_print_hex_dump(il, IL_DL_TX, (u8 *) tx_cmd, sizeof(*tx_cmd));
1883 il_print_hex_dump(il, IL_DL_TX, (u8 *) tx_cmd->hdr, hdr_len);
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001884
1885 /* Set up entry for this TFD in Tx byte-count array */
1886 if (info->flags & IEEE80211_TX_CTL_AMPDU)
1887 il->cfg->ops->lib->txq_update_byte_cnt_tbl(il, txq,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001888 le16_to_cpu(tx_cmd->
1889 len));
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001890
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001891 pci_dma_sync_single_for_device(il->pci_dev, txcmd_phys, firstlen,
1892 PCI_DMA_BIDIRECTIONAL);
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001893
1894 /* Tell device the write idx *just past* this latest filled TFD */
1895 q->write_ptr = il_queue_inc_wrap(q->write_ptr, q->n_bd);
1896 il_txq_update_write_ptr(il, txq);
1897 spin_unlock_irqrestore(&il->lock, flags);
1898
1899 /*
1900 * At this point the frame is "transmitted" successfully
1901 * and we will get a TX status notification eventually,
1902 * regardless of the value of ret. "ret" only indicates
1903 * whether or not we should update the write pointer.
1904 */
1905
1906 /*
1907 * Avoid atomic ops if it isn't an associated client.
1908 * Also, if this is a packet for aggregation, don't
1909 * increase the counter because the ucode will stop
1910 * aggregation queues when their respective station
1911 * goes to sleep.
1912 */
1913 if (sta_priv && sta_priv->client && !is_agg)
1914 atomic_inc(&sta_priv->pending_frames);
1915
1916 if (il_queue_space(q) < q->high_mark && il->mac80211_registered) {
1917 if (wait_write_ptr) {
1918 spin_lock_irqsave(&il->lock, flags);
1919 txq->need_update = 1;
1920 il_txq_update_write_ptr(il, txq);
1921 spin_unlock_irqrestore(&il->lock, flags);
1922 } else {
1923 il_stop_queue(il, txq);
1924 }
1925 }
1926
1927 return 0;
1928
1929drop_unlock:
1930 spin_unlock_irqrestore(&il->lock, flags);
1931 return -1;
1932}
1933
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001934static inline int
1935il4965_alloc_dma_ptr(struct il_priv *il, struct il_dma_ptr *ptr, size_t size)
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001936{
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001937 ptr->addr =
1938 dma_alloc_coherent(&il->pci_dev->dev, size, &ptr->dma, GFP_KERNEL);
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001939 if (!ptr->addr)
1940 return -ENOMEM;
1941 ptr->size = size;
1942 return 0;
1943}
1944
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001945static inline void
1946il4965_free_dma_ptr(struct il_priv *il, struct il_dma_ptr *ptr)
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001947{
1948 if (unlikely(!ptr->addr))
1949 return;
1950
1951 dma_free_coherent(&il->pci_dev->dev, ptr->size, ptr->addr, ptr->dma);
1952 memset(ptr, 0, sizeof(*ptr));
1953}
1954
1955/**
1956 * il4965_hw_txq_ctx_free - Free TXQ Context
1957 *
1958 * Destroy all TX DMA queues and structures
1959 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001960void
1961il4965_hw_txq_ctx_free(struct il_priv *il)
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001962{
1963 int txq_id;
1964
1965 /* Tx queues */
1966 if (il->txq) {
1967 for (txq_id = 0; txq_id < il->hw_params.max_txq_num; txq_id++)
1968 if (txq_id == il->cmd_queue)
1969 il_cmd_queue_free(il);
1970 else
1971 il_tx_queue_free(il, txq_id);
1972 }
1973 il4965_free_dma_ptr(il, &il->kw);
1974
1975 il4965_free_dma_ptr(il, &il->scd_bc_tbls);
1976
1977 /* free tx queue structure */
1978 il_txq_mem(il);
1979}
1980
1981/**
1982 * il4965_txq_ctx_alloc - allocate TX queue context
1983 * Allocate all Tx DMA structures and initialize them
1984 *
1985 * @param il
1986 * @return error code
1987 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001988int
1989il4965_txq_ctx_alloc(struct il_priv *il)
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01001990{
1991 int ret;
1992 int txq_id, slots_num;
1993 unsigned long flags;
1994
1995 /* Free all tx/cmd queues and keep-warm buffer */
1996 il4965_hw_txq_ctx_free(il);
1997
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001998 ret =
1999 il4965_alloc_dma_ptr(il, &il->scd_bc_tbls,
2000 il->hw_params.scd_bc_tbls_size);
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002001 if (ret) {
2002 IL_ERR("Scheduler BC Table allocation failed\n");
2003 goto error_bc_tbls;
2004 }
2005 /* Alloc keep-warm buffer */
2006 ret = il4965_alloc_dma_ptr(il, &il->kw, IL_KW_SIZE);
2007 if (ret) {
2008 IL_ERR("Keep Warm allocation failed\n");
2009 goto error_kw;
2010 }
2011
2012 /* allocate tx queue structure */
2013 ret = il_alloc_txq_mem(il);
2014 if (ret)
2015 goto error;
2016
2017 spin_lock_irqsave(&il->lock, flags);
2018
2019 /* Turn off all Tx DMA fifos */
2020 il4965_txq_set_sched(il, 0);
2021
2022 /* Tell NIC where to find the "keep warm" buffer */
Stanislaw Gruszka9a95b372011-08-31 14:20:23 +02002023 il_wr(il, FH49_KW_MEM_ADDR_REG, il->kw.dma >> 4);
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002024
2025 spin_unlock_irqrestore(&il->lock, flags);
2026
2027 /* Alloc and init all Tx queues, including the command queue (#4/#9) */
2028 for (txq_id = 0; txq_id < il->hw_params.max_txq_num; txq_id++) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002029 slots_num =
2030 (txq_id ==
2031 il->cmd_queue) ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
2032 ret = il_tx_queue_init(il, &il->txq[txq_id], slots_num, txq_id);
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002033 if (ret) {
2034 IL_ERR("Tx %d queue init failed\n", txq_id);
2035 goto error;
2036 }
2037 }
2038
2039 return ret;
2040
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002041error:
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002042 il4965_hw_txq_ctx_free(il);
2043 il4965_free_dma_ptr(il, &il->kw);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002044error_kw:
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002045 il4965_free_dma_ptr(il, &il->scd_bc_tbls);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002046error_bc_tbls:
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002047 return ret;
2048}
2049
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002050void
2051il4965_txq_ctx_reset(struct il_priv *il)
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002052{
2053 int txq_id, slots_num;
2054 unsigned long flags;
2055
2056 spin_lock_irqsave(&il->lock, flags);
2057
2058 /* Turn off all Tx DMA fifos */
2059 il4965_txq_set_sched(il, 0);
2060
2061 /* Tell NIC where to find the "keep warm" buffer */
Stanislaw Gruszka9a95b372011-08-31 14:20:23 +02002062 il_wr(il, FH49_KW_MEM_ADDR_REG, il->kw.dma >> 4);
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002063
2064 spin_unlock_irqrestore(&il->lock, flags);
2065
2066 /* Alloc and init all Tx queues, including the command queue (#4) */
2067 for (txq_id = 0; txq_id < il->hw_params.max_txq_num; txq_id++) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002068 slots_num =
2069 txq_id == il->cmd_queue ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
2070 il_tx_queue_reset(il, &il->txq[txq_id], slots_num, txq_id);
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002071 }
2072}
2073
2074/**
2075 * il4965_txq_ctx_stop - Stop all Tx DMA channels
2076 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002077void
2078il4965_txq_ctx_stop(struct il_priv *il)
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002079{
2080 int ch, txq_id;
2081 unsigned long flags;
2082
2083 /* Turn off all Tx DMA fifos */
2084 spin_lock_irqsave(&il->lock, flags);
2085
2086 il4965_txq_set_sched(il, 0);
2087
2088 /* Stop each Tx DMA channel, and wait for it to be idle */
2089 for (ch = 0; ch < il->hw_params.dma_chnl_num; ch++) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002090 il_wr(il, FH49_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0);
2091 if (il_poll_bit
2092 (il, FH49_TSSR_TX_STATUS_REG,
2093 FH49_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), 1000))
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002094 IL_ERR("Failing on timeout while stopping"
Stanislaw Gruszka1722f8e2011-11-15 14:51:01 +01002095 " DMA channel %d [0x%08x]", ch,
2096 il_rd(il, FH49_TSSR_TX_STATUS_REG));
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002097 }
2098 spin_unlock_irqrestore(&il->lock, flags);
2099
2100 if (!il->txq)
2101 return;
2102
2103 /* Unmap DMA from host system and free skb's */
2104 for (txq_id = 0; txq_id < il->hw_params.max_txq_num; txq_id++)
2105 if (txq_id == il->cmd_queue)
2106 il_cmd_queue_unmap(il);
2107 else
2108 il_tx_queue_unmap(il, txq_id);
2109}
2110
2111/*
2112 * Find first available (lowest unused) Tx Queue, mark it "active".
2113 * Called only when finding queue for aggregation.
2114 * Should never return anything < 7, because they should already
2115 * be in use as EDCA AC (0-3), Command (4), reserved (5, 6)
2116 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002117static int
2118il4965_txq_ctx_activate_free(struct il_priv *il)
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002119{
2120 int txq_id;
2121
2122 for (txq_id = 0; txq_id < il->hw_params.max_txq_num; txq_id++)
2123 if (!test_and_set_bit(txq_id, &il->txq_ctx_active_msk))
2124 return txq_id;
2125 return -1;
2126}
2127
2128/**
2129 * il4965_tx_queue_stop_scheduler - Stop queue, but keep configuration
2130 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002131static void
2132il4965_tx_queue_stop_scheduler(struct il_priv *il, u16 txq_id)
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002133{
2134 /* Simply stop the queue, but don't change any configuration;
2135 * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002136 il_wr_prph(il, IL49_SCD_QUEUE_STATUS_BITS(txq_id),
Stanislaw Gruszka1722f8e2011-11-15 14:51:01 +01002137 (0 << IL49_SCD_QUEUE_STTS_REG_POS_ACTIVE) |
2138 (1 << IL49_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN));
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002139}
2140
2141/**
2142 * il4965_tx_queue_set_q2ratid - Map unique receiver/tid combination to a queue
2143 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002144static int
2145il4965_tx_queue_set_q2ratid(struct il_priv *il, u16 ra_tid, u16 txq_id)
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002146{
2147 u32 tbl_dw_addr;
2148 u32 tbl_dw;
2149 u16 scd_q2ratid;
2150
2151 scd_q2ratid = ra_tid & IL_SCD_QUEUE_RA_TID_MAP_RATID_MSK;
2152
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002153 tbl_dw_addr =
2154 il->scd_base_addr + IL49_SCD_TRANSLATE_TBL_OFFSET_QUEUE(txq_id);
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002155
2156 tbl_dw = il_read_targ_mem(il, tbl_dw_addr);
2157
2158 if (txq_id & 0x1)
2159 tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF);
2160 else
2161 tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000);
2162
2163 il_write_targ_mem(il, tbl_dw_addr, tbl_dw);
2164
2165 return 0;
2166}
2167
2168/**
2169 * il4965_tx_queue_agg_enable - Set up & enable aggregation for selected queue
2170 *
2171 * NOTE: txq_id must be greater than IL49_FIRST_AMPDU_QUEUE,
2172 * i.e. it must be one of the higher queues used for aggregation
2173 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002174static int
2175il4965_txq_agg_enable(struct il_priv *il, int txq_id, int tx_fifo, int sta_id,
2176 int tid, u16 ssn_idx)
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002177{
2178 unsigned long flags;
2179 u16 ra_tid;
2180 int ret;
2181
2182 if ((IL49_FIRST_AMPDU_QUEUE > txq_id) ||
2183 (IL49_FIRST_AMPDU_QUEUE +
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002184 il->cfg->base_params->num_of_ampdu_queues <= txq_id)) {
2185 IL_WARN("queue number out of range: %d, must be %d to %d\n",
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002186 txq_id, IL49_FIRST_AMPDU_QUEUE,
2187 IL49_FIRST_AMPDU_QUEUE +
2188 il->cfg->base_params->num_of_ampdu_queues - 1);
2189 return -EINVAL;
2190 }
2191
2192 ra_tid = BUILD_RAxTID(sta_id, tid);
2193
2194 /* Modify device's station table to Tx this TID */
2195 ret = il4965_sta_tx_modify_enable_tid(il, sta_id, tid);
2196 if (ret)
2197 return ret;
2198
2199 spin_lock_irqsave(&il->lock, flags);
2200
2201 /* Stop this Tx queue before configuring it */
2202 il4965_tx_queue_stop_scheduler(il, txq_id);
2203
2204 /* Map receiver-address / traffic-ID to this queue */
2205 il4965_tx_queue_set_q2ratid(il, ra_tid, txq_id);
2206
2207 /* Set this queue as a chain-building queue */
2208 il_set_bits_prph(il, IL49_SCD_QUEUECHAIN_SEL, (1 << txq_id));
2209
2210 /* Place first TFD at idx corresponding to start sequence number.
2211 * Assumes that ssn_idx is valid (!= 0xFFF) */
2212 il->txq[txq_id].q.read_ptr = (ssn_idx & 0xff);
2213 il->txq[txq_id].q.write_ptr = (ssn_idx & 0xff);
2214 il4965_set_wr_ptrs(il, txq_id, ssn_idx);
2215
2216 /* Set up Tx win size and frame limit for this queue */
2217 il_write_targ_mem(il,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002218 il->scd_base_addr +
2219 IL49_SCD_CONTEXT_QUEUE_OFFSET(txq_id),
2220 (SCD_WIN_SIZE << IL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_POS)
2221 & IL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK);
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002222
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002223 il_write_targ_mem(il,
2224 il->scd_base_addr +
2225 IL49_SCD_CONTEXT_QUEUE_OFFSET(txq_id) + sizeof(u32),
2226 (SCD_FRAME_LIMIT <<
2227 IL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
2228 IL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK);
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002229
2230 il_set_bits_prph(il, IL49_SCD_INTERRUPT_MASK, (1 << txq_id));
2231
2232 /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */
2233 il4965_tx_queue_set_status(il, &il->txq[txq_id], tx_fifo, 1);
2234
2235 spin_unlock_irqrestore(&il->lock, flags);
2236
2237 return 0;
2238}
2239
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002240int
2241il4965_tx_agg_start(struct il_priv *il, struct ieee80211_vif *vif,
2242 struct ieee80211_sta *sta, u16 tid, u16 * ssn)
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002243{
2244 int sta_id;
2245 int tx_fifo;
2246 int txq_id;
2247 int ret;
2248 unsigned long flags;
2249 struct il_tid_data *tid_data;
2250
2251 tx_fifo = il4965_get_fifo_from_tid(il_rxon_ctx_from_vif(vif), tid);
2252 if (unlikely(tx_fifo < 0))
2253 return tx_fifo;
2254
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002255 IL_WARN("%s on ra = %pM tid = %d\n", __func__, sta->addr, tid);
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002256
2257 sta_id = il_sta_id(sta);
2258 if (sta_id == IL_INVALID_STATION) {
2259 IL_ERR("Start AGG on invalid station\n");
2260 return -ENXIO;
2261 }
2262 if (unlikely(tid >= MAX_TID_COUNT))
2263 return -EINVAL;
2264
2265 if (il->stations[sta_id].tid[tid].agg.state != IL_AGG_OFF) {
2266 IL_ERR("Start AGG when state is not IL_AGG_OFF !\n");
2267 return -ENXIO;
2268 }
2269
2270 txq_id = il4965_txq_ctx_activate_free(il);
2271 if (txq_id == -1) {
2272 IL_ERR("No free aggregation queue available\n");
2273 return -ENXIO;
2274 }
2275
2276 spin_lock_irqsave(&il->sta_lock, flags);
2277 tid_data = &il->stations[sta_id].tid[tid];
2278 *ssn = SEQ_TO_SN(tid_data->seq_number);
2279 tid_data->agg.txq_id = txq_id;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002280 il_set_swq_id(&il->txq[txq_id], il4965_get_ac_from_tid(tid), txq_id);
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002281 spin_unlock_irqrestore(&il->sta_lock, flags);
2282
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002283 ret = il4965_txq_agg_enable(il, txq_id, tx_fifo, sta_id, tid, *ssn);
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002284 if (ret)
2285 return ret;
2286
2287 spin_lock_irqsave(&il->sta_lock, flags);
2288 tid_data = &il->stations[sta_id].tid[tid];
2289 if (tid_data->tfds_in_queue == 0) {
2290 D_HT("HW queue is empty\n");
2291 tid_data->agg.state = IL_AGG_ON;
2292 ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
2293 } else {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002294 D_HT("HW queue is NOT empty: %d packets in HW queue\n",
2295 tid_data->tfds_in_queue);
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002296 tid_data->agg.state = IL_EMPTYING_HW_QUEUE_ADDBA;
2297 }
2298 spin_unlock_irqrestore(&il->sta_lock, flags);
2299 return ret;
2300}
2301
2302/**
2303 * txq_id must be greater than IL49_FIRST_AMPDU_QUEUE
2304 * il->lock must be held by the caller
2305 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002306static int
2307il4965_txq_agg_disable(struct il_priv *il, u16 txq_id, u16 ssn_idx, u8 tx_fifo)
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002308{
2309 if ((IL49_FIRST_AMPDU_QUEUE > txq_id) ||
2310 (IL49_FIRST_AMPDU_QUEUE +
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002311 il->cfg->base_params->num_of_ampdu_queues <= txq_id)) {
2312 IL_WARN("queue number out of range: %d, must be %d to %d\n",
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002313 txq_id, IL49_FIRST_AMPDU_QUEUE,
2314 IL49_FIRST_AMPDU_QUEUE +
2315 il->cfg->base_params->num_of_ampdu_queues - 1);
2316 return -EINVAL;
2317 }
2318
2319 il4965_tx_queue_stop_scheduler(il, txq_id);
2320
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002321 il_clear_bits_prph(il, IL49_SCD_QUEUECHAIN_SEL, (1 << txq_id));
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002322
2323 il->txq[txq_id].q.read_ptr = (ssn_idx & 0xff);
2324 il->txq[txq_id].q.write_ptr = (ssn_idx & 0xff);
2325 /* supposes that ssn_idx is valid (!= 0xFFF) */
2326 il4965_set_wr_ptrs(il, txq_id, ssn_idx);
2327
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002328 il_clear_bits_prph(il, IL49_SCD_INTERRUPT_MASK, (1 << txq_id));
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002329 il_txq_ctx_deactivate(il, txq_id);
2330 il4965_tx_queue_set_status(il, &il->txq[txq_id], tx_fifo, 0);
2331
2332 return 0;
2333}
2334
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002335int
2336il4965_tx_agg_stop(struct il_priv *il, struct ieee80211_vif *vif,
2337 struct ieee80211_sta *sta, u16 tid)
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002338{
2339 int tx_fifo_id, txq_id, sta_id, ssn;
2340 struct il_tid_data *tid_data;
2341 int write_ptr, read_ptr;
2342 unsigned long flags;
2343
2344 tx_fifo_id = il4965_get_fifo_from_tid(il_rxon_ctx_from_vif(vif), tid);
2345 if (unlikely(tx_fifo_id < 0))
2346 return tx_fifo_id;
2347
2348 sta_id = il_sta_id(sta);
2349
2350 if (sta_id == IL_INVALID_STATION) {
2351 IL_ERR("Invalid station for AGG tid %d\n", tid);
2352 return -ENXIO;
2353 }
2354
2355 spin_lock_irqsave(&il->sta_lock, flags);
2356
2357 tid_data = &il->stations[sta_id].tid[tid];
2358 ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4;
2359 txq_id = tid_data->agg.txq_id;
2360
2361 switch (il->stations[sta_id].tid[tid].agg.state) {
2362 case IL_EMPTYING_HW_QUEUE_ADDBA:
2363 /*
2364 * This can happen if the peer stops aggregation
2365 * again before we've had a chance to drain the
2366 * queue we selected previously, i.e. before the
2367 * session was really started completely.
2368 */
2369 D_HT("AGG stop before setup done\n");
2370 goto turn_off;
2371 case IL_AGG_ON:
2372 break;
2373 default:
2374 IL_WARN("Stopping AGG while state not ON or starting\n");
2375 }
2376
2377 write_ptr = il->txq[txq_id].q.write_ptr;
2378 read_ptr = il->txq[txq_id].q.read_ptr;
2379
2380 /* The queue is not empty */
2381 if (write_ptr != read_ptr) {
2382 D_HT("Stopping a non empty AGG HW QUEUE\n");
2383 il->stations[sta_id].tid[tid].agg.state =
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002384 IL_EMPTYING_HW_QUEUE_DELBA;
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002385 spin_unlock_irqrestore(&il->sta_lock, flags);
2386 return 0;
2387 }
2388
2389 D_HT("HW queue is empty\n");
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002390turn_off:
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002391 il->stations[sta_id].tid[tid].agg.state = IL_AGG_OFF;
2392
2393 /* do not restore/save irqs */
2394 spin_unlock(&il->sta_lock);
2395 spin_lock(&il->lock);
2396
2397 /*
2398 * the only reason this call can fail is queue number out of range,
2399 * which can happen if uCode is reloaded and all the station
2400 * information are lost. if it is outside the range, there is no need
2401 * to deactivate the uCode queue, just return "success" to allow
2402 * mac80211 to clean up it own data.
2403 */
2404 il4965_txq_agg_disable(il, txq_id, ssn, tx_fifo_id);
2405 spin_unlock_irqrestore(&il->lock, flags);
2406
2407 ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
2408
2409 return 0;
2410}
2411
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002412int
2413il4965_txq_check_empty(struct il_priv *il, int sta_id, u8 tid, int txq_id)
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002414{
2415 struct il_queue *q = &il->txq[txq_id].q;
2416 u8 *addr = il->stations[sta_id].sta.sta.addr;
2417 struct il_tid_data *tid_data = &il->stations[sta_id].tid[tid];
2418 struct il_rxon_context *ctx;
2419
2420 ctx = &il->ctx;
2421
2422 lockdep_assert_held(&il->sta_lock);
2423
2424 switch (il->stations[sta_id].tid[tid].agg.state) {
2425 case IL_EMPTYING_HW_QUEUE_DELBA:
2426 /* We are reclaiming the last packet of the */
2427 /* aggregated HW queue */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002428 if (txq_id == tid_data->agg.txq_id &&
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002429 q->read_ptr == q->write_ptr) {
2430 u16 ssn = SEQ_TO_SN(tid_data->seq_number);
2431 int tx_fifo = il4965_get_fifo_from_tid(ctx, tid);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002432 D_HT("HW queue empty: continue DELBA flow\n");
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002433 il4965_txq_agg_disable(il, txq_id, ssn, tx_fifo);
2434 tid_data->agg.state = IL_AGG_OFF;
2435 ieee80211_stop_tx_ba_cb_irqsafe(ctx->vif, addr, tid);
2436 }
2437 break;
2438 case IL_EMPTYING_HW_QUEUE_ADDBA:
2439 /* We are reclaiming the last packet of the queue */
2440 if (tid_data->tfds_in_queue == 0) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002441 D_HT("HW queue empty: continue ADDBA flow\n");
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002442 tid_data->agg.state = IL_AGG_ON;
2443 ieee80211_start_tx_ba_cb_irqsafe(ctx->vif, addr, tid);
2444 }
2445 break;
2446 }
2447
2448 return 0;
2449}
2450
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002451static void
2452il4965_non_agg_tx_status(struct il_priv *il, struct il_rxon_context *ctx,
Stanislaw Gruszka1722f8e2011-11-15 14:51:01 +01002453 const u8 *addr1)
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002454{
2455 struct ieee80211_sta *sta;
2456 struct il_station_priv *sta_priv;
2457
2458 rcu_read_lock();
2459 sta = ieee80211_find_sta(ctx->vif, addr1);
2460 if (sta) {
2461 sta_priv = (void *)sta->drv_priv;
2462 /* avoid atomic ops if this isn't a client */
2463 if (sta_priv->client &&
2464 atomic_dec_return(&sta_priv->pending_frames) == 0)
2465 ieee80211_sta_block_awake(il->hw, sta, false);
2466 }
2467 rcu_read_unlock();
2468}
2469
2470static void
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002471il4965_tx_status(struct il_priv *il, struct il_tx_info *tx_info, bool is_agg)
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002472{
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002473 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx_info->skb->data;
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002474
2475 if (!is_agg)
2476 il4965_non_agg_tx_status(il, tx_info->ctx, hdr->addr1);
2477
2478 ieee80211_tx_status_irqsafe(il->hw, tx_info->skb);
2479}
2480
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002481int
2482il4965_tx_queue_reclaim(struct il_priv *il, int txq_id, int idx)
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002483{
2484 struct il_tx_queue *txq = &il->txq[txq_id];
2485 struct il_queue *q = &txq->q;
2486 struct il_tx_info *tx_info;
2487 int nfreed = 0;
2488 struct ieee80211_hdr *hdr;
2489
2490 if (idx >= q->n_bd || il_queue_used(q, idx) == 0) {
2491 IL_ERR("Read idx for DMA queue txq id (%d), idx %d, "
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002492 "is out of range [0-%d] %d %d.\n", txq_id, idx, q->n_bd,
2493 q->write_ptr, q->read_ptr);
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002494 return 0;
2495 }
2496
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002497 for (idx = il_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx;
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002498 q->read_ptr = il_queue_inc_wrap(q->read_ptr, q->n_bd)) {
2499
2500 tx_info = &txq->txb[txq->q.read_ptr];
2501
2502 if (WARN_ON_ONCE(tx_info->skb == NULL))
2503 continue;
2504
2505 hdr = (struct ieee80211_hdr *)tx_info->skb->data;
2506 if (ieee80211_is_data_qos(hdr->frame_control))
2507 nfreed++;
2508
2509 il4965_tx_status(il, tx_info,
2510 txq_id >= IL4965_FIRST_AMPDU_QUEUE);
2511 tx_info->skb = NULL;
2512
2513 il->cfg->ops->lib->txq_free_tfd(il, txq);
2514 }
2515 return nfreed;
2516}
2517
2518/**
2519 * il4965_tx_status_reply_compressed_ba - Update tx status from block-ack
2520 *
2521 * Go through block-ack's bitmap of ACK'd frames, update driver's record of
2522 * ACK vs. not. This gets sent to mac80211, then to rate scaling algo.
2523 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002524static int
2525il4965_tx_status_reply_compressed_ba(struct il_priv *il, struct il_ht_agg *agg,
2526 struct il_compressed_ba_resp *ba_resp)
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002527{
2528 int i, sh, ack;
2529 u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl);
2530 u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
2531 int successes = 0;
2532 struct ieee80211_tx_info *info;
2533 u64 bitmap, sent_bitmap;
2534
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002535 if (unlikely(!agg->wait_for_ba)) {
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002536 if (unlikely(ba_resp->bitmap))
2537 IL_ERR("Received BA when not expected\n");
2538 return -EINVAL;
2539 }
2540
2541 /* Mark that the expected block-ack response arrived */
2542 agg->wait_for_ba = 0;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002543 D_TX_REPLY("BA %d %d\n", agg->start_idx, ba_resp->seq_ctl);
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002544
2545 /* Calculate shift to align block-ack bits with our Tx win bits */
2546 sh = agg->start_idx - SEQ_TO_IDX(seq_ctl >> 4);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002547 if (sh < 0) /* tbw something is wrong with indices */
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002548 sh += 0x100;
2549
2550 if (agg->frame_count > (64 - sh)) {
2551 D_TX_REPLY("more frames than bitmap size");
2552 return -1;
2553 }
2554
2555 /* don't use 64-bit values for now */
2556 bitmap = le64_to_cpu(ba_resp->bitmap) >> sh;
2557
2558 /* check for success or failure according to the
2559 * transmitted bitmap and block-ack bitmap */
2560 sent_bitmap = bitmap & agg->bitmap;
2561
2562 /* For each frame attempted in aggregation,
2563 * update driver's record of tx frame's status. */
2564 i = 0;
2565 while (sent_bitmap) {
2566 ack = sent_bitmap & 1ULL;
2567 successes += ack;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002568 D_TX_REPLY("%s ON i=%d idx=%d raw=%d\n", ack ? "ACK" : "NACK",
2569 i, (agg->start_idx + i) & 0xff, agg->start_idx + i);
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002570 sent_bitmap >>= 1;
2571 ++i;
2572 }
2573
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002574 D_TX_REPLY("Bitmap %llx\n", (unsigned long long)bitmap);
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002575
2576 info = IEEE80211_SKB_CB(il->txq[scd_flow].txb[agg->start_idx].skb);
2577 memset(&info->status, 0, sizeof(info->status));
2578 info->flags |= IEEE80211_TX_STAT_ACK;
2579 info->flags |= IEEE80211_TX_STAT_AMPDU;
2580 info->status.ampdu_ack_len = successes;
2581 info->status.ampdu_len = agg->frame_count;
2582 il4965_hwrate_to_tx_control(il, agg->rate_n_flags, info);
2583
2584 return 0;
2585}
2586
2587/**
2588 * translate ucode response to mac80211 tx status control values
2589 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002590void
2591il4965_hwrate_to_tx_control(struct il_priv *il, u32 rate_n_flags,
2592 struct ieee80211_tx_info *info)
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002593{
2594 struct ieee80211_tx_rate *r = &info->control.rates[0];
2595
2596 info->antenna_sel_tx =
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002597 ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS);
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002598 if (rate_n_flags & RATE_MCS_HT_MSK)
2599 r->flags |= IEEE80211_TX_RC_MCS;
2600 if (rate_n_flags & RATE_MCS_GF_MSK)
2601 r->flags |= IEEE80211_TX_RC_GREEN_FIELD;
2602 if (rate_n_flags & RATE_MCS_HT40_MSK)
2603 r->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
2604 if (rate_n_flags & RATE_MCS_DUP_MSK)
2605 r->flags |= IEEE80211_TX_RC_DUP_DATA;
2606 if (rate_n_flags & RATE_MCS_SGI_MSK)
2607 r->flags |= IEEE80211_TX_RC_SHORT_GI;
2608 r->idx = il4965_hwrate_to_mac80211_idx(rate_n_flags, info->band);
2609}
2610
2611/**
Stanislaw Gruszka6e9848b42011-08-30 15:45:31 +02002612 * il4965_hdl_compressed_ba - Handler for N_COMPRESSED_BA
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002613 *
2614 * Handles block-acknowledge notification from device, which reports success
2615 * of frames sent via aggregation.
2616 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002617void
2618il4965_hdl_compressed_ba(struct il_priv *il, struct il_rx_buf *rxb)
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002619{
2620 struct il_rx_pkt *pkt = rxb_addr(rxb);
2621 struct il_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba;
2622 struct il_tx_queue *txq = NULL;
2623 struct il_ht_agg *agg;
2624 int idx;
2625 int sta_id;
2626 int tid;
2627 unsigned long flags;
2628
2629 /* "flow" corresponds to Tx queue */
2630 u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
2631
2632 /* "ssn" is start of block-ack Tx win, corresponds to idx
2633 * (in Tx queue's circular buffer) of first TFD/frame in win */
2634 u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn);
2635
2636 if (scd_flow >= il->hw_params.max_txq_num) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002637 IL_ERR("BUG_ON scd_flow is bigger than number of queues\n");
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002638 return;
2639 }
2640
2641 txq = &il->txq[scd_flow];
2642 sta_id = ba_resp->sta_id;
2643 tid = ba_resp->tid;
2644 agg = &il->stations[sta_id].tid[tid].agg;
2645 if (unlikely(agg->txq_id != scd_flow)) {
2646 /*
2647 * FIXME: this is a uCode bug which need to be addressed,
2648 * log the information and return for now!
2649 * since it is possible happen very often and in order
2650 * not to fill the syslog, don't enable the logging by default
2651 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002652 D_TX_REPLY("BA scd_flow %d does not match txq_id %d\n",
2653 scd_flow, agg->txq_id);
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002654 return;
2655 }
2656
2657 /* Find idx just before block-ack win */
2658 idx = il_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd);
2659
2660 spin_lock_irqsave(&il->sta_lock, flags);
2661
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002662 D_TX_REPLY("N_COMPRESSED_BA [%d] Received from %pM, " "sta_id = %d\n",
Stanislaw Gruszka1722f8e2011-11-15 14:51:01 +01002663 agg->wait_for_ba, (u8 *) &ba_resp->sta_addr_lo32,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002664 ba_resp->sta_id);
2665 D_TX_REPLY("TID = %d, SeqCtl = %d, bitmap = 0x%llx," "scd_flow = "
2666 "%d, scd_ssn = %d\n", ba_resp->tid, ba_resp->seq_ctl,
2667 (unsigned long long)le64_to_cpu(ba_resp->bitmap),
2668 ba_resp->scd_flow, ba_resp->scd_ssn);
2669 D_TX_REPLY("DAT start_idx = %d, bitmap = 0x%llx\n", agg->start_idx,
2670 (unsigned long long)agg->bitmap);
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002671
2672 /* Update driver's record of ACK vs. not for each frame in win */
2673 il4965_tx_status_reply_compressed_ba(il, agg, ba_resp);
2674
2675 /* Release all TFDs before the SSN, i.e. all TFDs in front of
2676 * block-ack win (we assume that they've been successfully
2677 * transmitted ... if not, it's too late anyway). */
2678 if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) {
2679 /* calculate mac80211 ampdu sw queue to wake */
2680 int freed = il4965_tx_queue_reclaim(il, scd_flow, idx);
2681 il4965_free_tfds_in_queue(il, sta_id, tid, freed);
2682
2683 if (il_queue_space(&txq->q) > txq->q.low_mark &&
2684 il->mac80211_registered &&
2685 agg->state != IL_EMPTYING_HW_QUEUE_DELBA)
2686 il_wake_queue(il, txq);
2687
2688 il4965_txq_check_empty(il, sta_id, tid, scd_flow);
2689 }
2690
2691 spin_unlock_irqrestore(&il->sta_lock, flags);
2692}
2693
2694#ifdef CONFIG_IWLEGACY_DEBUG
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002695const char *
2696il4965_get_tx_fail_reason(u32 status)
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002697{
2698#define TX_STATUS_FAIL(x) case TX_STATUS_FAIL_ ## x: return #x
2699#define TX_STATUS_POSTPONE(x) case TX_STATUS_POSTPONE_ ## x: return #x
2700
2701 switch (status & TX_STATUS_MSK) {
2702 case TX_STATUS_SUCCESS:
2703 return "SUCCESS";
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002704 TX_STATUS_POSTPONE(DELAY);
2705 TX_STATUS_POSTPONE(FEW_BYTES);
2706 TX_STATUS_POSTPONE(QUIET_PERIOD);
2707 TX_STATUS_POSTPONE(CALC_TTAK);
2708 TX_STATUS_FAIL(INTERNAL_CROSSED_RETRY);
2709 TX_STATUS_FAIL(SHORT_LIMIT);
2710 TX_STATUS_FAIL(LONG_LIMIT);
2711 TX_STATUS_FAIL(FIFO_UNDERRUN);
2712 TX_STATUS_FAIL(DRAIN_FLOW);
2713 TX_STATUS_FAIL(RFKILL_FLUSH);
2714 TX_STATUS_FAIL(LIFE_EXPIRE);
2715 TX_STATUS_FAIL(DEST_PS);
2716 TX_STATUS_FAIL(HOST_ABORTED);
2717 TX_STATUS_FAIL(BT_RETRY);
2718 TX_STATUS_FAIL(STA_INVALID);
2719 TX_STATUS_FAIL(FRAG_DROPPED);
2720 TX_STATUS_FAIL(TID_DISABLE);
2721 TX_STATUS_FAIL(FIFO_FLUSHED);
2722 TX_STATUS_FAIL(INSUFFICIENT_CF_POLL);
2723 TX_STATUS_FAIL(PASSIVE_NO_RX);
2724 TX_STATUS_FAIL(NO_BEACON_ON_RADAR);
Stanislaw Gruszkaa1751b22011-11-15 12:50:37 +01002725 }
2726
2727 return "UNKNOWN";
2728
2729#undef TX_STATUS_FAIL
2730#undef TX_STATUS_POSTPONE
2731}
2732#endif /* CONFIG_IWLEGACY_DEBUG */
2733
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02002734static struct il_link_quality_cmd *
2735il4965_sta_alloc_lq(struct il_priv *il, u8 sta_id)
2736{
2737 int i, r;
2738 struct il_link_quality_cmd *link_cmd;
2739 u32 rate_flags = 0;
2740 __le32 rate_n_flags;
2741
2742 link_cmd = kzalloc(sizeof(struct il_link_quality_cmd), GFP_KERNEL);
2743 if (!link_cmd) {
2744 IL_ERR("Unable to allocate memory for LQ cmd.\n");
2745 return NULL;
2746 }
2747 /* Set up the rate scaling to start at selected rate, fall back
2748 * all the way down to 1M in IEEE order, and then spin on 1M */
2749 if (il->band == IEEE80211_BAND_5GHZ)
2750 r = RATE_6M_IDX;
2751 else
2752 r = RATE_1M_IDX;
2753
2754 if (r >= IL_FIRST_CCK_RATE && r <= IL_LAST_CCK_RATE)
2755 rate_flags |= RATE_MCS_CCK_MSK;
2756
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002757 rate_flags |=
2758 il4965_first_antenna(il->hw_params.
2759 valid_tx_ant) << RATE_MCS_ANT_POS;
2760 rate_n_flags = il4965_hw_set_rate_n_flags(il_rates[r].plcp, rate_flags);
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02002761 for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++)
2762 link_cmd->rs_table[i].rate_n_flags = rate_n_flags;
2763
2764 link_cmd->general_params.single_stream_ant_msk =
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002765 il4965_first_antenna(il->hw_params.valid_tx_ant);
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02002766
2767 link_cmd->general_params.dual_stream_ant_msk =
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002768 il->hw_params.valid_tx_ant & ~il4965_first_antenna(il->hw_params.
2769 valid_tx_ant);
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02002770 if (!link_cmd->general_params.dual_stream_ant_msk) {
2771 link_cmd->general_params.dual_stream_ant_msk = ANT_AB;
2772 } else if (il4965_num_of_ant(il->hw_params.valid_tx_ant) == 2) {
2773 link_cmd->general_params.dual_stream_ant_msk =
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002774 il->hw_params.valid_tx_ant;
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02002775 }
2776
2777 link_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF;
2778 link_cmd->agg_params.agg_time_limit =
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002779 cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF);
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02002780
2781 link_cmd->sta_id = sta_id;
2782
2783 return link_cmd;
2784}
2785
2786/*
2787 * il4965_add_bssid_station - Add the special IBSS BSSID station
2788 *
2789 * Function sleeps.
2790 */
2791int
2792il4965_add_bssid_station(struct il_priv *il, struct il_rxon_context *ctx,
Stanislaw Gruszka1722f8e2011-11-15 14:51:01 +01002793 const u8 *addr, u8 *sta_id_r)
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02002794{
2795 int ret;
2796 u8 sta_id;
2797 struct il_link_quality_cmd *link_cmd;
2798 unsigned long flags;
2799
2800 if (sta_id_r)
2801 *sta_id_r = IL_INVALID_STATION;
2802
2803 ret = il_add_station_common(il, ctx, addr, 0, NULL, &sta_id);
2804 if (ret) {
2805 IL_ERR("Unable to add station %pM\n", addr);
2806 return ret;
2807 }
2808
2809 if (sta_id_r)
2810 *sta_id_r = sta_id;
2811
2812 spin_lock_irqsave(&il->sta_lock, flags);
2813 il->stations[sta_id].used |= IL_STA_LOCAL;
2814 spin_unlock_irqrestore(&il->sta_lock, flags);
2815
2816 /* Set up default rate scaling table in device's station table */
2817 link_cmd = il4965_sta_alloc_lq(il, sta_id);
2818 if (!link_cmd) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002819 IL_ERR("Unable to initialize rate scaling for station %pM.\n",
2820 addr);
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02002821 return -ENOMEM;
2822 }
2823
2824 ret = il_send_lq_cmd(il, ctx, link_cmd, CMD_SYNC, true);
2825 if (ret)
2826 IL_ERR("Link quality command failed (%d)\n", ret);
2827
2828 spin_lock_irqsave(&il->sta_lock, flags);
2829 il->stations[sta_id].lq = link_cmd;
2830 spin_unlock_irqrestore(&il->sta_lock, flags);
2831
2832 return 0;
2833}
2834
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002835static int
2836il4965_static_wepkey_cmd(struct il_priv *il, struct il_rxon_context *ctx,
2837 bool send_if_empty)
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02002838{
2839 int i, not_empty = 0;
2840 u8 buff[sizeof(struct il_wep_cmd) +
2841 sizeof(struct il_wep_key) * WEP_KEYS_MAX];
2842 struct il_wep_cmd *wep_cmd = (struct il_wep_cmd *)buff;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002843 size_t cmd_size = sizeof(struct il_wep_cmd);
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02002844 struct il_host_cmd cmd = {
2845 .id = ctx->wep_key_cmd,
2846 .data = wep_cmd,
2847 .flags = CMD_SYNC,
2848 };
2849
2850 might_sleep();
2851
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002852 memset(wep_cmd, 0,
2853 cmd_size + (sizeof(struct il_wep_key) * WEP_KEYS_MAX));
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02002854
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002855 for (i = 0; i < WEP_KEYS_MAX; i++) {
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02002856 wep_cmd->key[i].key_idx = i;
2857 if (ctx->wep_keys[i].key_size) {
2858 wep_cmd->key[i].key_offset = i;
2859 not_empty = 1;
2860 } else {
2861 wep_cmd->key[i].key_offset = WEP_INVALID_OFFSET;
2862 }
2863
2864 wep_cmd->key[i].key_size = ctx->wep_keys[i].key_size;
2865 memcpy(&wep_cmd->key[i].key[3], ctx->wep_keys[i].key,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002866 ctx->wep_keys[i].key_size);
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02002867 }
2868
2869 wep_cmd->global_key_type = WEP_KEY_WEP_TYPE;
2870 wep_cmd->num_keys = WEP_KEYS_MAX;
2871
2872 cmd_size += sizeof(struct il_wep_key) * WEP_KEYS_MAX;
2873
2874 cmd.len = cmd_size;
2875
2876 if (not_empty || send_if_empty)
2877 return il_send_cmd(il, &cmd);
2878 else
2879 return 0;
2880}
2881
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002882int
2883il4965_restore_default_wep_keys(struct il_priv *il, struct il_rxon_context *ctx)
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02002884{
2885 lockdep_assert_held(&il->mutex);
2886
2887 return il4965_static_wepkey_cmd(il, ctx, false);
2888}
2889
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002890int
2891il4965_remove_default_wep_key(struct il_priv *il, struct il_rxon_context *ctx,
2892 struct ieee80211_key_conf *keyconf)
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02002893{
2894 int ret;
2895
2896 lockdep_assert_held(&il->mutex);
2897
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002898 D_WEP("Removing default WEP key: idx=%d\n", keyconf->keyidx);
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02002899
2900 memset(&ctx->wep_keys[keyconf->keyidx], 0, sizeof(ctx->wep_keys[0]));
2901 if (il_is_rfkill(il)) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002902 D_WEP("Not sending C_WEPKEY command due to RFKILL.\n");
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02002903 /* but keys in device are clear anyway so return success */
2904 return 0;
2905 }
2906 ret = il4965_static_wepkey_cmd(il, ctx, 1);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002907 D_WEP("Remove default WEP key: idx=%d ret=%d\n", keyconf->keyidx, ret);
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02002908
2909 return ret;
2910}
2911
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002912int
2913il4965_set_default_wep_key(struct il_priv *il, struct il_rxon_context *ctx,
2914 struct ieee80211_key_conf *keyconf)
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02002915{
2916 int ret;
2917
2918 lockdep_assert_held(&il->mutex);
2919
2920 if (keyconf->keylen != WEP_KEY_LEN_128 &&
2921 keyconf->keylen != WEP_KEY_LEN_64) {
2922 D_WEP("Bad WEP key length %d\n", keyconf->keylen);
2923 return -EINVAL;
2924 }
2925
2926 keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
2927 keyconf->hw_key_idx = HW_KEY_DEFAULT;
2928 il->stations[ctx->ap_sta_id].keyinfo.cipher = keyconf->cipher;
2929
2930 ctx->wep_keys[keyconf->keyidx].key_size = keyconf->keylen;
2931 memcpy(&ctx->wep_keys[keyconf->keyidx].key, &keyconf->key,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002932 keyconf->keylen);
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02002933
2934 ret = il4965_static_wepkey_cmd(il, ctx, false);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002935 D_WEP("Set default WEP key: len=%d idx=%d ret=%d\n", keyconf->keylen,
2936 keyconf->keyidx, ret);
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02002937
2938 return ret;
2939}
2940
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002941static int
2942il4965_set_wep_dynamic_key_info(struct il_priv *il, struct il_rxon_context *ctx,
2943 struct ieee80211_key_conf *keyconf, u8 sta_id)
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02002944{
2945 unsigned long flags;
2946 __le16 key_flags = 0;
2947 struct il_addsta_cmd sta_cmd;
2948
2949 lockdep_assert_held(&il->mutex);
2950
2951 keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
2952
2953 key_flags |= (STA_KEY_FLG_WEP | STA_KEY_FLG_MAP_KEY_MSK);
2954 key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
2955 key_flags &= ~STA_KEY_FLG_INVALID;
2956
2957 if (keyconf->keylen == WEP_KEY_LEN_128)
2958 key_flags |= STA_KEY_FLG_KEY_SIZE_MSK;
2959
2960 if (sta_id == ctx->bcast_sta_id)
2961 key_flags |= STA_KEY_MULTICAST_MSK;
2962
2963 spin_lock_irqsave(&il->sta_lock, flags);
2964
2965 il->stations[sta_id].keyinfo.cipher = keyconf->cipher;
2966 il->stations[sta_id].keyinfo.keylen = keyconf->keylen;
2967 il->stations[sta_id].keyinfo.keyidx = keyconf->keyidx;
2968
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002969 memcpy(il->stations[sta_id].keyinfo.key, keyconf->key, keyconf->keylen);
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02002970
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002971 memcpy(&il->stations[sta_id].sta.key.key[3], keyconf->key,
2972 keyconf->keylen);
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02002973
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002974 if ((il->stations[sta_id].sta.key.
2975 key_flags & STA_KEY_FLG_ENCRYPT_MSK) == STA_KEY_FLG_NO_ENC)
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02002976 il->stations[sta_id].sta.key.key_offset =
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002977 il_get_free_ucode_key_idx(il);
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02002978 /* else, we are overriding an existing key => no need to allocated room
2979 * in uCode. */
2980
2981 WARN(il->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002982 "no space for a new key");
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02002983
2984 il->stations[sta_id].sta.key.key_flags = key_flags;
2985 il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
2986 il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
2987
2988 memcpy(&sta_cmd, &il->stations[sta_id].sta,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002989 sizeof(struct il_addsta_cmd));
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02002990 spin_unlock_irqrestore(&il->sta_lock, flags);
2991
2992 return il_send_add_sta(il, &sta_cmd, CMD_SYNC);
2993}
2994
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002995static int
2996il4965_set_ccmp_dynamic_key_info(struct il_priv *il,
2997 struct il_rxon_context *ctx,
2998 struct ieee80211_key_conf *keyconf, u8 sta_id)
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02002999{
3000 unsigned long flags;
3001 __le16 key_flags = 0;
3002 struct il_addsta_cmd sta_cmd;
3003
3004 lockdep_assert_held(&il->mutex);
3005
3006 key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK);
3007 key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
3008 key_flags &= ~STA_KEY_FLG_INVALID;
3009
3010 if (sta_id == ctx->bcast_sta_id)
3011 key_flags |= STA_KEY_MULTICAST_MSK;
3012
3013 keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
3014
3015 spin_lock_irqsave(&il->sta_lock, flags);
3016 il->stations[sta_id].keyinfo.cipher = keyconf->cipher;
3017 il->stations[sta_id].keyinfo.keylen = keyconf->keylen;
3018
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003019 memcpy(il->stations[sta_id].keyinfo.key, keyconf->key, keyconf->keylen);
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003020
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003021 memcpy(il->stations[sta_id].sta.key.key, keyconf->key, keyconf->keylen);
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003022
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003023 if ((il->stations[sta_id].sta.key.
3024 key_flags & STA_KEY_FLG_ENCRYPT_MSK) == STA_KEY_FLG_NO_ENC)
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003025 il->stations[sta_id].sta.key.key_offset =
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003026 il_get_free_ucode_key_idx(il);
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003027 /* else, we are overriding an existing key => no need to allocated room
3028 * in uCode. */
3029
3030 WARN(il->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003031 "no space for a new key");
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003032
3033 il->stations[sta_id].sta.key.key_flags = key_flags;
3034 il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
3035 il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
3036
3037 memcpy(&sta_cmd, &il->stations[sta_id].sta,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003038 sizeof(struct il_addsta_cmd));
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003039 spin_unlock_irqrestore(&il->sta_lock, flags);
3040
3041 return il_send_add_sta(il, &sta_cmd, CMD_SYNC);
3042}
3043
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003044static int
3045il4965_set_tkip_dynamic_key_info(struct il_priv *il,
3046 struct il_rxon_context *ctx,
3047 struct ieee80211_key_conf *keyconf, u8 sta_id)
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003048{
3049 unsigned long flags;
3050 int ret = 0;
3051 __le16 key_flags = 0;
3052
3053 key_flags |= (STA_KEY_FLG_TKIP | STA_KEY_FLG_MAP_KEY_MSK);
3054 key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
3055 key_flags &= ~STA_KEY_FLG_INVALID;
3056
3057 if (sta_id == ctx->bcast_sta_id)
3058 key_flags |= STA_KEY_MULTICAST_MSK;
3059
3060 keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
3061 keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
3062
3063 spin_lock_irqsave(&il->sta_lock, flags);
3064
3065 il->stations[sta_id].keyinfo.cipher = keyconf->cipher;
3066 il->stations[sta_id].keyinfo.keylen = 16;
3067
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003068 if ((il->stations[sta_id].sta.key.
3069 key_flags & STA_KEY_FLG_ENCRYPT_MSK) == STA_KEY_FLG_NO_ENC)
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003070 il->stations[sta_id].sta.key.key_offset =
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003071 il_get_free_ucode_key_idx(il);
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003072 /* else, we are overriding an existing key => no need to allocated room
3073 * in uCode. */
3074
3075 WARN(il->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003076 "no space for a new key");
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003077
3078 il->stations[sta_id].sta.key.key_flags = key_flags;
3079
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003080 /* This copy is acutally not needed: we get the key with each TX */
3081 memcpy(il->stations[sta_id].keyinfo.key, keyconf->key, 16);
3082
3083 memcpy(il->stations[sta_id].sta.key.key, keyconf->key, 16);
3084
3085 spin_unlock_irqrestore(&il->sta_lock, flags);
3086
3087 return ret;
3088}
3089
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003090void
3091il4965_update_tkip_key(struct il_priv *il, struct il_rxon_context *ctx,
3092 struct ieee80211_key_conf *keyconf,
3093 struct ieee80211_sta *sta, u32 iv32, u16 * phase1key)
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003094{
3095 u8 sta_id;
3096 unsigned long flags;
3097 int i;
3098
3099 if (il_scan_cancel(il)) {
3100 /* cancel scan failed, just live w/ bad key and rely
3101 briefly on SW decryption */
3102 return;
3103 }
3104
3105 sta_id = il_sta_id_or_broadcast(il, ctx, sta);
3106 if (sta_id == IL_INVALID_STATION)
3107 return;
3108
3109 spin_lock_irqsave(&il->sta_lock, flags);
3110
3111 il->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32;
3112
3113 for (i = 0; i < 5; i++)
3114 il->stations[sta_id].sta.key.tkip_rx_ttak[i] =
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003115 cpu_to_le16(phase1key[i]);
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003116
3117 il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
3118 il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
3119
3120 il_send_add_sta(il, &il->stations[sta_id].sta, CMD_ASYNC);
3121
3122 spin_unlock_irqrestore(&il->sta_lock, flags);
3123
3124}
3125
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003126int
3127il4965_remove_dynamic_key(struct il_priv *il, struct il_rxon_context *ctx,
3128 struct ieee80211_key_conf *keyconf, u8 sta_id)
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003129{
3130 unsigned long flags;
3131 u16 key_flags;
3132 u8 keyidx;
3133 struct il_addsta_cmd sta_cmd;
3134
3135 lockdep_assert_held(&il->mutex);
3136
3137 ctx->key_mapping_keys--;
3138
3139 spin_lock_irqsave(&il->sta_lock, flags);
3140 key_flags = le16_to_cpu(il->stations[sta_id].sta.key.key_flags);
3141 keyidx = (key_flags >> STA_KEY_FLG_KEYID_POS) & 0x3;
3142
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003143 D_WEP("Remove dynamic key: idx=%d sta=%d\n", keyconf->keyidx, sta_id);
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003144
3145 if (keyconf->keyidx != keyidx) {
3146 /* We need to remove a key with idx different that the one
3147 * in the uCode. This means that the key we need to remove has
3148 * been replaced by another one with different idx.
3149 * Don't do anything and return ok
3150 */
3151 spin_unlock_irqrestore(&il->sta_lock, flags);
3152 return 0;
3153 }
3154
3155 if (il->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003156 IL_WARN("Removing wrong key %d 0x%x\n", keyconf->keyidx,
3157 key_flags);
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003158 spin_unlock_irqrestore(&il->sta_lock, flags);
3159 return 0;
3160 }
3161
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003162 if (!test_and_clear_bit
3163 (il->stations[sta_id].sta.key.key_offset, &il->ucode_key_table))
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003164 IL_ERR("idx %d not used in uCode key table.\n",
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003165 il->stations[sta_id].sta.key.key_offset);
3166 memset(&il->stations[sta_id].keyinfo, 0, sizeof(struct il_hw_key));
3167 memset(&il->stations[sta_id].sta.key, 0, sizeof(struct il4965_keyinfo));
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003168 il->stations[sta_id].sta.key.key_flags =
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003169 STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID;
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003170 il->stations[sta_id].sta.key.key_offset = WEP_INVALID_OFFSET;
3171 il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
3172 il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
3173
3174 if (il_is_rfkill(il)) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003175 D_WEP
3176 ("Not sending C_ADD_STA command because RFKILL enabled.\n");
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003177 spin_unlock_irqrestore(&il->sta_lock, flags);
3178 return 0;
3179 }
3180 memcpy(&sta_cmd, &il->stations[sta_id].sta,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003181 sizeof(struct il_addsta_cmd));
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003182 spin_unlock_irqrestore(&il->sta_lock, flags);
3183
3184 return il_send_add_sta(il, &sta_cmd, CMD_SYNC);
3185}
3186
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003187int
3188il4965_set_dynamic_key(struct il_priv *il, struct il_rxon_context *ctx,
3189 struct ieee80211_key_conf *keyconf, u8 sta_id)
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003190{
3191 int ret;
3192
3193 lockdep_assert_held(&il->mutex);
3194
3195 ctx->key_mapping_keys++;
3196 keyconf->hw_key_idx = HW_KEY_DYNAMIC;
3197
3198 switch (keyconf->cipher) {
3199 case WLAN_CIPHER_SUITE_CCMP:
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003200 ret =
3201 il4965_set_ccmp_dynamic_key_info(il, ctx, keyconf, sta_id);
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003202 break;
3203 case WLAN_CIPHER_SUITE_TKIP:
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003204 ret =
3205 il4965_set_tkip_dynamic_key_info(il, ctx, keyconf, sta_id);
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003206 break;
3207 case WLAN_CIPHER_SUITE_WEP40:
3208 case WLAN_CIPHER_SUITE_WEP104:
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003209 ret = il4965_set_wep_dynamic_key_info(il, ctx, keyconf, sta_id);
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003210 break;
3211 default:
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003212 IL_ERR("Unknown alg: %s cipher = %x\n", __func__,
3213 keyconf->cipher);
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003214 ret = -EINVAL;
3215 }
3216
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003217 D_WEP("Set dynamic key: cipher=%x len=%d idx=%d sta=%d ret=%d\n",
3218 keyconf->cipher, keyconf->keylen, keyconf->keyidx, sta_id, ret);
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003219
3220 return ret;
3221}
3222
3223/**
3224 * il4965_alloc_bcast_station - add broadcast station into driver's station table.
3225 *
3226 * This adds the broadcast station into the driver's station table
3227 * and marks it driver active, so that it will be restored to the
3228 * device at the next best time.
3229 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003230int
3231il4965_alloc_bcast_station(struct il_priv *il, struct il_rxon_context *ctx)
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003232{
3233 struct il_link_quality_cmd *link_cmd;
3234 unsigned long flags;
3235 u8 sta_id;
3236
3237 spin_lock_irqsave(&il->sta_lock, flags);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003238 sta_id = il_prep_station(il, ctx, il_bcast_addr, false, NULL);
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003239 if (sta_id == IL_INVALID_STATION) {
3240 IL_ERR("Unable to prepare broadcast station\n");
3241 spin_unlock_irqrestore(&il->sta_lock, flags);
3242
3243 return -EINVAL;
3244 }
3245
3246 il->stations[sta_id].used |= IL_STA_DRIVER_ACTIVE;
3247 il->stations[sta_id].used |= IL_STA_BCAST;
3248 spin_unlock_irqrestore(&il->sta_lock, flags);
3249
3250 link_cmd = il4965_sta_alloc_lq(il, sta_id);
3251 if (!link_cmd) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003252 IL_ERR
3253 ("Unable to initialize rate scaling for bcast station.\n");
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003254 return -ENOMEM;
3255 }
3256
3257 spin_lock_irqsave(&il->sta_lock, flags);
3258 il->stations[sta_id].lq = link_cmd;
3259 spin_unlock_irqrestore(&il->sta_lock, flags);
3260
3261 return 0;
3262}
3263
3264/**
3265 * il4965_update_bcast_station - update broadcast station's LQ command
3266 *
3267 * Only used by iwl4965. Placed here to have all bcast station management
3268 * code together.
3269 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003270static int
3271il4965_update_bcast_station(struct il_priv *il, struct il_rxon_context *ctx)
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003272{
3273 unsigned long flags;
3274 struct il_link_quality_cmd *link_cmd;
3275 u8 sta_id = ctx->bcast_sta_id;
3276
3277 link_cmd = il4965_sta_alloc_lq(il, sta_id);
3278 if (!link_cmd) {
Stanislaw Gruszka1722f8e2011-11-15 14:51:01 +01003279 IL_ERR("Unable to initialize rate scaling for bcast sta.\n");
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003280 return -ENOMEM;
3281 }
3282
3283 spin_lock_irqsave(&il->sta_lock, flags);
3284 if (il->stations[sta_id].lq)
3285 kfree(il->stations[sta_id].lq);
3286 else
Stanislaw Gruszka1722f8e2011-11-15 14:51:01 +01003287 D_INFO("Bcast sta rate scaling has not been initialized.\n");
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003288 il->stations[sta_id].lq = link_cmd;
3289 spin_unlock_irqrestore(&il->sta_lock, flags);
3290
3291 return 0;
3292}
3293
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003294int
3295il4965_update_bcast_stations(struct il_priv *il)
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003296{
3297 return il4965_update_bcast_station(il, &il->ctx);
3298}
3299
3300/**
3301 * il4965_sta_tx_modify_enable_tid - Enable Tx for this TID in station table
3302 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003303int
3304il4965_sta_tx_modify_enable_tid(struct il_priv *il, int sta_id, int tid)
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003305{
3306 unsigned long flags;
3307 struct il_addsta_cmd sta_cmd;
3308
3309 lockdep_assert_held(&il->mutex);
3310
3311 /* Remove "disable" flag, to enable Tx for this TID */
3312 spin_lock_irqsave(&il->sta_lock, flags);
3313 il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX;
3314 il->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid));
3315 il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
3316 memcpy(&sta_cmd, &il->stations[sta_id].sta,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003317 sizeof(struct il_addsta_cmd));
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003318 spin_unlock_irqrestore(&il->sta_lock, flags);
3319
3320 return il_send_add_sta(il, &sta_cmd, CMD_SYNC);
3321}
3322
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003323int
3324il4965_sta_rx_agg_start(struct il_priv *il, struct ieee80211_sta *sta, int tid,
3325 u16 ssn)
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003326{
3327 unsigned long flags;
3328 int sta_id;
3329 struct il_addsta_cmd sta_cmd;
3330
3331 lockdep_assert_held(&il->mutex);
3332
3333 sta_id = il_sta_id(sta);
3334 if (sta_id == IL_INVALID_STATION)
3335 return -ENXIO;
3336
3337 spin_lock_irqsave(&il->sta_lock, flags);
3338 il->stations[sta_id].sta.station_flags_msk = 0;
3339 il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_ADDBA_TID_MSK;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003340 il->stations[sta_id].sta.add_immediate_ba_tid = (u8) tid;
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003341 il->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn);
3342 il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
3343 memcpy(&sta_cmd, &il->stations[sta_id].sta,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003344 sizeof(struct il_addsta_cmd));
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003345 spin_unlock_irqrestore(&il->sta_lock, flags);
3346
3347 return il_send_add_sta(il, &sta_cmd, CMD_SYNC);
3348}
3349
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003350int
3351il4965_sta_rx_agg_stop(struct il_priv *il, struct ieee80211_sta *sta, int tid)
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003352{
3353 unsigned long flags;
3354 int sta_id;
3355 struct il_addsta_cmd sta_cmd;
3356
3357 lockdep_assert_held(&il->mutex);
3358
3359 sta_id = il_sta_id(sta);
3360 if (sta_id == IL_INVALID_STATION) {
3361 IL_ERR("Invalid station for AGG tid %d\n", tid);
3362 return -ENXIO;
3363 }
3364
3365 spin_lock_irqsave(&il->sta_lock, flags);
3366 il->stations[sta_id].sta.station_flags_msk = 0;
3367 il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003368 il->stations[sta_id].sta.remove_immediate_ba_tid = (u8) tid;
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003369 il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
3370 memcpy(&sta_cmd, &il->stations[sta_id].sta,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003371 sizeof(struct il_addsta_cmd));
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003372 spin_unlock_irqrestore(&il->sta_lock, flags);
3373
3374 return il_send_add_sta(il, &sta_cmd, CMD_SYNC);
3375}
3376
3377void
3378il4965_sta_modify_sleep_tx_count(struct il_priv *il, int sta_id, int cnt)
3379{
3380 unsigned long flags;
3381
3382 spin_lock_irqsave(&il->sta_lock, flags);
3383 il->stations[sta_id].sta.station_flags |= STA_FLG_PWR_SAVE_MSK;
3384 il->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK;
3385 il->stations[sta_id].sta.sta.modify_mask =
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003386 STA_MODIFY_SLEEP_TX_COUNT_MSK;
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003387 il->stations[sta_id].sta.sleep_tx_count = cpu_to_le16(cnt);
3388 il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003389 il_send_add_sta(il, &il->stations[sta_id].sta, CMD_ASYNC);
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +02003390 spin_unlock_irqrestore(&il->sta_lock, flags);
3391
3392}
3393
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003394void
3395il4965_update_chain_flags(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003396{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003397 if (il->cfg->ops->hcmd->set_rxon_chain) {
Stanislaw Gruszka17d6e552011-08-29 12:52:20 +02003398 il->cfg->ops->hcmd->set_rxon_chain(il, &il->ctx);
3399 if (il->ctx.active.rx_chain != il->ctx.staging.rx_chain)
3400 il_commit_rxon(il, &il->ctx);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003401 }
3402}
3403
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003404static void
3405il4965_clear_free_frames(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003406{
3407 struct list_head *element;
3408
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003409 D_INFO("%d frames on pre-allocated heap on clear.\n", il->frames_count);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003410
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003411 while (!list_empty(&il->free_frames)) {
3412 element = il->free_frames.next;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003413 list_del(element);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003414 kfree(list_entry(element, struct il_frame, list));
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003415 il->frames_count--;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003416 }
3417
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003418 if (il->frames_count) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003419 IL_WARN("%d frames still in use. Did we lose one?\n",
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003420 il->frames_count);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003421 il->frames_count = 0;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003422 }
3423}
3424
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003425static struct il_frame *
3426il4965_get_free_frame(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003427{
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003428 struct il_frame *frame;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003429 struct list_head *element;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003430 if (list_empty(&il->free_frames)) {
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003431 frame = kzalloc(sizeof(*frame), GFP_KERNEL);
3432 if (!frame) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003433 IL_ERR("Could not allocate frame!\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003434 return NULL;
3435 }
3436
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003437 il->frames_count++;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003438 return frame;
3439 }
3440
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003441 element = il->free_frames.next;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003442 list_del(element);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003443 return list_entry(element, struct il_frame, list);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003444}
3445
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003446static void
3447il4965_free_frame(struct il_priv *il, struct il_frame *frame)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003448{
3449 memset(frame, 0, sizeof(*frame));
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003450 list_add(&frame->list, &il->free_frames);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003451}
3452
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003453static u32
3454il4965_fill_beacon_frame(struct il_priv *il, struct ieee80211_hdr *hdr,
3455 int left)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003456{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003457 lockdep_assert_held(&il->mutex);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003458
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003459 if (!il->beacon_skb)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003460 return 0;
3461
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003462 if (il->beacon_skb->len > left)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003463 return 0;
3464
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003465 memcpy(hdr, il->beacon_skb->data, il->beacon_skb->len);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003466
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003467 return il->beacon_skb->len;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003468}
3469
3470/* Parse the beacon frame to find the TIM element and set tim_idx & tim_size */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003471static void
3472il4965_set_beacon_tim(struct il_priv *il,
3473 struct il_tx_beacon_cmd *tx_beacon_cmd, u8 * beacon,
3474 u32 frame_size)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003475{
3476 u16 tim_idx;
3477 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)beacon;
3478
3479 /*
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +01003480 * The idx is relative to frame start but we start looking at the
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003481 * variable-length part of the beacon.
3482 */
3483 tim_idx = mgmt->u.beacon.variable - beacon;
3484
3485 /* Parse variable-length elements of beacon to find WLAN_EID_TIM */
3486 while ((tim_idx < (frame_size - 2)) &&
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003487 (beacon[tim_idx] != WLAN_EID_TIM))
3488 tim_idx += beacon[tim_idx + 1] + 2;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003489
3490 /* If TIM field was found, set variables */
3491 if ((tim_idx < (frame_size - 1)) && (beacon[tim_idx] == WLAN_EID_TIM)) {
3492 tx_beacon_cmd->tim_idx = cpu_to_le16(tim_idx);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003493 tx_beacon_cmd->tim_size = beacon[tim_idx + 1];
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003494 } else
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003495 IL_WARN("Unable to find TIM Element in beacon\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003496}
3497
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003498static unsigned int
3499il4965_hw_get_beacon_cmd(struct il_priv *il, struct il_frame *frame)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003500{
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003501 struct il_tx_beacon_cmd *tx_beacon_cmd;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003502 u32 frame_size;
3503 u32 rate_flags;
3504 u32 rate;
3505 /*
3506 * We have to set up the TX command, the TX Beacon command, and the
3507 * beacon contents.
3508 */
3509
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003510 lockdep_assert_held(&il->mutex);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003511
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003512 if (!il->beacon_ctx) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003513 IL_ERR("trying to build beacon w/o beacon context!\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003514 return 0;
3515 }
3516
3517 /* Initialize memory */
3518 tx_beacon_cmd = &frame->u.beacon;
3519 memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd));
3520
3521 /* Set up TX beacon contents */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003522 frame_size =
3523 il4965_fill_beacon_frame(il, tx_beacon_cmd->frame,
3524 sizeof(frame->u) - sizeof(*tx_beacon_cmd));
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003525 if (WARN_ON_ONCE(frame_size > MAX_MPDU_SIZE))
3526 return 0;
3527 if (!frame_size)
3528 return 0;
3529
3530 /* Set up TX command fields */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003531 tx_beacon_cmd->tx.len = cpu_to_le16((u16) frame_size);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003532 tx_beacon_cmd->tx.sta_id = il->beacon_ctx->bcast_sta_id;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003533 tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003534 tx_beacon_cmd->tx.tx_flags =
3535 TX_CMD_FLG_SEQ_CTL_MSK | TX_CMD_FLG_TSF_MSK |
3536 TX_CMD_FLG_STA_RATE_MSK;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003537
3538 /* Set up TX beacon command fields */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003539 il4965_set_beacon_tim(il, tx_beacon_cmd, (u8 *) tx_beacon_cmd->frame,
3540 frame_size);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003541
3542 /* Set up packet rate and flags */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003543 rate = il_get_lowest_plcp(il, il->beacon_ctx);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003544 il->mgmt_tx_ant =
3545 il4965_toggle_tx_ant(il, il->mgmt_tx_ant,
3546 il->hw_params.valid_tx_ant);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003547 rate_flags = il4965_ant_idx_to_flags(il->mgmt_tx_ant);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003548 if ((rate >= IL_FIRST_CCK_RATE) && (rate <= IL_LAST_CCK_RATE))
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003549 rate_flags |= RATE_MCS_CCK_MSK;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003550 tx_beacon_cmd->tx.rate_n_flags =
3551 il4965_hw_set_rate_n_flags(rate, rate_flags);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003552
3553 return sizeof(*tx_beacon_cmd) + frame_size;
3554}
3555
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003556int
3557il4965_send_beacon_cmd(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003558{
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003559 struct il_frame *frame;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003560 unsigned int frame_size;
3561 int rc;
3562
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003563 frame = il4965_get_free_frame(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003564 if (!frame) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003565 IL_ERR("Could not obtain free frame buffer for beacon "
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003566 "command.\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003567 return -ENOMEM;
3568 }
3569
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003570 frame_size = il4965_hw_get_beacon_cmd(il, frame);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003571 if (!frame_size) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003572 IL_ERR("Error configuring the beacon command\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003573 il4965_free_frame(il, frame);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003574 return -EINVAL;
3575 }
3576
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003577 rc = il_send_cmd_pdu(il, C_TX_BEACON, frame_size, &frame->u.cmd[0]);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003578
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003579 il4965_free_frame(il, frame);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003580
3581 return rc;
3582}
3583
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003584static inline dma_addr_t
3585il4965_tfd_tb_get_addr(struct il_tfd *tfd, u8 idx)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003586{
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003587 struct il_tfd_tb *tb = &tfd->tbs[idx];
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003588
3589 dma_addr_t addr = get_unaligned_le32(&tb->lo);
3590 if (sizeof(dma_addr_t) > sizeof(u32))
3591 addr |=
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003592 ((dma_addr_t) (le16_to_cpu(tb->hi_n_len) & 0xF) << 16) <<
3593 16;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003594
3595 return addr;
3596}
3597
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003598static inline u16
3599il4965_tfd_tb_get_len(struct il_tfd *tfd, u8 idx)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003600{
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003601 struct il_tfd_tb *tb = &tfd->tbs[idx];
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003602
3603 return le16_to_cpu(tb->hi_n_len) >> 4;
3604}
3605
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003606static inline void
3607il4965_tfd_set_tb(struct il_tfd *tfd, u8 idx, dma_addr_t addr, u16 len)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003608{
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003609 struct il_tfd_tb *tb = &tfd->tbs[idx];
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003610 u16 hi_n_len = len << 4;
3611
3612 put_unaligned_le32(addr, &tb->lo);
3613 if (sizeof(dma_addr_t) > sizeof(u32))
3614 hi_n_len |= ((addr >> 16) >> 16) & 0xF;
3615
3616 tb->hi_n_len = cpu_to_le16(hi_n_len);
3617
3618 tfd->num_tbs = idx + 1;
3619}
3620
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003621static inline u8
3622il4965_tfd_get_num_tbs(struct il_tfd *tfd)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003623{
3624 return tfd->num_tbs & 0x1f;
3625}
3626
3627/**
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003628 * il4965_hw_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr]
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003629 * @il - driver ilate data
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003630 * @txq - tx queue
3631 *
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +01003632 * Does NOT advance any TFD circular buffer read/write idxes
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003633 * Does NOT free the TFD itself (which is within circular buffer)
3634 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003635void
3636il4965_hw_txq_free_tfd(struct il_priv *il, struct il_tx_queue *txq)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003637{
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003638 struct il_tfd *tfd_tmp = (struct il_tfd *)txq->tfds;
3639 struct il_tfd *tfd;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003640 struct pci_dev *dev = il->pci_dev;
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +01003641 int idx = txq->q.read_ptr;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003642 int i;
3643 int num_tbs;
3644
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +01003645 tfd = &tfd_tmp[idx];
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003646
3647 /* Sanity check on number of chunks */
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003648 num_tbs = il4965_tfd_get_num_tbs(tfd);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003649
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003650 if (num_tbs >= IL_NUM_OF_TBS) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003651 IL_ERR("Too many chunks: %i\n", num_tbs);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003652 /* @todo issue fatal error, it is quite serious situation */
3653 return;
3654 }
3655
3656 /* Unmap tx_cmd */
3657 if (num_tbs)
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003658 pci_unmap_single(dev, dma_unmap_addr(&txq->meta[idx], mapping),
3659 dma_unmap_len(&txq->meta[idx], len),
3660 PCI_DMA_BIDIRECTIONAL);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003661
3662 /* Unmap chunks, if any. */
3663 for (i = 1; i < num_tbs; i++)
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003664 pci_unmap_single(dev, il4965_tfd_tb_get_addr(tfd, i),
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003665 il4965_tfd_tb_get_len(tfd, i),
3666 PCI_DMA_TODEVICE);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003667
3668 /* free SKB */
3669 if (txq->txb) {
3670 struct sk_buff *skb;
3671
3672 skb = txq->txb[txq->q.read_ptr].skb;
3673
3674 /* can be called from irqs-disabled context */
3675 if (skb) {
3676 dev_kfree_skb_any(skb);
3677 txq->txb[txq->q.read_ptr].skb = NULL;
3678 }
3679 }
3680}
3681
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003682int
3683il4965_hw_txq_attach_buf_to_tfd(struct il_priv *il, struct il_tx_queue *txq,
3684 dma_addr_t addr, u16 len, u8 reset, u8 pad)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003685{
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003686 struct il_queue *q;
3687 struct il_tfd *tfd, *tfd_tmp;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003688 u32 num_tbs;
3689
3690 q = &txq->q;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003691 tfd_tmp = (struct il_tfd *)txq->tfds;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003692 tfd = &tfd_tmp[q->write_ptr];
3693
3694 if (reset)
3695 memset(tfd, 0, sizeof(*tfd));
3696
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003697 num_tbs = il4965_tfd_get_num_tbs(tfd);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003698
3699 /* Each TFD can point to a maximum 20 Tx buffers */
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003700 if (num_tbs >= IL_NUM_OF_TBS) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003701 IL_ERR("Error can not send more than %d chunks\n",
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003702 IL_NUM_OF_TBS);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003703 return -EINVAL;
3704 }
3705
3706 BUG_ON(addr & ~DMA_BIT_MASK(36));
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003707 if (unlikely(addr & ~IL_TX_DMA_MASK))
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003708 IL_ERR("Unaligned address = %llx\n", (unsigned long long)addr);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003709
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003710 il4965_tfd_set_tb(tfd, num_tbs, addr, len);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003711
3712 return 0;
3713}
3714
3715/*
3716 * Tell nic where to find circular buffer of Tx Frame Descriptors for
3717 * given Tx queue, and enable the DMA channel used for that queue.
3718 *
3719 * 4965 supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA
3720 * channels supported in hardware.
3721 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003722int
3723il4965_hw_tx_queue_init(struct il_priv *il, struct il_tx_queue *txq)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003724{
3725 int txq_id = txq->q.id;
3726
3727 /* Circular buffer (TFD queue in DRAM) physical base address */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003728 il_wr(il, FH49_MEM_CBBC_QUEUE(txq_id), txq->q.dma_addr >> 8);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003729
3730 return 0;
3731}
3732
3733/******************************************************************************
3734 *
3735 * Generic RX handler implementations
3736 *
3737 ******************************************************************************/
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003738static void
3739il4965_hdl_alive(struct il_priv *il, struct il_rx_buf *rxb)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003740{
Stanislaw Gruszkadcae1c62011-08-26 14:36:21 +02003741 struct il_rx_pkt *pkt = rxb_addr(rxb);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003742 struct il_alive_resp *palive;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003743 struct delayed_work *pwork;
3744
3745 palive = &pkt->u.alive_frame;
3746
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003747 D_INFO("Alive ucode status 0x%08X revision " "0x%01X 0x%01X\n",
3748 palive->is_valid, palive->ver_type, palive->ver_subtype);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003749
3750 if (palive->ver_subtype == INITIALIZE_SUBTYPE) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003751 D_INFO("Initialization Alive received.\n");
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003752 memcpy(&il->card_alive_init, &pkt->u.alive_frame,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003753 sizeof(struct il_init_alive_resp));
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003754 pwork = &il->init_alive_start;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003755 } else {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003756 D_INFO("Runtime Alive received.\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003757 memcpy(&il->card_alive, &pkt->u.alive_frame,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003758 sizeof(struct il_alive_resp));
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003759 pwork = &il->alive_start;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003760 }
3761
3762 /* We delay the ALIVE response by 5ms to
3763 * give the HW RF Kill time to activate... */
3764 if (palive->is_valid == UCODE_VALID_OK)
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003765 queue_delayed_work(il->workqueue, pwork, msecs_to_jiffies(5));
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003766 else
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003767 IL_WARN("uCode did not respond OK.\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003768}
3769
3770/**
Stanislaw Gruszkaebf0d902011-08-26 15:43:47 +02003771 * il4965_bg_stats_periodic - Timer callback to queue stats
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003772 *
Stanislaw Gruszkaebf0d902011-08-26 15:43:47 +02003773 * This callback is provided in order to send a stats request.
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003774 *
3775 * This timer function is continually reset to execute within
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +02003776 * REG_RECALIB_PERIOD seconds since the last N_STATS
Stanislaw Gruszkaebf0d902011-08-26 15:43:47 +02003777 * was received. We need to ensure we receive the stats in order
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003778 * to update the temperature used for calibrating the TXPOWER.
3779 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003780static void
3781il4965_bg_stats_periodic(unsigned long data)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003782{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003783 struct il_priv *il = (struct il_priv *)data;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003784
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01003785 if (test_bit(S_EXIT_PENDING, &il->status))
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003786 return;
3787
3788 /* dont send host command if rf-kill is on */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003789 if (!il_is_ready_rf(il))
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003790 return;
3791
Stanislaw Gruszkaebf0d902011-08-26 15:43:47 +02003792 il_send_stats_request(il, CMD_ASYNC, false);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003793}
3794
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003795static void
3796il4965_hdl_beacon(struct il_priv *il, struct il_rx_buf *rxb)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003797{
Stanislaw Gruszkadcae1c62011-08-26 14:36:21 +02003798 struct il_rx_pkt *pkt = rxb_addr(rxb);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003799 struct il4965_beacon_notif *beacon =
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003800 (struct il4965_beacon_notif *)pkt->u.raw;
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01003801#ifdef CONFIG_IWLEGACY_DEBUG
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003802 u8 rate = il4965_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003803
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003804 D_RX("beacon status %x retries %d iss %d " "tsf %d %d rate %d\n",
3805 le32_to_cpu(beacon->beacon_notify_hdr.u.status) & TX_STATUS_MSK,
3806 beacon->beacon_notify_hdr.failure_frame,
3807 le32_to_cpu(beacon->ibss_mgr_status),
3808 le32_to_cpu(beacon->high_tsf), le32_to_cpu(beacon->low_tsf), rate);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003809#endif
3810
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003811 il->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003812}
3813
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003814static void
3815il4965_perform_ct_kill_task(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003816{
3817 unsigned long flags;
3818
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003819 D_POWER("Stop all queues\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003820
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003821 if (il->mac80211_registered)
3822 ieee80211_stop_queues(il->hw);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003823
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02003824 _il_wr(il, CSR_UCODE_DRV_GP1_SET,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003825 CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02003826 _il_rd(il, CSR_UCODE_DRV_GP1);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003827
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003828 spin_lock_irqsave(&il->reg_lock, flags);
Stanislaw Gruszka13882262011-08-24 15:39:23 +02003829 if (!_il_grab_nic_access(il))
3830 _il_release_nic_access(il);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003831 spin_unlock_irqrestore(&il->reg_lock, flags);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003832}
3833
3834/* Handle notification from uCode that card's power state is changing
3835 * due to software, hardware, or critical temperature RFKILL */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003836static void
3837il4965_hdl_card_state(struct il_priv *il, struct il_rx_buf *rxb)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003838{
Stanislaw Gruszkadcae1c62011-08-26 14:36:21 +02003839 struct il_rx_pkt *pkt = rxb_addr(rxb);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003840 u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003841 unsigned long status = il->status;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003842
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003843 D_RF_KILL("Card state received: HW:%s SW:%s CT:%s\n",
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003844 (flags & HW_CARD_DISABLED) ? "Kill" : "On",
3845 (flags & SW_CARD_DISABLED) ? "Kill" : "On",
3846 (flags & CT_CARD_DISABLED) ? "Reached" : "Not reached");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003847
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003848 if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED | CT_CARD_DISABLED)) {
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003849
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02003850 _il_wr(il, CSR_UCODE_DRV_GP1_SET,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003851 CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003852
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003853 il_wr(il, HBUS_TARG_MBX_C, HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003854
3855 if (!(flags & RXON_CARD_DISABLED)) {
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02003856 _il_wr(il, CSR_UCODE_DRV_GP1_CLR,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003857 CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
Stanislaw Gruszka0c1a94e2011-08-24 17:37:16 +02003858 il_wr(il, HBUS_TARG_MBX_C,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003859 HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003860 }
3861 }
3862
3863 if (flags & CT_CARD_DISABLED)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003864 il4965_perform_ct_kill_task(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003865
3866 if (flags & HW_CARD_DISABLED)
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01003867 set_bit(S_RF_KILL_HW, &il->status);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003868 else
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01003869 clear_bit(S_RF_KILL_HW, &il->status);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003870
3871 if (!(flags & RXON_CARD_DISABLED))
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003872 il_scan_cancel(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003873
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01003874 if ((test_bit(S_RF_KILL_HW, &status) !=
3875 test_bit(S_RF_KILL_HW, &il->status)))
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003876 wiphy_rfkill_set_hw_state(il->hw->wiphy,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003877 test_bit(S_RF_KILL_HW, &il->status));
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003878 else
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003879 wake_up(&il->wait_command_queue);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003880}
3881
3882/**
Stanislaw Gruszkad0c72342011-08-30 15:39:42 +02003883 * il4965_setup_handlers - Initialize Rx handler callbacks
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003884 *
3885 * Setup the RX handlers for each of the reply types sent from the uCode
3886 * to the host.
3887 *
3888 * This function chains into the hardware specific files for them to setup
3889 * any hardware specific handlers as well.
3890 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003891static void
3892il4965_setup_handlers(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003893{
Stanislaw Gruszka6e9848b42011-08-30 15:45:31 +02003894 il->handlers[N_ALIVE] = il4965_hdl_alive;
3895 il->handlers[N_ERROR] = il_hdl_error;
Stanislaw Gruszkad2dfb332011-11-15 13:16:38 +01003896 il->handlers[N_CHANNEL_SWITCH] = il_hdl_csa;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003897 il->handlers[N_SPECTRUM_MEASUREMENT] = il_hdl_spectrum_measurement;
Stanislaw Gruszkad2dfb332011-11-15 13:16:38 +01003898 il->handlers[N_PM_SLEEP] = il_hdl_pm_sleep;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003899 il->handlers[N_PM_DEBUG_STATS] = il_hdl_pm_debug_stats;
Stanislaw Gruszkad2dfb332011-11-15 13:16:38 +01003900 il->handlers[N_BEACON] = il4965_hdl_beacon;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003901
3902 /*
3903 * The same handler is used for both the REPLY to a discrete
Stanislaw Gruszkaebf0d902011-08-26 15:43:47 +02003904 * stats request from the host as well as for the periodic
3905 * stats notifications (after received beacons) from the uCode.
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003906 */
Stanislaw Gruszkad2dfb332011-11-15 13:16:38 +01003907 il->handlers[C_STATS] = il4965_hdl_c_stats;
3908 il->handlers[N_STATS] = il4965_hdl_stats;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003909
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003910 il_setup_rx_scan_handlers(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003911
3912 /* status change handler */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003913 il->handlers[N_CARD_STATE] = il4965_hdl_card_state;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003914
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003915 il->handlers[N_MISSED_BEACONS] = il4965_hdl_missed_beacon;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003916 /* Rx handlers */
Stanislaw Gruszka6e9848b42011-08-30 15:45:31 +02003917 il->handlers[N_RX_PHY] = il4965_hdl_rx_phy;
3918 il->handlers[N_RX_MPDU] = il4965_hdl_rx;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003919 /* block ack */
Stanislaw Gruszka6e9848b42011-08-30 15:45:31 +02003920 il->handlers[N_COMPRESSED_BA] = il4965_hdl_compressed_ba;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003921 /* Set up hardware specific Rx handlers */
Stanislaw Gruszkad0c72342011-08-30 15:39:42 +02003922 il->cfg->ops->lib->handler_setup(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003923}
3924
3925/**
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003926 * il4965_rx_handle - Main entry function for receiving responses from uCode
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003927 *
Stanislaw Gruszkad0c72342011-08-30 15:39:42 +02003928 * Uses the il->handlers callback function array to invoke
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003929 * the appropriate handlers, including command responses,
3930 * frame-received notifications, and other notifications.
3931 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003932void
3933il4965_rx_handle(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003934{
Stanislaw Gruszkab73bb5f2011-08-26 14:37:54 +02003935 struct il_rx_buf *rxb;
Stanislaw Gruszkadcae1c62011-08-26 14:36:21 +02003936 struct il_rx_pkt *pkt;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003937 struct il_rx_queue *rxq = &il->rxq;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003938 u32 r, i;
3939 int reclaim;
3940 unsigned long flags;
3941 u8 fill_rx = 0;
3942 u32 count = 8;
3943 int total_empty;
3944
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +01003945 /* uCode's read idx (stored in shared DRAM) indicates the last Rx
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003946 * buffer that the driver may process (last buffer filled by ucode). */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003947 r = le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003948 i = rxq->read;
3949
3950 /* Rx interrupt, but nothing sent from uCode */
3951 if (i == r)
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003952 D_RX("r = %d, i = %d\n", r, i);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003953
3954 /* calculate total frames need to be restock after handling RX */
3955 total_empty = r - rxq->write_actual;
3956 if (total_empty < 0)
3957 total_empty += RX_QUEUE_SIZE;
3958
3959 if (total_empty > (RX_QUEUE_SIZE / 2))
3960 fill_rx = 1;
3961
3962 while (i != r) {
3963 int len;
3964
3965 rxb = rxq->queue[i];
3966
3967 /* If an RXB doesn't have a Rx queue slot associated with it,
3968 * then a bug has been introduced in the queue refilling
3969 * routines -- catch it here */
3970 BUG_ON(rxb == NULL);
3971
3972 rxq->queue[i] = NULL;
3973
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003974 pci_unmap_page(il->pci_dev, rxb->page_dma,
3975 PAGE_SIZE << il->hw_params.rx_page_order,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003976 PCI_DMA_FROMDEVICE);
3977 pkt = rxb_addr(rxb);
3978
Stanislaw Gruszkae94a4092011-08-31 13:23:20 +02003979 len = le32_to_cpu(pkt->len_n_flags) & IL_RX_FRAME_SIZE_MSK;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003980 len += sizeof(u32); /* account for status word */
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003981
3982 /* Reclaim a command buffer only if this packet is a response
3983 * to a (driver-originated) command.
3984 * If the packet (e.g. Rx frame) originated from uCode,
3985 * there is no command buffer to reclaim.
3986 * Ucode should set SEQ_RX_FRAME bit if ucode-originated,
3987 * but apparently a few don't get set; catch them here. */
3988 reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) &&
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003989 (pkt->hdr.cmd != N_RX_PHY) && (pkt->hdr.cmd != N_RX) &&
3990 (pkt->hdr.cmd != N_RX_MPDU) &&
3991 (pkt->hdr.cmd != N_COMPRESSED_BA) &&
3992 (pkt->hdr.cmd != N_STATS) && (pkt->hdr.cmd != C_TX);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003993
3994 /* Based on type of command response or notification,
3995 * handle those that need handling via function in
Stanislaw Gruszkad0c72342011-08-30 15:39:42 +02003996 * handlers table. See il4965_setup_handlers() */
3997 if (il->handlers[pkt->hdr.cmd]) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003998 D_RX("r = %d, i = %d, %s, 0x%02x\n", r, i,
3999 il_get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
Stanislaw Gruszkad0c72342011-08-30 15:39:42 +02004000 il->isr_stats.handlers[pkt->hdr.cmd]++;
4001 il->handlers[pkt->hdr.cmd] (il, rxb);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004002 } else {
4003 /* No handling needed */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004004 D_RX("r %d i %d No handler needed for %s, 0x%02x\n", r,
4005 i, il_get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004006 }
4007
4008 /*
4009 * XXX: After here, we should always check rxb->page
4010 * against NULL before touching it or its virtual
Stanislaw Gruszkad0c72342011-08-30 15:39:42 +02004011 * memory (pkt). Because some handler might have
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004012 * already taken or freed the pages.
4013 */
4014
4015 if (reclaim) {
4016 /* Invoke any callbacks, transfer the buffer to caller,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02004017 * and fire off the (possibly) blocking il_send_cmd()
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004018 * as we reclaim the driver command queue */
4019 if (rxb->page)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004020 il_tx_cmd_complete(il, rxb);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004021 else
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02004022 IL_WARN("Claim null rxb?\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004023 }
4024
4025 /* Reuse the page if possible. For notification packets and
4026 * SKBs that fail to Rx correctly, add them back into the
4027 * rx_free list for reuse later. */
4028 spin_lock_irqsave(&rxq->lock, flags);
4029 if (rxb->page != NULL) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004030 rxb->page_dma =
4031 pci_map_page(il->pci_dev, rxb->page, 0,
4032 PAGE_SIZE << il->hw_params.
4033 rx_page_order, PCI_DMA_FROMDEVICE);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004034 list_add_tail(&rxb->list, &rxq->rx_free);
4035 rxq->free_count++;
4036 } else
4037 list_add_tail(&rxb->list, &rxq->rx_used);
4038
4039 spin_unlock_irqrestore(&rxq->lock, flags);
4040
4041 i = (i + 1) & RX_QUEUE_MASK;
4042 /* If there are a lot of unused frames,
4043 * restock the Rx queue so ucode wont assert. */
4044 if (fill_rx) {
4045 count++;
4046 if (count >= 8) {
4047 rxq->read = i;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004048 il4965_rx_replenish_now(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004049 count = 0;
4050 }
4051 }
4052 }
4053
4054 /* Backtrack one entry */
4055 rxq->read = i;
4056 if (fill_rx)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004057 il4965_rx_replenish_now(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004058 else
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004059 il4965_rx_queue_restock(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004060}
4061
4062/* call this function to flush any scheduled tasklet */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004063static inline void
4064il4965_synchronize_irq(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004065{
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004066 /* wait to make sure we flush pending tasklet */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004067 synchronize_irq(il->pci_dev->irq);
4068 tasklet_kill(&il->irq_tasklet);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004069}
4070
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004071static void
4072il4965_irq_tasklet(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004073{
4074 u32 inta, handled = 0;
4075 u32 inta_fh;
4076 unsigned long flags;
4077 u32 i;
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01004078#ifdef CONFIG_IWLEGACY_DEBUG
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004079 u32 inta_mask;
4080#endif
4081
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004082 spin_lock_irqsave(&il->lock, flags);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004083
4084 /* Ack/clear/reset pending uCode interrupts.
4085 * Note: Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS,
4086 * and will clear only when CSR_FH_INT_STATUS gets cleared. */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02004087 inta = _il_rd(il, CSR_INT);
4088 _il_wr(il, CSR_INT, inta);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004089
4090 /* Ack/clear/reset pending flow-handler (DMA) interrupts.
4091 * Any new interrupts that happen after this, either while we're
4092 * in this tasklet, or later, will show up in next ISR/tasklet. */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02004093 inta_fh = _il_rd(il, CSR_FH_INT_STATUS);
4094 _il_wr(il, CSR_FH_INT_STATUS, inta_fh);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004095
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01004096#ifdef CONFIG_IWLEGACY_DEBUG
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004097 if (il_get_debug_level(il) & IL_DL_ISR) {
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004098 /* just for debug */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02004099 inta_mask = _il_rd(il, CSR_INT_MASK);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004100 D_ISR("inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", inta,
4101 inta_mask, inta_fh);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004102 }
4103#endif
4104
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004105 spin_unlock_irqrestore(&il->lock, flags);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004106
4107 /* Since CSR_INT and CSR_FH_INT_STATUS reads and clears are not
4108 * atomic, make sure that inta covers all the interrupts that
4109 * we've discovered, even if FH interrupt came in just after
4110 * reading CSR_INT. */
4111 if (inta_fh & CSR49_FH_INT_RX_MASK)
4112 inta |= CSR_INT_BIT_FH_RX;
4113 if (inta_fh & CSR49_FH_INT_TX_MASK)
4114 inta |= CSR_INT_BIT_FH_TX;
4115
4116 /* Now service all interrupt bits discovered above. */
4117 if (inta & CSR_INT_BIT_HW_ERR) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02004118 IL_ERR("Hardware error detected. Restarting.\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004119
4120 /* Tell the device to stop sending interrupts */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004121 il_disable_interrupts(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004122
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004123 il->isr_stats.hw++;
4124 il_irq_handle_error(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004125
4126 handled |= CSR_INT_BIT_HW_ERR;
4127
4128 return;
4129 }
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01004130#ifdef CONFIG_IWLEGACY_DEBUG
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004131 if (il_get_debug_level(il) & (IL_DL_ISR)) {
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004132 /* NIC fires this, but we don't use it, redundant with WAKEUP */
4133 if (inta & CSR_INT_BIT_SCD) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01004134 D_ISR("Scheduler finished to transmit "
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004135 "the frame/frames.\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004136 il->isr_stats.sch++;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004137 }
4138
4139 /* Alive notification via Rx interrupt will do the real work */
4140 if (inta & CSR_INT_BIT_ALIVE) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01004141 D_ISR("Alive interrupt\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004142 il->isr_stats.alive++;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004143 }
4144 }
4145#endif
4146 /* Safely ignore these bits for debug checks below */
4147 inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE);
4148
4149 /* HW RF KILL switch toggled */
4150 if (inta & CSR_INT_BIT_RF_KILL) {
4151 int hw_rf_kill = 0;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004152 if (!
4153 (_il_rd(il, CSR_GP_CNTRL) &
4154 CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004155 hw_rf_kill = 1;
4156
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02004157 IL_WARN("RF_KILL bit toggled to %s.\n",
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004158 hw_rf_kill ? "disable radio" : "enable radio");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004159
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004160 il->isr_stats.rfkill++;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004161
4162 /* driver only loads ucode once setting the interface up.
4163 * the driver allows loading the ucode even if the radio
4164 * is killed. Hence update the killswitch state here. The
4165 * rfkill handler will care about restarting if needed.
4166 */
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01004167 if (!test_bit(S_ALIVE, &il->status)) {
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004168 if (hw_rf_kill)
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01004169 set_bit(S_RF_KILL_HW, &il->status);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004170 else
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01004171 clear_bit(S_RF_KILL_HW, &il->status);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004172 wiphy_rfkill_set_hw_state(il->hw->wiphy, hw_rf_kill);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004173 }
4174
4175 handled |= CSR_INT_BIT_RF_KILL;
4176 }
4177
4178 /* Chip got too hot and stopped itself */
4179 if (inta & CSR_INT_BIT_CT_KILL) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02004180 IL_ERR("Microcode CT kill error detected.\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004181 il->isr_stats.ctkill++;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004182 handled |= CSR_INT_BIT_CT_KILL;
4183 }
4184
4185 /* Error detected by uCode */
4186 if (inta & CSR_INT_BIT_SW_ERR) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004187 IL_ERR("Microcode SW error detected. " " Restarting 0x%X.\n",
4188 inta);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004189 il->isr_stats.sw++;
4190 il_irq_handle_error(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004191 handled |= CSR_INT_BIT_SW_ERR;
4192 }
4193
4194 /*
4195 * uCode wakes up after power-down sleep.
4196 * Tell device about any new tx or host commands enqueued,
4197 * and about any Rx buffers made available while asleep.
4198 */
4199 if (inta & CSR_INT_BIT_WAKEUP) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01004200 D_ISR("Wakeup interrupt\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004201 il_rx_queue_update_write_ptr(il, &il->rxq);
4202 for (i = 0; i < il->hw_params.max_txq_num; i++)
4203 il_txq_update_write_ptr(il, &il->txq[i]);
4204 il->isr_stats.wakeup++;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004205 handled |= CSR_INT_BIT_WAKEUP;
4206 }
4207
4208 /* All uCode command responses, including Tx command responses,
4209 * Rx "responses" (frame-received notification), and other
4210 * notifications from uCode come through here*/
4211 if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004212 il4965_rx_handle(il);
4213 il->isr_stats.rx++;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004214 handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
4215 }
4216
4217 /* This "Tx" DMA channel is used only for loading uCode */
4218 if (inta & CSR_INT_BIT_FH_TX) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01004219 D_ISR("uCode load interrupt\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004220 il->isr_stats.tx++;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004221 handled |= CSR_INT_BIT_FH_TX;
4222 /* Wake up uCode load routine, now that load is complete */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004223 il->ucode_write_complete = 1;
4224 wake_up(&il->wait_command_queue);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004225 }
4226
4227 if (inta & ~handled) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02004228 IL_ERR("Unhandled INTA bits 0x%08x\n", inta & ~handled);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004229 il->isr_stats.unhandled++;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004230 }
4231
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004232 if (inta & ~(il->inta_mask)) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02004233 IL_WARN("Disabled INTA bits 0x%08x were pending\n",
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004234 inta & ~il->inta_mask);
Stanislaw Gruszka9a95b372011-08-31 14:20:23 +02004235 IL_WARN(" with FH49_INT = 0x%08x\n", inta_fh);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004236 }
4237
4238 /* Re-enable all interrupts */
Stanislaw Gruszka93fd74e2011-04-28 11:51:30 +02004239 /* only Re-enable if disabled by irq */
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01004240 if (test_bit(S_INT_ENABLED, &il->status))
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004241 il_enable_interrupts(il);
Stanislaw Gruszkaa078a1f2011-04-28 11:51:25 +02004242 /* Re-enable RF_KILL if it occurred */
4243 else if (handled & CSR_INT_BIT_RF_KILL)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004244 il_enable_rfkill_int(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004245
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01004246#ifdef CONFIG_IWLEGACY_DEBUG
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004247 if (il_get_debug_level(il) & (IL_DL_ISR)) {
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02004248 inta = _il_rd(il, CSR_INT);
4249 inta_mask = _il_rd(il, CSR_INT_MASK);
4250 inta_fh = _il_rd(il, CSR_FH_INT_STATUS);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004251 D_ISR("End inta 0x%08x, enabled 0x%08x, fh 0x%08x, "
4252 "flags 0x%08lx\n", inta, inta_mask, inta_fh, flags);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004253 }
4254#endif
4255}
4256
4257/*****************************************************************************
4258 *
4259 * sysfs attributes
4260 *
4261 *****************************************************************************/
4262
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01004263#ifdef CONFIG_IWLEGACY_DEBUG
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004264
4265/*
4266 * The following adds a new attribute to the sysfs representation
4267 * of this device driver (i.e. a new file in /sys/class/net/wlan0/device/)
4268 * used for controlling the debug level.
4269 *
4270 * See the level definitions in iwl for details.
4271 *
4272 * The debug_level being managed using sysfs below is a per device debug
4273 * level that is used instead of the global debug level if it (the per
4274 * device debug level) is set.
4275 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004276static ssize_t
4277il4965_show_debug_level(struct device *d, struct device_attribute *attr,
4278 char *buf)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004279{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004280 struct il_priv *il = dev_get_drvdata(d);
4281 return sprintf(buf, "0x%08X\n", il_get_debug_level(il));
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004282}
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004283
4284static ssize_t
4285il4965_store_debug_level(struct device *d, struct device_attribute *attr,
4286 const char *buf, size_t count)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004287{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004288 struct il_priv *il = dev_get_drvdata(d);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004289 unsigned long val;
4290 int ret;
4291
4292 ret = strict_strtoul(buf, 0, &val);
4293 if (ret)
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02004294 IL_ERR("%s is not in hex or decimal form.\n", buf);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004295 else {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004296 il->debug_level = val;
4297 if (il_alloc_traffic_mem(il))
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004298 IL_ERR("Not enough memory to generate traffic log\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004299 }
4300 return strnlen(buf, count);
4301}
4302
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004303static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO, il4965_show_debug_level,
4304 il4965_store_debug_level);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004305
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01004306#endif /* CONFIG_IWLEGACY_DEBUG */
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004307
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004308static ssize_t
4309il4965_show_temperature(struct device *d, struct device_attribute *attr,
4310 char *buf)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004311{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004312 struct il_priv *il = dev_get_drvdata(d);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004313
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004314 if (!il_is_alive(il))
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004315 return -EAGAIN;
4316
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004317 return sprintf(buf, "%d\n", il->temperature);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004318}
4319
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02004320static DEVICE_ATTR(temperature, S_IRUGO, il4965_show_temperature, NULL);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004321
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004322static ssize_t
4323il4965_show_tx_power(struct device *d, struct device_attribute *attr, char *buf)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004324{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004325 struct il_priv *il = dev_get_drvdata(d);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004326
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004327 if (!il_is_ready_rf(il))
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004328 return sprintf(buf, "off\n");
4329 else
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004330 return sprintf(buf, "%d\n", il->tx_power_user_lmt);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004331}
4332
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004333static ssize_t
4334il4965_store_tx_power(struct device *d, struct device_attribute *attr,
4335 const char *buf, size_t count)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004336{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004337 struct il_priv *il = dev_get_drvdata(d);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004338 unsigned long val;
4339 int ret;
4340
4341 ret = strict_strtoul(buf, 10, &val);
4342 if (ret)
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02004343 IL_INFO("%s is not in decimal form.\n", buf);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004344 else {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004345 ret = il_set_tx_power(il, val, false);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004346 if (ret)
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004347 IL_ERR("failed setting tx power (0x%d).\n", ret);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004348 else
4349 ret = count;
4350 }
4351 return ret;
4352}
4353
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004354static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, il4965_show_tx_power,
4355 il4965_store_tx_power);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004356
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02004357static struct attribute *il_sysfs_entries[] = {
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004358 &dev_attr_temperature.attr,
4359 &dev_attr_tx_power.attr,
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01004360#ifdef CONFIG_IWLEGACY_DEBUG
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004361 &dev_attr_debug_level.attr,
4362#endif
4363 NULL
4364};
4365
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02004366static struct attribute_group il_attribute_group = {
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004367 .name = NULL, /* put in device directory */
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02004368 .attrs = il_sysfs_entries,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004369};
4370
4371/******************************************************************************
4372 *
4373 * uCode download functions
4374 *
4375 ******************************************************************************/
4376
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004377static void
4378il4965_dealloc_ucode_pci(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004379{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004380 il_free_fw_desc(il->pci_dev, &il->ucode_code);
4381 il_free_fw_desc(il->pci_dev, &il->ucode_data);
4382 il_free_fw_desc(il->pci_dev, &il->ucode_data_backup);
4383 il_free_fw_desc(il->pci_dev, &il->ucode_init);
4384 il_free_fw_desc(il->pci_dev, &il->ucode_init_data);
4385 il_free_fw_desc(il->pci_dev, &il->ucode_boot);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004386}
4387
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004388static void
4389il4965_nic_start(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004390{
4391 /* Remove all resets to allow NIC to operate */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02004392 _il_wr(il, CSR_RESET, 0);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004393}
4394
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02004395static void il4965_ucode_callback(const struct firmware *ucode_raw,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004396 void *context);
4397static int il4965_mac_setup_register(struct il_priv *il, u32 max_probe_length);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004398
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004399static int __must_check
4400il4965_request_firmware(struct il_priv *il, bool first)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004401{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004402 const char *name_pre = il->cfg->fw_name_pre;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004403 char tag[8];
4404
4405 if (first) {
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +01004406 il->fw_idx = il->cfg->ucode_api_max;
4407 sprintf(tag, "%d", il->fw_idx);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004408 } else {
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +01004409 il->fw_idx--;
4410 sprintf(tag, "%d", il->fw_idx);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004411 }
4412
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +01004413 if (il->fw_idx < il->cfg->ucode_api_min) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02004414 IL_ERR("no suitable firmware found!\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004415 return -ENOENT;
4416 }
4417
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004418 sprintf(il->firmware_name, "%s%s%s", name_pre, tag, ".ucode");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004419
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004420 D_INFO("attempting to load firmware '%s'\n", il->firmware_name);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004421
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004422 return request_firmware_nowait(THIS_MODULE, 1, il->firmware_name,
4423 &il->pci_dev->dev, GFP_KERNEL, il,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02004424 il4965_ucode_callback);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004425}
4426
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02004427struct il4965_firmware_pieces {
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004428 const void *inst, *data, *init, *init_data, *boot;
4429 size_t inst_size, data_size, init_size, init_data_size, boot_size;
4430};
4431
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004432static int
4433il4965_load_firmware(struct il_priv *il, const struct firmware *ucode_raw,
4434 struct il4965_firmware_pieces *pieces)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004435{
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02004436 struct il_ucode_header *ucode = (void *)ucode_raw->data;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004437 u32 api_ver, hdr_size;
4438 const u8 *src;
4439
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004440 il->ucode_ver = le32_to_cpu(ucode->ver);
4441 api_ver = IL_UCODE_API(il->ucode_ver);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004442
4443 switch (api_ver) {
4444 default:
4445 case 0:
4446 case 1:
4447 case 2:
4448 hdr_size = 24;
4449 if (ucode_raw->size < hdr_size) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02004450 IL_ERR("File size too small!\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004451 return -EINVAL;
4452 }
4453 pieces->inst_size = le32_to_cpu(ucode->v1.inst_size);
4454 pieces->data_size = le32_to_cpu(ucode->v1.data_size);
4455 pieces->init_size = le32_to_cpu(ucode->v1.init_size);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004456 pieces->init_data_size = le32_to_cpu(ucode->v1.init_data_size);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004457 pieces->boot_size = le32_to_cpu(ucode->v1.boot_size);
4458 src = ucode->v1.data;
4459 break;
4460 }
4461
4462 /* Verify size of file vs. image size info in file's header */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004463 if (ucode_raw->size !=
4464 hdr_size + pieces->inst_size + pieces->data_size +
4465 pieces->init_size + pieces->init_data_size + pieces->boot_size) {
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004466
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004467 IL_ERR("uCode file size %d does not match expected size\n",
4468 (int)ucode_raw->size);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004469 return -EINVAL;
4470 }
4471
4472 pieces->inst = src;
4473 src += pieces->inst_size;
4474 pieces->data = src;
4475 src += pieces->data_size;
4476 pieces->init = src;
4477 src += pieces->init_size;
4478 pieces->init_data = src;
4479 src += pieces->init_data_size;
4480 pieces->boot = src;
4481 src += pieces->boot_size;
4482
4483 return 0;
4484}
4485
4486/**
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02004487 * il4965_ucode_callback - callback when firmware was loaded
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004488 *
4489 * If loaded successfully, copies the firmware into buffers
4490 * for the card to fetch (via DMA).
4491 */
4492static void
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02004493il4965_ucode_callback(const struct firmware *ucode_raw, void *context)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004494{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004495 struct il_priv *il = context;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02004496 struct il_ucode_header *ucode;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004497 int err;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02004498 struct il4965_firmware_pieces pieces;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004499 const unsigned int api_max = il->cfg->ucode_api_max;
4500 const unsigned int api_min = il->cfg->ucode_api_min;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004501 u32 api_ver;
4502
4503 u32 max_probe_length = 200;
4504 u32 standard_phy_calibration_size =
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004505 IL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004506
4507 memset(&pieces, 0, sizeof(pieces));
4508
4509 if (!ucode_raw) {
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +01004510 if (il->fw_idx <= il->cfg->ucode_api_max)
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004511 IL_ERR("request for firmware file '%s' failed.\n",
4512 il->firmware_name);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004513 goto try_again;
4514 }
4515
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004516 D_INFO("Loaded firmware file '%s' (%zd bytes).\n", il->firmware_name,
4517 ucode_raw->size);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004518
4519 /* Make sure that we got at least the API version number */
4520 if (ucode_raw->size < 4) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02004521 IL_ERR("File size way too small!\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004522 goto try_again;
4523 }
4524
4525 /* Data from ucode file: header followed by uCode images */
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02004526 ucode = (struct il_ucode_header *)ucode_raw->data;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004527
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004528 err = il4965_load_firmware(il, ucode_raw, &pieces);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004529
4530 if (err)
4531 goto try_again;
4532
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004533 api_ver = IL_UCODE_API(il->ucode_ver);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004534
4535 /*
4536 * api_ver should match the api version forming part of the
4537 * firmware filename ... but we don't check for that and only rely
4538 * on the API version read from firmware header from here on forward
4539 */
4540 if (api_ver < api_min || api_ver > api_max) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004541 IL_ERR("Driver unable to support your firmware API. "
4542 "Driver supports v%u, firmware is v%u.\n", api_max,
4543 api_ver);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004544 goto try_again;
4545 }
4546
4547 if (api_ver != api_max)
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004548 IL_ERR("Firmware has old API version. Expected v%u, "
4549 "got v%u. New firmware can be obtained "
4550 "from http://www.intellinuxwireless.org.\n", api_max,
4551 api_ver);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004552
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02004553 IL_INFO("loaded firmware version %u.%u.%u.%u\n",
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004554 IL_UCODE_MAJOR(il->ucode_ver), IL_UCODE_MINOR(il->ucode_ver),
4555 IL_UCODE_API(il->ucode_ver), IL_UCODE_SERIAL(il->ucode_ver));
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004556
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004557 snprintf(il->hw->wiphy->fw_version, sizeof(il->hw->wiphy->fw_version),
4558 "%u.%u.%u.%u", IL_UCODE_MAJOR(il->ucode_ver),
4559 IL_UCODE_MINOR(il->ucode_ver), IL_UCODE_API(il->ucode_ver),
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004560 IL_UCODE_SERIAL(il->ucode_ver));
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004561
4562 /*
4563 * For any of the failures below (before allocating pci memory)
4564 * we will try to load a version with a smaller API -- maybe the
4565 * user just got a corrupted version of the latest API.
4566 */
4567
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004568 D_INFO("f/w package hdr ucode version raw = 0x%x\n", il->ucode_ver);
4569 D_INFO("f/w package hdr runtime inst size = %Zd\n", pieces.inst_size);
4570 D_INFO("f/w package hdr runtime data size = %Zd\n", pieces.data_size);
4571 D_INFO("f/w package hdr init inst size = %Zd\n", pieces.init_size);
4572 D_INFO("f/w package hdr init data size = %Zd\n", pieces.init_data_size);
4573 D_INFO("f/w package hdr boot inst size = %Zd\n", pieces.boot_size);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004574
4575 /* Verify that uCode images will fit in card's SRAM */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004576 if (pieces.inst_size > il->hw_params.max_inst_size) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02004577 IL_ERR("uCode instr len %Zd too large to fit in\n",
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004578 pieces.inst_size);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004579 goto try_again;
4580 }
4581
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004582 if (pieces.data_size > il->hw_params.max_data_size) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02004583 IL_ERR("uCode data len %Zd too large to fit in\n",
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004584 pieces.data_size);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004585 goto try_again;
4586 }
4587
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004588 if (pieces.init_size > il->hw_params.max_inst_size) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02004589 IL_ERR("uCode init instr len %Zd too large to fit in\n",
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004590 pieces.init_size);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004591 goto try_again;
4592 }
4593
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004594 if (pieces.init_data_size > il->hw_params.max_data_size) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02004595 IL_ERR("uCode init data len %Zd too large to fit in\n",
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004596 pieces.init_data_size);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004597 goto try_again;
4598 }
4599
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004600 if (pieces.boot_size > il->hw_params.max_bsm_size) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02004601 IL_ERR("uCode boot instr len %Zd too large to fit in\n",
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004602 pieces.boot_size);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004603 goto try_again;
4604 }
4605
4606 /* Allocate ucode buffers for card's bus-master loading ... */
4607
4608 /* Runtime instructions and 2 copies of data:
4609 * 1) unmodified from disk
4610 * 2) backup cache for save/restore during power-downs */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004611 il->ucode_code.len = pieces.inst_size;
4612 il_alloc_fw_desc(il->pci_dev, &il->ucode_code);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004613
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004614 il->ucode_data.len = pieces.data_size;
4615 il_alloc_fw_desc(il->pci_dev, &il->ucode_data);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004616
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004617 il->ucode_data_backup.len = pieces.data_size;
4618 il_alloc_fw_desc(il->pci_dev, &il->ucode_data_backup);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004619
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004620 if (!il->ucode_code.v_addr || !il->ucode_data.v_addr ||
4621 !il->ucode_data_backup.v_addr)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004622 goto err_pci_alloc;
4623
4624 /* Initialization instructions and data */
4625 if (pieces.init_size && pieces.init_data_size) {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004626 il->ucode_init.len = pieces.init_size;
4627 il_alloc_fw_desc(il->pci_dev, &il->ucode_init);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004628
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004629 il->ucode_init_data.len = pieces.init_data_size;
4630 il_alloc_fw_desc(il->pci_dev, &il->ucode_init_data);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004631
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004632 if (!il->ucode_init.v_addr || !il->ucode_init_data.v_addr)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004633 goto err_pci_alloc;
4634 }
4635
4636 /* Bootstrap (instructions only, no data) */
4637 if (pieces.boot_size) {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004638 il->ucode_boot.len = pieces.boot_size;
4639 il_alloc_fw_desc(il->pci_dev, &il->ucode_boot);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004640
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004641 if (!il->ucode_boot.v_addr)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004642 goto err_pci_alloc;
4643 }
4644
4645 /* Now that we can no longer fail, copy information */
4646
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004647 il->sta_key_max_num = STA_KEY_MAX_NUM;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004648
4649 /* Copy images into buffers for card's bus-master reads ... */
4650
4651 /* Runtime instructions (first block of data in file) */
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01004652 D_INFO("Copying (but not loading) uCode instr len %Zd\n",
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004653 pieces.inst_size);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004654 memcpy(il->ucode_code.v_addr, pieces.inst, pieces.inst_size);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004655
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01004656 D_INFO("uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n",
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004657 il->ucode_code.v_addr, (u32) il->ucode_code.p_addr);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004658
4659 /*
4660 * Runtime data
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02004661 * NOTE: Copy into backup buffer will be done in il_up()
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004662 */
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01004663 D_INFO("Copying (but not loading) uCode data len %Zd\n",
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004664 pieces.data_size);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004665 memcpy(il->ucode_data.v_addr, pieces.data, pieces.data_size);
4666 memcpy(il->ucode_data_backup.v_addr, pieces.data, pieces.data_size);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004667
4668 /* Initialization instructions */
4669 if (pieces.init_size) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004670 D_INFO("Copying (but not loading) init instr len %Zd\n",
4671 pieces.init_size);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004672 memcpy(il->ucode_init.v_addr, pieces.init, pieces.init_size);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004673 }
4674
4675 /* Initialization data */
4676 if (pieces.init_data_size) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004677 D_INFO("Copying (but not loading) init data len %Zd\n",
4678 pieces.init_data_size);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004679 memcpy(il->ucode_init_data.v_addr, pieces.init_data,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004680 pieces.init_data_size);
4681 }
4682
4683 /* Bootstrap instructions */
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01004684 D_INFO("Copying (but not loading) boot instr len %Zd\n",
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004685 pieces.boot_size);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004686 memcpy(il->ucode_boot.v_addr, pieces.boot, pieces.boot_size);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004687
4688 /*
4689 * figure out the offset of chain noise reset and gain commands
4690 * base on the size of standard phy calibration commands table size
4691 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004692 il->_4965.phy_calib_chain_noise_reset_cmd =
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004693 standard_phy_calibration_size;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004694 il->_4965.phy_calib_chain_noise_gain_cmd =
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004695 standard_phy_calibration_size + 1;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004696
4697 /**************************************************
4698 * This is still part of probe() in a sense...
4699 *
4700 * 9. Setup and register with mac80211 and debugfs
4701 **************************************************/
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004702 err = il4965_mac_setup_register(il, max_probe_length);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004703 if (err)
4704 goto out_unbind;
4705
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004706 err = il_dbgfs_register(il, DRV_NAME);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004707 if (err)
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004708 IL_ERR("failed to create debugfs files. Ignoring error: %d\n",
4709 err);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004710
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004711 err = sysfs_create_group(&il->pci_dev->dev.kobj, &il_attribute_group);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004712 if (err) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02004713 IL_ERR("failed to create sysfs device attributes\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004714 goto out_unbind;
4715 }
4716
4717 /* We have our copies now, allow OS release its copies */
4718 release_firmware(ucode_raw);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004719 complete(&il->_4965.firmware_loading_complete);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004720 return;
4721
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004722try_again:
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004723 /* try next, if any */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004724 if (il4965_request_firmware(il, false))
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004725 goto out_unbind;
4726 release_firmware(ucode_raw);
4727 return;
4728
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004729err_pci_alloc:
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02004730 IL_ERR("failed to allocate pci memory\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004731 il4965_dealloc_ucode_pci(il);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004732out_unbind:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004733 complete(&il->_4965.firmware_loading_complete);
4734 device_release_driver(&il->pci_dev->dev);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004735 release_firmware(ucode_raw);
4736}
4737
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004738static const char *const desc_lookup_text[] = {
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004739 "OK",
4740 "FAIL",
4741 "BAD_PARAM",
4742 "BAD_CHECKSUM",
4743 "NMI_INTERRUPT_WDG",
4744 "SYSASSERT",
4745 "FATAL_ERROR",
4746 "BAD_COMMAND",
4747 "HW_ERROR_TUNE_LOCK",
4748 "HW_ERROR_TEMPERATURE",
4749 "ILLEGAL_CHAN_FREQ",
Stanislaw Gruszka3b98c7f2011-08-26 16:29:35 +02004750 "VCC_NOT_STBL",
Stanislaw Gruszka9a95b372011-08-31 14:20:23 +02004751 "FH49_ERROR",
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004752 "NMI_INTERRUPT_HOST",
4753 "NMI_INTERRUPT_ACTION_PT",
4754 "NMI_INTERRUPT_UNKNOWN",
4755 "UCODE_VERSION_MISMATCH",
4756 "HW_ERROR_ABS_LOCK",
4757 "HW_ERROR_CAL_LOCK_FAIL",
4758 "NMI_INTERRUPT_INST_ACTION_PT",
4759 "NMI_INTERRUPT_DATA_ACTION_PT",
4760 "NMI_TRM_HW_ER",
4761 "NMI_INTERRUPT_TRM",
Joe Perches861d9c32011-07-08 23:20:24 -07004762 "NMI_INTERRUPT_BREAK_POINT",
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004763 "DEBUG_0",
4764 "DEBUG_1",
4765 "DEBUG_2",
4766 "DEBUG_3",
4767};
4768
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004769static struct {
4770 char *name;
4771 u8 num;
4772} advanced_lookup[] = {
4773 {
4774 "NMI_INTERRUPT_WDG", 0x34}, {
4775 "SYSASSERT", 0x35}, {
4776 "UCODE_VERSION_MISMATCH", 0x37}, {
4777 "BAD_COMMAND", 0x38}, {
4778 "NMI_INTERRUPT_DATA_ACTION_PT", 0x3C}, {
4779 "FATAL_ERROR", 0x3D}, {
4780 "NMI_TRM_HW_ERR", 0x46}, {
4781 "NMI_INTERRUPT_TRM", 0x4C}, {
4782 "NMI_INTERRUPT_BREAK_POINT", 0x54}, {
4783 "NMI_INTERRUPT_WDG_RXF_FULL", 0x5C}, {
4784 "NMI_INTERRUPT_WDG_NO_RBD_RXF_FULL", 0x64}, {
4785 "NMI_INTERRUPT_HOST", 0x66}, {
4786 "NMI_INTERRUPT_ACTION_PT", 0x7C}, {
4787 "NMI_INTERRUPT_UNKNOWN", 0x84}, {
4788 "NMI_INTERRUPT_INST_ACTION_PT", 0x86}, {
4789"ADVANCED_SYSASSERT", 0},};
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004790
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004791static const char *
4792il4965_desc_lookup(u32 num)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004793{
4794 int i;
4795 int max = ARRAY_SIZE(desc_lookup_text);
4796
4797 if (num < max)
4798 return desc_lookup_text[num];
4799
4800 max = ARRAY_SIZE(advanced_lookup) - 1;
4801 for (i = 0; i < max; i++) {
4802 if (advanced_lookup[i].num == num)
4803 break;
4804 }
4805 return advanced_lookup[i].name;
4806}
4807
4808#define ERROR_START_OFFSET (1 * sizeof(u32))
4809#define ERROR_ELEM_SIZE (7 * sizeof(u32))
4810
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004811void
4812il4965_dump_nic_error_log(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004813{
4814 u32 data2, line;
4815 u32 desc, time, count, base, data1;
4816 u32 blink1, blink2, ilink1, ilink2;
4817 u32 pc, hcmd;
4818
Stanislaw Gruszka1722f8e2011-11-15 14:51:01 +01004819 if (il->ucode_type == UCODE_INIT)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004820 base = le32_to_cpu(il->card_alive_init.error_event_table_ptr);
Stanislaw Gruszka1722f8e2011-11-15 14:51:01 +01004821 else
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004822 base = le32_to_cpu(il->card_alive.error_event_table_ptr);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004823
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004824 if (!il->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004825 IL_ERR("Not valid error log pointer 0x%08X for %s uCode\n",
4826 base, (il->ucode_type == UCODE_INIT) ? "Init" : "RT");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004827 return;
4828 }
4829
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004830 count = il_read_targ_mem(il, base);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004831
4832 if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02004833 IL_ERR("Start IWL Error Log Dump:\n");
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004834 IL_ERR("Status: 0x%08lX, count: %d\n", il->status, count);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004835 }
4836
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004837 desc = il_read_targ_mem(il, base + 1 * sizeof(u32));
4838 il->isr_stats.err_code = desc;
4839 pc = il_read_targ_mem(il, base + 2 * sizeof(u32));
4840 blink1 = il_read_targ_mem(il, base + 3 * sizeof(u32));
4841 blink2 = il_read_targ_mem(il, base + 4 * sizeof(u32));
4842 ilink1 = il_read_targ_mem(il, base + 5 * sizeof(u32));
4843 ilink2 = il_read_targ_mem(il, base + 6 * sizeof(u32));
4844 data1 = il_read_targ_mem(il, base + 7 * sizeof(u32));
4845 data2 = il_read_targ_mem(il, base + 8 * sizeof(u32));
4846 line = il_read_targ_mem(il, base + 9 * sizeof(u32));
4847 time = il_read_targ_mem(il, base + 11 * sizeof(u32));
4848 hcmd = il_read_targ_mem(il, base + 22 * sizeof(u32));
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004849
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02004850 IL_ERR("Desc Time "
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004851 "data1 data2 line\n");
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02004852 IL_ERR("%-28s (0x%04X) %010u 0x%08X 0x%08X %u\n",
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004853 il4965_desc_lookup(desc), desc, time, data1, data2, line);
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02004854 IL_ERR("pc blink1 blink2 ilink1 ilink2 hcmd\n");
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004855 IL_ERR("0x%05X 0x%05X 0x%05X 0x%05X 0x%05X 0x%05X\n", pc, blink1,
4856 blink2, ilink1, ilink2, hcmd);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004857}
4858
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004859static void
4860il4965_rf_kill_ct_config(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004861{
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02004862 struct il_ct_kill_config cmd;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004863 unsigned long flags;
4864 int ret = 0;
4865
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004866 spin_lock_irqsave(&il->lock, flags);
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02004867 _il_wr(il, CSR_UCODE_DRV_GP1_CLR,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004868 CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004869 spin_unlock_irqrestore(&il->lock, flags);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004870
4871 cmd.critical_temperature_R =
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004872 cpu_to_le32(il->hw_params.ct_kill_threshold);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004873
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004874 ret = il_send_cmd_pdu(il, C_CT_KILL_CONFIG, sizeof(cmd), &cmd);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004875 if (ret)
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +02004876 IL_ERR("C_CT_KILL_CONFIG failed\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004877 else
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004878 D_INFO("C_CT_KILL_CONFIG " "succeeded, "
4879 "critical temperature is %d\n",
4880 il->hw_params.ct_kill_threshold);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004881}
4882
4883static const s8 default_queue_to_tx_fifo[] = {
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02004884 IL_TX_FIFO_VO,
4885 IL_TX_FIFO_VI,
4886 IL_TX_FIFO_BE,
4887 IL_TX_FIFO_BK,
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01004888 IL49_CMD_FIFO_NUM,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02004889 IL_TX_FIFO_UNUSED,
4890 IL_TX_FIFO_UNUSED,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004891};
4892
Stanislaw Gruszkae53aac42011-08-31 11:18:16 +02004893#define IL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo))))
4894
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004895static int
4896il4965_alive_notify(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004897{
4898 u32 a;
4899 unsigned long flags;
4900 int i, chan;
4901 u32 reg_val;
4902
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004903 spin_lock_irqsave(&il->lock, flags);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004904
4905 /* Clear 4965's internal Tx Scheduler data base */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004906 il->scd_base_addr = il_rd_prph(il, IL49_SCD_SRAM_BASE_ADDR);
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01004907 a = il->scd_base_addr + IL49_SCD_CONTEXT_DATA_OFFSET;
4908 for (; a < il->scd_base_addr + IL49_SCD_TX_STTS_BITMAP_OFFSET; a += 4)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004909 il_write_targ_mem(il, a, 0);
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01004910 for (; a < il->scd_base_addr + IL49_SCD_TRANSLATE_TBL_OFFSET; a += 4)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004911 il_write_targ_mem(il, a, 0);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004912 for (;
4913 a <
4914 il->scd_base_addr +
4915 IL49_SCD_TRANSLATE_TBL_OFFSET_QUEUE(il->hw_params.max_txq_num);
4916 a += 4)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004917 il_write_targ_mem(il, a, 0);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004918
4919 /* Tel 4965 where to find Tx byte count tables */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004920 il_wr_prph(il, IL49_SCD_DRAM_BASE_ADDR, il->scd_bc_tbls.dma >> 10);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004921
4922 /* Enable DMA channel */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004923 for (chan = 0; chan < FH49_TCSR_CHNL_NUM; chan++)
4924 il_wr(il, FH49_TCSR_CHNL_TX_CONFIG_REG(chan),
4925 FH49_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
4926 FH49_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004927
4928 /* Update FH chicken bits */
Stanislaw Gruszka9a95b372011-08-31 14:20:23 +02004929 reg_val = il_rd(il, FH49_TX_CHICKEN_BITS_REG);
4930 il_wr(il, FH49_TX_CHICKEN_BITS_REG,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004931 reg_val | FH49_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004932
4933 /* Disable chain mode for all queues */
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01004934 il_wr_prph(il, IL49_SCD_QUEUECHAIN_SEL, 0);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004935
4936 /* Initialize each Tx queue (including the command queue) */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004937 for (i = 0; i < il->hw_params.max_txq_num; i++) {
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004938
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +01004939 /* TFD circular buffer read/write idxes */
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01004940 il_wr_prph(il, IL49_SCD_QUEUE_RDPTR(i), 0);
Stanislaw Gruszka0c1a94e2011-08-24 17:37:16 +02004941 il_wr(il, HBUS_TARG_WRPTR, 0 | (i << 8));
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004942
4943 /* Max Tx Window size for Scheduler-ACK mode */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004944 il_write_targ_mem(il,
4945 il->scd_base_addr +
4946 IL49_SCD_CONTEXT_QUEUE_OFFSET(i),
4947 (SCD_WIN_SIZE <<
4948 IL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_POS) &
4949 IL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004950
4951 /* Frame limit */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004952 il_write_targ_mem(il,
4953 il->scd_base_addr +
4954 IL49_SCD_CONTEXT_QUEUE_OFFSET(i) +
4955 sizeof(u32),
4956 (SCD_FRAME_LIMIT <<
4957 IL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
4958 IL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004959
4960 }
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01004961 il_wr_prph(il, IL49_SCD_INTERRUPT_MASK,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01004962 (1 << il->hw_params.max_txq_num) - 1);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004963
4964 /* Activate all Tx DMA/FIFO channels */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004965 il4965_txq_set_sched(il, IL_MASK(0, 6));
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004966
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004967 il4965_set_wr_ptrs(il, IL_DEFAULT_CMD_QUEUE_NUM, 0);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004968
4969 /* make sure all queue are not stopped */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004970 memset(&il->queue_stopped[0], 0, sizeof(il->queue_stopped));
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004971 for (i = 0; i < 4; i++)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004972 atomic_set(&il->queue_stop_count[i], 0);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004973
4974 /* reset to 0 to enable all the queue first */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004975 il->txq_ctx_active_msk = 0;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004976 /* Map each Tx/cmd queue to its corresponding fifo */
4977 BUILD_BUG_ON(ARRAY_SIZE(default_queue_to_tx_fifo) != 7);
4978
4979 for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) {
4980 int ac = default_queue_to_tx_fifo[i];
4981
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004982 il_txq_ctx_activate(il, i);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004983
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02004984 if (ac == IL_TX_FIFO_UNUSED)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004985 continue;
4986
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004987 il4965_tx_queue_set_status(il, &il->txq[i], ac, 0);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004988 }
4989
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02004990 spin_unlock_irqrestore(&il->lock, flags);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004991
4992 return 0;
4993}
4994
4995/**
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +02004996 * il4965_alive_start - called after N_ALIVE notification received
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004997 * from protocol/runtime uCode (initialization uCode's
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02004998 * Alive gets handled by il_init_alive_start()).
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004999 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005000static void
5001il4965_alive_start(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005002{
5003 int ret = 0;
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01005004 struct il_rxon_context *ctx = &il->ctx;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005005
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01005006 D_INFO("Runtime Alive received.\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005007
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005008 if (il->card_alive.is_valid != UCODE_VALID_OK) {
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005009 /* We had an error bringing up the hardware, so take it
5010 * all the way back down so we can try again */
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01005011 D_INFO("Alive failed.\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005012 goto restart;
5013 }
5014
5015 /* Initialize uCode has loaded Runtime uCode ... verify inst image.
5016 * This is a paranoid check, because we would not have gotten the
5017 * "runtime" alive if code weren't properly loaded. */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005018 if (il4965_verify_ucode(il)) {
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005019 /* Runtime instruction load was bad;
5020 * take it all the way back down so we can try again */
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01005021 D_INFO("Bad runtime uCode load.\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005022 goto restart;
5023 }
5024
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005025 ret = il4965_alive_notify(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005026 if (ret) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005027 IL_WARN("Could not complete ALIVE transition [ntf]: %d\n", ret);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005028 goto restart;
5029 }
5030
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005031 /* After the ALIVE response, we can send host commands to the uCode */
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01005032 set_bit(S_ALIVE, &il->status);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005033
5034 /* Enable watchdog to monitor the driver tx queues */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005035 il_setup_watchdog(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005036
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005037 if (il_is_rfkill(il))
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005038 return;
5039
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005040 ieee80211_wake_queues(il->hw);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005041
Stanislaw Gruszka2eb05812011-08-26 16:07:43 +02005042 il->active_rate = RATES_MASK;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005043
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02005044 if (il_is_associated_ctx(ctx)) {
5045 struct il_rxon_cmd *active_rxon =
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005046 (struct il_rxon_cmd *)&ctx->active;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005047 /* apply any changes in staging */
5048 ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
5049 active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
5050 } else {
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005051 /* Initialize our rx_config data */
Stanislaw Gruszka17d6e552011-08-29 12:52:20 +02005052 il_connection_init_rx_config(il, &il->ctx);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005053
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005054 if (il->cfg->ops->hcmd->set_rxon_chain)
5055 il->cfg->ops->hcmd->set_rxon_chain(il, ctx);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005056 }
5057
5058 /* Configure bluetooth coexistence if enabled */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005059 il_send_bt_config(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005060
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005061 il4965_reset_run_time_calib(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005062
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01005063 set_bit(S_READY, &il->status);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005064
5065 /* Configure the adapter for unassociated operation */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005066 il_commit_rxon(il, ctx);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005067
5068 /* At this point, the NIC is initialized and operational */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005069 il4965_rf_kill_ct_config(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005070
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01005071 D_INFO("ALIVE processing complete.\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005072 wake_up(&il->wait_command_queue);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005073
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005074 il_power_update_mode(il, true);
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01005075 D_INFO("Updated power mode\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005076
5077 return;
5078
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005079restart:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005080 queue_work(il->workqueue, &il->restart);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005081}
5082
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005083static void il4965_cancel_deferred_work(struct il_priv *il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005084
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005085static void
5086__il4965_down(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005087{
5088 unsigned long flags;
Stanislaw Gruszkaab42b402011-04-28 11:51:24 +02005089 int exit_pending;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005090
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01005091 D_INFO(DRV_NAME " is going down\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005092
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005093 il_scan_cancel_timeout(il, 200);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005094
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01005095 exit_pending = test_and_set_bit(S_EXIT_PENDING, &il->status);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005096
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01005097 /* Stop TX queues watchdog. We need to have S_EXIT_PENDING bit set
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005098 * to prevent rearm timer */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005099 del_timer_sync(&il->watchdog);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005100
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005101 il_clear_ucode_stations(il, NULL);
5102 il_dealloc_bcast_stations(il);
5103 il_clear_driver_stations(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005104
5105 /* Unblock any waiting calls */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005106 wake_up_all(&il->wait_command_queue);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005107
5108 /* Wipe out the EXIT_PENDING status bit if we are not actually
5109 * exiting the module */
5110 if (!exit_pending)
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01005111 clear_bit(S_EXIT_PENDING, &il->status);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005112
5113 /* stop and reset the on-board processor */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02005114 _il_wr(il, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005115
5116 /* tell the device to stop sending interrupts */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005117 spin_lock_irqsave(&il->lock, flags);
5118 il_disable_interrupts(il);
5119 spin_unlock_irqrestore(&il->lock, flags);
5120 il4965_synchronize_irq(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005121
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005122 if (il->mac80211_registered)
5123 ieee80211_stop_queues(il->hw);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005124
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02005125 /* If we have not previously called il_init() then
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005126 * clear all bits but the RF Kill bit and return */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005127 if (!il_is_init(il)) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005128 il->status =
5129 test_bit(S_RF_KILL_HW,
5130 &il->
5131 status) << S_RF_KILL_HW |
5132 test_bit(S_GEO_CONFIGURED,
5133 &il->
5134 status) << S_GEO_CONFIGURED |
5135 test_bit(S_EXIT_PENDING, &il->status) << S_EXIT_PENDING;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005136 goto exit;
5137 }
5138
5139 /* ...otherwise clear out all the status bits but the RF Kill
5140 * bit and continue taking the NIC down. */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005141 il->status &=
5142 test_bit(S_RF_KILL_HW,
5143 &il->status) << S_RF_KILL_HW | test_bit(S_GEO_CONFIGURED,
5144 &il->
5145 status) <<
5146 S_GEO_CONFIGURED | test_bit(S_FW_ERROR,
5147 &il->
5148 status) << S_FW_ERROR |
5149 test_bit(S_EXIT_PENDING, &il->status) << S_EXIT_PENDING;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005150
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005151 il4965_txq_ctx_stop(il);
5152 il4965_rxq_stop(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005153
5154 /* Power-down device's busmaster DMA clocks */
Stanislaw Gruszkadb54eb52011-08-24 21:06:33 +02005155 il_wr_prph(il, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005156 udelay(5);
5157
5158 /* Make sure (redundant) we've released our request to stay awake */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005159 il_clear_bit(il, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005160
5161 /* Stop the device, and put it in low power state */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005162 il_apm_stop(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005163
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005164exit:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005165 memset(&il->card_alive, 0, sizeof(struct il_alive_resp));
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005166
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005167 dev_kfree_skb(il->beacon_skb);
5168 il->beacon_skb = NULL;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005169
5170 /* clear out any free frames */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005171 il4965_clear_free_frames(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005172}
5173
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005174static void
5175il4965_down(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005176{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005177 mutex_lock(&il->mutex);
5178 __il4965_down(il);
5179 mutex_unlock(&il->mutex);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005180
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005181 il4965_cancel_deferred_work(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005182}
5183
5184#define HW_READY_TIMEOUT (50)
5185
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005186static int
5187il4965_set_hw_ready(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005188{
5189 int ret = 0;
5190
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005191 il_set_bit(il, CSR_HW_IF_CONFIG_REG,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005192 CSR_HW_IF_CONFIG_REG_BIT_NIC_READY);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005193
5194 /* See if we got it */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005195 ret =
5196 _il_poll_bit(il, CSR_HW_IF_CONFIG_REG,
5197 CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
5198 CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, HW_READY_TIMEOUT);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005199 if (ret != -ETIMEDOUT)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005200 il->hw_ready = true;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005201 else
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005202 il->hw_ready = false;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005203
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005204 D_INFO("hardware %s\n", (il->hw_ready == 1) ? "ready" : "not ready");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005205 return ret;
5206}
5207
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005208static int
5209il4965_prepare_card_hw(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005210{
5211 int ret = 0;
5212
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01005213 D_INFO("il4965_prepare_card_hw enter\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005214
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005215 ret = il4965_set_hw_ready(il);
5216 if (il->hw_ready)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005217 return ret;
5218
5219 /* If HW is not ready, prepare the conditions to check again */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005220 il_set_bit(il, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_PREPARE);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005221
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005222 ret =
5223 _il_poll_bit(il, CSR_HW_IF_CONFIG_REG,
5224 ~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE,
5225 CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005226
5227 /* HW should be ready by now, check again. */
5228 if (ret != -ETIMEDOUT)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005229 il4965_set_hw_ready(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005230
5231 return ret;
5232}
5233
5234#define MAX_HW_RESTARTS 5
5235
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005236static int
5237__il4965_up(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005238{
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005239 int i;
5240 int ret;
5241
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01005242 if (test_bit(S_EXIT_PENDING, &il->status)) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02005243 IL_WARN("Exit pending; will not bring the NIC up\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005244 return -EIO;
5245 }
5246
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005247 if (!il->ucode_data_backup.v_addr || !il->ucode_data.v_addr) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02005248 IL_ERR("ucode not available for device bringup\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005249 return -EIO;
5250 }
5251
Stanislaw Gruszka17d6e552011-08-29 12:52:20 +02005252 ret = il4965_alloc_bcast_station(il, &il->ctx);
5253 if (ret) {
5254 il_dealloc_bcast_stations(il);
5255 return ret;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005256 }
5257
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005258 il4965_prepare_card_hw(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005259
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005260 if (!il->hw_ready) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02005261 IL_WARN("Exit HW not ready\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005262 return -EIO;
5263 }
5264
5265 /* If platform's RF_KILL switch is NOT set to KILL */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005266 if (_il_rd(il, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01005267 clear_bit(S_RF_KILL_HW, &il->status);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005268 else
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01005269 set_bit(S_RF_KILL_HW, &il->status);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005270
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005271 if (il_is_rfkill(il)) {
5272 wiphy_rfkill_set_hw_state(il->hw->wiphy, true);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005273
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005274 il_enable_interrupts(il);
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02005275 IL_WARN("Radio disabled by HW RF Kill switch\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005276 return 0;
5277 }
5278
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02005279 _il_wr(il, CSR_INT, 0xFFFFFFFF);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005280
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02005281 /* must be initialised before il_hw_nic_init */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005282 il->cmd_queue = IL_DEFAULT_CMD_QUEUE_NUM;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005283
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005284 ret = il4965_hw_nic_init(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005285 if (ret) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02005286 IL_ERR("Unable to init nic\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005287 return ret;
5288 }
5289
5290 /* make sure rfkill handshake bits are cleared */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02005291 _il_wr(il, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005292 _il_wr(il, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005293
5294 /* clear (again), then enable host interrupts */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02005295 _il_wr(il, CSR_INT, 0xFFFFFFFF);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005296 il_enable_interrupts(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005297
5298 /* really make sure rfkill handshake bits are cleared */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02005299 _il_wr(il, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
5300 _il_wr(il, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005301
5302 /* Copy original ucode data image from disk into backup cache.
5303 * This will be used to initialize the on-board processor's
5304 * data SRAM for a clean start when the runtime program first loads. */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005305 memcpy(il->ucode_data_backup.v_addr, il->ucode_data.v_addr,
5306 il->ucode_data.len);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005307
5308 for (i = 0; i < MAX_HW_RESTARTS; i++) {
5309
5310 /* load bootstrap state machine,
5311 * load bootstrap program into processor's memory,
5312 * prepare to load the "initialize" uCode */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005313 ret = il->cfg->ops->lib->load_ucode(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005314
5315 if (ret) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005316 IL_ERR("Unable to set up bootstrap uCode: %d\n", ret);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005317 continue;
5318 }
5319
5320 /* start card; "initialize" will load runtime ucode */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005321 il4965_nic_start(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005322
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01005323 D_INFO(DRV_NAME " is coming up\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005324
5325 return 0;
5326 }
5327
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01005328 set_bit(S_EXIT_PENDING, &il->status);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005329 __il4965_down(il);
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01005330 clear_bit(S_EXIT_PENDING, &il->status);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005331
5332 /* tried to restart and config the device for as long as our
5333 * patience could withstand */
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02005334 IL_ERR("Unable to initialize device after %d attempts.\n", i);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005335 return -EIO;
5336}
5337
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005338/*****************************************************************************
5339 *
5340 * Workqueue callbacks
5341 *
5342 *****************************************************************************/
5343
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005344static void
5345il4965_bg_init_alive_start(struct work_struct *data)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005346{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005347 struct il_priv *il =
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02005348 container_of(data, struct il_priv, init_alive_start.work);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005349
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005350 mutex_lock(&il->mutex);
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01005351 if (test_bit(S_EXIT_PENDING, &il->status))
Stanislaw Gruszka28a6e572011-04-28 11:51:32 +02005352 goto out;
5353
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005354 il->cfg->ops->lib->init_alive_start(il);
Stanislaw Gruszka28a6e572011-04-28 11:51:32 +02005355out:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005356 mutex_unlock(&il->mutex);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005357}
5358
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005359static void
5360il4965_bg_alive_start(struct work_struct *data)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005361{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005362 struct il_priv *il =
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02005363 container_of(data, struct il_priv, alive_start.work);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005364
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005365 mutex_lock(&il->mutex);
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01005366 if (test_bit(S_EXIT_PENDING, &il->status))
Stanislaw Gruszka28a6e572011-04-28 11:51:32 +02005367 goto out;
5368
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005369 il4965_alive_start(il);
Stanislaw Gruszka28a6e572011-04-28 11:51:32 +02005370out:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005371 mutex_unlock(&il->mutex);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005372}
5373
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005374static void
5375il4965_bg_run_time_calib_work(struct work_struct *work)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005376{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005377 struct il_priv *il = container_of(work, struct il_priv,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005378 run_time_calib_work);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005379
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005380 mutex_lock(&il->mutex);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005381
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01005382 if (test_bit(S_EXIT_PENDING, &il->status) ||
5383 test_bit(S_SCANNING, &il->status)) {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005384 mutex_unlock(&il->mutex);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005385 return;
5386 }
5387
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005388 if (il->start_calib) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005389 il4965_chain_noise_calibration(il, (void *)&il->_4965.stats);
5390 il4965_sensitivity_calibration(il, (void *)&il->_4965.stats);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005391 }
5392
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005393 mutex_unlock(&il->mutex);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005394}
5395
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005396static void
5397il4965_bg_restart(struct work_struct *data)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005398{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005399 struct il_priv *il = container_of(data, struct il_priv, restart);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005400
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01005401 if (test_bit(S_EXIT_PENDING, &il->status))
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005402 return;
5403
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01005404 if (test_and_clear_bit(S_FW_ERROR, &il->status)) {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005405 mutex_lock(&il->mutex);
Stanislaw Gruszka17d6e552011-08-29 12:52:20 +02005406 il->ctx.vif = NULL;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005407 il->is_open = 0;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005408
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005409 __il4965_down(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005410
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005411 mutex_unlock(&il->mutex);
5412 il4965_cancel_deferred_work(il);
5413 ieee80211_restart_hw(il->hw);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005414 } else {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005415 il4965_down(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005416
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005417 mutex_lock(&il->mutex);
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01005418 if (test_bit(S_EXIT_PENDING, &il->status)) {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005419 mutex_unlock(&il->mutex);
Stanislaw Gruszka28a6e572011-04-28 11:51:32 +02005420 return;
5421 }
5422
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005423 __il4965_up(il);
5424 mutex_unlock(&il->mutex);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005425 }
5426}
5427
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005428static void
5429il4965_bg_rx_replenish(struct work_struct *data)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005430{
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005431 struct il_priv *il = container_of(data, struct il_priv, rx_replenish);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005432
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01005433 if (test_bit(S_EXIT_PENDING, &il->status))
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005434 return;
5435
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005436 mutex_lock(&il->mutex);
5437 il4965_rx_replenish(il);
5438 mutex_unlock(&il->mutex);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005439}
5440
5441/*****************************************************************************
5442 *
5443 * mac80211 entry point functions
5444 *
5445 *****************************************************************************/
5446
5447#define UCODE_READY_TIMEOUT (4 * HZ)
5448
5449/*
5450 * Not a mac80211 entry point function, but it fits in with all the
5451 * other mac80211 functions grouped here.
5452 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005453static int
5454il4965_mac_setup_register(struct il_priv *il, u32 max_probe_length)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005455{
5456 int ret;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005457 struct ieee80211_hw *hw = il->hw;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005458
5459 hw->rate_control_algorithm = "iwl-4965-rs";
5460
5461 /* Tell mac80211 our characteristics */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005462 hw->flags =
5463 IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_AMPDU_AGGREGATION |
5464 IEEE80211_HW_NEED_DTIM_PERIOD | IEEE80211_HW_SPECTRUM_MGMT |
5465 IEEE80211_HW_REPORTS_TX_ACK_STATUS;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005466
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005467 if (il->cfg->sku & IL_SKU_N)
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005468 hw->flags |=
5469 IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
5470 IEEE80211_HW_SUPPORTS_STATIC_SMPS;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005471
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02005472 hw->sta_data_size = sizeof(struct il_station_priv);
5473 hw->vif_data_size = sizeof(struct il_vif_priv);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005474
Stanislaw Gruszka17d6e552011-08-29 12:52:20 +02005475 hw->wiphy->interface_modes |= il->ctx.interface_modes;
5476 hw->wiphy->interface_modes |= il->ctx.exclusive_interface_modes;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005477
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005478 hw->wiphy->flags |=
5479 WIPHY_FLAG_CUSTOM_REGULATORY | WIPHY_FLAG_DISABLE_BEACON_HINTS;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005480
5481 /*
5482 * For now, disable PS by default because it affects
5483 * RX performance significantly.
5484 */
5485 hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
5486
5487 hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX;
5488 /* we create the 802.11 header and a zero-length SSID element */
5489 hw->wiphy->max_scan_ie_len = max_probe_length - 24 - 2;
5490
5491 /* Default value; 4 EDCA QOS priorities */
5492 hw->queues = 4;
5493
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02005494 hw->max_listen_interval = IL_CONN_MAX_LISTEN_INTERVAL;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005495
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005496 if (il->bands[IEEE80211_BAND_2GHZ].n_channels)
5497 il->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005498 &il->bands[IEEE80211_BAND_2GHZ];
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005499 if (il->bands[IEEE80211_BAND_5GHZ].n_channels)
5500 il->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005501 &il->bands[IEEE80211_BAND_5GHZ];
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005502
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005503 il_leds_init(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005504
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005505 ret = ieee80211_register_hw(il->hw);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005506 if (ret) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02005507 IL_ERR("Failed to register hw (error %d)\n", ret);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005508 return ret;
5509 }
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005510 il->mac80211_registered = 1;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005511
5512 return 0;
5513}
5514
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005515int
5516il4965_mac_start(struct ieee80211_hw *hw)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005517{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005518 struct il_priv *il = hw->priv;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005519 int ret;
5520
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01005521 D_MAC80211("enter\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005522
5523 /* we should be verifying the device is ready to be opened */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005524 mutex_lock(&il->mutex);
5525 ret = __il4965_up(il);
5526 mutex_unlock(&il->mutex);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005527
5528 if (ret)
5529 return ret;
5530
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005531 if (il_is_rfkill(il))
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005532 goto out;
5533
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01005534 D_INFO("Start UP work done.\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005535
5536 /* Wait for START_ALIVE from Run Time ucode. Otherwise callbacks from
5537 * mac80211 will not be run successfully. */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005538 ret = wait_event_timeout(il->wait_command_queue,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005539 test_bit(S_READY, &il->status),
5540 UCODE_READY_TIMEOUT);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005541 if (!ret) {
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01005542 if (!test_bit(S_READY, &il->status)) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02005543 IL_ERR("START_ALIVE timeout after %dms.\n",
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005544 jiffies_to_msecs(UCODE_READY_TIMEOUT));
5545 return -ETIMEDOUT;
5546 }
5547 }
5548
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005549 il4965_led_enable(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005550
5551out:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005552 il->is_open = 1;
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01005553 D_MAC80211("leave\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005554 return 0;
5555}
5556
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005557void
5558il4965_mac_stop(struct ieee80211_hw *hw)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005559{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005560 struct il_priv *il = hw->priv;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005561
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01005562 D_MAC80211("enter\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005563
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005564 if (!il->is_open)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005565 return;
5566
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005567 il->is_open = 0;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005568
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005569 il4965_down(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005570
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005571 flush_workqueue(il->workqueue);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005572
Stanislaw Gruszkaa078a1f2011-04-28 11:51:25 +02005573 /* User space software may expect getting rfkill changes
5574 * even if interface is down */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02005575 _il_wr(il, CSR_INT, 0xFFFFFFFF);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005576 il_enable_rfkill_int(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005577
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01005578 D_MAC80211("leave\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005579}
5580
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005581void
5582il4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005583{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005584 struct il_priv *il = hw->priv;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005585
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01005586 D_MACDUMP("enter\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005587
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01005588 D_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005589 ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005590
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005591 if (il4965_tx_skb(il, skb))
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005592 dev_kfree_skb_any(skb);
5593
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01005594 D_MACDUMP("leave\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005595}
5596
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005597void
5598il4965_mac_update_tkip_key(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
5599 struct ieee80211_key_conf *keyconf,
5600 struct ieee80211_sta *sta, u32 iv32, u16 * phase1key)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005601{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005602 struct il_priv *il = hw->priv;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02005603 struct il_vif_priv *vif_priv = (void *)vif->drv_priv;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005604
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01005605 D_MAC80211("enter\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005606
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005607 il4965_update_tkip_key(il, vif_priv->ctx, keyconf, sta, iv32,
5608 phase1key);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005609
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01005610 D_MAC80211("leave\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005611}
5612
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005613int
5614il4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
5615 struct ieee80211_vif *vif, struct ieee80211_sta *sta,
5616 struct ieee80211_key_conf *key)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005617{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005618 struct il_priv *il = hw->priv;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02005619 struct il_vif_priv *vif_priv = (void *)vif->drv_priv;
5620 struct il_rxon_context *ctx = vif_priv->ctx;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005621 int ret;
5622 u8 sta_id;
5623 bool is_default_wep_key = false;
5624
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01005625 D_MAC80211("enter\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005626
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005627 if (il->cfg->mod_params->sw_crypto) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01005628 D_MAC80211("leave - hwcrypto disabled\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005629 return -EOPNOTSUPP;
5630 }
5631
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005632 sta_id = il_sta_id_or_broadcast(il, vif_priv->ctx, sta);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02005633 if (sta_id == IL_INVALID_STATION)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005634 return -EINVAL;
5635
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005636 mutex_lock(&il->mutex);
5637 il_scan_cancel_timeout(il, 100);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005638
5639 /*
5640 * If we are getting WEP group key and we didn't receive any key mapping
5641 * so far, we are in legacy wep mode (group key only), otherwise we are
5642 * in 1X mode.
5643 * In legacy wep mode, we use another host command to the uCode.
5644 */
5645 if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005646 key->cipher == WLAN_CIPHER_SUITE_WEP104) && !sta) {
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005647 if (cmd == SET_KEY)
5648 is_default_wep_key = !ctx->key_mapping_keys;
5649 else
5650 is_default_wep_key =
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005651 (key->hw_key_idx == HW_KEY_DEFAULT);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005652 }
5653
5654 switch (cmd) {
5655 case SET_KEY:
5656 if (is_default_wep_key)
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005657 ret =
5658 il4965_set_default_wep_key(il, vif_priv->ctx, key);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005659 else
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005660 ret =
5661 il4965_set_dynamic_key(il, vif_priv->ctx, key,
5662 sta_id);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005663
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01005664 D_MAC80211("enable hwcrypto key\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005665 break;
5666 case DISABLE_KEY:
5667 if (is_default_wep_key)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005668 ret = il4965_remove_default_wep_key(il, ctx, key);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005669 else
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005670 ret = il4965_remove_dynamic_key(il, ctx, key, sta_id);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005671
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01005672 D_MAC80211("disable hwcrypto key\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005673 break;
5674 default:
5675 ret = -EINVAL;
5676 }
5677
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005678 mutex_unlock(&il->mutex);
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01005679 D_MAC80211("leave\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005680
5681 return ret;
5682}
5683
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005684int
5685il4965_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
5686 enum ieee80211_ampdu_mlme_action action,
5687 struct ieee80211_sta *sta, u16 tid, u16 * ssn,
5688 u8 buf_size)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005689{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005690 struct il_priv *il = hw->priv;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005691 int ret = -EINVAL;
5692
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005693 D_HT("A-MPDU action on addr %pM tid %d\n", sta->addr, tid);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005694
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005695 if (!(il->cfg->sku & IL_SKU_N))
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005696 return -EACCES;
5697
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005698 mutex_lock(&il->mutex);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005699
5700 switch (action) {
5701 case IEEE80211_AMPDU_RX_START:
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01005702 D_HT("start Rx\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005703 ret = il4965_sta_rx_agg_start(il, sta, tid, *ssn);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005704 break;
5705 case IEEE80211_AMPDU_RX_STOP:
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01005706 D_HT("stop Rx\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005707 ret = il4965_sta_rx_agg_stop(il, sta, tid);
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01005708 if (test_bit(S_EXIT_PENDING, &il->status))
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005709 ret = 0;
5710 break;
5711 case IEEE80211_AMPDU_TX_START:
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01005712 D_HT("start Tx\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005713 ret = il4965_tx_agg_start(il, vif, sta, tid, ssn);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005714 break;
5715 case IEEE80211_AMPDU_TX_STOP:
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01005716 D_HT("stop Tx\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005717 ret = il4965_tx_agg_stop(il, vif, sta, tid);
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01005718 if (test_bit(S_EXIT_PENDING, &il->status))
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005719 ret = 0;
5720 break;
5721 case IEEE80211_AMPDU_TX_OPERATIONAL:
5722 ret = 0;
5723 break;
5724 }
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005725 mutex_unlock(&il->mutex);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005726
5727 return ret;
5728}
5729
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005730int
5731il4965_mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
5732 struct ieee80211_sta *sta)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005733{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005734 struct il_priv *il = hw->priv;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02005735 struct il_station_priv *sta_priv = (void *)sta->drv_priv;
5736 struct il_vif_priv *vif_priv = (void *)vif->drv_priv;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005737 bool is_ap = vif->type == NL80211_IFTYPE_STATION;
5738 int ret;
5739 u8 sta_id;
5740
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005741 D_INFO("received request to add station %pM\n", sta->addr);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005742 mutex_lock(&il->mutex);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005743 D_INFO("proceeding to add station %pM\n", sta->addr);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02005744 sta_priv->common.sta_id = IL_INVALID_STATION;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005745
5746 atomic_set(&sta_priv->pending_frames, 0);
5747
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005748 ret =
5749 il_add_station_common(il, vif_priv->ctx, sta->addr, is_ap, sta,
5750 &sta_id);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005751 if (ret) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005752 IL_ERR("Unable to add station %pM (%d)\n", sta->addr, ret);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005753 /* Should we return success if return code is EEXIST ? */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005754 mutex_unlock(&il->mutex);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005755 return ret;
5756 }
5757
5758 sta_priv->common.sta_id = sta_id;
5759
5760 /* Initialize rate scaling */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005761 D_INFO("Initializing rate scaling for station %pM\n", sta->addr);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005762 il4965_rs_rate_init(il, sta, sta_id);
5763 mutex_unlock(&il->mutex);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005764
5765 return 0;
5766}
5767
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005768void
5769il4965_mac_channel_switch(struct ieee80211_hw *hw,
5770 struct ieee80211_channel_switch *ch_switch)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005771{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005772 struct il_priv *il = hw->priv;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02005773 const struct il_channel_info *ch_info;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005774 struct ieee80211_conf *conf = &hw->conf;
5775 struct ieee80211_channel *channel = ch_switch->channel;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005776 struct il_ht_config *ht_conf = &il->current_ht_config;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005777
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01005778 struct il_rxon_context *ctx = &il->ctx;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005779 u16 ch;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005780
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01005781 D_MAC80211("enter\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005782
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005783 mutex_lock(&il->mutex);
Stanislaw Gruszka28a6e572011-04-28 11:51:32 +02005784
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005785 if (il_is_rfkill(il))
Stanislaw Gruszka28a6e572011-04-28 11:51:32 +02005786 goto out;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005787
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01005788 if (test_bit(S_EXIT_PENDING, &il->status) ||
5789 test_bit(S_SCANNING, &il->status) ||
5790 test_bit(S_CHANNEL_SWITCH_PENDING, &il->status))
Stanislaw Gruszka28a6e572011-04-28 11:51:32 +02005791 goto out;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005792
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02005793 if (!il_is_associated_ctx(ctx))
Stanislaw Gruszka28a6e572011-04-28 11:51:32 +02005794 goto out;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005795
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005796 if (!il->cfg->ops->lib->set_channel_switch)
Stanislaw Gruszka7f1f9742011-06-08 15:28:29 +02005797 goto out;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005798
Stanislaw Gruszka7f1f9742011-06-08 15:28:29 +02005799 ch = channel->hw_value;
5800 if (le16_to_cpu(ctx->active.channel) == ch)
5801 goto out;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005802
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005803 ch_info = il_get_channel_info(il, channel->band, ch);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02005804 if (!il_is_channel_valid(ch_info)) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01005805 D_MAC80211("invalid channel\n");
Stanislaw Gruszka7f1f9742011-06-08 15:28:29 +02005806 goto out;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005807 }
Stanislaw Gruszka7f1f9742011-06-08 15:28:29 +02005808
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005809 spin_lock_irq(&il->lock);
Stanislaw Gruszka7f1f9742011-06-08 15:28:29 +02005810
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005811 il->current_ht_config.smps = conf->smps_mode;
Stanislaw Gruszka7f1f9742011-06-08 15:28:29 +02005812
5813 /* Configure HT40 channels */
5814 ctx->ht.enabled = conf_is_ht(conf);
5815 if (ctx->ht.enabled) {
5816 if (conf_is_ht40_minus(conf)) {
5817 ctx->ht.extension_chan_offset =
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005818 IEEE80211_HT_PARAM_CHA_SEC_BELOW;
Stanislaw Gruszka7f1f9742011-06-08 15:28:29 +02005819 ctx->ht.is_40mhz = true;
5820 } else if (conf_is_ht40_plus(conf)) {
5821 ctx->ht.extension_chan_offset =
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005822 IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
Stanislaw Gruszka7f1f9742011-06-08 15:28:29 +02005823 ctx->ht.is_40mhz = true;
5824 } else {
5825 ctx->ht.extension_chan_offset =
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005826 IEEE80211_HT_PARAM_CHA_SEC_NONE;
Stanislaw Gruszka7f1f9742011-06-08 15:28:29 +02005827 ctx->ht.is_40mhz = false;
5828 }
5829 } else
5830 ctx->ht.is_40mhz = false;
5831
5832 if ((le16_to_cpu(ctx->staging.channel) != ch))
5833 ctx->staging.flags = 0;
5834
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005835 il_set_rxon_channel(il, channel, ctx);
5836 il_set_rxon_ht(il, ht_conf);
5837 il_set_flags_for_band(il, ctx, channel->band, ctx->vif);
Stanislaw Gruszka7f1f9742011-06-08 15:28:29 +02005838
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005839 spin_unlock_irq(&il->lock);
Stanislaw Gruszka7f1f9742011-06-08 15:28:29 +02005840
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005841 il_set_rate(il);
Stanislaw Gruszka7f1f9742011-06-08 15:28:29 +02005842 /*
5843 * at this point, staging_rxon has the
5844 * configuration for channel switch
5845 */
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01005846 set_bit(S_CHANNEL_SWITCH_PENDING, &il->status);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005847 il->switch_channel = cpu_to_le16(ch);
5848 if (il->cfg->ops->lib->set_channel_switch(il, ch_switch)) {
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01005849 clear_bit(S_CHANNEL_SWITCH_PENDING, &il->status);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005850 il->switch_channel = 0;
Stanislaw Gruszka7f1f9742011-06-08 15:28:29 +02005851 ieee80211_chswitch_done(ctx->vif, false);
5852 }
5853
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005854out:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005855 mutex_unlock(&il->mutex);
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01005856 D_MAC80211("leave\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005857}
5858
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005859void
5860il4965_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
5861 unsigned int *total_flags, u64 multicast)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005862{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005863 struct il_priv *il = hw->priv;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005864 __le32 filter_or = 0, filter_nand = 0;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005865
5866#define CHK(test, flag) do { \
5867 if (*total_flags & (test)) \
5868 filter_or |= (flag); \
5869 else \
5870 filter_nand |= (flag); \
5871 } while (0)
5872
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005873 D_MAC80211("Enter: changed: 0x%x, total: 0x%x\n", changed_flags,
5874 *total_flags);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005875
5876 CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK);
5877 /* Setting _just_ RXON_FILTER_CTL2HOST_MSK causes FH errors */
5878 CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_PROMISC_MSK);
5879 CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK);
5880
5881#undef CHK
5882
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005883 mutex_lock(&il->mutex);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005884
Stanislaw Gruszka17d6e552011-08-29 12:52:20 +02005885 il->ctx.staging.filter_flags &= ~filter_nand;
5886 il->ctx.staging.filter_flags |= filter_or;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005887
Stanislaw Gruszka17d6e552011-08-29 12:52:20 +02005888 /*
5889 * Not committing directly because hardware can perform a scan,
5890 * but we'll eventually commit the filter flags change anyway.
5891 */
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005892
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005893 mutex_unlock(&il->mutex);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005894
5895 /*
5896 * Receiving all multicast frames is always enabled by the
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02005897 * default flags setup in il_connection_init_rx_config()
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005898 * since we currently do not support programming multicast
5899 * filters into the device.
5900 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005901 *total_flags &=
5902 FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS |
5903 FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005904}
5905
5906/*****************************************************************************
5907 *
5908 * driver setup and teardown
5909 *
5910 *****************************************************************************/
5911
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005912static void
5913il4965_bg_txpower_work(struct work_struct *work)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005914{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005915 struct il_priv *il = container_of(work, struct il_priv,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005916 txpower_work);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005917
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005918 mutex_lock(&il->mutex);
Stanislaw Gruszkaf3257572011-04-28 11:36:54 +02005919
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005920 /* If a scan happened to start before we got here
Stanislaw Gruszkaebf0d902011-08-26 15:43:47 +02005921 * then just return; the stats notification will
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005922 * kick off another scheduled work to compensate for
5923 * any temperature delta we missed here. */
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01005924 if (test_bit(S_EXIT_PENDING, &il->status) ||
5925 test_bit(S_SCANNING, &il->status))
Stanislaw Gruszkaf3257572011-04-28 11:36:54 +02005926 goto out;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005927
5928 /* Regardless of if we are associated, we must reconfigure the
5929 * TX power since frames can be sent on non-radar channels while
5930 * not associated */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005931 il->cfg->ops->lib->send_tx_power(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005932
5933 /* Update last_temperature to keep is_calib_needed from running
5934 * when it isn't needed... */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005935 il->last_temperature = il->temperature;
Stanislaw Gruszkaf3257572011-04-28 11:36:54 +02005936out:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005937 mutex_unlock(&il->mutex);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005938}
5939
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005940static void
5941il4965_setup_deferred_work(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005942{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005943 il->workqueue = create_singlethread_workqueue(DRV_NAME);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005944
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005945 init_waitqueue_head(&il->wait_command_queue);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005946
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005947 INIT_WORK(&il->restart, il4965_bg_restart);
5948 INIT_WORK(&il->rx_replenish, il4965_bg_rx_replenish);
5949 INIT_WORK(&il->run_time_calib_work, il4965_bg_run_time_calib_work);
5950 INIT_DELAYED_WORK(&il->init_alive_start, il4965_bg_init_alive_start);
5951 INIT_DELAYED_WORK(&il->alive_start, il4965_bg_alive_start);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005952
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005953 il_setup_scan_deferred_work(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005954
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005955 INIT_WORK(&il->txpower_work, il4965_bg_txpower_work);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005956
Stanislaw Gruszkaebf0d902011-08-26 15:43:47 +02005957 init_timer(&il->stats_periodic);
5958 il->stats_periodic.data = (unsigned long)il;
5959 il->stats_periodic.function = il4965_bg_stats_periodic;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005960
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005961 init_timer(&il->watchdog);
5962 il->watchdog.data = (unsigned long)il;
5963 il->watchdog.function = il_bg_watchdog;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005964
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005965 tasklet_init(&il->irq_tasklet,
5966 (void (*)(unsigned long))il4965_irq_tasklet,
5967 (unsigned long)il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005968}
5969
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005970static void
5971il4965_cancel_deferred_work(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005972{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005973 cancel_work_sync(&il->txpower_work);
5974 cancel_delayed_work_sync(&il->init_alive_start);
5975 cancel_delayed_work(&il->alive_start);
5976 cancel_work_sync(&il->run_time_calib_work);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005977
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02005978 il_cancel_scan_deferred_work(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005979
Stanislaw Gruszkaebf0d902011-08-26 15:43:47 +02005980 del_timer_sync(&il->stats_periodic);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005981}
5982
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005983static void
5984il4965_init_hw_rates(struct il_priv *il, struct ieee80211_rate *rates)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005985{
5986 int i;
5987
Stanislaw Gruszka2eb05812011-08-26 16:07:43 +02005988 for (i = 0; i < RATE_COUNT_LEGACY; i++) {
Stanislaw Gruszkad2ddf6212011-08-16 14:17:04 +02005989 rates[i].bitrate = il_rates[i].ieee * 5;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005990 rates[i].hw_value = i; /* Rate scaling will work on idxes */
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005991 rates[i].hw_value_short = i;
5992 rates[i].flags = 0;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02005993 if ((i >= IL_FIRST_CCK_RATE) && (i <= IL_LAST_CCK_RATE)) {
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08005994 /*
5995 * If CCK != 1M then set short preamble rate flag.
5996 */
5997 rates[i].flags |=
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01005998 (il_rates[i].plcp ==
5999 RATE_1M_PLCP) ? 0 : IEEE80211_RATE_SHORT_PREAMBLE;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006000 }
6001 }
6002}
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01006003
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006004/*
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006005 * Acquire il->lock before calling this function !
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006006 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01006007void
6008il4965_set_wr_ptrs(struct il_priv *il, int txq_id, u32 idx)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006009{
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01006010 il_wr(il, HBUS_TARG_WRPTR, (idx & 0xff) | (txq_id << 8));
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +01006011 il_wr_prph(il, IL49_SCD_QUEUE_RDPTR(txq_id), idx);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006012}
6013
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01006014void
6015il4965_tx_queue_set_status(struct il_priv *il, struct il_tx_queue *txq,
6016 int tx_fifo_id, int scd_retry)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006017{
6018 int txq_id = txq->q.id;
6019
6020 /* Find out whether to activate Tx queue */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006021 int active = test_bit(txq_id, &il->txq_ctx_active_msk) ? 1 : 0;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006022
6023 /* Set up and activate */
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01006024 il_wr_prph(il, IL49_SCD_QUEUE_STATUS_BITS(txq_id),
Stanislaw Gruszka1722f8e2011-11-15 14:51:01 +01006025 (active << IL49_SCD_QUEUE_STTS_REG_POS_ACTIVE) |
6026 (tx_fifo_id << IL49_SCD_QUEUE_STTS_REG_POS_TXF) |
6027 (scd_retry << IL49_SCD_QUEUE_STTS_REG_POS_WSL) |
6028 (scd_retry << IL49_SCD_QUEUE_STTS_REG_POS_SCD_ACK) |
6029 IL49_SCD_QUEUE_STTS_REG_MSK);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006030
6031 txq->sched_retry = scd_retry;
6032
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01006033 D_INFO("%s %s Queue %d on AC %d\n", active ? "Activate" : "Deactivate",
6034 scd_retry ? "BA" : "AC", txq_id, tx_fifo_id);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006035}
6036
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01006037static int
6038il4965_init_drv(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006039{
6040 int ret;
6041
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006042 spin_lock_init(&il->sta_lock);
6043 spin_lock_init(&il->hcmd_lock);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006044
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006045 INIT_LIST_HEAD(&il->free_frames);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006046
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006047 mutex_init(&il->mutex);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006048
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006049 il->ieee_channels = NULL;
6050 il->ieee_rates = NULL;
6051 il->band = IEEE80211_BAND_2GHZ;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006052
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006053 il->iw_mode = NL80211_IFTYPE_STATION;
6054 il->current_ht_config.smps = IEEE80211_SMPS_STATIC;
6055 il->missed_beacon_threshold = IL_MISSED_BEACON_THRESHOLD_DEF;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006056
6057 /* initialize force reset */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006058 il->force_reset.reset_duration = IL_DELAY_NEXT_FORCE_FW_RELOAD;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006059
6060 /* Choose which receivers/antennas to use */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006061 if (il->cfg->ops->hcmd->set_rxon_chain)
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01006062 il->cfg->ops->hcmd->set_rxon_chain(il, &il->ctx);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006063
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006064 il_init_scan_params(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006065
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006066 ret = il_init_channel_map(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006067 if (ret) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02006068 IL_ERR("initializing regulatory failed: %d\n", ret);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006069 goto err;
6070 }
6071
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006072 ret = il_init_geos(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006073 if (ret) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02006074 IL_ERR("initializing geos failed: %d\n", ret);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006075 goto err_free_channel_map;
6076 }
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006077 il4965_init_hw_rates(il, il->ieee_rates);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006078
6079 return 0;
6080
6081err_free_channel_map:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006082 il_free_channel_map(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006083err:
6084 return ret;
6085}
6086
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01006087static void
6088il4965_uninit_drv(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006089{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006090 il4965_calib_free_results(il);
6091 il_free_geos(il);
6092 il_free_channel_map(il);
6093 kfree(il->scan_cmd);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006094}
6095
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01006096static void
6097il4965_hw_detect(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006098{
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02006099 il->hw_rev = _il_rd(il, CSR_HW_REV);
6100 il->hw_wa_rev = _il_rd(il, CSR_HW_REV_WA_REG);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006101 il->rev_id = il->pci_dev->revision;
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01006102 D_INFO("HW Revision ID = 0x%X\n", il->rev_id);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006103}
6104
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01006105static int
6106il4965_set_hw_params(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006107{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006108 il->hw_params.max_rxq_size = RX_QUEUE_SIZE;
6109 il->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;
6110 if (il->cfg->mod_params->amsdu_size_8K)
6111 il->hw_params.rx_page_order = get_order(IL_RX_BUF_SIZE_8K);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006112 else
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006113 il->hw_params.rx_page_order = get_order(IL_RX_BUF_SIZE_4K);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006114
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006115 il->hw_params.max_beacon_itrvl = IL_MAX_UCODE_BEACON_INTERVAL;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006116
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006117 if (il->cfg->mod_params->disable_11n)
6118 il->cfg->sku &= ~IL_SKU_N;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006119
6120 /* Device-specific setup */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006121 return il->cfg->ops->lib->set_hw_params(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006122}
6123
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02006124static const u8 il4965_bss_ac_to_fifo[] = {
6125 IL_TX_FIFO_VO,
6126 IL_TX_FIFO_VI,
6127 IL_TX_FIFO_BE,
6128 IL_TX_FIFO_BK,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006129};
6130
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02006131static const u8 il4965_bss_ac_to_queue[] = {
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006132 0, 1, 2, 3,
6133};
6134
6135static int
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02006136il4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006137{
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01006138 int err = 0;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006139 struct il_priv *il;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006140 struct ieee80211_hw *hw;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02006141 struct il_cfg *cfg = (struct il_cfg *)(ent->driver_data);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006142 unsigned long flags;
6143 u16 pci_cmd;
6144
6145 /************************
6146 * 1. Allocating HW data
6147 ************************/
6148
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02006149 hw = il_alloc_all(cfg);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006150 if (!hw) {
6151 err = -ENOMEM;
6152 goto out;
6153 }
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006154 il = hw->priv;
6155 /* At this point both hw and il are allocated. */
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006156
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01006157 il->ctx.ctxid = 0;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006158
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01006159 il->ctx.always_active = true;
6160 il->ctx.is_active = true;
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +02006161 il->ctx.rxon_cmd = C_RXON;
6162 il->ctx.rxon_timing_cmd = C_RXON_TIMING;
6163 il->ctx.rxon_assoc_cmd = C_RXON_ASSOC;
6164 il->ctx.qos_cmd = C_QOS_PARAM;
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01006165 il->ctx.ap_sta_id = IL_AP_ID;
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +02006166 il->ctx.wep_key_cmd = C_WEPKEY;
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01006167 il->ctx.ac_to_fifo = il4965_bss_ac_to_fifo;
6168 il->ctx.ac_to_queue = il4965_bss_ac_to_queue;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01006169 il->ctx.exclusive_interface_modes = BIT(NL80211_IFTYPE_ADHOC);
6170 il->ctx.interface_modes = BIT(NL80211_IFTYPE_STATION);
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01006171 il->ctx.ap_devtype = RXON_DEV_TYPE_AP;
6172 il->ctx.ibss_devtype = RXON_DEV_TYPE_IBSS;
6173 il->ctx.station_devtype = RXON_DEV_TYPE_ESS;
6174 il->ctx.unused_devtype = RXON_DEV_TYPE_ESS;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006175
6176 SET_IEEE80211_DEV(hw, &pdev->dev);
6177
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01006178 D_INFO("*** LOAD DRIVER ***\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006179 il->cfg = cfg;
6180 il->pci_dev = pdev;
6181 il->inta_mask = CSR_INI_SET_MASK;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006182
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006183 if (il_alloc_traffic_mem(il))
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02006184 IL_ERR("Not enough memory to generate traffic log\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006185
6186 /**************************
6187 * 2. Initializing PCI bus
6188 **************************/
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01006189 pci_disable_link_state(pdev,
6190 PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
6191 PCIE_LINK_STATE_CLKPM);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006192
6193 if (pci_enable_device(pdev)) {
6194 err = -ENODEV;
6195 goto out_ieee80211_free_hw;
6196 }
6197
6198 pci_set_master(pdev);
6199
6200 err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36));
6201 if (!err)
6202 err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(36));
6203 if (err) {
6204 err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
6205 if (!err)
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01006206 err =
6207 pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006208 /* both attempts failed: */
6209 if (err) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02006210 IL_WARN("No suitable DMA available.\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006211 goto out_pci_disable_device;
6212 }
6213 }
6214
6215 err = pci_request_regions(pdev, DRV_NAME);
6216 if (err)
6217 goto out_pci_disable_device;
6218
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006219 pci_set_drvdata(pdev, il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006220
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006221 /***********************
6222 * 3. Read REV register
6223 ***********************/
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006224 il->hw_base = pci_iomap(pdev, 0, 0);
6225 if (!il->hw_base) {
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006226 err = -ENODEV;
6227 goto out_pci_release_regions;
6228 }
6229
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01006230 D_INFO("pci_resource_len = 0x%08llx\n",
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01006231 (unsigned long long)pci_resource_len(pdev, 0));
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01006232 D_INFO("pci_resource_base = %p\n", il->hw_base);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006233
6234 /* these spin locks will be used in apm_ops.init and EEPROM access
6235 * we should init now
6236 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006237 spin_lock_init(&il->reg_lock);
6238 spin_lock_init(&il->lock);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006239
6240 /*
6241 * stop and reset the on-board processor just in case it is in a
6242 * strange state ... like being left stranded by a primary kernel
6243 * and this is now the kdump kernel trying to start up
6244 */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02006245 _il_wr(il, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006246
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006247 il4965_hw_detect(il);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01006248 IL_INFO("Detected %s, REV=0x%X\n", il->cfg->name, il->hw_rev);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006249
6250 /* We disable the RETRY_TIMEOUT register (0x41) to keep
6251 * PCI Tx retries from interfering with C3 CPU state */
6252 pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
6253
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006254 il4965_prepare_card_hw(il);
6255 if (!il->hw_ready) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02006256 IL_WARN("Failed, HW not ready\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006257 goto out_iounmap;
6258 }
6259
6260 /*****************
6261 * 4. Read EEPROM
6262 *****************/
6263 /* Read the EEPROM */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006264 err = il_eeprom_init(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006265 if (err) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02006266 IL_ERR("Unable to init EEPROM\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006267 goto out_iounmap;
6268 }
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006269 err = il4965_eeprom_check_version(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006270 if (err)
6271 goto out_free_eeprom;
6272
6273 if (err)
6274 goto out_free_eeprom;
6275
6276 /* extract MAC Address */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006277 il4965_eeprom_get_mac(il, il->addresses[0].addr);
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01006278 D_INFO("MAC address: %pM\n", il->addresses[0].addr);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006279 il->hw->wiphy->addresses = il->addresses;
6280 il->hw->wiphy->n_addresses = 1;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006281
6282 /************************
6283 * 5. Setup HW constants
6284 ************************/
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006285 if (il4965_set_hw_params(il)) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02006286 IL_ERR("failed to set hw parameters\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006287 goto out_free_eeprom;
6288 }
6289
6290 /*******************
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006291 * 6. Setup il
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006292 *******************/
6293
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006294 err = il4965_init_drv(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006295 if (err)
6296 goto out_free_eeprom;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006297 /* At this point both hw and il are initialized. */
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006298
6299 /********************
6300 * 7. Setup services
6301 ********************/
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006302 spin_lock_irqsave(&il->lock, flags);
6303 il_disable_interrupts(il);
6304 spin_unlock_irqrestore(&il->lock, flags);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006305
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006306 pci_enable_msi(il->pci_dev);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006307
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01006308 err = request_irq(il->pci_dev->irq, il_isr, IRQF_SHARED, DRV_NAME, il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006309 if (err) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02006310 IL_ERR("Error allocating IRQ %d\n", il->pci_dev->irq);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006311 goto out_disable_msi;
6312 }
6313
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006314 il4965_setup_deferred_work(il);
Stanislaw Gruszkad0c72342011-08-30 15:39:42 +02006315 il4965_setup_handlers(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006316
6317 /*********************************************
6318 * 8. Enable interrupts and read RFKILL state
6319 *********************************************/
6320
Stanislaw Gruszkaa078a1f2011-04-28 11:51:25 +02006321 /* enable rfkill interrupt: hw bug w/a */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006322 pci_read_config_word(il->pci_dev, PCI_COMMAND, &pci_cmd);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006323 if (pci_cmd & PCI_COMMAND_INTX_DISABLE) {
6324 pci_cmd &= ~PCI_COMMAND_INTX_DISABLE;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006325 pci_write_config_word(il->pci_dev, PCI_COMMAND, pci_cmd);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006326 }
6327
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006328 il_enable_rfkill_int(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006329
6330 /* If platform's RF_KILL switch is NOT set to KILL */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01006331 if (_il_rd(il, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01006332 clear_bit(S_RF_KILL_HW, &il->status);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006333 else
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01006334 set_bit(S_RF_KILL_HW, &il->status);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006335
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006336 wiphy_rfkill_set_hw_state(il->hw->wiphy,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01006337 test_bit(S_RF_KILL_HW, &il->status));
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006338
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006339 il_power_initialize(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006340
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006341 init_completion(&il->_4965.firmware_loading_complete);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006342
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006343 err = il4965_request_firmware(il, true);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006344 if (err)
6345 goto out_destroy_workqueue;
6346
6347 return 0;
6348
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01006349out_destroy_workqueue:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006350 destroy_workqueue(il->workqueue);
6351 il->workqueue = NULL;
6352 free_irq(il->pci_dev->irq, il);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01006353out_disable_msi:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006354 pci_disable_msi(il->pci_dev);
6355 il4965_uninit_drv(il);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01006356out_free_eeprom:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006357 il_eeprom_free(il);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01006358out_iounmap:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006359 pci_iounmap(pdev, il->hw_base);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01006360out_pci_release_regions:
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006361 pci_set_drvdata(pdev, NULL);
6362 pci_release_regions(pdev);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01006363out_pci_disable_device:
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006364 pci_disable_device(pdev);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01006365out_ieee80211_free_hw:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006366 il_free_traffic_mem(il);
6367 ieee80211_free_hw(il->hw);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01006368out:
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006369 return err;
6370}
6371
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01006372static void __devexit
6373il4965_pci_remove(struct pci_dev *pdev)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006374{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006375 struct il_priv *il = pci_get_drvdata(pdev);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006376 unsigned long flags;
6377
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006378 if (!il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006379 return;
6380
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006381 wait_for_completion(&il->_4965.firmware_loading_complete);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006382
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01006383 D_INFO("*** UNLOAD DRIVER ***\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006384
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006385 il_dbgfs_unregister(il);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02006386 sysfs_remove_group(&pdev->dev.kobj, &il_attribute_group);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006387
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02006388 /* ieee80211_unregister_hw call wil cause il_mac_stop to
6389 * to be called and il4965_down since we are removing the device
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01006390 * we need to set S_EXIT_PENDING bit.
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006391 */
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01006392 set_bit(S_EXIT_PENDING, &il->status);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006393
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006394 il_leds_exit(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006395
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006396 if (il->mac80211_registered) {
6397 ieee80211_unregister_hw(il->hw);
6398 il->mac80211_registered = 0;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006399 } else {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006400 il4965_down(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006401 }
6402
6403 /*
6404 * Make sure device is reset to low power before unloading driver.
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02006405 * This may be redundant with il4965_down(), but there are paths to
6406 * run il4965_down() without calling apm_ops.stop(), and there are
6407 * paths to avoid running il4965_down() at all before leaving driver.
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006408 * This (inexpensive) call *makes sure* device is reset.
6409 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006410 il_apm_stop(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006411
6412 /* make sure we flush any pending irq or
6413 * tasklet for the driver
6414 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006415 spin_lock_irqsave(&il->lock, flags);
6416 il_disable_interrupts(il);
6417 spin_unlock_irqrestore(&il->lock, flags);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006418
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006419 il4965_synchronize_irq(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006420
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006421 il4965_dealloc_ucode_pci(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006422
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006423 if (il->rxq.bd)
6424 il4965_rx_queue_free(il, &il->rxq);
6425 il4965_hw_txq_ctx_free(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006426
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006427 il_eeprom_free(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006428
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006429 /*netif_stop_queue(dev); */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006430 flush_workqueue(il->workqueue);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006431
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02006432 /* ieee80211_unregister_hw calls il_mac_stop, which flushes
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006433 * il->workqueue... so we can't take down the workqueue
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006434 * until now... */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006435 destroy_workqueue(il->workqueue);
6436 il->workqueue = NULL;
6437 il_free_traffic_mem(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006438
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006439 free_irq(il->pci_dev->irq, il);
6440 pci_disable_msi(il->pci_dev);
6441 pci_iounmap(pdev, il->hw_base);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006442 pci_release_regions(pdev);
6443 pci_disable_device(pdev);
6444 pci_set_drvdata(pdev, NULL);
6445
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006446 il4965_uninit_drv(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006447
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006448 dev_kfree_skb(il->beacon_skb);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006449
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006450 ieee80211_free_hw(il->hw);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006451}
6452
6453/*
6454 * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02006455 * must be called under il->lock and mac access
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006456 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01006457void
6458il4965_txq_set_sched(struct il_priv *il, u32 mask)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006459{
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01006460 il_wr_prph(il, IL49_SCD_TXFACT, mask);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006461}
6462
6463/*****************************************************************************
6464 *
6465 * driver and module entry point
6466 *
6467 *****************************************************************************/
6468
6469/* Hardware specific file defines the PCI IDs table for that hardware module */
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02006470static DEFINE_PCI_DEVICE_TABLE(il4965_hw_card_ids) = {
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02006471 {IL_PCI_DEVICE(0x4229, PCI_ANY_ID, il4965_cfg)},
6472 {IL_PCI_DEVICE(0x4230, PCI_ANY_ID, il4965_cfg)},
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006473 {0}
6474};
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02006475MODULE_DEVICE_TABLE(pci, il4965_hw_card_ids);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006476
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02006477static struct pci_driver il4965_driver = {
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006478 .name = DRV_NAME,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02006479 .id_table = il4965_hw_card_ids,
6480 .probe = il4965_pci_probe,
6481 .remove = __devexit_p(il4965_pci_remove),
6482 .driver.pm = IL_LEGACY_PM_OPS,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006483};
6484
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01006485static int __init
6486il4965_init(void)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006487{
6488
6489 int ret;
6490 pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n");
6491 pr_info(DRV_COPYRIGHT "\n");
6492
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02006493 ret = il4965_rate_control_register();
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006494 if (ret) {
6495 pr_err("Unable to register rate control algorithm: %d\n", ret);
6496 return ret;
6497 }
6498
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02006499 ret = pci_register_driver(&il4965_driver);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006500 if (ret) {
6501 pr_err("Unable to initialize PCI module\n");
6502 goto error_register;
6503 }
6504
6505 return ret;
6506
6507error_register:
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02006508 il4965_rate_control_unregister();
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006509 return ret;
6510}
6511
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01006512static void __exit
6513il4965_exit(void)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006514{
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02006515 pci_unregister_driver(&il4965_driver);
6516 il4965_rate_control_unregister();
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006517}
6518
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02006519module_exit(il4965_exit);
6520module_init(il4965_init);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006521
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01006522#ifdef CONFIG_IWLEGACY_DEBUG
Stanislaw Gruszkad2ddf6212011-08-16 14:17:04 +02006523module_param_named(debug, il_debug_level, uint, S_IRUGO | S_IWUSR);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006524MODULE_PARM_DESC(debug, "debug output mask");
6525#endif
6526
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02006527module_param_named(swcrypto, il4965_mod_params.sw_crypto, int, S_IRUGO);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006528MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])");
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02006529module_param_named(queues_num, il4965_mod_params.num_of_queues, int, S_IRUGO);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006530MODULE_PARM_DESC(queues_num, "number of hw queues.");
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02006531module_param_named(11n_disable, il4965_mod_params.disable_11n, int, S_IRUGO);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006532MODULE_PARM_DESC(11n_disable, "disable 11n functionality");
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01006533module_param_named(amsdu_size_8K, il4965_mod_params.amsdu_size_8K, int,
6534 S_IRUGO);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006535MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size");
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02006536module_param_named(fw_restart, il4965_mod_params.restart_fw, int, S_IRUGO);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08006537MODULE_PARM_DESC(fw_restart, "restart firmware in case of error");