116da78b7SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
27ac9a364SKalle Valo /******************************************************************************
37ac9a364SKalle Valo *
47ac9a364SKalle Valo * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
57ac9a364SKalle Valo *
67ac9a364SKalle Valo * Portions of this file are derived from the ipw3945 project, as well
77ac9a364SKalle Valo * as portions of the ieee80211 subsystem header files.
87ac9a364SKalle Valo *
97ac9a364SKalle Valo * Contact Information:
107ac9a364SKalle Valo * Intel Linux Wireless <ilw@linux.intel.com>
117ac9a364SKalle Valo * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
127ac9a364SKalle Valo *
137ac9a364SKalle Valo *****************************************************************************/
147ac9a364SKalle Valo
157ac9a364SKalle Valo #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
167ac9a364SKalle Valo
177ac9a364SKalle Valo #include <linux/kernel.h>
187ac9a364SKalle Valo #include <linux/module.h>
197ac9a364SKalle Valo #include <linux/init.h>
207ac9a364SKalle Valo #include <linux/pci.h>
217ac9a364SKalle Valo #include <linux/slab.h>
227ac9a364SKalle Valo #include <linux/dma-mapping.h>
237ac9a364SKalle Valo #include <linux/delay.h>
247ac9a364SKalle Valo #include <linux/sched.h>
257ac9a364SKalle Valo #include <linux/skbuff.h>
267ac9a364SKalle Valo #include <linux/netdevice.h>
277ac9a364SKalle Valo #include <linux/firmware.h>
287ac9a364SKalle Valo #include <linux/etherdevice.h>
297ac9a364SKalle Valo #include <linux/if_arp.h>
301410b2fcSAkinobu Mita #include <linux/units.h>
317ac9a364SKalle Valo
327ac9a364SKalle Valo #include <net/mac80211.h>
337ac9a364SKalle Valo
347ac9a364SKalle Valo #include <asm/div64.h>
357ac9a364SKalle Valo
367ac9a364SKalle Valo #define DRV_NAME "iwl4965"
377ac9a364SKalle Valo
387ac9a364SKalle Valo #include "common.h"
397ac9a364SKalle Valo #include "4965.h"
407ac9a364SKalle Valo
417ac9a364SKalle Valo /******************************************************************************
427ac9a364SKalle Valo *
437ac9a364SKalle Valo * module boiler plate
447ac9a364SKalle Valo *
457ac9a364SKalle Valo ******************************************************************************/
467ac9a364SKalle Valo
477ac9a364SKalle Valo /*
487ac9a364SKalle Valo * module name, copyright, version, etc.
497ac9a364SKalle Valo */
507ac9a364SKalle Valo #define DRV_DESCRIPTION "Intel(R) Wireless WiFi 4965 driver for Linux"
517ac9a364SKalle Valo
527ac9a364SKalle Valo #ifdef CONFIG_IWLEGACY_DEBUG
537ac9a364SKalle Valo #define VD "d"
547ac9a364SKalle Valo #else
557ac9a364SKalle Valo #define VD
567ac9a364SKalle Valo #endif
577ac9a364SKalle Valo
587ac9a364SKalle Valo #define DRV_VERSION IWLWIFI_VERSION VD
597ac9a364SKalle Valo
607ac9a364SKalle Valo MODULE_DESCRIPTION(DRV_DESCRIPTION);
617ac9a364SKalle Valo MODULE_VERSION(DRV_VERSION);
627ac9a364SKalle Valo MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
637ac9a364SKalle Valo MODULE_LICENSE("GPL");
647ac9a364SKalle Valo MODULE_ALIAS("iwl4965");
657ac9a364SKalle Valo
667ac9a364SKalle Valo void
il4965_check_abort_status(struct il_priv * il,u8 frame_count,u32 status)677ac9a364SKalle Valo il4965_check_abort_status(struct il_priv *il, u8 frame_count, u32 status)
687ac9a364SKalle Valo {
697ac9a364SKalle Valo if (frame_count == 1 && status == TX_STATUS_FAIL_RFKILL_FLUSH) {
707ac9a364SKalle Valo IL_ERR("Tx flush command to flush out all frames\n");
717ac9a364SKalle Valo if (!test_bit(S_EXIT_PENDING, &il->status))
727ac9a364SKalle Valo queue_work(il->workqueue, &il->tx_flush);
737ac9a364SKalle Valo }
747ac9a364SKalle Valo }
757ac9a364SKalle Valo
767ac9a364SKalle Valo /*
777ac9a364SKalle Valo * EEPROM
787ac9a364SKalle Valo */
797ac9a364SKalle Valo struct il_mod_params il4965_mod_params = {
807ac9a364SKalle Valo .restart_fw = 1,
817ac9a364SKalle Valo /* the rest are 0 by default */
827ac9a364SKalle Valo };
837ac9a364SKalle Valo
847ac9a364SKalle Valo void
il4965_rx_queue_reset(struct il_priv * il,struct il_rx_queue * rxq)857ac9a364SKalle Valo il4965_rx_queue_reset(struct il_priv *il, struct il_rx_queue *rxq)
867ac9a364SKalle Valo {
877ac9a364SKalle Valo unsigned long flags;
887ac9a364SKalle Valo int i;
897ac9a364SKalle Valo spin_lock_irqsave(&rxq->lock, flags);
907ac9a364SKalle Valo INIT_LIST_HEAD(&rxq->rx_free);
917ac9a364SKalle Valo INIT_LIST_HEAD(&rxq->rx_used);
927ac9a364SKalle Valo /* Fill the rx_used queue with _all_ of the Rx buffers */
937ac9a364SKalle Valo for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
947ac9a364SKalle Valo /* In the reset function, these buffers may have been allocated
957ac9a364SKalle Valo * to an SKB, so we need to unmap and free potential storage */
967ac9a364SKalle Valo if (rxq->pool[i].page != NULL) {
97ebe9e651SChristophe JAILLET dma_unmap_page(&il->pci_dev->dev,
98ebe9e651SChristophe JAILLET rxq->pool[i].page_dma,
997ac9a364SKalle Valo PAGE_SIZE << il->hw_params.rx_page_order,
100ebe9e651SChristophe JAILLET DMA_FROM_DEVICE);
1017ac9a364SKalle Valo __il_free_pages(il, rxq->pool[i].page);
1027ac9a364SKalle Valo rxq->pool[i].page = NULL;
1037ac9a364SKalle Valo }
1047ac9a364SKalle Valo list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
1057ac9a364SKalle Valo }
1067ac9a364SKalle Valo
1077ac9a364SKalle Valo for (i = 0; i < RX_QUEUE_SIZE; i++)
1087ac9a364SKalle Valo rxq->queue[i] = NULL;
1097ac9a364SKalle Valo
1107ac9a364SKalle Valo /* Set us so that we have processed and used all buffers, but have
1117ac9a364SKalle Valo * not restocked the Rx queue with fresh buffers */
1127ac9a364SKalle Valo rxq->read = rxq->write = 0;
1137ac9a364SKalle Valo rxq->write_actual = 0;
1147ac9a364SKalle Valo rxq->free_count = 0;
1157ac9a364SKalle Valo spin_unlock_irqrestore(&rxq->lock, flags);
1167ac9a364SKalle Valo }
1177ac9a364SKalle Valo
1187ac9a364SKalle Valo int
il4965_rx_init(struct il_priv * il,struct il_rx_queue * rxq)1197ac9a364SKalle Valo il4965_rx_init(struct il_priv *il, struct il_rx_queue *rxq)
1207ac9a364SKalle Valo {
1217ac9a364SKalle Valo u32 rb_size;
1227ac9a364SKalle Valo const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */
1237ac9a364SKalle Valo u32 rb_timeout = 0;
1247ac9a364SKalle Valo
1257ac9a364SKalle Valo if (il->cfg->mod_params->amsdu_size_8K)
1267ac9a364SKalle Valo rb_size = FH49_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K;
1277ac9a364SKalle Valo else
1287ac9a364SKalle Valo rb_size = FH49_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K;
1297ac9a364SKalle Valo
1307ac9a364SKalle Valo /* Stop Rx DMA */
1317ac9a364SKalle Valo il_wr(il, FH49_MEM_RCSR_CHNL0_CONFIG_REG, 0);
1327ac9a364SKalle Valo
1337ac9a364SKalle Valo /* Reset driver's Rx queue write idx */
1347ac9a364SKalle Valo il_wr(il, FH49_RSCSR_CHNL0_RBDCB_WPTR_REG, 0);
1357ac9a364SKalle Valo
1367ac9a364SKalle Valo /* Tell device where to find RBD circular buffer in DRAM */
1377ac9a364SKalle Valo il_wr(il, FH49_RSCSR_CHNL0_RBDCB_BASE_REG, (u32) (rxq->bd_dma >> 8));
1387ac9a364SKalle Valo
1397ac9a364SKalle Valo /* Tell device where in DRAM to update its Rx status */
1407ac9a364SKalle Valo il_wr(il, FH49_RSCSR_CHNL0_STTS_WPTR_REG, rxq->rb_stts_dma >> 4);
1417ac9a364SKalle Valo
1427ac9a364SKalle Valo /* Enable Rx DMA
1437ac9a364SKalle Valo * Direct rx interrupts to hosts
1447ac9a364SKalle Valo * Rx buffer size 4 or 8k
1457ac9a364SKalle Valo * RB timeout 0x10
1467ac9a364SKalle Valo * 256 RBDs
1477ac9a364SKalle Valo */
1487ac9a364SKalle Valo il_wr(il, FH49_MEM_RCSR_CHNL0_CONFIG_REG,
1497ac9a364SKalle Valo FH49_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
1507ac9a364SKalle Valo FH49_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
1517ac9a364SKalle Valo FH49_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK |
1527ac9a364SKalle Valo rb_size |
1537ac9a364SKalle Valo (rb_timeout << FH49_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS) |
1547ac9a364SKalle Valo (rfdnlog << FH49_RCSR_RX_CONFIG_RBDCB_SIZE_POS));
1557ac9a364SKalle Valo
1567ac9a364SKalle Valo /* Set interrupt coalescing timer to default (2048 usecs) */
1577ac9a364SKalle Valo il_write8(il, CSR_INT_COALESCING, IL_HOST_INT_TIMEOUT_DEF);
1587ac9a364SKalle Valo
1597ac9a364SKalle Valo return 0;
1607ac9a364SKalle Valo }
1617ac9a364SKalle Valo
1627ac9a364SKalle Valo static void
il4965_set_pwr_vmain(struct il_priv * il)1637ac9a364SKalle Valo il4965_set_pwr_vmain(struct il_priv *il)
1647ac9a364SKalle Valo {
1657ac9a364SKalle Valo /*
1667ac9a364SKalle Valo * (for documentation purposes)
1677ac9a364SKalle Valo * to set power to V_AUX, do:
1687ac9a364SKalle Valo
1697ac9a364SKalle Valo if (pci_pme_capable(il->pci_dev, PCI_D3cold))
1707ac9a364SKalle Valo il_set_bits_mask_prph(il, APMG_PS_CTRL_REG,
1717ac9a364SKalle Valo APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
1727ac9a364SKalle Valo ~APMG_PS_CTRL_MSK_PWR_SRC);
1737ac9a364SKalle Valo */
1747ac9a364SKalle Valo
1757ac9a364SKalle Valo il_set_bits_mask_prph(il, APMG_PS_CTRL_REG,
1767ac9a364SKalle Valo APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
1777ac9a364SKalle Valo ~APMG_PS_CTRL_MSK_PWR_SRC);
1787ac9a364SKalle Valo }
1797ac9a364SKalle Valo
1807ac9a364SKalle Valo int
il4965_hw_nic_init(struct il_priv * il)1817ac9a364SKalle Valo il4965_hw_nic_init(struct il_priv *il)
1827ac9a364SKalle Valo {
1837ac9a364SKalle Valo unsigned long flags;
1847ac9a364SKalle Valo struct il_rx_queue *rxq = &il->rxq;
1857ac9a364SKalle Valo int ret;
1867ac9a364SKalle Valo
1877ac9a364SKalle Valo spin_lock_irqsave(&il->lock, flags);
1887ac9a364SKalle Valo il_apm_init(il);
1897ac9a364SKalle Valo /* Set interrupt coalescing calibration timer to default (512 usecs) */
1907ac9a364SKalle Valo il_write8(il, CSR_INT_COALESCING, IL_HOST_INT_CALIB_TIMEOUT_DEF);
1917ac9a364SKalle Valo spin_unlock_irqrestore(&il->lock, flags);
1927ac9a364SKalle Valo
1937ac9a364SKalle Valo il4965_set_pwr_vmain(il);
1947ac9a364SKalle Valo il4965_nic_config(il);
1957ac9a364SKalle Valo
1967ac9a364SKalle Valo /* Allocate the RX queue, or reset if it is already allocated */
1977ac9a364SKalle Valo if (!rxq->bd) {
1987ac9a364SKalle Valo ret = il_rx_queue_alloc(il);
1997ac9a364SKalle Valo if (ret) {
2007ac9a364SKalle Valo IL_ERR("Unable to initialize Rx queue\n");
2017ac9a364SKalle Valo return -ENOMEM;
2027ac9a364SKalle Valo }
2037ac9a364SKalle Valo } else
2047ac9a364SKalle Valo il4965_rx_queue_reset(il, rxq);
2057ac9a364SKalle Valo
2067ac9a364SKalle Valo il4965_rx_replenish(il);
2077ac9a364SKalle Valo
2087ac9a364SKalle Valo il4965_rx_init(il, rxq);
2097ac9a364SKalle Valo
2107ac9a364SKalle Valo spin_lock_irqsave(&il->lock, flags);
2117ac9a364SKalle Valo
2127ac9a364SKalle Valo rxq->need_update = 1;
2137ac9a364SKalle Valo il_rx_queue_update_write_ptr(il, rxq);
2147ac9a364SKalle Valo
2157ac9a364SKalle Valo spin_unlock_irqrestore(&il->lock, flags);
2167ac9a364SKalle Valo
2177ac9a364SKalle Valo /* Allocate or reset and init all Tx and Command queues */
2187ac9a364SKalle Valo if (!il->txq) {
2197ac9a364SKalle Valo ret = il4965_txq_ctx_alloc(il);
2207ac9a364SKalle Valo if (ret)
2217ac9a364SKalle Valo return ret;
2227ac9a364SKalle Valo } else
2237ac9a364SKalle Valo il4965_txq_ctx_reset(il);
2247ac9a364SKalle Valo
2257ac9a364SKalle Valo set_bit(S_INIT, &il->status);
2267ac9a364SKalle Valo
2277ac9a364SKalle Valo return 0;
2287ac9a364SKalle Valo }
2297ac9a364SKalle Valo
23035b7fbfcSLee Jones /*
2317ac9a364SKalle Valo * il4965_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr
2327ac9a364SKalle Valo */
2337ac9a364SKalle Valo static inline __le32
il4965_dma_addr2rbd_ptr(struct il_priv * il,dma_addr_t dma_addr)2347ac9a364SKalle Valo il4965_dma_addr2rbd_ptr(struct il_priv *il, dma_addr_t dma_addr)
2357ac9a364SKalle Valo {
2367ac9a364SKalle Valo return cpu_to_le32((u32) (dma_addr >> 8));
2377ac9a364SKalle Valo }
2387ac9a364SKalle Valo
23935b7fbfcSLee Jones /*
2407ac9a364SKalle Valo * il4965_rx_queue_restock - refill RX queue from pre-allocated pool
2417ac9a364SKalle Valo *
2427ac9a364SKalle Valo * If there are slots in the RX queue that need to be restocked,
2437ac9a364SKalle Valo * and we have free pre-allocated buffers, fill the ranks as much
2447ac9a364SKalle Valo * as we can, pulling from rx_free.
2457ac9a364SKalle Valo *
2467ac9a364SKalle Valo * This moves the 'write' idx forward to catch up with 'processed', and
2477ac9a364SKalle Valo * also updates the memory address in the firmware to reference the new
2487ac9a364SKalle Valo * target buffer.
2497ac9a364SKalle Valo */
2507ac9a364SKalle Valo void
il4965_rx_queue_restock(struct il_priv * il)2517ac9a364SKalle Valo il4965_rx_queue_restock(struct il_priv *il)
2527ac9a364SKalle Valo {
2537ac9a364SKalle Valo struct il_rx_queue *rxq = &il->rxq;
2547ac9a364SKalle Valo struct list_head *element;
2557ac9a364SKalle Valo struct il_rx_buf *rxb;
2567ac9a364SKalle Valo unsigned long flags;
2577ac9a364SKalle Valo
2587ac9a364SKalle Valo spin_lock_irqsave(&rxq->lock, flags);
2597ac9a364SKalle Valo while (il_rx_queue_space(rxq) > 0 && rxq->free_count) {
2607ac9a364SKalle Valo /* The overwritten rxb must be a used one */
2617ac9a364SKalle Valo rxb = rxq->queue[rxq->write];
2627ac9a364SKalle Valo BUG_ON(rxb && rxb->page);
2637ac9a364SKalle Valo
2647ac9a364SKalle Valo /* Get next free Rx buffer, remove from free list */
2657ac9a364SKalle Valo element = rxq->rx_free.next;
2667ac9a364SKalle Valo rxb = list_entry(element, struct il_rx_buf, list);
2677ac9a364SKalle Valo list_del(element);
2687ac9a364SKalle Valo
2697ac9a364SKalle Valo /* Point to Rx buffer via next RBD in circular buffer */
2707ac9a364SKalle Valo rxq->bd[rxq->write] =
2717ac9a364SKalle Valo il4965_dma_addr2rbd_ptr(il, rxb->page_dma);
2727ac9a364SKalle Valo rxq->queue[rxq->write] = rxb;
2737ac9a364SKalle Valo rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
2747ac9a364SKalle Valo rxq->free_count--;
2757ac9a364SKalle Valo }
2767ac9a364SKalle Valo spin_unlock_irqrestore(&rxq->lock, flags);
2777ac9a364SKalle Valo /* If the pre-allocated buffer pool is dropping low, schedule to
2787ac9a364SKalle Valo * refill it */
2797ac9a364SKalle Valo if (rxq->free_count <= RX_LOW_WATERMARK)
2807ac9a364SKalle Valo queue_work(il->workqueue, &il->rx_replenish);
2817ac9a364SKalle Valo
2827ac9a364SKalle Valo /* If we've added more space for the firmware to place data, tell it.
2837ac9a364SKalle Valo * Increment device's write pointer in multiples of 8. */
2847ac9a364SKalle Valo if (rxq->write_actual != (rxq->write & ~0x7)) {
2857ac9a364SKalle Valo spin_lock_irqsave(&rxq->lock, flags);
2867ac9a364SKalle Valo rxq->need_update = 1;
2877ac9a364SKalle Valo spin_unlock_irqrestore(&rxq->lock, flags);
2887ac9a364SKalle Valo il_rx_queue_update_write_ptr(il, rxq);
2897ac9a364SKalle Valo }
2907ac9a364SKalle Valo }
2917ac9a364SKalle Valo
29235b7fbfcSLee Jones /*
2937ac9a364SKalle Valo * il4965_rx_replenish - Move all used packet from rx_used to rx_free
2947ac9a364SKalle Valo *
2957ac9a364SKalle Valo * When moving to rx_free an SKB is allocated for the slot.
2967ac9a364SKalle Valo *
2977ac9a364SKalle Valo * Also restock the Rx queue via il_rx_queue_restock.
2987ac9a364SKalle Valo * This is called as a scheduled work item (except for during initialization)
2997ac9a364SKalle Valo */
3007ac9a364SKalle Valo static void
il4965_rx_allocate(struct il_priv * il,gfp_t priority)3017ac9a364SKalle Valo il4965_rx_allocate(struct il_priv *il, gfp_t priority)
3027ac9a364SKalle Valo {
3037ac9a364SKalle Valo struct il_rx_queue *rxq = &il->rxq;
3047ac9a364SKalle Valo struct list_head *element;
3057ac9a364SKalle Valo struct il_rx_buf *rxb;
3067ac9a364SKalle Valo struct page *page;
3077ac9a364SKalle Valo dma_addr_t page_dma;
3087ac9a364SKalle Valo unsigned long flags;
3097ac9a364SKalle Valo gfp_t gfp_mask = priority;
3107ac9a364SKalle Valo
3117ac9a364SKalle Valo while (1) {
3127ac9a364SKalle Valo spin_lock_irqsave(&rxq->lock, flags);
3137ac9a364SKalle Valo if (list_empty(&rxq->rx_used)) {
3147ac9a364SKalle Valo spin_unlock_irqrestore(&rxq->lock, flags);
3157ac9a364SKalle Valo return;
3167ac9a364SKalle Valo }
3177ac9a364SKalle Valo spin_unlock_irqrestore(&rxq->lock, flags);
3187ac9a364SKalle Valo
3197ac9a364SKalle Valo if (rxq->free_count > RX_LOW_WATERMARK)
3207ac9a364SKalle Valo gfp_mask |= __GFP_NOWARN;
3217ac9a364SKalle Valo
3227ac9a364SKalle Valo if (il->hw_params.rx_page_order > 0)
3237ac9a364SKalle Valo gfp_mask |= __GFP_COMP;
3247ac9a364SKalle Valo
3257ac9a364SKalle Valo /* Alloc a new receive buffer */
3267ac9a364SKalle Valo page = alloc_pages(gfp_mask, il->hw_params.rx_page_order);
3277ac9a364SKalle Valo if (!page) {
3287ac9a364SKalle Valo if (net_ratelimit())
3297ac9a364SKalle Valo D_INFO("alloc_pages failed, " "order: %d\n",
3307ac9a364SKalle Valo il->hw_params.rx_page_order);
3317ac9a364SKalle Valo
3327ac9a364SKalle Valo if (rxq->free_count <= RX_LOW_WATERMARK &&
3337ac9a364SKalle Valo net_ratelimit())
3347ac9a364SKalle Valo IL_ERR("Failed to alloc_pages with %s. "
3357ac9a364SKalle Valo "Only %u free buffers remaining.\n",
3367ac9a364SKalle Valo priority ==
3377ac9a364SKalle Valo GFP_ATOMIC ? "GFP_ATOMIC" : "GFP_KERNEL",
3387ac9a364SKalle Valo rxq->free_count);
3397ac9a364SKalle Valo /* We don't reschedule replenish work here -- we will
3407ac9a364SKalle Valo * call the restock method and if it still needs
3417ac9a364SKalle Valo * more buffers it will schedule replenish */
3427ac9a364SKalle Valo return;
3437ac9a364SKalle Valo }
3447ac9a364SKalle Valo
3457ac9a364SKalle Valo /* Get physical address of the RB */
346ebe9e651SChristophe JAILLET page_dma = dma_map_page(&il->pci_dev->dev, page, 0,
3477ac9a364SKalle Valo PAGE_SIZE << il->hw_params.rx_page_order,
348ebe9e651SChristophe JAILLET DMA_FROM_DEVICE);
349ebe9e651SChristophe JAILLET if (unlikely(dma_mapping_error(&il->pci_dev->dev, page_dma))) {
3507ac9a364SKalle Valo __free_pages(page, il->hw_params.rx_page_order);
3517ac9a364SKalle Valo break;
3527ac9a364SKalle Valo }
3537ac9a364SKalle Valo
3547ac9a364SKalle Valo spin_lock_irqsave(&rxq->lock, flags);
3557ac9a364SKalle Valo
3567ac9a364SKalle Valo if (list_empty(&rxq->rx_used)) {
3577ac9a364SKalle Valo spin_unlock_irqrestore(&rxq->lock, flags);
358ebe9e651SChristophe JAILLET dma_unmap_page(&il->pci_dev->dev, page_dma,
3597ac9a364SKalle Valo PAGE_SIZE << il->hw_params.rx_page_order,
360ebe9e651SChristophe JAILLET DMA_FROM_DEVICE);
3617ac9a364SKalle Valo __free_pages(page, il->hw_params.rx_page_order);
3627ac9a364SKalle Valo return;
3637ac9a364SKalle Valo }
3647ac9a364SKalle Valo
3657ac9a364SKalle Valo element = rxq->rx_used.next;
3667ac9a364SKalle Valo rxb = list_entry(element, struct il_rx_buf, list);
3677ac9a364SKalle Valo list_del(element);
3687ac9a364SKalle Valo
3697ac9a364SKalle Valo BUG_ON(rxb->page);
3707ac9a364SKalle Valo
3717ac9a364SKalle Valo rxb->page = page;
3727ac9a364SKalle Valo rxb->page_dma = page_dma;
3737ac9a364SKalle Valo list_add_tail(&rxb->list, &rxq->rx_free);
3747ac9a364SKalle Valo rxq->free_count++;
3757ac9a364SKalle Valo il->alloc_rxb_page++;
3767ac9a364SKalle Valo
3777ac9a364SKalle Valo spin_unlock_irqrestore(&rxq->lock, flags);
3787ac9a364SKalle Valo }
3797ac9a364SKalle Valo }
3807ac9a364SKalle Valo
3817ac9a364SKalle Valo void
il4965_rx_replenish(struct il_priv * il)3827ac9a364SKalle Valo il4965_rx_replenish(struct il_priv *il)
3837ac9a364SKalle Valo {
3847ac9a364SKalle Valo unsigned long flags;
3857ac9a364SKalle Valo
3867ac9a364SKalle Valo il4965_rx_allocate(il, GFP_KERNEL);
3877ac9a364SKalle Valo
3887ac9a364SKalle Valo spin_lock_irqsave(&il->lock, flags);
3897ac9a364SKalle Valo il4965_rx_queue_restock(il);
3907ac9a364SKalle Valo spin_unlock_irqrestore(&il->lock, flags);
3917ac9a364SKalle Valo }
3927ac9a364SKalle Valo
3937ac9a364SKalle Valo void
il4965_rx_replenish_now(struct il_priv * il)3947ac9a364SKalle Valo il4965_rx_replenish_now(struct il_priv *il)
3957ac9a364SKalle Valo {
3967ac9a364SKalle Valo il4965_rx_allocate(il, GFP_ATOMIC);
3977ac9a364SKalle Valo
3987ac9a364SKalle Valo il4965_rx_queue_restock(il);
3997ac9a364SKalle Valo }
4007ac9a364SKalle Valo
4017ac9a364SKalle Valo /* Assumes that the skb field of the buffers in 'pool' is kept accurate.
4027ac9a364SKalle Valo * If an SKB has been detached, the POOL needs to have its SKB set to NULL
4037ac9a364SKalle Valo * This free routine walks the list of POOL entries and if SKB is set to
4047ac9a364SKalle Valo * non NULL it is unmapped and freed
4057ac9a364SKalle Valo */
4067ac9a364SKalle Valo void
il4965_rx_queue_free(struct il_priv * il,struct il_rx_queue * rxq)4077ac9a364SKalle Valo il4965_rx_queue_free(struct il_priv *il, struct il_rx_queue *rxq)
4087ac9a364SKalle Valo {
4097ac9a364SKalle Valo int i;
4107ac9a364SKalle Valo for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
4117ac9a364SKalle Valo if (rxq->pool[i].page != NULL) {
412ebe9e651SChristophe JAILLET dma_unmap_page(&il->pci_dev->dev,
413ebe9e651SChristophe JAILLET rxq->pool[i].page_dma,
4147ac9a364SKalle Valo PAGE_SIZE << il->hw_params.rx_page_order,
415ebe9e651SChristophe JAILLET DMA_FROM_DEVICE);
4167ac9a364SKalle Valo __il_free_pages(il, rxq->pool[i].page);
4177ac9a364SKalle Valo rxq->pool[i].page = NULL;
4187ac9a364SKalle Valo }
4197ac9a364SKalle Valo }
4207ac9a364SKalle Valo
4217ac9a364SKalle Valo dma_free_coherent(&il->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
4227ac9a364SKalle Valo rxq->bd_dma);
4237ac9a364SKalle Valo dma_free_coherent(&il->pci_dev->dev, sizeof(struct il_rb_status),
4247ac9a364SKalle Valo rxq->rb_stts, rxq->rb_stts_dma);
4257ac9a364SKalle Valo rxq->bd = NULL;
4267ac9a364SKalle Valo rxq->rb_stts = NULL;
4277ac9a364SKalle Valo }
4287ac9a364SKalle Valo
4297ac9a364SKalle Valo int
il4965_rxq_stop(struct il_priv * il)4307ac9a364SKalle Valo il4965_rxq_stop(struct il_priv *il)
4317ac9a364SKalle Valo {
4327ac9a364SKalle Valo int ret;
4337ac9a364SKalle Valo
4347ac9a364SKalle Valo _il_wr(il, FH49_MEM_RCSR_CHNL0_CONFIG_REG, 0);
4357ac9a364SKalle Valo ret = _il_poll_bit(il, FH49_MEM_RSSR_RX_STATUS_REG,
4367ac9a364SKalle Valo FH49_RSSR_CHNL0_RX_STATUS_CHNL_IDLE,
4377ac9a364SKalle Valo FH49_RSSR_CHNL0_RX_STATUS_CHNL_IDLE,
4387ac9a364SKalle Valo 1000);
4397ac9a364SKalle Valo if (ret < 0)
4407ac9a364SKalle Valo IL_ERR("Can't stop Rx DMA.\n");
4417ac9a364SKalle Valo
4427ac9a364SKalle Valo return 0;
4437ac9a364SKalle Valo }
4447ac9a364SKalle Valo
4457ac9a364SKalle Valo int
il4965_hwrate_to_mac80211_idx(u32 rate_n_flags,enum nl80211_band band)44657fbcce3SJohannes Berg il4965_hwrate_to_mac80211_idx(u32 rate_n_flags, enum nl80211_band band)
4477ac9a364SKalle Valo {
4487ac9a364SKalle Valo int idx = 0;
4497ac9a364SKalle Valo int band_offset = 0;
4507ac9a364SKalle Valo
4517ac9a364SKalle Valo /* HT rate format: mac80211 wants an MCS number, which is just LSB */
4527ac9a364SKalle Valo if (rate_n_flags & RATE_MCS_HT_MSK) {
4537ac9a364SKalle Valo idx = (rate_n_flags & 0xff);
4547ac9a364SKalle Valo return idx;
4557ac9a364SKalle Valo /* Legacy rate format, search for match in table */
4567ac9a364SKalle Valo } else {
45757fbcce3SJohannes Berg if (band == NL80211_BAND_5GHZ)
4587ac9a364SKalle Valo band_offset = IL_FIRST_OFDM_RATE;
4597ac9a364SKalle Valo for (idx = band_offset; idx < RATE_COUNT_LEGACY; idx++)
4607ac9a364SKalle Valo if (il_rates[idx].plcp == (rate_n_flags & 0xFF))
4617ac9a364SKalle Valo return idx - band_offset;
4627ac9a364SKalle Valo }
4637ac9a364SKalle Valo
4647ac9a364SKalle Valo return -1;
4657ac9a364SKalle Valo }
4667ac9a364SKalle Valo
4677ac9a364SKalle Valo static int
il4965_calc_rssi(struct il_priv * il,struct il_rx_phy_res * rx_resp)4687ac9a364SKalle Valo il4965_calc_rssi(struct il_priv *il, struct il_rx_phy_res *rx_resp)
4697ac9a364SKalle Valo {
4707ac9a364SKalle Valo /* data from PHY/DSP regarding signal strength, etc.,
4717ac9a364SKalle Valo * contents are always there, not configurable by host. */
4727ac9a364SKalle Valo struct il4965_rx_non_cfg_phy *ncphy =
4737ac9a364SKalle Valo (struct il4965_rx_non_cfg_phy *)rx_resp->non_cfg_phy_buf;
4747ac9a364SKalle Valo u32 agc =
4757ac9a364SKalle Valo (le16_to_cpu(ncphy->agc_info) & IL49_AGC_DB_MASK) >>
4767ac9a364SKalle Valo IL49_AGC_DB_POS;
4777ac9a364SKalle Valo
4787ac9a364SKalle Valo u32 valid_antennae =
4797ac9a364SKalle Valo (le16_to_cpu(rx_resp->phy_flags) & IL49_RX_PHY_FLAGS_ANTENNAE_MASK)
4807ac9a364SKalle Valo >> IL49_RX_PHY_FLAGS_ANTENNAE_OFFSET;
4817ac9a364SKalle Valo u8 max_rssi = 0;
4827ac9a364SKalle Valo u32 i;
4837ac9a364SKalle Valo
4847ac9a364SKalle Valo /* Find max rssi among 3 possible receivers.
4857ac9a364SKalle Valo * These values are measured by the digital signal processor (DSP).
4867ac9a364SKalle Valo * They should stay fairly constant even as the signal strength varies,
4877ac9a364SKalle Valo * if the radio's automatic gain control (AGC) is working right.
4887ac9a364SKalle Valo * AGC value (see below) will provide the "interesting" info. */
4897ac9a364SKalle Valo for (i = 0; i < 3; i++)
4907ac9a364SKalle Valo if (valid_antennae & (1 << i))
4917ac9a364SKalle Valo max_rssi = max(ncphy->rssi_info[i << 1], max_rssi);
4927ac9a364SKalle Valo
4937ac9a364SKalle Valo D_STATS("Rssi In A %d B %d C %d Max %d AGC dB %d\n",
4947ac9a364SKalle Valo ncphy->rssi_info[0], ncphy->rssi_info[2], ncphy->rssi_info[4],
4957ac9a364SKalle Valo max_rssi, agc);
4967ac9a364SKalle Valo
4977ac9a364SKalle Valo /* dBm = max_rssi dB - agc dB - constant.
4987ac9a364SKalle Valo * Higher AGC (higher radio gain) means lower signal. */
4997ac9a364SKalle Valo return max_rssi - agc - IL4965_RSSI_OFFSET;
5007ac9a364SKalle Valo }
5017ac9a364SKalle Valo
5027ac9a364SKalle Valo static u32
il4965_translate_rx_status(struct il_priv * il,u32 decrypt_in)5037ac9a364SKalle Valo il4965_translate_rx_status(struct il_priv *il, u32 decrypt_in)
5047ac9a364SKalle Valo {
5057ac9a364SKalle Valo u32 decrypt_out = 0;
5067ac9a364SKalle Valo
5077ac9a364SKalle Valo if ((decrypt_in & RX_RES_STATUS_STATION_FOUND) ==
5087ac9a364SKalle Valo RX_RES_STATUS_STATION_FOUND)
5097ac9a364SKalle Valo decrypt_out |=
5107ac9a364SKalle Valo (RX_RES_STATUS_STATION_FOUND |
5117ac9a364SKalle Valo RX_RES_STATUS_NO_STATION_INFO_MISMATCH);
5127ac9a364SKalle Valo
5137ac9a364SKalle Valo decrypt_out |= (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK);
5147ac9a364SKalle Valo
5157ac9a364SKalle Valo /* packet was not encrypted */
5167ac9a364SKalle Valo if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) ==
5177ac9a364SKalle Valo RX_RES_STATUS_SEC_TYPE_NONE)
5187ac9a364SKalle Valo return decrypt_out;
5197ac9a364SKalle Valo
5207ac9a364SKalle Valo /* packet was encrypted with unknown alg */
5217ac9a364SKalle Valo if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) ==
5227ac9a364SKalle Valo RX_RES_STATUS_SEC_TYPE_ERR)
5237ac9a364SKalle Valo return decrypt_out;
5247ac9a364SKalle Valo
5257ac9a364SKalle Valo /* decryption was not done in HW */
5267ac9a364SKalle Valo if ((decrypt_in & RX_MPDU_RES_STATUS_DEC_DONE_MSK) !=
5277ac9a364SKalle Valo RX_MPDU_RES_STATUS_DEC_DONE_MSK)
5287ac9a364SKalle Valo return decrypt_out;
5297ac9a364SKalle Valo
5307ac9a364SKalle Valo switch (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) {
5317ac9a364SKalle Valo
5327ac9a364SKalle Valo case RX_RES_STATUS_SEC_TYPE_CCMP:
5337ac9a364SKalle Valo /* alg is CCM: check MIC only */
5347ac9a364SKalle Valo if (!(decrypt_in & RX_MPDU_RES_STATUS_MIC_OK))
5357ac9a364SKalle Valo /* Bad MIC */
5367ac9a364SKalle Valo decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC;
5377ac9a364SKalle Valo else
5387ac9a364SKalle Valo decrypt_out |= RX_RES_STATUS_DECRYPT_OK;
5397ac9a364SKalle Valo
5407ac9a364SKalle Valo break;
5417ac9a364SKalle Valo
5427ac9a364SKalle Valo case RX_RES_STATUS_SEC_TYPE_TKIP:
5437ac9a364SKalle Valo if (!(decrypt_in & RX_MPDU_RES_STATUS_TTAK_OK)) {
5447ac9a364SKalle Valo /* Bad TTAK */
5457ac9a364SKalle Valo decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK;
5467ac9a364SKalle Valo break;
5477ac9a364SKalle Valo }
5483f95e92cSGustavo A. R. Silva fallthrough; /* if TTAK OK */
5497ac9a364SKalle Valo default:
5507ac9a364SKalle Valo if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK))
5517ac9a364SKalle Valo decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC;
5527ac9a364SKalle Valo else
5537ac9a364SKalle Valo decrypt_out |= RX_RES_STATUS_DECRYPT_OK;
5547ac9a364SKalle Valo break;
5557ac9a364SKalle Valo }
5567ac9a364SKalle Valo
5577ac9a364SKalle Valo D_RX("decrypt_in:0x%x decrypt_out = 0x%x\n", decrypt_in, decrypt_out);
5587ac9a364SKalle Valo
5597ac9a364SKalle Valo return decrypt_out;
5607ac9a364SKalle Valo }
5617ac9a364SKalle Valo
5627ac9a364SKalle Valo #define SMALL_PACKET_SIZE 256
5637ac9a364SKalle Valo
5647ac9a364SKalle Valo static void
il4965_pass_packet_to_mac80211(struct il_priv * il,struct ieee80211_hdr * hdr,u32 len,u32 ampdu_status,struct il_rx_buf * rxb,struct ieee80211_rx_status * stats)5657ac9a364SKalle Valo il4965_pass_packet_to_mac80211(struct il_priv *il, struct ieee80211_hdr *hdr,
5667ac9a364SKalle Valo u32 len, u32 ampdu_status, struct il_rx_buf *rxb,
5677ac9a364SKalle Valo struct ieee80211_rx_status *stats)
5687ac9a364SKalle Valo {
5697ac9a364SKalle Valo struct sk_buff *skb;
5707ac9a364SKalle Valo __le16 fc = hdr->frame_control;
5717ac9a364SKalle Valo
5727ac9a364SKalle Valo /* We only process data packets if the interface is open */
5737ac9a364SKalle Valo if (unlikely(!il->is_open)) {
5747ac9a364SKalle Valo D_DROP("Dropping packet while interface is not open.\n");
5757ac9a364SKalle Valo return;
5767ac9a364SKalle Valo }
5777ac9a364SKalle Valo
5787ac9a364SKalle Valo if (unlikely(test_bit(IL_STOP_REASON_PASSIVE, &il->stop_reason))) {
5797ac9a364SKalle Valo il_wake_queues_by_reason(il, IL_STOP_REASON_PASSIVE);
5807ac9a364SKalle Valo D_INFO("Woke queues - frame received on passive channel\n");
5817ac9a364SKalle Valo }
5827ac9a364SKalle Valo
5837ac9a364SKalle Valo /* In case of HW accelerated crypto and bad decryption, drop */
5847ac9a364SKalle Valo if (!il->cfg->mod_params->sw_crypto &&
5857ac9a364SKalle Valo il_set_decrypted_flag(il, hdr, ampdu_status, stats))
5867ac9a364SKalle Valo return;
5877ac9a364SKalle Valo
5887ac9a364SKalle Valo skb = dev_alloc_skb(SMALL_PACKET_SIZE);
5897ac9a364SKalle Valo if (!skb) {
5907ac9a364SKalle Valo IL_ERR("dev_alloc_skb failed\n");
5917ac9a364SKalle Valo return;
5927ac9a364SKalle Valo }
5937ac9a364SKalle Valo
5947ac9a364SKalle Valo if (len <= SMALL_PACKET_SIZE) {
59559ae1d12SJohannes Berg skb_put_data(skb, hdr, len);
5967ac9a364SKalle Valo } else {
5977ac9a364SKalle Valo skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb),
5987ac9a364SKalle Valo len, PAGE_SIZE << il->hw_params.rx_page_order);
5997ac9a364SKalle Valo il->alloc_rxb_page--;
6007ac9a364SKalle Valo rxb->page = NULL;
6017ac9a364SKalle Valo }
6027ac9a364SKalle Valo
6037ac9a364SKalle Valo il_update_stats(il, false, fc, len);
6047ac9a364SKalle Valo memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
6057ac9a364SKalle Valo
6067ac9a364SKalle Valo ieee80211_rx(il->hw, skb);
6077ac9a364SKalle Valo }
6087ac9a364SKalle Valo
6097ac9a364SKalle Valo /* Called for N_RX (legacy ABG frames), or
6107ac9a364SKalle Valo * N_RX_MPDU (HT high-throughput N frames). */
6117ac9a364SKalle Valo static void
il4965_hdl_rx(struct il_priv * il,struct il_rx_buf * rxb)6127ac9a364SKalle Valo il4965_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb)
6137ac9a364SKalle Valo {
6147ac9a364SKalle Valo struct ieee80211_hdr *header;
6157ac9a364SKalle Valo struct ieee80211_rx_status rx_status = {};
6167ac9a364SKalle Valo struct il_rx_pkt *pkt = rxb_addr(rxb);
6177ac9a364SKalle Valo struct il_rx_phy_res *phy_res;
6187ac9a364SKalle Valo __le32 rx_pkt_status;
6197ac9a364SKalle Valo struct il_rx_mpdu_res_start *amsdu;
6207ac9a364SKalle Valo u32 len;
6217ac9a364SKalle Valo u32 ampdu_status;
6227ac9a364SKalle Valo u32 rate_n_flags;
6237ac9a364SKalle Valo
6247ac9a364SKalle Valo /**
6257ac9a364SKalle Valo * N_RX and N_RX_MPDU are handled differently.
6267ac9a364SKalle Valo * N_RX: physical layer info is in this buffer
6277ac9a364SKalle Valo * N_RX_MPDU: physical layer info was sent in separate
6287ac9a364SKalle Valo * command and cached in il->last_phy_res
6297ac9a364SKalle Valo *
6307ac9a364SKalle Valo * Here we set up local variables depending on which command is
6317ac9a364SKalle Valo * received.
6327ac9a364SKalle Valo */
6337ac9a364SKalle Valo if (pkt->hdr.cmd == N_RX) {
6347ac9a364SKalle Valo phy_res = (struct il_rx_phy_res *)pkt->u.raw;
6357ac9a364SKalle Valo header =
6367ac9a364SKalle Valo (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*phy_res) +
6377ac9a364SKalle Valo phy_res->cfg_phy_cnt);
6387ac9a364SKalle Valo
6397ac9a364SKalle Valo len = le16_to_cpu(phy_res->byte_count);
6407ac9a364SKalle Valo rx_pkt_status =
6417ac9a364SKalle Valo *(__le32 *) (pkt->u.raw + sizeof(*phy_res) +
6427ac9a364SKalle Valo phy_res->cfg_phy_cnt + len);
6437ac9a364SKalle Valo ampdu_status = le32_to_cpu(rx_pkt_status);
6447ac9a364SKalle Valo } else {
6457ac9a364SKalle Valo if (!il->_4965.last_phy_res_valid) {
6467ac9a364SKalle Valo IL_ERR("MPDU frame without cached PHY data\n");
6477ac9a364SKalle Valo return;
6487ac9a364SKalle Valo }
6497ac9a364SKalle Valo phy_res = &il->_4965.last_phy_res;
6507ac9a364SKalle Valo amsdu = (struct il_rx_mpdu_res_start *)pkt->u.raw;
6517ac9a364SKalle Valo header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu));
6527ac9a364SKalle Valo len = le16_to_cpu(amsdu->byte_count);
6537ac9a364SKalle Valo rx_pkt_status = *(__le32 *) (pkt->u.raw + sizeof(*amsdu) + len);
6547ac9a364SKalle Valo ampdu_status =
6557ac9a364SKalle Valo il4965_translate_rx_status(il, le32_to_cpu(rx_pkt_status));
6567ac9a364SKalle Valo }
6577ac9a364SKalle Valo
6587ac9a364SKalle Valo if ((unlikely(phy_res->cfg_phy_cnt > 20))) {
6597ac9a364SKalle Valo D_DROP("dsp size out of range [0,20]: %d\n",
6607ac9a364SKalle Valo phy_res->cfg_phy_cnt);
6617ac9a364SKalle Valo return;
6627ac9a364SKalle Valo }
6637ac9a364SKalle Valo
6647ac9a364SKalle Valo if (!(rx_pkt_status & RX_RES_STATUS_NO_CRC32_ERROR) ||
6657ac9a364SKalle Valo !(rx_pkt_status & RX_RES_STATUS_NO_RXE_OVERFLOW)) {
6667ac9a364SKalle Valo D_RX("Bad CRC or FIFO: 0x%08X.\n", le32_to_cpu(rx_pkt_status));
6677ac9a364SKalle Valo return;
6687ac9a364SKalle Valo }
6697ac9a364SKalle Valo
6707ac9a364SKalle Valo /* This will be used in several places later */
6717ac9a364SKalle Valo rate_n_flags = le32_to_cpu(phy_res->rate_n_flags);
6727ac9a364SKalle Valo
6737ac9a364SKalle Valo /* rx_status carries information about the packet to mac80211 */
6747ac9a364SKalle Valo rx_status.mactime = le64_to_cpu(phy_res->timestamp);
6757ac9a364SKalle Valo rx_status.band =
6767ac9a364SKalle Valo (phy_res->
67757fbcce3SJohannes Berg phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? NL80211_BAND_2GHZ :
67857fbcce3SJohannes Berg NL80211_BAND_5GHZ;
6797ac9a364SKalle Valo rx_status.freq =
6807ac9a364SKalle Valo ieee80211_channel_to_frequency(le16_to_cpu(phy_res->channel),
6817ac9a364SKalle Valo rx_status.band);
6827ac9a364SKalle Valo rx_status.rate_idx =
6837ac9a364SKalle Valo il4965_hwrate_to_mac80211_idx(rate_n_flags, rx_status.band);
6847ac9a364SKalle Valo rx_status.flag = 0;
6857ac9a364SKalle Valo
6867ac9a364SKalle Valo /* TSF isn't reliable. In order to allow smooth user experience,
6877ac9a364SKalle Valo * this W/A doesn't propagate it to the mac80211 */
6887ac9a364SKalle Valo /*rx_status.flag |= RX_FLAG_MACTIME_START; */
6897ac9a364SKalle Valo
6907ac9a364SKalle Valo il->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp);
6917ac9a364SKalle Valo
6927ac9a364SKalle Valo /* Find max signal strength (dBm) among 3 antenna/receiver chains */
6937ac9a364SKalle Valo rx_status.signal = il4965_calc_rssi(il, phy_res);
6947ac9a364SKalle Valo
6957ac9a364SKalle Valo D_STATS("Rssi %d, TSF %llu\n", rx_status.signal,
6967ac9a364SKalle Valo (unsigned long long)rx_status.mactime);
6977ac9a364SKalle Valo
6987ac9a364SKalle Valo /*
6997ac9a364SKalle Valo * "antenna number"
7007ac9a364SKalle Valo *
7017ac9a364SKalle Valo * It seems that the antenna field in the phy flags value
7027ac9a364SKalle Valo * is actually a bit field. This is undefined by radiotap,
7037ac9a364SKalle Valo * it wants an actual antenna number but I always get "7"
7047ac9a364SKalle Valo * for most legacy frames I receive indicating that the
7057ac9a364SKalle Valo * same frame was received on all three RX chains.
7067ac9a364SKalle Valo *
7077ac9a364SKalle Valo * I think this field should be removed in favor of a
7087ac9a364SKalle Valo * new 802.11n radiotap field "RX chains" that is defined
7097ac9a364SKalle Valo * as a bitmask.
7107ac9a364SKalle Valo */
7117ac9a364SKalle Valo rx_status.antenna =
7127ac9a364SKalle Valo (le16_to_cpu(phy_res->phy_flags) & RX_RES_PHY_FLAGS_ANTENNA_MSK) >>
7137ac9a364SKalle Valo RX_RES_PHY_FLAGS_ANTENNA_POS;
7147ac9a364SKalle Valo
7157ac9a364SKalle Valo /* set the preamble flag if appropriate */
7167ac9a364SKalle Valo if (phy_res->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
7177fdd69c5SJohannes Berg rx_status.enc_flags |= RX_ENC_FLAG_SHORTPRE;
7187ac9a364SKalle Valo
7197ac9a364SKalle Valo /* Set up the HT phy flags */
7207ac9a364SKalle Valo if (rate_n_flags & RATE_MCS_HT_MSK)
721da6a4352SJohannes Berg rx_status.encoding = RX_ENC_HT;
7227ac9a364SKalle Valo if (rate_n_flags & RATE_MCS_HT40_MSK)
7232f242bf4SJohannes Berg rx_status.bw = RATE_INFO_BW_40;
7242f242bf4SJohannes Berg else
7252f242bf4SJohannes Berg rx_status.bw = RATE_INFO_BW_20;
7267ac9a364SKalle Valo if (rate_n_flags & RATE_MCS_SGI_MSK)
7277fdd69c5SJohannes Berg rx_status.enc_flags |= RX_ENC_FLAG_SHORT_GI;
7287ac9a364SKalle Valo
7297ac9a364SKalle Valo if (phy_res->phy_flags & RX_RES_PHY_FLAGS_AGG_MSK) {
7307ac9a364SKalle Valo /* We know which subframes of an A-MPDU belong
7317ac9a364SKalle Valo * together since we get a single PHY response
7327ac9a364SKalle Valo * from the firmware for all of them.
7337ac9a364SKalle Valo */
7347ac9a364SKalle Valo
7357ac9a364SKalle Valo rx_status.flag |= RX_FLAG_AMPDU_DETAILS;
7367ac9a364SKalle Valo rx_status.ampdu_reference = il->_4965.ampdu_ref;
7377ac9a364SKalle Valo }
7387ac9a364SKalle Valo
7397ac9a364SKalle Valo il4965_pass_packet_to_mac80211(il, header, len, ampdu_status, rxb,
7407ac9a364SKalle Valo &rx_status);
7417ac9a364SKalle Valo }
7427ac9a364SKalle Valo
7437ac9a364SKalle Valo /* Cache phy data (Rx signal strength, etc) for HT frame (N_RX_PHY).
7447ac9a364SKalle Valo * This will be used later in il_hdl_rx() for N_RX_MPDU. */
7457ac9a364SKalle Valo static void
il4965_hdl_rx_phy(struct il_priv * il,struct il_rx_buf * rxb)7467ac9a364SKalle Valo il4965_hdl_rx_phy(struct il_priv *il, struct il_rx_buf *rxb)
7477ac9a364SKalle Valo {
7487ac9a364SKalle Valo struct il_rx_pkt *pkt = rxb_addr(rxb);
7497ac9a364SKalle Valo il->_4965.last_phy_res_valid = true;
7507ac9a364SKalle Valo il->_4965.ampdu_ref++;
7517ac9a364SKalle Valo memcpy(&il->_4965.last_phy_res, pkt->u.raw,
7527ac9a364SKalle Valo sizeof(struct il_rx_phy_res));
7537ac9a364SKalle Valo }
7547ac9a364SKalle Valo
7557ac9a364SKalle Valo static int
il4965_get_channels_for_scan(struct il_priv * il,struct ieee80211_vif * vif,enum nl80211_band band,u8 is_active,u8 n_probes,struct il_scan_channel * scan_ch)7567ac9a364SKalle Valo il4965_get_channels_for_scan(struct il_priv *il, struct ieee80211_vif *vif,
75757fbcce3SJohannes Berg enum nl80211_band band, u8 is_active,
7587ac9a364SKalle Valo u8 n_probes, struct il_scan_channel *scan_ch)
7597ac9a364SKalle Valo {
7607ac9a364SKalle Valo struct ieee80211_channel *chan;
7617ac9a364SKalle Valo const struct ieee80211_supported_band *sband;
7627ac9a364SKalle Valo const struct il_channel_info *ch_info;
7637ac9a364SKalle Valo u16 passive_dwell = 0;
7647ac9a364SKalle Valo u16 active_dwell = 0;
7657ac9a364SKalle Valo int added, i;
7667ac9a364SKalle Valo u16 channel;
7677ac9a364SKalle Valo
7687ac9a364SKalle Valo sband = il_get_hw_mode(il, band);
7697ac9a364SKalle Valo if (!sband)
7707ac9a364SKalle Valo return 0;
7717ac9a364SKalle Valo
7727ac9a364SKalle Valo active_dwell = il_get_active_dwell_time(il, band, n_probes);
7737ac9a364SKalle Valo passive_dwell = il_get_passive_dwell_time(il, band, vif);
7747ac9a364SKalle Valo
7757ac9a364SKalle Valo if (passive_dwell <= active_dwell)
7767ac9a364SKalle Valo passive_dwell = active_dwell + 1;
7777ac9a364SKalle Valo
7787ac9a364SKalle Valo for (i = 0, added = 0; i < il->scan_request->n_channels; i++) {
7797ac9a364SKalle Valo chan = il->scan_request->channels[i];
7807ac9a364SKalle Valo
7817ac9a364SKalle Valo if (chan->band != band)
7827ac9a364SKalle Valo continue;
7837ac9a364SKalle Valo
7847ac9a364SKalle Valo channel = chan->hw_value;
7857ac9a364SKalle Valo scan_ch->channel = cpu_to_le16(channel);
7867ac9a364SKalle Valo
7877ac9a364SKalle Valo ch_info = il_get_channel_info(il, band, channel);
7887ac9a364SKalle Valo if (!il_is_channel_valid(ch_info)) {
7897ac9a364SKalle Valo D_SCAN("Channel %d is INVALID for this band.\n",
7907ac9a364SKalle Valo channel);
7917ac9a364SKalle Valo continue;
7927ac9a364SKalle Valo }
7937ac9a364SKalle Valo
7947ac9a364SKalle Valo if (!is_active || il_is_channel_passive(ch_info) ||
7957ac9a364SKalle Valo (chan->flags & IEEE80211_CHAN_NO_IR))
7967ac9a364SKalle Valo scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
7977ac9a364SKalle Valo else
7987ac9a364SKalle Valo scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE;
7997ac9a364SKalle Valo
8007ac9a364SKalle Valo if (n_probes)
8017ac9a364SKalle Valo scan_ch->type |= IL_SCAN_PROBE_MASK(n_probes);
8027ac9a364SKalle Valo
8037ac9a364SKalle Valo scan_ch->active_dwell = cpu_to_le16(active_dwell);
8047ac9a364SKalle Valo scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
8057ac9a364SKalle Valo
8067ac9a364SKalle Valo /* Set txpower levels to defaults */
8077ac9a364SKalle Valo scan_ch->dsp_atten = 110;
8087ac9a364SKalle Valo
8097ac9a364SKalle Valo /* NOTE: if we were doing 6Mb OFDM for scans we'd use
8107ac9a364SKalle Valo * power level:
8117ac9a364SKalle Valo * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3;
8127ac9a364SKalle Valo */
81357fbcce3SJohannes Berg if (band == NL80211_BAND_5GHZ)
8147ac9a364SKalle Valo scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
8157ac9a364SKalle Valo else
8167ac9a364SKalle Valo scan_ch->tx_gain = ((1 << 5) | (5 << 3));
8177ac9a364SKalle Valo
8187ac9a364SKalle Valo D_SCAN("Scanning ch=%d prob=0x%X [%s %d]\n", channel,
8197ac9a364SKalle Valo le32_to_cpu(scan_ch->type),
8207ac9a364SKalle Valo (scan_ch->
8217ac9a364SKalle Valo type & SCAN_CHANNEL_TYPE_ACTIVE) ? "ACTIVE" : "PASSIVE",
8227ac9a364SKalle Valo (scan_ch->
8237ac9a364SKalle Valo type & SCAN_CHANNEL_TYPE_ACTIVE) ? active_dwell :
8247ac9a364SKalle Valo passive_dwell);
8257ac9a364SKalle Valo
8267ac9a364SKalle Valo scan_ch++;
8277ac9a364SKalle Valo added++;
8287ac9a364SKalle Valo }
8297ac9a364SKalle Valo
8307ac9a364SKalle Valo D_SCAN("total channels to scan %d\n", added);
8317ac9a364SKalle Valo return added;
8327ac9a364SKalle Valo }
8337ac9a364SKalle Valo
8347ac9a364SKalle Valo static void
il4965_toggle_tx_ant(struct il_priv * il,u8 * ant,u8 valid)8357ac9a364SKalle Valo il4965_toggle_tx_ant(struct il_priv *il, u8 *ant, u8 valid)
8367ac9a364SKalle Valo {
8377ac9a364SKalle Valo int i;
8387ac9a364SKalle Valo u8 ind = *ant;
8397ac9a364SKalle Valo
8407ac9a364SKalle Valo for (i = 0; i < RATE_ANT_NUM - 1; i++) {
8417ac9a364SKalle Valo ind = (ind + 1) < RATE_ANT_NUM ? ind + 1 : 0;
8427ac9a364SKalle Valo if (valid & BIT(ind)) {
8437ac9a364SKalle Valo *ant = ind;
8447ac9a364SKalle Valo return;
8457ac9a364SKalle Valo }
8467ac9a364SKalle Valo }
8477ac9a364SKalle Valo }
8487ac9a364SKalle Valo
8497ac9a364SKalle Valo int
il4965_request_scan(struct il_priv * il,struct ieee80211_vif * vif)8507ac9a364SKalle Valo il4965_request_scan(struct il_priv *il, struct ieee80211_vif *vif)
8517ac9a364SKalle Valo {
8527ac9a364SKalle Valo struct il_host_cmd cmd = {
8537ac9a364SKalle Valo .id = C_SCAN,
8547ac9a364SKalle Valo .len = sizeof(struct il_scan_cmd),
8557ac9a364SKalle Valo .flags = CMD_SIZE_HUGE,
8567ac9a364SKalle Valo };
8577ac9a364SKalle Valo struct il_scan_cmd *scan;
8587ac9a364SKalle Valo u32 rate_flags = 0;
8597ac9a364SKalle Valo u16 cmd_len;
8607ac9a364SKalle Valo u16 rx_chain = 0;
86157fbcce3SJohannes Berg enum nl80211_band band;
8627ac9a364SKalle Valo u8 n_probes = 0;
8637ac9a364SKalle Valo u8 rx_ant = il->hw_params.valid_rx_ant;
8647ac9a364SKalle Valo u8 rate;
8657ac9a364SKalle Valo bool is_active = false;
8667ac9a364SKalle Valo int chan_mod;
8677ac9a364SKalle Valo u8 active_chains;
8687ac9a364SKalle Valo u8 scan_tx_antennas = il->hw_params.valid_tx_ant;
8697ac9a364SKalle Valo int ret;
8707ac9a364SKalle Valo
8717ac9a364SKalle Valo lockdep_assert_held(&il->mutex);
8727ac9a364SKalle Valo
8737ac9a364SKalle Valo if (!il->scan_cmd) {
8747ac9a364SKalle Valo il->scan_cmd =
8757ac9a364SKalle Valo kmalloc(sizeof(struct il_scan_cmd) + IL_MAX_SCAN_SIZE,
8767ac9a364SKalle Valo GFP_KERNEL);
8777ac9a364SKalle Valo if (!il->scan_cmd) {
8787ac9a364SKalle Valo D_SCAN("fail to allocate memory for scan\n");
8797ac9a364SKalle Valo return -ENOMEM;
8807ac9a364SKalle Valo }
8817ac9a364SKalle Valo }
8827ac9a364SKalle Valo scan = il->scan_cmd;
8837ac9a364SKalle Valo memset(scan, 0, sizeof(struct il_scan_cmd) + IL_MAX_SCAN_SIZE);
8847ac9a364SKalle Valo
8857ac9a364SKalle Valo scan->quiet_plcp_th = IL_PLCP_QUIET_THRESH;
8867ac9a364SKalle Valo scan->quiet_time = IL_ACTIVE_QUIET_TIME;
8877ac9a364SKalle Valo
8887ac9a364SKalle Valo if (il_is_any_associated(il)) {
8897ac9a364SKalle Valo u16 interval;
8907ac9a364SKalle Valo u32 extra;
8917ac9a364SKalle Valo u32 suspend_time = 100;
8927ac9a364SKalle Valo u32 scan_suspend_time = 100;
8937ac9a364SKalle Valo
8947ac9a364SKalle Valo D_INFO("Scanning while associated...\n");
8957ac9a364SKalle Valo interval = vif->bss_conf.beacon_int;
8967ac9a364SKalle Valo
8977ac9a364SKalle Valo scan->suspend_time = 0;
8987ac9a364SKalle Valo scan->max_out_time = cpu_to_le32(200 * 1024);
8997ac9a364SKalle Valo if (!interval)
9007ac9a364SKalle Valo interval = suspend_time;
9017ac9a364SKalle Valo
9027ac9a364SKalle Valo extra = (suspend_time / interval) << 22;
9037ac9a364SKalle Valo scan_suspend_time =
9047ac9a364SKalle Valo (extra | ((suspend_time % interval) * 1024));
9057ac9a364SKalle Valo scan->suspend_time = cpu_to_le32(scan_suspend_time);
9067ac9a364SKalle Valo D_SCAN("suspend_time 0x%X beacon interval %d\n",
9077ac9a364SKalle Valo scan_suspend_time, interval);
9087ac9a364SKalle Valo }
9097ac9a364SKalle Valo
9107ac9a364SKalle Valo if (il->scan_request->n_ssids) {
9117ac9a364SKalle Valo int i, p = 0;
9127ac9a364SKalle Valo D_SCAN("Kicking off active scan\n");
9137ac9a364SKalle Valo for (i = 0; i < il->scan_request->n_ssids; i++) {
9147ac9a364SKalle Valo /* always does wildcard anyway */
9157ac9a364SKalle Valo if (!il->scan_request->ssids[i].ssid_len)
9167ac9a364SKalle Valo continue;
9177ac9a364SKalle Valo scan->direct_scan[p].id = WLAN_EID_SSID;
9187ac9a364SKalle Valo scan->direct_scan[p].len =
9197ac9a364SKalle Valo il->scan_request->ssids[i].ssid_len;
9207ac9a364SKalle Valo memcpy(scan->direct_scan[p].ssid,
9217ac9a364SKalle Valo il->scan_request->ssids[i].ssid,
9227ac9a364SKalle Valo il->scan_request->ssids[i].ssid_len);
9237ac9a364SKalle Valo n_probes++;
9247ac9a364SKalle Valo p++;
9257ac9a364SKalle Valo }
9267ac9a364SKalle Valo is_active = true;
9277ac9a364SKalle Valo } else
9287ac9a364SKalle Valo D_SCAN("Start passive scan.\n");
9297ac9a364SKalle Valo
9307ac9a364SKalle Valo scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
9317ac9a364SKalle Valo scan->tx_cmd.sta_id = il->hw_params.bcast_id;
9327ac9a364SKalle Valo scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
9337ac9a364SKalle Valo
9347ac9a364SKalle Valo switch (il->scan_band) {
93557fbcce3SJohannes Berg case NL80211_BAND_2GHZ:
9367ac9a364SKalle Valo scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
9377ac9a364SKalle Valo chan_mod =
9387ac9a364SKalle Valo le32_to_cpu(il->active.flags & RXON_FLG_CHANNEL_MODE_MSK) >>
9397ac9a364SKalle Valo RXON_FLG_CHANNEL_MODE_POS;
9407ac9a364SKalle Valo if (chan_mod == CHANNEL_MODE_PURE_40) {
9417ac9a364SKalle Valo rate = RATE_6M_PLCP;
9427ac9a364SKalle Valo } else {
9437ac9a364SKalle Valo rate = RATE_1M_PLCP;
9447ac9a364SKalle Valo rate_flags = RATE_MCS_CCK_MSK;
9457ac9a364SKalle Valo }
9467ac9a364SKalle Valo break;
94757fbcce3SJohannes Berg case NL80211_BAND_5GHZ:
9487ac9a364SKalle Valo rate = RATE_6M_PLCP;
9497ac9a364SKalle Valo break;
9507ac9a364SKalle Valo default:
9517ac9a364SKalle Valo IL_WARN("Invalid scan band\n");
9527ac9a364SKalle Valo return -EIO;
9537ac9a364SKalle Valo }
9547ac9a364SKalle Valo
9557ac9a364SKalle Valo /*
9567ac9a364SKalle Valo * If active scanning is requested but a certain channel is
9577ac9a364SKalle Valo * marked passive, we can do active scanning if we detect
9587ac9a364SKalle Valo * transmissions.
9597ac9a364SKalle Valo *
9607ac9a364SKalle Valo * There is an issue with some firmware versions that triggers
9617ac9a364SKalle Valo * a sysassert on a "good CRC threshold" of zero (== disabled),
9627ac9a364SKalle Valo * on a radar channel even though this means that we should NOT
9637ac9a364SKalle Valo * send probes.
9647ac9a364SKalle Valo *
9657ac9a364SKalle Valo * The "good CRC threshold" is the number of frames that we
9667ac9a364SKalle Valo * need to receive during our dwell time on a channel before
9677ac9a364SKalle Valo * sending out probes -- setting this to a huge value will
9687ac9a364SKalle Valo * mean we never reach it, but at the same time work around
9697ac9a364SKalle Valo * the aforementioned issue. Thus use IL_GOOD_CRC_TH_NEVER
9707ac9a364SKalle Valo * here instead of IL_GOOD_CRC_TH_DISABLED.
9717ac9a364SKalle Valo */
9727ac9a364SKalle Valo scan->good_CRC_th =
9737ac9a364SKalle Valo is_active ? IL_GOOD_CRC_TH_DEFAULT : IL_GOOD_CRC_TH_NEVER;
9747ac9a364SKalle Valo
9757ac9a364SKalle Valo band = il->scan_band;
9767ac9a364SKalle Valo
9777ac9a364SKalle Valo if (il->cfg->scan_rx_antennas[band])
9787ac9a364SKalle Valo rx_ant = il->cfg->scan_rx_antennas[band];
9797ac9a364SKalle Valo
9807ac9a364SKalle Valo il4965_toggle_tx_ant(il, &il->scan_tx_ant[band], scan_tx_antennas);
9817ac9a364SKalle Valo rate_flags |= BIT(il->scan_tx_ant[band]) << RATE_MCS_ANT_POS;
9827ac9a364SKalle Valo scan->tx_cmd.rate_n_flags = cpu_to_le32(rate | rate_flags);
9837ac9a364SKalle Valo
9847ac9a364SKalle Valo /* In power save mode use one chain, otherwise use all chains */
9857ac9a364SKalle Valo if (test_bit(S_POWER_PMI, &il->status)) {
9867ac9a364SKalle Valo /* rx_ant has been set to all valid chains previously */
9877ac9a364SKalle Valo active_chains =
9887ac9a364SKalle Valo rx_ant & ((u8) (il->chain_noise_data.active_chains));
9897ac9a364SKalle Valo if (!active_chains)
9907ac9a364SKalle Valo active_chains = rx_ant;
9917ac9a364SKalle Valo
9927ac9a364SKalle Valo D_SCAN("chain_noise_data.active_chains: %u\n",
9937ac9a364SKalle Valo il->chain_noise_data.active_chains);
9947ac9a364SKalle Valo
9957ac9a364SKalle Valo rx_ant = il4965_first_antenna(active_chains);
9967ac9a364SKalle Valo }
9977ac9a364SKalle Valo
9987ac9a364SKalle Valo /* MIMO is not used here, but value is required */
9997ac9a364SKalle Valo rx_chain |= il->hw_params.valid_rx_ant << RXON_RX_CHAIN_VALID_POS;
10007ac9a364SKalle Valo rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS;
10017ac9a364SKalle Valo rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS;
10027ac9a364SKalle Valo rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS;
10037ac9a364SKalle Valo scan->rx_chain = cpu_to_le16(rx_chain);
10047ac9a364SKalle Valo
10057ac9a364SKalle Valo cmd_len =
10067ac9a364SKalle Valo il_fill_probe_req(il, (struct ieee80211_mgmt *)scan->data,
10077ac9a364SKalle Valo vif->addr, il->scan_request->ie,
10087ac9a364SKalle Valo il->scan_request->ie_len,
10097ac9a364SKalle Valo IL_MAX_SCAN_SIZE - sizeof(*scan));
10107ac9a364SKalle Valo scan->tx_cmd.len = cpu_to_le16(cmd_len);
10117ac9a364SKalle Valo
10127ac9a364SKalle Valo scan->filter_flags |=
10137ac9a364SKalle Valo (RXON_FILTER_ACCEPT_GRP_MSK | RXON_FILTER_BCON_AWARE_MSK);
10147ac9a364SKalle Valo
10157ac9a364SKalle Valo scan->channel_count =
10167ac9a364SKalle Valo il4965_get_channels_for_scan(il, vif, band, is_active, n_probes,
10177ac9a364SKalle Valo (void *)&scan->data[cmd_len]);
10187ac9a364SKalle Valo if (scan->channel_count == 0) {
10197ac9a364SKalle Valo D_SCAN("channel count %d\n", scan->channel_count);
10207ac9a364SKalle Valo return -EIO;
10217ac9a364SKalle Valo }
10227ac9a364SKalle Valo
10237ac9a364SKalle Valo cmd.len +=
10247ac9a364SKalle Valo le16_to_cpu(scan->tx_cmd.len) +
10257ac9a364SKalle Valo scan->channel_count * sizeof(struct il_scan_channel);
10267ac9a364SKalle Valo cmd.data = scan;
10277ac9a364SKalle Valo scan->len = cpu_to_le16(cmd.len);
10287ac9a364SKalle Valo
10297ac9a364SKalle Valo set_bit(S_SCAN_HW, &il->status);
10307ac9a364SKalle Valo
10317ac9a364SKalle Valo ret = il_send_cmd_sync(il, &cmd);
10327ac9a364SKalle Valo if (ret)
10337ac9a364SKalle Valo clear_bit(S_SCAN_HW, &il->status);
10347ac9a364SKalle Valo
10357ac9a364SKalle Valo return ret;
10367ac9a364SKalle Valo }
10377ac9a364SKalle Valo
10387ac9a364SKalle Valo int
il4965_manage_ibss_station(struct il_priv * il,struct ieee80211_vif * vif,bool add)10397ac9a364SKalle Valo il4965_manage_ibss_station(struct il_priv *il, struct ieee80211_vif *vif,
10407ac9a364SKalle Valo bool add)
10417ac9a364SKalle Valo {
10427ac9a364SKalle Valo struct il_vif_priv *vif_priv = (void *)vif->drv_priv;
10437ac9a364SKalle Valo
10447ac9a364SKalle Valo if (add)
10457ac9a364SKalle Valo return il4965_add_bssid_station(il, vif->bss_conf.bssid,
10467ac9a364SKalle Valo &vif_priv->ibss_bssid_sta_id);
10477ac9a364SKalle Valo return il_remove_station(il, vif_priv->ibss_bssid_sta_id,
10487ac9a364SKalle Valo vif->bss_conf.bssid);
10497ac9a364SKalle Valo }
10507ac9a364SKalle Valo
10517ac9a364SKalle Valo void
il4965_free_tfds_in_queue(struct il_priv * il,int sta_id,int tid,int freed)10527ac9a364SKalle Valo il4965_free_tfds_in_queue(struct il_priv *il, int sta_id, int tid, int freed)
10537ac9a364SKalle Valo {
10547ac9a364SKalle Valo lockdep_assert_held(&il->sta_lock);
10557ac9a364SKalle Valo
10567ac9a364SKalle Valo if (il->stations[sta_id].tid[tid].tfds_in_queue >= freed)
10577ac9a364SKalle Valo il->stations[sta_id].tid[tid].tfds_in_queue -= freed;
10587ac9a364SKalle Valo else {
10597ac9a364SKalle Valo D_TX("free more than tfds_in_queue (%u:%d)\n",
10607ac9a364SKalle Valo il->stations[sta_id].tid[tid].tfds_in_queue, freed);
10617ac9a364SKalle Valo il->stations[sta_id].tid[tid].tfds_in_queue = 0;
10627ac9a364SKalle Valo }
10637ac9a364SKalle Valo }
10647ac9a364SKalle Valo
10657ac9a364SKalle Valo #define IL_TX_QUEUE_MSK 0xfffff
10667ac9a364SKalle Valo
10677ac9a364SKalle Valo static bool
il4965_is_single_rx_stream(struct il_priv * il)10687ac9a364SKalle Valo il4965_is_single_rx_stream(struct il_priv *il)
10697ac9a364SKalle Valo {
10707ac9a364SKalle Valo return il->current_ht_config.smps == IEEE80211_SMPS_STATIC ||
10717ac9a364SKalle Valo il->current_ht_config.single_chain_sufficient;
10727ac9a364SKalle Valo }
10737ac9a364SKalle Valo
10747ac9a364SKalle Valo #define IL_NUM_RX_CHAINS_MULTIPLE 3
10757ac9a364SKalle Valo #define IL_NUM_RX_CHAINS_SINGLE 2
10767ac9a364SKalle Valo #define IL_NUM_IDLE_CHAINS_DUAL 2
10777ac9a364SKalle Valo #define IL_NUM_IDLE_CHAINS_SINGLE 1
10787ac9a364SKalle Valo
10797ac9a364SKalle Valo /*
10807ac9a364SKalle Valo * Determine how many receiver/antenna chains to use.
10817ac9a364SKalle Valo *
10827ac9a364SKalle Valo * More provides better reception via diversity. Fewer saves power
10837ac9a364SKalle Valo * at the expense of throughput, but only when not in powersave to
10847ac9a364SKalle Valo * start with.
10857ac9a364SKalle Valo *
10867ac9a364SKalle Valo * MIMO (dual stream) requires at least 2, but works better with 3.
10877ac9a364SKalle Valo * This does not determine *which* chains to use, just how many.
10887ac9a364SKalle Valo */
10897ac9a364SKalle Valo static int
il4965_get_active_rx_chain_count(struct il_priv * il)10907ac9a364SKalle Valo il4965_get_active_rx_chain_count(struct il_priv *il)
10917ac9a364SKalle Valo {
10927ac9a364SKalle Valo /* # of Rx chains to use when expecting MIMO. */
10937ac9a364SKalle Valo if (il4965_is_single_rx_stream(il))
10947ac9a364SKalle Valo return IL_NUM_RX_CHAINS_SINGLE;
10957ac9a364SKalle Valo else
10967ac9a364SKalle Valo return IL_NUM_RX_CHAINS_MULTIPLE;
10977ac9a364SKalle Valo }
10987ac9a364SKalle Valo
10997ac9a364SKalle Valo /*
11007ac9a364SKalle Valo * When we are in power saving mode, unless device support spatial
11017ac9a364SKalle Valo * multiplexing power save, use the active count for rx chain count.
11027ac9a364SKalle Valo */
11037ac9a364SKalle Valo static int
il4965_get_idle_rx_chain_count(struct il_priv * il,int active_cnt)11047ac9a364SKalle Valo il4965_get_idle_rx_chain_count(struct il_priv *il, int active_cnt)
11057ac9a364SKalle Valo {
11067ac9a364SKalle Valo /* # Rx chains when idling, depending on SMPS mode */
11077ac9a364SKalle Valo switch (il->current_ht_config.smps) {
11087ac9a364SKalle Valo case IEEE80211_SMPS_STATIC:
11097ac9a364SKalle Valo case IEEE80211_SMPS_DYNAMIC:
11107ac9a364SKalle Valo return IL_NUM_IDLE_CHAINS_SINGLE;
11117ac9a364SKalle Valo case IEEE80211_SMPS_OFF:
11127ac9a364SKalle Valo return active_cnt;
11137ac9a364SKalle Valo default:
11147ac9a364SKalle Valo WARN(1, "invalid SMPS mode %d", il->current_ht_config.smps);
11157ac9a364SKalle Valo return active_cnt;
11167ac9a364SKalle Valo }
11177ac9a364SKalle Valo }
11187ac9a364SKalle Valo
11197ac9a364SKalle Valo /* up to 4 chains */
11207ac9a364SKalle Valo static u8
il4965_count_chain_bitmap(u32 chain_bitmap)11217ac9a364SKalle Valo il4965_count_chain_bitmap(u32 chain_bitmap)
11227ac9a364SKalle Valo {
11237ac9a364SKalle Valo u8 res;
11247ac9a364SKalle Valo res = (chain_bitmap & BIT(0)) >> 0;
11257ac9a364SKalle Valo res += (chain_bitmap & BIT(1)) >> 1;
11267ac9a364SKalle Valo res += (chain_bitmap & BIT(2)) >> 2;
11277ac9a364SKalle Valo res += (chain_bitmap & BIT(3)) >> 3;
11287ac9a364SKalle Valo return res;
11297ac9a364SKalle Valo }
11307ac9a364SKalle Valo
113135b7fbfcSLee Jones /*
11327ac9a364SKalle Valo * il4965_set_rxon_chain - Set up Rx chain usage in "staging" RXON image
11337ac9a364SKalle Valo *
11347ac9a364SKalle Valo * Selects how many and which Rx receivers/antennas/chains to use.
11357ac9a364SKalle Valo * This should not be used for scan command ... it puts data in wrong place.
11367ac9a364SKalle Valo */
11377ac9a364SKalle Valo void
il4965_set_rxon_chain(struct il_priv * il)11387ac9a364SKalle Valo il4965_set_rxon_chain(struct il_priv *il)
11397ac9a364SKalle Valo {
11407ac9a364SKalle Valo bool is_single = il4965_is_single_rx_stream(il);
11417ac9a364SKalle Valo bool is_cam = !test_bit(S_POWER_PMI, &il->status);
11427ac9a364SKalle Valo u8 idle_rx_cnt, active_rx_cnt, valid_rx_cnt;
11437ac9a364SKalle Valo u32 active_chains;
11447ac9a364SKalle Valo u16 rx_chain;
11457ac9a364SKalle Valo
11467ac9a364SKalle Valo /* Tell uCode which antennas are actually connected.
11477ac9a364SKalle Valo * Before first association, we assume all antennas are connected.
11487ac9a364SKalle Valo * Just after first association, il4965_chain_noise_calibration()
11497ac9a364SKalle Valo * checks which antennas actually *are* connected. */
11507ac9a364SKalle Valo if (il->chain_noise_data.active_chains)
11517ac9a364SKalle Valo active_chains = il->chain_noise_data.active_chains;
11527ac9a364SKalle Valo else
11537ac9a364SKalle Valo active_chains = il->hw_params.valid_rx_ant;
11547ac9a364SKalle Valo
11557ac9a364SKalle Valo rx_chain = active_chains << RXON_RX_CHAIN_VALID_POS;
11567ac9a364SKalle Valo
11577ac9a364SKalle Valo /* How many receivers should we use? */
11587ac9a364SKalle Valo active_rx_cnt = il4965_get_active_rx_chain_count(il);
11597ac9a364SKalle Valo idle_rx_cnt = il4965_get_idle_rx_chain_count(il, active_rx_cnt);
11607ac9a364SKalle Valo
11617ac9a364SKalle Valo /* correct rx chain count according hw settings
11627ac9a364SKalle Valo * and chain noise calibration
11637ac9a364SKalle Valo */
11647ac9a364SKalle Valo valid_rx_cnt = il4965_count_chain_bitmap(active_chains);
11657ac9a364SKalle Valo if (valid_rx_cnt < active_rx_cnt)
11667ac9a364SKalle Valo active_rx_cnt = valid_rx_cnt;
11677ac9a364SKalle Valo
11687ac9a364SKalle Valo if (valid_rx_cnt < idle_rx_cnt)
11697ac9a364SKalle Valo idle_rx_cnt = valid_rx_cnt;
11707ac9a364SKalle Valo
11717ac9a364SKalle Valo rx_chain |= active_rx_cnt << RXON_RX_CHAIN_MIMO_CNT_POS;
11727ac9a364SKalle Valo rx_chain |= idle_rx_cnt << RXON_RX_CHAIN_CNT_POS;
11737ac9a364SKalle Valo
11747ac9a364SKalle Valo il->staging.rx_chain = cpu_to_le16(rx_chain);
11757ac9a364SKalle Valo
11767ac9a364SKalle Valo if (!is_single && active_rx_cnt >= IL_NUM_RX_CHAINS_SINGLE && is_cam)
11777ac9a364SKalle Valo il->staging.rx_chain |= RXON_RX_CHAIN_MIMO_FORCE_MSK;
11787ac9a364SKalle Valo else
11797ac9a364SKalle Valo il->staging.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK;
11807ac9a364SKalle Valo
11817ac9a364SKalle Valo D_ASSOC("rx_chain=0x%X active=%d idle=%d\n", il->staging.rx_chain,
11827ac9a364SKalle Valo active_rx_cnt, idle_rx_cnt);
11837ac9a364SKalle Valo
11847ac9a364SKalle Valo WARN_ON(active_rx_cnt == 0 || idle_rx_cnt == 0 ||
11857ac9a364SKalle Valo active_rx_cnt < idle_rx_cnt);
11867ac9a364SKalle Valo }
11877ac9a364SKalle Valo
11887ac9a364SKalle Valo static const char *
il4965_get_fh_string(int cmd)11897ac9a364SKalle Valo il4965_get_fh_string(int cmd)
11907ac9a364SKalle Valo {
11917ac9a364SKalle Valo switch (cmd) {
11927ac9a364SKalle Valo IL_CMD(FH49_RSCSR_CHNL0_STTS_WPTR_REG);
11937ac9a364SKalle Valo IL_CMD(FH49_RSCSR_CHNL0_RBDCB_BASE_REG);
11947ac9a364SKalle Valo IL_CMD(FH49_RSCSR_CHNL0_WPTR);
11957ac9a364SKalle Valo IL_CMD(FH49_MEM_RCSR_CHNL0_CONFIG_REG);
11967ac9a364SKalle Valo IL_CMD(FH49_MEM_RSSR_SHARED_CTRL_REG);
11977ac9a364SKalle Valo IL_CMD(FH49_MEM_RSSR_RX_STATUS_REG);
11987ac9a364SKalle Valo IL_CMD(FH49_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV);
11997ac9a364SKalle Valo IL_CMD(FH49_TSSR_TX_STATUS_REG);
12007ac9a364SKalle Valo IL_CMD(FH49_TSSR_TX_ERROR_REG);
12017ac9a364SKalle Valo default:
12027ac9a364SKalle Valo return "UNKNOWN";
12037ac9a364SKalle Valo }
12047ac9a364SKalle Valo }
12057ac9a364SKalle Valo
12067ac9a364SKalle Valo int
il4965_dump_fh(struct il_priv * il,char ** buf,bool display)12077ac9a364SKalle Valo il4965_dump_fh(struct il_priv *il, char **buf, bool display)
12087ac9a364SKalle Valo {
12097ac9a364SKalle Valo int i;
12107ac9a364SKalle Valo #ifdef CONFIG_IWLEGACY_DEBUG
12117ac9a364SKalle Valo int pos = 0;
12127ac9a364SKalle Valo size_t bufsz = 0;
12137ac9a364SKalle Valo #endif
12147ac9a364SKalle Valo static const u32 fh_tbl[] = {
12157ac9a364SKalle Valo FH49_RSCSR_CHNL0_STTS_WPTR_REG,
12167ac9a364SKalle Valo FH49_RSCSR_CHNL0_RBDCB_BASE_REG,
12177ac9a364SKalle Valo FH49_RSCSR_CHNL0_WPTR,
12187ac9a364SKalle Valo FH49_MEM_RCSR_CHNL0_CONFIG_REG,
12197ac9a364SKalle Valo FH49_MEM_RSSR_SHARED_CTRL_REG,
12207ac9a364SKalle Valo FH49_MEM_RSSR_RX_STATUS_REG,
12217ac9a364SKalle Valo FH49_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV,
12227ac9a364SKalle Valo FH49_TSSR_TX_STATUS_REG,
12237ac9a364SKalle Valo FH49_TSSR_TX_ERROR_REG
12247ac9a364SKalle Valo };
12257ac9a364SKalle Valo #ifdef CONFIG_IWLEGACY_DEBUG
12267ac9a364SKalle Valo if (display) {
12277ac9a364SKalle Valo bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40;
12287ac9a364SKalle Valo *buf = kmalloc(bufsz, GFP_KERNEL);
12297ac9a364SKalle Valo if (!*buf)
12307ac9a364SKalle Valo return -ENOMEM;
12317ac9a364SKalle Valo pos +=
12327ac9a364SKalle Valo scnprintf(*buf + pos, bufsz - pos, "FH register values:\n");
12337ac9a364SKalle Valo for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) {
12347ac9a364SKalle Valo pos +=
12357ac9a364SKalle Valo scnprintf(*buf + pos, bufsz - pos,
12367ac9a364SKalle Valo " %34s: 0X%08x\n",
12377ac9a364SKalle Valo il4965_get_fh_string(fh_tbl[i]),
12387ac9a364SKalle Valo il_rd(il, fh_tbl[i]));
12397ac9a364SKalle Valo }
12407ac9a364SKalle Valo return pos;
12417ac9a364SKalle Valo }
12427ac9a364SKalle Valo #endif
12437ac9a364SKalle Valo IL_ERR("FH register values:\n");
12447ac9a364SKalle Valo for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) {
12457ac9a364SKalle Valo IL_ERR(" %34s: 0X%08x\n", il4965_get_fh_string(fh_tbl[i]),
12467ac9a364SKalle Valo il_rd(il, fh_tbl[i]));
12477ac9a364SKalle Valo }
12487ac9a364SKalle Valo return 0;
12497ac9a364SKalle Valo }
12507ac9a364SKalle Valo
12517ac9a364SKalle Valo static void
il4965_hdl_missed_beacon(struct il_priv * il,struct il_rx_buf * rxb)12527ac9a364SKalle Valo il4965_hdl_missed_beacon(struct il_priv *il, struct il_rx_buf *rxb)
12537ac9a364SKalle Valo {
12547ac9a364SKalle Valo struct il_rx_pkt *pkt = rxb_addr(rxb);
12557ac9a364SKalle Valo struct il_missed_beacon_notif *missed_beacon;
12567ac9a364SKalle Valo
12577ac9a364SKalle Valo missed_beacon = &pkt->u.missed_beacon;
12587ac9a364SKalle Valo if (le32_to_cpu(missed_beacon->consecutive_missed_beacons) >
12597ac9a364SKalle Valo il->missed_beacon_threshold) {
12607ac9a364SKalle Valo D_CALIB("missed bcn cnsq %d totl %d rcd %d expctd %d\n",
12617ac9a364SKalle Valo le32_to_cpu(missed_beacon->consecutive_missed_beacons),
12627ac9a364SKalle Valo le32_to_cpu(missed_beacon->total_missed_becons),
12637ac9a364SKalle Valo le32_to_cpu(missed_beacon->num_recvd_beacons),
12647ac9a364SKalle Valo le32_to_cpu(missed_beacon->num_expected_beacons));
12657ac9a364SKalle Valo if (!test_bit(S_SCANNING, &il->status))
12667ac9a364SKalle Valo il4965_init_sensitivity(il);
12677ac9a364SKalle Valo }
12687ac9a364SKalle Valo }
12697ac9a364SKalle Valo
12707ac9a364SKalle Valo /* Calculate noise level, based on measurements during network silence just
12717ac9a364SKalle Valo * before arriving beacon. This measurement can be done only if we know
12727ac9a364SKalle Valo * exactly when to expect beacons, therefore only when we're associated. */
12737ac9a364SKalle Valo static void
il4965_rx_calc_noise(struct il_priv * il)12747ac9a364SKalle Valo il4965_rx_calc_noise(struct il_priv *il)
12757ac9a364SKalle Valo {
12767ac9a364SKalle Valo struct stats_rx_non_phy *rx_info;
12777ac9a364SKalle Valo int num_active_rx = 0;
12787ac9a364SKalle Valo int total_silence = 0;
12797ac9a364SKalle Valo int bcn_silence_a, bcn_silence_b, bcn_silence_c;
12807ac9a364SKalle Valo int last_rx_noise;
12817ac9a364SKalle Valo
12827ac9a364SKalle Valo rx_info = &(il->_4965.stats.rx.general);
12837ac9a364SKalle Valo bcn_silence_a =
12847ac9a364SKalle Valo le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER;
12857ac9a364SKalle Valo bcn_silence_b =
12867ac9a364SKalle Valo le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER;
12877ac9a364SKalle Valo bcn_silence_c =
12887ac9a364SKalle Valo le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER;
12897ac9a364SKalle Valo
12907ac9a364SKalle Valo if (bcn_silence_a) {
12917ac9a364SKalle Valo total_silence += bcn_silence_a;
12927ac9a364SKalle Valo num_active_rx++;
12937ac9a364SKalle Valo }
12947ac9a364SKalle Valo if (bcn_silence_b) {
12957ac9a364SKalle Valo total_silence += bcn_silence_b;
12967ac9a364SKalle Valo num_active_rx++;
12977ac9a364SKalle Valo }
12987ac9a364SKalle Valo if (bcn_silence_c) {
12997ac9a364SKalle Valo total_silence += bcn_silence_c;
13007ac9a364SKalle Valo num_active_rx++;
13017ac9a364SKalle Valo }
13027ac9a364SKalle Valo
13037ac9a364SKalle Valo /* Average among active antennas */
13047ac9a364SKalle Valo if (num_active_rx)
13057ac9a364SKalle Valo last_rx_noise = (total_silence / num_active_rx) - 107;
13067ac9a364SKalle Valo else
13077ac9a364SKalle Valo last_rx_noise = IL_NOISE_MEAS_NOT_AVAILABLE;
13087ac9a364SKalle Valo
13097ac9a364SKalle Valo D_CALIB("inband silence a %u, b %u, c %u, dBm %d\n", bcn_silence_a,
13107ac9a364SKalle Valo bcn_silence_b, bcn_silence_c, last_rx_noise);
13117ac9a364SKalle Valo }
13127ac9a364SKalle Valo
13137ac9a364SKalle Valo #ifdef CONFIG_IWLEGACY_DEBUGFS
13147ac9a364SKalle Valo /*
13157ac9a364SKalle Valo * based on the assumption of all stats counter are in DWORD
13167ac9a364SKalle Valo * FIXME: This function is for debugging, do not deal with
13177ac9a364SKalle Valo * the case of counters roll-over.
13187ac9a364SKalle Valo */
13197ac9a364SKalle Valo static void
il4965_accumulative_stats(struct il_priv * il,__le32 * stats)13207ac9a364SKalle Valo il4965_accumulative_stats(struct il_priv *il, __le32 * stats)
13217ac9a364SKalle Valo {
13227ac9a364SKalle Valo int i, size;
13237ac9a364SKalle Valo __le32 *prev_stats;
13247ac9a364SKalle Valo u32 *accum_stats;
13257ac9a364SKalle Valo u32 *delta, *max_delta;
13267ac9a364SKalle Valo struct stats_general_common *general, *accum_general;
13277ac9a364SKalle Valo
13287ac9a364SKalle Valo prev_stats = (__le32 *) &il->_4965.stats;
13297ac9a364SKalle Valo accum_stats = (u32 *) &il->_4965.accum_stats;
13307ac9a364SKalle Valo size = sizeof(struct il_notif_stats);
13317ac9a364SKalle Valo general = &il->_4965.stats.general.common;
13327ac9a364SKalle Valo accum_general = &il->_4965.accum_stats.general.common;
13337ac9a364SKalle Valo delta = (u32 *) &il->_4965.delta_stats;
13347ac9a364SKalle Valo max_delta = (u32 *) &il->_4965.max_delta;
13357ac9a364SKalle Valo
13367ac9a364SKalle Valo for (i = sizeof(__le32); i < size;
13377ac9a364SKalle Valo i +=
13387ac9a364SKalle Valo sizeof(__le32), stats++, prev_stats++, delta++, max_delta++,
13397ac9a364SKalle Valo accum_stats++) {
13407ac9a364SKalle Valo if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) {
13417ac9a364SKalle Valo *delta =
13427ac9a364SKalle Valo (le32_to_cpu(*stats) - le32_to_cpu(*prev_stats));
13437ac9a364SKalle Valo *accum_stats += *delta;
13447ac9a364SKalle Valo if (*delta > *max_delta)
13457ac9a364SKalle Valo *max_delta = *delta;
13467ac9a364SKalle Valo }
13477ac9a364SKalle Valo }
13487ac9a364SKalle Valo
13497ac9a364SKalle Valo /* reset accumulative stats for "no-counter" type stats */
13507ac9a364SKalle Valo accum_general->temperature = general->temperature;
13517ac9a364SKalle Valo accum_general->ttl_timestamp = general->ttl_timestamp;
13527ac9a364SKalle Valo }
13537ac9a364SKalle Valo #endif
13547ac9a364SKalle Valo
13557ac9a364SKalle Valo static void
il4965_hdl_stats(struct il_priv * il,struct il_rx_buf * rxb)13567ac9a364SKalle Valo il4965_hdl_stats(struct il_priv *il, struct il_rx_buf *rxb)
13577ac9a364SKalle Valo {
13587ac9a364SKalle Valo const int recalib_seconds = 60;
13597ac9a364SKalle Valo bool change;
13607ac9a364SKalle Valo struct il_rx_pkt *pkt = rxb_addr(rxb);
13617ac9a364SKalle Valo
13627ac9a364SKalle Valo D_RX("Statistics notification received (%d vs %d).\n",
13637ac9a364SKalle Valo (int)sizeof(struct il_notif_stats),
13647ac9a364SKalle Valo le32_to_cpu(pkt->len_n_flags) & IL_RX_FRAME_SIZE_MSK);
13657ac9a364SKalle Valo
13667ac9a364SKalle Valo change =
13677ac9a364SKalle Valo ((il->_4965.stats.general.common.temperature !=
13687ac9a364SKalle Valo pkt->u.stats.general.common.temperature) ||
13697ac9a364SKalle Valo ((il->_4965.stats.flag & STATS_REPLY_FLG_HT40_MODE_MSK) !=
13707ac9a364SKalle Valo (pkt->u.stats.flag & STATS_REPLY_FLG_HT40_MODE_MSK)));
13717ac9a364SKalle Valo #ifdef CONFIG_IWLEGACY_DEBUGFS
13727ac9a364SKalle Valo il4965_accumulative_stats(il, (__le32 *) &pkt->u.stats);
13737ac9a364SKalle Valo #endif
13747ac9a364SKalle Valo
13757ac9a364SKalle Valo /* TODO: reading some of stats is unneeded */
13767ac9a364SKalle Valo memcpy(&il->_4965.stats, &pkt->u.stats, sizeof(il->_4965.stats));
13777ac9a364SKalle Valo
13787ac9a364SKalle Valo set_bit(S_STATS, &il->status);
13797ac9a364SKalle Valo
13807ac9a364SKalle Valo /*
13817ac9a364SKalle Valo * Reschedule the stats timer to occur in recalib_seconds to ensure
13827ac9a364SKalle Valo * we get a thermal update even if the uCode doesn't give us one
13837ac9a364SKalle Valo */
13847ac9a364SKalle Valo mod_timer(&il->stats_periodic,
13857ac9a364SKalle Valo jiffies + msecs_to_jiffies(recalib_seconds * 1000));
13867ac9a364SKalle Valo
13877ac9a364SKalle Valo if (unlikely(!test_bit(S_SCANNING, &il->status)) &&
13887ac9a364SKalle Valo (pkt->hdr.cmd == N_STATS)) {
13897ac9a364SKalle Valo il4965_rx_calc_noise(il);
13907ac9a364SKalle Valo queue_work(il->workqueue, &il->run_time_calib_work);
13917ac9a364SKalle Valo }
13927ac9a364SKalle Valo
13937ac9a364SKalle Valo if (change)
13947ac9a364SKalle Valo il4965_temperature_calib(il);
13957ac9a364SKalle Valo }
13967ac9a364SKalle Valo
13977ac9a364SKalle Valo static void
il4965_hdl_c_stats(struct il_priv * il,struct il_rx_buf * rxb)13987ac9a364SKalle Valo il4965_hdl_c_stats(struct il_priv *il, struct il_rx_buf *rxb)
13997ac9a364SKalle Valo {
14007ac9a364SKalle Valo struct il_rx_pkt *pkt = rxb_addr(rxb);
14017ac9a364SKalle Valo
14027ac9a364SKalle Valo if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATS_CLEAR_MSK) {
14037ac9a364SKalle Valo #ifdef CONFIG_IWLEGACY_DEBUGFS
14047ac9a364SKalle Valo memset(&il->_4965.accum_stats, 0,
14057ac9a364SKalle Valo sizeof(struct il_notif_stats));
14067ac9a364SKalle Valo memset(&il->_4965.delta_stats, 0,
14077ac9a364SKalle Valo sizeof(struct il_notif_stats));
14087ac9a364SKalle Valo memset(&il->_4965.max_delta, 0, sizeof(struct il_notif_stats));
14097ac9a364SKalle Valo #endif
14107ac9a364SKalle Valo D_RX("Statistics have been cleared\n");
14117ac9a364SKalle Valo }
14127ac9a364SKalle Valo il4965_hdl_stats(il, rxb);
14137ac9a364SKalle Valo }
14147ac9a364SKalle Valo
14157ac9a364SKalle Valo
14167ac9a364SKalle Valo /*
14177ac9a364SKalle Valo * mac80211 queues, ACs, hardware queues, FIFOs.
14187ac9a364SKalle Valo *
1419e00c6d8dSFlavio Suligoi * Cf. https://wireless.wiki.kernel.org/en/developers/Documentation/mac80211/queues
14207ac9a364SKalle Valo *
14217ac9a364SKalle Valo * Mac80211 uses the following numbers, which we get as from it
14227ac9a364SKalle Valo * by way of skb_get_queue_mapping(skb):
14237ac9a364SKalle Valo *
14247ac9a364SKalle Valo * VO 0
14257ac9a364SKalle Valo * VI 1
14267ac9a364SKalle Valo * BE 2
14277ac9a364SKalle Valo * BK 3
14287ac9a364SKalle Valo *
14297ac9a364SKalle Valo *
14307ac9a364SKalle Valo * Regular (not A-MPDU) frames are put into hardware queues corresponding
14317ac9a364SKalle Valo * to the FIFOs, see comments in iwl-prph.h. Aggregated frames get their
14327ac9a364SKalle Valo * own queue per aggregation session (RA/TID combination), such queues are
14337ac9a364SKalle Valo * set up to map into FIFOs too, for which we need an AC->FIFO mapping. In
14347ac9a364SKalle Valo * order to map frames to the right queue, we also need an AC->hw queue
14357ac9a364SKalle Valo * mapping. This is implemented here.
14367ac9a364SKalle Valo *
14377ac9a364SKalle Valo * Due to the way hw queues are set up (by the hw specific modules like
14387ac9a364SKalle Valo * 4965.c), the AC->hw queue mapping is the identity
14397ac9a364SKalle Valo * mapping.
14407ac9a364SKalle Valo */
14417ac9a364SKalle Valo
14427ac9a364SKalle Valo static const u8 tid_to_ac[] = {
14437ac9a364SKalle Valo IEEE80211_AC_BE,
14447ac9a364SKalle Valo IEEE80211_AC_BK,
14457ac9a364SKalle Valo IEEE80211_AC_BK,
14467ac9a364SKalle Valo IEEE80211_AC_BE,
14477ac9a364SKalle Valo IEEE80211_AC_VI,
14487ac9a364SKalle Valo IEEE80211_AC_VI,
14497ac9a364SKalle Valo IEEE80211_AC_VO,
14507ac9a364SKalle Valo IEEE80211_AC_VO
14517ac9a364SKalle Valo };
14527ac9a364SKalle Valo
14537ac9a364SKalle Valo static inline int
il4965_get_ac_from_tid(u16 tid)14547ac9a364SKalle Valo il4965_get_ac_from_tid(u16 tid)
14557ac9a364SKalle Valo {
14567ac9a364SKalle Valo if (likely(tid < ARRAY_SIZE(tid_to_ac)))
14577ac9a364SKalle Valo return tid_to_ac[tid];
14587ac9a364SKalle Valo
14597ac9a364SKalle Valo /* no support for TIDs 8-15 yet */
14607ac9a364SKalle Valo return -EINVAL;
14617ac9a364SKalle Valo }
14627ac9a364SKalle Valo
14637ac9a364SKalle Valo static inline int
il4965_get_fifo_from_tid(u16 tid)14647ac9a364SKalle Valo il4965_get_fifo_from_tid(u16 tid)
14657ac9a364SKalle Valo {
14669b029e17SColin Ian King static const u8 ac_to_fifo[] = {
14677ac9a364SKalle Valo IL_TX_FIFO_VO,
14687ac9a364SKalle Valo IL_TX_FIFO_VI,
14697ac9a364SKalle Valo IL_TX_FIFO_BE,
14707ac9a364SKalle Valo IL_TX_FIFO_BK,
14717ac9a364SKalle Valo };
14727ac9a364SKalle Valo
14737ac9a364SKalle Valo if (likely(tid < ARRAY_SIZE(tid_to_ac)))
14747ac9a364SKalle Valo return ac_to_fifo[tid_to_ac[tid]];
14757ac9a364SKalle Valo
14767ac9a364SKalle Valo /* no support for TIDs 8-15 yet */
14777ac9a364SKalle Valo return -EINVAL;
14787ac9a364SKalle Valo }
14797ac9a364SKalle Valo
14807ac9a364SKalle Valo /*
14817ac9a364SKalle Valo * handle build C_TX command notification.
14827ac9a364SKalle Valo */
14837ac9a364SKalle Valo static void
il4965_tx_cmd_build_basic(struct il_priv * il,struct sk_buff * skb,struct il_tx_cmd * tx_cmd,struct ieee80211_tx_info * info,struct ieee80211_hdr * hdr,u8 std_id)14847ac9a364SKalle Valo il4965_tx_cmd_build_basic(struct il_priv *il, struct sk_buff *skb,
14857ac9a364SKalle Valo struct il_tx_cmd *tx_cmd,
14867ac9a364SKalle Valo struct ieee80211_tx_info *info,
14877ac9a364SKalle Valo struct ieee80211_hdr *hdr, u8 std_id)
14887ac9a364SKalle Valo {
14897ac9a364SKalle Valo __le16 fc = hdr->frame_control;
14907ac9a364SKalle Valo __le32 tx_flags = tx_cmd->tx_flags;
14917ac9a364SKalle Valo
14927ac9a364SKalle Valo tx_cmd->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
14937ac9a364SKalle Valo if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
14947ac9a364SKalle Valo tx_flags |= TX_CMD_FLG_ACK_MSK;
14957ac9a364SKalle Valo if (ieee80211_is_mgmt(fc))
14967ac9a364SKalle Valo tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
14977ac9a364SKalle Valo if (ieee80211_is_probe_resp(fc) &&
14987ac9a364SKalle Valo !(le16_to_cpu(hdr->seq_ctrl) & 0xf))
14997ac9a364SKalle Valo tx_flags |= TX_CMD_FLG_TSF_MSK;
15007ac9a364SKalle Valo } else {
15017ac9a364SKalle Valo tx_flags &= (~TX_CMD_FLG_ACK_MSK);
15027ac9a364SKalle Valo tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
15037ac9a364SKalle Valo }
15047ac9a364SKalle Valo
15057ac9a364SKalle Valo if (ieee80211_is_back_req(fc))
15067ac9a364SKalle Valo tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK;
15077ac9a364SKalle Valo
15087ac9a364SKalle Valo tx_cmd->sta_id = std_id;
15097ac9a364SKalle Valo if (ieee80211_has_morefrags(fc))
15107ac9a364SKalle Valo tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK;
15117ac9a364SKalle Valo
15127ac9a364SKalle Valo if (ieee80211_is_data_qos(fc)) {
15137ac9a364SKalle Valo u8 *qc = ieee80211_get_qos_ctl(hdr);
15147ac9a364SKalle Valo tx_cmd->tid_tspec = qc[0] & 0xf;
15157ac9a364SKalle Valo tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK;
15167ac9a364SKalle Valo } else {
15177ac9a364SKalle Valo tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
15187ac9a364SKalle Valo }
15197ac9a364SKalle Valo
15207ac9a364SKalle Valo il_tx_cmd_protection(il, info, fc, &tx_flags);
15217ac9a364SKalle Valo
15227ac9a364SKalle Valo tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK);
15237ac9a364SKalle Valo if (ieee80211_is_mgmt(fc)) {
15247ac9a364SKalle Valo if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc))
15257ac9a364SKalle Valo tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(3);
15267ac9a364SKalle Valo else
15277ac9a364SKalle Valo tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(2);
15287ac9a364SKalle Valo } else {
15297ac9a364SKalle Valo tx_cmd->timeout.pm_frame_timeout = 0;
15307ac9a364SKalle Valo }
15317ac9a364SKalle Valo
15327ac9a364SKalle Valo tx_cmd->driver_txop = 0;
15337ac9a364SKalle Valo tx_cmd->tx_flags = tx_flags;
15347ac9a364SKalle Valo tx_cmd->next_frame_len = 0;
15357ac9a364SKalle Valo }
15367ac9a364SKalle Valo
15377ac9a364SKalle Valo static void
il4965_tx_cmd_build_rate(struct il_priv * il,struct il_tx_cmd * tx_cmd,struct ieee80211_tx_info * info,struct ieee80211_sta * sta,__le16 fc)15387ac9a364SKalle Valo il4965_tx_cmd_build_rate(struct il_priv *il,
15397ac9a364SKalle Valo struct il_tx_cmd *tx_cmd,
15407ac9a364SKalle Valo struct ieee80211_tx_info *info,
15417ac9a364SKalle Valo struct ieee80211_sta *sta,
15427ac9a364SKalle Valo __le16 fc)
15437ac9a364SKalle Valo {
15447ac9a364SKalle Valo const u8 rts_retry_limit = 60;
15457ac9a364SKalle Valo u32 rate_flags;
15467ac9a364SKalle Valo int rate_idx;
15477ac9a364SKalle Valo u8 data_retry_limit;
15487ac9a364SKalle Valo u8 rate_plcp;
15497ac9a364SKalle Valo
15507ac9a364SKalle Valo /* Set retry limit on DATA packets and Probe Responses */
15517ac9a364SKalle Valo if (ieee80211_is_probe_resp(fc))
15527ac9a364SKalle Valo data_retry_limit = 3;
15537ac9a364SKalle Valo else
15547ac9a364SKalle Valo data_retry_limit = IL4965_DEFAULT_TX_RETRY;
15557ac9a364SKalle Valo tx_cmd->data_retry_limit = data_retry_limit;
15567ac9a364SKalle Valo /* Set retry limit on RTS packets */
15577ac9a364SKalle Valo tx_cmd->rts_retry_limit = min(data_retry_limit, rts_retry_limit);
15587ac9a364SKalle Valo
15597ac9a364SKalle Valo /* DATA packets will use the uCode station table for rate/antenna
15607ac9a364SKalle Valo * selection */
15617ac9a364SKalle Valo if (ieee80211_is_data(fc)) {
15627ac9a364SKalle Valo tx_cmd->initial_rate_idx = 0;
15637ac9a364SKalle Valo tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK;
15647ac9a364SKalle Valo return;
15657ac9a364SKalle Valo }
15667ac9a364SKalle Valo
15677ac9a364SKalle Valo /**
15687ac9a364SKalle Valo * If the current TX rate stored in mac80211 has the MCS bit set, it's
15697ac9a364SKalle Valo * not really a TX rate. Thus, we use the lowest supported rate for
15707ac9a364SKalle Valo * this band. Also use the lowest supported rate if the stored rate
15717ac9a364SKalle Valo * idx is invalid.
15727ac9a364SKalle Valo */
15737ac9a364SKalle Valo rate_idx = info->control.rates[0].idx;
15747ac9a364SKalle Valo if ((info->control.rates[0].flags & IEEE80211_TX_RC_MCS) || rate_idx < 0
15757ac9a364SKalle Valo || rate_idx > RATE_COUNT_LEGACY)
15767ac9a364SKalle Valo rate_idx = rate_lowest_index(&il->bands[info->band], sta);
15777ac9a364SKalle Valo /* For 5 GHZ band, remap mac80211 rate indices into driver indices */
157857fbcce3SJohannes Berg if (info->band == NL80211_BAND_5GHZ)
15797ac9a364SKalle Valo rate_idx += IL_FIRST_OFDM_RATE;
15807ac9a364SKalle Valo /* Get PLCP rate for tx_cmd->rate_n_flags */
15817ac9a364SKalle Valo rate_plcp = il_rates[rate_idx].plcp;
15827ac9a364SKalle Valo /* Zero out flags for this packet */
15837ac9a364SKalle Valo rate_flags = 0;
15847ac9a364SKalle Valo
15857ac9a364SKalle Valo /* Set CCK flag as needed */
15867ac9a364SKalle Valo if (rate_idx >= IL_FIRST_CCK_RATE && rate_idx <= IL_LAST_CCK_RATE)
15877ac9a364SKalle Valo rate_flags |= RATE_MCS_CCK_MSK;
15887ac9a364SKalle Valo
15897ac9a364SKalle Valo /* Set up antennas */
15907ac9a364SKalle Valo il4965_toggle_tx_ant(il, &il->mgmt_tx_ant, il->hw_params.valid_tx_ant);
15917ac9a364SKalle Valo rate_flags |= BIT(il->mgmt_tx_ant) << RATE_MCS_ANT_POS;
15927ac9a364SKalle Valo
15937ac9a364SKalle Valo /* Set the rate in the TX cmd */
15947ac9a364SKalle Valo tx_cmd->rate_n_flags = cpu_to_le32(rate_plcp | rate_flags);
15957ac9a364SKalle Valo }
15967ac9a364SKalle Valo
15977ac9a364SKalle Valo static void
il4965_tx_cmd_build_hwcrypto(struct il_priv * il,struct ieee80211_tx_info * info,struct il_tx_cmd * tx_cmd,struct sk_buff * skb_frag,int sta_id)15987ac9a364SKalle Valo il4965_tx_cmd_build_hwcrypto(struct il_priv *il, struct ieee80211_tx_info *info,
15997ac9a364SKalle Valo struct il_tx_cmd *tx_cmd, struct sk_buff *skb_frag,
16007ac9a364SKalle Valo int sta_id)
16017ac9a364SKalle Valo {
16027ac9a364SKalle Valo struct ieee80211_key_conf *keyconf = info->control.hw_key;
16037ac9a364SKalle Valo
16047ac9a364SKalle Valo switch (keyconf->cipher) {
16057ac9a364SKalle Valo case WLAN_CIPHER_SUITE_CCMP:
16067ac9a364SKalle Valo tx_cmd->sec_ctl = TX_CMD_SEC_CCM;
16077ac9a364SKalle Valo memcpy(tx_cmd->key, keyconf->key, keyconf->keylen);
16087ac9a364SKalle Valo if (info->flags & IEEE80211_TX_CTL_AMPDU)
16097ac9a364SKalle Valo tx_cmd->tx_flags |= TX_CMD_FLG_AGG_CCMP_MSK;
16107ac9a364SKalle Valo D_TX("tx_cmd with AES hwcrypto\n");
16117ac9a364SKalle Valo break;
16127ac9a364SKalle Valo
16137ac9a364SKalle Valo case WLAN_CIPHER_SUITE_TKIP:
16147ac9a364SKalle Valo tx_cmd->sec_ctl = TX_CMD_SEC_TKIP;
16157ac9a364SKalle Valo ieee80211_get_tkip_p2k(keyconf, skb_frag, tx_cmd->key);
16167ac9a364SKalle Valo D_TX("tx_cmd with tkip hwcrypto\n");
16177ac9a364SKalle Valo break;
16187ac9a364SKalle Valo
16197ac9a364SKalle Valo case WLAN_CIPHER_SUITE_WEP104:
16207ac9a364SKalle Valo tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128;
16213f95e92cSGustavo A. R. Silva fallthrough;
16227ac9a364SKalle Valo case WLAN_CIPHER_SUITE_WEP40:
16237ac9a364SKalle Valo tx_cmd->sec_ctl |=
16247ac9a364SKalle Valo (TX_CMD_SEC_WEP | (keyconf->keyidx & TX_CMD_SEC_MSK) <<
16257ac9a364SKalle Valo TX_CMD_SEC_SHIFT);
16267ac9a364SKalle Valo
16277ac9a364SKalle Valo memcpy(&tx_cmd->key[3], keyconf->key, keyconf->keylen);
16287ac9a364SKalle Valo
16297ac9a364SKalle Valo D_TX("Configuring packet for WEP encryption " "with key %d\n",
16307ac9a364SKalle Valo keyconf->keyidx);
16317ac9a364SKalle Valo break;
16327ac9a364SKalle Valo
16337ac9a364SKalle Valo default:
16347ac9a364SKalle Valo IL_ERR("Unknown encode cipher %x\n", keyconf->cipher);
16357ac9a364SKalle Valo break;
16367ac9a364SKalle Valo }
16377ac9a364SKalle Valo }
16387ac9a364SKalle Valo
16397ac9a364SKalle Valo /*
16407ac9a364SKalle Valo * start C_TX command process
16417ac9a364SKalle Valo */
16427ac9a364SKalle Valo int
il4965_tx_skb(struct il_priv * il,struct ieee80211_sta * sta,struct sk_buff * skb)16437ac9a364SKalle Valo il4965_tx_skb(struct il_priv *il,
16447ac9a364SKalle Valo struct ieee80211_sta *sta,
16457ac9a364SKalle Valo struct sk_buff *skb)
16467ac9a364SKalle Valo {
16477ac9a364SKalle Valo struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
16487ac9a364SKalle Valo struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
16497ac9a364SKalle Valo struct il_station_priv *sta_priv = NULL;
16507ac9a364SKalle Valo struct il_tx_queue *txq;
16517ac9a364SKalle Valo struct il_queue *q;
16527ac9a364SKalle Valo struct il_device_cmd *out_cmd;
16537ac9a364SKalle Valo struct il_cmd_meta *out_meta;
16547ac9a364SKalle Valo struct il_tx_cmd *tx_cmd;
16557ac9a364SKalle Valo int txq_id;
16567ac9a364SKalle Valo dma_addr_t phys_addr;
16577ac9a364SKalle Valo dma_addr_t txcmd_phys;
16587ac9a364SKalle Valo dma_addr_t scratch_phys;
16597ac9a364SKalle Valo u16 len, firstlen, secondlen;
16607ac9a364SKalle Valo u16 seq_number = 0;
16617ac9a364SKalle Valo __le16 fc;
16627ac9a364SKalle Valo u8 hdr_len;
16637ac9a364SKalle Valo u8 sta_id;
16647ac9a364SKalle Valo u8 wait_write_ptr = 0;
16657ac9a364SKalle Valo u8 tid = 0;
16667ac9a364SKalle Valo u8 *qc = NULL;
16677ac9a364SKalle Valo unsigned long flags;
16687ac9a364SKalle Valo bool is_agg = false;
16697ac9a364SKalle Valo
16707ac9a364SKalle Valo spin_lock_irqsave(&il->lock, flags);
16717ac9a364SKalle Valo if (il_is_rfkill(il)) {
16727ac9a364SKalle Valo D_DROP("Dropping - RF KILL\n");
16737ac9a364SKalle Valo goto drop_unlock;
16747ac9a364SKalle Valo }
16757ac9a364SKalle Valo
16767ac9a364SKalle Valo fc = hdr->frame_control;
16777ac9a364SKalle Valo
16787ac9a364SKalle Valo #ifdef CONFIG_IWLEGACY_DEBUG
16797ac9a364SKalle Valo if (ieee80211_is_auth(fc))
16807ac9a364SKalle Valo D_TX("Sending AUTH frame\n");
16817ac9a364SKalle Valo else if (ieee80211_is_assoc_req(fc))
16827ac9a364SKalle Valo D_TX("Sending ASSOC frame\n");
16837ac9a364SKalle Valo else if (ieee80211_is_reassoc_req(fc))
16847ac9a364SKalle Valo D_TX("Sending REASSOC frame\n");
16857ac9a364SKalle Valo #endif
16867ac9a364SKalle Valo
16877ac9a364SKalle Valo hdr_len = ieee80211_hdrlen(fc);
16887ac9a364SKalle Valo
16897ac9a364SKalle Valo /* For management frames use broadcast id to do not break aggregation */
16907ac9a364SKalle Valo if (!ieee80211_is_data(fc))
16917ac9a364SKalle Valo sta_id = il->hw_params.bcast_id;
16927ac9a364SKalle Valo else {
16937ac9a364SKalle Valo /* Find idx into station table for destination station */
16947ac9a364SKalle Valo sta_id = il_sta_id_or_broadcast(il, sta);
16957ac9a364SKalle Valo
16967ac9a364SKalle Valo if (sta_id == IL_INVALID_STATION) {
16977ac9a364SKalle Valo D_DROP("Dropping - INVALID STATION: %pM\n", hdr->addr1);
16987ac9a364SKalle Valo goto drop_unlock;
16997ac9a364SKalle Valo }
17007ac9a364SKalle Valo }
17017ac9a364SKalle Valo
17027ac9a364SKalle Valo D_TX("station Id %d\n", sta_id);
17037ac9a364SKalle Valo
17047ac9a364SKalle Valo if (sta)
17057ac9a364SKalle Valo sta_priv = (void *)sta->drv_priv;
17067ac9a364SKalle Valo
17077ac9a364SKalle Valo if (sta_priv && sta_priv->asleep &&
17087ac9a364SKalle Valo (info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER)) {
17097ac9a364SKalle Valo /*
17107ac9a364SKalle Valo * This sends an asynchronous command to the device,
17117ac9a364SKalle Valo * but we can rely on it being processed before the
17127ac9a364SKalle Valo * next frame is processed -- and the next frame to
17137ac9a364SKalle Valo * this station is the one that will consume this
17147ac9a364SKalle Valo * counter.
17157ac9a364SKalle Valo * For now set the counter to just 1 since we do not
17167ac9a364SKalle Valo * support uAPSD yet.
17177ac9a364SKalle Valo */
17187ac9a364SKalle Valo il4965_sta_modify_sleep_tx_count(il, sta_id, 1);
17197ac9a364SKalle Valo }
17207ac9a364SKalle Valo
17217ac9a364SKalle Valo /* FIXME: remove me ? */
17227ac9a364SKalle Valo WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM);
17237ac9a364SKalle Valo
17247ac9a364SKalle Valo /* Access category (AC) is also the queue number */
17257ac9a364SKalle Valo txq_id = skb_get_queue_mapping(skb);
17267ac9a364SKalle Valo
17277ac9a364SKalle Valo /* irqs already disabled/saved above when locking il->lock */
17287ac9a364SKalle Valo spin_lock(&il->sta_lock);
17297ac9a364SKalle Valo
17307ac9a364SKalle Valo if (ieee80211_is_data_qos(fc)) {
17317ac9a364SKalle Valo qc = ieee80211_get_qos_ctl(hdr);
17327ac9a364SKalle Valo tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
17337ac9a364SKalle Valo if (WARN_ON_ONCE(tid >= MAX_TID_COUNT)) {
17347ac9a364SKalle Valo spin_unlock(&il->sta_lock);
17357ac9a364SKalle Valo goto drop_unlock;
17367ac9a364SKalle Valo }
17377ac9a364SKalle Valo seq_number = il->stations[sta_id].tid[tid].seq_number;
17387ac9a364SKalle Valo seq_number &= IEEE80211_SCTL_SEQ;
17397ac9a364SKalle Valo hdr->seq_ctrl =
17407ac9a364SKalle Valo hdr->seq_ctrl & cpu_to_le16(IEEE80211_SCTL_FRAG);
17417ac9a364SKalle Valo hdr->seq_ctrl |= cpu_to_le16(seq_number);
17427ac9a364SKalle Valo seq_number += 0x10;
17437ac9a364SKalle Valo /* aggregation is on for this <sta,tid> */
17447ac9a364SKalle Valo if (info->flags & IEEE80211_TX_CTL_AMPDU &&
17457ac9a364SKalle Valo il->stations[sta_id].tid[tid].agg.state == IL_AGG_ON) {
17467ac9a364SKalle Valo txq_id = il->stations[sta_id].tid[tid].agg.txq_id;
17477ac9a364SKalle Valo is_agg = true;
17487ac9a364SKalle Valo }
17497ac9a364SKalle Valo }
17507ac9a364SKalle Valo
17517ac9a364SKalle Valo txq = &il->txq[txq_id];
17527ac9a364SKalle Valo q = &txq->q;
17537ac9a364SKalle Valo
17547ac9a364SKalle Valo if (unlikely(il_queue_space(q) < q->high_mark)) {
17557ac9a364SKalle Valo spin_unlock(&il->sta_lock);
17567ac9a364SKalle Valo goto drop_unlock;
17577ac9a364SKalle Valo }
17587ac9a364SKalle Valo
17597ac9a364SKalle Valo if (ieee80211_is_data_qos(fc)) {
17607ac9a364SKalle Valo il->stations[sta_id].tid[tid].tfds_in_queue++;
17617ac9a364SKalle Valo if (!ieee80211_has_morefrags(fc))
17627ac9a364SKalle Valo il->stations[sta_id].tid[tid].seq_number = seq_number;
17637ac9a364SKalle Valo }
17647ac9a364SKalle Valo
17657ac9a364SKalle Valo spin_unlock(&il->sta_lock);
17667ac9a364SKalle Valo
17677ac9a364SKalle Valo txq->skbs[q->write_ptr] = skb;
17687ac9a364SKalle Valo
17697ac9a364SKalle Valo /* Set up first empty entry in queue's array of Tx/cmd buffers */
17707ac9a364SKalle Valo out_cmd = txq->cmd[q->write_ptr];
17717ac9a364SKalle Valo out_meta = &txq->meta[q->write_ptr];
17727ac9a364SKalle Valo tx_cmd = &out_cmd->cmd.tx;
17737ac9a364SKalle Valo memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr));
17747ac9a364SKalle Valo memset(tx_cmd, 0, sizeof(struct il_tx_cmd));
17757ac9a364SKalle Valo
17767ac9a364SKalle Valo /*
17777ac9a364SKalle Valo * Set up the Tx-command (not MAC!) header.
17787ac9a364SKalle Valo * Store the chosen Tx queue and TFD idx within the sequence field;
17797ac9a364SKalle Valo * after Tx, uCode's Tx response will return this value so driver can
17807ac9a364SKalle Valo * locate the frame within the tx queue and do post-tx processing.
17817ac9a364SKalle Valo */
17827ac9a364SKalle Valo out_cmd->hdr.cmd = C_TX;
17837ac9a364SKalle Valo out_cmd->hdr.sequence =
17847ac9a364SKalle Valo cpu_to_le16((u16)
17857ac9a364SKalle Valo (QUEUE_TO_SEQ(txq_id) | IDX_TO_SEQ(q->write_ptr)));
17867ac9a364SKalle Valo
17877ac9a364SKalle Valo /* Copy MAC header from skb into command buffer */
17887ac9a364SKalle Valo memcpy(tx_cmd->hdr, hdr, hdr_len);
17897ac9a364SKalle Valo
17907ac9a364SKalle Valo /* Total # bytes to be transmitted */
17917ac9a364SKalle Valo tx_cmd->len = cpu_to_le16((u16) skb->len);
17927ac9a364SKalle Valo
17937ac9a364SKalle Valo if (info->control.hw_key)
17947ac9a364SKalle Valo il4965_tx_cmd_build_hwcrypto(il, info, tx_cmd, skb, sta_id);
17957ac9a364SKalle Valo
17967ac9a364SKalle Valo /* TODO need this for burst mode later on */
17977ac9a364SKalle Valo il4965_tx_cmd_build_basic(il, skb, tx_cmd, info, hdr, sta_id);
17987ac9a364SKalle Valo
17997ac9a364SKalle Valo il4965_tx_cmd_build_rate(il, tx_cmd, info, sta, fc);
18007ac9a364SKalle Valo
18017ac9a364SKalle Valo /*
18027ac9a364SKalle Valo * Use the first empty entry in this queue's command buffer array
18037ac9a364SKalle Valo * to contain the Tx command and MAC header concatenated together
18047ac9a364SKalle Valo * (payload data will be in another buffer).
18057ac9a364SKalle Valo * Size of this varies, due to varying MAC header length.
18067ac9a364SKalle Valo * If end is not dword aligned, we'll have 2 extra bytes at the end
18077ac9a364SKalle Valo * of the MAC header (device reads on dword boundaries).
18087ac9a364SKalle Valo * We'll tell device about this padding later.
18097ac9a364SKalle Valo */
18107ac9a364SKalle Valo len = sizeof(struct il_tx_cmd) + sizeof(struct il_cmd_header) + hdr_len;
18117ac9a364SKalle Valo firstlen = (len + 3) & ~3;
18127ac9a364SKalle Valo
18137ac9a364SKalle Valo /* Tell NIC about any 2-byte padding after MAC header */
18147ac9a364SKalle Valo if (firstlen != len)
18157ac9a364SKalle Valo tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK;
18167ac9a364SKalle Valo
18177ac9a364SKalle Valo /* Physical address of this Tx command's header (not MAC header!),
18187ac9a364SKalle Valo * within command buffer array. */
1819ebe9e651SChristophe JAILLET txcmd_phys = dma_map_single(&il->pci_dev->dev, &out_cmd->hdr, firstlen,
1820ebe9e651SChristophe JAILLET DMA_BIDIRECTIONAL);
1821ebe9e651SChristophe JAILLET if (unlikely(dma_mapping_error(&il->pci_dev->dev, txcmd_phys)))
18227ac9a364SKalle Valo goto drop_unlock;
18237ac9a364SKalle Valo
18247ac9a364SKalle Valo /* Set up TFD's 2nd entry to point directly to remainder of skb,
18257ac9a364SKalle Valo * if any (802.11 null frames have no payload). */
18267ac9a364SKalle Valo secondlen = skb->len - hdr_len;
18277ac9a364SKalle Valo if (secondlen > 0) {
1828ebe9e651SChristophe JAILLET phys_addr = dma_map_single(&il->pci_dev->dev, skb->data + hdr_len,
1829ebe9e651SChristophe JAILLET secondlen, DMA_TO_DEVICE);
1830ebe9e651SChristophe JAILLET if (unlikely(dma_mapping_error(&il->pci_dev->dev, phys_addr)))
18317ac9a364SKalle Valo goto drop_unlock;
18327ac9a364SKalle Valo }
18337ac9a364SKalle Valo
18347ac9a364SKalle Valo /* Add buffer containing Tx command and MAC(!) header to TFD's
18357ac9a364SKalle Valo * first entry */
18367ac9a364SKalle Valo il->ops->txq_attach_buf_to_tfd(il, txq, txcmd_phys, firstlen, 1, 0);
18377ac9a364SKalle Valo dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
18387ac9a364SKalle Valo dma_unmap_len_set(out_meta, len, firstlen);
18397ac9a364SKalle Valo if (secondlen)
18407ac9a364SKalle Valo il->ops->txq_attach_buf_to_tfd(il, txq, phys_addr, secondlen,
18417ac9a364SKalle Valo 0, 0);
18427ac9a364SKalle Valo
18437ac9a364SKalle Valo if (!ieee80211_has_morefrags(hdr->frame_control)) {
18447ac9a364SKalle Valo txq->need_update = 1;
18457ac9a364SKalle Valo } else {
18467ac9a364SKalle Valo wait_write_ptr = 1;
18477ac9a364SKalle Valo txq->need_update = 0;
18487ac9a364SKalle Valo }
18497ac9a364SKalle Valo
18507ac9a364SKalle Valo scratch_phys =
18517ac9a364SKalle Valo txcmd_phys + sizeof(struct il_cmd_header) +
18527ac9a364SKalle Valo offsetof(struct il_tx_cmd, scratch);
18537ac9a364SKalle Valo
18547ac9a364SKalle Valo /* take back ownership of DMA buffer to enable update */
1855ebe9e651SChristophe JAILLET dma_sync_single_for_cpu(&il->pci_dev->dev, txcmd_phys, firstlen,
1856ebe9e651SChristophe JAILLET DMA_BIDIRECTIONAL);
18577ac9a364SKalle Valo tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys);
18587ac9a364SKalle Valo tx_cmd->dram_msb_ptr = il_get_dma_hi_addr(scratch_phys);
18597ac9a364SKalle Valo
18607ac9a364SKalle Valo il_update_stats(il, true, fc, skb->len);
18617ac9a364SKalle Valo
18627ac9a364SKalle Valo D_TX("sequence nr = 0X%x\n", le16_to_cpu(out_cmd->hdr.sequence));
18637ac9a364SKalle Valo D_TX("tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags));
18647ac9a364SKalle Valo il_print_hex_dump(il, IL_DL_TX, (u8 *) tx_cmd, sizeof(*tx_cmd));
18657ac9a364SKalle Valo il_print_hex_dump(il, IL_DL_TX, (u8 *) tx_cmd->hdr, hdr_len);
18667ac9a364SKalle Valo
18677ac9a364SKalle Valo /* Set up entry for this TFD in Tx byte-count array */
18687ac9a364SKalle Valo if (info->flags & IEEE80211_TX_CTL_AMPDU)
18697ac9a364SKalle Valo il->ops->txq_update_byte_cnt_tbl(il, txq, le16_to_cpu(tx_cmd->len));
18707ac9a364SKalle Valo
1871ebe9e651SChristophe JAILLET dma_sync_single_for_device(&il->pci_dev->dev, txcmd_phys, firstlen,
1872ebe9e651SChristophe JAILLET DMA_BIDIRECTIONAL);
18737ac9a364SKalle Valo
18747ac9a364SKalle Valo /* Tell device the write idx *just past* this latest filled TFD */
18757ac9a364SKalle Valo q->write_ptr = il_queue_inc_wrap(q->write_ptr, q->n_bd);
18767ac9a364SKalle Valo il_txq_update_write_ptr(il, txq);
18777ac9a364SKalle Valo spin_unlock_irqrestore(&il->lock, flags);
18787ac9a364SKalle Valo
18797ac9a364SKalle Valo /*
18807ac9a364SKalle Valo * At this point the frame is "transmitted" successfully
18817ac9a364SKalle Valo * and we will get a TX status notification eventually,
18827ac9a364SKalle Valo * regardless of the value of ret. "ret" only indicates
18837ac9a364SKalle Valo * whether or not we should update the write pointer.
18847ac9a364SKalle Valo */
18857ac9a364SKalle Valo
18867ac9a364SKalle Valo /*
18877ac9a364SKalle Valo * Avoid atomic ops if it isn't an associated client.
18887ac9a364SKalle Valo * Also, if this is a packet for aggregation, don't
18897ac9a364SKalle Valo * increase the counter because the ucode will stop
18907ac9a364SKalle Valo * aggregation queues when their respective station
18917ac9a364SKalle Valo * goes to sleep.
18927ac9a364SKalle Valo */
18937ac9a364SKalle Valo if (sta_priv && sta_priv->client && !is_agg)
18947ac9a364SKalle Valo atomic_inc(&sta_priv->pending_frames);
18957ac9a364SKalle Valo
18967ac9a364SKalle Valo if (il_queue_space(q) < q->high_mark && il->mac80211_registered) {
18977ac9a364SKalle Valo if (wait_write_ptr) {
18987ac9a364SKalle Valo spin_lock_irqsave(&il->lock, flags);
18997ac9a364SKalle Valo txq->need_update = 1;
19007ac9a364SKalle Valo il_txq_update_write_ptr(il, txq);
19017ac9a364SKalle Valo spin_unlock_irqrestore(&il->lock, flags);
19027ac9a364SKalle Valo } else {
19037ac9a364SKalle Valo il_stop_queue(il, txq);
19047ac9a364SKalle Valo }
19057ac9a364SKalle Valo }
19067ac9a364SKalle Valo
19077ac9a364SKalle Valo return 0;
19087ac9a364SKalle Valo
19097ac9a364SKalle Valo drop_unlock:
19107ac9a364SKalle Valo spin_unlock_irqrestore(&il->lock, flags);
19117ac9a364SKalle Valo return -1;
19127ac9a364SKalle Valo }
19137ac9a364SKalle Valo
19147ac9a364SKalle Valo static inline int
il4965_alloc_dma_ptr(struct il_priv * il,struct il_dma_ptr * ptr,size_t size)19157ac9a364SKalle Valo il4965_alloc_dma_ptr(struct il_priv *il, struct il_dma_ptr *ptr, size_t size)
19167ac9a364SKalle Valo {
19177ac9a364SKalle Valo ptr->addr = dma_alloc_coherent(&il->pci_dev->dev, size, &ptr->dma,
19187ac9a364SKalle Valo GFP_KERNEL);
19197ac9a364SKalle Valo if (!ptr->addr)
19207ac9a364SKalle Valo return -ENOMEM;
19217ac9a364SKalle Valo ptr->size = size;
19227ac9a364SKalle Valo return 0;
19237ac9a364SKalle Valo }
19247ac9a364SKalle Valo
19257ac9a364SKalle Valo static inline void
il4965_free_dma_ptr(struct il_priv * il,struct il_dma_ptr * ptr)19267ac9a364SKalle Valo il4965_free_dma_ptr(struct il_priv *il, struct il_dma_ptr *ptr)
19277ac9a364SKalle Valo {
19287ac9a364SKalle Valo if (unlikely(!ptr->addr))
19297ac9a364SKalle Valo return;
19307ac9a364SKalle Valo
19317ac9a364SKalle Valo dma_free_coherent(&il->pci_dev->dev, ptr->size, ptr->addr, ptr->dma);
19327ac9a364SKalle Valo memset(ptr, 0, sizeof(*ptr));
19337ac9a364SKalle Valo }
19347ac9a364SKalle Valo
193535b7fbfcSLee Jones /*
19367ac9a364SKalle Valo * il4965_hw_txq_ctx_free - Free TXQ Context
19377ac9a364SKalle Valo *
19387ac9a364SKalle Valo * Destroy all TX DMA queues and structures
19397ac9a364SKalle Valo */
19407ac9a364SKalle Valo void
il4965_hw_txq_ctx_free(struct il_priv * il)19417ac9a364SKalle Valo il4965_hw_txq_ctx_free(struct il_priv *il)
19427ac9a364SKalle Valo {
19437ac9a364SKalle Valo int txq_id;
19447ac9a364SKalle Valo
19457ac9a364SKalle Valo /* Tx queues */
19467ac9a364SKalle Valo if (il->txq) {
19477ac9a364SKalle Valo for (txq_id = 0; txq_id < il->hw_params.max_txq_num; txq_id++)
19487ac9a364SKalle Valo if (txq_id == il->cmd_queue)
19497ac9a364SKalle Valo il_cmd_queue_free(il);
19507ac9a364SKalle Valo else
19517ac9a364SKalle Valo il_tx_queue_free(il, txq_id);
19527ac9a364SKalle Valo }
19537ac9a364SKalle Valo il4965_free_dma_ptr(il, &il->kw);
19547ac9a364SKalle Valo
19557ac9a364SKalle Valo il4965_free_dma_ptr(il, &il->scd_bc_tbls);
19567ac9a364SKalle Valo
19577ac9a364SKalle Valo /* free tx queue structure */
19587ac9a364SKalle Valo il_free_txq_mem(il);
19597ac9a364SKalle Valo }
19607ac9a364SKalle Valo
196135b7fbfcSLee Jones /*
19627ac9a364SKalle Valo * il4965_txq_ctx_alloc - allocate TX queue context
19637ac9a364SKalle Valo * Allocate all Tx DMA structures and initialize them
19647ac9a364SKalle Valo */
19657ac9a364SKalle Valo int
il4965_txq_ctx_alloc(struct il_priv * il)19667ac9a364SKalle Valo il4965_txq_ctx_alloc(struct il_priv *il)
19677ac9a364SKalle Valo {
19687ac9a364SKalle Valo int ret, txq_id;
19697ac9a364SKalle Valo unsigned long flags;
19707ac9a364SKalle Valo
19717ac9a364SKalle Valo /* Free all tx/cmd queues and keep-warm buffer */
19727ac9a364SKalle Valo il4965_hw_txq_ctx_free(il);
19737ac9a364SKalle Valo
19747ac9a364SKalle Valo ret =
19757ac9a364SKalle Valo il4965_alloc_dma_ptr(il, &il->scd_bc_tbls,
19767ac9a364SKalle Valo il->hw_params.scd_bc_tbls_size);
19777ac9a364SKalle Valo if (ret) {
19787ac9a364SKalle Valo IL_ERR("Scheduler BC Table allocation failed\n");
19797ac9a364SKalle Valo goto error_bc_tbls;
19807ac9a364SKalle Valo }
19817ac9a364SKalle Valo /* Alloc keep-warm buffer */
19827ac9a364SKalle Valo ret = il4965_alloc_dma_ptr(il, &il->kw, IL_KW_SIZE);
19837ac9a364SKalle Valo if (ret) {
19847ac9a364SKalle Valo IL_ERR("Keep Warm allocation failed\n");
19857ac9a364SKalle Valo goto error_kw;
19867ac9a364SKalle Valo }
19877ac9a364SKalle Valo
19887ac9a364SKalle Valo /* allocate tx queue structure */
19897ac9a364SKalle Valo ret = il_alloc_txq_mem(il);
19907ac9a364SKalle Valo if (ret)
19917ac9a364SKalle Valo goto error;
19927ac9a364SKalle Valo
19937ac9a364SKalle Valo spin_lock_irqsave(&il->lock, flags);
19947ac9a364SKalle Valo
19957ac9a364SKalle Valo /* Turn off all Tx DMA fifos */
19967ac9a364SKalle Valo il4965_txq_set_sched(il, 0);
19977ac9a364SKalle Valo
19987ac9a364SKalle Valo /* Tell NIC where to find the "keep warm" buffer */
19997ac9a364SKalle Valo il_wr(il, FH49_KW_MEM_ADDR_REG, il->kw.dma >> 4);
20007ac9a364SKalle Valo
20017ac9a364SKalle Valo spin_unlock_irqrestore(&il->lock, flags);
20027ac9a364SKalle Valo
20037ac9a364SKalle Valo /* Alloc and init all Tx queues, including the command queue (#4/#9) */
20047ac9a364SKalle Valo for (txq_id = 0; txq_id < il->hw_params.max_txq_num; txq_id++) {
20057ac9a364SKalle Valo ret = il_tx_queue_init(il, txq_id);
20067ac9a364SKalle Valo if (ret) {
20077ac9a364SKalle Valo IL_ERR("Tx %d queue init failed\n", txq_id);
20087ac9a364SKalle Valo goto error;
20097ac9a364SKalle Valo }
20107ac9a364SKalle Valo }
20117ac9a364SKalle Valo
20127ac9a364SKalle Valo return ret;
20137ac9a364SKalle Valo
20147ac9a364SKalle Valo error:
20157ac9a364SKalle Valo il4965_hw_txq_ctx_free(il);
20167ac9a364SKalle Valo il4965_free_dma_ptr(il, &il->kw);
20177ac9a364SKalle Valo error_kw:
20187ac9a364SKalle Valo il4965_free_dma_ptr(il, &il->scd_bc_tbls);
20197ac9a364SKalle Valo error_bc_tbls:
20207ac9a364SKalle Valo return ret;
20217ac9a364SKalle Valo }
20227ac9a364SKalle Valo
20237ac9a364SKalle Valo void
il4965_txq_ctx_reset(struct il_priv * il)20247ac9a364SKalle Valo il4965_txq_ctx_reset(struct il_priv *il)
20257ac9a364SKalle Valo {
20267ac9a364SKalle Valo int txq_id;
20277ac9a364SKalle Valo unsigned long flags;
20287ac9a364SKalle Valo
20297ac9a364SKalle Valo spin_lock_irqsave(&il->lock, flags);
20307ac9a364SKalle Valo
20317ac9a364SKalle Valo /* Turn off all Tx DMA fifos */
20327ac9a364SKalle Valo il4965_txq_set_sched(il, 0);
20337ac9a364SKalle Valo /* Tell NIC where to find the "keep warm" buffer */
20347ac9a364SKalle Valo il_wr(il, FH49_KW_MEM_ADDR_REG, il->kw.dma >> 4);
20357ac9a364SKalle Valo
20367ac9a364SKalle Valo spin_unlock_irqrestore(&il->lock, flags);
20377ac9a364SKalle Valo
20387ac9a364SKalle Valo /* Alloc and init all Tx queues, including the command queue (#4) */
20397ac9a364SKalle Valo for (txq_id = 0; txq_id < il->hw_params.max_txq_num; txq_id++)
20407ac9a364SKalle Valo il_tx_queue_reset(il, txq_id);
20417ac9a364SKalle Valo }
20427ac9a364SKalle Valo
20437ac9a364SKalle Valo static void
il4965_txq_ctx_unmap(struct il_priv * il)20447ac9a364SKalle Valo il4965_txq_ctx_unmap(struct il_priv *il)
20457ac9a364SKalle Valo {
20467ac9a364SKalle Valo int txq_id;
20477ac9a364SKalle Valo
20487ac9a364SKalle Valo if (!il->txq)
20497ac9a364SKalle Valo return;
20507ac9a364SKalle Valo
20517ac9a364SKalle Valo /* Unmap DMA from host system and free skb's */
20527ac9a364SKalle Valo for (txq_id = 0; txq_id < il->hw_params.max_txq_num; txq_id++)
20537ac9a364SKalle Valo if (txq_id == il->cmd_queue)
20547ac9a364SKalle Valo il_cmd_queue_unmap(il);
20557ac9a364SKalle Valo else
20567ac9a364SKalle Valo il_tx_queue_unmap(il, txq_id);
20577ac9a364SKalle Valo }
20587ac9a364SKalle Valo
205935b7fbfcSLee Jones /*
20607ac9a364SKalle Valo * il4965_txq_ctx_stop - Stop all Tx DMA channels
20617ac9a364SKalle Valo */
20627ac9a364SKalle Valo void
il4965_txq_ctx_stop(struct il_priv * il)20637ac9a364SKalle Valo il4965_txq_ctx_stop(struct il_priv *il)
20647ac9a364SKalle Valo {
20657ac9a364SKalle Valo int ch, ret;
20667ac9a364SKalle Valo
20677ac9a364SKalle Valo _il_wr_prph(il, IL49_SCD_TXFACT, 0);
20687ac9a364SKalle Valo
20697ac9a364SKalle Valo /* Stop each Tx DMA channel, and wait for it to be idle */
20707ac9a364SKalle Valo for (ch = 0; ch < il->hw_params.dma_chnl_num; ch++) {
20717ac9a364SKalle Valo _il_wr(il, FH49_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0);
20727ac9a364SKalle Valo ret =
20737ac9a364SKalle Valo _il_poll_bit(il, FH49_TSSR_TX_STATUS_REG,
20747ac9a364SKalle Valo FH49_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch),
20757ac9a364SKalle Valo FH49_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch),
20767ac9a364SKalle Valo 1000);
20777ac9a364SKalle Valo if (ret < 0)
20787ac9a364SKalle Valo IL_ERR("Timeout stopping DMA channel %d [0x%08x]",
20797ac9a364SKalle Valo ch, _il_rd(il, FH49_TSSR_TX_STATUS_REG));
20807ac9a364SKalle Valo }
20817ac9a364SKalle Valo }
20827ac9a364SKalle Valo
20837ac9a364SKalle Valo /*
20847ac9a364SKalle Valo * Find first available (lowest unused) Tx Queue, mark it "active".
20857ac9a364SKalle Valo * Called only when finding queue for aggregation.
20867ac9a364SKalle Valo * Should never return anything < 7, because they should already
20877ac9a364SKalle Valo * be in use as EDCA AC (0-3), Command (4), reserved (5, 6)
20887ac9a364SKalle Valo */
20897ac9a364SKalle Valo static int
il4965_txq_ctx_activate_free(struct il_priv * il)20907ac9a364SKalle Valo il4965_txq_ctx_activate_free(struct il_priv *il)
20917ac9a364SKalle Valo {
20927ac9a364SKalle Valo int txq_id;
20937ac9a364SKalle Valo
20947ac9a364SKalle Valo for (txq_id = 0; txq_id < il->hw_params.max_txq_num; txq_id++)
20957ac9a364SKalle Valo if (!test_and_set_bit(txq_id, &il->txq_ctx_active_msk))
20967ac9a364SKalle Valo return txq_id;
20977ac9a364SKalle Valo return -1;
20987ac9a364SKalle Valo }
20997ac9a364SKalle Valo
210035b7fbfcSLee Jones /*
21017ac9a364SKalle Valo * il4965_tx_queue_stop_scheduler - Stop queue, but keep configuration
21027ac9a364SKalle Valo */
21037ac9a364SKalle Valo static void
il4965_tx_queue_stop_scheduler(struct il_priv * il,u16 txq_id)21047ac9a364SKalle Valo il4965_tx_queue_stop_scheduler(struct il_priv *il, u16 txq_id)
21057ac9a364SKalle Valo {
21067ac9a364SKalle Valo /* Simply stop the queue, but don't change any configuration;
21077ac9a364SKalle Valo * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */
21087ac9a364SKalle Valo il_wr_prph(il, IL49_SCD_QUEUE_STATUS_BITS(txq_id),
21097ac9a364SKalle Valo (0 << IL49_SCD_QUEUE_STTS_REG_POS_ACTIVE) |
21107ac9a364SKalle Valo (1 << IL49_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN));
21117ac9a364SKalle Valo }
21127ac9a364SKalle Valo
211335b7fbfcSLee Jones /*
21147ac9a364SKalle Valo * il4965_tx_queue_set_q2ratid - Map unique receiver/tid combination to a queue
21157ac9a364SKalle Valo */
21167ac9a364SKalle Valo static int
il4965_tx_queue_set_q2ratid(struct il_priv * il,u16 ra_tid,u16 txq_id)21177ac9a364SKalle Valo il4965_tx_queue_set_q2ratid(struct il_priv *il, u16 ra_tid, u16 txq_id)
21187ac9a364SKalle Valo {
21197ac9a364SKalle Valo u32 tbl_dw_addr;
21207ac9a364SKalle Valo u32 tbl_dw;
21217ac9a364SKalle Valo u16 scd_q2ratid;
21227ac9a364SKalle Valo
21237ac9a364SKalle Valo scd_q2ratid = ra_tid & IL_SCD_QUEUE_RA_TID_MAP_RATID_MSK;
21247ac9a364SKalle Valo
21257ac9a364SKalle Valo tbl_dw_addr =
21267ac9a364SKalle Valo il->scd_base_addr + IL49_SCD_TRANSLATE_TBL_OFFSET_QUEUE(txq_id);
21277ac9a364SKalle Valo
21287ac9a364SKalle Valo tbl_dw = il_read_targ_mem(il, tbl_dw_addr);
21297ac9a364SKalle Valo
21307ac9a364SKalle Valo if (txq_id & 0x1)
21317ac9a364SKalle Valo tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF);
21327ac9a364SKalle Valo else
21337ac9a364SKalle Valo tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000);
21347ac9a364SKalle Valo
21357ac9a364SKalle Valo il_write_targ_mem(il, tbl_dw_addr, tbl_dw);
21367ac9a364SKalle Valo
21377ac9a364SKalle Valo return 0;
21387ac9a364SKalle Valo }
21397ac9a364SKalle Valo
214035b7fbfcSLee Jones /*
21417ac9a364SKalle Valo * il4965_tx_queue_agg_enable - Set up & enable aggregation for selected queue
21427ac9a364SKalle Valo *
21437ac9a364SKalle Valo * NOTE: txq_id must be greater than IL49_FIRST_AMPDU_QUEUE,
21447ac9a364SKalle Valo * i.e. it must be one of the higher queues used for aggregation
21457ac9a364SKalle Valo */
21467ac9a364SKalle Valo static int
il4965_txq_agg_enable(struct il_priv * il,int txq_id,int tx_fifo,int sta_id,int tid,u16 ssn_idx)21477ac9a364SKalle Valo il4965_txq_agg_enable(struct il_priv *il, int txq_id, int tx_fifo, int sta_id,
21487ac9a364SKalle Valo int tid, u16 ssn_idx)
21497ac9a364SKalle Valo {
21507ac9a364SKalle Valo unsigned long flags;
21517ac9a364SKalle Valo u16 ra_tid;
21527ac9a364SKalle Valo int ret;
21537ac9a364SKalle Valo
21547ac9a364SKalle Valo if ((IL49_FIRST_AMPDU_QUEUE > txq_id) ||
21557ac9a364SKalle Valo (IL49_FIRST_AMPDU_QUEUE +
21567ac9a364SKalle Valo il->cfg->num_of_ampdu_queues <= txq_id)) {
21577ac9a364SKalle Valo IL_WARN("queue number out of range: %d, must be %d to %d\n",
21587ac9a364SKalle Valo txq_id, IL49_FIRST_AMPDU_QUEUE,
21597ac9a364SKalle Valo IL49_FIRST_AMPDU_QUEUE +
21607ac9a364SKalle Valo il->cfg->num_of_ampdu_queues - 1);
21617ac9a364SKalle Valo return -EINVAL;
21627ac9a364SKalle Valo }
21637ac9a364SKalle Valo
21647ac9a364SKalle Valo ra_tid = BUILD_RAxTID(sta_id, tid);
21657ac9a364SKalle Valo
21667ac9a364SKalle Valo /* Modify device's station table to Tx this TID */
21677ac9a364SKalle Valo ret = il4965_sta_tx_modify_enable_tid(il, sta_id, tid);
21687ac9a364SKalle Valo if (ret)
21697ac9a364SKalle Valo return ret;
21707ac9a364SKalle Valo
21717ac9a364SKalle Valo spin_lock_irqsave(&il->lock, flags);
21727ac9a364SKalle Valo
21737ac9a364SKalle Valo /* Stop this Tx queue before configuring it */
21747ac9a364SKalle Valo il4965_tx_queue_stop_scheduler(il, txq_id);
21757ac9a364SKalle Valo
21767ac9a364SKalle Valo /* Map receiver-address / traffic-ID to this queue */
21777ac9a364SKalle Valo il4965_tx_queue_set_q2ratid(il, ra_tid, txq_id);
21787ac9a364SKalle Valo
21797ac9a364SKalle Valo /* Set this queue as a chain-building queue */
21807ac9a364SKalle Valo il_set_bits_prph(il, IL49_SCD_QUEUECHAIN_SEL, (1 << txq_id));
21817ac9a364SKalle Valo
21827ac9a364SKalle Valo /* Place first TFD at idx corresponding to start sequence number.
21837ac9a364SKalle Valo * Assumes that ssn_idx is valid (!= 0xFFF) */
21847ac9a364SKalle Valo il->txq[txq_id].q.read_ptr = (ssn_idx & 0xff);
21857ac9a364SKalle Valo il->txq[txq_id].q.write_ptr = (ssn_idx & 0xff);
21867ac9a364SKalle Valo il4965_set_wr_ptrs(il, txq_id, ssn_idx);
21877ac9a364SKalle Valo
21887ac9a364SKalle Valo /* Set up Tx win size and frame limit for this queue */
21897ac9a364SKalle Valo il_write_targ_mem(il,
21907ac9a364SKalle Valo il->scd_base_addr +
21917ac9a364SKalle Valo IL49_SCD_CONTEXT_QUEUE_OFFSET(txq_id),
21927ac9a364SKalle Valo (SCD_WIN_SIZE << IL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_POS)
21937ac9a364SKalle Valo & IL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK);
21947ac9a364SKalle Valo
21957ac9a364SKalle Valo il_write_targ_mem(il,
21967ac9a364SKalle Valo il->scd_base_addr +
21977ac9a364SKalle Valo IL49_SCD_CONTEXT_QUEUE_OFFSET(txq_id) + sizeof(u32),
21987ac9a364SKalle Valo (SCD_FRAME_LIMIT <<
21997ac9a364SKalle Valo IL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
22007ac9a364SKalle Valo IL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK);
22017ac9a364SKalle Valo
22027ac9a364SKalle Valo il_set_bits_prph(il, IL49_SCD_INTERRUPT_MASK, (1 << txq_id));
22037ac9a364SKalle Valo
22047ac9a364SKalle Valo /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */
22057ac9a364SKalle Valo il4965_tx_queue_set_status(il, &il->txq[txq_id], tx_fifo, 1);
22067ac9a364SKalle Valo
22077ac9a364SKalle Valo spin_unlock_irqrestore(&il->lock, flags);
22087ac9a364SKalle Valo
22097ac9a364SKalle Valo return 0;
22107ac9a364SKalle Valo }
22117ac9a364SKalle Valo
22127ac9a364SKalle Valo int
il4965_tx_agg_start(struct il_priv * il,struct ieee80211_vif * vif,struct ieee80211_sta * sta,u16 tid,u16 * ssn)22137ac9a364SKalle Valo il4965_tx_agg_start(struct il_priv *il, struct ieee80211_vif *vif,
22147ac9a364SKalle Valo struct ieee80211_sta *sta, u16 tid, u16 * ssn)
22157ac9a364SKalle Valo {
22167ac9a364SKalle Valo int sta_id;
22177ac9a364SKalle Valo int tx_fifo;
22187ac9a364SKalle Valo int txq_id;
22197ac9a364SKalle Valo int ret;
22207ac9a364SKalle Valo unsigned long flags;
22217ac9a364SKalle Valo struct il_tid_data *tid_data;
22227ac9a364SKalle Valo
22237ac9a364SKalle Valo /* FIXME: warning if tx fifo not found ? */
22247ac9a364SKalle Valo tx_fifo = il4965_get_fifo_from_tid(tid);
22257ac9a364SKalle Valo if (unlikely(tx_fifo < 0))
22267ac9a364SKalle Valo return tx_fifo;
22277ac9a364SKalle Valo
22287ac9a364SKalle Valo D_HT("%s on ra = %pM tid = %d\n", __func__, sta->addr, tid);
22297ac9a364SKalle Valo
22307ac9a364SKalle Valo sta_id = il_sta_id(sta);
22317ac9a364SKalle Valo if (sta_id == IL_INVALID_STATION) {
22327ac9a364SKalle Valo IL_ERR("Start AGG on invalid station\n");
22337ac9a364SKalle Valo return -ENXIO;
22347ac9a364SKalle Valo }
22357ac9a364SKalle Valo if (unlikely(tid >= MAX_TID_COUNT))
22367ac9a364SKalle Valo return -EINVAL;
22377ac9a364SKalle Valo
22387ac9a364SKalle Valo if (il->stations[sta_id].tid[tid].agg.state != IL_AGG_OFF) {
22397ac9a364SKalle Valo IL_ERR("Start AGG when state is not IL_AGG_OFF !\n");
22407ac9a364SKalle Valo return -ENXIO;
22417ac9a364SKalle Valo }
22427ac9a364SKalle Valo
22437ac9a364SKalle Valo txq_id = il4965_txq_ctx_activate_free(il);
22447ac9a364SKalle Valo if (txq_id == -1) {
22457ac9a364SKalle Valo IL_ERR("No free aggregation queue available\n");
22467ac9a364SKalle Valo return -ENXIO;
22477ac9a364SKalle Valo }
22487ac9a364SKalle Valo
22497ac9a364SKalle Valo spin_lock_irqsave(&il->sta_lock, flags);
22507ac9a364SKalle Valo tid_data = &il->stations[sta_id].tid[tid];
22517ac9a364SKalle Valo *ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number);
22527ac9a364SKalle Valo tid_data->agg.txq_id = txq_id;
22537ac9a364SKalle Valo il_set_swq_id(&il->txq[txq_id], il4965_get_ac_from_tid(tid), txq_id);
22547ac9a364SKalle Valo spin_unlock_irqrestore(&il->sta_lock, flags);
22557ac9a364SKalle Valo
22567ac9a364SKalle Valo ret = il4965_txq_agg_enable(il, txq_id, tx_fifo, sta_id, tid, *ssn);
22577ac9a364SKalle Valo if (ret)
22587ac9a364SKalle Valo return ret;
22597ac9a364SKalle Valo
22607ac9a364SKalle Valo spin_lock_irqsave(&il->sta_lock, flags);
22617ac9a364SKalle Valo tid_data = &il->stations[sta_id].tid[tid];
22627ac9a364SKalle Valo if (tid_data->tfds_in_queue == 0) {
22637ac9a364SKalle Valo D_HT("HW queue is empty\n");
22647ac9a364SKalle Valo tid_data->agg.state = IL_AGG_ON;
22652ce113deSJohannes Berg ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
22667ac9a364SKalle Valo } else {
22677ac9a364SKalle Valo D_HT("HW queue is NOT empty: %d packets in HW queue\n",
22687ac9a364SKalle Valo tid_data->tfds_in_queue);
22697ac9a364SKalle Valo tid_data->agg.state = IL_EMPTYING_HW_QUEUE_ADDBA;
22707ac9a364SKalle Valo }
22717ac9a364SKalle Valo spin_unlock_irqrestore(&il->sta_lock, flags);
22727ac9a364SKalle Valo return ret;
22737ac9a364SKalle Valo }
22747ac9a364SKalle Valo
227535b7fbfcSLee Jones /*
22767ac9a364SKalle Valo * txq_id must be greater than IL49_FIRST_AMPDU_QUEUE
22777ac9a364SKalle Valo * il->lock must be held by the caller
22787ac9a364SKalle Valo */
22797ac9a364SKalle Valo static int
il4965_txq_agg_disable(struct il_priv * il,u16 txq_id,u16 ssn_idx,u8 tx_fifo)22807ac9a364SKalle Valo il4965_txq_agg_disable(struct il_priv *il, u16 txq_id, u16 ssn_idx, u8 tx_fifo)
22817ac9a364SKalle Valo {
22827ac9a364SKalle Valo if ((IL49_FIRST_AMPDU_QUEUE > txq_id) ||
22837ac9a364SKalle Valo (IL49_FIRST_AMPDU_QUEUE +
22847ac9a364SKalle Valo il->cfg->num_of_ampdu_queues <= txq_id)) {
22857ac9a364SKalle Valo IL_WARN("queue number out of range: %d, must be %d to %d\n",
22867ac9a364SKalle Valo txq_id, IL49_FIRST_AMPDU_QUEUE,
22877ac9a364SKalle Valo IL49_FIRST_AMPDU_QUEUE +
22887ac9a364SKalle Valo il->cfg->num_of_ampdu_queues - 1);
22897ac9a364SKalle Valo return -EINVAL;
22907ac9a364SKalle Valo }
22917ac9a364SKalle Valo
22927ac9a364SKalle Valo il4965_tx_queue_stop_scheduler(il, txq_id);
22937ac9a364SKalle Valo
22947ac9a364SKalle Valo il_clear_bits_prph(il, IL49_SCD_QUEUECHAIN_SEL, (1 << txq_id));
22957ac9a364SKalle Valo
22967ac9a364SKalle Valo il->txq[txq_id].q.read_ptr = (ssn_idx & 0xff);
22977ac9a364SKalle Valo il->txq[txq_id].q.write_ptr = (ssn_idx & 0xff);
22987ac9a364SKalle Valo /* supposes that ssn_idx is valid (!= 0xFFF) */
22997ac9a364SKalle Valo il4965_set_wr_ptrs(il, txq_id, ssn_idx);
23007ac9a364SKalle Valo
23017ac9a364SKalle Valo il_clear_bits_prph(il, IL49_SCD_INTERRUPT_MASK, (1 << txq_id));
23027ac9a364SKalle Valo il_txq_ctx_deactivate(il, txq_id);
23037ac9a364SKalle Valo il4965_tx_queue_set_status(il, &il->txq[txq_id], tx_fifo, 0);
23047ac9a364SKalle Valo
23057ac9a364SKalle Valo return 0;
23067ac9a364SKalle Valo }
23077ac9a364SKalle Valo
23087ac9a364SKalle Valo int
il4965_tx_agg_stop(struct il_priv * il,struct ieee80211_vif * vif,struct ieee80211_sta * sta,u16 tid)23097ac9a364SKalle Valo il4965_tx_agg_stop(struct il_priv *il, struct ieee80211_vif *vif,
23107ac9a364SKalle Valo struct ieee80211_sta *sta, u16 tid)
23117ac9a364SKalle Valo {
23127ac9a364SKalle Valo int tx_fifo_id, txq_id, sta_id, ssn;
23137ac9a364SKalle Valo struct il_tid_data *tid_data;
23147ac9a364SKalle Valo int write_ptr, read_ptr;
23157ac9a364SKalle Valo unsigned long flags;
23167ac9a364SKalle Valo
23177ac9a364SKalle Valo /* FIXME: warning if tx_fifo_id not found ? */
23187ac9a364SKalle Valo tx_fifo_id = il4965_get_fifo_from_tid(tid);
23197ac9a364SKalle Valo if (unlikely(tx_fifo_id < 0))
23207ac9a364SKalle Valo return tx_fifo_id;
23217ac9a364SKalle Valo
23227ac9a364SKalle Valo sta_id = il_sta_id(sta);
23237ac9a364SKalle Valo
23247ac9a364SKalle Valo if (sta_id == IL_INVALID_STATION) {
23257ac9a364SKalle Valo IL_ERR("Invalid station for AGG tid %d\n", tid);
23267ac9a364SKalle Valo return -ENXIO;
23277ac9a364SKalle Valo }
23287ac9a364SKalle Valo
23297ac9a364SKalle Valo spin_lock_irqsave(&il->sta_lock, flags);
23307ac9a364SKalle Valo
23317ac9a364SKalle Valo tid_data = &il->stations[sta_id].tid[tid];
23327ac9a364SKalle Valo ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4;
23337ac9a364SKalle Valo txq_id = tid_data->agg.txq_id;
23347ac9a364SKalle Valo
23357ac9a364SKalle Valo switch (il->stations[sta_id].tid[tid].agg.state) {
23367ac9a364SKalle Valo case IL_EMPTYING_HW_QUEUE_ADDBA:
23377ac9a364SKalle Valo /*
23387ac9a364SKalle Valo * This can happen if the peer stops aggregation
23397ac9a364SKalle Valo * again before we've had a chance to drain the
23407ac9a364SKalle Valo * queue we selected previously, i.e. before the
23417ac9a364SKalle Valo * session was really started completely.
23427ac9a364SKalle Valo */
23437ac9a364SKalle Valo D_HT("AGG stop before setup done\n");
23447ac9a364SKalle Valo goto turn_off;
23457ac9a364SKalle Valo case IL_AGG_ON:
23467ac9a364SKalle Valo break;
23477ac9a364SKalle Valo default:
23487ac9a364SKalle Valo IL_WARN("Stopping AGG while state not ON or starting\n");
23497ac9a364SKalle Valo }
23507ac9a364SKalle Valo
23517ac9a364SKalle Valo write_ptr = il->txq[txq_id].q.write_ptr;
23527ac9a364SKalle Valo read_ptr = il->txq[txq_id].q.read_ptr;
23537ac9a364SKalle Valo
23547ac9a364SKalle Valo /* The queue is not empty */
23557ac9a364SKalle Valo if (write_ptr != read_ptr) {
23567ac9a364SKalle Valo D_HT("Stopping a non empty AGG HW QUEUE\n");
23577ac9a364SKalle Valo il->stations[sta_id].tid[tid].agg.state =
23587ac9a364SKalle Valo IL_EMPTYING_HW_QUEUE_DELBA;
23597ac9a364SKalle Valo spin_unlock_irqrestore(&il->sta_lock, flags);
23607ac9a364SKalle Valo return 0;
23617ac9a364SKalle Valo }
23627ac9a364SKalle Valo
23637ac9a364SKalle Valo D_HT("HW queue is empty\n");
23647ac9a364SKalle Valo turn_off:
23657ac9a364SKalle Valo il->stations[sta_id].tid[tid].agg.state = IL_AGG_OFF;
23667ac9a364SKalle Valo
23677ac9a364SKalle Valo /* do not restore/save irqs */
23687ac9a364SKalle Valo spin_unlock(&il->sta_lock);
23697ac9a364SKalle Valo spin_lock(&il->lock);
23707ac9a364SKalle Valo
23717ac9a364SKalle Valo /*
23727ac9a364SKalle Valo * the only reason this call can fail is queue number out of range,
23737ac9a364SKalle Valo * which can happen if uCode is reloaded and all the station
23747ac9a364SKalle Valo * information are lost. if it is outside the range, there is no need
23757ac9a364SKalle Valo * to deactivate the uCode queue, just return "success" to allow
23767ac9a364SKalle Valo * mac80211 to clean up it own data.
23777ac9a364SKalle Valo */
23787ac9a364SKalle Valo il4965_txq_agg_disable(il, txq_id, ssn, tx_fifo_id);
23797ac9a364SKalle Valo spin_unlock_irqrestore(&il->lock, flags);
23807ac9a364SKalle Valo
23817ac9a364SKalle Valo ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
23827ac9a364SKalle Valo
23837ac9a364SKalle Valo return 0;
23847ac9a364SKalle Valo }
23857ac9a364SKalle Valo
23867ac9a364SKalle Valo int
il4965_txq_check_empty(struct il_priv * il,int sta_id,u8 tid,int txq_id)23877ac9a364SKalle Valo il4965_txq_check_empty(struct il_priv *il, int sta_id, u8 tid, int txq_id)
23887ac9a364SKalle Valo {
23897ac9a364SKalle Valo struct il_queue *q = &il->txq[txq_id].q;
23907ac9a364SKalle Valo u8 *addr = il->stations[sta_id].sta.sta.addr;
23917ac9a364SKalle Valo struct il_tid_data *tid_data = &il->stations[sta_id].tid[tid];
23927ac9a364SKalle Valo
23937ac9a364SKalle Valo lockdep_assert_held(&il->sta_lock);
23947ac9a364SKalle Valo
23957ac9a364SKalle Valo switch (il->stations[sta_id].tid[tid].agg.state) {
23967ac9a364SKalle Valo case IL_EMPTYING_HW_QUEUE_DELBA:
23977ac9a364SKalle Valo /* We are reclaiming the last packet of the */
23987ac9a364SKalle Valo /* aggregated HW queue */
23997ac9a364SKalle Valo if (txq_id == tid_data->agg.txq_id &&
24007ac9a364SKalle Valo q->read_ptr == q->write_ptr) {
24017ac9a364SKalle Valo u16 ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number);
24027ac9a364SKalle Valo int tx_fifo = il4965_get_fifo_from_tid(tid);
24037ac9a364SKalle Valo D_HT("HW queue empty: continue DELBA flow\n");
24047ac9a364SKalle Valo il4965_txq_agg_disable(il, txq_id, ssn, tx_fifo);
24057ac9a364SKalle Valo tid_data->agg.state = IL_AGG_OFF;
24067ac9a364SKalle Valo ieee80211_stop_tx_ba_cb_irqsafe(il->vif, addr, tid);
24077ac9a364SKalle Valo }
24087ac9a364SKalle Valo break;
24097ac9a364SKalle Valo case IL_EMPTYING_HW_QUEUE_ADDBA:
24107ac9a364SKalle Valo /* We are reclaiming the last packet of the queue */
24117ac9a364SKalle Valo if (tid_data->tfds_in_queue == 0) {
24127ac9a364SKalle Valo D_HT("HW queue empty: continue ADDBA flow\n");
24137ac9a364SKalle Valo tid_data->agg.state = IL_AGG_ON;
24147ac9a364SKalle Valo ieee80211_start_tx_ba_cb_irqsafe(il->vif, addr, tid);
24157ac9a364SKalle Valo }
24167ac9a364SKalle Valo break;
24177ac9a364SKalle Valo }
24187ac9a364SKalle Valo
24197ac9a364SKalle Valo return 0;
24207ac9a364SKalle Valo }
24217ac9a364SKalle Valo
24227ac9a364SKalle Valo static void
il4965_non_agg_tx_status(struct il_priv * il,const u8 * addr1)24237ac9a364SKalle Valo il4965_non_agg_tx_status(struct il_priv *il, const u8 *addr1)
24247ac9a364SKalle Valo {
24257ac9a364SKalle Valo struct ieee80211_sta *sta;
24267ac9a364SKalle Valo struct il_station_priv *sta_priv;
24277ac9a364SKalle Valo
24287ac9a364SKalle Valo rcu_read_lock();
24297ac9a364SKalle Valo sta = ieee80211_find_sta(il->vif, addr1);
24307ac9a364SKalle Valo if (sta) {
24317ac9a364SKalle Valo sta_priv = (void *)sta->drv_priv;
24327ac9a364SKalle Valo /* avoid atomic ops if this isn't a client */
24337ac9a364SKalle Valo if (sta_priv->client &&
24347ac9a364SKalle Valo atomic_dec_return(&sta_priv->pending_frames) == 0)
24357ac9a364SKalle Valo ieee80211_sta_block_awake(il->hw, sta, false);
24367ac9a364SKalle Valo }
24377ac9a364SKalle Valo rcu_read_unlock();
24387ac9a364SKalle Valo }
24397ac9a364SKalle Valo
24407ac9a364SKalle Valo static void
il4965_tx_status(struct il_priv * il,struct sk_buff * skb,bool is_agg)24417ac9a364SKalle Valo il4965_tx_status(struct il_priv *il, struct sk_buff *skb, bool is_agg)
24427ac9a364SKalle Valo {
24437ac9a364SKalle Valo struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
24447ac9a364SKalle Valo
24457ac9a364SKalle Valo if (!is_agg)
24467ac9a364SKalle Valo il4965_non_agg_tx_status(il, hdr->addr1);
24477ac9a364SKalle Valo
24487ac9a364SKalle Valo ieee80211_tx_status_irqsafe(il->hw, skb);
24497ac9a364SKalle Valo }
24507ac9a364SKalle Valo
24517ac9a364SKalle Valo int
il4965_tx_queue_reclaim(struct il_priv * il,int txq_id,int idx)24527ac9a364SKalle Valo il4965_tx_queue_reclaim(struct il_priv *il, int txq_id, int idx)
24537ac9a364SKalle Valo {
24547ac9a364SKalle Valo struct il_tx_queue *txq = &il->txq[txq_id];
24557ac9a364SKalle Valo struct il_queue *q = &txq->q;
24567ac9a364SKalle Valo int nfreed = 0;
24577ac9a364SKalle Valo struct ieee80211_hdr *hdr;
24587ac9a364SKalle Valo struct sk_buff *skb;
24597ac9a364SKalle Valo
24607ac9a364SKalle Valo if (idx >= q->n_bd || il_queue_used(q, idx) == 0) {
24617ac9a364SKalle Valo IL_ERR("Read idx for DMA queue txq id (%d), idx %d, "
24627ac9a364SKalle Valo "is out of range [0-%d] %d %d.\n", txq_id, idx, q->n_bd,
24637ac9a364SKalle Valo q->write_ptr, q->read_ptr);
24647ac9a364SKalle Valo return 0;
24657ac9a364SKalle Valo }
24667ac9a364SKalle Valo
24677ac9a364SKalle Valo for (idx = il_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx;
24687ac9a364SKalle Valo q->read_ptr = il_queue_inc_wrap(q->read_ptr, q->n_bd)) {
24697ac9a364SKalle Valo
24707ac9a364SKalle Valo skb = txq->skbs[txq->q.read_ptr];
24717ac9a364SKalle Valo
24727ac9a364SKalle Valo if (WARN_ON_ONCE(skb == NULL))
24737ac9a364SKalle Valo continue;
24747ac9a364SKalle Valo
24757ac9a364SKalle Valo hdr = (struct ieee80211_hdr *) skb->data;
24767ac9a364SKalle Valo if (ieee80211_is_data_qos(hdr->frame_control))
24777ac9a364SKalle Valo nfreed++;
24787ac9a364SKalle Valo
24797ac9a364SKalle Valo il4965_tx_status(il, skb, txq_id >= IL4965_FIRST_AMPDU_QUEUE);
24807ac9a364SKalle Valo
24817ac9a364SKalle Valo txq->skbs[txq->q.read_ptr] = NULL;
24827ac9a364SKalle Valo il->ops->txq_free_tfd(il, txq);
24837ac9a364SKalle Valo }
24847ac9a364SKalle Valo return nfreed;
24857ac9a364SKalle Valo }
24867ac9a364SKalle Valo
248735b7fbfcSLee Jones /*
24887ac9a364SKalle Valo * il4965_tx_status_reply_compressed_ba - Update tx status from block-ack
24897ac9a364SKalle Valo *
24907ac9a364SKalle Valo * Go through block-ack's bitmap of ACK'd frames, update driver's record of
24917ac9a364SKalle Valo * ACK vs. not. This gets sent to mac80211, then to rate scaling algo.
24927ac9a364SKalle Valo */
24937ac9a364SKalle Valo static int
il4965_tx_status_reply_compressed_ba(struct il_priv * il,struct il_ht_agg * agg,struct il_compressed_ba_resp * ba_resp)24947ac9a364SKalle Valo il4965_tx_status_reply_compressed_ba(struct il_priv *il, struct il_ht_agg *agg,
24957ac9a364SKalle Valo struct il_compressed_ba_resp *ba_resp)
24967ac9a364SKalle Valo {
24977ac9a364SKalle Valo int i, sh, ack;
24987ac9a364SKalle Valo u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl);
24997ac9a364SKalle Valo u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
25007ac9a364SKalle Valo int successes = 0;
25017ac9a364SKalle Valo struct ieee80211_tx_info *info;
25027ac9a364SKalle Valo u64 bitmap, sent_bitmap;
25037ac9a364SKalle Valo
25047ac9a364SKalle Valo if (unlikely(!agg->wait_for_ba)) {
25057ac9a364SKalle Valo if (unlikely(ba_resp->bitmap))
25067ac9a364SKalle Valo IL_ERR("Received BA when not expected\n");
25077ac9a364SKalle Valo return -EINVAL;
25087ac9a364SKalle Valo }
25097ac9a364SKalle Valo
25107ac9a364SKalle Valo /* Mark that the expected block-ack response arrived */
25117ac9a364SKalle Valo agg->wait_for_ba = 0;
25127ac9a364SKalle Valo D_TX_REPLY("BA %d %d\n", agg->start_idx, ba_resp->seq_ctl);
25137ac9a364SKalle Valo
25147ac9a364SKalle Valo /* Calculate shift to align block-ack bits with our Tx win bits */
25157ac9a364SKalle Valo sh = agg->start_idx - SEQ_TO_IDX(seq_ctl >> 4);
25167ac9a364SKalle Valo if (sh < 0) /* tbw something is wrong with indices */
25177ac9a364SKalle Valo sh += 0x100;
25187ac9a364SKalle Valo
25197ac9a364SKalle Valo if (agg->frame_count > (64 - sh)) {
25207ac9a364SKalle Valo D_TX_REPLY("more frames than bitmap size");
25217ac9a364SKalle Valo return -1;
25227ac9a364SKalle Valo }
25237ac9a364SKalle Valo
25247ac9a364SKalle Valo /* don't use 64-bit values for now */
25257ac9a364SKalle Valo bitmap = le64_to_cpu(ba_resp->bitmap) >> sh;
25267ac9a364SKalle Valo
25277ac9a364SKalle Valo /* check for success or failure according to the
25287ac9a364SKalle Valo * transmitted bitmap and block-ack bitmap */
25297ac9a364SKalle Valo sent_bitmap = bitmap & agg->bitmap;
25307ac9a364SKalle Valo
25317ac9a364SKalle Valo /* For each frame attempted in aggregation,
25327ac9a364SKalle Valo * update driver's record of tx frame's status. */
25337ac9a364SKalle Valo i = 0;
25347ac9a364SKalle Valo while (sent_bitmap) {
25357ac9a364SKalle Valo ack = sent_bitmap & 1ULL;
25367ac9a364SKalle Valo successes += ack;
25377ac9a364SKalle Valo D_TX_REPLY("%s ON i=%d idx=%d raw=%d\n", ack ? "ACK" : "NACK",
25387ac9a364SKalle Valo i, (agg->start_idx + i) & 0xff, agg->start_idx + i);
25397ac9a364SKalle Valo sent_bitmap >>= 1;
25407ac9a364SKalle Valo ++i;
25417ac9a364SKalle Valo }
25427ac9a364SKalle Valo
25437ac9a364SKalle Valo D_TX_REPLY("Bitmap %llx\n", (unsigned long long)bitmap);
25447ac9a364SKalle Valo
25457ac9a364SKalle Valo info = IEEE80211_SKB_CB(il->txq[scd_flow].skbs[agg->start_idx]);
25467ac9a364SKalle Valo memset(&info->status, 0, sizeof(info->status));
25477ac9a364SKalle Valo info->flags |= IEEE80211_TX_STAT_ACK;
25487ac9a364SKalle Valo info->flags |= IEEE80211_TX_STAT_AMPDU;
25497ac9a364SKalle Valo info->status.ampdu_ack_len = successes;
25507ac9a364SKalle Valo info->status.ampdu_len = agg->frame_count;
25517ac9a364SKalle Valo il4965_hwrate_to_tx_control(il, agg->rate_n_flags, info);
25527ac9a364SKalle Valo
25537ac9a364SKalle Valo return 0;
25547ac9a364SKalle Valo }
25557ac9a364SKalle Valo
25567ac9a364SKalle Valo static inline bool
il4965_is_tx_success(u32 status)25577ac9a364SKalle Valo il4965_is_tx_success(u32 status)
25587ac9a364SKalle Valo {
25597ac9a364SKalle Valo status &= TX_STATUS_MSK;
25607ac9a364SKalle Valo return (status == TX_STATUS_SUCCESS || status == TX_STATUS_DIRECT_DONE);
25617ac9a364SKalle Valo }
25627ac9a364SKalle Valo
25637ac9a364SKalle Valo static u8
il4965_find_station(struct il_priv * il,const u8 * addr)25647ac9a364SKalle Valo il4965_find_station(struct il_priv *il, const u8 *addr)
25657ac9a364SKalle Valo {
25667ac9a364SKalle Valo int i;
25677ac9a364SKalle Valo int start = 0;
25687ac9a364SKalle Valo int ret = IL_INVALID_STATION;
25697ac9a364SKalle Valo unsigned long flags;
25707ac9a364SKalle Valo
25717ac9a364SKalle Valo if (il->iw_mode == NL80211_IFTYPE_ADHOC)
25727ac9a364SKalle Valo start = IL_STA_ID;
25737ac9a364SKalle Valo
25747ac9a364SKalle Valo if (is_broadcast_ether_addr(addr))
25757ac9a364SKalle Valo return il->hw_params.bcast_id;
25767ac9a364SKalle Valo
25777ac9a364SKalle Valo spin_lock_irqsave(&il->sta_lock, flags);
25787ac9a364SKalle Valo for (i = start; i < il->hw_params.max_stations; i++)
25797ac9a364SKalle Valo if (il->stations[i].used &&
25807ac9a364SKalle Valo ether_addr_equal(il->stations[i].sta.sta.addr, addr)) {
25817ac9a364SKalle Valo ret = i;
25827ac9a364SKalle Valo goto out;
25837ac9a364SKalle Valo }
25847ac9a364SKalle Valo
25857ac9a364SKalle Valo D_ASSOC("can not find STA %pM total %d\n", addr, il->num_stations);
25867ac9a364SKalle Valo
25877ac9a364SKalle Valo out:
25887ac9a364SKalle Valo /*
25897ac9a364SKalle Valo * It may be possible that more commands interacting with stations
25907ac9a364SKalle Valo * arrive before we completed processing the adding of
25917ac9a364SKalle Valo * station
25927ac9a364SKalle Valo */
25937ac9a364SKalle Valo if (ret != IL_INVALID_STATION &&
25947ac9a364SKalle Valo (!(il->stations[ret].used & IL_STA_UCODE_ACTIVE) ||
2595fcb8f3caSJiapeng Chong (il->stations[ret].used & IL_STA_UCODE_INPROGRESS))) {
25967ac9a364SKalle Valo IL_ERR("Requested station info for sta %d before ready.\n",
25977ac9a364SKalle Valo ret);
25987ac9a364SKalle Valo ret = IL_INVALID_STATION;
25997ac9a364SKalle Valo }
26007ac9a364SKalle Valo spin_unlock_irqrestore(&il->sta_lock, flags);
26017ac9a364SKalle Valo return ret;
26027ac9a364SKalle Valo }
26037ac9a364SKalle Valo
26047ac9a364SKalle Valo static int
il4965_get_ra_sta_id(struct il_priv * il,struct ieee80211_hdr * hdr)26057ac9a364SKalle Valo il4965_get_ra_sta_id(struct il_priv *il, struct ieee80211_hdr *hdr)
26067ac9a364SKalle Valo {
26077ac9a364SKalle Valo if (il->iw_mode == NL80211_IFTYPE_STATION)
26087ac9a364SKalle Valo return IL_AP_ID;
26097ac9a364SKalle Valo else {
26107ac9a364SKalle Valo u8 *da = ieee80211_get_DA(hdr);
26117ac9a364SKalle Valo
26127ac9a364SKalle Valo return il4965_find_station(il, da);
26137ac9a364SKalle Valo }
26147ac9a364SKalle Valo }
26157ac9a364SKalle Valo
26167ac9a364SKalle Valo static inline u32
il4965_get_scd_ssn(struct il4965_tx_resp * tx_resp)26177ac9a364SKalle Valo il4965_get_scd_ssn(struct il4965_tx_resp *tx_resp)
26187ac9a364SKalle Valo {
26197ac9a364SKalle Valo return le32_to_cpup(&tx_resp->u.status +
26207ac9a364SKalle Valo tx_resp->frame_count) & IEEE80211_MAX_SN;
26217ac9a364SKalle Valo }
26227ac9a364SKalle Valo
26237ac9a364SKalle Valo static inline u32
il4965_tx_status_to_mac80211(u32 status)26247ac9a364SKalle Valo il4965_tx_status_to_mac80211(u32 status)
26257ac9a364SKalle Valo {
26267ac9a364SKalle Valo status &= TX_STATUS_MSK;
26277ac9a364SKalle Valo
26287ac9a364SKalle Valo switch (status) {
26297ac9a364SKalle Valo case TX_STATUS_SUCCESS:
26307ac9a364SKalle Valo case TX_STATUS_DIRECT_DONE:
26317ac9a364SKalle Valo return IEEE80211_TX_STAT_ACK;
26327ac9a364SKalle Valo case TX_STATUS_FAIL_DEST_PS:
26337ac9a364SKalle Valo return IEEE80211_TX_STAT_TX_FILTERED;
26347ac9a364SKalle Valo default:
26357ac9a364SKalle Valo return 0;
26367ac9a364SKalle Valo }
26377ac9a364SKalle Valo }
26387ac9a364SKalle Valo
263935b7fbfcSLee Jones /*
26407ac9a364SKalle Valo * il4965_tx_status_reply_tx - Handle Tx response for frames in aggregation queue
26417ac9a364SKalle Valo */
26427ac9a364SKalle Valo static int
il4965_tx_status_reply_tx(struct il_priv * il,struct il_ht_agg * agg,struct il4965_tx_resp * tx_resp,int txq_id,u16 start_idx)26437ac9a364SKalle Valo il4965_tx_status_reply_tx(struct il_priv *il, struct il_ht_agg *agg,
26447ac9a364SKalle Valo struct il4965_tx_resp *tx_resp, int txq_id,
26457ac9a364SKalle Valo u16 start_idx)
26467ac9a364SKalle Valo {
26477ac9a364SKalle Valo u16 status;
26487ac9a364SKalle Valo struct agg_tx_status *frame_status = tx_resp->u.agg_status;
26497ac9a364SKalle Valo struct ieee80211_tx_info *info = NULL;
26507ac9a364SKalle Valo struct ieee80211_hdr *hdr = NULL;
26517ac9a364SKalle Valo u32 rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags);
26527ac9a364SKalle Valo int i, sh, idx;
26537ac9a364SKalle Valo u16 seq;
26547ac9a364SKalle Valo if (agg->wait_for_ba)
26557ac9a364SKalle Valo D_TX_REPLY("got tx response w/o block-ack\n");
26567ac9a364SKalle Valo
26577ac9a364SKalle Valo agg->frame_count = tx_resp->frame_count;
26587ac9a364SKalle Valo agg->start_idx = start_idx;
26597ac9a364SKalle Valo agg->rate_n_flags = rate_n_flags;
26607ac9a364SKalle Valo agg->bitmap = 0;
26617ac9a364SKalle Valo
26627ac9a364SKalle Valo /* num frames attempted by Tx command */
26637ac9a364SKalle Valo if (agg->frame_count == 1) {
26647ac9a364SKalle Valo /* Only one frame was attempted; no block-ack will arrive */
26657ac9a364SKalle Valo status = le16_to_cpu(frame_status[0].status);
26667ac9a364SKalle Valo idx = start_idx;
26677ac9a364SKalle Valo
26687ac9a364SKalle Valo D_TX_REPLY("FrameCnt = %d, StartIdx=%d idx=%d\n",
26697ac9a364SKalle Valo agg->frame_count, agg->start_idx, idx);
26707ac9a364SKalle Valo
26717ac9a364SKalle Valo info = IEEE80211_SKB_CB(il->txq[txq_id].skbs[idx]);
26727ac9a364SKalle Valo info->status.rates[0].count = tx_resp->failure_frame + 1;
26737ac9a364SKalle Valo info->flags &= ~IEEE80211_TX_CTL_AMPDU;
26747ac9a364SKalle Valo info->flags |= il4965_tx_status_to_mac80211(status);
26757ac9a364SKalle Valo il4965_hwrate_to_tx_control(il, rate_n_flags, info);
26767ac9a364SKalle Valo
26777ac9a364SKalle Valo D_TX_REPLY("1 Frame 0x%x failure :%d\n", status & 0xff,
26787ac9a364SKalle Valo tx_resp->failure_frame);
26797ac9a364SKalle Valo D_TX_REPLY("Rate Info rate_n_flags=%x\n", rate_n_flags);
26807ac9a364SKalle Valo
26817ac9a364SKalle Valo agg->wait_for_ba = 0;
26827ac9a364SKalle Valo } else {
26837ac9a364SKalle Valo /* Two or more frames were attempted; expect block-ack */
26847ac9a364SKalle Valo u64 bitmap = 0;
26857ac9a364SKalle Valo int start = agg->start_idx;
26867ac9a364SKalle Valo struct sk_buff *skb;
26877ac9a364SKalle Valo
26887ac9a364SKalle Valo /* Construct bit-map of pending frames within Tx win */
26897ac9a364SKalle Valo for (i = 0; i < agg->frame_count; i++) {
26907ac9a364SKalle Valo u16 sc;
26917ac9a364SKalle Valo status = le16_to_cpu(frame_status[i].status);
26927ac9a364SKalle Valo seq = le16_to_cpu(frame_status[i].sequence);
26937ac9a364SKalle Valo idx = SEQ_TO_IDX(seq);
26947ac9a364SKalle Valo txq_id = SEQ_TO_QUEUE(seq);
26957ac9a364SKalle Valo
26967ac9a364SKalle Valo if (status &
26977ac9a364SKalle Valo (AGG_TX_STATE_FEW_BYTES_MSK |
26987ac9a364SKalle Valo AGG_TX_STATE_ABORT_MSK))
26997ac9a364SKalle Valo continue;
27007ac9a364SKalle Valo
27017ac9a364SKalle Valo D_TX_REPLY("FrameCnt = %d, txq_id=%d idx=%d\n",
27027ac9a364SKalle Valo agg->frame_count, txq_id, idx);
27037ac9a364SKalle Valo
27047ac9a364SKalle Valo skb = il->txq[txq_id].skbs[idx];
27057ac9a364SKalle Valo if (WARN_ON_ONCE(skb == NULL))
27067ac9a364SKalle Valo return -1;
27077ac9a364SKalle Valo hdr = (struct ieee80211_hdr *) skb->data;
27087ac9a364SKalle Valo
27097ac9a364SKalle Valo sc = le16_to_cpu(hdr->seq_ctrl);
27107ac9a364SKalle Valo if (idx != (IEEE80211_SEQ_TO_SN(sc) & 0xff)) {
27117ac9a364SKalle Valo IL_ERR("BUG_ON idx doesn't match seq control"
27127ac9a364SKalle Valo " idx=%d, seq_idx=%d, seq=%d\n", idx,
27137ac9a364SKalle Valo IEEE80211_SEQ_TO_SN(sc), hdr->seq_ctrl);
27147ac9a364SKalle Valo return -1;
27157ac9a364SKalle Valo }
27167ac9a364SKalle Valo
27177ac9a364SKalle Valo D_TX_REPLY("AGG Frame i=%d idx %d seq=%d\n", i, idx,
27187ac9a364SKalle Valo IEEE80211_SEQ_TO_SN(sc));
27197ac9a364SKalle Valo
27207ac9a364SKalle Valo sh = idx - start;
27217ac9a364SKalle Valo if (sh > 64) {
27227ac9a364SKalle Valo sh = (start - idx) + 0xff;
27237ac9a364SKalle Valo bitmap = bitmap << sh;
27247ac9a364SKalle Valo sh = 0;
27257ac9a364SKalle Valo start = idx;
27267ac9a364SKalle Valo } else if (sh < -64)
27277ac9a364SKalle Valo sh = 0xff - (start - idx);
27287ac9a364SKalle Valo else if (sh < 0) {
27297ac9a364SKalle Valo sh = start - idx;
27307ac9a364SKalle Valo start = idx;
27317ac9a364SKalle Valo bitmap = bitmap << sh;
27327ac9a364SKalle Valo sh = 0;
27337ac9a364SKalle Valo }
27347ac9a364SKalle Valo bitmap |= 1ULL << sh;
27357ac9a364SKalle Valo D_TX_REPLY("start=%d bitmap=0x%llx\n", start,
27367ac9a364SKalle Valo (unsigned long long)bitmap);
27377ac9a364SKalle Valo }
27387ac9a364SKalle Valo
27397ac9a364SKalle Valo agg->bitmap = bitmap;
27407ac9a364SKalle Valo agg->start_idx = start;
27417ac9a364SKalle Valo D_TX_REPLY("Frames %d start_idx=%d bitmap=0x%llx\n",
27427ac9a364SKalle Valo agg->frame_count, agg->start_idx,
27437ac9a364SKalle Valo (unsigned long long)agg->bitmap);
27447ac9a364SKalle Valo
27457ac9a364SKalle Valo if (bitmap)
27467ac9a364SKalle Valo agg->wait_for_ba = 1;
27477ac9a364SKalle Valo }
27487ac9a364SKalle Valo return 0;
27497ac9a364SKalle Valo }
27507ac9a364SKalle Valo
275135b7fbfcSLee Jones /*
27527ac9a364SKalle Valo * il4965_hdl_tx - Handle standard (non-aggregation) Tx response
27537ac9a364SKalle Valo */
27547ac9a364SKalle Valo static void
il4965_hdl_tx(struct il_priv * il,struct il_rx_buf * rxb)27557ac9a364SKalle Valo il4965_hdl_tx(struct il_priv *il, struct il_rx_buf *rxb)
27567ac9a364SKalle Valo {
27577ac9a364SKalle Valo struct il_rx_pkt *pkt = rxb_addr(rxb);
27587ac9a364SKalle Valo u16 sequence = le16_to_cpu(pkt->hdr.sequence);
27597ac9a364SKalle Valo int txq_id = SEQ_TO_QUEUE(sequence);
27607ac9a364SKalle Valo int idx = SEQ_TO_IDX(sequence);
27617ac9a364SKalle Valo struct il_tx_queue *txq = &il->txq[txq_id];
27627ac9a364SKalle Valo struct sk_buff *skb;
27637ac9a364SKalle Valo struct ieee80211_hdr *hdr;
27647ac9a364SKalle Valo struct ieee80211_tx_info *info;
27657ac9a364SKalle Valo struct il4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
27667ac9a364SKalle Valo u32 status = le32_to_cpu(tx_resp->u.status);
27673f649ab7SKees Cook int tid;
27687ac9a364SKalle Valo int sta_id;
27697ac9a364SKalle Valo int freed;
27707ac9a364SKalle Valo u8 *qc = NULL;
27717ac9a364SKalle Valo unsigned long flags;
27727ac9a364SKalle Valo
27737ac9a364SKalle Valo if (idx >= txq->q.n_bd || il_queue_used(&txq->q, idx) == 0) {
27747ac9a364SKalle Valo IL_ERR("Read idx for DMA queue txq_id (%d) idx %d "
27757ac9a364SKalle Valo "is out of range [0-%d] %d %d\n", txq_id, idx,
27767ac9a364SKalle Valo txq->q.n_bd, txq->q.write_ptr, txq->q.read_ptr);
27777ac9a364SKalle Valo return;
27787ac9a364SKalle Valo }
27797ac9a364SKalle Valo
27807ac9a364SKalle Valo txq->time_stamp = jiffies;
27817ac9a364SKalle Valo
27827ac9a364SKalle Valo skb = txq->skbs[txq->q.read_ptr];
27837ac9a364SKalle Valo info = IEEE80211_SKB_CB(skb);
27847ac9a364SKalle Valo memset(&info->status, 0, sizeof(info->status));
27857ac9a364SKalle Valo
27867ac9a364SKalle Valo hdr = (struct ieee80211_hdr *) skb->data;
27877ac9a364SKalle Valo if (ieee80211_is_data_qos(hdr->frame_control)) {
27887ac9a364SKalle Valo qc = ieee80211_get_qos_ctl(hdr);
27897ac9a364SKalle Valo tid = qc[0] & 0xf;
27907ac9a364SKalle Valo }
27917ac9a364SKalle Valo
27927ac9a364SKalle Valo sta_id = il4965_get_ra_sta_id(il, hdr);
27937ac9a364SKalle Valo if (txq->sched_retry && unlikely(sta_id == IL_INVALID_STATION)) {
27947ac9a364SKalle Valo IL_ERR("Station not known\n");
27957ac9a364SKalle Valo return;
27967ac9a364SKalle Valo }
27977ac9a364SKalle Valo
27987ac9a364SKalle Valo /*
27997ac9a364SKalle Valo * Firmware will not transmit frame on passive channel, if it not yet
28007ac9a364SKalle Valo * received some valid frame on that channel. When this error happen
28017ac9a364SKalle Valo * we have to wait until firmware will unblock itself i.e. when we
28027ac9a364SKalle Valo * note received beacon or other frame. We unblock queues in
28037ac9a364SKalle Valo * il4965_pass_packet_to_mac80211 or in il_mac_bss_info_changed.
28047ac9a364SKalle Valo */
28057ac9a364SKalle Valo if (unlikely((status & TX_STATUS_MSK) == TX_STATUS_FAIL_PASSIVE_NO_RX) &&
28067ac9a364SKalle Valo il->iw_mode == NL80211_IFTYPE_STATION) {
28077ac9a364SKalle Valo il_stop_queues_by_reason(il, IL_STOP_REASON_PASSIVE);
28087ac9a364SKalle Valo D_INFO("Stopped queues - RX waiting on passive channel\n");
28097ac9a364SKalle Valo }
28107ac9a364SKalle Valo
28117ac9a364SKalle Valo spin_lock_irqsave(&il->sta_lock, flags);
28127ac9a364SKalle Valo if (txq->sched_retry) {
28137ac9a364SKalle Valo const u32 scd_ssn = il4965_get_scd_ssn(tx_resp);
28144832bb37SStanislaw Gruszka struct il_ht_agg *agg;
28154832bb37SStanislaw Gruszka
28164832bb37SStanislaw Gruszka if (WARN_ON(!qc))
28174832bb37SStanislaw Gruszka goto out;
28187ac9a364SKalle Valo
28197ac9a364SKalle Valo agg = &il->stations[sta_id].tid[tid].agg;
28207ac9a364SKalle Valo
28217ac9a364SKalle Valo il4965_tx_status_reply_tx(il, agg, tx_resp, txq_id, idx);
28227ac9a364SKalle Valo
28237ac9a364SKalle Valo /* check if BAR is needed */
28247ac9a364SKalle Valo if (tx_resp->frame_count == 1 &&
28257ac9a364SKalle Valo !il4965_is_tx_success(status))
28267ac9a364SKalle Valo info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
28277ac9a364SKalle Valo
28287ac9a364SKalle Valo if (txq->q.read_ptr != (scd_ssn & 0xff)) {
28297ac9a364SKalle Valo idx = il_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd);
28307ac9a364SKalle Valo D_TX_REPLY("Retry scheduler reclaim scd_ssn "
28317ac9a364SKalle Valo "%d idx %d\n", scd_ssn, idx);
28327ac9a364SKalle Valo freed = il4965_tx_queue_reclaim(il, txq_id, idx);
28334832bb37SStanislaw Gruszka il4965_free_tfds_in_queue(il, sta_id, tid, freed);
28347ac9a364SKalle Valo
28357ac9a364SKalle Valo if (il->mac80211_registered &&
28367ac9a364SKalle Valo il_queue_space(&txq->q) > txq->q.low_mark &&
28377ac9a364SKalle Valo agg->state != IL_EMPTYING_HW_QUEUE_DELBA)
28387ac9a364SKalle Valo il_wake_queue(il, txq);
28397ac9a364SKalle Valo }
28407ac9a364SKalle Valo } else {
28417ac9a364SKalle Valo info->status.rates[0].count = tx_resp->failure_frame + 1;
28427ac9a364SKalle Valo info->flags |= il4965_tx_status_to_mac80211(status);
28437ac9a364SKalle Valo il4965_hwrate_to_tx_control(il,
28447ac9a364SKalle Valo le32_to_cpu(tx_resp->rate_n_flags),
28457ac9a364SKalle Valo info);
28467ac9a364SKalle Valo
28477ac9a364SKalle Valo D_TX_REPLY("TXQ %d status %s (0x%08x) "
28487ac9a364SKalle Valo "rate_n_flags 0x%x retries %d\n", txq_id,
28497ac9a364SKalle Valo il4965_get_tx_fail_reason(status), status,
28507ac9a364SKalle Valo le32_to_cpu(tx_resp->rate_n_flags),
28517ac9a364SKalle Valo tx_resp->failure_frame);
28527ac9a364SKalle Valo
28537ac9a364SKalle Valo freed = il4965_tx_queue_reclaim(il, txq_id, idx);
28547ac9a364SKalle Valo if (qc && likely(sta_id != IL_INVALID_STATION))
28557ac9a364SKalle Valo il4965_free_tfds_in_queue(il, sta_id, tid, freed);
28567ac9a364SKalle Valo else if (sta_id == IL_INVALID_STATION)
28577ac9a364SKalle Valo D_TX_REPLY("Station not known\n");
28587ac9a364SKalle Valo
28597ac9a364SKalle Valo if (il->mac80211_registered &&
28607ac9a364SKalle Valo il_queue_space(&txq->q) > txq->q.low_mark)
28617ac9a364SKalle Valo il_wake_queue(il, txq);
28627ac9a364SKalle Valo }
28634832bb37SStanislaw Gruszka out:
28647ac9a364SKalle Valo if (qc && likely(sta_id != IL_INVALID_STATION))
28657ac9a364SKalle Valo il4965_txq_check_empty(il, sta_id, tid, txq_id);
28667ac9a364SKalle Valo
28677ac9a364SKalle Valo il4965_check_abort_status(il, tx_resp->frame_count, status);
28687ac9a364SKalle Valo
28697ac9a364SKalle Valo spin_unlock_irqrestore(&il->sta_lock, flags);
28707ac9a364SKalle Valo }
28717ac9a364SKalle Valo
287235b7fbfcSLee Jones /*
28737ac9a364SKalle Valo * translate ucode response to mac80211 tx status control values
28747ac9a364SKalle Valo */
28757ac9a364SKalle Valo void
il4965_hwrate_to_tx_control(struct il_priv * il,u32 rate_n_flags,struct ieee80211_tx_info * info)28767ac9a364SKalle Valo il4965_hwrate_to_tx_control(struct il_priv *il, u32 rate_n_flags,
28777ac9a364SKalle Valo struct ieee80211_tx_info *info)
28787ac9a364SKalle Valo {
28797ac9a364SKalle Valo struct ieee80211_tx_rate *r = &info->status.rates[0];
28807ac9a364SKalle Valo
28817ac9a364SKalle Valo info->status.antenna =
28827ac9a364SKalle Valo ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS);
28837ac9a364SKalle Valo if (rate_n_flags & RATE_MCS_HT_MSK)
28847ac9a364SKalle Valo r->flags |= IEEE80211_TX_RC_MCS;
28857ac9a364SKalle Valo if (rate_n_flags & RATE_MCS_GF_MSK)
28867ac9a364SKalle Valo r->flags |= IEEE80211_TX_RC_GREEN_FIELD;
28877ac9a364SKalle Valo if (rate_n_flags & RATE_MCS_HT40_MSK)
28887ac9a364SKalle Valo r->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
28897ac9a364SKalle Valo if (rate_n_flags & RATE_MCS_DUP_MSK)
28907ac9a364SKalle Valo r->flags |= IEEE80211_TX_RC_DUP_DATA;
28917ac9a364SKalle Valo if (rate_n_flags & RATE_MCS_SGI_MSK)
28927ac9a364SKalle Valo r->flags |= IEEE80211_TX_RC_SHORT_GI;
28937ac9a364SKalle Valo r->idx = il4965_hwrate_to_mac80211_idx(rate_n_flags, info->band);
28947ac9a364SKalle Valo }
28957ac9a364SKalle Valo
289635b7fbfcSLee Jones /*
28977ac9a364SKalle Valo * il4965_hdl_compressed_ba - Handler for N_COMPRESSED_BA
28987ac9a364SKalle Valo *
28997ac9a364SKalle Valo * Handles block-acknowledge notification from device, which reports success
29007ac9a364SKalle Valo * of frames sent via aggregation.
29017ac9a364SKalle Valo */
29027ac9a364SKalle Valo static void
il4965_hdl_compressed_ba(struct il_priv * il,struct il_rx_buf * rxb)29037ac9a364SKalle Valo il4965_hdl_compressed_ba(struct il_priv *il, struct il_rx_buf *rxb)
29047ac9a364SKalle Valo {
29057ac9a364SKalle Valo struct il_rx_pkt *pkt = rxb_addr(rxb);
29067ac9a364SKalle Valo struct il_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba;
29077ac9a364SKalle Valo struct il_tx_queue *txq = NULL;
29087ac9a364SKalle Valo struct il_ht_agg *agg;
29097ac9a364SKalle Valo int idx;
29107ac9a364SKalle Valo int sta_id;
29117ac9a364SKalle Valo int tid;
29127ac9a364SKalle Valo unsigned long flags;
29137ac9a364SKalle Valo
29147ac9a364SKalle Valo /* "flow" corresponds to Tx queue */
29157ac9a364SKalle Valo u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
29167ac9a364SKalle Valo
29177ac9a364SKalle Valo /* "ssn" is start of block-ack Tx win, corresponds to idx
29187ac9a364SKalle Valo * (in Tx queue's circular buffer) of first TFD/frame in win */
29197ac9a364SKalle Valo u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn);
29207ac9a364SKalle Valo
29217ac9a364SKalle Valo if (scd_flow >= il->hw_params.max_txq_num) {
29227ac9a364SKalle Valo IL_ERR("BUG_ON scd_flow is bigger than number of queues\n");
29237ac9a364SKalle Valo return;
29247ac9a364SKalle Valo }
29257ac9a364SKalle Valo
29267ac9a364SKalle Valo txq = &il->txq[scd_flow];
29277ac9a364SKalle Valo sta_id = ba_resp->sta_id;
29287ac9a364SKalle Valo tid = ba_resp->tid;
29297ac9a364SKalle Valo agg = &il->stations[sta_id].tid[tid].agg;
29307ac9a364SKalle Valo if (unlikely(agg->txq_id != scd_flow)) {
29317ac9a364SKalle Valo /*
29327ac9a364SKalle Valo * FIXME: this is a uCode bug which need to be addressed,
29337ac9a364SKalle Valo * log the information and return for now!
29347ac9a364SKalle Valo * since it is possible happen very often and in order
29357ac9a364SKalle Valo * not to fill the syslog, don't enable the logging by default
29367ac9a364SKalle Valo */
29377ac9a364SKalle Valo D_TX_REPLY("BA scd_flow %d does not match txq_id %d\n",
29387ac9a364SKalle Valo scd_flow, agg->txq_id);
29397ac9a364SKalle Valo return;
29407ac9a364SKalle Valo }
29417ac9a364SKalle Valo
29427ac9a364SKalle Valo /* Find idx just before block-ack win */
29437ac9a364SKalle Valo idx = il_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd);
29447ac9a364SKalle Valo
29457ac9a364SKalle Valo spin_lock_irqsave(&il->sta_lock, flags);
29467ac9a364SKalle Valo
29477ac9a364SKalle Valo D_TX_REPLY("N_COMPRESSED_BA [%d] Received from %pM, " "sta_id = %d\n",
29487ac9a364SKalle Valo agg->wait_for_ba, (u8 *) &ba_resp->sta_addr_lo32,
29497ac9a364SKalle Valo ba_resp->sta_id);
29507ac9a364SKalle Valo D_TX_REPLY("TID = %d, SeqCtl = %d, bitmap = 0x%llx," "scd_flow = "
29517ac9a364SKalle Valo "%d, scd_ssn = %d\n", ba_resp->tid, ba_resp->seq_ctl,
29527ac9a364SKalle Valo (unsigned long long)le64_to_cpu(ba_resp->bitmap),
29537ac9a364SKalle Valo ba_resp->scd_flow, ba_resp->scd_ssn);
29547ac9a364SKalle Valo D_TX_REPLY("DAT start_idx = %d, bitmap = 0x%llx\n", agg->start_idx,
29557ac9a364SKalle Valo (unsigned long long)agg->bitmap);
29567ac9a364SKalle Valo
29577ac9a364SKalle Valo /* Update driver's record of ACK vs. not for each frame in win */
29587ac9a364SKalle Valo il4965_tx_status_reply_compressed_ba(il, agg, ba_resp);
29597ac9a364SKalle Valo
29607ac9a364SKalle Valo /* Release all TFDs before the SSN, i.e. all TFDs in front of
29617ac9a364SKalle Valo * block-ack win (we assume that they've been successfully
29627ac9a364SKalle Valo * transmitted ... if not, it's too late anyway). */
29637ac9a364SKalle Valo if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) {
29647ac9a364SKalle Valo /* calculate mac80211 ampdu sw queue to wake */
29657ac9a364SKalle Valo int freed = il4965_tx_queue_reclaim(il, scd_flow, idx);
29667ac9a364SKalle Valo il4965_free_tfds_in_queue(il, sta_id, tid, freed);
29677ac9a364SKalle Valo
29687ac9a364SKalle Valo if (il_queue_space(&txq->q) > txq->q.low_mark &&
29697ac9a364SKalle Valo il->mac80211_registered &&
29707ac9a364SKalle Valo agg->state != IL_EMPTYING_HW_QUEUE_DELBA)
29717ac9a364SKalle Valo il_wake_queue(il, txq);
29727ac9a364SKalle Valo
29737ac9a364SKalle Valo il4965_txq_check_empty(il, sta_id, tid, scd_flow);
29747ac9a364SKalle Valo }
29757ac9a364SKalle Valo
29767ac9a364SKalle Valo spin_unlock_irqrestore(&il->sta_lock, flags);
29777ac9a364SKalle Valo }
29787ac9a364SKalle Valo
29797ac9a364SKalle Valo #ifdef CONFIG_IWLEGACY_DEBUG
29807ac9a364SKalle Valo const char *
il4965_get_tx_fail_reason(u32 status)29817ac9a364SKalle Valo il4965_get_tx_fail_reason(u32 status)
29827ac9a364SKalle Valo {
29837ac9a364SKalle Valo #define TX_STATUS_FAIL(x) case TX_STATUS_FAIL_ ## x: return #x
29847ac9a364SKalle Valo #define TX_STATUS_POSTPONE(x) case TX_STATUS_POSTPONE_ ## x: return #x
29857ac9a364SKalle Valo
29867ac9a364SKalle Valo switch (status & TX_STATUS_MSK) {
29877ac9a364SKalle Valo case TX_STATUS_SUCCESS:
29887ac9a364SKalle Valo return "SUCCESS";
29897ac9a364SKalle Valo TX_STATUS_POSTPONE(DELAY);
29907ac9a364SKalle Valo TX_STATUS_POSTPONE(FEW_BYTES);
29917ac9a364SKalle Valo TX_STATUS_POSTPONE(QUIET_PERIOD);
29927ac9a364SKalle Valo TX_STATUS_POSTPONE(CALC_TTAK);
29937ac9a364SKalle Valo TX_STATUS_FAIL(INTERNAL_CROSSED_RETRY);
29947ac9a364SKalle Valo TX_STATUS_FAIL(SHORT_LIMIT);
29957ac9a364SKalle Valo TX_STATUS_FAIL(LONG_LIMIT);
29967ac9a364SKalle Valo TX_STATUS_FAIL(FIFO_UNDERRUN);
29977ac9a364SKalle Valo TX_STATUS_FAIL(DRAIN_FLOW);
29987ac9a364SKalle Valo TX_STATUS_FAIL(RFKILL_FLUSH);
29997ac9a364SKalle Valo TX_STATUS_FAIL(LIFE_EXPIRE);
30007ac9a364SKalle Valo TX_STATUS_FAIL(DEST_PS);
30017ac9a364SKalle Valo TX_STATUS_FAIL(HOST_ABORTED);
30027ac9a364SKalle Valo TX_STATUS_FAIL(BT_RETRY);
30037ac9a364SKalle Valo TX_STATUS_FAIL(STA_INVALID);
30047ac9a364SKalle Valo TX_STATUS_FAIL(FRAG_DROPPED);
30057ac9a364SKalle Valo TX_STATUS_FAIL(TID_DISABLE);
30067ac9a364SKalle Valo TX_STATUS_FAIL(FIFO_FLUSHED);
30077ac9a364SKalle Valo TX_STATUS_FAIL(INSUFFICIENT_CF_POLL);
30087ac9a364SKalle Valo TX_STATUS_FAIL(PASSIVE_NO_RX);
30097ac9a364SKalle Valo TX_STATUS_FAIL(NO_BEACON_ON_RADAR);
30107ac9a364SKalle Valo }
30117ac9a364SKalle Valo
30127ac9a364SKalle Valo return "UNKNOWN";
30137ac9a364SKalle Valo
30147ac9a364SKalle Valo #undef TX_STATUS_FAIL
30157ac9a364SKalle Valo #undef TX_STATUS_POSTPONE
30167ac9a364SKalle Valo }
30177ac9a364SKalle Valo #endif /* CONFIG_IWLEGACY_DEBUG */
30187ac9a364SKalle Valo
30197ac9a364SKalle Valo static struct il_link_quality_cmd *
il4965_sta_alloc_lq(struct il_priv * il,u8 sta_id)30207ac9a364SKalle Valo il4965_sta_alloc_lq(struct il_priv *il, u8 sta_id)
30217ac9a364SKalle Valo {
30227ac9a364SKalle Valo int i, r;
30237ac9a364SKalle Valo struct il_link_quality_cmd *link_cmd;
30247ac9a364SKalle Valo u32 rate_flags = 0;
30257ac9a364SKalle Valo __le32 rate_n_flags;
30267ac9a364SKalle Valo
30277ac9a364SKalle Valo link_cmd = kzalloc(sizeof(struct il_link_quality_cmd), GFP_KERNEL);
30287ac9a364SKalle Valo if (!link_cmd) {
30297ac9a364SKalle Valo IL_ERR("Unable to allocate memory for LQ cmd.\n");
30307ac9a364SKalle Valo return NULL;
30317ac9a364SKalle Valo }
30327ac9a364SKalle Valo /* Set up the rate scaling to start at selected rate, fall back
30337ac9a364SKalle Valo * all the way down to 1M in IEEE order, and then spin on 1M */
303457fbcce3SJohannes Berg if (il->band == NL80211_BAND_5GHZ)
30357ac9a364SKalle Valo r = RATE_6M_IDX;
30367ac9a364SKalle Valo else
30377ac9a364SKalle Valo r = RATE_1M_IDX;
30387ac9a364SKalle Valo
30397ac9a364SKalle Valo if (r >= IL_FIRST_CCK_RATE && r <= IL_LAST_CCK_RATE)
30407ac9a364SKalle Valo rate_flags |= RATE_MCS_CCK_MSK;
30417ac9a364SKalle Valo
30427ac9a364SKalle Valo rate_flags |=
30437ac9a364SKalle Valo il4965_first_antenna(il->hw_params.
30447ac9a364SKalle Valo valid_tx_ant) << RATE_MCS_ANT_POS;
30457ac9a364SKalle Valo rate_n_flags = cpu_to_le32(il_rates[r].plcp | rate_flags);
30467ac9a364SKalle Valo for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++)
30477ac9a364SKalle Valo link_cmd->rs_table[i].rate_n_flags = rate_n_flags;
30487ac9a364SKalle Valo
30497ac9a364SKalle Valo link_cmd->general_params.single_stream_ant_msk =
30507ac9a364SKalle Valo il4965_first_antenna(il->hw_params.valid_tx_ant);
30517ac9a364SKalle Valo
30527ac9a364SKalle Valo link_cmd->general_params.dual_stream_ant_msk =
30537ac9a364SKalle Valo il->hw_params.valid_tx_ant & ~il4965_first_antenna(il->hw_params.
30547ac9a364SKalle Valo valid_tx_ant);
30557ac9a364SKalle Valo if (!link_cmd->general_params.dual_stream_ant_msk) {
30567ac9a364SKalle Valo link_cmd->general_params.dual_stream_ant_msk = ANT_AB;
30577ac9a364SKalle Valo } else if (il4965_num_of_ant(il->hw_params.valid_tx_ant) == 2) {
30587ac9a364SKalle Valo link_cmd->general_params.dual_stream_ant_msk =
30597ac9a364SKalle Valo il->hw_params.valid_tx_ant;
30607ac9a364SKalle Valo }
30617ac9a364SKalle Valo
30627ac9a364SKalle Valo link_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF;
30637ac9a364SKalle Valo link_cmd->agg_params.agg_time_limit =
30647ac9a364SKalle Valo cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF);
30657ac9a364SKalle Valo
30667ac9a364SKalle Valo link_cmd->sta_id = sta_id;
30677ac9a364SKalle Valo
30687ac9a364SKalle Valo return link_cmd;
30697ac9a364SKalle Valo }
30707ac9a364SKalle Valo
30717ac9a364SKalle Valo /*
30727ac9a364SKalle Valo * il4965_add_bssid_station - Add the special IBSS BSSID station
30737ac9a364SKalle Valo *
30747ac9a364SKalle Valo * Function sleeps.
30757ac9a364SKalle Valo */
30767ac9a364SKalle Valo int
il4965_add_bssid_station(struct il_priv * il,const u8 * addr,u8 * sta_id_r)30777ac9a364SKalle Valo il4965_add_bssid_station(struct il_priv *il, const u8 *addr, u8 *sta_id_r)
30787ac9a364SKalle Valo {
30797ac9a364SKalle Valo int ret;
30807ac9a364SKalle Valo u8 sta_id;
30817ac9a364SKalle Valo struct il_link_quality_cmd *link_cmd;
30827ac9a364SKalle Valo unsigned long flags;
30837ac9a364SKalle Valo
30847ac9a364SKalle Valo if (sta_id_r)
30857ac9a364SKalle Valo *sta_id_r = IL_INVALID_STATION;
30867ac9a364SKalle Valo
30877ac9a364SKalle Valo ret = il_add_station_common(il, addr, 0, NULL, &sta_id);
30887ac9a364SKalle Valo if (ret) {
30897ac9a364SKalle Valo IL_ERR("Unable to add station %pM\n", addr);
30907ac9a364SKalle Valo return ret;
30917ac9a364SKalle Valo }
30927ac9a364SKalle Valo
30937ac9a364SKalle Valo if (sta_id_r)
30947ac9a364SKalle Valo *sta_id_r = sta_id;
30957ac9a364SKalle Valo
30967ac9a364SKalle Valo spin_lock_irqsave(&il->sta_lock, flags);
30977ac9a364SKalle Valo il->stations[sta_id].used |= IL_STA_LOCAL;
30987ac9a364SKalle Valo spin_unlock_irqrestore(&il->sta_lock, flags);
30997ac9a364SKalle Valo
31007ac9a364SKalle Valo /* Set up default rate scaling table in device's station table */
31017ac9a364SKalle Valo link_cmd = il4965_sta_alloc_lq(il, sta_id);
31027ac9a364SKalle Valo if (!link_cmd) {
31037ac9a364SKalle Valo IL_ERR("Unable to initialize rate scaling for station %pM.\n",
31047ac9a364SKalle Valo addr);
31057ac9a364SKalle Valo return -ENOMEM;
31067ac9a364SKalle Valo }
31077ac9a364SKalle Valo
31087ac9a364SKalle Valo ret = il_send_lq_cmd(il, link_cmd, CMD_SYNC, true);
31097ac9a364SKalle Valo if (ret)
31107ac9a364SKalle Valo IL_ERR("Link quality command failed (%d)\n", ret);
31117ac9a364SKalle Valo
31127ac9a364SKalle Valo spin_lock_irqsave(&il->sta_lock, flags);
31137ac9a364SKalle Valo il->stations[sta_id].lq = link_cmd;
31147ac9a364SKalle Valo spin_unlock_irqrestore(&il->sta_lock, flags);
31157ac9a364SKalle Valo
31167ac9a364SKalle Valo return 0;
31177ac9a364SKalle Valo }
31187ac9a364SKalle Valo
31197ac9a364SKalle Valo static int
il4965_static_wepkey_cmd(struct il_priv * il,bool send_if_empty)31207ac9a364SKalle Valo il4965_static_wepkey_cmd(struct il_priv *il, bool send_if_empty)
31217ac9a364SKalle Valo {
31227ac9a364SKalle Valo int i;
31237ac9a364SKalle Valo u8 buff[sizeof(struct il_wep_cmd) +
31247ac9a364SKalle Valo sizeof(struct il_wep_key) * WEP_KEYS_MAX];
31257ac9a364SKalle Valo struct il_wep_cmd *wep_cmd = (struct il_wep_cmd *)buff;
31267ac9a364SKalle Valo size_t cmd_size = sizeof(struct il_wep_cmd);
31277ac9a364SKalle Valo struct il_host_cmd cmd = {
31287ac9a364SKalle Valo .id = C_WEPKEY,
31297ac9a364SKalle Valo .data = wep_cmd,
31307ac9a364SKalle Valo .flags = CMD_SYNC,
31317ac9a364SKalle Valo };
31327ac9a364SKalle Valo bool not_empty = false;
31337ac9a364SKalle Valo
31347ac9a364SKalle Valo might_sleep();
31357ac9a364SKalle Valo
31367ac9a364SKalle Valo memset(wep_cmd, 0,
31377ac9a364SKalle Valo cmd_size + (sizeof(struct il_wep_key) * WEP_KEYS_MAX));
31387ac9a364SKalle Valo
31397ac9a364SKalle Valo for (i = 0; i < WEP_KEYS_MAX; i++) {
31407ac9a364SKalle Valo u8 key_size = il->_4965.wep_keys[i].key_size;
31417ac9a364SKalle Valo
31427ac9a364SKalle Valo wep_cmd->key[i].key_idx = i;
31437ac9a364SKalle Valo if (key_size) {
31447ac9a364SKalle Valo wep_cmd->key[i].key_offset = i;
31457ac9a364SKalle Valo not_empty = true;
31467ac9a364SKalle Valo } else
31477ac9a364SKalle Valo wep_cmd->key[i].key_offset = WEP_INVALID_OFFSET;
31487ac9a364SKalle Valo
31497ac9a364SKalle Valo wep_cmd->key[i].key_size = key_size;
31507ac9a364SKalle Valo memcpy(&wep_cmd->key[i].key[3], il->_4965.wep_keys[i].key, key_size);
31517ac9a364SKalle Valo }
31527ac9a364SKalle Valo
31537ac9a364SKalle Valo wep_cmd->global_key_type = WEP_KEY_WEP_TYPE;
31547ac9a364SKalle Valo wep_cmd->num_keys = WEP_KEYS_MAX;
31557ac9a364SKalle Valo
31567ac9a364SKalle Valo cmd_size += sizeof(struct il_wep_key) * WEP_KEYS_MAX;
31577ac9a364SKalle Valo cmd.len = cmd_size;
31587ac9a364SKalle Valo
31597ac9a364SKalle Valo if (not_empty || send_if_empty)
31607ac9a364SKalle Valo return il_send_cmd(il, &cmd);
31617ac9a364SKalle Valo else
31627ac9a364SKalle Valo return 0;
31637ac9a364SKalle Valo }
31647ac9a364SKalle Valo
31657ac9a364SKalle Valo int
il4965_restore_default_wep_keys(struct il_priv * il)31667ac9a364SKalle Valo il4965_restore_default_wep_keys(struct il_priv *il)
31677ac9a364SKalle Valo {
31687ac9a364SKalle Valo lockdep_assert_held(&il->mutex);
31697ac9a364SKalle Valo
31707ac9a364SKalle Valo return il4965_static_wepkey_cmd(il, false);
31717ac9a364SKalle Valo }
31727ac9a364SKalle Valo
31737ac9a364SKalle Valo int
il4965_remove_default_wep_key(struct il_priv * il,struct ieee80211_key_conf * keyconf)31747ac9a364SKalle Valo il4965_remove_default_wep_key(struct il_priv *il,
31757ac9a364SKalle Valo struct ieee80211_key_conf *keyconf)
31767ac9a364SKalle Valo {
31777ac9a364SKalle Valo int ret;
31787ac9a364SKalle Valo int idx = keyconf->keyidx;
31797ac9a364SKalle Valo
31807ac9a364SKalle Valo lockdep_assert_held(&il->mutex);
31817ac9a364SKalle Valo
31827ac9a364SKalle Valo D_WEP("Removing default WEP key: idx=%d\n", idx);
31837ac9a364SKalle Valo
31847ac9a364SKalle Valo memset(&il->_4965.wep_keys[idx], 0, sizeof(struct il_wep_key));
31857ac9a364SKalle Valo if (il_is_rfkill(il)) {
31867ac9a364SKalle Valo D_WEP("Not sending C_WEPKEY command due to RFKILL.\n");
31877ac9a364SKalle Valo /* but keys in device are clear anyway so return success */
31887ac9a364SKalle Valo return 0;
31897ac9a364SKalle Valo }
31907ac9a364SKalle Valo ret = il4965_static_wepkey_cmd(il, 1);
31917ac9a364SKalle Valo D_WEP("Remove default WEP key: idx=%d ret=%d\n", idx, ret);
31927ac9a364SKalle Valo
31937ac9a364SKalle Valo return ret;
31947ac9a364SKalle Valo }
31957ac9a364SKalle Valo
31967ac9a364SKalle Valo int
il4965_set_default_wep_key(struct il_priv * il,struct ieee80211_key_conf * keyconf)31977ac9a364SKalle Valo il4965_set_default_wep_key(struct il_priv *il,
31987ac9a364SKalle Valo struct ieee80211_key_conf *keyconf)
31997ac9a364SKalle Valo {
32007ac9a364SKalle Valo int ret;
32017ac9a364SKalle Valo int len = keyconf->keylen;
32027ac9a364SKalle Valo int idx = keyconf->keyidx;
32037ac9a364SKalle Valo
32047ac9a364SKalle Valo lockdep_assert_held(&il->mutex);
32057ac9a364SKalle Valo
32067ac9a364SKalle Valo if (len != WEP_KEY_LEN_128 && len != WEP_KEY_LEN_64) {
32077ac9a364SKalle Valo D_WEP("Bad WEP key length %d\n", keyconf->keylen);
32087ac9a364SKalle Valo return -EINVAL;
32097ac9a364SKalle Valo }
32107ac9a364SKalle Valo
32117ac9a364SKalle Valo keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
32127ac9a364SKalle Valo keyconf->hw_key_idx = HW_KEY_DEFAULT;
32137ac9a364SKalle Valo il->stations[IL_AP_ID].keyinfo.cipher = keyconf->cipher;
32147ac9a364SKalle Valo
32157ac9a364SKalle Valo il->_4965.wep_keys[idx].key_size = len;
32167ac9a364SKalle Valo memcpy(&il->_4965.wep_keys[idx].key, &keyconf->key, len);
32177ac9a364SKalle Valo
32187ac9a364SKalle Valo ret = il4965_static_wepkey_cmd(il, false);
32197ac9a364SKalle Valo
32207ac9a364SKalle Valo D_WEP("Set default WEP key: len=%d idx=%d ret=%d\n", len, idx, ret);
32217ac9a364SKalle Valo return ret;
32227ac9a364SKalle Valo }
32237ac9a364SKalle Valo
32247ac9a364SKalle Valo static int
il4965_set_wep_dynamic_key_info(struct il_priv * il,struct ieee80211_key_conf * keyconf,u8 sta_id)32257ac9a364SKalle Valo il4965_set_wep_dynamic_key_info(struct il_priv *il,
32267ac9a364SKalle Valo struct ieee80211_key_conf *keyconf, u8 sta_id)
32277ac9a364SKalle Valo {
32287ac9a364SKalle Valo unsigned long flags;
32297ac9a364SKalle Valo __le16 key_flags = 0;
32307ac9a364SKalle Valo struct il_addsta_cmd sta_cmd;
32317ac9a364SKalle Valo
32327ac9a364SKalle Valo lockdep_assert_held(&il->mutex);
32337ac9a364SKalle Valo
32347ac9a364SKalle Valo keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
32357ac9a364SKalle Valo
32367ac9a364SKalle Valo key_flags |= (STA_KEY_FLG_WEP | STA_KEY_FLG_MAP_KEY_MSK);
32377ac9a364SKalle Valo key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
32387ac9a364SKalle Valo key_flags &= ~STA_KEY_FLG_INVALID;
32397ac9a364SKalle Valo
32407ac9a364SKalle Valo if (keyconf->keylen == WEP_KEY_LEN_128)
32417ac9a364SKalle Valo key_flags |= STA_KEY_FLG_KEY_SIZE_MSK;
32427ac9a364SKalle Valo
32437ac9a364SKalle Valo if (sta_id == il->hw_params.bcast_id)
32447ac9a364SKalle Valo key_flags |= STA_KEY_MULTICAST_MSK;
32457ac9a364SKalle Valo
32467ac9a364SKalle Valo spin_lock_irqsave(&il->sta_lock, flags);
32477ac9a364SKalle Valo
32487ac9a364SKalle Valo il->stations[sta_id].keyinfo.cipher = keyconf->cipher;
32497ac9a364SKalle Valo il->stations[sta_id].keyinfo.keylen = keyconf->keylen;
32507ac9a364SKalle Valo il->stations[sta_id].keyinfo.keyidx = keyconf->keyidx;
32517ac9a364SKalle Valo
32527ac9a364SKalle Valo memcpy(il->stations[sta_id].keyinfo.key, keyconf->key, keyconf->keylen);
32537ac9a364SKalle Valo
32547ac9a364SKalle Valo memcpy(&il->stations[sta_id].sta.key.key[3], keyconf->key,
32557ac9a364SKalle Valo keyconf->keylen);
32567ac9a364SKalle Valo
32577ac9a364SKalle Valo if ((il->stations[sta_id].sta.key.
32587ac9a364SKalle Valo key_flags & STA_KEY_FLG_ENCRYPT_MSK) == STA_KEY_FLG_NO_ENC)
32597ac9a364SKalle Valo il->stations[sta_id].sta.key.key_offset =
32607ac9a364SKalle Valo il_get_free_ucode_key_idx(il);
32617ac9a364SKalle Valo /* else, we are overriding an existing key => no need to allocated room
32627ac9a364SKalle Valo * in uCode. */
32637ac9a364SKalle Valo
32647ac9a364SKalle Valo WARN(il->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
32657ac9a364SKalle Valo "no space for a new key");
32667ac9a364SKalle Valo
32677ac9a364SKalle Valo il->stations[sta_id].sta.key.key_flags = key_flags;
32687ac9a364SKalle Valo il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
32697ac9a364SKalle Valo il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
32707ac9a364SKalle Valo
32717ac9a364SKalle Valo memcpy(&sta_cmd, &il->stations[sta_id].sta,
32727ac9a364SKalle Valo sizeof(struct il_addsta_cmd));
32737ac9a364SKalle Valo spin_unlock_irqrestore(&il->sta_lock, flags);
32747ac9a364SKalle Valo
32757ac9a364SKalle Valo return il_send_add_sta(il, &sta_cmd, CMD_SYNC);
32767ac9a364SKalle Valo }
32777ac9a364SKalle Valo
32787ac9a364SKalle Valo static int
il4965_set_ccmp_dynamic_key_info(struct il_priv * il,struct ieee80211_key_conf * keyconf,u8 sta_id)32797ac9a364SKalle Valo il4965_set_ccmp_dynamic_key_info(struct il_priv *il,
32807ac9a364SKalle Valo struct ieee80211_key_conf *keyconf, u8 sta_id)
32817ac9a364SKalle Valo {
32827ac9a364SKalle Valo unsigned long flags;
32837ac9a364SKalle Valo __le16 key_flags = 0;
32847ac9a364SKalle Valo struct il_addsta_cmd sta_cmd;
32857ac9a364SKalle Valo
32867ac9a364SKalle Valo lockdep_assert_held(&il->mutex);
32877ac9a364SKalle Valo
32887ac9a364SKalle Valo key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK);
32897ac9a364SKalle Valo key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
32907ac9a364SKalle Valo key_flags &= ~STA_KEY_FLG_INVALID;
32917ac9a364SKalle Valo
32927ac9a364SKalle Valo if (sta_id == il->hw_params.bcast_id)
32937ac9a364SKalle Valo key_flags |= STA_KEY_MULTICAST_MSK;
32947ac9a364SKalle Valo
32957ac9a364SKalle Valo keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
32967ac9a364SKalle Valo
32977ac9a364SKalle Valo spin_lock_irqsave(&il->sta_lock, flags);
32987ac9a364SKalle Valo il->stations[sta_id].keyinfo.cipher = keyconf->cipher;
32997ac9a364SKalle Valo il->stations[sta_id].keyinfo.keylen = keyconf->keylen;
33007ac9a364SKalle Valo
33017ac9a364SKalle Valo memcpy(il->stations[sta_id].keyinfo.key, keyconf->key, keyconf->keylen);
33027ac9a364SKalle Valo
33037ac9a364SKalle Valo memcpy(il->stations[sta_id].sta.key.key, keyconf->key, keyconf->keylen);
33047ac9a364SKalle Valo
33057ac9a364SKalle Valo if ((il->stations[sta_id].sta.key.
33067ac9a364SKalle Valo key_flags & STA_KEY_FLG_ENCRYPT_MSK) == STA_KEY_FLG_NO_ENC)
33077ac9a364SKalle Valo il->stations[sta_id].sta.key.key_offset =
33087ac9a364SKalle Valo il_get_free_ucode_key_idx(il);
33097ac9a364SKalle Valo /* else, we are overriding an existing key => no need to allocated room
33107ac9a364SKalle Valo * in uCode. */
33117ac9a364SKalle Valo
33127ac9a364SKalle Valo WARN(il->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
33137ac9a364SKalle Valo "no space for a new key");
33147ac9a364SKalle Valo
33157ac9a364SKalle Valo il->stations[sta_id].sta.key.key_flags = key_flags;
33167ac9a364SKalle Valo il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
33177ac9a364SKalle Valo il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
33187ac9a364SKalle Valo
33197ac9a364SKalle Valo memcpy(&sta_cmd, &il->stations[sta_id].sta,
33207ac9a364SKalle Valo sizeof(struct il_addsta_cmd));
33217ac9a364SKalle Valo spin_unlock_irqrestore(&il->sta_lock, flags);
33227ac9a364SKalle Valo
33237ac9a364SKalle Valo return il_send_add_sta(il, &sta_cmd, CMD_SYNC);
33247ac9a364SKalle Valo }
33257ac9a364SKalle Valo
33267ac9a364SKalle Valo static int
il4965_set_tkip_dynamic_key_info(struct il_priv * il,struct ieee80211_key_conf * keyconf,u8 sta_id)33277ac9a364SKalle Valo il4965_set_tkip_dynamic_key_info(struct il_priv *il,
33287ac9a364SKalle Valo struct ieee80211_key_conf *keyconf, u8 sta_id)
33297ac9a364SKalle Valo {
33307ac9a364SKalle Valo unsigned long flags;
33317ac9a364SKalle Valo __le16 key_flags = 0;
33327ac9a364SKalle Valo
33337ac9a364SKalle Valo key_flags |= (STA_KEY_FLG_TKIP | STA_KEY_FLG_MAP_KEY_MSK);
33347ac9a364SKalle Valo key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
33357ac9a364SKalle Valo key_flags &= ~STA_KEY_FLG_INVALID;
33367ac9a364SKalle Valo
33377ac9a364SKalle Valo if (sta_id == il->hw_params.bcast_id)
33387ac9a364SKalle Valo key_flags |= STA_KEY_MULTICAST_MSK;
33397ac9a364SKalle Valo
33407ac9a364SKalle Valo keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
33417ac9a364SKalle Valo keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
33427ac9a364SKalle Valo
33437ac9a364SKalle Valo spin_lock_irqsave(&il->sta_lock, flags);
33447ac9a364SKalle Valo
33457ac9a364SKalle Valo il->stations[sta_id].keyinfo.cipher = keyconf->cipher;
33467ac9a364SKalle Valo il->stations[sta_id].keyinfo.keylen = 16;
33477ac9a364SKalle Valo
33487ac9a364SKalle Valo if ((il->stations[sta_id].sta.key.
33497ac9a364SKalle Valo key_flags & STA_KEY_FLG_ENCRYPT_MSK) == STA_KEY_FLG_NO_ENC)
33507ac9a364SKalle Valo il->stations[sta_id].sta.key.key_offset =
33517ac9a364SKalle Valo il_get_free_ucode_key_idx(il);
33527ac9a364SKalle Valo /* else, we are overriding an existing key => no need to allocated room
33537ac9a364SKalle Valo * in uCode. */
33547ac9a364SKalle Valo
33557ac9a364SKalle Valo WARN(il->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
33567ac9a364SKalle Valo "no space for a new key");
33577ac9a364SKalle Valo
33587ac9a364SKalle Valo il->stations[sta_id].sta.key.key_flags = key_flags;
33597ac9a364SKalle Valo
33607ac9a364SKalle Valo /* This copy is acutally not needed: we get the key with each TX */
33617ac9a364SKalle Valo memcpy(il->stations[sta_id].keyinfo.key, keyconf->key, 16);
33627ac9a364SKalle Valo
33637ac9a364SKalle Valo memcpy(il->stations[sta_id].sta.key.key, keyconf->key, 16);
33647ac9a364SKalle Valo
33657ac9a364SKalle Valo spin_unlock_irqrestore(&il->sta_lock, flags);
33667ac9a364SKalle Valo
3367ea7ad5f1Szhong jiang return 0;
33687ac9a364SKalle Valo }
33697ac9a364SKalle Valo
33707ac9a364SKalle Valo void
il4965_update_tkip_key(struct il_priv * il,struct ieee80211_key_conf * keyconf,struct ieee80211_sta * sta,u32 iv32,u16 * phase1key)33717ac9a364SKalle Valo il4965_update_tkip_key(struct il_priv *il, struct ieee80211_key_conf *keyconf,
33727ac9a364SKalle Valo struct ieee80211_sta *sta, u32 iv32, u16 *phase1key)
33737ac9a364SKalle Valo {
33747ac9a364SKalle Valo u8 sta_id;
33757ac9a364SKalle Valo unsigned long flags;
33767ac9a364SKalle Valo int i;
33777ac9a364SKalle Valo
33787ac9a364SKalle Valo if (il_scan_cancel(il)) {
33797ac9a364SKalle Valo /* cancel scan failed, just live w/ bad key and rely
33807ac9a364SKalle Valo briefly on SW decryption */
33817ac9a364SKalle Valo return;
33827ac9a364SKalle Valo }
33837ac9a364SKalle Valo
33847ac9a364SKalle Valo sta_id = il_sta_id_or_broadcast(il, sta);
33857ac9a364SKalle Valo if (sta_id == IL_INVALID_STATION)
33867ac9a364SKalle Valo return;
33877ac9a364SKalle Valo
33887ac9a364SKalle Valo spin_lock_irqsave(&il->sta_lock, flags);
33897ac9a364SKalle Valo
33907ac9a364SKalle Valo il->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32;
33917ac9a364SKalle Valo
33927ac9a364SKalle Valo for (i = 0; i < 5; i++)
33937ac9a364SKalle Valo il->stations[sta_id].sta.key.tkip_rx_ttak[i] =
33947ac9a364SKalle Valo cpu_to_le16(phase1key[i]);
33957ac9a364SKalle Valo
33967ac9a364SKalle Valo il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
33977ac9a364SKalle Valo il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
33987ac9a364SKalle Valo
33997ac9a364SKalle Valo il_send_add_sta(il, &il->stations[sta_id].sta, CMD_ASYNC);
34007ac9a364SKalle Valo
34017ac9a364SKalle Valo spin_unlock_irqrestore(&il->sta_lock, flags);
34027ac9a364SKalle Valo }
34037ac9a364SKalle Valo
34047ac9a364SKalle Valo int
il4965_remove_dynamic_key(struct il_priv * il,struct ieee80211_key_conf * keyconf,u8 sta_id)34057ac9a364SKalle Valo il4965_remove_dynamic_key(struct il_priv *il,
34067ac9a364SKalle Valo struct ieee80211_key_conf *keyconf, u8 sta_id)
34077ac9a364SKalle Valo {
34087ac9a364SKalle Valo unsigned long flags;
34097ac9a364SKalle Valo u16 key_flags;
34107ac9a364SKalle Valo u8 keyidx;
34117ac9a364SKalle Valo struct il_addsta_cmd sta_cmd;
34127ac9a364SKalle Valo
34137ac9a364SKalle Valo lockdep_assert_held(&il->mutex);
34147ac9a364SKalle Valo
34157ac9a364SKalle Valo il->_4965.key_mapping_keys--;
34167ac9a364SKalle Valo
34177ac9a364SKalle Valo spin_lock_irqsave(&il->sta_lock, flags);
34187ac9a364SKalle Valo key_flags = le16_to_cpu(il->stations[sta_id].sta.key.key_flags);
34197ac9a364SKalle Valo keyidx = (key_flags >> STA_KEY_FLG_KEYID_POS) & 0x3;
34207ac9a364SKalle Valo
34217ac9a364SKalle Valo D_WEP("Remove dynamic key: idx=%d sta=%d\n", keyconf->keyidx, sta_id);
34227ac9a364SKalle Valo
34237ac9a364SKalle Valo if (keyconf->keyidx != keyidx) {
34247ac9a364SKalle Valo /* We need to remove a key with idx different that the one
34257ac9a364SKalle Valo * in the uCode. This means that the key we need to remove has
34267ac9a364SKalle Valo * been replaced by another one with different idx.
34277ac9a364SKalle Valo * Don't do anything and return ok
34287ac9a364SKalle Valo */
34297ac9a364SKalle Valo spin_unlock_irqrestore(&il->sta_lock, flags);
34307ac9a364SKalle Valo return 0;
34317ac9a364SKalle Valo }
34327ac9a364SKalle Valo
34337ac9a364SKalle Valo if (il->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_INVALID) {
34347ac9a364SKalle Valo IL_WARN("Removing wrong key %d 0x%x\n", keyconf->keyidx,
34357ac9a364SKalle Valo key_flags);
34367ac9a364SKalle Valo spin_unlock_irqrestore(&il->sta_lock, flags);
34377ac9a364SKalle Valo return 0;
34387ac9a364SKalle Valo }
34397ac9a364SKalle Valo
34407ac9a364SKalle Valo if (!test_and_clear_bit
34417ac9a364SKalle Valo (il->stations[sta_id].sta.key.key_offset, &il->ucode_key_table))
34427ac9a364SKalle Valo IL_ERR("idx %d not used in uCode key table.\n",
34437ac9a364SKalle Valo il->stations[sta_id].sta.key.key_offset);
34447ac9a364SKalle Valo memset(&il->stations[sta_id].keyinfo, 0, sizeof(struct il_hw_key));
34457ac9a364SKalle Valo memset(&il->stations[sta_id].sta.key, 0, sizeof(struct il4965_keyinfo));
34467ac9a364SKalle Valo il->stations[sta_id].sta.key.key_flags =
34477ac9a364SKalle Valo STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID;
34487ac9a364SKalle Valo il->stations[sta_id].sta.key.key_offset = keyconf->hw_key_idx;
34497ac9a364SKalle Valo il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
34507ac9a364SKalle Valo il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
34517ac9a364SKalle Valo
34527ac9a364SKalle Valo if (il_is_rfkill(il)) {
34537ac9a364SKalle Valo D_WEP
34547ac9a364SKalle Valo ("Not sending C_ADD_STA command because RFKILL enabled.\n");
34557ac9a364SKalle Valo spin_unlock_irqrestore(&il->sta_lock, flags);
34567ac9a364SKalle Valo return 0;
34577ac9a364SKalle Valo }
34587ac9a364SKalle Valo memcpy(&sta_cmd, &il->stations[sta_id].sta,
34597ac9a364SKalle Valo sizeof(struct il_addsta_cmd));
34607ac9a364SKalle Valo spin_unlock_irqrestore(&il->sta_lock, flags);
34617ac9a364SKalle Valo
34627ac9a364SKalle Valo return il_send_add_sta(il, &sta_cmd, CMD_SYNC);
34637ac9a364SKalle Valo }
34647ac9a364SKalle Valo
34657ac9a364SKalle Valo int
il4965_set_dynamic_key(struct il_priv * il,struct ieee80211_key_conf * keyconf,u8 sta_id)34667ac9a364SKalle Valo il4965_set_dynamic_key(struct il_priv *il, struct ieee80211_key_conf *keyconf,
34677ac9a364SKalle Valo u8 sta_id)
34687ac9a364SKalle Valo {
34697ac9a364SKalle Valo int ret;
34707ac9a364SKalle Valo
34717ac9a364SKalle Valo lockdep_assert_held(&il->mutex);
34727ac9a364SKalle Valo
34737ac9a364SKalle Valo il->_4965.key_mapping_keys++;
34747ac9a364SKalle Valo keyconf->hw_key_idx = HW_KEY_DYNAMIC;
34757ac9a364SKalle Valo
34767ac9a364SKalle Valo switch (keyconf->cipher) {
34777ac9a364SKalle Valo case WLAN_CIPHER_SUITE_CCMP:
34787ac9a364SKalle Valo ret =
34797ac9a364SKalle Valo il4965_set_ccmp_dynamic_key_info(il, keyconf, sta_id);
34807ac9a364SKalle Valo break;
34817ac9a364SKalle Valo case WLAN_CIPHER_SUITE_TKIP:
34827ac9a364SKalle Valo ret =
34837ac9a364SKalle Valo il4965_set_tkip_dynamic_key_info(il, keyconf, sta_id);
34847ac9a364SKalle Valo break;
34857ac9a364SKalle Valo case WLAN_CIPHER_SUITE_WEP40:
34867ac9a364SKalle Valo case WLAN_CIPHER_SUITE_WEP104:
34877ac9a364SKalle Valo ret = il4965_set_wep_dynamic_key_info(il, keyconf, sta_id);
34887ac9a364SKalle Valo break;
34897ac9a364SKalle Valo default:
34907ac9a364SKalle Valo IL_ERR("Unknown alg: %s cipher = %x\n", __func__,
34917ac9a364SKalle Valo keyconf->cipher);
34927ac9a364SKalle Valo ret = -EINVAL;
34937ac9a364SKalle Valo }
34947ac9a364SKalle Valo
34957ac9a364SKalle Valo D_WEP("Set dynamic key: cipher=%x len=%d idx=%d sta=%d ret=%d\n",
34967ac9a364SKalle Valo keyconf->cipher, keyconf->keylen, keyconf->keyidx, sta_id, ret);
34977ac9a364SKalle Valo
34987ac9a364SKalle Valo return ret;
34997ac9a364SKalle Valo }
35007ac9a364SKalle Valo
350135b7fbfcSLee Jones /*
35027ac9a364SKalle Valo * il4965_alloc_bcast_station - add broadcast station into driver's station table.
35037ac9a364SKalle Valo *
35047ac9a364SKalle Valo * This adds the broadcast station into the driver's station table
35057ac9a364SKalle Valo * and marks it driver active, so that it will be restored to the
35067ac9a364SKalle Valo * device at the next best time.
35077ac9a364SKalle Valo */
35087ac9a364SKalle Valo int
il4965_alloc_bcast_station(struct il_priv * il)35097ac9a364SKalle Valo il4965_alloc_bcast_station(struct il_priv *il)
35107ac9a364SKalle Valo {
35117ac9a364SKalle Valo struct il_link_quality_cmd *link_cmd;
35127ac9a364SKalle Valo unsigned long flags;
35137ac9a364SKalle Valo u8 sta_id;
35147ac9a364SKalle Valo
35157ac9a364SKalle Valo spin_lock_irqsave(&il->sta_lock, flags);
35167ac9a364SKalle Valo sta_id = il_prep_station(il, il_bcast_addr, false, NULL);
35177ac9a364SKalle Valo if (sta_id == IL_INVALID_STATION) {
35187ac9a364SKalle Valo IL_ERR("Unable to prepare broadcast station\n");
35197ac9a364SKalle Valo spin_unlock_irqrestore(&il->sta_lock, flags);
35207ac9a364SKalle Valo
35217ac9a364SKalle Valo return -EINVAL;
35227ac9a364SKalle Valo }
35237ac9a364SKalle Valo
35247ac9a364SKalle Valo il->stations[sta_id].used |= IL_STA_DRIVER_ACTIVE;
35257ac9a364SKalle Valo il->stations[sta_id].used |= IL_STA_BCAST;
35267ac9a364SKalle Valo spin_unlock_irqrestore(&il->sta_lock, flags);
35277ac9a364SKalle Valo
35287ac9a364SKalle Valo link_cmd = il4965_sta_alloc_lq(il, sta_id);
35297ac9a364SKalle Valo if (!link_cmd) {
35307ac9a364SKalle Valo IL_ERR
35317ac9a364SKalle Valo ("Unable to initialize rate scaling for bcast station.\n");
35327ac9a364SKalle Valo return -ENOMEM;
35337ac9a364SKalle Valo }
35347ac9a364SKalle Valo
35357ac9a364SKalle Valo spin_lock_irqsave(&il->sta_lock, flags);
35367ac9a364SKalle Valo il->stations[sta_id].lq = link_cmd;
35377ac9a364SKalle Valo spin_unlock_irqrestore(&il->sta_lock, flags);
35387ac9a364SKalle Valo
35397ac9a364SKalle Valo return 0;
35407ac9a364SKalle Valo }
35417ac9a364SKalle Valo
354235b7fbfcSLee Jones /*
35437ac9a364SKalle Valo * il4965_update_bcast_station - update broadcast station's LQ command
35447ac9a364SKalle Valo *
35457ac9a364SKalle Valo * Only used by iwl4965. Placed here to have all bcast station management
35467ac9a364SKalle Valo * code together.
35477ac9a364SKalle Valo */
35487ac9a364SKalle Valo static int
il4965_update_bcast_station(struct il_priv * il)35497ac9a364SKalle Valo il4965_update_bcast_station(struct il_priv *il)
35507ac9a364SKalle Valo {
35517ac9a364SKalle Valo unsigned long flags;
35527ac9a364SKalle Valo struct il_link_quality_cmd *link_cmd;
35537ac9a364SKalle Valo u8 sta_id = il->hw_params.bcast_id;
35547ac9a364SKalle Valo
35557ac9a364SKalle Valo link_cmd = il4965_sta_alloc_lq(il, sta_id);
35567ac9a364SKalle Valo if (!link_cmd) {
35577ac9a364SKalle Valo IL_ERR("Unable to initialize rate scaling for bcast sta.\n");
35587ac9a364SKalle Valo return -ENOMEM;
35597ac9a364SKalle Valo }
35607ac9a364SKalle Valo
35617ac9a364SKalle Valo spin_lock_irqsave(&il->sta_lock, flags);
35627ac9a364SKalle Valo if (il->stations[sta_id].lq)
35637ac9a364SKalle Valo kfree(il->stations[sta_id].lq);
35647ac9a364SKalle Valo else
35657ac9a364SKalle Valo D_INFO("Bcast sta rate scaling has not been initialized.\n");
35667ac9a364SKalle Valo il->stations[sta_id].lq = link_cmd;
35677ac9a364SKalle Valo spin_unlock_irqrestore(&il->sta_lock, flags);
35687ac9a364SKalle Valo
35697ac9a364SKalle Valo return 0;
35707ac9a364SKalle Valo }
35717ac9a364SKalle Valo
35727ac9a364SKalle Valo int
il4965_update_bcast_stations(struct il_priv * il)35737ac9a364SKalle Valo il4965_update_bcast_stations(struct il_priv *il)
35747ac9a364SKalle Valo {
35757ac9a364SKalle Valo return il4965_update_bcast_station(il);
35767ac9a364SKalle Valo }
35777ac9a364SKalle Valo
357835b7fbfcSLee Jones /*
35797ac9a364SKalle Valo * il4965_sta_tx_modify_enable_tid - Enable Tx for this TID in station table
35807ac9a364SKalle Valo */
35817ac9a364SKalle Valo int
il4965_sta_tx_modify_enable_tid(struct il_priv * il,int sta_id,int tid)35827ac9a364SKalle Valo il4965_sta_tx_modify_enable_tid(struct il_priv *il, int sta_id, int tid)
35837ac9a364SKalle Valo {
35847ac9a364SKalle Valo unsigned long flags;
35857ac9a364SKalle Valo struct il_addsta_cmd sta_cmd;
35867ac9a364SKalle Valo
35877ac9a364SKalle Valo lockdep_assert_held(&il->mutex);
35887ac9a364SKalle Valo
35897ac9a364SKalle Valo /* Remove "disable" flag, to enable Tx for this TID */
35907ac9a364SKalle Valo spin_lock_irqsave(&il->sta_lock, flags);
35917ac9a364SKalle Valo il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX;
35927ac9a364SKalle Valo il->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid));
35937ac9a364SKalle Valo il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
35947ac9a364SKalle Valo memcpy(&sta_cmd, &il->stations[sta_id].sta,
35957ac9a364SKalle Valo sizeof(struct il_addsta_cmd));
35967ac9a364SKalle Valo spin_unlock_irqrestore(&il->sta_lock, flags);
35977ac9a364SKalle Valo
35987ac9a364SKalle Valo return il_send_add_sta(il, &sta_cmd, CMD_SYNC);
35997ac9a364SKalle Valo }
36007ac9a364SKalle Valo
36017ac9a364SKalle Valo int
il4965_sta_rx_agg_start(struct il_priv * il,struct ieee80211_sta * sta,int tid,u16 ssn)36027ac9a364SKalle Valo il4965_sta_rx_agg_start(struct il_priv *il, struct ieee80211_sta *sta, int tid,
36037ac9a364SKalle Valo u16 ssn)
36047ac9a364SKalle Valo {
36057ac9a364SKalle Valo unsigned long flags;
36067ac9a364SKalle Valo int sta_id;
36077ac9a364SKalle Valo struct il_addsta_cmd sta_cmd;
36087ac9a364SKalle Valo
36097ac9a364SKalle Valo lockdep_assert_held(&il->mutex);
36107ac9a364SKalle Valo
36117ac9a364SKalle Valo sta_id = il_sta_id(sta);
36127ac9a364SKalle Valo if (sta_id == IL_INVALID_STATION)
36137ac9a364SKalle Valo return -ENXIO;
36147ac9a364SKalle Valo
36157ac9a364SKalle Valo spin_lock_irqsave(&il->sta_lock, flags);
36167ac9a364SKalle Valo il->stations[sta_id].sta.station_flags_msk = 0;
36177ac9a364SKalle Valo il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_ADDBA_TID_MSK;
36187ac9a364SKalle Valo il->stations[sta_id].sta.add_immediate_ba_tid = (u8) tid;
36197ac9a364SKalle Valo il->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn);
36207ac9a364SKalle Valo il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
36217ac9a364SKalle Valo memcpy(&sta_cmd, &il->stations[sta_id].sta,
36227ac9a364SKalle Valo sizeof(struct il_addsta_cmd));
36237ac9a364SKalle Valo spin_unlock_irqrestore(&il->sta_lock, flags);
36247ac9a364SKalle Valo
36257ac9a364SKalle Valo return il_send_add_sta(il, &sta_cmd, CMD_SYNC);
36267ac9a364SKalle Valo }
36277ac9a364SKalle Valo
36287ac9a364SKalle Valo int
il4965_sta_rx_agg_stop(struct il_priv * il,struct ieee80211_sta * sta,int tid)36297ac9a364SKalle Valo il4965_sta_rx_agg_stop(struct il_priv *il, struct ieee80211_sta *sta, int tid)
36307ac9a364SKalle Valo {
36317ac9a364SKalle Valo unsigned long flags;
36327ac9a364SKalle Valo int sta_id;
36337ac9a364SKalle Valo struct il_addsta_cmd sta_cmd;
36347ac9a364SKalle Valo
36357ac9a364SKalle Valo lockdep_assert_held(&il->mutex);
36367ac9a364SKalle Valo
36377ac9a364SKalle Valo sta_id = il_sta_id(sta);
36387ac9a364SKalle Valo if (sta_id == IL_INVALID_STATION) {
36397ac9a364SKalle Valo IL_ERR("Invalid station for AGG tid %d\n", tid);
36407ac9a364SKalle Valo return -ENXIO;
36417ac9a364SKalle Valo }
36427ac9a364SKalle Valo
36437ac9a364SKalle Valo spin_lock_irqsave(&il->sta_lock, flags);
36447ac9a364SKalle Valo il->stations[sta_id].sta.station_flags_msk = 0;
36457ac9a364SKalle Valo il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK;
36467ac9a364SKalle Valo il->stations[sta_id].sta.remove_immediate_ba_tid = (u8) tid;
36477ac9a364SKalle Valo il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
36487ac9a364SKalle Valo memcpy(&sta_cmd, &il->stations[sta_id].sta,
36497ac9a364SKalle Valo sizeof(struct il_addsta_cmd));
36507ac9a364SKalle Valo spin_unlock_irqrestore(&il->sta_lock, flags);
36517ac9a364SKalle Valo
36527ac9a364SKalle Valo return il_send_add_sta(il, &sta_cmd, CMD_SYNC);
36537ac9a364SKalle Valo }
36547ac9a364SKalle Valo
36557ac9a364SKalle Valo void
il4965_sta_modify_sleep_tx_count(struct il_priv * il,int sta_id,int cnt)36567ac9a364SKalle Valo il4965_sta_modify_sleep_tx_count(struct il_priv *il, int sta_id, int cnt)
36577ac9a364SKalle Valo {
36587ac9a364SKalle Valo unsigned long flags;
36597ac9a364SKalle Valo
36607ac9a364SKalle Valo spin_lock_irqsave(&il->sta_lock, flags);
36617ac9a364SKalle Valo il->stations[sta_id].sta.station_flags |= STA_FLG_PWR_SAVE_MSK;
36627ac9a364SKalle Valo il->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK;
36637ac9a364SKalle Valo il->stations[sta_id].sta.sta.modify_mask =
36647ac9a364SKalle Valo STA_MODIFY_SLEEP_TX_COUNT_MSK;
36657ac9a364SKalle Valo il->stations[sta_id].sta.sleep_tx_count = cpu_to_le16(cnt);
36667ac9a364SKalle Valo il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
36677ac9a364SKalle Valo il_send_add_sta(il, &il->stations[sta_id].sta, CMD_ASYNC);
36687ac9a364SKalle Valo spin_unlock_irqrestore(&il->sta_lock, flags);
36697ac9a364SKalle Valo
36707ac9a364SKalle Valo }
36717ac9a364SKalle Valo
36727ac9a364SKalle Valo void
il4965_update_chain_flags(struct il_priv * il)36737ac9a364SKalle Valo il4965_update_chain_flags(struct il_priv *il)
36747ac9a364SKalle Valo {
36757ac9a364SKalle Valo if (il->ops->set_rxon_chain) {
36767ac9a364SKalle Valo il->ops->set_rxon_chain(il);
36777ac9a364SKalle Valo if (il->active.rx_chain != il->staging.rx_chain)
36787ac9a364SKalle Valo il_commit_rxon(il);
36797ac9a364SKalle Valo }
36807ac9a364SKalle Valo }
36817ac9a364SKalle Valo
36827ac9a364SKalle Valo static void
il4965_clear_free_frames(struct il_priv * il)36837ac9a364SKalle Valo il4965_clear_free_frames(struct il_priv *il)
36847ac9a364SKalle Valo {
36857ac9a364SKalle Valo struct list_head *element;
36867ac9a364SKalle Valo
36877ac9a364SKalle Valo D_INFO("%d frames on pre-allocated heap on clear.\n", il->frames_count);
36887ac9a364SKalle Valo
36897ac9a364SKalle Valo while (!list_empty(&il->free_frames)) {
36907ac9a364SKalle Valo element = il->free_frames.next;
36917ac9a364SKalle Valo list_del(element);
36927ac9a364SKalle Valo kfree(list_entry(element, struct il_frame, list));
36937ac9a364SKalle Valo il->frames_count--;
36947ac9a364SKalle Valo }
36957ac9a364SKalle Valo
36967ac9a364SKalle Valo if (il->frames_count) {
36977ac9a364SKalle Valo IL_WARN("%d frames still in use. Did we lose one?\n",
36987ac9a364SKalle Valo il->frames_count);
36997ac9a364SKalle Valo il->frames_count = 0;
37007ac9a364SKalle Valo }
37017ac9a364SKalle Valo }
37027ac9a364SKalle Valo
37037ac9a364SKalle Valo static struct il_frame *
il4965_get_free_frame(struct il_priv * il)37047ac9a364SKalle Valo il4965_get_free_frame(struct il_priv *il)
37057ac9a364SKalle Valo {
37067ac9a364SKalle Valo struct il_frame *frame;
37077ac9a364SKalle Valo struct list_head *element;
37087ac9a364SKalle Valo if (list_empty(&il->free_frames)) {
37097ac9a364SKalle Valo frame = kzalloc(sizeof(*frame), GFP_KERNEL);
37107ac9a364SKalle Valo if (!frame) {
37117ac9a364SKalle Valo IL_ERR("Could not allocate frame!\n");
37127ac9a364SKalle Valo return NULL;
37137ac9a364SKalle Valo }
37147ac9a364SKalle Valo
37157ac9a364SKalle Valo il->frames_count++;
37167ac9a364SKalle Valo return frame;
37177ac9a364SKalle Valo }
37187ac9a364SKalle Valo
37197ac9a364SKalle Valo element = il->free_frames.next;
37207ac9a364SKalle Valo list_del(element);
37217ac9a364SKalle Valo return list_entry(element, struct il_frame, list);
37227ac9a364SKalle Valo }
37237ac9a364SKalle Valo
37247ac9a364SKalle Valo static void
il4965_free_frame(struct il_priv * il,struct il_frame * frame)37257ac9a364SKalle Valo il4965_free_frame(struct il_priv *il, struct il_frame *frame)
37267ac9a364SKalle Valo {
37277ac9a364SKalle Valo memset(frame, 0, sizeof(*frame));
37287ac9a364SKalle Valo list_add(&frame->list, &il->free_frames);
37297ac9a364SKalle Valo }
37307ac9a364SKalle Valo
37317ac9a364SKalle Valo static u32
il4965_fill_beacon_frame(struct il_priv * il,struct ieee80211_hdr * hdr,int left)37327ac9a364SKalle Valo il4965_fill_beacon_frame(struct il_priv *il, struct ieee80211_hdr *hdr,
37337ac9a364SKalle Valo int left)
37347ac9a364SKalle Valo {
37357ac9a364SKalle Valo lockdep_assert_held(&il->mutex);
37367ac9a364SKalle Valo
37377ac9a364SKalle Valo if (!il->beacon_skb)
37387ac9a364SKalle Valo return 0;
37397ac9a364SKalle Valo
37407ac9a364SKalle Valo if (il->beacon_skb->len > left)
37417ac9a364SKalle Valo return 0;
37427ac9a364SKalle Valo
37437ac9a364SKalle Valo memcpy(hdr, il->beacon_skb->data, il->beacon_skb->len);
37447ac9a364SKalle Valo
37457ac9a364SKalle Valo return il->beacon_skb->len;
37467ac9a364SKalle Valo }
37477ac9a364SKalle Valo
37487ac9a364SKalle Valo /* Parse the beacon frame to find the TIM element and set tim_idx & tim_size */
37497ac9a364SKalle Valo static void
il4965_set_beacon_tim(struct il_priv * il,struct il_tx_beacon_cmd * tx_beacon_cmd,u8 * beacon,u32 frame_size)37507ac9a364SKalle Valo il4965_set_beacon_tim(struct il_priv *il,
37517ac9a364SKalle Valo struct il_tx_beacon_cmd *tx_beacon_cmd, u8 * beacon,
37527ac9a364SKalle Valo u32 frame_size)
37537ac9a364SKalle Valo {
37547ac9a364SKalle Valo u16 tim_idx;
37557ac9a364SKalle Valo struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)beacon;
37567ac9a364SKalle Valo
37577ac9a364SKalle Valo /*
37587ac9a364SKalle Valo * The idx is relative to frame start but we start looking at the
37597ac9a364SKalle Valo * variable-length part of the beacon.
37607ac9a364SKalle Valo */
37617ac9a364SKalle Valo tim_idx = mgmt->u.beacon.variable - beacon;
37627ac9a364SKalle Valo
37637ac9a364SKalle Valo /* Parse variable-length elements of beacon to find WLAN_EID_TIM */
37647ac9a364SKalle Valo while ((tim_idx < (frame_size - 2)) &&
37657ac9a364SKalle Valo (beacon[tim_idx] != WLAN_EID_TIM))
37667ac9a364SKalle Valo tim_idx += beacon[tim_idx + 1] + 2;
37677ac9a364SKalle Valo
37687ac9a364SKalle Valo /* If TIM field was found, set variables */
37697ac9a364SKalle Valo if ((tim_idx < (frame_size - 1)) && (beacon[tim_idx] == WLAN_EID_TIM)) {
37707ac9a364SKalle Valo tx_beacon_cmd->tim_idx = cpu_to_le16(tim_idx);
37717ac9a364SKalle Valo tx_beacon_cmd->tim_size = beacon[tim_idx + 1];
37727ac9a364SKalle Valo } else
37737ac9a364SKalle Valo IL_WARN("Unable to find TIM Element in beacon\n");
37747ac9a364SKalle Valo }
37757ac9a364SKalle Valo
37767ac9a364SKalle Valo static unsigned int
il4965_hw_get_beacon_cmd(struct il_priv * il,struct il_frame * frame)37777ac9a364SKalle Valo il4965_hw_get_beacon_cmd(struct il_priv *il, struct il_frame *frame)
37787ac9a364SKalle Valo {
37797ac9a364SKalle Valo struct il_tx_beacon_cmd *tx_beacon_cmd;
37807ac9a364SKalle Valo u32 frame_size;
37817ac9a364SKalle Valo u32 rate_flags;
37827ac9a364SKalle Valo u32 rate;
37837ac9a364SKalle Valo /*
37847ac9a364SKalle Valo * We have to set up the TX command, the TX Beacon command, and the
37857ac9a364SKalle Valo * beacon contents.
37867ac9a364SKalle Valo */
37877ac9a364SKalle Valo
37887ac9a364SKalle Valo lockdep_assert_held(&il->mutex);
37897ac9a364SKalle Valo
37907ac9a364SKalle Valo if (!il->beacon_enabled) {
37917ac9a364SKalle Valo IL_ERR("Trying to build beacon without beaconing enabled\n");
37927ac9a364SKalle Valo return 0;
37937ac9a364SKalle Valo }
37947ac9a364SKalle Valo
37957ac9a364SKalle Valo /* Initialize memory */
37967ac9a364SKalle Valo tx_beacon_cmd = &frame->u.beacon;
37977ac9a364SKalle Valo memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd));
37987ac9a364SKalle Valo
37997ac9a364SKalle Valo /* Set up TX beacon contents */
38007ac9a364SKalle Valo frame_size =
38017ac9a364SKalle Valo il4965_fill_beacon_frame(il, tx_beacon_cmd->frame,
38027ac9a364SKalle Valo sizeof(frame->u) - sizeof(*tx_beacon_cmd));
38037ac9a364SKalle Valo if (WARN_ON_ONCE(frame_size > MAX_MPDU_SIZE))
38047ac9a364SKalle Valo return 0;
38057ac9a364SKalle Valo if (!frame_size)
38067ac9a364SKalle Valo return 0;
38077ac9a364SKalle Valo
38087ac9a364SKalle Valo /* Set up TX command fields */
38097ac9a364SKalle Valo tx_beacon_cmd->tx.len = cpu_to_le16((u16) frame_size);
38107ac9a364SKalle Valo tx_beacon_cmd->tx.sta_id = il->hw_params.bcast_id;
38117ac9a364SKalle Valo tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
38127ac9a364SKalle Valo tx_beacon_cmd->tx.tx_flags =
38137ac9a364SKalle Valo TX_CMD_FLG_SEQ_CTL_MSK | TX_CMD_FLG_TSF_MSK |
38147ac9a364SKalle Valo TX_CMD_FLG_STA_RATE_MSK;
38157ac9a364SKalle Valo
38167ac9a364SKalle Valo /* Set up TX beacon command fields */
38177ac9a364SKalle Valo il4965_set_beacon_tim(il, tx_beacon_cmd, (u8 *) tx_beacon_cmd->frame,
38187ac9a364SKalle Valo frame_size);
38197ac9a364SKalle Valo
38207ac9a364SKalle Valo /* Set up packet rate and flags */
38217ac9a364SKalle Valo rate = il_get_lowest_plcp(il);
38227ac9a364SKalle Valo il4965_toggle_tx_ant(il, &il->mgmt_tx_ant, il->hw_params.valid_tx_ant);
38237ac9a364SKalle Valo rate_flags = BIT(il->mgmt_tx_ant) << RATE_MCS_ANT_POS;
38247ac9a364SKalle Valo if ((rate >= IL_FIRST_CCK_RATE) && (rate <= IL_LAST_CCK_RATE))
38257ac9a364SKalle Valo rate_flags |= RATE_MCS_CCK_MSK;
38267ac9a364SKalle Valo tx_beacon_cmd->tx.rate_n_flags = cpu_to_le32(rate | rate_flags);
38277ac9a364SKalle Valo
38287ac9a364SKalle Valo return sizeof(*tx_beacon_cmd) + frame_size;
38297ac9a364SKalle Valo }
38307ac9a364SKalle Valo
38317ac9a364SKalle Valo int
il4965_send_beacon_cmd(struct il_priv * il)38327ac9a364SKalle Valo il4965_send_beacon_cmd(struct il_priv *il)
38337ac9a364SKalle Valo {
38347ac9a364SKalle Valo struct il_frame *frame;
38357ac9a364SKalle Valo unsigned int frame_size;
38367ac9a364SKalle Valo int rc;
38377ac9a364SKalle Valo
38387ac9a364SKalle Valo frame = il4965_get_free_frame(il);
38397ac9a364SKalle Valo if (!frame) {
38407ac9a364SKalle Valo IL_ERR("Could not obtain free frame buffer for beacon "
38417ac9a364SKalle Valo "command.\n");
38427ac9a364SKalle Valo return -ENOMEM;
38437ac9a364SKalle Valo }
38447ac9a364SKalle Valo
38457ac9a364SKalle Valo frame_size = il4965_hw_get_beacon_cmd(il, frame);
38467ac9a364SKalle Valo if (!frame_size) {
38477ac9a364SKalle Valo IL_ERR("Error configuring the beacon command\n");
38487ac9a364SKalle Valo il4965_free_frame(il, frame);
38497ac9a364SKalle Valo return -EINVAL;
38507ac9a364SKalle Valo }
38517ac9a364SKalle Valo
38527ac9a364SKalle Valo rc = il_send_cmd_pdu(il, C_TX_BEACON, frame_size, &frame->u.cmd[0]);
38537ac9a364SKalle Valo
38547ac9a364SKalle Valo il4965_free_frame(il, frame);
38557ac9a364SKalle Valo
38567ac9a364SKalle Valo return rc;
38577ac9a364SKalle Valo }
38587ac9a364SKalle Valo
38597ac9a364SKalle Valo static inline dma_addr_t
il4965_tfd_tb_get_addr(struct il_tfd * tfd,u8 idx)38607ac9a364SKalle Valo il4965_tfd_tb_get_addr(struct il_tfd *tfd, u8 idx)
38617ac9a364SKalle Valo {
38627ac9a364SKalle Valo struct il_tfd_tb *tb = &tfd->tbs[idx];
38637ac9a364SKalle Valo
38647ac9a364SKalle Valo dma_addr_t addr = get_unaligned_le32(&tb->lo);
38657ac9a364SKalle Valo if (sizeof(dma_addr_t) > sizeof(u32))
38667ac9a364SKalle Valo addr |=
38677ac9a364SKalle Valo ((dma_addr_t) (le16_to_cpu(tb->hi_n_len) & 0xF) << 16) <<
38687ac9a364SKalle Valo 16;
38697ac9a364SKalle Valo
38707ac9a364SKalle Valo return addr;
38717ac9a364SKalle Valo }
38727ac9a364SKalle Valo
38737ac9a364SKalle Valo static inline u16
il4965_tfd_tb_get_len(struct il_tfd * tfd,u8 idx)38747ac9a364SKalle Valo il4965_tfd_tb_get_len(struct il_tfd *tfd, u8 idx)
38757ac9a364SKalle Valo {
38767ac9a364SKalle Valo struct il_tfd_tb *tb = &tfd->tbs[idx];
38777ac9a364SKalle Valo
38787ac9a364SKalle Valo return le16_to_cpu(tb->hi_n_len) >> 4;
38797ac9a364SKalle Valo }
38807ac9a364SKalle Valo
38817ac9a364SKalle Valo static inline void
il4965_tfd_set_tb(struct il_tfd * tfd,u8 idx,dma_addr_t addr,u16 len)38827ac9a364SKalle Valo il4965_tfd_set_tb(struct il_tfd *tfd, u8 idx, dma_addr_t addr, u16 len)
38837ac9a364SKalle Valo {
38847ac9a364SKalle Valo struct il_tfd_tb *tb = &tfd->tbs[idx];
38857ac9a364SKalle Valo u16 hi_n_len = len << 4;
38867ac9a364SKalle Valo
38877ac9a364SKalle Valo put_unaligned_le32(addr, &tb->lo);
38887ac9a364SKalle Valo if (sizeof(dma_addr_t) > sizeof(u32))
38897ac9a364SKalle Valo hi_n_len |= ((addr >> 16) >> 16) & 0xF;
38907ac9a364SKalle Valo
38917ac9a364SKalle Valo tb->hi_n_len = cpu_to_le16(hi_n_len);
38927ac9a364SKalle Valo
38937ac9a364SKalle Valo tfd->num_tbs = idx + 1;
38947ac9a364SKalle Valo }
38957ac9a364SKalle Valo
38967ac9a364SKalle Valo static inline u8
il4965_tfd_get_num_tbs(struct il_tfd * tfd)38977ac9a364SKalle Valo il4965_tfd_get_num_tbs(struct il_tfd *tfd)
38987ac9a364SKalle Valo {
38997ac9a364SKalle Valo return tfd->num_tbs & 0x1f;
39007ac9a364SKalle Valo }
39017ac9a364SKalle Valo
390235b7fbfcSLee Jones /*
39037ac9a364SKalle Valo * il4965_hw_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr]
39047ac9a364SKalle Valo *
39057ac9a364SKalle Valo * Does NOT advance any TFD circular buffer read/write idxes
39067ac9a364SKalle Valo * Does NOT free the TFD itself (which is within circular buffer)
39077ac9a364SKalle Valo */
39087ac9a364SKalle Valo void
il4965_hw_txq_free_tfd(struct il_priv * il,struct il_tx_queue * txq)39097ac9a364SKalle Valo il4965_hw_txq_free_tfd(struct il_priv *il, struct il_tx_queue *txq)
39107ac9a364SKalle Valo {
39117ac9a364SKalle Valo struct il_tfd *tfd_tmp = (struct il_tfd *)txq->tfds;
39127ac9a364SKalle Valo struct il_tfd *tfd;
39137ac9a364SKalle Valo struct pci_dev *dev = il->pci_dev;
39147ac9a364SKalle Valo int idx = txq->q.read_ptr;
39157ac9a364SKalle Valo int i;
39167ac9a364SKalle Valo int num_tbs;
39177ac9a364SKalle Valo
39187ac9a364SKalle Valo tfd = &tfd_tmp[idx];
39197ac9a364SKalle Valo
39207ac9a364SKalle Valo /* Sanity check on number of chunks */
39217ac9a364SKalle Valo num_tbs = il4965_tfd_get_num_tbs(tfd);
39227ac9a364SKalle Valo
39237ac9a364SKalle Valo if (num_tbs >= IL_NUM_OF_TBS) {
39247ac9a364SKalle Valo IL_ERR("Too many chunks: %i\n", num_tbs);
39257ac9a364SKalle Valo /* @todo issue fatal error, it is quite serious situation */
39267ac9a364SKalle Valo return;
39277ac9a364SKalle Valo }
39287ac9a364SKalle Valo
39297ac9a364SKalle Valo /* Unmap tx_cmd */
39307ac9a364SKalle Valo if (num_tbs)
3931ebe9e651SChristophe JAILLET dma_unmap_single(&dev->dev,
3932ebe9e651SChristophe JAILLET dma_unmap_addr(&txq->meta[idx], mapping),
39337ac9a364SKalle Valo dma_unmap_len(&txq->meta[idx], len),
3934ebe9e651SChristophe JAILLET DMA_BIDIRECTIONAL);
39357ac9a364SKalle Valo
39367ac9a364SKalle Valo /* Unmap chunks, if any. */
39377ac9a364SKalle Valo for (i = 1; i < num_tbs; i++)
3938ebe9e651SChristophe JAILLET dma_unmap_single(&dev->dev, il4965_tfd_tb_get_addr(tfd, i),
3939ebe9e651SChristophe JAILLET il4965_tfd_tb_get_len(tfd, i), DMA_TO_DEVICE);
39407ac9a364SKalle Valo
39417ac9a364SKalle Valo /* free SKB */
39427ac9a364SKalle Valo if (txq->skbs) {
39437ac9a364SKalle Valo struct sk_buff *skb = txq->skbs[txq->q.read_ptr];
39447ac9a364SKalle Valo
39457ac9a364SKalle Valo /* can be called from irqs-disabled context */
39467ac9a364SKalle Valo if (skb) {
39477ac9a364SKalle Valo dev_kfree_skb_any(skb);
39487ac9a364SKalle Valo txq->skbs[txq->q.read_ptr] = NULL;
39497ac9a364SKalle Valo }
39507ac9a364SKalle Valo }
39517ac9a364SKalle Valo }
39527ac9a364SKalle Valo
39537ac9a364SKalle Valo int
il4965_hw_txq_attach_buf_to_tfd(struct il_priv * il,struct il_tx_queue * txq,dma_addr_t addr,u16 len,u8 reset,u8 pad)39547ac9a364SKalle Valo il4965_hw_txq_attach_buf_to_tfd(struct il_priv *il, struct il_tx_queue *txq,
39557ac9a364SKalle Valo dma_addr_t addr, u16 len, u8 reset, u8 pad)
39567ac9a364SKalle Valo {
39577ac9a364SKalle Valo struct il_queue *q;
39587ac9a364SKalle Valo struct il_tfd *tfd, *tfd_tmp;
39597ac9a364SKalle Valo u32 num_tbs;
39607ac9a364SKalle Valo
39617ac9a364SKalle Valo q = &txq->q;
39627ac9a364SKalle Valo tfd_tmp = (struct il_tfd *)txq->tfds;
39637ac9a364SKalle Valo tfd = &tfd_tmp[q->write_ptr];
39647ac9a364SKalle Valo
39657ac9a364SKalle Valo if (reset)
39667ac9a364SKalle Valo memset(tfd, 0, sizeof(*tfd));
39677ac9a364SKalle Valo
39687ac9a364SKalle Valo num_tbs = il4965_tfd_get_num_tbs(tfd);
39697ac9a364SKalle Valo
39707ac9a364SKalle Valo /* Each TFD can point to a maximum 20 Tx buffers */
39717ac9a364SKalle Valo if (num_tbs >= IL_NUM_OF_TBS) {
39727ac9a364SKalle Valo IL_ERR("Error can not send more than %d chunks\n",
39737ac9a364SKalle Valo IL_NUM_OF_TBS);
39747ac9a364SKalle Valo return -EINVAL;
39757ac9a364SKalle Valo }
39767ac9a364SKalle Valo
39777ac9a364SKalle Valo BUG_ON(addr & ~DMA_BIT_MASK(36));
39787ac9a364SKalle Valo if (unlikely(addr & ~IL_TX_DMA_MASK))
39797ac9a364SKalle Valo IL_ERR("Unaligned address = %llx\n", (unsigned long long)addr);
39807ac9a364SKalle Valo
39817ac9a364SKalle Valo il4965_tfd_set_tb(tfd, num_tbs, addr, len);
39827ac9a364SKalle Valo
39837ac9a364SKalle Valo return 0;
39847ac9a364SKalle Valo }
39857ac9a364SKalle Valo
39867ac9a364SKalle Valo /*
39877ac9a364SKalle Valo * Tell nic where to find circular buffer of Tx Frame Descriptors for
39887ac9a364SKalle Valo * given Tx queue, and enable the DMA channel used for that queue.
39897ac9a364SKalle Valo *
39907ac9a364SKalle Valo * 4965 supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA
39917ac9a364SKalle Valo * channels supported in hardware.
39927ac9a364SKalle Valo */
39937ac9a364SKalle Valo int
il4965_hw_tx_queue_init(struct il_priv * il,struct il_tx_queue * txq)39947ac9a364SKalle Valo il4965_hw_tx_queue_init(struct il_priv *il, struct il_tx_queue *txq)
39957ac9a364SKalle Valo {
39967ac9a364SKalle Valo int txq_id = txq->q.id;
39977ac9a364SKalle Valo
39987ac9a364SKalle Valo /* Circular buffer (TFD queue in DRAM) physical base address */
39997ac9a364SKalle Valo il_wr(il, FH49_MEM_CBBC_QUEUE(txq_id), txq->q.dma_addr >> 8);
40007ac9a364SKalle Valo
40017ac9a364SKalle Valo return 0;
40027ac9a364SKalle Valo }
40037ac9a364SKalle Valo
40047ac9a364SKalle Valo /******************************************************************************
40057ac9a364SKalle Valo *
40067ac9a364SKalle Valo * Generic RX handler implementations
40077ac9a364SKalle Valo *
40087ac9a364SKalle Valo ******************************************************************************/
40097ac9a364SKalle Valo static void
il4965_hdl_alive(struct il_priv * il,struct il_rx_buf * rxb)40107ac9a364SKalle Valo il4965_hdl_alive(struct il_priv *il, struct il_rx_buf *rxb)
40117ac9a364SKalle Valo {
40127ac9a364SKalle Valo struct il_rx_pkt *pkt = rxb_addr(rxb);
40137ac9a364SKalle Valo struct il_alive_resp *palive;
40147ac9a364SKalle Valo struct delayed_work *pwork;
40157ac9a364SKalle Valo
40167ac9a364SKalle Valo palive = &pkt->u.alive_frame;
40177ac9a364SKalle Valo
40187ac9a364SKalle Valo D_INFO("Alive ucode status 0x%08X revision " "0x%01X 0x%01X\n",
40197ac9a364SKalle Valo palive->is_valid, palive->ver_type, palive->ver_subtype);
40207ac9a364SKalle Valo
40217ac9a364SKalle Valo if (palive->ver_subtype == INITIALIZE_SUBTYPE) {
40227ac9a364SKalle Valo D_INFO("Initialization Alive received.\n");
4023*3a156b52SJohannes Berg memcpy(&il->card_alive_init, &pkt->u.raw,
40247ac9a364SKalle Valo sizeof(struct il_init_alive_resp));
40257ac9a364SKalle Valo pwork = &il->init_alive_start;
40267ac9a364SKalle Valo } else {
40277ac9a364SKalle Valo D_INFO("Runtime Alive received.\n");
40287ac9a364SKalle Valo memcpy(&il->card_alive, &pkt->u.alive_frame,
40297ac9a364SKalle Valo sizeof(struct il_alive_resp));
40307ac9a364SKalle Valo pwork = &il->alive_start;
40317ac9a364SKalle Valo }
40327ac9a364SKalle Valo
40337ac9a364SKalle Valo /* We delay the ALIVE response by 5ms to
40347ac9a364SKalle Valo * give the HW RF Kill time to activate... */
40357ac9a364SKalle Valo if (palive->is_valid == UCODE_VALID_OK)
40367ac9a364SKalle Valo queue_delayed_work(il->workqueue, pwork, msecs_to_jiffies(5));
40377ac9a364SKalle Valo else
40387ac9a364SKalle Valo IL_WARN("uCode did not respond OK.\n");
40397ac9a364SKalle Valo }
40407ac9a364SKalle Valo
404135b7fbfcSLee Jones /*
40427ac9a364SKalle Valo * il4965_bg_stats_periodic - Timer callback to queue stats
40437ac9a364SKalle Valo *
40447ac9a364SKalle Valo * This callback is provided in order to send a stats request.
40457ac9a364SKalle Valo *
40467ac9a364SKalle Valo * This timer function is continually reset to execute within
40477ac9a364SKalle Valo * 60 seconds since the last N_STATS was received. We need to
40487ac9a364SKalle Valo * ensure we receive the stats in order to update the temperature
40497ac9a364SKalle Valo * used for calibrating the TXPOWER.
40507ac9a364SKalle Valo */
40517ac9a364SKalle Valo static void
il4965_bg_stats_periodic(struct timer_list * t)40522b77839bSKees Cook il4965_bg_stats_periodic(struct timer_list *t)
40537ac9a364SKalle Valo {
40542b77839bSKees Cook struct il_priv *il = from_timer(il, t, stats_periodic);
40557ac9a364SKalle Valo
40567ac9a364SKalle Valo if (test_bit(S_EXIT_PENDING, &il->status))
40577ac9a364SKalle Valo return;
40587ac9a364SKalle Valo
40597ac9a364SKalle Valo /* dont send host command if rf-kill is on */
40607ac9a364SKalle Valo if (!il_is_ready_rf(il))
40617ac9a364SKalle Valo return;
40627ac9a364SKalle Valo
40637ac9a364SKalle Valo il_send_stats_request(il, CMD_ASYNC, false);
40647ac9a364SKalle Valo }
40657ac9a364SKalle Valo
40667ac9a364SKalle Valo static void
il4965_hdl_beacon(struct il_priv * il,struct il_rx_buf * rxb)40677ac9a364SKalle Valo il4965_hdl_beacon(struct il_priv *il, struct il_rx_buf *rxb)
40687ac9a364SKalle Valo {
40697ac9a364SKalle Valo struct il_rx_pkt *pkt = rxb_addr(rxb);
40707ac9a364SKalle Valo struct il4965_beacon_notif *beacon =
40717ac9a364SKalle Valo (struct il4965_beacon_notif *)pkt->u.raw;
40727ac9a364SKalle Valo #ifdef CONFIG_IWLEGACY_DEBUG
40737ac9a364SKalle Valo u8 rate = il4965_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);
40747ac9a364SKalle Valo
40757ac9a364SKalle Valo D_RX("beacon status %x retries %d iss %d tsf:0x%.8x%.8x rate %d\n",
40767ac9a364SKalle Valo le32_to_cpu(beacon->beacon_notify_hdr.u.status) & TX_STATUS_MSK,
40777ac9a364SKalle Valo beacon->beacon_notify_hdr.failure_frame,
40787ac9a364SKalle Valo le32_to_cpu(beacon->ibss_mgr_status),
40797ac9a364SKalle Valo le32_to_cpu(beacon->high_tsf), le32_to_cpu(beacon->low_tsf), rate);
40807ac9a364SKalle Valo #endif
40817ac9a364SKalle Valo il->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status);
40827ac9a364SKalle Valo }
40837ac9a364SKalle Valo
40847ac9a364SKalle Valo static void
il4965_perform_ct_kill_task(struct il_priv * il)40857ac9a364SKalle Valo il4965_perform_ct_kill_task(struct il_priv *il)
40867ac9a364SKalle Valo {
40877ac9a364SKalle Valo unsigned long flags;
40887ac9a364SKalle Valo
40897ac9a364SKalle Valo D_POWER("Stop all queues\n");
40907ac9a364SKalle Valo
40917ac9a364SKalle Valo if (il->mac80211_registered)
40927ac9a364SKalle Valo ieee80211_stop_queues(il->hw);
40937ac9a364SKalle Valo
40947ac9a364SKalle Valo _il_wr(il, CSR_UCODE_DRV_GP1_SET,
40957ac9a364SKalle Valo CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
40967ac9a364SKalle Valo _il_rd(il, CSR_UCODE_DRV_GP1);
40977ac9a364SKalle Valo
40987ac9a364SKalle Valo spin_lock_irqsave(&il->reg_lock, flags);
40997ac9a364SKalle Valo if (likely(_il_grab_nic_access(il)))
41007ac9a364SKalle Valo _il_release_nic_access(il);
41017ac9a364SKalle Valo spin_unlock_irqrestore(&il->reg_lock, flags);
41027ac9a364SKalle Valo }
41037ac9a364SKalle Valo
41047ac9a364SKalle Valo /* Handle notification from uCode that card's power state is changing
41057ac9a364SKalle Valo * due to software, hardware, or critical temperature RFKILL */
41067ac9a364SKalle Valo static void
il4965_hdl_card_state(struct il_priv * il,struct il_rx_buf * rxb)41077ac9a364SKalle Valo il4965_hdl_card_state(struct il_priv *il, struct il_rx_buf *rxb)
41087ac9a364SKalle Valo {
41097ac9a364SKalle Valo struct il_rx_pkt *pkt = rxb_addr(rxb);
41107ac9a364SKalle Valo u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
41117ac9a364SKalle Valo unsigned long status = il->status;
41127ac9a364SKalle Valo
41137ac9a364SKalle Valo D_RF_KILL("Card state received: HW:%s SW:%s CT:%s\n",
41147ac9a364SKalle Valo (flags & HW_CARD_DISABLED) ? "Kill" : "On",
41157ac9a364SKalle Valo (flags & SW_CARD_DISABLED) ? "Kill" : "On",
41167ac9a364SKalle Valo (flags & CT_CARD_DISABLED) ? "Reached" : "Not reached");
41177ac9a364SKalle Valo
41187ac9a364SKalle Valo if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED | CT_CARD_DISABLED)) {
41197ac9a364SKalle Valo
41207ac9a364SKalle Valo _il_wr(il, CSR_UCODE_DRV_GP1_SET,
41217ac9a364SKalle Valo CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
41227ac9a364SKalle Valo
41237ac9a364SKalle Valo il_wr(il, HBUS_TARG_MBX_C, HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
41247ac9a364SKalle Valo
41257ac9a364SKalle Valo if (!(flags & RXON_CARD_DISABLED)) {
41267ac9a364SKalle Valo _il_wr(il, CSR_UCODE_DRV_GP1_CLR,
41277ac9a364SKalle Valo CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
41287ac9a364SKalle Valo il_wr(il, HBUS_TARG_MBX_C,
41297ac9a364SKalle Valo HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
41307ac9a364SKalle Valo }
41317ac9a364SKalle Valo }
41327ac9a364SKalle Valo
41337ac9a364SKalle Valo if (flags & CT_CARD_DISABLED)
41347ac9a364SKalle Valo il4965_perform_ct_kill_task(il);
41357ac9a364SKalle Valo
41367ac9a364SKalle Valo if (flags & HW_CARD_DISABLED)
41377ac9a364SKalle Valo set_bit(S_RFKILL, &il->status);
41387ac9a364SKalle Valo else
41397ac9a364SKalle Valo clear_bit(S_RFKILL, &il->status);
41407ac9a364SKalle Valo
41417ac9a364SKalle Valo if (!(flags & RXON_CARD_DISABLED))
41427ac9a364SKalle Valo il_scan_cancel(il);
41437ac9a364SKalle Valo
41447ac9a364SKalle Valo if ((test_bit(S_RFKILL, &status) !=
41457ac9a364SKalle Valo test_bit(S_RFKILL, &il->status)))
41467ac9a364SKalle Valo wiphy_rfkill_set_hw_state(il->hw->wiphy,
41477ac9a364SKalle Valo test_bit(S_RFKILL, &il->status));
41487ac9a364SKalle Valo else
41497ac9a364SKalle Valo wake_up(&il->wait_command_queue);
41507ac9a364SKalle Valo }
41517ac9a364SKalle Valo
415235b7fbfcSLee Jones /*
41537ac9a364SKalle Valo * il4965_setup_handlers - Initialize Rx handler callbacks
41547ac9a364SKalle Valo *
41557ac9a364SKalle Valo * Setup the RX handlers for each of the reply types sent from the uCode
41567ac9a364SKalle Valo * to the host.
41577ac9a364SKalle Valo *
41587ac9a364SKalle Valo * This function chains into the hardware specific files for them to setup
41597ac9a364SKalle Valo * any hardware specific handlers as well.
41607ac9a364SKalle Valo */
41617ac9a364SKalle Valo static void
il4965_setup_handlers(struct il_priv * il)41627ac9a364SKalle Valo il4965_setup_handlers(struct il_priv *il)
41637ac9a364SKalle Valo {
41647ac9a364SKalle Valo il->handlers[N_ALIVE] = il4965_hdl_alive;
41657ac9a364SKalle Valo il->handlers[N_ERROR] = il_hdl_error;
41667ac9a364SKalle Valo il->handlers[N_CHANNEL_SWITCH] = il_hdl_csa;
41677ac9a364SKalle Valo il->handlers[N_SPECTRUM_MEASUREMENT] = il_hdl_spectrum_measurement;
41687ac9a364SKalle Valo il->handlers[N_PM_SLEEP] = il_hdl_pm_sleep;
41697ac9a364SKalle Valo il->handlers[N_PM_DEBUG_STATS] = il_hdl_pm_debug_stats;
41707ac9a364SKalle Valo il->handlers[N_BEACON] = il4965_hdl_beacon;
41717ac9a364SKalle Valo
41727ac9a364SKalle Valo /*
41737ac9a364SKalle Valo * The same handler is used for both the REPLY to a discrete
41747ac9a364SKalle Valo * stats request from the host as well as for the periodic
41757ac9a364SKalle Valo * stats notifications (after received beacons) from the uCode.
41767ac9a364SKalle Valo */
41777ac9a364SKalle Valo il->handlers[C_STATS] = il4965_hdl_c_stats;
41787ac9a364SKalle Valo il->handlers[N_STATS] = il4965_hdl_stats;
41797ac9a364SKalle Valo
41807ac9a364SKalle Valo il_setup_rx_scan_handlers(il);
41817ac9a364SKalle Valo
41827ac9a364SKalle Valo /* status change handler */
41837ac9a364SKalle Valo il->handlers[N_CARD_STATE] = il4965_hdl_card_state;
41847ac9a364SKalle Valo
41857ac9a364SKalle Valo il->handlers[N_MISSED_BEACONS] = il4965_hdl_missed_beacon;
41867ac9a364SKalle Valo /* Rx handlers */
41877ac9a364SKalle Valo il->handlers[N_RX_PHY] = il4965_hdl_rx_phy;
41887ac9a364SKalle Valo il->handlers[N_RX_MPDU] = il4965_hdl_rx;
41897ac9a364SKalle Valo il->handlers[N_RX] = il4965_hdl_rx;
41907ac9a364SKalle Valo /* block ack */
41917ac9a364SKalle Valo il->handlers[N_COMPRESSED_BA] = il4965_hdl_compressed_ba;
41927ac9a364SKalle Valo /* Tx response */
41937ac9a364SKalle Valo il->handlers[C_TX] = il4965_hdl_tx;
41947ac9a364SKalle Valo }
41957ac9a364SKalle Valo
419635b7fbfcSLee Jones /*
41977ac9a364SKalle Valo * il4965_rx_handle - Main entry function for receiving responses from uCode
41987ac9a364SKalle Valo *
41997ac9a364SKalle Valo * Uses the il->handlers callback function array to invoke
42007ac9a364SKalle Valo * the appropriate handlers, including command responses,
42017ac9a364SKalle Valo * frame-received notifications, and other notifications.
42027ac9a364SKalle Valo */
42037ac9a364SKalle Valo void
il4965_rx_handle(struct il_priv * il)42047ac9a364SKalle Valo il4965_rx_handle(struct il_priv *il)
42057ac9a364SKalle Valo {
42067ac9a364SKalle Valo struct il_rx_buf *rxb;
42077ac9a364SKalle Valo struct il_rx_pkt *pkt;
42087ac9a364SKalle Valo struct il_rx_queue *rxq = &il->rxq;
42097ac9a364SKalle Valo u32 r, i;
42107ac9a364SKalle Valo int reclaim;
42117ac9a364SKalle Valo unsigned long flags;
42127ac9a364SKalle Valo u8 fill_rx = 0;
42137ac9a364SKalle Valo u32 count = 8;
42147ac9a364SKalle Valo int total_empty;
42157ac9a364SKalle Valo
42167ac9a364SKalle Valo /* uCode's read idx (stored in shared DRAM) indicates the last Rx
42177ac9a364SKalle Valo * buffer that the driver may process (last buffer filled by ucode). */
42187ac9a364SKalle Valo r = le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF;
42197ac9a364SKalle Valo i = rxq->read;
42207ac9a364SKalle Valo
42217ac9a364SKalle Valo /* Rx interrupt, but nothing sent from uCode */
42227ac9a364SKalle Valo if (i == r)
42237ac9a364SKalle Valo D_RX("r = %d, i = %d\n", r, i);
42247ac9a364SKalle Valo
42257ac9a364SKalle Valo /* calculate total frames need to be restock after handling RX */
42267ac9a364SKalle Valo total_empty = r - rxq->write_actual;
42277ac9a364SKalle Valo if (total_empty < 0)
42287ac9a364SKalle Valo total_empty += RX_QUEUE_SIZE;
42297ac9a364SKalle Valo
42307ac9a364SKalle Valo if (total_empty > (RX_QUEUE_SIZE / 2))
42317ac9a364SKalle Valo fill_rx = 1;
42327ac9a364SKalle Valo
42337ac9a364SKalle Valo while (i != r) {
42347ac9a364SKalle Valo int len;
42357ac9a364SKalle Valo
42367ac9a364SKalle Valo rxb = rxq->queue[i];
42377ac9a364SKalle Valo
42387ac9a364SKalle Valo /* If an RXB doesn't have a Rx queue slot associated with it,
42397ac9a364SKalle Valo * then a bug has been introduced in the queue refilling
42407ac9a364SKalle Valo * routines -- catch it here */
42417ac9a364SKalle Valo BUG_ON(rxb == NULL);
42427ac9a364SKalle Valo
42437ac9a364SKalle Valo rxq->queue[i] = NULL;
42447ac9a364SKalle Valo
4245ebe9e651SChristophe JAILLET dma_unmap_page(&il->pci_dev->dev, rxb->page_dma,
42467ac9a364SKalle Valo PAGE_SIZE << il->hw_params.rx_page_order,
4247ebe9e651SChristophe JAILLET DMA_FROM_DEVICE);
42487ac9a364SKalle Valo pkt = rxb_addr(rxb);
42497ac9a364SKalle Valo
42507ac9a364SKalle Valo len = le32_to_cpu(pkt->len_n_flags) & IL_RX_FRAME_SIZE_MSK;
42517ac9a364SKalle Valo len += sizeof(u32); /* account for status word */
42527ac9a364SKalle Valo
42537ac9a364SKalle Valo reclaim = il_need_reclaim(il, pkt);
42547ac9a364SKalle Valo
42557ac9a364SKalle Valo /* Based on type of command response or notification,
42567ac9a364SKalle Valo * handle those that need handling via function in
42577ac9a364SKalle Valo * handlers table. See il4965_setup_handlers() */
42587ac9a364SKalle Valo if (il->handlers[pkt->hdr.cmd]) {
42597ac9a364SKalle Valo D_RX("r = %d, i = %d, %s, 0x%02x\n", r, i,
42607ac9a364SKalle Valo il_get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
42617ac9a364SKalle Valo il->isr_stats.handlers[pkt->hdr.cmd]++;
42627ac9a364SKalle Valo il->handlers[pkt->hdr.cmd] (il, rxb);
42637ac9a364SKalle Valo } else {
42647ac9a364SKalle Valo /* No handling needed */
42657ac9a364SKalle Valo D_RX("r %d i %d No handler needed for %s, 0x%02x\n", r,
42667ac9a364SKalle Valo i, il_get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
42677ac9a364SKalle Valo }
42687ac9a364SKalle Valo
42697ac9a364SKalle Valo /*
42707ac9a364SKalle Valo * XXX: After here, we should always check rxb->page
42717ac9a364SKalle Valo * against NULL before touching it or its virtual
42727ac9a364SKalle Valo * memory (pkt). Because some handler might have
42737ac9a364SKalle Valo * already taken or freed the pages.
42747ac9a364SKalle Valo */
42757ac9a364SKalle Valo
42767ac9a364SKalle Valo if (reclaim) {
42777ac9a364SKalle Valo /* Invoke any callbacks, transfer the buffer to caller,
42787ac9a364SKalle Valo * and fire off the (possibly) blocking il_send_cmd()
42797ac9a364SKalle Valo * as we reclaim the driver command queue */
42807ac9a364SKalle Valo if (rxb->page)
42817ac9a364SKalle Valo il_tx_cmd_complete(il, rxb);
42827ac9a364SKalle Valo else
42837ac9a364SKalle Valo IL_WARN("Claim null rxb?\n");
42847ac9a364SKalle Valo }
42857ac9a364SKalle Valo
42867ac9a364SKalle Valo /* Reuse the page if possible. For notification packets and
42877ac9a364SKalle Valo * SKBs that fail to Rx correctly, add them back into the
42887ac9a364SKalle Valo * rx_free list for reuse later. */
42897ac9a364SKalle Valo spin_lock_irqsave(&rxq->lock, flags);
42907ac9a364SKalle Valo if (rxb->page != NULL) {
42917ac9a364SKalle Valo rxb->page_dma =
4292ebe9e651SChristophe JAILLET dma_map_page(&il->pci_dev->dev, rxb->page, 0,
4293ebe9e651SChristophe JAILLET PAGE_SIZE << il->hw_params.rx_page_order,
4294ebe9e651SChristophe JAILLET DMA_FROM_DEVICE);
42957ac9a364SKalle Valo
4296ebe9e651SChristophe JAILLET if (unlikely(dma_mapping_error(&il->pci_dev->dev,
42977ac9a364SKalle Valo rxb->page_dma))) {
42987ac9a364SKalle Valo __il_free_pages(il, rxb->page);
42997ac9a364SKalle Valo rxb->page = NULL;
43007ac9a364SKalle Valo list_add_tail(&rxb->list, &rxq->rx_used);
43017ac9a364SKalle Valo } else {
43027ac9a364SKalle Valo list_add_tail(&rxb->list, &rxq->rx_free);
43037ac9a364SKalle Valo rxq->free_count++;
43047ac9a364SKalle Valo }
43057ac9a364SKalle Valo } else
43067ac9a364SKalle Valo list_add_tail(&rxb->list, &rxq->rx_used);
43077ac9a364SKalle Valo
43087ac9a364SKalle Valo spin_unlock_irqrestore(&rxq->lock, flags);
43097ac9a364SKalle Valo
43107ac9a364SKalle Valo i = (i + 1) & RX_QUEUE_MASK;
43117ac9a364SKalle Valo /* If there are a lot of unused frames,
43127ac9a364SKalle Valo * restock the Rx queue so ucode wont assert. */
43137ac9a364SKalle Valo if (fill_rx) {
43147ac9a364SKalle Valo count++;
43157ac9a364SKalle Valo if (count >= 8) {
43167ac9a364SKalle Valo rxq->read = i;
43177ac9a364SKalle Valo il4965_rx_replenish_now(il);
43187ac9a364SKalle Valo count = 0;
43197ac9a364SKalle Valo }
43207ac9a364SKalle Valo }
43217ac9a364SKalle Valo }
43227ac9a364SKalle Valo
43237ac9a364SKalle Valo /* Backtrack one entry */
43247ac9a364SKalle Valo rxq->read = i;
43257ac9a364SKalle Valo if (fill_rx)
43267ac9a364SKalle Valo il4965_rx_replenish_now(il);
43277ac9a364SKalle Valo else
43287ac9a364SKalle Valo il4965_rx_queue_restock(il);
43297ac9a364SKalle Valo }
43307ac9a364SKalle Valo
43317ac9a364SKalle Valo /* call this function to flush any scheduled tasklet */
43327ac9a364SKalle Valo static inline void
il4965_synchronize_irq(struct il_priv * il)43337ac9a364SKalle Valo il4965_synchronize_irq(struct il_priv *il)
43347ac9a364SKalle Valo {
43357ac9a364SKalle Valo /* wait to make sure we flush pending tasklet */
43367ac9a364SKalle Valo synchronize_irq(il->pci_dev->irq);
43377ac9a364SKalle Valo tasklet_kill(&il->irq_tasklet);
43387ac9a364SKalle Valo }
43397ac9a364SKalle Valo
43407ac9a364SKalle Valo static void
il4965_irq_tasklet(struct tasklet_struct * t)4341b81b9d37SAllen Pais il4965_irq_tasklet(struct tasklet_struct *t)
43427ac9a364SKalle Valo {
4343b81b9d37SAllen Pais struct il_priv *il = from_tasklet(il, t, irq_tasklet);
43447ac9a364SKalle Valo u32 inta, handled = 0;
43457ac9a364SKalle Valo u32 inta_fh;
43467ac9a364SKalle Valo unsigned long flags;
43477ac9a364SKalle Valo u32 i;
43487ac9a364SKalle Valo #ifdef CONFIG_IWLEGACY_DEBUG
43497ac9a364SKalle Valo u32 inta_mask;
43507ac9a364SKalle Valo #endif
43517ac9a364SKalle Valo
43527ac9a364SKalle Valo spin_lock_irqsave(&il->lock, flags);
43537ac9a364SKalle Valo
43547ac9a364SKalle Valo /* Ack/clear/reset pending uCode interrupts.
43557ac9a364SKalle Valo * Note: Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS,
43567ac9a364SKalle Valo * and will clear only when CSR_FH_INT_STATUS gets cleared. */
43577ac9a364SKalle Valo inta = _il_rd(il, CSR_INT);
43587ac9a364SKalle Valo _il_wr(il, CSR_INT, inta);
43597ac9a364SKalle Valo
43607ac9a364SKalle Valo /* Ack/clear/reset pending flow-handler (DMA) interrupts.
43617ac9a364SKalle Valo * Any new interrupts that happen after this, either while we're
43627ac9a364SKalle Valo * in this tasklet, or later, will show up in next ISR/tasklet. */
43637ac9a364SKalle Valo inta_fh = _il_rd(il, CSR_FH_INT_STATUS);
43647ac9a364SKalle Valo _il_wr(il, CSR_FH_INT_STATUS, inta_fh);
43657ac9a364SKalle Valo
43667ac9a364SKalle Valo #ifdef CONFIG_IWLEGACY_DEBUG
43677ac9a364SKalle Valo if (il_get_debug_level(il) & IL_DL_ISR) {
43687ac9a364SKalle Valo /* just for debug */
43697ac9a364SKalle Valo inta_mask = _il_rd(il, CSR_INT_MASK);
43707ac9a364SKalle Valo D_ISR("inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", inta,
43717ac9a364SKalle Valo inta_mask, inta_fh);
43727ac9a364SKalle Valo }
43737ac9a364SKalle Valo #endif
43747ac9a364SKalle Valo
43757ac9a364SKalle Valo spin_unlock_irqrestore(&il->lock, flags);
43767ac9a364SKalle Valo
43777ac9a364SKalle Valo /* Since CSR_INT and CSR_FH_INT_STATUS reads and clears are not
43787ac9a364SKalle Valo * atomic, make sure that inta covers all the interrupts that
43797ac9a364SKalle Valo * we've discovered, even if FH interrupt came in just after
43807ac9a364SKalle Valo * reading CSR_INT. */
43817ac9a364SKalle Valo if (inta_fh & CSR49_FH_INT_RX_MASK)
43827ac9a364SKalle Valo inta |= CSR_INT_BIT_FH_RX;
43837ac9a364SKalle Valo if (inta_fh & CSR49_FH_INT_TX_MASK)
43847ac9a364SKalle Valo inta |= CSR_INT_BIT_FH_TX;
43857ac9a364SKalle Valo
43867ac9a364SKalle Valo /* Now service all interrupt bits discovered above. */
43877ac9a364SKalle Valo if (inta & CSR_INT_BIT_HW_ERR) {
43887ac9a364SKalle Valo IL_ERR("Hardware error detected. Restarting.\n");
43897ac9a364SKalle Valo
43907ac9a364SKalle Valo /* Tell the device to stop sending interrupts */
43917ac9a364SKalle Valo il_disable_interrupts(il);
43927ac9a364SKalle Valo
43937ac9a364SKalle Valo il->isr_stats.hw++;
43947ac9a364SKalle Valo il_irq_handle_error(il);
43957ac9a364SKalle Valo
43967ac9a364SKalle Valo handled |= CSR_INT_BIT_HW_ERR;
43977ac9a364SKalle Valo
43987ac9a364SKalle Valo return;
43997ac9a364SKalle Valo }
44007ac9a364SKalle Valo #ifdef CONFIG_IWLEGACY_DEBUG
44017ac9a364SKalle Valo if (il_get_debug_level(il) & (IL_DL_ISR)) {
44027ac9a364SKalle Valo /* NIC fires this, but we don't use it, redundant with WAKEUP */
44037ac9a364SKalle Valo if (inta & CSR_INT_BIT_SCD) {
44047ac9a364SKalle Valo D_ISR("Scheduler finished to transmit "
44057ac9a364SKalle Valo "the frame/frames.\n");
44067ac9a364SKalle Valo il->isr_stats.sch++;
44077ac9a364SKalle Valo }
44087ac9a364SKalle Valo
44097ac9a364SKalle Valo /* Alive notification via Rx interrupt will do the real work */
44107ac9a364SKalle Valo if (inta & CSR_INT_BIT_ALIVE) {
44117ac9a364SKalle Valo D_ISR("Alive interrupt\n");
44127ac9a364SKalle Valo il->isr_stats.alive++;
44137ac9a364SKalle Valo }
44147ac9a364SKalle Valo }
44157ac9a364SKalle Valo #endif
44167ac9a364SKalle Valo /* Safely ignore these bits for debug checks below */
44177ac9a364SKalle Valo inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE);
44187ac9a364SKalle Valo
44197ac9a364SKalle Valo /* HW RF KILL switch toggled */
44207ac9a364SKalle Valo if (inta & CSR_INT_BIT_RF_KILL) {
44217ac9a364SKalle Valo int hw_rf_kill = 0;
44227ac9a364SKalle Valo
44237ac9a364SKalle Valo if (!(_il_rd(il, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
44247ac9a364SKalle Valo hw_rf_kill = 1;
44257ac9a364SKalle Valo
44267ac9a364SKalle Valo IL_WARN("RF_KILL bit toggled to %s.\n",
44277ac9a364SKalle Valo hw_rf_kill ? "disable radio" : "enable radio");
44287ac9a364SKalle Valo
44297ac9a364SKalle Valo il->isr_stats.rfkill++;
44307ac9a364SKalle Valo
44317ac9a364SKalle Valo /* driver only loads ucode once setting the interface up.
44327ac9a364SKalle Valo * the driver allows loading the ucode even if the radio
44337ac9a364SKalle Valo * is killed. Hence update the killswitch state here. The
44347ac9a364SKalle Valo * rfkill handler will care about restarting if needed.
44357ac9a364SKalle Valo */
44367ac9a364SKalle Valo if (hw_rf_kill) {
44377ac9a364SKalle Valo set_bit(S_RFKILL, &il->status);
44387ac9a364SKalle Valo } else {
44397ac9a364SKalle Valo clear_bit(S_RFKILL, &il->status);
44407ac9a364SKalle Valo il_force_reset(il, true);
44417ac9a364SKalle Valo }
44427ac9a364SKalle Valo wiphy_rfkill_set_hw_state(il->hw->wiphy, hw_rf_kill);
44437ac9a364SKalle Valo
44447ac9a364SKalle Valo handled |= CSR_INT_BIT_RF_KILL;
44457ac9a364SKalle Valo }
44467ac9a364SKalle Valo
44477ac9a364SKalle Valo /* Chip got too hot and stopped itself */
44487ac9a364SKalle Valo if (inta & CSR_INT_BIT_CT_KILL) {
44497ac9a364SKalle Valo IL_ERR("Microcode CT kill error detected.\n");
44507ac9a364SKalle Valo il->isr_stats.ctkill++;
44517ac9a364SKalle Valo handled |= CSR_INT_BIT_CT_KILL;
44527ac9a364SKalle Valo }
44537ac9a364SKalle Valo
44547ac9a364SKalle Valo /* Error detected by uCode */
44557ac9a364SKalle Valo if (inta & CSR_INT_BIT_SW_ERR) {
44567ac9a364SKalle Valo IL_ERR("Microcode SW error detected. " " Restarting 0x%X.\n",
44577ac9a364SKalle Valo inta);
44587ac9a364SKalle Valo il->isr_stats.sw++;
44597ac9a364SKalle Valo il_irq_handle_error(il);
44607ac9a364SKalle Valo handled |= CSR_INT_BIT_SW_ERR;
44617ac9a364SKalle Valo }
44627ac9a364SKalle Valo
44637ac9a364SKalle Valo /*
44647ac9a364SKalle Valo * uCode wakes up after power-down sleep.
44657ac9a364SKalle Valo * Tell device about any new tx or host commands enqueued,
44667ac9a364SKalle Valo * and about any Rx buffers made available while asleep.
44677ac9a364SKalle Valo */
44687ac9a364SKalle Valo if (inta & CSR_INT_BIT_WAKEUP) {
44697ac9a364SKalle Valo D_ISR("Wakeup interrupt\n");
44707ac9a364SKalle Valo il_rx_queue_update_write_ptr(il, &il->rxq);
44717ac9a364SKalle Valo for (i = 0; i < il->hw_params.max_txq_num; i++)
44727ac9a364SKalle Valo il_txq_update_write_ptr(il, &il->txq[i]);
44737ac9a364SKalle Valo il->isr_stats.wakeup++;
44747ac9a364SKalle Valo handled |= CSR_INT_BIT_WAKEUP;
44757ac9a364SKalle Valo }
44767ac9a364SKalle Valo
44777ac9a364SKalle Valo /* All uCode command responses, including Tx command responses,
44787ac9a364SKalle Valo * Rx "responses" (frame-received notification), and other
44797ac9a364SKalle Valo * notifications from uCode come through here*/
44807ac9a364SKalle Valo if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) {
44817ac9a364SKalle Valo il4965_rx_handle(il);
44827ac9a364SKalle Valo il->isr_stats.rx++;
44837ac9a364SKalle Valo handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
44847ac9a364SKalle Valo }
44857ac9a364SKalle Valo
44867ac9a364SKalle Valo /* This "Tx" DMA channel is used only for loading uCode */
44877ac9a364SKalle Valo if (inta & CSR_INT_BIT_FH_TX) {
44887ac9a364SKalle Valo D_ISR("uCode load interrupt\n");
44897ac9a364SKalle Valo il->isr_stats.tx++;
44907ac9a364SKalle Valo handled |= CSR_INT_BIT_FH_TX;
44917ac9a364SKalle Valo /* Wake up uCode load routine, now that load is complete */
44927ac9a364SKalle Valo il->ucode_write_complete = 1;
44937ac9a364SKalle Valo wake_up(&il->wait_command_queue);
44947ac9a364SKalle Valo }
44957ac9a364SKalle Valo
44967ac9a364SKalle Valo if (inta & ~handled) {
44977ac9a364SKalle Valo IL_ERR("Unhandled INTA bits 0x%08x\n", inta & ~handled);
44987ac9a364SKalle Valo il->isr_stats.unhandled++;
44997ac9a364SKalle Valo }
45007ac9a364SKalle Valo
45017ac9a364SKalle Valo if (inta & ~(il->inta_mask)) {
45027ac9a364SKalle Valo IL_WARN("Disabled INTA bits 0x%08x were pending\n",
45037ac9a364SKalle Valo inta & ~il->inta_mask);
45047ac9a364SKalle Valo IL_WARN(" with FH49_INT = 0x%08x\n", inta_fh);
45057ac9a364SKalle Valo }
45067ac9a364SKalle Valo
45077ac9a364SKalle Valo /* Re-enable all interrupts */
45087ac9a364SKalle Valo /* only Re-enable if disabled by irq */
45097ac9a364SKalle Valo if (test_bit(S_INT_ENABLED, &il->status))
45107ac9a364SKalle Valo il_enable_interrupts(il);
45117ac9a364SKalle Valo /* Re-enable RF_KILL if it occurred */
45127ac9a364SKalle Valo else if (handled & CSR_INT_BIT_RF_KILL)
45137ac9a364SKalle Valo il_enable_rfkill_int(il);
45147ac9a364SKalle Valo
45157ac9a364SKalle Valo #ifdef CONFIG_IWLEGACY_DEBUG
45167ac9a364SKalle Valo if (il_get_debug_level(il) & (IL_DL_ISR)) {
45177ac9a364SKalle Valo inta = _il_rd(il, CSR_INT);
45187ac9a364SKalle Valo inta_mask = _il_rd(il, CSR_INT_MASK);
45197ac9a364SKalle Valo inta_fh = _il_rd(il, CSR_FH_INT_STATUS);
45207ac9a364SKalle Valo D_ISR("End inta 0x%08x, enabled 0x%08x, fh 0x%08x, "
45217ac9a364SKalle Valo "flags 0x%08lx\n", inta, inta_mask, inta_fh, flags);
45227ac9a364SKalle Valo }
45237ac9a364SKalle Valo #endif
45247ac9a364SKalle Valo }
45257ac9a364SKalle Valo
45267ac9a364SKalle Valo /*****************************************************************************
45277ac9a364SKalle Valo *
45287ac9a364SKalle Valo * sysfs attributes
45297ac9a364SKalle Valo *
45307ac9a364SKalle Valo *****************************************************************************/
45317ac9a364SKalle Valo
45327ac9a364SKalle Valo #ifdef CONFIG_IWLEGACY_DEBUG
45337ac9a364SKalle Valo
45347ac9a364SKalle Valo /*
45357ac9a364SKalle Valo * The following adds a new attribute to the sysfs representation
45367ac9a364SKalle Valo * of this device driver (i.e. a new file in /sys/class/net/wlan0/device/)
45377ac9a364SKalle Valo * used for controlling the debug level.
45387ac9a364SKalle Valo *
45397ac9a364SKalle Valo * See the level definitions in iwl for details.
45407ac9a364SKalle Valo *
45417ac9a364SKalle Valo * The debug_level being managed using sysfs below is a per device debug
45427ac9a364SKalle Valo * level that is used instead of the global debug level if it (the per
45437ac9a364SKalle Valo * device debug level) is set.
45447ac9a364SKalle Valo */
45457ac9a364SKalle Valo static ssize_t
il4965_show_debug_level(struct device * d,struct device_attribute * attr,char * buf)45467ac9a364SKalle Valo il4965_show_debug_level(struct device *d, struct device_attribute *attr,
45477ac9a364SKalle Valo char *buf)
45487ac9a364SKalle Valo {
45497ac9a364SKalle Valo struct il_priv *il = dev_get_drvdata(d);
45507ac9a364SKalle Valo return sprintf(buf, "0x%08X\n", il_get_debug_level(il));
45517ac9a364SKalle Valo }
45527ac9a364SKalle Valo
45537ac9a364SKalle Valo static ssize_t
il4965_store_debug_level(struct device * d,struct device_attribute * attr,const char * buf,size_t count)45547ac9a364SKalle Valo il4965_store_debug_level(struct device *d, struct device_attribute *attr,
45557ac9a364SKalle Valo const char *buf, size_t count)
45567ac9a364SKalle Valo {
45577ac9a364SKalle Valo struct il_priv *il = dev_get_drvdata(d);
45587ac9a364SKalle Valo unsigned long val;
45597ac9a364SKalle Valo int ret;
45607ac9a364SKalle Valo
45617ac9a364SKalle Valo ret = kstrtoul(buf, 0, &val);
45627ac9a364SKalle Valo if (ret)
45637ac9a364SKalle Valo IL_ERR("%s is not in hex or decimal form.\n", buf);
45647ac9a364SKalle Valo else
45657ac9a364SKalle Valo il->debug_level = val;
45667ac9a364SKalle Valo
45677ac9a364SKalle Valo return strnlen(buf, count);
45687ac9a364SKalle Valo }
45697ac9a364SKalle Valo
45702ef00c53SJoe Perches static DEVICE_ATTR(debug_level, 0644, il4965_show_debug_level,
45717ac9a364SKalle Valo il4965_store_debug_level);
45727ac9a364SKalle Valo
45737ac9a364SKalle Valo #endif /* CONFIG_IWLEGACY_DEBUG */
45747ac9a364SKalle Valo
45757ac9a364SKalle Valo static ssize_t
il4965_show_temperature(struct device * d,struct device_attribute * attr,char * buf)45767ac9a364SKalle Valo il4965_show_temperature(struct device *d, struct device_attribute *attr,
45777ac9a364SKalle Valo char *buf)
45787ac9a364SKalle Valo {
45797ac9a364SKalle Valo struct il_priv *il = dev_get_drvdata(d);
45807ac9a364SKalle Valo
45817ac9a364SKalle Valo if (!il_is_alive(il))
45827ac9a364SKalle Valo return -EAGAIN;
45837ac9a364SKalle Valo
45847ac9a364SKalle Valo return sprintf(buf, "%d\n", il->temperature);
45857ac9a364SKalle Valo }
45867ac9a364SKalle Valo
45872ef00c53SJoe Perches static DEVICE_ATTR(temperature, 0444, il4965_show_temperature, NULL);
45887ac9a364SKalle Valo
45897ac9a364SKalle Valo static ssize_t
il4965_show_tx_power(struct device * d,struct device_attribute * attr,char * buf)45907ac9a364SKalle Valo il4965_show_tx_power(struct device *d, struct device_attribute *attr, char *buf)
45917ac9a364SKalle Valo {
45927ac9a364SKalle Valo struct il_priv *il = dev_get_drvdata(d);
45937ac9a364SKalle Valo
45947ac9a364SKalle Valo if (!il_is_ready_rf(il))
45957ac9a364SKalle Valo return sprintf(buf, "off\n");
45967ac9a364SKalle Valo else
45977ac9a364SKalle Valo return sprintf(buf, "%d\n", il->tx_power_user_lmt);
45987ac9a364SKalle Valo }
45997ac9a364SKalle Valo
46007ac9a364SKalle Valo static ssize_t
il4965_store_tx_power(struct device * d,struct device_attribute * attr,const char * buf,size_t count)46017ac9a364SKalle Valo il4965_store_tx_power(struct device *d, struct device_attribute *attr,
46027ac9a364SKalle Valo const char *buf, size_t count)
46037ac9a364SKalle Valo {
46047ac9a364SKalle Valo struct il_priv *il = dev_get_drvdata(d);
46057ac9a364SKalle Valo unsigned long val;
46067ac9a364SKalle Valo int ret;
46077ac9a364SKalle Valo
46087ac9a364SKalle Valo ret = kstrtoul(buf, 10, &val);
46097ac9a364SKalle Valo if (ret)
46107ac9a364SKalle Valo IL_INFO("%s is not in decimal form.\n", buf);
46117ac9a364SKalle Valo else {
46127ac9a364SKalle Valo ret = il_set_tx_power(il, val, false);
46137ac9a364SKalle Valo if (ret)
46147ac9a364SKalle Valo IL_ERR("failed setting tx power (0x%08x).\n", ret);
46157ac9a364SKalle Valo else
46167ac9a364SKalle Valo ret = count;
46177ac9a364SKalle Valo }
46187ac9a364SKalle Valo return ret;
46197ac9a364SKalle Valo }
46207ac9a364SKalle Valo
46212ef00c53SJoe Perches static DEVICE_ATTR(tx_power, 0644, il4965_show_tx_power,
46227ac9a364SKalle Valo il4965_store_tx_power);
46237ac9a364SKalle Valo
46247ac9a364SKalle Valo static struct attribute *il_sysfs_entries[] = {
46257ac9a364SKalle Valo &dev_attr_temperature.attr,
46267ac9a364SKalle Valo &dev_attr_tx_power.attr,
46277ac9a364SKalle Valo #ifdef CONFIG_IWLEGACY_DEBUG
46287ac9a364SKalle Valo &dev_attr_debug_level.attr,
46297ac9a364SKalle Valo #endif
46307ac9a364SKalle Valo NULL
46317ac9a364SKalle Valo };
46327ac9a364SKalle Valo
46336cbbd7ecSArvind Yadav static const struct attribute_group il_attribute_group = {
46347ac9a364SKalle Valo .name = NULL, /* put in device directory */
46357ac9a364SKalle Valo .attrs = il_sysfs_entries,
46367ac9a364SKalle Valo };
46377ac9a364SKalle Valo
46387ac9a364SKalle Valo /******************************************************************************
46397ac9a364SKalle Valo *
46407ac9a364SKalle Valo * uCode download functions
46417ac9a364SKalle Valo *
46427ac9a364SKalle Valo ******************************************************************************/
46437ac9a364SKalle Valo
46447ac9a364SKalle Valo static void
il4965_dealloc_ucode_pci(struct il_priv * il)46457ac9a364SKalle Valo il4965_dealloc_ucode_pci(struct il_priv *il)
46467ac9a364SKalle Valo {
46477ac9a364SKalle Valo il_free_fw_desc(il->pci_dev, &il->ucode_code);
46487ac9a364SKalle Valo il_free_fw_desc(il->pci_dev, &il->ucode_data);
46497ac9a364SKalle Valo il_free_fw_desc(il->pci_dev, &il->ucode_data_backup);
46507ac9a364SKalle Valo il_free_fw_desc(il->pci_dev, &il->ucode_init);
46517ac9a364SKalle Valo il_free_fw_desc(il->pci_dev, &il->ucode_init_data);
46527ac9a364SKalle Valo il_free_fw_desc(il->pci_dev, &il->ucode_boot);
46537ac9a364SKalle Valo }
46547ac9a364SKalle Valo
46557ac9a364SKalle Valo static void
il4965_nic_start(struct il_priv * il)46567ac9a364SKalle Valo il4965_nic_start(struct il_priv *il)
46577ac9a364SKalle Valo {
46587ac9a364SKalle Valo /* Remove all resets to allow NIC to operate */
46597ac9a364SKalle Valo _il_wr(il, CSR_RESET, 0);
46607ac9a364SKalle Valo }
46617ac9a364SKalle Valo
46627ac9a364SKalle Valo static void il4965_ucode_callback(const struct firmware *ucode_raw,
46637ac9a364SKalle Valo void *context);
46647ac9a364SKalle Valo static int il4965_mac_setup_register(struct il_priv *il, u32 max_probe_length);
46657ac9a364SKalle Valo
46667ac9a364SKalle Valo static int __must_check
il4965_request_firmware(struct il_priv * il,bool first)46677ac9a364SKalle Valo il4965_request_firmware(struct il_priv *il, bool first)
46687ac9a364SKalle Valo {
46697ac9a364SKalle Valo const char *name_pre = il->cfg->fw_name_pre;
46707ac9a364SKalle Valo char tag[8];
46717ac9a364SKalle Valo
46727ac9a364SKalle Valo if (first) {
46737ac9a364SKalle Valo il->fw_idx = il->cfg->ucode_api_max;
46747ac9a364SKalle Valo sprintf(tag, "%d", il->fw_idx);
46757ac9a364SKalle Valo } else {
46767ac9a364SKalle Valo il->fw_idx--;
46777ac9a364SKalle Valo sprintf(tag, "%d", il->fw_idx);
46787ac9a364SKalle Valo }
46797ac9a364SKalle Valo
46807ac9a364SKalle Valo if (il->fw_idx < il->cfg->ucode_api_min) {
46817ac9a364SKalle Valo IL_ERR("no suitable firmware found!\n");
46827ac9a364SKalle Valo return -ENOENT;
46837ac9a364SKalle Valo }
46847ac9a364SKalle Valo
46857ac9a364SKalle Valo sprintf(il->firmware_name, "%s%s%s", name_pre, tag, ".ucode");
46867ac9a364SKalle Valo
46877ac9a364SKalle Valo D_INFO("attempting to load firmware '%s'\n", il->firmware_name);
46887ac9a364SKalle Valo
46897ac9a364SKalle Valo return request_firmware_nowait(THIS_MODULE, 1, il->firmware_name,
46907ac9a364SKalle Valo &il->pci_dev->dev, GFP_KERNEL, il,
46917ac9a364SKalle Valo il4965_ucode_callback);
46927ac9a364SKalle Valo }
46937ac9a364SKalle Valo
46947ac9a364SKalle Valo struct il4965_firmware_pieces {
46957ac9a364SKalle Valo const void *inst, *data, *init, *init_data, *boot;
46967ac9a364SKalle Valo size_t inst_size, data_size, init_size, init_data_size, boot_size;
46977ac9a364SKalle Valo };
46987ac9a364SKalle Valo
46997ac9a364SKalle Valo static int
il4965_load_firmware(struct il_priv * il,const struct firmware * ucode_raw,struct il4965_firmware_pieces * pieces)47007ac9a364SKalle Valo il4965_load_firmware(struct il_priv *il, const struct firmware *ucode_raw,
47017ac9a364SKalle Valo struct il4965_firmware_pieces *pieces)
47027ac9a364SKalle Valo {
47037ac9a364SKalle Valo struct il_ucode_header *ucode = (void *)ucode_raw->data;
47047ac9a364SKalle Valo u32 api_ver, hdr_size;
47057ac9a364SKalle Valo const u8 *src;
47067ac9a364SKalle Valo
47077ac9a364SKalle Valo il->ucode_ver = le32_to_cpu(ucode->ver);
47087ac9a364SKalle Valo api_ver = IL_UCODE_API(il->ucode_ver);
47097ac9a364SKalle Valo
47107ac9a364SKalle Valo switch (api_ver) {
47117ac9a364SKalle Valo default:
47127ac9a364SKalle Valo case 0:
47137ac9a364SKalle Valo case 1:
47147ac9a364SKalle Valo case 2:
47157ac9a364SKalle Valo hdr_size = 24;
47167ac9a364SKalle Valo if (ucode_raw->size < hdr_size) {
47177ac9a364SKalle Valo IL_ERR("File size too small!\n");
47187ac9a364SKalle Valo return -EINVAL;
47197ac9a364SKalle Valo }
47207ac9a364SKalle Valo pieces->inst_size = le32_to_cpu(ucode->v1.inst_size);
47217ac9a364SKalle Valo pieces->data_size = le32_to_cpu(ucode->v1.data_size);
47227ac9a364SKalle Valo pieces->init_size = le32_to_cpu(ucode->v1.init_size);
47237ac9a364SKalle Valo pieces->init_data_size = le32_to_cpu(ucode->v1.init_data_size);
47247ac9a364SKalle Valo pieces->boot_size = le32_to_cpu(ucode->v1.boot_size);
47257ac9a364SKalle Valo src = ucode->v1.data;
47267ac9a364SKalle Valo break;
47277ac9a364SKalle Valo }
47287ac9a364SKalle Valo
47297ac9a364SKalle Valo /* Verify size of file vs. image size info in file's header */
47307ac9a364SKalle Valo if (ucode_raw->size !=
47317ac9a364SKalle Valo hdr_size + pieces->inst_size + pieces->data_size +
47327ac9a364SKalle Valo pieces->init_size + pieces->init_data_size + pieces->boot_size) {
47337ac9a364SKalle Valo
47347ac9a364SKalle Valo IL_ERR("uCode file size %d does not match expected size\n",
47357ac9a364SKalle Valo (int)ucode_raw->size);
47367ac9a364SKalle Valo return -EINVAL;
47377ac9a364SKalle Valo }
47387ac9a364SKalle Valo
47397ac9a364SKalle Valo pieces->inst = src;
47407ac9a364SKalle Valo src += pieces->inst_size;
47417ac9a364SKalle Valo pieces->data = src;
47427ac9a364SKalle Valo src += pieces->data_size;
47437ac9a364SKalle Valo pieces->init = src;
47447ac9a364SKalle Valo src += pieces->init_size;
47457ac9a364SKalle Valo pieces->init_data = src;
47467ac9a364SKalle Valo src += pieces->init_data_size;
47477ac9a364SKalle Valo pieces->boot = src;
47487ac9a364SKalle Valo src += pieces->boot_size;
47497ac9a364SKalle Valo
47507ac9a364SKalle Valo return 0;
47517ac9a364SKalle Valo }
47527ac9a364SKalle Valo
475335b7fbfcSLee Jones /*
47547ac9a364SKalle Valo * il4965_ucode_callback - callback when firmware was loaded
47557ac9a364SKalle Valo *
47567ac9a364SKalle Valo * If loaded successfully, copies the firmware into buffers
47577ac9a364SKalle Valo * for the card to fetch (via DMA).
47587ac9a364SKalle Valo */
47597ac9a364SKalle Valo static void
il4965_ucode_callback(const struct firmware * ucode_raw,void * context)47607ac9a364SKalle Valo il4965_ucode_callback(const struct firmware *ucode_raw, void *context)
47617ac9a364SKalle Valo {
47627ac9a364SKalle Valo struct il_priv *il = context;
47637ac9a364SKalle Valo int err;
47647ac9a364SKalle Valo struct il4965_firmware_pieces pieces;
47657ac9a364SKalle Valo const unsigned int api_max = il->cfg->ucode_api_max;
47667ac9a364SKalle Valo const unsigned int api_min = il->cfg->ucode_api_min;
47677ac9a364SKalle Valo u32 api_ver;
47687ac9a364SKalle Valo
47697ac9a364SKalle Valo u32 max_probe_length = 200;
47707ac9a364SKalle Valo u32 standard_phy_calibration_size =
47717ac9a364SKalle Valo IL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE;
47727ac9a364SKalle Valo
47737ac9a364SKalle Valo memset(&pieces, 0, sizeof(pieces));
47747ac9a364SKalle Valo
47757ac9a364SKalle Valo if (!ucode_raw) {
47767ac9a364SKalle Valo if (il->fw_idx <= il->cfg->ucode_api_max)
47777ac9a364SKalle Valo IL_ERR("request for firmware file '%s' failed.\n",
47787ac9a364SKalle Valo il->firmware_name);
47797ac9a364SKalle Valo goto try_again;
47807ac9a364SKalle Valo }
47817ac9a364SKalle Valo
47827ac9a364SKalle Valo D_INFO("Loaded firmware file '%s' (%zd bytes).\n", il->firmware_name,
47837ac9a364SKalle Valo ucode_raw->size);
47847ac9a364SKalle Valo
47857ac9a364SKalle Valo /* Make sure that we got at least the API version number */
47867ac9a364SKalle Valo if (ucode_raw->size < 4) {
47877ac9a364SKalle Valo IL_ERR("File size way too small!\n");
47887ac9a364SKalle Valo goto try_again;
47897ac9a364SKalle Valo }
47907ac9a364SKalle Valo
47917ac9a364SKalle Valo /* Data from ucode file: header followed by uCode images */
47927ac9a364SKalle Valo err = il4965_load_firmware(il, ucode_raw, &pieces);
47937ac9a364SKalle Valo
47947ac9a364SKalle Valo if (err)
47957ac9a364SKalle Valo goto try_again;
47967ac9a364SKalle Valo
47977ac9a364SKalle Valo api_ver = IL_UCODE_API(il->ucode_ver);
47987ac9a364SKalle Valo
47997ac9a364SKalle Valo /*
48007ac9a364SKalle Valo * api_ver should match the api version forming part of the
48017ac9a364SKalle Valo * firmware filename ... but we don't check for that and only rely
48027ac9a364SKalle Valo * on the API version read from firmware header from here on forward
48037ac9a364SKalle Valo */
48047ac9a364SKalle Valo if (api_ver < api_min || api_ver > api_max) {
48057ac9a364SKalle Valo IL_ERR("Driver unable to support your firmware API. "
48067ac9a364SKalle Valo "Driver supports v%u, firmware is v%u.\n", api_max,
48077ac9a364SKalle Valo api_ver);
48087ac9a364SKalle Valo goto try_again;
48097ac9a364SKalle Valo }
48107ac9a364SKalle Valo
48117ac9a364SKalle Valo if (api_ver != api_max)
48127ac9a364SKalle Valo IL_ERR("Firmware has old API version. Expected v%u, "
48137ac9a364SKalle Valo "got v%u. New firmware can be obtained "
48147ac9a364SKalle Valo "from http://www.intellinuxwireless.org.\n", api_max,
48157ac9a364SKalle Valo api_ver);
48167ac9a364SKalle Valo
48177ac9a364SKalle Valo IL_INFO("loaded firmware version %u.%u.%u.%u\n",
48187ac9a364SKalle Valo IL_UCODE_MAJOR(il->ucode_ver), IL_UCODE_MINOR(il->ucode_ver),
48197ac9a364SKalle Valo IL_UCODE_API(il->ucode_ver), IL_UCODE_SERIAL(il->ucode_ver));
48207ac9a364SKalle Valo
48217ac9a364SKalle Valo snprintf(il->hw->wiphy->fw_version, sizeof(il->hw->wiphy->fw_version),
48227ac9a364SKalle Valo "%u.%u.%u.%u", IL_UCODE_MAJOR(il->ucode_ver),
48237ac9a364SKalle Valo IL_UCODE_MINOR(il->ucode_ver), IL_UCODE_API(il->ucode_ver),
48247ac9a364SKalle Valo IL_UCODE_SERIAL(il->ucode_ver));
48257ac9a364SKalle Valo
48267ac9a364SKalle Valo /*
48277ac9a364SKalle Valo * For any of the failures below (before allocating pci memory)
48287ac9a364SKalle Valo * we will try to load a version with a smaller API -- maybe the
48297ac9a364SKalle Valo * user just got a corrupted version of the latest API.
48307ac9a364SKalle Valo */
48317ac9a364SKalle Valo
48327ac9a364SKalle Valo D_INFO("f/w package hdr ucode version raw = 0x%x\n", il->ucode_ver);
48335b5e0928SAlexey Dobriyan D_INFO("f/w package hdr runtime inst size = %zd\n", pieces.inst_size);
48345b5e0928SAlexey Dobriyan D_INFO("f/w package hdr runtime data size = %zd\n", pieces.data_size);
48355b5e0928SAlexey Dobriyan D_INFO("f/w package hdr init inst size = %zd\n", pieces.init_size);
48365b5e0928SAlexey Dobriyan D_INFO("f/w package hdr init data size = %zd\n", pieces.init_data_size);
48375b5e0928SAlexey Dobriyan D_INFO("f/w package hdr boot inst size = %zd\n", pieces.boot_size);
48387ac9a364SKalle Valo
48397ac9a364SKalle Valo /* Verify that uCode images will fit in card's SRAM */
48407ac9a364SKalle Valo if (pieces.inst_size > il->hw_params.max_inst_size) {
48415b5e0928SAlexey Dobriyan IL_ERR("uCode instr len %zd too large to fit in\n",
48427ac9a364SKalle Valo pieces.inst_size);
48437ac9a364SKalle Valo goto try_again;
48447ac9a364SKalle Valo }
48457ac9a364SKalle Valo
48467ac9a364SKalle Valo if (pieces.data_size > il->hw_params.max_data_size) {
48475b5e0928SAlexey Dobriyan IL_ERR("uCode data len %zd too large to fit in\n",
48487ac9a364SKalle Valo pieces.data_size);
48497ac9a364SKalle Valo goto try_again;
48507ac9a364SKalle Valo }
48517ac9a364SKalle Valo
48527ac9a364SKalle Valo if (pieces.init_size > il->hw_params.max_inst_size) {
48535b5e0928SAlexey Dobriyan IL_ERR("uCode init instr len %zd too large to fit in\n",
48547ac9a364SKalle Valo pieces.init_size);
48557ac9a364SKalle Valo goto try_again;
48567ac9a364SKalle Valo }
48577ac9a364SKalle Valo
48587ac9a364SKalle Valo if (pieces.init_data_size > il->hw_params.max_data_size) {
48595b5e0928SAlexey Dobriyan IL_ERR("uCode init data len %zd too large to fit in\n",
48607ac9a364SKalle Valo pieces.init_data_size);
48617ac9a364SKalle Valo goto try_again;
48627ac9a364SKalle Valo }
48637ac9a364SKalle Valo
48647ac9a364SKalle Valo if (pieces.boot_size > il->hw_params.max_bsm_size) {
48655b5e0928SAlexey Dobriyan IL_ERR("uCode boot instr len %zd too large to fit in\n",
48667ac9a364SKalle Valo pieces.boot_size);
48677ac9a364SKalle Valo goto try_again;
48687ac9a364SKalle Valo }
48697ac9a364SKalle Valo
48707ac9a364SKalle Valo /* Allocate ucode buffers for card's bus-master loading ... */
48717ac9a364SKalle Valo
48727ac9a364SKalle Valo /* Runtime instructions and 2 copies of data:
48737ac9a364SKalle Valo * 1) unmodified from disk
48747ac9a364SKalle Valo * 2) backup cache for save/restore during power-downs */
48757ac9a364SKalle Valo il->ucode_code.len = pieces.inst_size;
48767ac9a364SKalle Valo il_alloc_fw_desc(il->pci_dev, &il->ucode_code);
48777ac9a364SKalle Valo
48787ac9a364SKalle Valo il->ucode_data.len = pieces.data_size;
48797ac9a364SKalle Valo il_alloc_fw_desc(il->pci_dev, &il->ucode_data);
48807ac9a364SKalle Valo
48817ac9a364SKalle Valo il->ucode_data_backup.len = pieces.data_size;
48827ac9a364SKalle Valo il_alloc_fw_desc(il->pci_dev, &il->ucode_data_backup);
48837ac9a364SKalle Valo
48847ac9a364SKalle Valo if (!il->ucode_code.v_addr || !il->ucode_data.v_addr ||
48857ac9a364SKalle Valo !il->ucode_data_backup.v_addr)
48867ac9a364SKalle Valo goto err_pci_alloc;
48877ac9a364SKalle Valo
48887ac9a364SKalle Valo /* Initialization instructions and data */
48897ac9a364SKalle Valo if (pieces.init_size && pieces.init_data_size) {
48907ac9a364SKalle Valo il->ucode_init.len = pieces.init_size;
48917ac9a364SKalle Valo il_alloc_fw_desc(il->pci_dev, &il->ucode_init);
48927ac9a364SKalle Valo
48937ac9a364SKalle Valo il->ucode_init_data.len = pieces.init_data_size;
48947ac9a364SKalle Valo il_alloc_fw_desc(il->pci_dev, &il->ucode_init_data);
48957ac9a364SKalle Valo
48967ac9a364SKalle Valo if (!il->ucode_init.v_addr || !il->ucode_init_data.v_addr)
48977ac9a364SKalle Valo goto err_pci_alloc;
48987ac9a364SKalle Valo }
48997ac9a364SKalle Valo
49007ac9a364SKalle Valo /* Bootstrap (instructions only, no data) */
49017ac9a364SKalle Valo if (pieces.boot_size) {
49027ac9a364SKalle Valo il->ucode_boot.len = pieces.boot_size;
49037ac9a364SKalle Valo il_alloc_fw_desc(il->pci_dev, &il->ucode_boot);
49047ac9a364SKalle Valo
49057ac9a364SKalle Valo if (!il->ucode_boot.v_addr)
49067ac9a364SKalle Valo goto err_pci_alloc;
49077ac9a364SKalle Valo }
49087ac9a364SKalle Valo
49097ac9a364SKalle Valo /* Now that we can no longer fail, copy information */
49107ac9a364SKalle Valo
49117ac9a364SKalle Valo il->sta_key_max_num = STA_KEY_MAX_NUM;
49127ac9a364SKalle Valo
49137ac9a364SKalle Valo /* Copy images into buffers for card's bus-master reads ... */
49147ac9a364SKalle Valo
49157ac9a364SKalle Valo /* Runtime instructions (first block of data in file) */
49165b5e0928SAlexey Dobriyan D_INFO("Copying (but not loading) uCode instr len %zd\n",
49177ac9a364SKalle Valo pieces.inst_size);
49187ac9a364SKalle Valo memcpy(il->ucode_code.v_addr, pieces.inst, pieces.inst_size);
49197ac9a364SKalle Valo
49207ac9a364SKalle Valo D_INFO("uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n",
49217ac9a364SKalle Valo il->ucode_code.v_addr, (u32) il->ucode_code.p_addr);
49227ac9a364SKalle Valo
49237ac9a364SKalle Valo /*
49247ac9a364SKalle Valo * Runtime data
49257ac9a364SKalle Valo * NOTE: Copy into backup buffer will be done in il_up()
49267ac9a364SKalle Valo */
49275b5e0928SAlexey Dobriyan D_INFO("Copying (but not loading) uCode data len %zd\n",
49287ac9a364SKalle Valo pieces.data_size);
49297ac9a364SKalle Valo memcpy(il->ucode_data.v_addr, pieces.data, pieces.data_size);
49307ac9a364SKalle Valo memcpy(il->ucode_data_backup.v_addr, pieces.data, pieces.data_size);
49317ac9a364SKalle Valo
49327ac9a364SKalle Valo /* Initialization instructions */
49337ac9a364SKalle Valo if (pieces.init_size) {
49345b5e0928SAlexey Dobriyan D_INFO("Copying (but not loading) init instr len %zd\n",
49357ac9a364SKalle Valo pieces.init_size);
49367ac9a364SKalle Valo memcpy(il->ucode_init.v_addr, pieces.init, pieces.init_size);
49377ac9a364SKalle Valo }
49387ac9a364SKalle Valo
49397ac9a364SKalle Valo /* Initialization data */
49407ac9a364SKalle Valo if (pieces.init_data_size) {
49415b5e0928SAlexey Dobriyan D_INFO("Copying (but not loading) init data len %zd\n",
49427ac9a364SKalle Valo pieces.init_data_size);
49437ac9a364SKalle Valo memcpy(il->ucode_init_data.v_addr, pieces.init_data,
49447ac9a364SKalle Valo pieces.init_data_size);
49457ac9a364SKalle Valo }
49467ac9a364SKalle Valo
49477ac9a364SKalle Valo /* Bootstrap instructions */
49485b5e0928SAlexey Dobriyan D_INFO("Copying (but not loading) boot instr len %zd\n",
49497ac9a364SKalle Valo pieces.boot_size);
49507ac9a364SKalle Valo memcpy(il->ucode_boot.v_addr, pieces.boot, pieces.boot_size);
49517ac9a364SKalle Valo
49527ac9a364SKalle Valo /*
49537ac9a364SKalle Valo * figure out the offset of chain noise reset and gain commands
49547ac9a364SKalle Valo * base on the size of standard phy calibration commands table size
49557ac9a364SKalle Valo */
49567ac9a364SKalle Valo il->_4965.phy_calib_chain_noise_reset_cmd =
49577ac9a364SKalle Valo standard_phy_calibration_size;
49587ac9a364SKalle Valo il->_4965.phy_calib_chain_noise_gain_cmd =
49597ac9a364SKalle Valo standard_phy_calibration_size + 1;
49607ac9a364SKalle Valo
49617ac9a364SKalle Valo /**************************************************
49627ac9a364SKalle Valo * This is still part of probe() in a sense...
49637ac9a364SKalle Valo *
49647ac9a364SKalle Valo * 9. Setup and register with mac80211 and debugfs
49657ac9a364SKalle Valo **************************************************/
49667ac9a364SKalle Valo err = il4965_mac_setup_register(il, max_probe_length);
49677ac9a364SKalle Valo if (err)
49687ac9a364SKalle Valo goto out_unbind;
49697ac9a364SKalle Valo
497071ee1284SGreg Kroah-Hartman il_dbgfs_register(il, DRV_NAME);
49717ac9a364SKalle Valo
49727ac9a364SKalle Valo err = sysfs_create_group(&il->pci_dev->dev.kobj, &il_attribute_group);
49737ac9a364SKalle Valo if (err) {
49747ac9a364SKalle Valo IL_ERR("failed to create sysfs device attributes\n");
49757ac9a364SKalle Valo goto out_unbind;
49767ac9a364SKalle Valo }
49777ac9a364SKalle Valo
49787ac9a364SKalle Valo /* We have our copies now, allow OS release its copies */
49797ac9a364SKalle Valo release_firmware(ucode_raw);
49807ac9a364SKalle Valo complete(&il->_4965.firmware_loading_complete);
49817ac9a364SKalle Valo return;
49827ac9a364SKalle Valo
49837ac9a364SKalle Valo try_again:
49847ac9a364SKalle Valo /* try next, if any */
49857ac9a364SKalle Valo if (il4965_request_firmware(il, false))
49867ac9a364SKalle Valo goto out_unbind;
49877ac9a364SKalle Valo release_firmware(ucode_raw);
49887ac9a364SKalle Valo return;
49897ac9a364SKalle Valo
49907ac9a364SKalle Valo err_pci_alloc:
49917ac9a364SKalle Valo IL_ERR("failed to allocate pci memory\n");
49927ac9a364SKalle Valo il4965_dealloc_ucode_pci(il);
49937ac9a364SKalle Valo out_unbind:
49947ac9a364SKalle Valo complete(&il->_4965.firmware_loading_complete);
49957ac9a364SKalle Valo device_release_driver(&il->pci_dev->dev);
49967ac9a364SKalle Valo release_firmware(ucode_raw);
49977ac9a364SKalle Valo }
49987ac9a364SKalle Valo
49997ac9a364SKalle Valo static const char *const desc_lookup_text[] = {
50007ac9a364SKalle Valo "OK",
50017ac9a364SKalle Valo "FAIL",
50027ac9a364SKalle Valo "BAD_PARAM",
50037ac9a364SKalle Valo "BAD_CHECKSUM",
50047ac9a364SKalle Valo "NMI_INTERRUPT_WDG",
50057ac9a364SKalle Valo "SYSASSERT",
50067ac9a364SKalle Valo "FATAL_ERROR",
50077ac9a364SKalle Valo "BAD_COMMAND",
50087ac9a364SKalle Valo "HW_ERROR_TUNE_LOCK",
50097ac9a364SKalle Valo "HW_ERROR_TEMPERATURE",
50107ac9a364SKalle Valo "ILLEGAL_CHAN_FREQ",
50117ac9a364SKalle Valo "VCC_NOT_STBL",
50127ac9a364SKalle Valo "FH49_ERROR",
50137ac9a364SKalle Valo "NMI_INTERRUPT_HOST",
50147ac9a364SKalle Valo "NMI_INTERRUPT_ACTION_PT",
50157ac9a364SKalle Valo "NMI_INTERRUPT_UNKNOWN",
50167ac9a364SKalle Valo "UCODE_VERSION_MISMATCH",
50177ac9a364SKalle Valo "HW_ERROR_ABS_LOCK",
50187ac9a364SKalle Valo "HW_ERROR_CAL_LOCK_FAIL",
50197ac9a364SKalle Valo "NMI_INTERRUPT_INST_ACTION_PT",
50207ac9a364SKalle Valo "NMI_INTERRUPT_DATA_ACTION_PT",
50217ac9a364SKalle Valo "NMI_TRM_HW_ER",
50227ac9a364SKalle Valo "NMI_INTERRUPT_TRM",
50237ac9a364SKalle Valo "NMI_INTERRUPT_BREAK_POINT",
50247ac9a364SKalle Valo "DEBUG_0",
50257ac9a364SKalle Valo "DEBUG_1",
50267ac9a364SKalle Valo "DEBUG_2",
50277ac9a364SKalle Valo "DEBUG_3",
50287ac9a364SKalle Valo };
50297ac9a364SKalle Valo
50307ac9a364SKalle Valo static struct {
50317ac9a364SKalle Valo char *name;
50327ac9a364SKalle Valo u8 num;
50337ac9a364SKalle Valo } advanced_lookup[] = {
50347ac9a364SKalle Valo {
50357ac9a364SKalle Valo "NMI_INTERRUPT_WDG", 0x34}, {
50367ac9a364SKalle Valo "SYSASSERT", 0x35}, {
50377ac9a364SKalle Valo "UCODE_VERSION_MISMATCH", 0x37}, {
50387ac9a364SKalle Valo "BAD_COMMAND", 0x38}, {
50397ac9a364SKalle Valo "NMI_INTERRUPT_DATA_ACTION_PT", 0x3C}, {
50407ac9a364SKalle Valo "FATAL_ERROR", 0x3D}, {
50417ac9a364SKalle Valo "NMI_TRM_HW_ERR", 0x46}, {
50427ac9a364SKalle Valo "NMI_INTERRUPT_TRM", 0x4C}, {
50437ac9a364SKalle Valo "NMI_INTERRUPT_BREAK_POINT", 0x54}, {
50447ac9a364SKalle Valo "NMI_INTERRUPT_WDG_RXF_FULL", 0x5C}, {
50457ac9a364SKalle Valo "NMI_INTERRUPT_WDG_NO_RBD_RXF_FULL", 0x64}, {
50467ac9a364SKalle Valo "NMI_INTERRUPT_HOST", 0x66}, {
50477ac9a364SKalle Valo "NMI_INTERRUPT_ACTION_PT", 0x7C}, {
50487ac9a364SKalle Valo "NMI_INTERRUPT_UNKNOWN", 0x84}, {
50497ac9a364SKalle Valo "NMI_INTERRUPT_INST_ACTION_PT", 0x86}, {
50507ac9a364SKalle Valo "ADVANCED_SYSASSERT", 0},};
50517ac9a364SKalle Valo
50527ac9a364SKalle Valo static const char *
il4965_desc_lookup(u32 num)50537ac9a364SKalle Valo il4965_desc_lookup(u32 num)
50547ac9a364SKalle Valo {
50557ac9a364SKalle Valo int i;
50567ac9a364SKalle Valo int max = ARRAY_SIZE(desc_lookup_text);
50577ac9a364SKalle Valo
50587ac9a364SKalle Valo if (num < max)
50597ac9a364SKalle Valo return desc_lookup_text[num];
50607ac9a364SKalle Valo
50617ac9a364SKalle Valo max = ARRAY_SIZE(advanced_lookup) - 1;
50627ac9a364SKalle Valo for (i = 0; i < max; i++) {
50637ac9a364SKalle Valo if (advanced_lookup[i].num == num)
50647ac9a364SKalle Valo break;
50657ac9a364SKalle Valo }
50667ac9a364SKalle Valo return advanced_lookup[i].name;
50677ac9a364SKalle Valo }
50687ac9a364SKalle Valo
50697ac9a364SKalle Valo #define ERROR_START_OFFSET (1 * sizeof(u32))
50707ac9a364SKalle Valo #define ERROR_ELEM_SIZE (7 * sizeof(u32))
50717ac9a364SKalle Valo
50727ac9a364SKalle Valo void
il4965_dump_nic_error_log(struct il_priv * il)50737ac9a364SKalle Valo il4965_dump_nic_error_log(struct il_priv *il)
50747ac9a364SKalle Valo {
50757ac9a364SKalle Valo u32 data2, line;
50767ac9a364SKalle Valo u32 desc, time, count, base, data1;
50777ac9a364SKalle Valo u32 blink1, blink2, ilink1, ilink2;
50787ac9a364SKalle Valo u32 pc, hcmd;
50797ac9a364SKalle Valo
50807ac9a364SKalle Valo if (il->ucode_type == UCODE_INIT)
50817ac9a364SKalle Valo base = le32_to_cpu(il->card_alive_init.error_event_table_ptr);
50827ac9a364SKalle Valo else
50837ac9a364SKalle Valo base = le32_to_cpu(il->card_alive.error_event_table_ptr);
50847ac9a364SKalle Valo
50857ac9a364SKalle Valo if (!il->ops->is_valid_rtc_data_addr(base)) {
50867ac9a364SKalle Valo IL_ERR("Not valid error log pointer 0x%08X for %s uCode\n",
50877ac9a364SKalle Valo base, (il->ucode_type == UCODE_INIT) ? "Init" : "RT");
50887ac9a364SKalle Valo return;
50897ac9a364SKalle Valo }
50907ac9a364SKalle Valo
50917ac9a364SKalle Valo count = il_read_targ_mem(il, base);
50927ac9a364SKalle Valo
50937ac9a364SKalle Valo if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
50947ac9a364SKalle Valo IL_ERR("Start IWL Error Log Dump:\n");
50957ac9a364SKalle Valo IL_ERR("Status: 0x%08lX, count: %d\n", il->status, count);
50967ac9a364SKalle Valo }
50977ac9a364SKalle Valo
50987ac9a364SKalle Valo desc = il_read_targ_mem(il, base + 1 * sizeof(u32));
50997ac9a364SKalle Valo il->isr_stats.err_code = desc;
51007ac9a364SKalle Valo pc = il_read_targ_mem(il, base + 2 * sizeof(u32));
51017ac9a364SKalle Valo blink1 = il_read_targ_mem(il, base + 3 * sizeof(u32));
51027ac9a364SKalle Valo blink2 = il_read_targ_mem(il, base + 4 * sizeof(u32));
51037ac9a364SKalle Valo ilink1 = il_read_targ_mem(il, base + 5 * sizeof(u32));
51047ac9a364SKalle Valo ilink2 = il_read_targ_mem(il, base + 6 * sizeof(u32));
51057ac9a364SKalle Valo data1 = il_read_targ_mem(il, base + 7 * sizeof(u32));
51067ac9a364SKalle Valo data2 = il_read_targ_mem(il, base + 8 * sizeof(u32));
51077ac9a364SKalle Valo line = il_read_targ_mem(il, base + 9 * sizeof(u32));
51087ac9a364SKalle Valo time = il_read_targ_mem(il, base + 11 * sizeof(u32));
51097ac9a364SKalle Valo hcmd = il_read_targ_mem(il, base + 22 * sizeof(u32));
51107ac9a364SKalle Valo
51117ac9a364SKalle Valo IL_ERR("Desc Time "
51127ac9a364SKalle Valo "data1 data2 line\n");
51137ac9a364SKalle Valo IL_ERR("%-28s (0x%04X) %010u 0x%08X 0x%08X %u\n",
51147ac9a364SKalle Valo il4965_desc_lookup(desc), desc, time, data1, data2, line);
51157ac9a364SKalle Valo IL_ERR("pc blink1 blink2 ilink1 ilink2 hcmd\n");
51167ac9a364SKalle Valo IL_ERR("0x%05X 0x%05X 0x%05X 0x%05X 0x%05X 0x%05X\n", pc, blink1,
51177ac9a364SKalle Valo blink2, ilink1, ilink2, hcmd);
51187ac9a364SKalle Valo }
51197ac9a364SKalle Valo
51207ac9a364SKalle Valo static void
il4965_rf_kill_ct_config(struct il_priv * il)51217ac9a364SKalle Valo il4965_rf_kill_ct_config(struct il_priv *il)
51227ac9a364SKalle Valo {
51237ac9a364SKalle Valo struct il_ct_kill_config cmd;
51247ac9a364SKalle Valo unsigned long flags;
51257ac9a364SKalle Valo int ret = 0;
51267ac9a364SKalle Valo
51277ac9a364SKalle Valo spin_lock_irqsave(&il->lock, flags);
51287ac9a364SKalle Valo _il_wr(il, CSR_UCODE_DRV_GP1_CLR,
51297ac9a364SKalle Valo CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
51307ac9a364SKalle Valo spin_unlock_irqrestore(&il->lock, flags);
51317ac9a364SKalle Valo
51327ac9a364SKalle Valo cmd.critical_temperature_R =
51337ac9a364SKalle Valo cpu_to_le32(il->hw_params.ct_kill_threshold);
51347ac9a364SKalle Valo
51357ac9a364SKalle Valo ret = il_send_cmd_pdu(il, C_CT_KILL_CONFIG, sizeof(cmd), &cmd);
51367ac9a364SKalle Valo if (ret)
51377ac9a364SKalle Valo IL_ERR("C_CT_KILL_CONFIG failed\n");
51387ac9a364SKalle Valo else
51397ac9a364SKalle Valo D_INFO("C_CT_KILL_CONFIG " "succeeded, "
51407ac9a364SKalle Valo "critical temperature is %d\n",
51417ac9a364SKalle Valo il->hw_params.ct_kill_threshold);
51427ac9a364SKalle Valo }
51437ac9a364SKalle Valo
51447ac9a364SKalle Valo static const s8 default_queue_to_tx_fifo[] = {
51457ac9a364SKalle Valo IL_TX_FIFO_VO,
51467ac9a364SKalle Valo IL_TX_FIFO_VI,
51477ac9a364SKalle Valo IL_TX_FIFO_BE,
51487ac9a364SKalle Valo IL_TX_FIFO_BK,
51497ac9a364SKalle Valo IL49_CMD_FIFO_NUM,
51507ac9a364SKalle Valo IL_TX_FIFO_UNUSED,
51517ac9a364SKalle Valo IL_TX_FIFO_UNUSED,
51527ac9a364SKalle Valo };
51537ac9a364SKalle Valo
51547ac9a364SKalle Valo #define IL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo))))
51557ac9a364SKalle Valo
51567ac9a364SKalle Valo static int
il4965_alive_notify(struct il_priv * il)51577ac9a364SKalle Valo il4965_alive_notify(struct il_priv *il)
51587ac9a364SKalle Valo {
51597ac9a364SKalle Valo u32 a;
51607ac9a364SKalle Valo unsigned long flags;
51617ac9a364SKalle Valo int i, chan;
51627ac9a364SKalle Valo u32 reg_val;
51637ac9a364SKalle Valo
51647ac9a364SKalle Valo spin_lock_irqsave(&il->lock, flags);
51657ac9a364SKalle Valo
51667ac9a364SKalle Valo /* Clear 4965's internal Tx Scheduler data base */
51677ac9a364SKalle Valo il->scd_base_addr = il_rd_prph(il, IL49_SCD_SRAM_BASE_ADDR);
51687ac9a364SKalle Valo a = il->scd_base_addr + IL49_SCD_CONTEXT_DATA_OFFSET;
51697ac9a364SKalle Valo for (; a < il->scd_base_addr + IL49_SCD_TX_STTS_BITMAP_OFFSET; a += 4)
51707ac9a364SKalle Valo il_write_targ_mem(il, a, 0);
51717ac9a364SKalle Valo for (; a < il->scd_base_addr + IL49_SCD_TRANSLATE_TBL_OFFSET; a += 4)
51727ac9a364SKalle Valo il_write_targ_mem(il, a, 0);
51737ac9a364SKalle Valo for (;
51747ac9a364SKalle Valo a <
51757ac9a364SKalle Valo il->scd_base_addr +
51767ac9a364SKalle Valo IL49_SCD_TRANSLATE_TBL_OFFSET_QUEUE(il->hw_params.max_txq_num);
51777ac9a364SKalle Valo a += 4)
51787ac9a364SKalle Valo il_write_targ_mem(il, a, 0);
51797ac9a364SKalle Valo
51807ac9a364SKalle Valo /* Tel 4965 where to find Tx byte count tables */
51817ac9a364SKalle Valo il_wr_prph(il, IL49_SCD_DRAM_BASE_ADDR, il->scd_bc_tbls.dma >> 10);
51827ac9a364SKalle Valo
51837ac9a364SKalle Valo /* Enable DMA channel */
51847ac9a364SKalle Valo for (chan = 0; chan < FH49_TCSR_CHNL_NUM; chan++)
51857ac9a364SKalle Valo il_wr(il, FH49_TCSR_CHNL_TX_CONFIG_REG(chan),
51867ac9a364SKalle Valo FH49_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
51877ac9a364SKalle Valo FH49_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE);
51887ac9a364SKalle Valo
51897ac9a364SKalle Valo /* Update FH chicken bits */
51907ac9a364SKalle Valo reg_val = il_rd(il, FH49_TX_CHICKEN_BITS_REG);
51917ac9a364SKalle Valo il_wr(il, FH49_TX_CHICKEN_BITS_REG,
51927ac9a364SKalle Valo reg_val | FH49_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
51937ac9a364SKalle Valo
51947ac9a364SKalle Valo /* Disable chain mode for all queues */
51957ac9a364SKalle Valo il_wr_prph(il, IL49_SCD_QUEUECHAIN_SEL, 0);
51967ac9a364SKalle Valo
51977ac9a364SKalle Valo /* Initialize each Tx queue (including the command queue) */
51987ac9a364SKalle Valo for (i = 0; i < il->hw_params.max_txq_num; i++) {
51997ac9a364SKalle Valo
52007ac9a364SKalle Valo /* TFD circular buffer read/write idxes */
52017ac9a364SKalle Valo il_wr_prph(il, IL49_SCD_QUEUE_RDPTR(i), 0);
52027ac9a364SKalle Valo il_wr(il, HBUS_TARG_WRPTR, 0 | (i << 8));
52037ac9a364SKalle Valo
52047ac9a364SKalle Valo /* Max Tx Window size for Scheduler-ACK mode */
52057ac9a364SKalle Valo il_write_targ_mem(il,
52067ac9a364SKalle Valo il->scd_base_addr +
52077ac9a364SKalle Valo IL49_SCD_CONTEXT_QUEUE_OFFSET(i),
52087ac9a364SKalle Valo (SCD_WIN_SIZE <<
52097ac9a364SKalle Valo IL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_POS) &
52107ac9a364SKalle Valo IL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK);
52117ac9a364SKalle Valo
52127ac9a364SKalle Valo /* Frame limit */
52137ac9a364SKalle Valo il_write_targ_mem(il,
52147ac9a364SKalle Valo il->scd_base_addr +
52157ac9a364SKalle Valo IL49_SCD_CONTEXT_QUEUE_OFFSET(i) +
52167ac9a364SKalle Valo sizeof(u32),
52177ac9a364SKalle Valo (SCD_FRAME_LIMIT <<
52187ac9a364SKalle Valo IL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
52197ac9a364SKalle Valo IL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK);
52207ac9a364SKalle Valo
52217ac9a364SKalle Valo }
52227ac9a364SKalle Valo il_wr_prph(il, IL49_SCD_INTERRUPT_MASK,
52237ac9a364SKalle Valo (1 << il->hw_params.max_txq_num) - 1);
52247ac9a364SKalle Valo
52257ac9a364SKalle Valo /* Activate all Tx DMA/FIFO channels */
52267ac9a364SKalle Valo il4965_txq_set_sched(il, IL_MASK(0, 6));
52277ac9a364SKalle Valo
52287ac9a364SKalle Valo il4965_set_wr_ptrs(il, IL_DEFAULT_CMD_QUEUE_NUM, 0);
52297ac9a364SKalle Valo
52307ac9a364SKalle Valo /* make sure all queue are not stopped */
52317ac9a364SKalle Valo memset(&il->queue_stopped[0], 0, sizeof(il->queue_stopped));
52327ac9a364SKalle Valo for (i = 0; i < 4; i++)
52337ac9a364SKalle Valo atomic_set(&il->queue_stop_count[i], 0);
52347ac9a364SKalle Valo
52357ac9a364SKalle Valo /* reset to 0 to enable all the queue first */
52367ac9a364SKalle Valo il->txq_ctx_active_msk = 0;
52377ac9a364SKalle Valo /* Map each Tx/cmd queue to its corresponding fifo */
52387ac9a364SKalle Valo BUILD_BUG_ON(ARRAY_SIZE(default_queue_to_tx_fifo) != 7);
52397ac9a364SKalle Valo
52407ac9a364SKalle Valo for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) {
52417ac9a364SKalle Valo int ac = default_queue_to_tx_fifo[i];
52427ac9a364SKalle Valo
52437ac9a364SKalle Valo il_txq_ctx_activate(il, i);
52447ac9a364SKalle Valo
52457ac9a364SKalle Valo if (ac == IL_TX_FIFO_UNUSED)
52467ac9a364SKalle Valo continue;
52477ac9a364SKalle Valo
52487ac9a364SKalle Valo il4965_tx_queue_set_status(il, &il->txq[i], ac, 0);
52497ac9a364SKalle Valo }
52507ac9a364SKalle Valo
52517ac9a364SKalle Valo spin_unlock_irqrestore(&il->lock, flags);
52527ac9a364SKalle Valo
52537ac9a364SKalle Valo return 0;
52547ac9a364SKalle Valo }
52557ac9a364SKalle Valo
525635b7fbfcSLee Jones /*
52577ac9a364SKalle Valo * il4965_alive_start - called after N_ALIVE notification received
52587ac9a364SKalle Valo * from protocol/runtime uCode (initialization uCode's
52597ac9a364SKalle Valo * Alive gets handled by il_init_alive_start()).
52607ac9a364SKalle Valo */
52617ac9a364SKalle Valo static void
il4965_alive_start(struct il_priv * il)52627ac9a364SKalle Valo il4965_alive_start(struct il_priv *il)
52637ac9a364SKalle Valo {
52647ac9a364SKalle Valo int ret = 0;
52657ac9a364SKalle Valo
52667ac9a364SKalle Valo D_INFO("Runtime Alive received.\n");
52677ac9a364SKalle Valo
52687ac9a364SKalle Valo if (il->card_alive.is_valid != UCODE_VALID_OK) {
52697ac9a364SKalle Valo /* We had an error bringing up the hardware, so take it
52707ac9a364SKalle Valo * all the way back down so we can try again */
52717ac9a364SKalle Valo D_INFO("Alive failed.\n");
52727ac9a364SKalle Valo goto restart;
52737ac9a364SKalle Valo }
52747ac9a364SKalle Valo
52757ac9a364SKalle Valo /* Initialize uCode has loaded Runtime uCode ... verify inst image.
52767ac9a364SKalle Valo * This is a paranoid check, because we would not have gotten the
52777ac9a364SKalle Valo * "runtime" alive if code weren't properly loaded. */
52787ac9a364SKalle Valo if (il4965_verify_ucode(il)) {
52797ac9a364SKalle Valo /* Runtime instruction load was bad;
52807ac9a364SKalle Valo * take it all the way back down so we can try again */
52817ac9a364SKalle Valo D_INFO("Bad runtime uCode load.\n");
52827ac9a364SKalle Valo goto restart;
52837ac9a364SKalle Valo }
52847ac9a364SKalle Valo
52857ac9a364SKalle Valo ret = il4965_alive_notify(il);
52867ac9a364SKalle Valo if (ret) {
52877ac9a364SKalle Valo IL_WARN("Could not complete ALIVE transition [ntf]: %d\n", ret);
52887ac9a364SKalle Valo goto restart;
52897ac9a364SKalle Valo }
52907ac9a364SKalle Valo
52917ac9a364SKalle Valo /* After the ALIVE response, we can send host commands to the uCode */
52927ac9a364SKalle Valo set_bit(S_ALIVE, &il->status);
52937ac9a364SKalle Valo
52947ac9a364SKalle Valo /* Enable watchdog to monitor the driver tx queues */
52957ac9a364SKalle Valo il_setup_watchdog(il);
52967ac9a364SKalle Valo
52977ac9a364SKalle Valo if (il_is_rfkill(il))
52987ac9a364SKalle Valo return;
52997ac9a364SKalle Valo
53007ac9a364SKalle Valo ieee80211_wake_queues(il->hw);
53017ac9a364SKalle Valo
53027ac9a364SKalle Valo il->active_rate = RATES_MASK;
53037ac9a364SKalle Valo
53047ac9a364SKalle Valo il_power_update_mode(il, true);
53057ac9a364SKalle Valo D_INFO("Updated power mode\n");
53067ac9a364SKalle Valo
53077ac9a364SKalle Valo if (il_is_associated(il)) {
53087ac9a364SKalle Valo struct il_rxon_cmd *active_rxon =
53097ac9a364SKalle Valo (struct il_rxon_cmd *)&il->active;
53107ac9a364SKalle Valo /* apply any changes in staging */
53117ac9a364SKalle Valo il->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
53127ac9a364SKalle Valo active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
53137ac9a364SKalle Valo } else {
53147ac9a364SKalle Valo /* Initialize our rx_config data */
53157ac9a364SKalle Valo il_connection_init_rx_config(il);
53167ac9a364SKalle Valo
53177ac9a364SKalle Valo if (il->ops->set_rxon_chain)
53187ac9a364SKalle Valo il->ops->set_rxon_chain(il);
53197ac9a364SKalle Valo }
53207ac9a364SKalle Valo
53217ac9a364SKalle Valo /* Configure bluetooth coexistence if enabled */
53227ac9a364SKalle Valo il_send_bt_config(il);
53237ac9a364SKalle Valo
53247ac9a364SKalle Valo il4965_reset_run_time_calib(il);
53257ac9a364SKalle Valo
53267ac9a364SKalle Valo set_bit(S_READY, &il->status);
53277ac9a364SKalle Valo
53287ac9a364SKalle Valo /* Configure the adapter for unassociated operation */
53297ac9a364SKalle Valo il_commit_rxon(il);
53307ac9a364SKalle Valo
53317ac9a364SKalle Valo /* At this point, the NIC is initialized and operational */
53327ac9a364SKalle Valo il4965_rf_kill_ct_config(il);
53337ac9a364SKalle Valo
53347ac9a364SKalle Valo D_INFO("ALIVE processing complete.\n");
53357ac9a364SKalle Valo wake_up(&il->wait_command_queue);
53367ac9a364SKalle Valo
53377ac9a364SKalle Valo return;
53387ac9a364SKalle Valo
53397ac9a364SKalle Valo restart:
53407ac9a364SKalle Valo queue_work(il->workqueue, &il->restart);
53417ac9a364SKalle Valo }
53427ac9a364SKalle Valo
53437ac9a364SKalle Valo static void il4965_cancel_deferred_work(struct il_priv *il);
53447ac9a364SKalle Valo
53457ac9a364SKalle Valo static void
__il4965_down(struct il_priv * il)53467ac9a364SKalle Valo __il4965_down(struct il_priv *il)
53477ac9a364SKalle Valo {
53487ac9a364SKalle Valo unsigned long flags;
53497ac9a364SKalle Valo int exit_pending;
53507ac9a364SKalle Valo
53517ac9a364SKalle Valo D_INFO(DRV_NAME " is going down\n");
53527ac9a364SKalle Valo
53537ac9a364SKalle Valo il_scan_cancel_timeout(il, 200);
53547ac9a364SKalle Valo
53557ac9a364SKalle Valo exit_pending = test_and_set_bit(S_EXIT_PENDING, &il->status);
53567ac9a364SKalle Valo
53577ac9a364SKalle Valo /* Stop TX queues watchdog. We need to have S_EXIT_PENDING bit set
53587ac9a364SKalle Valo * to prevent rearm timer */
53597ac9a364SKalle Valo del_timer_sync(&il->watchdog);
53607ac9a364SKalle Valo
53617ac9a364SKalle Valo il_clear_ucode_stations(il);
53627ac9a364SKalle Valo
53637ac9a364SKalle Valo /* FIXME: race conditions ? */
53647ac9a364SKalle Valo spin_lock_irq(&il->sta_lock);
53657ac9a364SKalle Valo /*
53667ac9a364SKalle Valo * Remove all key information that is not stored as part
53677ac9a364SKalle Valo * of station information since mac80211 may not have had
53687ac9a364SKalle Valo * a chance to remove all the keys. When device is
53697ac9a364SKalle Valo * reconfigured by mac80211 after an error all keys will
53707ac9a364SKalle Valo * be reconfigured.
53717ac9a364SKalle Valo */
53727ac9a364SKalle Valo memset(il->_4965.wep_keys, 0, sizeof(il->_4965.wep_keys));
53737ac9a364SKalle Valo il->_4965.key_mapping_keys = 0;
53747ac9a364SKalle Valo spin_unlock_irq(&il->sta_lock);
53757ac9a364SKalle Valo
53767ac9a364SKalle Valo il_dealloc_bcast_stations(il);
53777ac9a364SKalle Valo il_clear_driver_stations(il);
53787ac9a364SKalle Valo
53797ac9a364SKalle Valo /* Unblock any waiting calls */
53807ac9a364SKalle Valo wake_up_all(&il->wait_command_queue);
53817ac9a364SKalle Valo
53827ac9a364SKalle Valo /* Wipe out the EXIT_PENDING status bit if we are not actually
53837ac9a364SKalle Valo * exiting the module */
53847ac9a364SKalle Valo if (!exit_pending)
53857ac9a364SKalle Valo clear_bit(S_EXIT_PENDING, &il->status);
53867ac9a364SKalle Valo
53877ac9a364SKalle Valo /* stop and reset the on-board processor */
53887ac9a364SKalle Valo _il_wr(il, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
53897ac9a364SKalle Valo
53907ac9a364SKalle Valo /* tell the device to stop sending interrupts */
53917ac9a364SKalle Valo spin_lock_irqsave(&il->lock, flags);
53927ac9a364SKalle Valo il_disable_interrupts(il);
53937ac9a364SKalle Valo spin_unlock_irqrestore(&il->lock, flags);
53947ac9a364SKalle Valo il4965_synchronize_irq(il);
53957ac9a364SKalle Valo
53967ac9a364SKalle Valo if (il->mac80211_registered)
53977ac9a364SKalle Valo ieee80211_stop_queues(il->hw);
53987ac9a364SKalle Valo
53997ac9a364SKalle Valo /* If we have not previously called il_init() then
54007ac9a364SKalle Valo * clear all bits but the RF Kill bit and return */
54017ac9a364SKalle Valo if (!il_is_init(il)) {
54027ac9a364SKalle Valo il->status =
54037ac9a364SKalle Valo test_bit(S_RFKILL, &il->status) << S_RFKILL |
54047ac9a364SKalle Valo test_bit(S_GEO_CONFIGURED, &il->status) << S_GEO_CONFIGURED |
54057ac9a364SKalle Valo test_bit(S_EXIT_PENDING, &il->status) << S_EXIT_PENDING;
54067ac9a364SKalle Valo goto exit;
54077ac9a364SKalle Valo }
54087ac9a364SKalle Valo
54097ac9a364SKalle Valo /* ...otherwise clear out all the status bits but the RF Kill
54107ac9a364SKalle Valo * bit and continue taking the NIC down. */
54117ac9a364SKalle Valo il->status &=
54127ac9a364SKalle Valo test_bit(S_RFKILL, &il->status) << S_RFKILL |
54137ac9a364SKalle Valo test_bit(S_GEO_CONFIGURED, &il->status) << S_GEO_CONFIGURED |
54147ac9a364SKalle Valo test_bit(S_FW_ERROR, &il->status) << S_FW_ERROR |
54157ac9a364SKalle Valo test_bit(S_EXIT_PENDING, &il->status) << S_EXIT_PENDING;
54167ac9a364SKalle Valo
54177ac9a364SKalle Valo /*
54187ac9a364SKalle Valo * We disabled and synchronized interrupt, and priv->mutex is taken, so
54197ac9a364SKalle Valo * here is the only thread which will program device registers, but
54207ac9a364SKalle Valo * still have lockdep assertions, so we are taking reg_lock.
54217ac9a364SKalle Valo */
54227ac9a364SKalle Valo spin_lock_irq(&il->reg_lock);
54237ac9a364SKalle Valo /* FIXME: il_grab_nic_access if rfkill is off ? */
54247ac9a364SKalle Valo
54257ac9a364SKalle Valo il4965_txq_ctx_stop(il);
54267ac9a364SKalle Valo il4965_rxq_stop(il);
54277ac9a364SKalle Valo /* Power-down device's busmaster DMA clocks */
54287ac9a364SKalle Valo _il_wr_prph(il, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT);
54297ac9a364SKalle Valo udelay(5);
54307ac9a364SKalle Valo /* Make sure (redundant) we've released our request to stay awake */
54317ac9a364SKalle Valo _il_clear_bit(il, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
54327ac9a364SKalle Valo /* Stop the device, and put it in low power state */
54337ac9a364SKalle Valo _il_apm_stop(il);
54347ac9a364SKalle Valo
54357ac9a364SKalle Valo spin_unlock_irq(&il->reg_lock);
54367ac9a364SKalle Valo
54377ac9a364SKalle Valo il4965_txq_ctx_unmap(il);
54387ac9a364SKalle Valo exit:
54397ac9a364SKalle Valo memset(&il->card_alive, 0, sizeof(struct il_alive_resp));
54407ac9a364SKalle Valo
54417ac9a364SKalle Valo dev_kfree_skb(il->beacon_skb);
54427ac9a364SKalle Valo il->beacon_skb = NULL;
54437ac9a364SKalle Valo
54447ac9a364SKalle Valo /* clear out any free frames */
54457ac9a364SKalle Valo il4965_clear_free_frames(il);
54467ac9a364SKalle Valo }
54477ac9a364SKalle Valo
54487ac9a364SKalle Valo static void
il4965_down(struct il_priv * il)54497ac9a364SKalle Valo il4965_down(struct il_priv *il)
54507ac9a364SKalle Valo {
54517ac9a364SKalle Valo mutex_lock(&il->mutex);
54527ac9a364SKalle Valo __il4965_down(il);
54537ac9a364SKalle Valo mutex_unlock(&il->mutex);
54547ac9a364SKalle Valo
54557ac9a364SKalle Valo il4965_cancel_deferred_work(il);
54567ac9a364SKalle Valo }
54577ac9a364SKalle Valo
54587ac9a364SKalle Valo
54597ac9a364SKalle Valo static void
il4965_set_hw_ready(struct il_priv * il)54607ac9a364SKalle Valo il4965_set_hw_ready(struct il_priv *il)
54617ac9a364SKalle Valo {
54627ac9a364SKalle Valo int ret;
54637ac9a364SKalle Valo
54647ac9a364SKalle Valo il_set_bit(il, CSR_HW_IF_CONFIG_REG,
54657ac9a364SKalle Valo CSR_HW_IF_CONFIG_REG_BIT_NIC_READY);
54667ac9a364SKalle Valo
54677ac9a364SKalle Valo /* See if we got it */
54687ac9a364SKalle Valo ret = _il_poll_bit(il, CSR_HW_IF_CONFIG_REG,
54697ac9a364SKalle Valo CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
54707ac9a364SKalle Valo CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
54717ac9a364SKalle Valo 100);
54727ac9a364SKalle Valo if (ret >= 0)
54737ac9a364SKalle Valo il->hw_ready = true;
54747ac9a364SKalle Valo
54757ac9a364SKalle Valo D_INFO("hardware %s ready\n", (il->hw_ready) ? "" : "not");
54767ac9a364SKalle Valo }
54777ac9a364SKalle Valo
54787ac9a364SKalle Valo static void
il4965_prepare_card_hw(struct il_priv * il)54797ac9a364SKalle Valo il4965_prepare_card_hw(struct il_priv *il)
54807ac9a364SKalle Valo {
54817ac9a364SKalle Valo int ret;
54827ac9a364SKalle Valo
54837ac9a364SKalle Valo il->hw_ready = false;
54847ac9a364SKalle Valo
54857ac9a364SKalle Valo il4965_set_hw_ready(il);
54867ac9a364SKalle Valo if (il->hw_ready)
54877ac9a364SKalle Valo return;
54887ac9a364SKalle Valo
54897ac9a364SKalle Valo /* If HW is not ready, prepare the conditions to check again */
54907ac9a364SKalle Valo il_set_bit(il, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_PREPARE);
54917ac9a364SKalle Valo
54927ac9a364SKalle Valo ret =
54937ac9a364SKalle Valo _il_poll_bit(il, CSR_HW_IF_CONFIG_REG,
54947ac9a364SKalle Valo ~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE,
54957ac9a364SKalle Valo CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000);
54967ac9a364SKalle Valo
54977ac9a364SKalle Valo /* HW should be ready by now, check again. */
54987ac9a364SKalle Valo if (ret != -ETIMEDOUT)
54997ac9a364SKalle Valo il4965_set_hw_ready(il);
55007ac9a364SKalle Valo }
55017ac9a364SKalle Valo
55027ac9a364SKalle Valo #define MAX_HW_RESTARTS 5
55037ac9a364SKalle Valo
55047ac9a364SKalle Valo static int
__il4965_up(struct il_priv * il)55057ac9a364SKalle Valo __il4965_up(struct il_priv *il)
55067ac9a364SKalle Valo {
55077ac9a364SKalle Valo int i;
55087ac9a364SKalle Valo int ret;
55097ac9a364SKalle Valo
55107ac9a364SKalle Valo if (test_bit(S_EXIT_PENDING, &il->status)) {
55117ac9a364SKalle Valo IL_WARN("Exit pending; will not bring the NIC up\n");
55127ac9a364SKalle Valo return -EIO;
55137ac9a364SKalle Valo }
55147ac9a364SKalle Valo
55157ac9a364SKalle Valo if (!il->ucode_data_backup.v_addr || !il->ucode_data.v_addr) {
55167ac9a364SKalle Valo IL_ERR("ucode not available for device bringup\n");
55177ac9a364SKalle Valo return -EIO;
55187ac9a364SKalle Valo }
55197ac9a364SKalle Valo
55207ac9a364SKalle Valo ret = il4965_alloc_bcast_station(il);
55217ac9a364SKalle Valo if (ret) {
55227ac9a364SKalle Valo il_dealloc_bcast_stations(il);
55237ac9a364SKalle Valo return ret;
55247ac9a364SKalle Valo }
55257ac9a364SKalle Valo
55267ac9a364SKalle Valo il4965_prepare_card_hw(il);
55277ac9a364SKalle Valo if (!il->hw_ready) {
552884d17a2aSJulian Calaby il_dealloc_bcast_stations(il);
55297ac9a364SKalle Valo IL_ERR("HW not ready\n");
55307ac9a364SKalle Valo return -EIO;
55317ac9a364SKalle Valo }
55327ac9a364SKalle Valo
55337ac9a364SKalle Valo /* If platform's RF_KILL switch is NOT set to KILL */
55347ac9a364SKalle Valo if (_il_rd(il, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
55357ac9a364SKalle Valo clear_bit(S_RFKILL, &il->status);
55367ac9a364SKalle Valo else {
55377ac9a364SKalle Valo set_bit(S_RFKILL, &il->status);
55387ac9a364SKalle Valo wiphy_rfkill_set_hw_state(il->hw->wiphy, true);
55397ac9a364SKalle Valo
554084d17a2aSJulian Calaby il_dealloc_bcast_stations(il);
55417ac9a364SKalle Valo il_enable_rfkill_int(il);
55427ac9a364SKalle Valo IL_WARN("Radio disabled by HW RF Kill switch\n");
55437ac9a364SKalle Valo return 0;
55447ac9a364SKalle Valo }
55457ac9a364SKalle Valo
55467ac9a364SKalle Valo _il_wr(il, CSR_INT, 0xFFFFFFFF);
55477ac9a364SKalle Valo
55487ac9a364SKalle Valo /* must be initialised before il_hw_nic_init */
55497ac9a364SKalle Valo il->cmd_queue = IL_DEFAULT_CMD_QUEUE_NUM;
55507ac9a364SKalle Valo
55517ac9a364SKalle Valo ret = il4965_hw_nic_init(il);
55527ac9a364SKalle Valo if (ret) {
55537ac9a364SKalle Valo IL_ERR("Unable to init nic\n");
5554c2fd3446SJia-Ju Bai il_dealloc_bcast_stations(il);
55557ac9a364SKalle Valo return ret;
55567ac9a364SKalle Valo }
55577ac9a364SKalle Valo
55587ac9a364SKalle Valo /* make sure rfkill handshake bits are cleared */
55597ac9a364SKalle Valo _il_wr(il, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
55607ac9a364SKalle Valo _il_wr(il, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
55617ac9a364SKalle Valo
55627ac9a364SKalle Valo /* clear (again), then enable host interrupts */
55637ac9a364SKalle Valo _il_wr(il, CSR_INT, 0xFFFFFFFF);
55647ac9a364SKalle Valo il_enable_interrupts(il);
55657ac9a364SKalle Valo
55667ac9a364SKalle Valo /* really make sure rfkill handshake bits are cleared */
55677ac9a364SKalle Valo _il_wr(il, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
55687ac9a364SKalle Valo _il_wr(il, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
55697ac9a364SKalle Valo
55707ac9a364SKalle Valo /* Copy original ucode data image from disk into backup cache.
55717ac9a364SKalle Valo * This will be used to initialize the on-board processor's
55727ac9a364SKalle Valo * data SRAM for a clean start when the runtime program first loads. */
55737ac9a364SKalle Valo memcpy(il->ucode_data_backup.v_addr, il->ucode_data.v_addr,
55747ac9a364SKalle Valo il->ucode_data.len);
55757ac9a364SKalle Valo
55767ac9a364SKalle Valo for (i = 0; i < MAX_HW_RESTARTS; i++) {
55777ac9a364SKalle Valo
55787ac9a364SKalle Valo /* load bootstrap state machine,
55797ac9a364SKalle Valo * load bootstrap program into processor's memory,
55807ac9a364SKalle Valo * prepare to load the "initialize" uCode */
55817ac9a364SKalle Valo ret = il->ops->load_ucode(il);
55827ac9a364SKalle Valo
55837ac9a364SKalle Valo if (ret) {
55847ac9a364SKalle Valo IL_ERR("Unable to set up bootstrap uCode: %d\n", ret);
55857ac9a364SKalle Valo continue;
55867ac9a364SKalle Valo }
55877ac9a364SKalle Valo
55887ac9a364SKalle Valo /* start card; "initialize" will load runtime ucode */
55897ac9a364SKalle Valo il4965_nic_start(il);
55907ac9a364SKalle Valo
55917ac9a364SKalle Valo D_INFO(DRV_NAME " is coming up\n");
55927ac9a364SKalle Valo
55937ac9a364SKalle Valo return 0;
55947ac9a364SKalle Valo }
55957ac9a364SKalle Valo
55967ac9a364SKalle Valo set_bit(S_EXIT_PENDING, &il->status);
55977ac9a364SKalle Valo __il4965_down(il);
55987ac9a364SKalle Valo clear_bit(S_EXIT_PENDING, &il->status);
55997ac9a364SKalle Valo
56007ac9a364SKalle Valo /* tried to restart and config the device for as long as our
56017ac9a364SKalle Valo * patience could withstand */
56027ac9a364SKalle Valo IL_ERR("Unable to initialize device after %d attempts.\n", i);
56037ac9a364SKalle Valo return -EIO;
56047ac9a364SKalle Valo }
56057ac9a364SKalle Valo
56067ac9a364SKalle Valo /*****************************************************************************
56077ac9a364SKalle Valo *
56087ac9a364SKalle Valo * Workqueue callbacks
56097ac9a364SKalle Valo *
56107ac9a364SKalle Valo *****************************************************************************/
56117ac9a364SKalle Valo
56127ac9a364SKalle Valo static void
il4965_bg_init_alive_start(struct work_struct * data)56137ac9a364SKalle Valo il4965_bg_init_alive_start(struct work_struct *data)
56147ac9a364SKalle Valo {
56157ac9a364SKalle Valo struct il_priv *il =
56167ac9a364SKalle Valo container_of(data, struct il_priv, init_alive_start.work);
56177ac9a364SKalle Valo
56187ac9a364SKalle Valo mutex_lock(&il->mutex);
56197ac9a364SKalle Valo if (test_bit(S_EXIT_PENDING, &il->status))
56207ac9a364SKalle Valo goto out;
56217ac9a364SKalle Valo
56227ac9a364SKalle Valo il->ops->init_alive_start(il);
56237ac9a364SKalle Valo out:
56247ac9a364SKalle Valo mutex_unlock(&il->mutex);
56257ac9a364SKalle Valo }
56267ac9a364SKalle Valo
56277ac9a364SKalle Valo static void
il4965_bg_alive_start(struct work_struct * data)56287ac9a364SKalle Valo il4965_bg_alive_start(struct work_struct *data)
56297ac9a364SKalle Valo {
56307ac9a364SKalle Valo struct il_priv *il =
56317ac9a364SKalle Valo container_of(data, struct il_priv, alive_start.work);
56327ac9a364SKalle Valo
56337ac9a364SKalle Valo mutex_lock(&il->mutex);
56347ac9a364SKalle Valo if (test_bit(S_EXIT_PENDING, &il->status))
56357ac9a364SKalle Valo goto out;
56367ac9a364SKalle Valo
56377ac9a364SKalle Valo il4965_alive_start(il);
56387ac9a364SKalle Valo out:
56397ac9a364SKalle Valo mutex_unlock(&il->mutex);
56407ac9a364SKalle Valo }
56417ac9a364SKalle Valo
56427ac9a364SKalle Valo static void
il4965_bg_run_time_calib_work(struct work_struct * work)56437ac9a364SKalle Valo il4965_bg_run_time_calib_work(struct work_struct *work)
56447ac9a364SKalle Valo {
56457ac9a364SKalle Valo struct il_priv *il = container_of(work, struct il_priv,
56467ac9a364SKalle Valo run_time_calib_work);
56477ac9a364SKalle Valo
56487ac9a364SKalle Valo mutex_lock(&il->mutex);
56497ac9a364SKalle Valo
56507ac9a364SKalle Valo if (test_bit(S_EXIT_PENDING, &il->status) ||
56517ac9a364SKalle Valo test_bit(S_SCANNING, &il->status)) {
56527ac9a364SKalle Valo mutex_unlock(&il->mutex);
56537ac9a364SKalle Valo return;
56547ac9a364SKalle Valo }
56557ac9a364SKalle Valo
56567ac9a364SKalle Valo if (il->start_calib) {
56577ac9a364SKalle Valo il4965_chain_noise_calibration(il, (void *)&il->_4965.stats);
56587ac9a364SKalle Valo il4965_sensitivity_calibration(il, (void *)&il->_4965.stats);
56597ac9a364SKalle Valo }
56607ac9a364SKalle Valo
56617ac9a364SKalle Valo mutex_unlock(&il->mutex);
56627ac9a364SKalle Valo }
56637ac9a364SKalle Valo
56647ac9a364SKalle Valo static void
il4965_bg_restart(struct work_struct * data)56657ac9a364SKalle Valo il4965_bg_restart(struct work_struct *data)
56667ac9a364SKalle Valo {
56677ac9a364SKalle Valo struct il_priv *il = container_of(data, struct il_priv, restart);
56687ac9a364SKalle Valo
56697ac9a364SKalle Valo if (test_bit(S_EXIT_PENDING, &il->status))
56707ac9a364SKalle Valo return;
56717ac9a364SKalle Valo
56727ac9a364SKalle Valo if (test_and_clear_bit(S_FW_ERROR, &il->status)) {
56737ac9a364SKalle Valo mutex_lock(&il->mutex);
56747ac9a364SKalle Valo il->is_open = 0;
56757ac9a364SKalle Valo
56767ac9a364SKalle Valo __il4965_down(il);
56777ac9a364SKalle Valo
56787ac9a364SKalle Valo mutex_unlock(&il->mutex);
56797ac9a364SKalle Valo il4965_cancel_deferred_work(il);
56807ac9a364SKalle Valo ieee80211_restart_hw(il->hw);
56817ac9a364SKalle Valo } else {
56827ac9a364SKalle Valo il4965_down(il);
56837ac9a364SKalle Valo
56847ac9a364SKalle Valo mutex_lock(&il->mutex);
56857ac9a364SKalle Valo if (test_bit(S_EXIT_PENDING, &il->status)) {
56867ac9a364SKalle Valo mutex_unlock(&il->mutex);
56877ac9a364SKalle Valo return;
56887ac9a364SKalle Valo }
56897ac9a364SKalle Valo
56907ac9a364SKalle Valo __il4965_up(il);
56917ac9a364SKalle Valo mutex_unlock(&il->mutex);
56927ac9a364SKalle Valo }
56937ac9a364SKalle Valo }
56947ac9a364SKalle Valo
56957ac9a364SKalle Valo static void
il4965_bg_rx_replenish(struct work_struct * data)56967ac9a364SKalle Valo il4965_bg_rx_replenish(struct work_struct *data)
56977ac9a364SKalle Valo {
56987ac9a364SKalle Valo struct il_priv *il = container_of(data, struct il_priv, rx_replenish);
56997ac9a364SKalle Valo
57007ac9a364SKalle Valo if (test_bit(S_EXIT_PENDING, &il->status))
57017ac9a364SKalle Valo return;
57027ac9a364SKalle Valo
57037ac9a364SKalle Valo mutex_lock(&il->mutex);
57047ac9a364SKalle Valo il4965_rx_replenish(il);
57057ac9a364SKalle Valo mutex_unlock(&il->mutex);
57067ac9a364SKalle Valo }
57077ac9a364SKalle Valo
57087ac9a364SKalle Valo /*****************************************************************************
57097ac9a364SKalle Valo *
57107ac9a364SKalle Valo * mac80211 entry point functions
57117ac9a364SKalle Valo *
57127ac9a364SKalle Valo *****************************************************************************/
57137ac9a364SKalle Valo
57147ac9a364SKalle Valo #define UCODE_READY_TIMEOUT (4 * HZ)
57157ac9a364SKalle Valo
57167ac9a364SKalle Valo /*
57177ac9a364SKalle Valo * Not a mac80211 entry point function, but it fits in with all the
57187ac9a364SKalle Valo * other mac80211 functions grouped here.
57197ac9a364SKalle Valo */
57207ac9a364SKalle Valo static int
il4965_mac_setup_register(struct il_priv * il,u32 max_probe_length)57217ac9a364SKalle Valo il4965_mac_setup_register(struct il_priv *il, u32 max_probe_length)
57227ac9a364SKalle Valo {
57237ac9a364SKalle Valo int ret;
57247ac9a364SKalle Valo struct ieee80211_hw *hw = il->hw;
57257ac9a364SKalle Valo
57267ac9a364SKalle Valo hw->rate_control_algorithm = "iwl-4965-rs";
57277ac9a364SKalle Valo
57287ac9a364SKalle Valo /* Tell mac80211 our characteristics */
57297ac9a364SKalle Valo ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);
57307ac9a364SKalle Valo ieee80211_hw_set(hw, SUPPORTS_PS);
57317ac9a364SKalle Valo ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS);
57327ac9a364SKalle Valo ieee80211_hw_set(hw, SPECTRUM_MGMT);
57337ac9a364SKalle Valo ieee80211_hw_set(hw, NEED_DTIM_BEFORE_ASSOC);
57347ac9a364SKalle Valo ieee80211_hw_set(hw, SIGNAL_DBM);
57357ac9a364SKalle Valo ieee80211_hw_set(hw, AMPDU_AGGREGATION);
57367ac9a364SKalle Valo if (il->cfg->sku & IL_SKU_N)
57377ac9a364SKalle Valo hw->wiphy->features |= NL80211_FEATURE_DYNAMIC_SMPS |
57387ac9a364SKalle Valo NL80211_FEATURE_STATIC_SMPS;
57397ac9a364SKalle Valo
57407ac9a364SKalle Valo hw->sta_data_size = sizeof(struct il_station_priv);
57417ac9a364SKalle Valo hw->vif_data_size = sizeof(struct il_vif_priv);
57427ac9a364SKalle Valo
57437ac9a364SKalle Valo hw->wiphy->interface_modes =
57447ac9a364SKalle Valo BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC);
57457ac9a364SKalle Valo
57467ac9a364SKalle Valo hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
57477ac9a364SKalle Valo hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG |
57487ac9a364SKalle Valo REGULATORY_DISABLE_BEACON_HINTS;
57497ac9a364SKalle Valo
57507ac9a364SKalle Valo /*
57517ac9a364SKalle Valo * For now, disable PS by default because it affects
57527ac9a364SKalle Valo * RX performance significantly.
57537ac9a364SKalle Valo */
57547ac9a364SKalle Valo hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
57557ac9a364SKalle Valo
57567ac9a364SKalle Valo hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX;
57577ac9a364SKalle Valo /* we create the 802.11 header and a zero-length SSID element */
57587ac9a364SKalle Valo hw->wiphy->max_scan_ie_len = max_probe_length - 24 - 2;
57597ac9a364SKalle Valo
57607ac9a364SKalle Valo /* Default value; 4 EDCA QOS priorities */
57617ac9a364SKalle Valo hw->queues = 4;
57627ac9a364SKalle Valo
57637ac9a364SKalle Valo hw->max_listen_interval = IL_CONN_MAX_LISTEN_INTERVAL;
57647ac9a364SKalle Valo
576557fbcce3SJohannes Berg if (il->bands[NL80211_BAND_2GHZ].n_channels)
576657fbcce3SJohannes Berg il->hw->wiphy->bands[NL80211_BAND_2GHZ] =
576757fbcce3SJohannes Berg &il->bands[NL80211_BAND_2GHZ];
576857fbcce3SJohannes Berg if (il->bands[NL80211_BAND_5GHZ].n_channels)
576957fbcce3SJohannes Berg il->hw->wiphy->bands[NL80211_BAND_5GHZ] =
577057fbcce3SJohannes Berg &il->bands[NL80211_BAND_5GHZ];
57717ac9a364SKalle Valo
57727ac9a364SKalle Valo il_leds_init(il);
57737ac9a364SKalle Valo
5774ae44b502SAndrew Zaborowski wiphy_ext_feature_set(il->hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
5775ae44b502SAndrew Zaborowski
57767ac9a364SKalle Valo ret = ieee80211_register_hw(il->hw);
57777ac9a364SKalle Valo if (ret) {
57787ac9a364SKalle Valo IL_ERR("Failed to register hw (error %d)\n", ret);
57797ac9a364SKalle Valo return ret;
57807ac9a364SKalle Valo }
57817ac9a364SKalle Valo il->mac80211_registered = 1;
57827ac9a364SKalle Valo
57837ac9a364SKalle Valo return 0;
57847ac9a364SKalle Valo }
57857ac9a364SKalle Valo
57867ac9a364SKalle Valo int
il4965_mac_start(struct ieee80211_hw * hw)57877ac9a364SKalle Valo il4965_mac_start(struct ieee80211_hw *hw)
57887ac9a364SKalle Valo {
57897ac9a364SKalle Valo struct il_priv *il = hw->priv;
57907ac9a364SKalle Valo int ret;
57917ac9a364SKalle Valo
57927ac9a364SKalle Valo D_MAC80211("enter\n");
57937ac9a364SKalle Valo
57947ac9a364SKalle Valo /* we should be verifying the device is ready to be opened */
57957ac9a364SKalle Valo mutex_lock(&il->mutex);
57967ac9a364SKalle Valo ret = __il4965_up(il);
57977ac9a364SKalle Valo mutex_unlock(&il->mutex);
57987ac9a364SKalle Valo
57997ac9a364SKalle Valo if (ret)
58007ac9a364SKalle Valo return ret;
58017ac9a364SKalle Valo
58027ac9a364SKalle Valo if (il_is_rfkill(il))
58037ac9a364SKalle Valo goto out;
58047ac9a364SKalle Valo
58057ac9a364SKalle Valo D_INFO("Start UP work done.\n");
58067ac9a364SKalle Valo
58077ac9a364SKalle Valo /* Wait for START_ALIVE from Run Time ucode. Otherwise callbacks from
58087ac9a364SKalle Valo * mac80211 will not be run successfully. */
58097ac9a364SKalle Valo ret = wait_event_timeout(il->wait_command_queue,
58107ac9a364SKalle Valo test_bit(S_READY, &il->status),
58117ac9a364SKalle Valo UCODE_READY_TIMEOUT);
58127ac9a364SKalle Valo if (!ret) {
58137ac9a364SKalle Valo if (!test_bit(S_READY, &il->status)) {
58147ac9a364SKalle Valo IL_ERR("START_ALIVE timeout after %dms.\n",
58157ac9a364SKalle Valo jiffies_to_msecs(UCODE_READY_TIMEOUT));
58167ac9a364SKalle Valo return -ETIMEDOUT;
58177ac9a364SKalle Valo }
58187ac9a364SKalle Valo }
58197ac9a364SKalle Valo
58207ac9a364SKalle Valo il4965_led_enable(il);
58217ac9a364SKalle Valo
58227ac9a364SKalle Valo out:
58237ac9a364SKalle Valo il->is_open = 1;
58247ac9a364SKalle Valo D_MAC80211("leave\n");
58257ac9a364SKalle Valo return 0;
58267ac9a364SKalle Valo }
58277ac9a364SKalle Valo
58287ac9a364SKalle Valo void
il4965_mac_stop(struct ieee80211_hw * hw)58297ac9a364SKalle Valo il4965_mac_stop(struct ieee80211_hw *hw)
58307ac9a364SKalle Valo {
58317ac9a364SKalle Valo struct il_priv *il = hw->priv;
58327ac9a364SKalle Valo
58337ac9a364SKalle Valo D_MAC80211("enter\n");
58347ac9a364SKalle Valo
58357ac9a364SKalle Valo if (!il->is_open)
58367ac9a364SKalle Valo return;
58377ac9a364SKalle Valo
58387ac9a364SKalle Valo il->is_open = 0;
58397ac9a364SKalle Valo
58407ac9a364SKalle Valo il4965_down(il);
58417ac9a364SKalle Valo
58427ac9a364SKalle Valo flush_workqueue(il->workqueue);
58437ac9a364SKalle Valo
58447ac9a364SKalle Valo /* User space software may expect getting rfkill changes
58457ac9a364SKalle Valo * even if interface is down */
58467ac9a364SKalle Valo _il_wr(il, CSR_INT, 0xFFFFFFFF);
58477ac9a364SKalle Valo il_enable_rfkill_int(il);
58487ac9a364SKalle Valo
58497ac9a364SKalle Valo D_MAC80211("leave\n");
58507ac9a364SKalle Valo }
58517ac9a364SKalle Valo
58527ac9a364SKalle Valo void
il4965_mac_tx(struct ieee80211_hw * hw,struct ieee80211_tx_control * control,struct sk_buff * skb)58537ac9a364SKalle Valo il4965_mac_tx(struct ieee80211_hw *hw,
58547ac9a364SKalle Valo struct ieee80211_tx_control *control,
58557ac9a364SKalle Valo struct sk_buff *skb)
58567ac9a364SKalle Valo {
58577ac9a364SKalle Valo struct il_priv *il = hw->priv;
58587ac9a364SKalle Valo
58597ac9a364SKalle Valo D_MACDUMP("enter\n");
58607ac9a364SKalle Valo
58617ac9a364SKalle Valo D_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
58627ac9a364SKalle Valo ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate);
58637ac9a364SKalle Valo
58647ac9a364SKalle Valo if (il4965_tx_skb(il, control->sta, skb))
58657ac9a364SKalle Valo dev_kfree_skb_any(skb);
58667ac9a364SKalle Valo
58677ac9a364SKalle Valo D_MACDUMP("leave\n");
58687ac9a364SKalle Valo }
58697ac9a364SKalle Valo
58707ac9a364SKalle Valo void
il4965_mac_update_tkip_key(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_key_conf * keyconf,struct ieee80211_sta * sta,u32 iv32,u16 * phase1key)58717ac9a364SKalle Valo il4965_mac_update_tkip_key(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
58727ac9a364SKalle Valo struct ieee80211_key_conf *keyconf,
58737ac9a364SKalle Valo struct ieee80211_sta *sta, u32 iv32, u16 * phase1key)
58747ac9a364SKalle Valo {
58757ac9a364SKalle Valo struct il_priv *il = hw->priv;
58767ac9a364SKalle Valo
58777ac9a364SKalle Valo D_MAC80211("enter\n");
58787ac9a364SKalle Valo
58797ac9a364SKalle Valo il4965_update_tkip_key(il, keyconf, sta, iv32, phase1key);
58807ac9a364SKalle Valo
58817ac9a364SKalle Valo D_MAC80211("leave\n");
58827ac9a364SKalle Valo }
58837ac9a364SKalle Valo
58847ac9a364SKalle Valo int
il4965_mac_set_key(struct ieee80211_hw * hw,enum set_key_cmd cmd,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct ieee80211_key_conf * key)58857ac9a364SKalle Valo il4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
58867ac9a364SKalle Valo struct ieee80211_vif *vif, struct ieee80211_sta *sta,
58877ac9a364SKalle Valo struct ieee80211_key_conf *key)
58887ac9a364SKalle Valo {
58897ac9a364SKalle Valo struct il_priv *il = hw->priv;
58907ac9a364SKalle Valo int ret;
58917ac9a364SKalle Valo u8 sta_id;
58927ac9a364SKalle Valo bool is_default_wep_key = false;
58937ac9a364SKalle Valo
58947ac9a364SKalle Valo D_MAC80211("enter\n");
58957ac9a364SKalle Valo
58967ac9a364SKalle Valo if (il->cfg->mod_params->sw_crypto) {
58977ac9a364SKalle Valo D_MAC80211("leave - hwcrypto disabled\n");
58987ac9a364SKalle Valo return -EOPNOTSUPP;
58997ac9a364SKalle Valo }
59007ac9a364SKalle Valo
59017ac9a364SKalle Valo /*
59027ac9a364SKalle Valo * To support IBSS RSN, don't program group keys in IBSS, the
59037ac9a364SKalle Valo * hardware will then not attempt to decrypt the frames.
59047ac9a364SKalle Valo */
59057ac9a364SKalle Valo if (vif->type == NL80211_IFTYPE_ADHOC &&
59067ac9a364SKalle Valo !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
59077ac9a364SKalle Valo D_MAC80211("leave - ad-hoc group key\n");
59087ac9a364SKalle Valo return -EOPNOTSUPP;
59097ac9a364SKalle Valo }
59107ac9a364SKalle Valo
59117ac9a364SKalle Valo sta_id = il_sta_id_or_broadcast(il, sta);
59127ac9a364SKalle Valo if (sta_id == IL_INVALID_STATION)
59137ac9a364SKalle Valo return -EINVAL;
59147ac9a364SKalle Valo
59157ac9a364SKalle Valo mutex_lock(&il->mutex);
59167ac9a364SKalle Valo il_scan_cancel_timeout(il, 100);
59177ac9a364SKalle Valo
59187ac9a364SKalle Valo /*
59197ac9a364SKalle Valo * If we are getting WEP group key and we didn't receive any key mapping
59207ac9a364SKalle Valo * so far, we are in legacy wep mode (group key only), otherwise we are
59217ac9a364SKalle Valo * in 1X mode.
59227ac9a364SKalle Valo * In legacy wep mode, we use another host command to the uCode.
59237ac9a364SKalle Valo */
59247ac9a364SKalle Valo if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
59257ac9a364SKalle Valo key->cipher == WLAN_CIPHER_SUITE_WEP104) && !sta) {
59267ac9a364SKalle Valo if (cmd == SET_KEY)
59277ac9a364SKalle Valo is_default_wep_key = !il->_4965.key_mapping_keys;
59287ac9a364SKalle Valo else
59297ac9a364SKalle Valo is_default_wep_key =
59307ac9a364SKalle Valo (key->hw_key_idx == HW_KEY_DEFAULT);
59317ac9a364SKalle Valo }
59327ac9a364SKalle Valo
59337ac9a364SKalle Valo switch (cmd) {
59347ac9a364SKalle Valo case SET_KEY:
59357ac9a364SKalle Valo if (is_default_wep_key)
59367ac9a364SKalle Valo ret = il4965_set_default_wep_key(il, key);
59377ac9a364SKalle Valo else
59387ac9a364SKalle Valo ret = il4965_set_dynamic_key(il, key, sta_id);
59397ac9a364SKalle Valo
59407ac9a364SKalle Valo D_MAC80211("enable hwcrypto key\n");
59417ac9a364SKalle Valo break;
59427ac9a364SKalle Valo case DISABLE_KEY:
59437ac9a364SKalle Valo if (is_default_wep_key)
59447ac9a364SKalle Valo ret = il4965_remove_default_wep_key(il, key);
59457ac9a364SKalle Valo else
59467ac9a364SKalle Valo ret = il4965_remove_dynamic_key(il, key, sta_id);
59477ac9a364SKalle Valo
59487ac9a364SKalle Valo D_MAC80211("disable hwcrypto key\n");
59497ac9a364SKalle Valo break;
59507ac9a364SKalle Valo default:
59517ac9a364SKalle Valo ret = -EINVAL;
59527ac9a364SKalle Valo }
59537ac9a364SKalle Valo
59547ac9a364SKalle Valo mutex_unlock(&il->mutex);
59557ac9a364SKalle Valo D_MAC80211("leave\n");
59567ac9a364SKalle Valo
59577ac9a364SKalle Valo return ret;
59587ac9a364SKalle Valo }
59597ac9a364SKalle Valo
59607ac9a364SKalle Valo int
il4965_mac_ampdu_action(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_ampdu_params * params)59617ac9a364SKalle Valo il4965_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
596250ea05efSSara Sharon struct ieee80211_ampdu_params *params)
59637ac9a364SKalle Valo {
59647ac9a364SKalle Valo struct il_priv *il = hw->priv;
59657ac9a364SKalle Valo int ret = -EINVAL;
596650ea05efSSara Sharon struct ieee80211_sta *sta = params->sta;
596750ea05efSSara Sharon enum ieee80211_ampdu_mlme_action action = params->action;
596850ea05efSSara Sharon u16 tid = params->tid;
596950ea05efSSara Sharon u16 *ssn = ¶ms->ssn;
59707ac9a364SKalle Valo
59717ac9a364SKalle Valo D_HT("A-MPDU action on addr %pM tid %d\n", sta->addr, tid);
59727ac9a364SKalle Valo
59737ac9a364SKalle Valo if (!(il->cfg->sku & IL_SKU_N))
59747ac9a364SKalle Valo return -EACCES;
59757ac9a364SKalle Valo
59767ac9a364SKalle Valo mutex_lock(&il->mutex);
59777ac9a364SKalle Valo
59787ac9a364SKalle Valo switch (action) {
59797ac9a364SKalle Valo case IEEE80211_AMPDU_RX_START:
59807ac9a364SKalle Valo D_HT("start Rx\n");
59817ac9a364SKalle Valo ret = il4965_sta_rx_agg_start(il, sta, tid, *ssn);
59827ac9a364SKalle Valo break;
59837ac9a364SKalle Valo case IEEE80211_AMPDU_RX_STOP:
59847ac9a364SKalle Valo D_HT("stop Rx\n");
59857ac9a364SKalle Valo ret = il4965_sta_rx_agg_stop(il, sta, tid);
59867ac9a364SKalle Valo if (test_bit(S_EXIT_PENDING, &il->status))
59877ac9a364SKalle Valo ret = 0;
59887ac9a364SKalle Valo break;
59897ac9a364SKalle Valo case IEEE80211_AMPDU_TX_START:
59907ac9a364SKalle Valo D_HT("start Tx\n");
59917ac9a364SKalle Valo ret = il4965_tx_agg_start(il, vif, sta, tid, ssn);
59927ac9a364SKalle Valo break;
59937ac9a364SKalle Valo case IEEE80211_AMPDU_TX_STOP_CONT:
59947ac9a364SKalle Valo case IEEE80211_AMPDU_TX_STOP_FLUSH:
59957ac9a364SKalle Valo case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
59967ac9a364SKalle Valo D_HT("stop Tx\n");
59977ac9a364SKalle Valo ret = il4965_tx_agg_stop(il, vif, sta, tid);
59987ac9a364SKalle Valo if (test_bit(S_EXIT_PENDING, &il->status))
59997ac9a364SKalle Valo ret = 0;
60007ac9a364SKalle Valo break;
60017ac9a364SKalle Valo case IEEE80211_AMPDU_TX_OPERATIONAL:
60027ac9a364SKalle Valo ret = 0;
60037ac9a364SKalle Valo break;
60047ac9a364SKalle Valo }
60057ac9a364SKalle Valo mutex_unlock(&il->mutex);
60067ac9a364SKalle Valo
60077ac9a364SKalle Valo return ret;
60087ac9a364SKalle Valo }
60097ac9a364SKalle Valo
60107ac9a364SKalle Valo int
il4965_mac_sta_add(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_sta * sta)60117ac9a364SKalle Valo il4965_mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
60127ac9a364SKalle Valo struct ieee80211_sta *sta)
60137ac9a364SKalle Valo {
60147ac9a364SKalle Valo struct il_priv *il = hw->priv;
60157ac9a364SKalle Valo struct il_station_priv *sta_priv = (void *)sta->drv_priv;
60167ac9a364SKalle Valo bool is_ap = vif->type == NL80211_IFTYPE_STATION;
60177ac9a364SKalle Valo int ret;
60187ac9a364SKalle Valo u8 sta_id;
60197ac9a364SKalle Valo
60207ac9a364SKalle Valo D_INFO("received request to add station %pM\n", sta->addr);
60217ac9a364SKalle Valo mutex_lock(&il->mutex);
60227ac9a364SKalle Valo D_INFO("proceeding to add station %pM\n", sta->addr);
60237ac9a364SKalle Valo sta_priv->common.sta_id = IL_INVALID_STATION;
60247ac9a364SKalle Valo
60257ac9a364SKalle Valo atomic_set(&sta_priv->pending_frames, 0);
60267ac9a364SKalle Valo
60277ac9a364SKalle Valo ret =
60287ac9a364SKalle Valo il_add_station_common(il, sta->addr, is_ap, sta, &sta_id);
60297ac9a364SKalle Valo if (ret) {
60307ac9a364SKalle Valo IL_ERR("Unable to add station %pM (%d)\n", sta->addr, ret);
60317ac9a364SKalle Valo /* Should we return success if return code is EEXIST ? */
60327ac9a364SKalle Valo mutex_unlock(&il->mutex);
60337ac9a364SKalle Valo return ret;
60347ac9a364SKalle Valo }
60357ac9a364SKalle Valo
60367ac9a364SKalle Valo sta_priv->common.sta_id = sta_id;
60377ac9a364SKalle Valo
60387ac9a364SKalle Valo /* Initialize rate scaling */
60397ac9a364SKalle Valo D_INFO("Initializing rate scaling for station %pM\n", sta->addr);
60407ac9a364SKalle Valo il4965_rs_rate_init(il, sta, sta_id);
60417ac9a364SKalle Valo mutex_unlock(&il->mutex);
60427ac9a364SKalle Valo
60437ac9a364SKalle Valo return 0;
60447ac9a364SKalle Valo }
60457ac9a364SKalle Valo
60467ac9a364SKalle Valo void
il4965_mac_channel_switch(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_channel_switch * ch_switch)60477ac9a364SKalle Valo il4965_mac_channel_switch(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
60487ac9a364SKalle Valo struct ieee80211_channel_switch *ch_switch)
60497ac9a364SKalle Valo {
60507ac9a364SKalle Valo struct il_priv *il = hw->priv;
60517ac9a364SKalle Valo const struct il_channel_info *ch_info;
60527ac9a364SKalle Valo struct ieee80211_conf *conf = &hw->conf;
60537ac9a364SKalle Valo struct ieee80211_channel *channel = ch_switch->chandef.chan;
60547ac9a364SKalle Valo struct il_ht_config *ht_conf = &il->current_ht_config;
60557ac9a364SKalle Valo u16 ch;
60567ac9a364SKalle Valo
60577ac9a364SKalle Valo D_MAC80211("enter\n");
60587ac9a364SKalle Valo
60597ac9a364SKalle Valo mutex_lock(&il->mutex);
60607ac9a364SKalle Valo
60617ac9a364SKalle Valo if (il_is_rfkill(il))
60627ac9a364SKalle Valo goto out;
60637ac9a364SKalle Valo
60647ac9a364SKalle Valo if (test_bit(S_EXIT_PENDING, &il->status) ||
60657ac9a364SKalle Valo test_bit(S_SCANNING, &il->status) ||
60667ac9a364SKalle Valo test_bit(S_CHANNEL_SWITCH_PENDING, &il->status))
60677ac9a364SKalle Valo goto out;
60687ac9a364SKalle Valo
60697ac9a364SKalle Valo if (!il_is_associated(il))
60707ac9a364SKalle Valo goto out;
60717ac9a364SKalle Valo
60727ac9a364SKalle Valo if (!il->ops->set_channel_switch)
60737ac9a364SKalle Valo goto out;
60747ac9a364SKalle Valo
60757ac9a364SKalle Valo ch = channel->hw_value;
60767ac9a364SKalle Valo if (le16_to_cpu(il->active.channel) == ch)
60777ac9a364SKalle Valo goto out;
60787ac9a364SKalle Valo
60797ac9a364SKalle Valo ch_info = il_get_channel_info(il, channel->band, ch);
60807ac9a364SKalle Valo if (!il_is_channel_valid(ch_info)) {
60817ac9a364SKalle Valo D_MAC80211("invalid channel\n");
60827ac9a364SKalle Valo goto out;
60837ac9a364SKalle Valo }
60847ac9a364SKalle Valo
60857ac9a364SKalle Valo spin_lock_irq(&il->lock);
60867ac9a364SKalle Valo
60877ac9a364SKalle Valo il->current_ht_config.smps = conf->smps_mode;
60887ac9a364SKalle Valo
60897ac9a364SKalle Valo /* Configure HT40 channels */
60907ac9a364SKalle Valo switch (cfg80211_get_chandef_type(&ch_switch->chandef)) {
60917ac9a364SKalle Valo case NL80211_CHAN_NO_HT:
60927ac9a364SKalle Valo case NL80211_CHAN_HT20:
60937ac9a364SKalle Valo il->ht.is_40mhz = false;
60947ac9a364SKalle Valo il->ht.extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE;
60957ac9a364SKalle Valo break;
60967ac9a364SKalle Valo case NL80211_CHAN_HT40MINUS:
60977ac9a364SKalle Valo il->ht.extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
60987ac9a364SKalle Valo il->ht.is_40mhz = true;
60997ac9a364SKalle Valo break;
61007ac9a364SKalle Valo case NL80211_CHAN_HT40PLUS:
61017ac9a364SKalle Valo il->ht.extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
61027ac9a364SKalle Valo il->ht.is_40mhz = true;
61037ac9a364SKalle Valo break;
61047ac9a364SKalle Valo }
61057ac9a364SKalle Valo
61067ac9a364SKalle Valo if ((le16_to_cpu(il->staging.channel) != ch))
61077ac9a364SKalle Valo il->staging.flags = 0;
61087ac9a364SKalle Valo
61097ac9a364SKalle Valo il_set_rxon_channel(il, channel);
61107ac9a364SKalle Valo il_set_rxon_ht(il, ht_conf);
61117ac9a364SKalle Valo il_set_flags_for_band(il, channel->band, il->vif);
61127ac9a364SKalle Valo
61137ac9a364SKalle Valo spin_unlock_irq(&il->lock);
61147ac9a364SKalle Valo
61157ac9a364SKalle Valo il_set_rate(il);
61167ac9a364SKalle Valo /*
61177ac9a364SKalle Valo * at this point, staging_rxon has the
61187ac9a364SKalle Valo * configuration for channel switch
61197ac9a364SKalle Valo */
61207ac9a364SKalle Valo set_bit(S_CHANNEL_SWITCH_PENDING, &il->status);
61217ac9a364SKalle Valo il->switch_channel = cpu_to_le16(ch);
61227ac9a364SKalle Valo if (il->ops->set_channel_switch(il, ch_switch)) {
61237ac9a364SKalle Valo clear_bit(S_CHANNEL_SWITCH_PENDING, &il->status);
61247ac9a364SKalle Valo il->switch_channel = 0;
61257ac9a364SKalle Valo ieee80211_chswitch_done(il->vif, false);
61267ac9a364SKalle Valo }
61277ac9a364SKalle Valo
61287ac9a364SKalle Valo out:
61297ac9a364SKalle Valo mutex_unlock(&il->mutex);
61307ac9a364SKalle Valo D_MAC80211("leave\n");
61317ac9a364SKalle Valo }
61327ac9a364SKalle Valo
61337ac9a364SKalle Valo void
il4965_configure_filter(struct ieee80211_hw * hw,unsigned int changed_flags,unsigned int * total_flags,u64 multicast)61347ac9a364SKalle Valo il4965_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
61357ac9a364SKalle Valo unsigned int *total_flags, u64 multicast)
61367ac9a364SKalle Valo {
61377ac9a364SKalle Valo struct il_priv *il = hw->priv;
61387ac9a364SKalle Valo __le32 filter_or = 0, filter_nand = 0;
61397ac9a364SKalle Valo
61407ac9a364SKalle Valo #define CHK(test, flag) do { \
61417ac9a364SKalle Valo if (*total_flags & (test)) \
61427ac9a364SKalle Valo filter_or |= (flag); \
61437ac9a364SKalle Valo else \
61447ac9a364SKalle Valo filter_nand |= (flag); \
61457ac9a364SKalle Valo } while (0)
61467ac9a364SKalle Valo
61477ac9a364SKalle Valo D_MAC80211("Enter: changed: 0x%x, total: 0x%x\n", changed_flags,
61487ac9a364SKalle Valo *total_flags);
61497ac9a364SKalle Valo
61507ac9a364SKalle Valo CHK(FIF_OTHER_BSS, RXON_FILTER_PROMISC_MSK);
61517ac9a364SKalle Valo /* Setting _just_ RXON_FILTER_CTL2HOST_MSK causes FH errors */
61527ac9a364SKalle Valo CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_PROMISC_MSK);
61537ac9a364SKalle Valo CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK);
61547ac9a364SKalle Valo
61557ac9a364SKalle Valo #undef CHK
61567ac9a364SKalle Valo
61577ac9a364SKalle Valo mutex_lock(&il->mutex);
61587ac9a364SKalle Valo
61597ac9a364SKalle Valo il->staging.filter_flags &= ~filter_nand;
61607ac9a364SKalle Valo il->staging.filter_flags |= filter_or;
61617ac9a364SKalle Valo
61627ac9a364SKalle Valo /*
61637ac9a364SKalle Valo * Not committing directly because hardware can perform a scan,
61647ac9a364SKalle Valo * but we'll eventually commit the filter flags change anyway.
61657ac9a364SKalle Valo */
61667ac9a364SKalle Valo
61677ac9a364SKalle Valo mutex_unlock(&il->mutex);
61687ac9a364SKalle Valo
61697ac9a364SKalle Valo /*
61707ac9a364SKalle Valo * Receiving all multicast frames is always enabled by the
61717ac9a364SKalle Valo * default flags setup in il_connection_init_rx_config()
61727ac9a364SKalle Valo * since we currently do not support programming multicast
61737ac9a364SKalle Valo * filters into the device.
61747ac9a364SKalle Valo */
61757ac9a364SKalle Valo *total_flags &=
61767ac9a364SKalle Valo FIF_OTHER_BSS | FIF_ALLMULTI |
61777ac9a364SKalle Valo FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
61787ac9a364SKalle Valo }
61797ac9a364SKalle Valo
61807ac9a364SKalle Valo /*****************************************************************************
61817ac9a364SKalle Valo *
61827ac9a364SKalle Valo * driver setup and teardown
61837ac9a364SKalle Valo *
61847ac9a364SKalle Valo *****************************************************************************/
61857ac9a364SKalle Valo
61867ac9a364SKalle Valo static void
il4965_bg_txpower_work(struct work_struct * work)61877ac9a364SKalle Valo il4965_bg_txpower_work(struct work_struct *work)
61887ac9a364SKalle Valo {
61897ac9a364SKalle Valo struct il_priv *il = container_of(work, struct il_priv,
61907ac9a364SKalle Valo txpower_work);
61917ac9a364SKalle Valo
61927ac9a364SKalle Valo mutex_lock(&il->mutex);
61937ac9a364SKalle Valo
61947ac9a364SKalle Valo /* If a scan happened to start before we got here
61957ac9a364SKalle Valo * then just return; the stats notification will
61967ac9a364SKalle Valo * kick off another scheduled work to compensate for
61977ac9a364SKalle Valo * any temperature delta we missed here. */
61987ac9a364SKalle Valo if (test_bit(S_EXIT_PENDING, &il->status) ||
61997ac9a364SKalle Valo test_bit(S_SCANNING, &il->status))
62007ac9a364SKalle Valo goto out;
62017ac9a364SKalle Valo
62027ac9a364SKalle Valo /* Regardless of if we are associated, we must reconfigure the
62037ac9a364SKalle Valo * TX power since frames can be sent on non-radar channels while
62047ac9a364SKalle Valo * not associated */
62057ac9a364SKalle Valo il->ops->send_tx_power(il);
62067ac9a364SKalle Valo
62077ac9a364SKalle Valo /* Update last_temperature to keep is_calib_needed from running
62087ac9a364SKalle Valo * when it isn't needed... */
62097ac9a364SKalle Valo il->last_temperature = il->temperature;
62107ac9a364SKalle Valo out:
62117ac9a364SKalle Valo mutex_unlock(&il->mutex);
62127ac9a364SKalle Valo }
62137ac9a364SKalle Valo
621426e6775fSJiasheng Jiang static int
il4965_setup_deferred_work(struct il_priv * il)62157ac9a364SKalle Valo il4965_setup_deferred_work(struct il_priv *il)
62167ac9a364SKalle Valo {
62177ac9a364SKalle Valo il->workqueue = create_singlethread_workqueue(DRV_NAME);
621826e6775fSJiasheng Jiang if (!il->workqueue)
621926e6775fSJiasheng Jiang return -ENOMEM;
62207ac9a364SKalle Valo
62217ac9a364SKalle Valo init_waitqueue_head(&il->wait_command_queue);
62227ac9a364SKalle Valo
62237ac9a364SKalle Valo INIT_WORK(&il->restart, il4965_bg_restart);
62247ac9a364SKalle Valo INIT_WORK(&il->rx_replenish, il4965_bg_rx_replenish);
62257ac9a364SKalle Valo INIT_WORK(&il->run_time_calib_work, il4965_bg_run_time_calib_work);
62267ac9a364SKalle Valo INIT_DELAYED_WORK(&il->init_alive_start, il4965_bg_init_alive_start);
62277ac9a364SKalle Valo INIT_DELAYED_WORK(&il->alive_start, il4965_bg_alive_start);
62287ac9a364SKalle Valo
62297ac9a364SKalle Valo il_setup_scan_deferred_work(il);
62307ac9a364SKalle Valo
62317ac9a364SKalle Valo INIT_WORK(&il->txpower_work, il4965_bg_txpower_work);
62327ac9a364SKalle Valo
62332b77839bSKees Cook timer_setup(&il->stats_periodic, il4965_bg_stats_periodic, 0);
62347ac9a364SKalle Valo
62352b77839bSKees Cook timer_setup(&il->watchdog, il_bg_watchdog, 0);
62367ac9a364SKalle Valo
6237b81b9d37SAllen Pais tasklet_setup(&il->irq_tasklet, il4965_irq_tasklet);
623826e6775fSJiasheng Jiang
623926e6775fSJiasheng Jiang return 0;
62407ac9a364SKalle Valo }
62417ac9a364SKalle Valo
62427ac9a364SKalle Valo static void
il4965_cancel_deferred_work(struct il_priv * il)62437ac9a364SKalle Valo il4965_cancel_deferred_work(struct il_priv *il)
62447ac9a364SKalle Valo {
62457ac9a364SKalle Valo cancel_work_sync(&il->txpower_work);
62467ac9a364SKalle Valo cancel_delayed_work_sync(&il->init_alive_start);
62477ac9a364SKalle Valo cancel_delayed_work(&il->alive_start);
62487ac9a364SKalle Valo cancel_work_sync(&il->run_time_calib_work);
62497ac9a364SKalle Valo
62507ac9a364SKalle Valo il_cancel_scan_deferred_work(il);
62517ac9a364SKalle Valo
62527ac9a364SKalle Valo del_timer_sync(&il->stats_periodic);
62537ac9a364SKalle Valo }
62547ac9a364SKalle Valo
62557ac9a364SKalle Valo static void
il4965_init_hw_rates(struct il_priv * il,struct ieee80211_rate * rates)62567ac9a364SKalle Valo il4965_init_hw_rates(struct il_priv *il, struct ieee80211_rate *rates)
62577ac9a364SKalle Valo {
62587ac9a364SKalle Valo int i;
62597ac9a364SKalle Valo
62607ac9a364SKalle Valo for (i = 0; i < RATE_COUNT_LEGACY; i++) {
62617ac9a364SKalle Valo rates[i].bitrate = il_rates[i].ieee * 5;
62627ac9a364SKalle Valo rates[i].hw_value = i; /* Rate scaling will work on idxes */
62637ac9a364SKalle Valo rates[i].hw_value_short = i;
62647ac9a364SKalle Valo rates[i].flags = 0;
62657ac9a364SKalle Valo if ((i >= IL_FIRST_CCK_RATE) && (i <= IL_LAST_CCK_RATE)) {
62667ac9a364SKalle Valo /*
62677ac9a364SKalle Valo * If CCK != 1M then set short preamble rate flag.
62687ac9a364SKalle Valo */
62697ac9a364SKalle Valo rates[i].flags |=
62707ac9a364SKalle Valo (il_rates[i].plcp ==
62717ac9a364SKalle Valo RATE_1M_PLCP) ? 0 : IEEE80211_RATE_SHORT_PREAMBLE;
62727ac9a364SKalle Valo }
62737ac9a364SKalle Valo }
62747ac9a364SKalle Valo }
62757ac9a364SKalle Valo
62767ac9a364SKalle Valo /*
62777ac9a364SKalle Valo * Acquire il->lock before calling this function !
62787ac9a364SKalle Valo */
62797ac9a364SKalle Valo void
il4965_set_wr_ptrs(struct il_priv * il,int txq_id,u32 idx)62807ac9a364SKalle Valo il4965_set_wr_ptrs(struct il_priv *il, int txq_id, u32 idx)
62817ac9a364SKalle Valo {
62827ac9a364SKalle Valo il_wr(il, HBUS_TARG_WRPTR, (idx & 0xff) | (txq_id << 8));
62837ac9a364SKalle Valo il_wr_prph(il, IL49_SCD_QUEUE_RDPTR(txq_id), idx);
62847ac9a364SKalle Valo }
62857ac9a364SKalle Valo
62867ac9a364SKalle Valo void
il4965_tx_queue_set_status(struct il_priv * il,struct il_tx_queue * txq,int tx_fifo_id,int scd_retry)62877ac9a364SKalle Valo il4965_tx_queue_set_status(struct il_priv *il, struct il_tx_queue *txq,
62887ac9a364SKalle Valo int tx_fifo_id, int scd_retry)
62897ac9a364SKalle Valo {
62907ac9a364SKalle Valo int txq_id = txq->q.id;
62917ac9a364SKalle Valo
62927ac9a364SKalle Valo /* Find out whether to activate Tx queue */
62937ac9a364SKalle Valo int active = test_bit(txq_id, &il->txq_ctx_active_msk) ? 1 : 0;
62947ac9a364SKalle Valo
62957ac9a364SKalle Valo /* Set up and activate */
62967ac9a364SKalle Valo il_wr_prph(il, IL49_SCD_QUEUE_STATUS_BITS(txq_id),
62977ac9a364SKalle Valo (active << IL49_SCD_QUEUE_STTS_REG_POS_ACTIVE) |
62987ac9a364SKalle Valo (tx_fifo_id << IL49_SCD_QUEUE_STTS_REG_POS_TXF) |
62997ac9a364SKalle Valo (scd_retry << IL49_SCD_QUEUE_STTS_REG_POS_WSL) |
63007ac9a364SKalle Valo (scd_retry << IL49_SCD_QUEUE_STTS_REG_POS_SCD_ACK) |
63017ac9a364SKalle Valo IL49_SCD_QUEUE_STTS_REG_MSK);
63027ac9a364SKalle Valo
63037ac9a364SKalle Valo txq->sched_retry = scd_retry;
63047ac9a364SKalle Valo
63057ac9a364SKalle Valo D_INFO("%s %s Queue %d on AC %d\n", active ? "Activate" : "Deactivate",
63067ac9a364SKalle Valo scd_retry ? "BA" : "AC", txq_id, tx_fifo_id);
63077ac9a364SKalle Valo }
63087ac9a364SKalle Valo
63097ac9a364SKalle Valo static const struct ieee80211_ops il4965_mac_ops = {
63107ac9a364SKalle Valo .tx = il4965_mac_tx,
6311a790cc3aSAlexander Wetzel .wake_tx_queue = ieee80211_handle_wake_tx_queue,
63127ac9a364SKalle Valo .start = il4965_mac_start,
63137ac9a364SKalle Valo .stop = il4965_mac_stop,
63147ac9a364SKalle Valo .add_interface = il_mac_add_interface,
63157ac9a364SKalle Valo .remove_interface = il_mac_remove_interface,
63167ac9a364SKalle Valo .change_interface = il_mac_change_interface,
63177ac9a364SKalle Valo .config = il_mac_config,
63187ac9a364SKalle Valo .configure_filter = il4965_configure_filter,
63197ac9a364SKalle Valo .set_key = il4965_mac_set_key,
63207ac9a364SKalle Valo .update_tkip_key = il4965_mac_update_tkip_key,
63217ac9a364SKalle Valo .conf_tx = il_mac_conf_tx,
63227ac9a364SKalle Valo .reset_tsf = il_mac_reset_tsf,
63237ac9a364SKalle Valo .bss_info_changed = il_mac_bss_info_changed,
63247ac9a364SKalle Valo .ampdu_action = il4965_mac_ampdu_action,
63257ac9a364SKalle Valo .hw_scan = il_mac_hw_scan,
63267ac9a364SKalle Valo .sta_add = il4965_mac_sta_add,
63277ac9a364SKalle Valo .sta_remove = il_mac_sta_remove,
63287ac9a364SKalle Valo .channel_switch = il4965_mac_channel_switch,
63297ac9a364SKalle Valo .tx_last_beacon = il_mac_tx_last_beacon,
63307ac9a364SKalle Valo .flush = il_mac_flush,
63317ac9a364SKalle Valo };
63327ac9a364SKalle Valo
63337ac9a364SKalle Valo static int
il4965_init_drv(struct il_priv * il)63347ac9a364SKalle Valo il4965_init_drv(struct il_priv *il)
63357ac9a364SKalle Valo {
63367ac9a364SKalle Valo int ret;
63377ac9a364SKalle Valo
63387ac9a364SKalle Valo spin_lock_init(&il->sta_lock);
63397ac9a364SKalle Valo spin_lock_init(&il->hcmd_lock);
63407ac9a364SKalle Valo
63417ac9a364SKalle Valo INIT_LIST_HEAD(&il->free_frames);
63427ac9a364SKalle Valo
63437ac9a364SKalle Valo mutex_init(&il->mutex);
63447ac9a364SKalle Valo
63457ac9a364SKalle Valo il->ieee_channels = NULL;
63467ac9a364SKalle Valo il->ieee_rates = NULL;
634757fbcce3SJohannes Berg il->band = NL80211_BAND_2GHZ;
63487ac9a364SKalle Valo
63497ac9a364SKalle Valo il->iw_mode = NL80211_IFTYPE_STATION;
63507ac9a364SKalle Valo il->current_ht_config.smps = IEEE80211_SMPS_STATIC;
63517ac9a364SKalle Valo il->missed_beacon_threshold = IL_MISSED_BEACON_THRESHOLD_DEF;
63527ac9a364SKalle Valo
63537ac9a364SKalle Valo /* initialize force reset */
63547ac9a364SKalle Valo il->force_reset.reset_duration = IL_DELAY_NEXT_FORCE_FW_RELOAD;
63557ac9a364SKalle Valo
63567ac9a364SKalle Valo /* Choose which receivers/antennas to use */
63577ac9a364SKalle Valo if (il->ops->set_rxon_chain)
63587ac9a364SKalle Valo il->ops->set_rxon_chain(il);
63597ac9a364SKalle Valo
63607ac9a364SKalle Valo il_init_scan_params(il);
63617ac9a364SKalle Valo
63627ac9a364SKalle Valo ret = il_init_channel_map(il);
63637ac9a364SKalle Valo if (ret) {
63647ac9a364SKalle Valo IL_ERR("initializing regulatory failed: %d\n", ret);
63657ac9a364SKalle Valo goto err;
63667ac9a364SKalle Valo }
63677ac9a364SKalle Valo
63687ac9a364SKalle Valo ret = il_init_geos(il);
63697ac9a364SKalle Valo if (ret) {
63707ac9a364SKalle Valo IL_ERR("initializing geos failed: %d\n", ret);
63717ac9a364SKalle Valo goto err_free_channel_map;
63727ac9a364SKalle Valo }
63737ac9a364SKalle Valo il4965_init_hw_rates(il, il->ieee_rates);
63747ac9a364SKalle Valo
63757ac9a364SKalle Valo return 0;
63767ac9a364SKalle Valo
63777ac9a364SKalle Valo err_free_channel_map:
63787ac9a364SKalle Valo il_free_channel_map(il);
63797ac9a364SKalle Valo err:
63807ac9a364SKalle Valo return ret;
63817ac9a364SKalle Valo }
63827ac9a364SKalle Valo
63837ac9a364SKalle Valo static void
il4965_uninit_drv(struct il_priv * il)63847ac9a364SKalle Valo il4965_uninit_drv(struct il_priv *il)
63857ac9a364SKalle Valo {
63867ac9a364SKalle Valo il_free_geos(il);
63877ac9a364SKalle Valo il_free_channel_map(il);
63887ac9a364SKalle Valo kfree(il->scan_cmd);
63897ac9a364SKalle Valo }
63907ac9a364SKalle Valo
63917ac9a364SKalle Valo static void
il4965_hw_detect(struct il_priv * il)63927ac9a364SKalle Valo il4965_hw_detect(struct il_priv *il)
63937ac9a364SKalle Valo {
63947ac9a364SKalle Valo il->hw_rev = _il_rd(il, CSR_HW_REV);
63957ac9a364SKalle Valo il->hw_wa_rev = _il_rd(il, CSR_HW_REV_WA_REG);
63967ac9a364SKalle Valo il->rev_id = il->pci_dev->revision;
63977ac9a364SKalle Valo D_INFO("HW Revision ID = 0x%X\n", il->rev_id);
63987ac9a364SKalle Valo }
63997ac9a364SKalle Valo
64009ec855ccSJulia Lawall static const struct il_sensitivity_ranges il4965_sensitivity = {
64017ac9a364SKalle Valo .min_nrg_cck = 97,
64027ac9a364SKalle Valo .max_nrg_cck = 0, /* not used, set to 0 */
64037ac9a364SKalle Valo
64047ac9a364SKalle Valo .auto_corr_min_ofdm = 85,
64057ac9a364SKalle Valo .auto_corr_min_ofdm_mrc = 170,
64067ac9a364SKalle Valo .auto_corr_min_ofdm_x1 = 105,
64077ac9a364SKalle Valo .auto_corr_min_ofdm_mrc_x1 = 220,
64087ac9a364SKalle Valo
64097ac9a364SKalle Valo .auto_corr_max_ofdm = 120,
64107ac9a364SKalle Valo .auto_corr_max_ofdm_mrc = 210,
64117ac9a364SKalle Valo .auto_corr_max_ofdm_x1 = 140,
64127ac9a364SKalle Valo .auto_corr_max_ofdm_mrc_x1 = 270,
64137ac9a364SKalle Valo
64147ac9a364SKalle Valo .auto_corr_min_cck = 125,
64157ac9a364SKalle Valo .auto_corr_max_cck = 200,
64167ac9a364SKalle Valo .auto_corr_min_cck_mrc = 200,
64177ac9a364SKalle Valo .auto_corr_max_cck_mrc = 400,
64187ac9a364SKalle Valo
64197ac9a364SKalle Valo .nrg_th_cck = 100,
64207ac9a364SKalle Valo .nrg_th_ofdm = 100,
64217ac9a364SKalle Valo
64227ac9a364SKalle Valo .barker_corr_th_min = 190,
64237ac9a364SKalle Valo .barker_corr_th_min_mrc = 390,
64247ac9a364SKalle Valo .nrg_th_cca = 62,
64257ac9a364SKalle Valo };
64267ac9a364SKalle Valo
64277ac9a364SKalle Valo static void
il4965_set_hw_params(struct il_priv * il)64287ac9a364SKalle Valo il4965_set_hw_params(struct il_priv *il)
64297ac9a364SKalle Valo {
64307ac9a364SKalle Valo il->hw_params.bcast_id = IL4965_BROADCAST_ID;
64317ac9a364SKalle Valo il->hw_params.max_rxq_size = RX_QUEUE_SIZE;
64327ac9a364SKalle Valo il->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;
64337ac9a364SKalle Valo if (il->cfg->mod_params->amsdu_size_8K)
64347ac9a364SKalle Valo il->hw_params.rx_page_order = get_order(IL_RX_BUF_SIZE_8K);
64357ac9a364SKalle Valo else
64367ac9a364SKalle Valo il->hw_params.rx_page_order = get_order(IL_RX_BUF_SIZE_4K);
64377ac9a364SKalle Valo
64387ac9a364SKalle Valo il->hw_params.max_beacon_itrvl = IL_MAX_UCODE_BEACON_INTERVAL;
64397ac9a364SKalle Valo
64407ac9a364SKalle Valo if (il->cfg->mod_params->disable_11n)
64417ac9a364SKalle Valo il->cfg->sku &= ~IL_SKU_N;
64427ac9a364SKalle Valo
64437ac9a364SKalle Valo if (il->cfg->mod_params->num_of_queues >= IL_MIN_NUM_QUEUES &&
64447ac9a364SKalle Valo il->cfg->mod_params->num_of_queues <= IL49_NUM_QUEUES)
64457ac9a364SKalle Valo il->cfg->num_of_queues =
64467ac9a364SKalle Valo il->cfg->mod_params->num_of_queues;
64477ac9a364SKalle Valo
64487ac9a364SKalle Valo il->hw_params.max_txq_num = il->cfg->num_of_queues;
64497ac9a364SKalle Valo il->hw_params.dma_chnl_num = FH49_TCSR_CHNL_NUM;
64507ac9a364SKalle Valo il->hw_params.scd_bc_tbls_size =
64517ac9a364SKalle Valo il->cfg->num_of_queues *
64527ac9a364SKalle Valo sizeof(struct il4965_scd_bc_tbl);
64537ac9a364SKalle Valo
64547ac9a364SKalle Valo il->hw_params.tfd_size = sizeof(struct il_tfd);
64557ac9a364SKalle Valo il->hw_params.max_stations = IL4965_STATION_COUNT;
64567ac9a364SKalle Valo il->hw_params.max_data_size = IL49_RTC_DATA_SIZE;
64577ac9a364SKalle Valo il->hw_params.max_inst_size = IL49_RTC_INST_SIZE;
64587ac9a364SKalle Valo il->hw_params.max_bsm_size = BSM_SRAM_SIZE;
645957fbcce3SJohannes Berg il->hw_params.ht40_channel = BIT(NL80211_BAND_5GHZ);
64607ac9a364SKalle Valo
64617ac9a364SKalle Valo il->hw_params.rx_wrt_ptr_reg = FH49_RSCSR_CHNL0_WPTR;
64627ac9a364SKalle Valo
64637ac9a364SKalle Valo il->hw_params.tx_chains_num = il4965_num_of_ant(il->cfg->valid_tx_ant);
64647ac9a364SKalle Valo il->hw_params.rx_chains_num = il4965_num_of_ant(il->cfg->valid_rx_ant);
64657ac9a364SKalle Valo il->hw_params.valid_tx_ant = il->cfg->valid_tx_ant;
64667ac9a364SKalle Valo il->hw_params.valid_rx_ant = il->cfg->valid_rx_ant;
64677ac9a364SKalle Valo
64687ac9a364SKalle Valo il->hw_params.ct_kill_threshold =
64691410b2fcSAkinobu Mita celsius_to_kelvin(CT_KILL_THRESHOLD_LEGACY);
64707ac9a364SKalle Valo
64717ac9a364SKalle Valo il->hw_params.sens = &il4965_sensitivity;
64727ac9a364SKalle Valo il->hw_params.beacon_time_tsf_bits = IL4965_EXT_BEACON_TIME_POS;
64737ac9a364SKalle Valo }
64747ac9a364SKalle Valo
64757ac9a364SKalle Valo static int
il4965_pci_probe(struct pci_dev * pdev,const struct pci_device_id * ent)64767ac9a364SKalle Valo il4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
64777ac9a364SKalle Valo {
64787ac9a364SKalle Valo int err = 0;
64797ac9a364SKalle Valo struct il_priv *il;
64807ac9a364SKalle Valo struct ieee80211_hw *hw;
64817ac9a364SKalle Valo struct il_cfg *cfg = (struct il_cfg *)(ent->driver_data);
64827ac9a364SKalle Valo unsigned long flags;
64837ac9a364SKalle Valo u16 pci_cmd;
64847ac9a364SKalle Valo
64857ac9a364SKalle Valo /************************
64867ac9a364SKalle Valo * 1. Allocating HW data
64877ac9a364SKalle Valo ************************/
64887ac9a364SKalle Valo
64897ac9a364SKalle Valo hw = ieee80211_alloc_hw(sizeof(struct il_priv), &il4965_mac_ops);
64907ac9a364SKalle Valo if (!hw) {
64917ac9a364SKalle Valo err = -ENOMEM;
64927ac9a364SKalle Valo goto out;
64937ac9a364SKalle Valo }
64947ac9a364SKalle Valo il = hw->priv;
64957ac9a364SKalle Valo il->hw = hw;
64967ac9a364SKalle Valo SET_IEEE80211_DEV(hw, &pdev->dev);
64977ac9a364SKalle Valo
64987ac9a364SKalle Valo D_INFO("*** LOAD DRIVER ***\n");
64997ac9a364SKalle Valo il->cfg = cfg;
65007ac9a364SKalle Valo il->ops = &il4965_ops;
65017ac9a364SKalle Valo #ifdef CONFIG_IWLEGACY_DEBUGFS
65027ac9a364SKalle Valo il->debugfs_ops = &il4965_debugfs_ops;
65037ac9a364SKalle Valo #endif
65047ac9a364SKalle Valo il->pci_dev = pdev;
65057ac9a364SKalle Valo il->inta_mask = CSR_INI_SET_MASK;
65067ac9a364SKalle Valo
65077ac9a364SKalle Valo /**************************
65087ac9a364SKalle Valo * 2. Initializing PCI bus
65097ac9a364SKalle Valo **************************/
65107ac9a364SKalle Valo pci_disable_link_state(pdev,
65117ac9a364SKalle Valo PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
65127ac9a364SKalle Valo PCIE_LINK_STATE_CLKPM);
65137ac9a364SKalle Valo
65147ac9a364SKalle Valo if (pci_enable_device(pdev)) {
65157ac9a364SKalle Valo err = -ENODEV;
65167ac9a364SKalle Valo goto out_ieee80211_free_hw;
65177ac9a364SKalle Valo }
65187ac9a364SKalle Valo
65197ac9a364SKalle Valo pci_set_master(pdev);
65207ac9a364SKalle Valo
6521ebe9e651SChristophe JAILLET err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(36));
65227ac9a364SKalle Valo if (err) {
6523ebe9e651SChristophe JAILLET err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
65247ac9a364SKalle Valo /* both attempts failed: */
65257ac9a364SKalle Valo if (err) {
65267ac9a364SKalle Valo IL_WARN("No suitable DMA available.\n");
65277ac9a364SKalle Valo goto out_pci_disable_device;
65287ac9a364SKalle Valo }
65297ac9a364SKalle Valo }
65307ac9a364SKalle Valo
65317ac9a364SKalle Valo err = pci_request_regions(pdev, DRV_NAME);
65327ac9a364SKalle Valo if (err)
65337ac9a364SKalle Valo goto out_pci_disable_device;
65347ac9a364SKalle Valo
65357ac9a364SKalle Valo pci_set_drvdata(pdev, il);
65367ac9a364SKalle Valo
65377ac9a364SKalle Valo /***********************
65387ac9a364SKalle Valo * 3. Read REV register
65397ac9a364SKalle Valo ***********************/
65407ac9a364SKalle Valo il->hw_base = pci_ioremap_bar(pdev, 0);
65417ac9a364SKalle Valo if (!il->hw_base) {
65427ac9a364SKalle Valo err = -ENODEV;
65437ac9a364SKalle Valo goto out_pci_release_regions;
65447ac9a364SKalle Valo }
65457ac9a364SKalle Valo
65467ac9a364SKalle Valo D_INFO("pci_resource_len = 0x%08llx\n",
65477ac9a364SKalle Valo (unsigned long long)pci_resource_len(pdev, 0));
65487ac9a364SKalle Valo D_INFO("pci_resource_base = %p\n", il->hw_base);
65497ac9a364SKalle Valo
65507ac9a364SKalle Valo /* these spin locks will be used in apm_ops.init and EEPROM access
65517ac9a364SKalle Valo * we should init now
65527ac9a364SKalle Valo */
65537ac9a364SKalle Valo spin_lock_init(&il->reg_lock);
65547ac9a364SKalle Valo spin_lock_init(&il->lock);
65557ac9a364SKalle Valo
65567ac9a364SKalle Valo /*
65577ac9a364SKalle Valo * stop and reset the on-board processor just in case it is in a
65587ac9a364SKalle Valo * strange state ... like being left stranded by a primary kernel
65597ac9a364SKalle Valo * and this is now the kdump kernel trying to start up
65607ac9a364SKalle Valo */
65617ac9a364SKalle Valo _il_wr(il, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
65627ac9a364SKalle Valo
65637ac9a364SKalle Valo il4965_hw_detect(il);
65647ac9a364SKalle Valo IL_INFO("Detected %s, REV=0x%X\n", il->cfg->name, il->hw_rev);
65657ac9a364SKalle Valo
65667ac9a364SKalle Valo /* We disable the RETRY_TIMEOUT register (0x41) to keep
65677ac9a364SKalle Valo * PCI Tx retries from interfering with C3 CPU state */
65687ac9a364SKalle Valo pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
65697ac9a364SKalle Valo
65707ac9a364SKalle Valo il4965_prepare_card_hw(il);
65717ac9a364SKalle Valo if (!il->hw_ready) {
65727ac9a364SKalle Valo IL_WARN("Failed, HW not ready\n");
65737ac9a364SKalle Valo err = -EIO;
65747ac9a364SKalle Valo goto out_iounmap;
65757ac9a364SKalle Valo }
65767ac9a364SKalle Valo
65777ac9a364SKalle Valo /*****************
65787ac9a364SKalle Valo * 4. Read EEPROM
65797ac9a364SKalle Valo *****************/
65807ac9a364SKalle Valo /* Read the EEPROM */
65817ac9a364SKalle Valo err = il_eeprom_init(il);
65827ac9a364SKalle Valo if (err) {
65837ac9a364SKalle Valo IL_ERR("Unable to init EEPROM\n");
65847ac9a364SKalle Valo goto out_iounmap;
65857ac9a364SKalle Valo }
65867ac9a364SKalle Valo err = il4965_eeprom_check_version(il);
65877ac9a364SKalle Valo if (err)
65887ac9a364SKalle Valo goto out_free_eeprom;
65897ac9a364SKalle Valo
65907ac9a364SKalle Valo /* extract MAC Address */
65917ac9a364SKalle Valo il4965_eeprom_get_mac(il, il->addresses[0].addr);
65927ac9a364SKalle Valo D_INFO("MAC address: %pM\n", il->addresses[0].addr);
65937ac9a364SKalle Valo il->hw->wiphy->addresses = il->addresses;
65947ac9a364SKalle Valo il->hw->wiphy->n_addresses = 1;
65957ac9a364SKalle Valo
65967ac9a364SKalle Valo /************************
65977ac9a364SKalle Valo * 5. Setup HW constants
65987ac9a364SKalle Valo ************************/
65997ac9a364SKalle Valo il4965_set_hw_params(il);
66007ac9a364SKalle Valo
66017ac9a364SKalle Valo /*******************
66027ac9a364SKalle Valo * 6. Setup il
66037ac9a364SKalle Valo *******************/
66047ac9a364SKalle Valo
66057ac9a364SKalle Valo err = il4965_init_drv(il);
66067ac9a364SKalle Valo if (err)
66077ac9a364SKalle Valo goto out_free_eeprom;
66087ac9a364SKalle Valo /* At this point both hw and il are initialized. */
66097ac9a364SKalle Valo
66107ac9a364SKalle Valo /********************
66117ac9a364SKalle Valo * 7. Setup services
66127ac9a364SKalle Valo ********************/
66137ac9a364SKalle Valo spin_lock_irqsave(&il->lock, flags);
66147ac9a364SKalle Valo il_disable_interrupts(il);
66157ac9a364SKalle Valo spin_unlock_irqrestore(&il->lock, flags);
66167ac9a364SKalle Valo
66177ac9a364SKalle Valo pci_enable_msi(il->pci_dev);
66187ac9a364SKalle Valo
66197ac9a364SKalle Valo err = request_irq(il->pci_dev->irq, il_isr, IRQF_SHARED, DRV_NAME, il);
66207ac9a364SKalle Valo if (err) {
66217ac9a364SKalle Valo IL_ERR("Error allocating IRQ %d\n", il->pci_dev->irq);
66227ac9a364SKalle Valo goto out_disable_msi;
66237ac9a364SKalle Valo }
66247ac9a364SKalle Valo
662526e6775fSJiasheng Jiang err = il4965_setup_deferred_work(il);
662626e6775fSJiasheng Jiang if (err)
662726e6775fSJiasheng Jiang goto out_free_irq;
662826e6775fSJiasheng Jiang
66297ac9a364SKalle Valo il4965_setup_handlers(il);
66307ac9a364SKalle Valo
66317ac9a364SKalle Valo /*********************************************
66327ac9a364SKalle Valo * 8. Enable interrupts and read RFKILL state
66337ac9a364SKalle Valo *********************************************/
66347ac9a364SKalle Valo
66357ac9a364SKalle Valo /* enable rfkill interrupt: hw bug w/a */
66367ac9a364SKalle Valo pci_read_config_word(il->pci_dev, PCI_COMMAND, &pci_cmd);
66377ac9a364SKalle Valo if (pci_cmd & PCI_COMMAND_INTX_DISABLE) {
66387ac9a364SKalle Valo pci_cmd &= ~PCI_COMMAND_INTX_DISABLE;
66397ac9a364SKalle Valo pci_write_config_word(il->pci_dev, PCI_COMMAND, pci_cmd);
66407ac9a364SKalle Valo }
66417ac9a364SKalle Valo
66427ac9a364SKalle Valo il_enable_rfkill_int(il);
66437ac9a364SKalle Valo
66447ac9a364SKalle Valo /* If platform's RF_KILL switch is NOT set to KILL */
66457ac9a364SKalle Valo if (_il_rd(il, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
66467ac9a364SKalle Valo clear_bit(S_RFKILL, &il->status);
66477ac9a364SKalle Valo else
66487ac9a364SKalle Valo set_bit(S_RFKILL, &il->status);
66497ac9a364SKalle Valo
66507ac9a364SKalle Valo wiphy_rfkill_set_hw_state(il->hw->wiphy,
66517ac9a364SKalle Valo test_bit(S_RFKILL, &il->status));
66527ac9a364SKalle Valo
66537ac9a364SKalle Valo il_power_initialize(il);
66547ac9a364SKalle Valo
66557ac9a364SKalle Valo init_completion(&il->_4965.firmware_loading_complete);
66567ac9a364SKalle Valo
66577ac9a364SKalle Valo err = il4965_request_firmware(il, true);
66587ac9a364SKalle Valo if (err)
66597ac9a364SKalle Valo goto out_destroy_workqueue;
66607ac9a364SKalle Valo
66617ac9a364SKalle Valo return 0;
66627ac9a364SKalle Valo
66637ac9a364SKalle Valo out_destroy_workqueue:
66647ac9a364SKalle Valo destroy_workqueue(il->workqueue);
66657ac9a364SKalle Valo il->workqueue = NULL;
666626e6775fSJiasheng Jiang out_free_irq:
66677ac9a364SKalle Valo free_irq(il->pci_dev->irq, il);
66687ac9a364SKalle Valo out_disable_msi:
66697ac9a364SKalle Valo pci_disable_msi(il->pci_dev);
66707ac9a364SKalle Valo il4965_uninit_drv(il);
66717ac9a364SKalle Valo out_free_eeprom:
66727ac9a364SKalle Valo il_eeprom_free(il);
66737ac9a364SKalle Valo out_iounmap:
66747ac9a364SKalle Valo iounmap(il->hw_base);
66757ac9a364SKalle Valo out_pci_release_regions:
66767ac9a364SKalle Valo pci_release_regions(pdev);
66777ac9a364SKalle Valo out_pci_disable_device:
66787ac9a364SKalle Valo pci_disable_device(pdev);
66797ac9a364SKalle Valo out_ieee80211_free_hw:
66807ac9a364SKalle Valo ieee80211_free_hw(il->hw);
66817ac9a364SKalle Valo out:
66827ac9a364SKalle Valo return err;
66837ac9a364SKalle Valo }
66847ac9a364SKalle Valo
66857ac9a364SKalle Valo static void
il4965_pci_remove(struct pci_dev * pdev)66867ac9a364SKalle Valo il4965_pci_remove(struct pci_dev *pdev)
66877ac9a364SKalle Valo {
66887ac9a364SKalle Valo struct il_priv *il = pci_get_drvdata(pdev);
66897ac9a364SKalle Valo unsigned long flags;
66907ac9a364SKalle Valo
66917ac9a364SKalle Valo if (!il)
66927ac9a364SKalle Valo return;
66937ac9a364SKalle Valo
66947ac9a364SKalle Valo wait_for_completion(&il->_4965.firmware_loading_complete);
66957ac9a364SKalle Valo
66967ac9a364SKalle Valo D_INFO("*** UNLOAD DRIVER ***\n");
66977ac9a364SKalle Valo
66987ac9a364SKalle Valo il_dbgfs_unregister(il);
66997ac9a364SKalle Valo sysfs_remove_group(&pdev->dev.kobj, &il_attribute_group);
67007ac9a364SKalle Valo
67017ac9a364SKalle Valo /* ieee80211_unregister_hw call wil cause il_mac_stop to
6702f29c2151SJilin Yuan * be called and il4965_down since we are removing the device
67037ac9a364SKalle Valo * we need to set S_EXIT_PENDING bit.
67047ac9a364SKalle Valo */
67057ac9a364SKalle Valo set_bit(S_EXIT_PENDING, &il->status);
67067ac9a364SKalle Valo
67077ac9a364SKalle Valo il_leds_exit(il);
67087ac9a364SKalle Valo
67097ac9a364SKalle Valo if (il->mac80211_registered) {
67107ac9a364SKalle Valo ieee80211_unregister_hw(il->hw);
67117ac9a364SKalle Valo il->mac80211_registered = 0;
67127ac9a364SKalle Valo } else {
67137ac9a364SKalle Valo il4965_down(il);
67147ac9a364SKalle Valo }
67157ac9a364SKalle Valo
67167ac9a364SKalle Valo /*
67177ac9a364SKalle Valo * Make sure device is reset to low power before unloading driver.
67187ac9a364SKalle Valo * This may be redundant with il4965_down(), but there are paths to
67197ac9a364SKalle Valo * run il4965_down() without calling apm_ops.stop(), and there are
67207ac9a364SKalle Valo * paths to avoid running il4965_down() at all before leaving driver.
67217ac9a364SKalle Valo * This (inexpensive) call *makes sure* device is reset.
67227ac9a364SKalle Valo */
67237ac9a364SKalle Valo il_apm_stop(il);
67247ac9a364SKalle Valo
67257ac9a364SKalle Valo /* make sure we flush any pending irq or
67267ac9a364SKalle Valo * tasklet for the driver
67277ac9a364SKalle Valo */
67287ac9a364SKalle Valo spin_lock_irqsave(&il->lock, flags);
67297ac9a364SKalle Valo il_disable_interrupts(il);
67307ac9a364SKalle Valo spin_unlock_irqrestore(&il->lock, flags);
67317ac9a364SKalle Valo
67327ac9a364SKalle Valo il4965_synchronize_irq(il);
67337ac9a364SKalle Valo
67347ac9a364SKalle Valo il4965_dealloc_ucode_pci(il);
67357ac9a364SKalle Valo
67367ac9a364SKalle Valo if (il->rxq.bd)
67377ac9a364SKalle Valo il4965_rx_queue_free(il, &il->rxq);
67387ac9a364SKalle Valo il4965_hw_txq_ctx_free(il);
67397ac9a364SKalle Valo
67407ac9a364SKalle Valo il_eeprom_free(il);
67417ac9a364SKalle Valo
67427ac9a364SKalle Valo /*netif_stop_queue(dev); */
67437ac9a364SKalle Valo
67447ac9a364SKalle Valo /* ieee80211_unregister_hw calls il_mac_stop, which flushes
67457ac9a364SKalle Valo * il->workqueue... so we can't take down the workqueue
67467ac9a364SKalle Valo * until now... */
67477ac9a364SKalle Valo destroy_workqueue(il->workqueue);
67487ac9a364SKalle Valo il->workqueue = NULL;
67497ac9a364SKalle Valo
67507ac9a364SKalle Valo free_irq(il->pci_dev->irq, il);
67517ac9a364SKalle Valo pci_disable_msi(il->pci_dev);
67527ac9a364SKalle Valo iounmap(il->hw_base);
67537ac9a364SKalle Valo pci_release_regions(pdev);
67547ac9a364SKalle Valo pci_disable_device(pdev);
67557ac9a364SKalle Valo
67567ac9a364SKalle Valo il4965_uninit_drv(il);
67577ac9a364SKalle Valo
67587ac9a364SKalle Valo dev_kfree_skb(il->beacon_skb);
67597ac9a364SKalle Valo
67607ac9a364SKalle Valo ieee80211_free_hw(il->hw);
67617ac9a364SKalle Valo }
67627ac9a364SKalle Valo
67637ac9a364SKalle Valo /*
67647ac9a364SKalle Valo * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask
67657ac9a364SKalle Valo * must be called under il->lock and mac access
67667ac9a364SKalle Valo */
67677ac9a364SKalle Valo void
il4965_txq_set_sched(struct il_priv * il,u32 mask)67687ac9a364SKalle Valo il4965_txq_set_sched(struct il_priv *il, u32 mask)
67697ac9a364SKalle Valo {
67707ac9a364SKalle Valo il_wr_prph(il, IL49_SCD_TXFACT, mask);
67717ac9a364SKalle Valo }
67727ac9a364SKalle Valo
67737ac9a364SKalle Valo /*****************************************************************************
67747ac9a364SKalle Valo *
67757ac9a364SKalle Valo * driver and module entry point
67767ac9a364SKalle Valo *
67777ac9a364SKalle Valo *****************************************************************************/
67787ac9a364SKalle Valo
67797ac9a364SKalle Valo /* Hardware specific file defines the PCI IDs table for that hardware module */
67807ac9a364SKalle Valo static const struct pci_device_id il4965_hw_card_ids[] = {
67817ac9a364SKalle Valo {IL_PCI_DEVICE(0x4229, PCI_ANY_ID, il4965_cfg)},
67827ac9a364SKalle Valo {IL_PCI_DEVICE(0x4230, PCI_ANY_ID, il4965_cfg)},
67837ac9a364SKalle Valo {0}
67847ac9a364SKalle Valo };
67857ac9a364SKalle Valo MODULE_DEVICE_TABLE(pci, il4965_hw_card_ids);
67867ac9a364SKalle Valo
67877ac9a364SKalle Valo static struct pci_driver il4965_driver = {
67887ac9a364SKalle Valo .name = DRV_NAME,
67897ac9a364SKalle Valo .id_table = il4965_hw_card_ids,
67907ac9a364SKalle Valo .probe = il4965_pci_probe,
67917ac9a364SKalle Valo .remove = il4965_pci_remove,
67927ac9a364SKalle Valo .driver.pm = IL_LEGACY_PM_OPS,
67937ac9a364SKalle Valo };
67947ac9a364SKalle Valo
67957ac9a364SKalle Valo static int __init
il4965_init(void)67967ac9a364SKalle Valo il4965_init(void)
67977ac9a364SKalle Valo {
67987ac9a364SKalle Valo
67997ac9a364SKalle Valo int ret;
68007ac9a364SKalle Valo pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n");
68017ac9a364SKalle Valo pr_info(DRV_COPYRIGHT "\n");
68027ac9a364SKalle Valo
68037ac9a364SKalle Valo ret = il4965_rate_control_register();
68047ac9a364SKalle Valo if (ret) {
68057ac9a364SKalle Valo pr_err("Unable to register rate control algorithm: %d\n", ret);
68067ac9a364SKalle Valo return ret;
68077ac9a364SKalle Valo }
68087ac9a364SKalle Valo
68097ac9a364SKalle Valo ret = pci_register_driver(&il4965_driver);
68107ac9a364SKalle Valo if (ret) {
68117ac9a364SKalle Valo pr_err("Unable to initialize PCI module\n");
68127ac9a364SKalle Valo goto error_register;
68137ac9a364SKalle Valo }
68147ac9a364SKalle Valo
68157ac9a364SKalle Valo return ret;
68167ac9a364SKalle Valo
68177ac9a364SKalle Valo error_register:
68187ac9a364SKalle Valo il4965_rate_control_unregister();
68197ac9a364SKalle Valo return ret;
68207ac9a364SKalle Valo }
68217ac9a364SKalle Valo
68227ac9a364SKalle Valo static void __exit
il4965_exit(void)68237ac9a364SKalle Valo il4965_exit(void)
68247ac9a364SKalle Valo {
68257ac9a364SKalle Valo pci_unregister_driver(&il4965_driver);
68267ac9a364SKalle Valo il4965_rate_control_unregister();
68277ac9a364SKalle Valo }
68287ac9a364SKalle Valo
68297ac9a364SKalle Valo module_exit(il4965_exit);
68307ac9a364SKalle Valo module_init(il4965_init);
68317ac9a364SKalle Valo
68327ac9a364SKalle Valo #ifdef CONFIG_IWLEGACY_DEBUG
68332ef00c53SJoe Perches module_param_named(debug, il_debug_level, uint, 0644);
68347ac9a364SKalle Valo MODULE_PARM_DESC(debug, "debug output mask");
68357ac9a364SKalle Valo #endif
68367ac9a364SKalle Valo
68372ef00c53SJoe Perches module_param_named(swcrypto, il4965_mod_params.sw_crypto, int, 0444);
68387ac9a364SKalle Valo MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])");
68392ef00c53SJoe Perches module_param_named(queues_num, il4965_mod_params.num_of_queues, int, 0444);
68407ac9a364SKalle Valo MODULE_PARM_DESC(queues_num, "number of hw queues.");
68412ef00c53SJoe Perches module_param_named(11n_disable, il4965_mod_params.disable_11n, int, 0444);
68427ac9a364SKalle Valo MODULE_PARM_DESC(11n_disable, "disable 11n functionality");
68432ef00c53SJoe Perches module_param_named(amsdu_size_8K, il4965_mod_params.amsdu_size_8K, int, 0444);
68447ac9a364SKalle Valo MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size (default 0 [disabled])");
68452ef00c53SJoe Perches module_param_named(fw_restart, il4965_mod_params.restart_fw, int, 0444);
68467ac9a364SKalle Valo MODULE_PARM_DESC(fw_restart, "restart firmware in case of error");
6847