diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/pcie/internal.h')
-rw-r--r-- | drivers/net/wireless/iwlwifi/pcie/internal.h | 440 |
1 files changed, 440 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h new file mode 100644 index 000000000000..5024fb662bf6 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/pcie/internal.h | |||
@@ -0,0 +1,440 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. | ||
4 | * | ||
5 | * Portions of this file are derived from the ipw3945 project, as well | ||
6 | * as portions of the ieee80211 subsystem header files. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of version 2 of the GNU General Public License as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
15 | * more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along with | ||
18 | * this program; if not, write to the Free Software Foundation, Inc., | ||
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
20 | * | ||
21 | * The full GNU General Public License is included in this distribution in the | ||
22 | * file called LICENSE. | ||
23 | * | ||
24 | * Contact Information: | ||
25 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | #ifndef __iwl_trans_int_pcie_h__ | ||
30 | #define __iwl_trans_int_pcie_h__ | ||
31 | |||
32 | #include <linux/spinlock.h> | ||
33 | #include <linux/interrupt.h> | ||
34 | #include <linux/skbuff.h> | ||
35 | #include <linux/wait.h> | ||
36 | #include <linux/pci.h> | ||
37 | #include <linux/timer.h> | ||
38 | |||
39 | #include "iwl-fh.h" | ||
40 | #include "iwl-csr.h" | ||
41 | #include "iwl-trans.h" | ||
42 | #include "iwl-debug.h" | ||
43 | #include "iwl-io.h" | ||
44 | #include "iwl-op-mode.h" | ||
45 | |||
46 | struct iwl_host_cmd; | ||
47 | |||
48 | /*This file includes the declaration that are internal to the | ||
49 | * trans_pcie layer */ | ||
50 | |||
51 | struct iwl_rx_mem_buffer { | ||
52 | dma_addr_t page_dma; | ||
53 | struct page *page; | ||
54 | struct list_head list; | ||
55 | }; | ||
56 | |||
57 | /** | ||
58 | * struct isr_statistics - interrupt statistics | ||
59 | * | ||
60 | */ | ||
61 | struct isr_statistics { | ||
62 | u32 hw; | ||
63 | u32 sw; | ||
64 | u32 err_code; | ||
65 | u32 sch; | ||
66 | u32 alive; | ||
67 | u32 rfkill; | ||
68 | u32 ctkill; | ||
69 | u32 wakeup; | ||
70 | u32 rx; | ||
71 | u32 tx; | ||
72 | u32 unhandled; | ||
73 | }; | ||
74 | |||
75 | /** | ||
76 | * struct iwl_rx_queue - Rx queue | ||
77 | * @bd: driver's pointer to buffer of receive buffer descriptors (rbd) | ||
78 | * @bd_dma: bus address of buffer of receive buffer descriptors (rbd) | ||
79 | * @pool: | ||
80 | * @queue: | ||
81 | * @read: Shared index to newest available Rx buffer | ||
82 | * @write: Shared index to oldest written Rx packet | ||
83 | * @free_count: Number of pre-allocated buffers in rx_free | ||
84 | * @write_actual: | ||
85 | * @rx_free: list of free SKBs for use | ||
86 | * @rx_used: List of Rx buffers with no SKB | ||
87 | * @need_update: flag to indicate we need to update read/write index | ||
88 | * @rb_stts: driver's pointer to receive buffer status | ||
89 | * @rb_stts_dma: bus address of receive buffer status | ||
90 | * @lock: | ||
91 | * | ||
92 | * NOTE: rx_free and rx_used are used as a FIFO for iwl_rx_mem_buffers | ||
93 | */ | ||
94 | struct iwl_rx_queue { | ||
95 | __le32 *bd; | ||
96 | dma_addr_t bd_dma; | ||
97 | struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS]; | ||
98 | struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE]; | ||
99 | u32 read; | ||
100 | u32 write; | ||
101 | u32 free_count; | ||
102 | u32 write_actual; | ||
103 | struct list_head rx_free; | ||
104 | struct list_head rx_used; | ||
105 | int need_update; | ||
106 | struct iwl_rb_status *rb_stts; | ||
107 | dma_addr_t rb_stts_dma; | ||
108 | spinlock_t lock; | ||
109 | }; | ||
110 | |||
111 | struct iwl_dma_ptr { | ||
112 | dma_addr_t dma; | ||
113 | void *addr; | ||
114 | size_t size; | ||
115 | }; | ||
116 | |||
117 | /** | ||
118 | * iwl_queue_inc_wrap - increment queue index, wrap back to beginning | ||
119 | * @index -- current index | ||
120 | * @n_bd -- total number of entries in queue (must be power of 2) | ||
121 | */ | ||
122 | static inline int iwl_queue_inc_wrap(int index, int n_bd) | ||
123 | { | ||
124 | return ++index & (n_bd - 1); | ||
125 | } | ||
126 | |||
127 | /** | ||
128 | * iwl_queue_dec_wrap - decrement queue index, wrap back to end | ||
129 | * @index -- current index | ||
130 | * @n_bd -- total number of entries in queue (must be power of 2) | ||
131 | */ | ||
132 | static inline int iwl_queue_dec_wrap(int index, int n_bd) | ||
133 | { | ||
134 | return --index & (n_bd - 1); | ||
135 | } | ||
136 | |||
137 | struct iwl_cmd_meta { | ||
138 | /* only for SYNC commands, iff the reply skb is wanted */ | ||
139 | struct iwl_host_cmd *source; | ||
140 | |||
141 | DEFINE_DMA_UNMAP_ADDR(mapping); | ||
142 | DEFINE_DMA_UNMAP_LEN(len); | ||
143 | |||
144 | u32 flags; | ||
145 | }; | ||
146 | |||
147 | /* | ||
148 | * Generic queue structure | ||
149 | * | ||
150 | * Contains common data for Rx and Tx queues. | ||
151 | * | ||
152 | * Note the difference between n_bd and n_window: the hardware | ||
153 | * always assumes 256 descriptors, so n_bd is always 256 (unless | ||
154 | * there might be HW changes in the future). For the normal TX | ||
155 | * queues, n_window, which is the size of the software queue data | ||
156 | * is also 256; however, for the command queue, n_window is only | ||
157 | * 32 since we don't need so many commands pending. Since the HW | ||
158 | * still uses 256 BDs for DMA though, n_bd stays 256. As a result, | ||
159 | * the software buffers (in the variables @meta, @txb in struct | ||
160 | * iwl_tx_queue) only have 32 entries, while the HW buffers (@tfds | ||
161 | * in the same struct) have 256. | ||
162 | * This means that we end up with the following: | ||
163 | * HW entries: | 0 | ... | N * 32 | ... | N * 32 + 31 | ... | 255 | | ||
164 | * SW entries: | 0 | ... | 31 | | ||
165 | * where N is a number between 0 and 7. This means that the SW | ||
166 | * data is a window overlayed over the HW queue. | ||
167 | */ | ||
168 | struct iwl_queue { | ||
169 | int n_bd; /* number of BDs in this queue */ | ||
170 | int write_ptr; /* 1-st empty entry (index) host_w*/ | ||
171 | int read_ptr; /* last used entry (index) host_r*/ | ||
172 | /* use for monitoring and recovering the stuck queue */ | ||
173 | dma_addr_t dma_addr; /* physical addr for BD's */ | ||
174 | int n_window; /* safe queue window */ | ||
175 | u32 id; | ||
176 | int low_mark; /* low watermark, resume queue if free | ||
177 | * space more than this */ | ||
178 | int high_mark; /* high watermark, stop queue if free | ||
179 | * space less than this */ | ||
180 | }; | ||
181 | |||
182 | #define TFD_TX_CMD_SLOTS 256 | ||
183 | #define TFD_CMD_SLOTS 32 | ||
184 | |||
185 | struct iwl_pcie_tx_queue_entry { | ||
186 | struct iwl_device_cmd *cmd; | ||
187 | struct sk_buff *skb; | ||
188 | struct iwl_cmd_meta meta; | ||
189 | }; | ||
190 | |||
191 | /** | ||
192 | * struct iwl_tx_queue - Tx Queue for DMA | ||
193 | * @q: generic Rx/Tx queue descriptor | ||
194 | * @tfds: transmit frame descriptors (DMA memory) | ||
195 | * @entries: transmit entries (driver state) | ||
196 | * @lock: queue lock | ||
197 | * @stuck_timer: timer that fires if queue gets stuck | ||
198 | * @trans_pcie: pointer back to transport (for timer) | ||
199 | * @need_update: indicates need to update read/write index | ||
200 | * @active: stores if queue is active | ||
201 | * | ||
202 | * A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame | ||
203 | * descriptors) and required locking structures. | ||
204 | */ | ||
205 | struct iwl_tx_queue { | ||
206 | struct iwl_queue q; | ||
207 | struct iwl_tfd *tfds; | ||
208 | struct iwl_pcie_tx_queue_entry *entries; | ||
209 | spinlock_t lock; | ||
210 | struct timer_list stuck_timer; | ||
211 | struct iwl_trans_pcie *trans_pcie; | ||
212 | u8 need_update; | ||
213 | u8 active; | ||
214 | }; | ||
215 | |||
216 | /** | ||
217 | * struct iwl_trans_pcie - PCIe transport specific data | ||
218 | * @rxq: all the RX queue data | ||
219 | * @rx_replenish: work that will be called when buffers need to be allocated | ||
220 | * @drv - pointer to iwl_drv | ||
221 | * @trans: pointer to the generic transport area | ||
222 | * @irq - the irq number for the device | ||
223 | * @irq_requested: true when the irq has been requested | ||
224 | * @scd_base_addr: scheduler sram base address in SRAM | ||
225 | * @scd_bc_tbls: pointer to the byte count table of the scheduler | ||
226 | * @kw: keep warm address | ||
227 | * @pci_dev: basic pci-network driver stuff | ||
228 | * @hw_base: pci hardware address support | ||
229 | * @ucode_write_complete: indicates that the ucode has been copied. | ||
230 | * @ucode_write_waitq: wait queue for uCode load | ||
231 | * @status - transport specific status flags | ||
232 | * @cmd_queue - command queue number | ||
233 | * @rx_buf_size_8k: 8 kB RX buffer size | ||
234 | * @rx_page_order: page order for receive buffer size | ||
235 | * @wd_timeout: queue watchdog timeout (jiffies) | ||
236 | */ | ||
237 | struct iwl_trans_pcie { | ||
238 | struct iwl_rx_queue rxq; | ||
239 | struct work_struct rx_replenish; | ||
240 | struct iwl_trans *trans; | ||
241 | struct iwl_drv *drv; | ||
242 | |||
243 | /* INT ICT Table */ | ||
244 | __le32 *ict_tbl; | ||
245 | dma_addr_t ict_tbl_dma; | ||
246 | int ict_index; | ||
247 | u32 inta; | ||
248 | bool use_ict; | ||
249 | bool irq_requested; | ||
250 | struct tasklet_struct irq_tasklet; | ||
251 | struct isr_statistics isr_stats; | ||
252 | |||
253 | unsigned int irq; | ||
254 | spinlock_t irq_lock; | ||
255 | u32 inta_mask; | ||
256 | u32 scd_base_addr; | ||
257 | struct iwl_dma_ptr scd_bc_tbls; | ||
258 | struct iwl_dma_ptr kw; | ||
259 | |||
260 | struct iwl_tx_queue *txq; | ||
261 | unsigned long queue_used[BITS_TO_LONGS(IWL_MAX_HW_QUEUES)]; | ||
262 | unsigned long queue_stopped[BITS_TO_LONGS(IWL_MAX_HW_QUEUES)]; | ||
263 | |||
264 | /* PCI bus related data */ | ||
265 | struct pci_dev *pci_dev; | ||
266 | void __iomem *hw_base; | ||
267 | |||
268 | bool ucode_write_complete; | ||
269 | wait_queue_head_t ucode_write_waitq; | ||
270 | unsigned long status; | ||
271 | u8 cmd_queue; | ||
272 | u8 n_no_reclaim_cmds; | ||
273 | u8 no_reclaim_cmds[MAX_NO_RECLAIM_CMDS]; | ||
274 | u8 setup_q_to_fifo[IWL_MAX_HW_QUEUES]; | ||
275 | u8 n_q_to_fifo; | ||
276 | |||
277 | bool rx_buf_size_8k; | ||
278 | u32 rx_page_order; | ||
279 | |||
280 | const char **command_names; | ||
281 | |||
282 | /* queue watchdog */ | ||
283 | unsigned long wd_timeout; | ||
284 | }; | ||
285 | |||
286 | /***************************************************** | ||
287 | * DRIVER STATUS FUNCTIONS | ||
288 | ******************************************************/ | ||
289 | #define STATUS_HCMD_ACTIVE 0 | ||
290 | #define STATUS_DEVICE_ENABLED 1 | ||
291 | #define STATUS_TPOWER_PMI 2 | ||
292 | #define STATUS_INT_ENABLED 3 | ||
293 | |||
294 | #define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \ | ||
295 | ((struct iwl_trans_pcie *) ((_iwl_trans)->trans_specific)) | ||
296 | |||
297 | static inline struct iwl_trans * | ||
298 | iwl_trans_pcie_get_trans(struct iwl_trans_pcie *trans_pcie) | ||
299 | { | ||
300 | return container_of((void *)trans_pcie, struct iwl_trans, | ||
301 | trans_specific); | ||
302 | } | ||
303 | |||
304 | struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, | ||
305 | const struct pci_device_id *ent, | ||
306 | const struct iwl_cfg *cfg); | ||
307 | void iwl_trans_pcie_free(struct iwl_trans *trans); | ||
308 | |||
309 | /***************************************************** | ||
310 | * RX | ||
311 | ******************************************************/ | ||
312 | void iwl_bg_rx_replenish(struct work_struct *data); | ||
313 | void iwl_irq_tasklet(struct iwl_trans *trans); | ||
314 | void iwlagn_rx_replenish(struct iwl_trans *trans); | ||
315 | void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, | ||
316 | struct iwl_rx_queue *q); | ||
317 | |||
318 | /***************************************************** | ||
319 | * ICT | ||
320 | ******************************************************/ | ||
321 | void iwl_reset_ict(struct iwl_trans *trans); | ||
322 | void iwl_disable_ict(struct iwl_trans *trans); | ||
323 | int iwl_alloc_isr_ict(struct iwl_trans *trans); | ||
324 | void iwl_free_isr_ict(struct iwl_trans *trans); | ||
325 | irqreturn_t iwl_isr_ict(int irq, void *data); | ||
326 | |||
327 | /***************************************************** | ||
328 | * TX / HCMD | ||
329 | ******************************************************/ | ||
330 | void iwl_txq_update_write_ptr(struct iwl_trans *trans, | ||
331 | struct iwl_tx_queue *txq); | ||
332 | int iwlagn_txq_attach_buf_to_tfd(struct iwl_trans *trans, | ||
333 | struct iwl_tx_queue *txq, | ||
334 | dma_addr_t addr, u16 len, u8 reset); | ||
335 | int iwl_queue_init(struct iwl_queue *q, int count, int slots_num, u32 id); | ||
336 | int iwl_trans_pcie_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd); | ||
337 | void iwl_tx_cmd_complete(struct iwl_trans *trans, | ||
338 | struct iwl_rx_cmd_buffer *rxb, int handler_status); | ||
339 | void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans, | ||
340 | struct iwl_tx_queue *txq, | ||
341 | u16 byte_cnt); | ||
342 | void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo, | ||
343 | int sta_id, int tid, int frame_limit, u16 ssn); | ||
344 | void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int queue); | ||
345 | void iwl_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq, | ||
346 | enum dma_data_direction dma_dir); | ||
347 | int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, | ||
348 | struct sk_buff_head *skbs); | ||
349 | int iwl_queue_space(const struct iwl_queue *q); | ||
350 | |||
351 | /***************************************************** | ||
352 | * Error handling | ||
353 | ******************************************************/ | ||
354 | int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display); | ||
355 | void iwl_dump_csr(struct iwl_trans *trans); | ||
356 | |||
357 | /***************************************************** | ||
358 | * Helpers | ||
359 | ******************************************************/ | ||
360 | static inline void iwl_disable_interrupts(struct iwl_trans *trans) | ||
361 | { | ||
362 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
363 | clear_bit(STATUS_INT_ENABLED, &trans_pcie->status); | ||
364 | |||
365 | /* disable interrupts from uCode/NIC to host */ | ||
366 | iwl_write32(trans, CSR_INT_MASK, 0x00000000); | ||
367 | |||
368 | /* acknowledge/clear/reset any interrupts still pending | ||
369 | * from uCode or flow handler (Rx/Tx DMA) */ | ||
370 | iwl_write32(trans, CSR_INT, 0xffffffff); | ||
371 | iwl_write32(trans, CSR_FH_INT_STATUS, 0xffffffff); | ||
372 | IWL_DEBUG_ISR(trans, "Disabled interrupts\n"); | ||
373 | } | ||
374 | |||
375 | static inline void iwl_enable_interrupts(struct iwl_trans *trans) | ||
376 | { | ||
377 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
378 | |||
379 | IWL_DEBUG_ISR(trans, "Enabling interrupts\n"); | ||
380 | set_bit(STATUS_INT_ENABLED, &trans_pcie->status); | ||
381 | iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask); | ||
382 | } | ||
383 | |||
384 | static inline void iwl_enable_rfkill_int(struct iwl_trans *trans) | ||
385 | { | ||
386 | IWL_DEBUG_ISR(trans, "Enabling rfkill interrupt\n"); | ||
387 | iwl_write32(trans, CSR_INT_MASK, CSR_INT_BIT_RF_KILL); | ||
388 | } | ||
389 | |||
390 | static inline void iwl_wake_queue(struct iwl_trans *trans, | ||
391 | struct iwl_tx_queue *txq) | ||
392 | { | ||
393 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
394 | |||
395 | if (test_and_clear_bit(txq->q.id, trans_pcie->queue_stopped)) { | ||
396 | IWL_DEBUG_TX_QUEUES(trans, "Wake hwq %d\n", txq->q.id); | ||
397 | iwl_op_mode_queue_not_full(trans->op_mode, txq->q.id); | ||
398 | } | ||
399 | } | ||
400 | |||
401 | static inline void iwl_stop_queue(struct iwl_trans *trans, | ||
402 | struct iwl_tx_queue *txq) | ||
403 | { | ||
404 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
405 | |||
406 | if (!test_and_set_bit(txq->q.id, trans_pcie->queue_stopped)) { | ||
407 | iwl_op_mode_queue_full(trans->op_mode, txq->q.id); | ||
408 | IWL_DEBUG_TX_QUEUES(trans, "Stop hwq %d\n", txq->q.id); | ||
409 | } else | ||
410 | IWL_DEBUG_TX_QUEUES(trans, "hwq %d already stopped\n", | ||
411 | txq->q.id); | ||
412 | } | ||
413 | |||
414 | static inline int iwl_queue_used(const struct iwl_queue *q, int i) | ||
415 | { | ||
416 | return q->write_ptr >= q->read_ptr ? | ||
417 | (i >= q->read_ptr && i < q->write_ptr) : | ||
418 | !(i < q->read_ptr && i >= q->write_ptr); | ||
419 | } | ||
420 | |||
421 | static inline u8 get_cmd_index(struct iwl_queue *q, u32 index) | ||
422 | { | ||
423 | return index & (q->n_window - 1); | ||
424 | } | ||
425 | |||
426 | static inline const char * | ||
427 | trans_pcie_get_cmd_string(struct iwl_trans_pcie *trans_pcie, u8 cmd) | ||
428 | { | ||
429 | if (!trans_pcie->command_names || !trans_pcie->command_names[cmd]) | ||
430 | return "UNKNOWN"; | ||
431 | return trans_pcie->command_names[cmd]; | ||
432 | } | ||
433 | |||
434 | static inline bool iwl_is_rfkill_set(struct iwl_trans *trans) | ||
435 | { | ||
436 | return !(iwl_read32(trans, CSR_GP_CNTRL) & | ||
437 | CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW); | ||
438 | } | ||
439 | |||
440 | #endif /* __iwl_trans_int_pcie_h__ */ | ||