1ab697a9f1e73ba817955e15bd899a8a0627f9fd6Emmanuel Grumbach/****************************************************************************** 2ab697a9f1e73ba817955e15bd899a8a0627f9fd6Emmanuel Grumbach * 34e3182626a914443a5e0fbe014813f03e51a75dfWey-Yi Guy * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. 4ab697a9f1e73ba817955e15bd899a8a0627f9fd6Emmanuel Grumbach * 5ab697a9f1e73ba817955e15bd899a8a0627f9fd6Emmanuel Grumbach * Portions of this file are derived from the ipw3945 project, as well 6ab697a9f1e73ba817955e15bd899a8a0627f9fd6Emmanuel Grumbach * as portions of the ieee80211 subsystem header files. 7ab697a9f1e73ba817955e15bd899a8a0627f9fd6Emmanuel Grumbach * 8ab697a9f1e73ba817955e15bd899a8a0627f9fd6Emmanuel Grumbach * This program is free software; you can redistribute it and/or modify it 9ab697a9f1e73ba817955e15bd899a8a0627f9fd6Emmanuel Grumbach * under the terms of version 2 of the GNU General Public License as 10ab697a9f1e73ba817955e15bd899a8a0627f9fd6Emmanuel Grumbach * published by the Free Software Foundation. 11ab697a9f1e73ba817955e15bd899a8a0627f9fd6Emmanuel Grumbach * 12ab697a9f1e73ba817955e15bd899a8a0627f9fd6Emmanuel Grumbach * This program is distributed in the hope that it will be useful, but WITHOUT 13ab697a9f1e73ba817955e15bd899a8a0627f9fd6Emmanuel Grumbach * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14ab697a9f1e73ba817955e15bd899a8a0627f9fd6Emmanuel Grumbach * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15ab697a9f1e73ba817955e15bd899a8a0627f9fd6Emmanuel Grumbach * more details. 16ab697a9f1e73ba817955e15bd899a8a0627f9fd6Emmanuel Grumbach * 17ab697a9f1e73ba817955e15bd899a8a0627f9fd6Emmanuel Grumbach * You should have received a copy of the GNU General Public License along with 18ab697a9f1e73ba817955e15bd899a8a0627f9fd6Emmanuel Grumbach * this program; if not, write to the Free Software Foundation, Inc., 19ab697a9f1e73ba817955e15bd899a8a0627f9fd6Emmanuel Grumbach * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA 20ab697a9f1e73ba817955e15bd899a8a0627f9fd6Emmanuel Grumbach * 21ab697a9f1e73ba817955e15bd899a8a0627f9fd6Emmanuel Grumbach * The full GNU General Public License is included in this distribution in the 22ab697a9f1e73ba817955e15bd899a8a0627f9fd6Emmanuel Grumbach * file called LICENSE. 23ab697a9f1e73ba817955e15bd899a8a0627f9fd6Emmanuel Grumbach * 24ab697a9f1e73ba817955e15bd899a8a0627f9fd6Emmanuel Grumbach * Contact Information: 25ab697a9f1e73ba817955e15bd899a8a0627f9fd6Emmanuel Grumbach * Intel Linux Wireless <ilw@linux.intel.com> 26ab697a9f1e73ba817955e15bd899a8a0627f9fd6Emmanuel Grumbach * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 27ab697a9f1e73ba817955e15bd899a8a0627f9fd6Emmanuel Grumbach * 28ab697a9f1e73ba817955e15bd899a8a0627f9fd6Emmanuel Grumbach *****************************************************************************/ 29ab697a9f1e73ba817955e15bd899a8a0627f9fd6Emmanuel Grumbach#ifndef __iwl_trans_int_pcie_h__ 30ab697a9f1e73ba817955e15bd899a8a0627f9fd6Emmanuel Grumbach#define __iwl_trans_int_pcie_h__ 31ab697a9f1e73ba817955e15bd899a8a0627f9fd6Emmanuel Grumbach 32a72b8b088c3465b28192c1a14ba97be8223a8cecEmmanuel Grumbach#include <linux/spinlock.h> 33a72b8b088c3465b28192c1a14ba97be8223a8cecEmmanuel Grumbach#include <linux/interrupt.h> 34a72b8b088c3465b28192c1a14ba97be8223a8cecEmmanuel Grumbach#include <linux/skbuff.h> 3513df1aab4aa3cd99693c0cdeb7177e5359218431Johannes Berg#include <linux/wait.h> 36522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach#include <linux/pci.h> 37a72b8b088c3465b28192c1a14ba97be8223a8cecEmmanuel Grumbach 38dda61a4482661d71034cc132d1f474f19ce34a4dEmmanuel Grumbach#include "iwl-fh.h" 39a72b8b088c3465b28192c1a14ba97be8223a8cecEmmanuel Grumbach#include "iwl-csr.h" 40a72b8b088c3465b28192c1a14ba97be8223a8cecEmmanuel Grumbach#include "iwl-shared.h" 41a72b8b088c3465b28192c1a14ba97be8223a8cecEmmanuel Grumbach#include "iwl-trans.h" 42a72b8b088c3465b28192c1a14ba97be8223a8cecEmmanuel Grumbach#include "iwl-debug.h" 43a72b8b088c3465b28192c1a14ba97be8223a8cecEmmanuel Grumbach#include "iwl-io.h" 4402e3835884f352ac707dcf14d8bf455c0c0acbc5Emmanuel Grumbach#include "iwl-op-mode.h" 45a72b8b088c3465b28192c1a14ba97be8223a8cecEmmanuel Grumbach 46a72b8b088c3465b28192c1a14ba97be8223a8cecEmmanuel Grumbachstruct iwl_tx_queue; 47a72b8b088c3465b28192c1a14ba97be8223a8cecEmmanuel Grumbachstruct iwl_queue; 48a72b8b088c3465b28192c1a14ba97be8223a8cecEmmanuel Grumbachstruct iwl_host_cmd; 49dda61a4482661d71034cc132d1f474f19ce34a4dEmmanuel Grumbach 50ab697a9f1e73ba817955e15bd899a8a0627f9fd6Emmanuel Grumbach/*This file includes the declaration that are internal to the 51ab697a9f1e73ba817955e15bd899a8a0627f9fd6Emmanuel Grumbach * trans_pcie layer */ 52ab697a9f1e73ba817955e15bd899a8a0627f9fd6Emmanuel Grumbach 5348a2d66f58d2bf1818acf5ff7ed9897a9977a96eJohannes Bergstruct iwl_rx_mem_buffer { 5448a2d66f58d2bf1818acf5ff7ed9897a9977a96eJohannes Berg dma_addr_t page_dma; 5548a2d66f58d2bf1818acf5ff7ed9897a9977a96eJohannes Berg struct page *page; 5648a2d66f58d2bf1818acf5ff7ed9897a9977a96eJohannes Berg struct list_head list; 5748a2d66f58d2bf1818acf5ff7ed9897a9977a96eJohannes Berg}; 5848a2d66f58d2bf1818acf5ff7ed9897a9977a96eJohannes Berg 59e6bb4c9c00892c488f3218ea317dc6a71674faf4Emmanuel Grumbach/** 601f7b6172db86e9ab2b4cd794441bb2c40ab287fcEmmanuel Grumbach * struct isr_statistics - interrupt statistics 611f7b6172db86e9ab2b4cd794441bb2c40ab287fcEmmanuel Grumbach * 621f7b6172db86e9ab2b4cd794441bb2c40ab287fcEmmanuel Grumbach */ 631f7b6172db86e9ab2b4cd794441bb2c40ab287fcEmmanuel Grumbachstruct isr_statistics { 641f7b6172db86e9ab2b4cd794441bb2c40ab287fcEmmanuel Grumbach u32 hw; 651f7b6172db86e9ab2b4cd794441bb2c40ab287fcEmmanuel Grumbach u32 sw; 661f7b6172db86e9ab2b4cd794441bb2c40ab287fcEmmanuel Grumbach u32 err_code; 671f7b6172db86e9ab2b4cd794441bb2c40ab287fcEmmanuel Grumbach u32 sch; 681f7b6172db86e9ab2b4cd794441bb2c40ab287fcEmmanuel Grumbach u32 alive; 691f7b6172db86e9ab2b4cd794441bb2c40ab287fcEmmanuel Grumbach u32 rfkill; 701f7b6172db86e9ab2b4cd794441bb2c40ab287fcEmmanuel Grumbach u32 ctkill; 711f7b6172db86e9ab2b4cd794441bb2c40ab287fcEmmanuel Grumbach u32 wakeup; 721f7b6172db86e9ab2b4cd794441bb2c40ab287fcEmmanuel Grumbach u32 rx; 731f7b6172db86e9ab2b4cd794441bb2c40ab287fcEmmanuel Grumbach u32 tx; 741f7b6172db86e9ab2b4cd794441bb2c40ab287fcEmmanuel Grumbach u32 unhandled; 751f7b6172db86e9ab2b4cd794441bb2c40ab287fcEmmanuel Grumbach}; 761f7b6172db86e9ab2b4cd794441bb2c40ab287fcEmmanuel Grumbach 771f7b6172db86e9ab2b4cd794441bb2c40ab287fcEmmanuel Grumbach/** 785a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach * struct iwl_rx_queue - Rx queue 795a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach * @bd: driver's pointer to buffer of receive buffer descriptors (rbd) 805a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach * @bd_dma: bus address of buffer of receive buffer descriptors (rbd) 815a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach * @pool: 825a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach * @queue: 835a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach * @read: Shared index to newest available Rx buffer 845a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach * @write: Shared index to oldest written Rx packet 855a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach * @free_count: Number of pre-allocated buffers in rx_free 865a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach * @write_actual: 875a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach * @rx_free: list of free SKBs for use 885a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach * @rx_used: List of Rx buffers with no SKB 895a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach * @need_update: flag to indicate we need to update read/write index 905a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach * @rb_stts: driver's pointer to receive buffer status 915a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach * @rb_stts_dma: bus address of receive buffer status 925a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach * @lock: 935a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach * 945a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach * NOTE: rx_free and rx_used are used as a FIFO for iwl_rx_mem_buffers 955a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach */ 965a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbachstruct iwl_rx_queue { 975a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach __le32 *bd; 985a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach dma_addr_t bd_dma; 995a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS]; 1005a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE]; 1015a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach u32 read; 1025a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach u32 write; 1035a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach u32 free_count; 1045a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach u32 write_actual; 1055a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach struct list_head rx_free; 1065a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach struct list_head rx_used; 1075a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach int need_update; 1085a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach struct iwl_rb_status *rb_stts; 1095a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach dma_addr_t rb_stts_dma; 1105a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach spinlock_t lock; 1115a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach}; 1125a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach 113a72b8b088c3465b28192c1a14ba97be8223a8cecEmmanuel Grumbachstruct iwl_dma_ptr { 114a72b8b088c3465b28192c1a14ba97be8223a8cecEmmanuel Grumbach dma_addr_t dma; 115a72b8b088c3465b28192c1a14ba97be8223a8cecEmmanuel Grumbach void *addr; 116a72b8b088c3465b28192c1a14ba97be8223a8cecEmmanuel Grumbach size_t size; 117a72b8b088c3465b28192c1a14ba97be8223a8cecEmmanuel Grumbach}; 118a72b8b088c3465b28192c1a14ba97be8223a8cecEmmanuel Grumbach 119bffc66ce2210b149fd171eccad2aef9802c0b35dJohannes Berg/** 120bffc66ce2210b149fd171eccad2aef9802c0b35dJohannes Berg * iwl_queue_inc_wrap - increment queue index, wrap back to beginning 121bffc66ce2210b149fd171eccad2aef9802c0b35dJohannes Berg * @index -- current index 122bffc66ce2210b149fd171eccad2aef9802c0b35dJohannes Berg * @n_bd -- total number of entries in queue (must be power of 2) 123bffc66ce2210b149fd171eccad2aef9802c0b35dJohannes Berg */ 124bffc66ce2210b149fd171eccad2aef9802c0b35dJohannes Bergstatic inline int iwl_queue_inc_wrap(int index, int n_bd) 125bffc66ce2210b149fd171eccad2aef9802c0b35dJohannes Berg{ 126bffc66ce2210b149fd171eccad2aef9802c0b35dJohannes Berg return ++index & (n_bd - 1); 127bffc66ce2210b149fd171eccad2aef9802c0b35dJohannes Berg} 128bffc66ce2210b149fd171eccad2aef9802c0b35dJohannes Berg 129bffc66ce2210b149fd171eccad2aef9802c0b35dJohannes Berg/** 130bffc66ce2210b149fd171eccad2aef9802c0b35dJohannes Berg * iwl_queue_dec_wrap - decrement queue index, wrap back to end 131bffc66ce2210b149fd171eccad2aef9802c0b35dJohannes Berg * @index -- current index 132bffc66ce2210b149fd171eccad2aef9802c0b35dJohannes Berg * @n_bd -- total number of entries in queue (must be power of 2) 133bffc66ce2210b149fd171eccad2aef9802c0b35dJohannes Berg */ 134bffc66ce2210b149fd171eccad2aef9802c0b35dJohannes Bergstatic inline int iwl_queue_dec_wrap(int index, int n_bd) 135bffc66ce2210b149fd171eccad2aef9802c0b35dJohannes Berg{ 136bffc66ce2210b149fd171eccad2aef9802c0b35dJohannes Berg return --index & (n_bd - 1); 137bffc66ce2210b149fd171eccad2aef9802c0b35dJohannes Berg} 138bffc66ce2210b149fd171eccad2aef9802c0b35dJohannes Berg 139e13c0c59e0ec38558ac853d56555e915b4dc7dc2Emmanuel Grumbach/* 140e13c0c59e0ec38558ac853d56555e915b4dc7dc2Emmanuel Grumbach * This queue number is required for proper operation 141e13c0c59e0ec38558ac853d56555e915b4dc7dc2Emmanuel Grumbach * because the ucode will stop/start the scheduler as 142e13c0c59e0ec38558ac853d56555e915b4dc7dc2Emmanuel Grumbach * required. 143e13c0c59e0ec38558ac853d56555e915b4dc7dc2Emmanuel Grumbach */ 144e13c0c59e0ec38558ac853d56555e915b4dc7dc2Emmanuel Grumbach#define IWL_IPAN_MCAST_QUEUE 8 145e13c0c59e0ec38558ac853d56555e915b4dc7dc2Emmanuel Grumbach 146522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbachstruct iwl_cmd_meta { 147522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach /* only for SYNC commands, iff the reply skb is wanted */ 148522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach struct iwl_host_cmd *source; 149522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach 150522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach u32 flags; 151522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach 152522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach DEFINE_DMA_UNMAP_ADDR(mapping); 153522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach DEFINE_DMA_UNMAP_LEN(len); 154522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach}; 155522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach 156522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach/* 157522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach * Generic queue structure 158522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach * 159522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach * Contains common data for Rx and Tx queues. 160522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach * 161522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach * Note the difference between n_bd and n_window: the hardware 162522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach * always assumes 256 descriptors, so n_bd is always 256 (unless 163522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach * there might be HW changes in the future). For the normal TX 164522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach * queues, n_window, which is the size of the software queue data 165522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach * is also 256; however, for the command queue, n_window is only 166522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach * 32 since we don't need so many commands pending. Since the HW 167522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach * still uses 256 BDs for DMA though, n_bd stays 256. As a result, 168522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach * the software buffers (in the variables @meta, @txb in struct 169522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach * iwl_tx_queue) only have 32 entries, while the HW buffers (@tfds 170522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach * in the same struct) have 256. 171522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach * This means that we end up with the following: 172522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach * HW entries: | 0 | ... | N * 32 | ... | N * 32 + 31 | ... | 255 | 173522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach * SW entries: | 0 | ... | 31 | 174522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach * where N is a number between 0 and 7. This means that the SW 175522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach * data is a window overlayed over the HW queue. 176522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach */ 177522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbachstruct iwl_queue { 178522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach int n_bd; /* number of BDs in this queue */ 179522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach int write_ptr; /* 1-st empty entry (index) host_w*/ 180522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach int read_ptr; /* last used entry (index) host_r*/ 181522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach /* use for monitoring and recovering the stuck queue */ 182522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach dma_addr_t dma_addr; /* physical addr for BD's */ 183522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach int n_window; /* safe queue window */ 184522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach u32 id; 185522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach int low_mark; /* low watermark, resume queue if free 186522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach * space more than this */ 187522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach int high_mark; /* high watermark, stop queue if free 188522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach * space less than this */ 189522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach}; 190522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach 191522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach/** 192522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach * struct iwl_tx_queue - Tx Queue for DMA 193522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach * @q: generic Rx/Tx queue descriptor 194522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach * @bd: base of circular buffer of TFDs 195522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach * @cmd: array of command/TX buffer pointers 196522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach * @meta: array of meta data for each command/tx buffer 197522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach * @dma_addr_cmd: physical address of cmd/tx buffer array 198522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach * @txb: array of per-TFD driver data 199015c15e1067c988fc87fb550b222f075c8d3f47cJohannes Berg * lock: queue lock 200522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach * @time_stamp: time (in jiffies) of last read_ptr change 201522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach * @need_update: indicates need to update read/write index 202522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach * @sched_retry: indicates queue is high-throughput aggregation (HT AGG) enabled 203522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach * @sta_id: valid if sched_retry is set 204522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach * @tid: valid if sched_retry is set 205522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach * 206522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach * A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame 207522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach * descriptors) and required locking structures. 208522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach */ 209522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach#define TFD_TX_CMD_SLOTS 256 210522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach#define TFD_CMD_SLOTS 32 211522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach 212522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbachstruct iwl_tx_queue { 213522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach struct iwl_queue q; 214522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach struct iwl_tfd *tfds; 215522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach struct iwl_device_cmd **cmd; 216522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach struct iwl_cmd_meta *meta; 217522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach struct sk_buff **skbs; 218015c15e1067c988fc87fb550b222f075c8d3f47cJohannes Berg spinlock_t lock; 219522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach unsigned long time_stamp; 220522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach u8 need_update; 221522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach u8 sched_retry; 222522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach u8 active; 223522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach u8 swq_id; 224522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach 225522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach u16 sta_id; 226522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach u16 tid; 227522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach}; 228522376d206da66cecc90929134ad70c0446e874bEmmanuel Grumbach 2295a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach/** 230e6bb4c9c00892c488f3218ea317dc6a71674faf4Emmanuel Grumbach * struct iwl_trans_pcie - PCIe transport specific data 2315a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach * @rxq: all the RX queue data 2325a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach * @rx_replenish: work that will be called when buffers need to be allocated 2335a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach * @trans: pointer to the generic transport area 2347559553660da6cda3aa798c4e8eb681b63402819Johannes Berg * @irq - the irq number for the device 23557a1dc89097982874f50a0e6f68ab08f62e9e5aaEmmanuel Grumbach * @irq_requested: true when the irq has been requested 236105183b156b7c220b47c3162e087101a0a6abc9fEmmanuel Grumbach * @scd_base_addr: scheduler sram base address in SRAM 237105183b156b7c220b47c3162e087101a0a6abc9fEmmanuel Grumbach * @scd_bc_tbls: pointer to the byte count table of the scheduler 2389d6b2cb1ccf9c1e00a0891eff78b93eb1a1fc372Emmanuel Grumbach * @kw: keep warm address 239e13c0c59e0ec38558ac853d56555e915b4dc7dc2Emmanuel Grumbach * @ac_to_fifo: to what fifo is a specifc AC mapped ? 240e13c0c59e0ec38558ac853d56555e915b4dc7dc2Emmanuel Grumbach * @ac_to_queue: to what tx queue is a specifc AC mapped ? 241e13c0c59e0ec38558ac853d56555e915b4dc7dc2Emmanuel Grumbach * @mcast_queue: 2428ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbach * @txq: Tx DMA processing queues 2438ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbach * @txq_ctx_active_msk: what queue is active 2448ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbach * queue_stopped: tracks what queue is stopped 2458ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbach * queue_stop_count: tracks what SW queue is stopped 246a42a184458ae95937893cb873c988385637c5e14Emmanuel Grumbach * @pci_dev: basic pci-network driver stuff 247a42a184458ae95937893cb873c988385637c5e14Emmanuel Grumbach * @hw_base: pci hardware address support 24813df1aab4aa3cd99693c0cdeb7177e5359218431Johannes Berg * @ucode_write_complete: indicates that the ucode has been copied. 24913df1aab4aa3cd99693c0cdeb7177e5359218431Johannes Berg * @ucode_write_waitq: wait queue for uCode load 2509a716863ae4a2f039bc4d0b2b2bb4b24a1dc7a91Don Fry * @status - transport specific status flags 251c6f600fcfe8a7e4f594fc4c80b2c7b66f248958bMeenakshi Venkataraman * @cmd_queue - command queue number 252e6bb4c9c00892c488f3218ea317dc6a71674faf4Emmanuel Grumbach */ 253e6bb4c9c00892c488f3218ea317dc6a71674faf4Emmanuel Grumbachstruct iwl_trans_pcie { 2545a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach struct iwl_rx_queue rxq; 2555a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach struct work_struct rx_replenish; 2565a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach struct iwl_trans *trans; 2570c325769a394559941acda83e888a1d9b1ef8b7fEmmanuel Grumbach 2580c325769a394559941acda83e888a1d9b1ef8b7fEmmanuel Grumbach /* INT ICT Table */ 2590c325769a394559941acda83e888a1d9b1ef8b7fEmmanuel Grumbach __le32 *ict_tbl; 2600c325769a394559941acda83e888a1d9b1ef8b7fEmmanuel Grumbach dma_addr_t ict_tbl_dma; 2610c325769a394559941acda83e888a1d9b1ef8b7fEmmanuel Grumbach int ict_index; 2620c325769a394559941acda83e888a1d9b1ef8b7fEmmanuel Grumbach u32 inta; 2630c325769a394559941acda83e888a1d9b1ef8b7fEmmanuel Grumbach bool use_ict; 26457a1dc89097982874f50a0e6f68ab08f62e9e5aaEmmanuel Grumbach bool irq_requested; 2650c325769a394559941acda83e888a1d9b1ef8b7fEmmanuel Grumbach struct tasklet_struct irq_tasklet; 2661f7b6172db86e9ab2b4cd794441bb2c40ab287fcEmmanuel Grumbach struct isr_statistics isr_stats; 2670c325769a394559941acda83e888a1d9b1ef8b7fEmmanuel Grumbach 2687559553660da6cda3aa798c4e8eb681b63402819Johannes Berg unsigned int irq; 2697b11488fbbbe06ada39a396dec16532db8c933e6Johannes Berg spinlock_t irq_lock; 2700c325769a394559941acda83e888a1d9b1ef8b7fEmmanuel Grumbach u32 inta_mask; 271105183b156b7c220b47c3162e087101a0a6abc9fEmmanuel Grumbach u32 scd_base_addr; 272105183b156b7c220b47c3162e087101a0a6abc9fEmmanuel Grumbach struct iwl_dma_ptr scd_bc_tbls; 2739d6b2cb1ccf9c1e00a0891eff78b93eb1a1fc372Emmanuel Grumbach struct iwl_dma_ptr kw; 274e13c0c59e0ec38558ac853d56555e915b4dc7dc2Emmanuel Grumbach 275e13c0c59e0ec38558ac853d56555e915b4dc7dc2Emmanuel Grumbach const u8 *ac_to_fifo[NUM_IWL_RXON_CTX]; 276e13c0c59e0ec38558ac853d56555e915b4dc7dc2Emmanuel Grumbach const u8 *ac_to_queue[NUM_IWL_RXON_CTX]; 277e13c0c59e0ec38558ac853d56555e915b4dc7dc2Emmanuel Grumbach u8 mcast_queue[NUM_IWL_RXON_CTX]; 27876bc10fcd128ad028cf77c62e179cd20dc2ffecfEmmanuel Grumbach u8 agg_txq[IWLAGN_STATION_COUNT][IWL_MAX_TID_COUNT]; 2798ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbach 2808ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbach struct iwl_tx_queue *txq; 2818ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbach unsigned long txq_ctx_active_msk; 2828ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbach#define IWL_MAX_HW_QUEUES 32 2838ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbach unsigned long queue_stopped[BITS_TO_LONGS(IWL_MAX_HW_QUEUES)]; 2848ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbach atomic_t queue_stop_count[4]; 285a42a184458ae95937893cb873c988385637c5e14Emmanuel Grumbach 286a42a184458ae95937893cb873c988385637c5e14Emmanuel Grumbach /* PCI bus related data */ 287a42a184458ae95937893cb873c988385637c5e14Emmanuel Grumbach struct pci_dev *pci_dev; 288a42a184458ae95937893cb873c988385637c5e14Emmanuel Grumbach void __iomem *hw_base; 28913df1aab4aa3cd99693c0cdeb7177e5359218431Johannes Berg 29013df1aab4aa3cd99693c0cdeb7177e5359218431Johannes Berg bool ucode_write_complete; 29113df1aab4aa3cd99693c0cdeb7177e5359218431Johannes Berg wait_queue_head_t ucode_write_waitq; 2929a716863ae4a2f039bc4d0b2b2bb4b24a1dc7a91Don Fry unsigned long status; 293c6f600fcfe8a7e4f594fc4c80b2c7b66f248958bMeenakshi Venkataraman u8 cmd_queue; 294d663ee73f62903aed334eca25832a76c4a7e4c1cJohannes Berg u8 n_no_reclaim_cmds; 295d663ee73f62903aed334eca25832a76c4a7e4c1cJohannes Berg u8 no_reclaim_cmds[MAX_NO_RECLAIM_CMDS]; 296e6bb4c9c00892c488f3218ea317dc6a71674faf4Emmanuel Grumbach}; 297e6bb4c9c00892c488f3218ea317dc6a71674faf4Emmanuel Grumbach 2985a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach#define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \ 2995a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach ((struct iwl_trans_pcie *) ((_iwl_trans)->trans_specific)) 3005a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbach 301253a634ccd1b291282cd0cade219bd90eb0371ebEmmanuel Grumbach/***************************************************** 302253a634ccd1b291282cd0cade219bd90eb0371ebEmmanuel Grumbach* RX 303253a634ccd1b291282cd0cade219bd90eb0371ebEmmanuel Grumbach******************************************************/ 304ab697a9f1e73ba817955e15bd899a8a0627f9fd6Emmanuel Grumbachvoid iwl_bg_rx_replenish(struct work_struct *data); 3050c325769a394559941acda83e888a1d9b1ef8b7fEmmanuel Grumbachvoid iwl_irq_tasklet(struct iwl_trans *trans); 3065a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbachvoid iwlagn_rx_replenish(struct iwl_trans *trans); 3075a878bf60b2bb1f1509f49b8b1784e3c9f204c64Emmanuel Grumbachvoid iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, 308ab697a9f1e73ba817955e15bd899a8a0627f9fd6Emmanuel Grumbach struct iwl_rx_queue *q); 309ab697a9f1e73ba817955e15bd899a8a0627f9fd6Emmanuel Grumbach 310253a634ccd1b291282cd0cade219bd90eb0371ebEmmanuel Grumbach/***************************************************** 3111a361cd838173879672cb0f0ebe1e7654d7edff6Emmanuel Grumbach* ICT 3121a361cd838173879672cb0f0ebe1e7654d7edff6Emmanuel Grumbach******************************************************/ 313ed6a3803408f18da387463d569b4edc5078fd9aaEmmanuel Grumbachvoid iwl_reset_ict(struct iwl_trans *trans); 3140c325769a394559941acda83e888a1d9b1ef8b7fEmmanuel Grumbachvoid iwl_disable_ict(struct iwl_trans *trans); 3150c325769a394559941acda83e888a1d9b1ef8b7fEmmanuel Grumbachint iwl_alloc_isr_ict(struct iwl_trans *trans); 3160c325769a394559941acda83e888a1d9b1ef8b7fEmmanuel Grumbachvoid iwl_free_isr_ict(struct iwl_trans *trans); 3171a361cd838173879672cb0f0ebe1e7654d7edff6Emmanuel Grumbachirqreturn_t iwl_isr_ict(int irq, void *data); 3181a361cd838173879672cb0f0ebe1e7654d7edff6Emmanuel Grumbach 3191a361cd838173879672cb0f0ebe1e7654d7edff6Emmanuel Grumbach/***************************************************** 320253a634ccd1b291282cd0cade219bd90eb0371ebEmmanuel Grumbach* TX / HCMD 321253a634ccd1b291282cd0cade219bd90eb0371ebEmmanuel Grumbach******************************************************/ 322fd656935cd05f522d7db97386633f6a0d7751218Emmanuel Grumbachvoid iwl_txq_update_write_ptr(struct iwl_trans *trans, 323fd656935cd05f522d7db97386633f6a0d7751218Emmanuel Grumbach struct iwl_tx_queue *txq); 3246d8f6eeb350696050a1f5cf8f9d0daabab68eaf5Emmanuel Grumbachint iwlagn_txq_attach_buf_to_tfd(struct iwl_trans *trans, 325253a634ccd1b291282cd0cade219bd90eb0371ebEmmanuel Grumbach struct iwl_tx_queue *txq, 326253a634ccd1b291282cd0cade219bd90eb0371ebEmmanuel Grumbach dma_addr_t addr, u16 len, u8 reset); 3276d8f6eeb350696050a1f5cf8f9d0daabab68eaf5Emmanuel Grumbachint iwl_queue_init(struct iwl_queue *q, int count, int slots_num, u32 id); 3286d8f6eeb350696050a1f5cf8f9d0daabab68eaf5Emmanuel Grumbachint iwl_trans_pcie_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd); 3293e10caeb55b2693b38f1f80c67c79d918fc42e42Emmanuel Grumbachvoid iwl_tx_cmd_complete(struct iwl_trans *trans, 33048a2d66f58d2bf1818acf5ff7ed9897a9977a96eJohannes Berg struct iwl_rx_cmd_buffer *rxb, int handler_status); 3316d8f6eeb350696050a1f5cf8f9d0daabab68eaf5Emmanuel Grumbachvoid iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans, 33248d42c426947d8ffba0caa3cf9c58be6903302e0Emmanuel Grumbach struct iwl_tx_queue *txq, 33348d42c426947d8ffba0caa3cf9c58be6903302e0Emmanuel Grumbach u16 byte_cnt); 3347f01d567c5b9e136d9b070e00be88169d5b2227eEmmanuel Grumbachint iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans, 335bc23773059ecea24cb653994686d230b6be08536Emmanuel Grumbach int sta_id, int tid); 3366d8f6eeb350696050a1f5cf8f9d0daabab68eaf5Emmanuel Grumbachvoid iwl_trans_set_wr_ptrs(struct iwl_trans *trans, int txq_id, u32 index); 337c91bd12489f50809af94c46d7c4c4d98b70c6f47Emmanuel Grumbachvoid iwl_trans_tx_queue_set_status(struct iwl_trans *trans, 33848d42c426947d8ffba0caa3cf9c58be6903302e0Emmanuel Grumbach struct iwl_tx_queue *txq, 33948d42c426947d8ffba0caa3cf9c58be6903302e0Emmanuel Grumbach int tx_fifo_id, int scd_retry); 3403c69b5954225b41cfa57338b17466816072d55a2Emmanuel Grumbachint iwl_trans_pcie_tx_agg_alloc(struct iwl_trans *trans, int sta_id, int tid); 341c91bd12489f50809af94c46d7c4c4d98b70c6f47Emmanuel Grumbachvoid iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans, 342c91bd12489f50809af94c46d7c4c4d98b70c6f47Emmanuel Grumbach enum iwl_rxon_context_id ctx, 343822e8b2a2d708f99daf1ae4cd9b9e4c9d84069c6Emmanuel Grumbach int sta_id, int tid, int frame_limit, u16 ssn); 3446d8f6eeb350696050a1f5cf8f9d0daabab68eaf5Emmanuel Grumbachvoid iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq, 34577bcff9d8249e55b43349ddc3f5ef3b8a63600b8Emmanuel Grumbach enum dma_data_direction dma_dir); 346464021ffc1c080283e67729d966d76612728a08cEmmanuel Grumbachint iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, 347464021ffc1c080283e67729d966d76612728a08cEmmanuel Grumbach struct sk_buff_head *skbs); 3488ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbachint iwl_queue_space(const struct iwl_queue *q); 349253a634ccd1b291282cd0cade219bd90eb0371ebEmmanuel Grumbach 3507ff94706a055f3e21710b08ffbe3979d7db615dbEmmanuel Grumbach/***************************************************** 3517ff94706a055f3e21710b08ffbe3979d7db615dbEmmanuel Grumbach* Error handling 3527ff94706a055f3e21710b08ffbe3979d7db615dbEmmanuel Grumbach******************************************************/ 3536bb7884758965ad0afd67801f0f41cefd53d0b0cEmmanuel Grumbachint iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log, 3546bb7884758965ad0afd67801f0f41cefd53d0b0cEmmanuel Grumbach char **buf, bool display); 35516db88ba51d669ef63c58990771a47208913152cEmmanuel Grumbachint iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display); 35616db88ba51d669ef63c58990771a47208913152cEmmanuel Grumbachvoid iwl_dump_csr(struct iwl_trans *trans); 35716db88ba51d669ef63c58990771a47208913152cEmmanuel Grumbach 3588ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbach/***************************************************** 3598ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbach* Helpers 3608ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbach******************************************************/ 3610c325769a394559941acda83e888a1d9b1ef8b7fEmmanuel Grumbachstatic inline void iwl_disable_interrupts(struct iwl_trans *trans) 3620c325769a394559941acda83e888a1d9b1ef8b7fEmmanuel Grumbach{ 36383626404a70da74c67f32f119e53c0ba032ba2d8Don Fry struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 36483626404a70da74c67f32f119e53c0ba032ba2d8Don Fry clear_bit(STATUS_INT_ENABLED, &trans_pcie->status); 3650c325769a394559941acda83e888a1d9b1ef8b7fEmmanuel Grumbach 3660c325769a394559941acda83e888a1d9b1ef8b7fEmmanuel Grumbach /* disable interrupts from uCode/NIC to host */ 3671042db2af183b96cdce5972014d85e8bca0634adEmmanuel Grumbach iwl_write32(trans, CSR_INT_MASK, 0x00000000); 3680c325769a394559941acda83e888a1d9b1ef8b7fEmmanuel Grumbach 3690c325769a394559941acda83e888a1d9b1ef8b7fEmmanuel Grumbach /* acknowledge/clear/reset any interrupts still pending 3700c325769a394559941acda83e888a1d9b1ef8b7fEmmanuel Grumbach * from uCode or flow handler (Rx/Tx DMA) */ 3711042db2af183b96cdce5972014d85e8bca0634adEmmanuel Grumbach iwl_write32(trans, CSR_INT, 0xffffffff); 3721042db2af183b96cdce5972014d85e8bca0634adEmmanuel Grumbach iwl_write32(trans, CSR_FH_INT_STATUS, 0xffffffff); 3730c325769a394559941acda83e888a1d9b1ef8b7fEmmanuel Grumbach IWL_DEBUG_ISR(trans, "Disabled interrupts\n"); 3740c325769a394559941acda83e888a1d9b1ef8b7fEmmanuel Grumbach} 3750c325769a394559941acda83e888a1d9b1ef8b7fEmmanuel Grumbach 3760c325769a394559941acda83e888a1d9b1ef8b7fEmmanuel Grumbachstatic inline void iwl_enable_interrupts(struct iwl_trans *trans) 3770c325769a394559941acda83e888a1d9b1ef8b7fEmmanuel Grumbach{ 37883626404a70da74c67f32f119e53c0ba032ba2d8Don Fry struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 3790c325769a394559941acda83e888a1d9b1ef8b7fEmmanuel Grumbach 3800c325769a394559941acda83e888a1d9b1ef8b7fEmmanuel Grumbach IWL_DEBUG_ISR(trans, "Enabling interrupts\n"); 38183626404a70da74c67f32f119e53c0ba032ba2d8Don Fry set_bit(STATUS_INT_ENABLED, &trans_pcie->status); 3821042db2af183b96cdce5972014d85e8bca0634adEmmanuel Grumbach iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask); 3830c325769a394559941acda83e888a1d9b1ef8b7fEmmanuel Grumbach} 3840c325769a394559941acda83e888a1d9b1ef8b7fEmmanuel Grumbach 3858722c899a07f45457464803142bd1c2d2a2c3bd8Stanislaw Gruszkastatic inline void iwl_enable_rfkill_int(struct iwl_trans *trans) 3868722c899a07f45457464803142bd1c2d2a2c3bd8Stanislaw Gruszka{ 3878722c899a07f45457464803142bd1c2d2a2c3bd8Stanislaw Gruszka IWL_DEBUG_ISR(trans, "Enabling rfkill interrupt\n"); 3888722c899a07f45457464803142bd1c2d2a2c3bd8Stanislaw Gruszka iwl_write32(trans, CSR_INT_MASK, CSR_INT_BIT_RF_KILL); 3898722c899a07f45457464803142bd1c2d2a2c3bd8Stanislaw Gruszka} 3908722c899a07f45457464803142bd1c2d2a2c3bd8Stanislaw Gruszka 391e20d434170c3a7f388d5e916825499c9c0738606Emmanuel Grumbach/* 392e20d434170c3a7f388d5e916825499c9c0738606Emmanuel Grumbach * we have 8 bits used like this: 393e20d434170c3a7f388d5e916825499c9c0738606Emmanuel Grumbach * 394e20d434170c3a7f388d5e916825499c9c0738606Emmanuel Grumbach * 7 6 5 4 3 2 1 0 395e20d434170c3a7f388d5e916825499c9c0738606Emmanuel Grumbach * | | | | | | | | 396e20d434170c3a7f388d5e916825499c9c0738606Emmanuel Grumbach * | | | | | | +-+-------- AC queue (0-3) 397e20d434170c3a7f388d5e916825499c9c0738606Emmanuel Grumbach * | | | | | | 398e20d434170c3a7f388d5e916825499c9c0738606Emmanuel Grumbach * | +-+-+-+-+------------ HW queue ID 399e20d434170c3a7f388d5e916825499c9c0738606Emmanuel Grumbach * | 400e20d434170c3a7f388d5e916825499c9c0738606Emmanuel Grumbach * +---------------------- unused 401e20d434170c3a7f388d5e916825499c9c0738606Emmanuel Grumbach */ 402e20d434170c3a7f388d5e916825499c9c0738606Emmanuel Grumbachstatic inline void iwl_set_swq_id(struct iwl_tx_queue *txq, u8 ac, u8 hwq) 403e20d434170c3a7f388d5e916825499c9c0738606Emmanuel Grumbach{ 404e20d434170c3a7f388d5e916825499c9c0738606Emmanuel Grumbach BUG_ON(ac > 3); /* only have 2 bits */ 405e20d434170c3a7f388d5e916825499c9c0738606Emmanuel Grumbach BUG_ON(hwq > 31); /* only use 5 bits */ 406e20d434170c3a7f388d5e916825499c9c0738606Emmanuel Grumbach 407e20d434170c3a7f388d5e916825499c9c0738606Emmanuel Grumbach txq->swq_id = (hwq << 2) | ac; 408e20d434170c3a7f388d5e916825499c9c0738606Emmanuel Grumbach} 409e20d434170c3a7f388d5e916825499c9c0738606Emmanuel Grumbach 4101daf04b8ac51f911f32aedc77f7f6559924d8ab3Emmanuel Grumbachstatic inline u8 iwl_get_queue_ac(struct iwl_tx_queue *txq) 4111daf04b8ac51f911f32aedc77f7f6559924d8ab3Emmanuel Grumbach{ 4121daf04b8ac51f911f32aedc77f7f6559924d8ab3Emmanuel Grumbach return txq->swq_id & 0x3; 4131daf04b8ac51f911f32aedc77f7f6559924d8ab3Emmanuel Grumbach} 4141daf04b8ac51f911f32aedc77f7f6559924d8ab3Emmanuel Grumbach 415e20d434170c3a7f388d5e916825499c9c0738606Emmanuel Grumbachstatic inline void iwl_wake_queue(struct iwl_trans *trans, 416bada991b4590122c847520ed2b651b679c16afd3Johannes Berg struct iwl_tx_queue *txq) 417e20d434170c3a7f388d5e916825499c9c0738606Emmanuel Grumbach{ 418e20d434170c3a7f388d5e916825499c9c0738606Emmanuel Grumbach u8 queue = txq->swq_id; 419e20d434170c3a7f388d5e916825499c9c0738606Emmanuel Grumbach u8 ac = queue & 3; 420e20d434170c3a7f388d5e916825499c9c0738606Emmanuel Grumbach u8 hwq = (queue >> 2) & 0x1f; 4218ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbach struct iwl_trans_pcie *trans_pcie = 4228ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbach IWL_TRANS_GET_PCIE_TRANS(trans); 423e20d434170c3a7f388d5e916825499c9c0738606Emmanuel Grumbach 42481a3de1ce2929fef2b112c048c50bc52b686f94dEmmanuel Grumbach if (test_and_clear_bit(hwq, trans_pcie->queue_stopped)) { 42581a3de1ce2929fef2b112c048c50bc52b686f94dEmmanuel Grumbach if (atomic_dec_return(&trans_pcie->queue_stop_count[ac]) <= 0) { 42602e3835884f352ac707dcf14d8bf455c0c0acbc5Emmanuel Grumbach iwl_op_mode_queue_not_full(trans->op_mode, ac); 427bada991b4590122c847520ed2b651b679c16afd3Johannes Berg IWL_DEBUG_TX_QUEUES(trans, "Wake hwq %d ac %d", 428bada991b4590122c847520ed2b651b679c16afd3Johannes Berg hwq, ac); 42981a3de1ce2929fef2b112c048c50bc52b686f94dEmmanuel Grumbach } else { 430bada991b4590122c847520ed2b651b679c16afd3Johannes Berg IWL_DEBUG_TX_QUEUES(trans, 431bada991b4590122c847520ed2b651b679c16afd3Johannes Berg "Don't wake hwq %d ac %d stop count %d", 432bada991b4590122c847520ed2b651b679c16afd3Johannes Berg hwq, ac, 433bada991b4590122c847520ed2b651b679c16afd3Johannes Berg atomic_read(&trans_pcie->queue_stop_count[ac])); 43481a3de1ce2929fef2b112c048c50bc52b686f94dEmmanuel Grumbach } 43581a3de1ce2929fef2b112c048c50bc52b686f94dEmmanuel Grumbach } 436e20d434170c3a7f388d5e916825499c9c0738606Emmanuel Grumbach} 437e20d434170c3a7f388d5e916825499c9c0738606Emmanuel Grumbach 438e20d434170c3a7f388d5e916825499c9c0738606Emmanuel Grumbachstatic inline void iwl_stop_queue(struct iwl_trans *trans, 439bada991b4590122c847520ed2b651b679c16afd3Johannes Berg struct iwl_tx_queue *txq) 440e20d434170c3a7f388d5e916825499c9c0738606Emmanuel Grumbach{ 441e20d434170c3a7f388d5e916825499c9c0738606Emmanuel Grumbach u8 queue = txq->swq_id; 442e20d434170c3a7f388d5e916825499c9c0738606Emmanuel Grumbach u8 ac = queue & 3; 443e20d434170c3a7f388d5e916825499c9c0738606Emmanuel Grumbach u8 hwq = (queue >> 2) & 0x1f; 4448ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbach struct iwl_trans_pcie *trans_pcie = 4458ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbach IWL_TRANS_GET_PCIE_TRANS(trans); 446e20d434170c3a7f388d5e916825499c9c0738606Emmanuel Grumbach 44781a3de1ce2929fef2b112c048c50bc52b686f94dEmmanuel Grumbach if (!test_and_set_bit(hwq, trans_pcie->queue_stopped)) { 44881a3de1ce2929fef2b112c048c50bc52b686f94dEmmanuel Grumbach if (atomic_inc_return(&trans_pcie->queue_stop_count[ac]) > 0) { 44902e3835884f352ac707dcf14d8bf455c0c0acbc5Emmanuel Grumbach iwl_op_mode_queue_full(trans->op_mode, ac); 450bada991b4590122c847520ed2b651b679c16afd3Johannes Berg IWL_DEBUG_TX_QUEUES(trans, 451bada991b4590122c847520ed2b651b679c16afd3Johannes Berg "Stop hwq %d ac %d stop count %d", 452bada991b4590122c847520ed2b651b679c16afd3Johannes Berg hwq, ac, 453bada991b4590122c847520ed2b651b679c16afd3Johannes Berg atomic_read(&trans_pcie->queue_stop_count[ac])); 45481a3de1ce2929fef2b112c048c50bc52b686f94dEmmanuel Grumbach } else { 455bada991b4590122c847520ed2b651b679c16afd3Johannes Berg IWL_DEBUG_TX_QUEUES(trans, 456bada991b4590122c847520ed2b651b679c16afd3Johannes Berg "Don't stop hwq %d ac %d stop count %d", 457bada991b4590122c847520ed2b651b679c16afd3Johannes Berg hwq, ac, 458bada991b4590122c847520ed2b651b679c16afd3Johannes Berg atomic_read(&trans_pcie->queue_stop_count[ac])); 45981a3de1ce2929fef2b112c048c50bc52b686f94dEmmanuel Grumbach } 46081a3de1ce2929fef2b112c048c50bc52b686f94dEmmanuel Grumbach } else { 461bada991b4590122c847520ed2b651b679c16afd3Johannes Berg IWL_DEBUG_TX_QUEUES(trans, "stop hwq %d, but it is stopped", 462bada991b4590122c847520ed2b651b679c16afd3Johannes Berg hwq); 46381a3de1ce2929fef2b112c048c50bc52b686f94dEmmanuel Grumbach } 464e20d434170c3a7f388d5e916825499c9c0738606Emmanuel Grumbach} 465e20d434170c3a7f388d5e916825499c9c0738606Emmanuel Grumbach 4668ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbachstatic inline void iwl_txq_ctx_activate(struct iwl_trans_pcie *trans_pcie, 4678ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbach int txq_id) 4688ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbach{ 4698ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbach set_bit(txq_id, &trans_pcie->txq_ctx_active_msk); 4708ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbach} 4718ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbach 4728ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbachstatic inline void iwl_txq_ctx_deactivate(struct iwl_trans_pcie *trans_pcie, 4738ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbach int txq_id) 4748ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbach{ 4758ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbach clear_bit(txq_id, &trans_pcie->txq_ctx_active_msk); 4768ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbach} 4778ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbach 4788ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbachstatic inline int iwl_queue_used(const struct iwl_queue *q, int i) 4798ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbach{ 4808ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbach return q->write_ptr >= q->read_ptr ? 4818ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbach (i >= q->read_ptr && i < q->write_ptr) : 4828ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbach !(i < q->read_ptr && i >= q->write_ptr); 4838ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbach} 4848ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbach 4858ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbachstatic inline u8 get_cmd_index(struct iwl_queue *q, u32 index) 4868ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbach{ 4878ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbach return index & (q->n_window - 1); 4888ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbach} 4898ad71bef4a9d8173cbcfbb2f796b08d33d4ca01bEmmanuel Grumbach 4907a10e3e4076d09779da5a02b0ab6ce551d964d48Emmanuel Grumbach#define IWL_TX_FIFO_BK 0 /* shared */ 4917a10e3e4076d09779da5a02b0ab6ce551d964d48Emmanuel Grumbach#define IWL_TX_FIFO_BE 1 4927a10e3e4076d09779da5a02b0ab6ce551d964d48Emmanuel Grumbach#define IWL_TX_FIFO_VI 2 /* shared */ 4937a10e3e4076d09779da5a02b0ab6ce551d964d48Emmanuel Grumbach#define IWL_TX_FIFO_VO 3 4947a10e3e4076d09779da5a02b0ab6ce551d964d48Emmanuel Grumbach#define IWL_TX_FIFO_BK_IPAN IWL_TX_FIFO_BK 4957a10e3e4076d09779da5a02b0ab6ce551d964d48Emmanuel Grumbach#define IWL_TX_FIFO_BE_IPAN 4 4967a10e3e4076d09779da5a02b0ab6ce551d964d48Emmanuel Grumbach#define IWL_TX_FIFO_VI_IPAN IWL_TX_FIFO_VI 4977a10e3e4076d09779da5a02b0ab6ce551d964d48Emmanuel Grumbach#define IWL_TX_FIFO_VO_IPAN 5 4987a10e3e4076d09779da5a02b0ab6ce551d964d48Emmanuel Grumbach/* re-uses the VO FIFO, uCode will properly flush/schedule */ 4997a10e3e4076d09779da5a02b0ab6ce551d964d48Emmanuel Grumbach#define IWL_TX_FIFO_AUX 5 5007a10e3e4076d09779da5a02b0ab6ce551d964d48Emmanuel Grumbach#define IWL_TX_FIFO_UNUSED -1 5017a10e3e4076d09779da5a02b0ab6ce551d964d48Emmanuel Grumbach 5027a10e3e4076d09779da5a02b0ab6ce551d964d48Emmanuel Grumbach/* AUX (TX during scan dwell) queue */ 5037a10e3e4076d09779da5a02b0ab6ce551d964d48Emmanuel Grumbach#define IWL_AUX_QUEUE 10 5047a10e3e4076d09779da5a02b0ab6ce551d964d48Emmanuel Grumbach 505ab697a9f1e73ba817955e15bd899a8a0627f9fd6Emmanuel Grumbach#endif /* __iwl_trans_int_pcie_h__ */ 506