1
/******************************************************************************
3
* Copyright(c) 2005 - 2013 Intel Corporation.
8
*****************************************************************************/
10
#include <linux/kthread.h>
16
#include "iwl-em-sfdb.h"
17
#include "trans_slave/idi_al.h"
18
#include "iwl-emulation.h"
19
#include "iwl-target-access.h"
21
#ifdef CPTCFG_IWLWIFI_TRANS_UT
22
#include <linux/interrupt.h>
23
#include "trans_slave/idi_UT/iwl-idi-ut.h"
26
* IWL SFDB Emulation Logger
28
#define SFDB_LOG_PREFIX "[SFDB]"
30
#ifdef __IWL_SFDB_LOG_ENABLED__
31
#define SFDB_TRACE_ENTER \
32
IWL_EM_TRACE_ENTER(__SFDB_LOG_LEVEL_TRACE__, SFDB_LOG_PREFIX)
33
#define SFDB_TRACE_EXIT \
34
IWL_EM_TRACE_EXIT(__SFDB_LOG_LEVEL_TRACE__, SFDB_LOG_PREFIX)
35
#define SFDB_TRACE_EXIT_RET_STR(_ret) \
36
IWL_EM_LOG(__SFDB_LOG_LEVEL_TRACE__, SFDB_LOG_PREFIX, "<<< "_ret)
37
#define SFDB_TRACE_EXIT_RET(_ret) \
38
IWL_EM_TRACE_EXIT_RET(__SFDB_LOG_LEVEL_TRACE__, SFDB_LOG_PREFIX,\
40
#define IWL_SFDB_LOG(fmt, args ...) \
41
IWL_EM_LOG(__SFDB_LOG_LEVEL_DEBUG__, SFDB_LOG_PREFIX, fmt, ## args)
42
#define IWL_SFDB_LOG_HEX_DUMP(msg, p, len) \
43
IWL_EM_LOG_HEX_DUMP(msg, p, len)
46
#define SFDB_TRACE_ENTER
47
#define SFDB_TRACE_EXIT
48
#define SFDB_TRACE_EXIT_RET_STR(_ret)
49
#define SFDB_TRACE_EXIT_RET(_ret)
50
#define IWL_SFDB_LOG(fmt, args ...)
51
#define IWL_SFDB_LOG_HEX_DUMP(msg, p, len)
54
/* Always print error messages */
55
#define IWL_SFDB_LOG_ERR(fmt, args ...) \
56
IWL_EM_LOG_ERR(fmt, ## args)
58
/* Pointer manipulation defines */
59
#define SFDB_SCD_PTR_MASK (SFDB_SCD_QUEUE_SIZE - 1)
60
#define SFDB_QUEUE_PTR_MASK (SFDB_TFD_NUM_ENTRIES - 1)
61
#define SFDB_SCD_PTR(_p) ((_p) & SFDB_SCD_PTR_MASK)
62
#define SFDB_QUEUE_PTR(_p) ((_p) & SFDB_QUEUE_PTR_MASK)
63
#define SFDB_INC_PTR(_p) ((_p) = ((_p)+1) & SFDB_SCD_PTR_MASK)
64
#define SFDB_GET_QUEUE(_qid) (&iwl_sfdb_em->tfd_queues[_qid])
66
/* This is the order of TFD size, size = 64 ==> order = 6 */
67
#define HIT_DATA_TFD_SIZE_ORDER (6)
69
/* dma_addr_t of allocated BC table, externed to replace AL define */
70
u32 IWL_SFDB_BC_ADDRESS;
72
#ifdef CPTCFG_IWLWIFI_TRANS_UT
73
static void iwl_sfdb_em_dispatch_reclaim_emu(unsigned long data);
76
/* Like struct iwl_dma_ptr, which is currently PCIe-specific. */
77
struct iwl_em_dma_ptr {
84
* Holds one TFD queue for the emulation.
86
* The PCIe TFD queue itself is dynamically allocated, and its virtual and dma
87
* address is saved in 'tfds'. The queue is used by the PCIe FH.
88
* The indices array is used to tell which PCIe TFD entry (in the tfds queue)
89
* is a decompression of which tfd index as represented by the AL FW and mapped
91
* Meaning that when we attach TFD x from the pool (of IDI TFDs),
92
* we both decompress it to pcie_tfds.addr[write_ptr], and write 'x'
93
* in lut_table[write_ptr],
94
* so later we would be able to free/clean both its representations.
96
struct iwl_tfd_em_queue {
103
struct iwl_em_dma_ptr pci_tfds;
104
u8 lut_table[SFDB_TFD_NUM_ENTRIES];
108
* Represents a byte count table per one queue.
109
* For each entry in the queue holds a 2-byte count.
110
* This is multiplied by 2 in order to
111
* provide duplication of each entry as needed by the scheduler.
113
struct iwl_sfdb_em_bc_tbl {
114
__le16 sfdb_queue_bc_table[SFDB_TFD_NUM_ENTRIES * 2];
118
* Holds the whole TFD queues (SFDB) emulation context.
119
* kw -- keep warm buffer (not present in IDI, so here we manage it)
120
* tfd_queues -- array of TFD queue contexts
121
* trans -- pointer to transport layer, to interact with the driver
124
/* Connection to PCI transport */
125
struct iwl_trans *trans;
127
/* Internal KW and BC buffers */
128
struct iwl_em_dma_ptr kw_buffer;
129
struct iwl_em_dma_ptr bc_tables;
132
struct iwl_tfd_em_queue tfd_queues[SFDB_NUM_QUEUES];
134
#ifdef CPTCFG_IWLWIFI_TRANS_UT
135
/* Gate on the queue id given to the reclaim flow */
138
/* Runs the reclaim flow emulation - needs to be in tasklet context
139
* to emulate RX packet*/
140
struct tasklet_struct reclaim_flow;
144
/* Global SFDB struct */
145
static struct iwl_sfdb_t iwl_sfdb_em_global;
146
static struct iwl_sfdb_t *iwl_sfdb_em = &iwl_sfdb_em_global;
149
* Represents IDI form of transmission buffers
151
* @tb _addr - The index of the TB in the SRAM TB Pool.
152
* @t_len - The length of the tb.
154
struct iwl_sfdb_idi_tb {
160
* Represents IDI form of transmission frame descriptor (TFD)
162
struct iwl_sfdb_idi_tfd {
165
struct iwl_sfdb_idi_tb tbs[SFDB_NUM_OF_TBS];
169
************ Utils functions *************
173
* Allocates a DMAable address and fills it to the emulation dma pointer struct.
174
* The dma memory is zeroed.
176
* Returns 0 on success, negative value describing the error otherwise.
178
static inline int iwl_sfdb_em_alloc_dma_ptr(struct iwl_em_dma_ptr *ptr,
183
if (WARN_ON(ptr->addr))
186
/* Alloc dmaable pointer */
187
ptr->addr = dma_alloc_coherent(iwl_sfdb_em->trans->dev,
189
&ptr->dma, GFP_KERNEL);
194
/* Zero allocated memory */
195
memset(ptr->addr, 0, size);
197
IWL_SFDB_LOG("Allocated DMA pointer: virt %p phys %lx size %zu\n",
198
ptr->addr, (unsigned long)ptr->dma, ptr->size);
204
* Frees a DMAable memory location with the emulation dma pointer struct.
205
* The struct is zeroed before return.
207
static inline void iwl_sfdb_em_free_dma_ptr(struct iwl_em_dma_ptr *ptr)
214
IWL_SFDB_LOG("Freeing DMA pointer: virt %p phys %lx size %zu\n",
215
ptr->addr, (unsigned long)ptr->dma, ptr->size);
216
dma_free_coherent(iwl_sfdb_em->trans->dev,
220
memset(ptr, 0, sizeof(*ptr));
226
* Gets a pointer to a TFD in the IDI form which is located in the AL SRAM.
228
static inline struct iwl_sfdb_idi_tfd *iwl_sfdb_em_get_idi_tfd(u8 tfd_index)
230
return ((struct iwl_sfdb_idi_tfd *)((u8 *)AL_SRAM_VIRTUAL_ADDRESS
231
+ IDI_AL_SFDB_TFD_POOL_OFFSET))
236
* Gets a pointer to a TB in the IDI form which is located in the AL SRAM.
238
static void *iwl_sfdb_em_get_idi_tb(u8 tb_index)
242
return ((u8 *)AL_SRAM_VIRTUAL_ADDRESS + IDI_AL_SFDB_PAYLOAD_MEM_OFFSET)
243
+ (tb_index * SFDB_TB_SIZE);
249
* Converts a TB in the IDI form to the PCIe TB form.
251
* Each IDI TB is composed of one-byte index to the TB pool, and 1 byte length.
252
* The PCIe TB is made of 36 bit of address, and 12 bits of length.
254
* Copyies the idi_tb to the pci_tb.
256
static inline void iwl_sfdb_em_convert_tb(struct iwl_sfdb_idi_tb *idi_tb,
257
struct iwl_tfd_tb *pcie_tb,
260
/* Buffer is the virtual address of the idi tb
261
phys_addr is the phisical address of the idi tb */
262
void *virt_addr = iwl_sfdb_em_get_idi_tb(idi_tb->tb_addr);
263
u16 hi_n_len = (le16_to_cpu(idi_tb->tb_len) << 4);
264
dma_addr_t phys_addr;
267
/* Calc IDI TB phisical address */
268
phys_addr = (dma_addr_t)((u8 *)AL_SRAM_ADDRESS +
269
((u8 *)virt_addr - (u8 *)AL_SRAM_VIRTUAL_ADDRESS));
270
IWL_SFDB_LOG("IDI TB: Convertin TB - index=%d, addres=%lx, len=%u",
271
idi_tb->tb_addr, (unsigned long)phys_addr,
274
put_unaligned_le32(phys_addr, &pcie_tb->lo);
275
if (sizeof(dma_addr_t) > sizeof(u32))
276
hi_n_len |= (((phys_addr >> 16) >> 16) & 0xF);
277
pcie_tb->hi_n_len = cpu_to_le16(hi_n_len);
283
************ API functions ***************
287
* Initializes the SFDB module in the emulation.
289
*@trans - transport to the pci.
291
* Returns 0 on success, negative value describing the error otherwise.
293
int iwl_sfdb_em_init(struct iwl_trans *trans)
299
memset(iwl_sfdb_em, 0, sizeof(struct iwl_sfdb_t));
302
iwl_sfdb_em->trans = trans;
304
/* Initialize keep warm buffers */
305
IWL_SFDB_LOG("Initializing keep-warm buffer");
306
ret = iwl_sfdb_em_alloc_dma_ptr(&iwl_sfdb_em->kw_buffer, IWL_KW_SIZE);
308
IWL_SFDB_LOG_ERR("Keep Warm allocation failed (%d)", ret);
312
/* Initialize Byte Count tables*/
313
IWL_SFDB_LOG("Initializing BC tables");
314
ret = iwl_sfdb_em_alloc_dma_ptr(&iwl_sfdb_em->bc_tables,
315
SFDB_NUM_QUEUES * sizeof(struct iwl_sfdb_em_bc_tbl));
317
IWL_SFDB_LOG_ERR("BC tables allocation failed (%d)", ret);
320
IWL_SFDB_BC_ADDRESS = (u32)&iwl_sfdb_em->bc_tables.dma;
322
#ifdef CPTCFG_IWLWIFI_TRANS_UT
323
/* Init reclaim flow tasklet */
324
tasklet_init(&(iwl_sfdb_em->reclaim_flow),
325
iwl_sfdb_em_dispatch_reclaim_emu, 0);
326
spin_lock_init(&iwl_sfdb_em->gate);
329
IWL_SFDB_LOG("SFDB Initialized");
333
iwl_sfdb_em_free_dma_ptr(&iwl_sfdb_em->kw_buffer);
341
* The start should be called only after sfdb init or after stop flow.
343
* Returns 0 on success, negative value describing the error otherwise.
345
int iwl_sfdb_em_start(void)
347
/* Write KW address to NIC */
348
iwl_idi_tg_write32(iwl_sfdb_em->trans,
350
iwl_sfdb_em->kw_buffer.dma >> 4);
352
#ifdef CPTCFG_IWLWIFI_TRANS_UT
353
/* Re Init reclaim flow tasklet */
354
tasklet_init(&(iwl_sfdb_em->reclaim_flow),
355
iwl_sfdb_em_dispatch_reclaim_emu, 0);
361
* Reset the queue data struct to default values.
363
* @queue_id - The queue id to reset in the sfdb.
365
static void iwl_sfdb_em_reset_queue(u8 queue_id)
367
struct iwl_tfd_em_queue *q = SFDB_GET_QUEUE(queue_id);
371
q->is_aggregated = false;
372
q->need_update = true;
374
/* Read/Write pointer */
378
/* Set all TB indexes to invalid */
379
memset(q->lut_table, SFDB_INVALID_ENTRY, SFDB_TFD_NUM_ENTRIES);
386
* Does not free the data structures just zeroes them.
388
* NOTE: The LMAC should be stopped before this call to prevent
389
* a race condition of LMAC pulling data from zeroed ring.
391
* Returns 0 on success, negative value describing the error otherwise.
393
int iwl_sfdb_em_stop(void)
398
/* Clear the BC tables */
399
memset(iwl_sfdb_em->bc_tables.addr,
401
SFDB_NUM_QUEUES * sizeof(struct iwl_sfdb_em_bc_tbl));
403
/* Clear the Queues */
404
for (i = 0; i < SFDB_NUM_QUEUES; i++)
405
iwl_sfdb_em_reset_queue(i);
407
#ifdef CPTCFG_IWLWIFI_TRANS_UT
408
tasklet_kill(&iwl_sfdb_em->reclaim_flow);
416
* Frees the sfdb emulation struct.
418
* The al emulation stopping should be called before trying to stop the SFDB.
420
void iwl_sfdb_em_free(void)
423
struct iwl_tfd_em_queue *q;
426
/* Free internal structures */
427
iwl_sfdb_em_free_dma_ptr(&iwl_sfdb_em->bc_tables);
428
iwl_sfdb_em_free_dma_ptr(&iwl_sfdb_em->kw_buffer);
431
for (i = 0; i < SFDB_NUM_QUEUES; i++) {
432
IWL_SFDB_LOG("SFDB: Freeing Queue %d", i);
433
q = SFDB_GET_QUEUE(i);
434
iwl_sfdb_em_free_dma_ptr(&q->pci_tfds);
437
#ifdef CPTCFG_IWLWIFI_TRANS_UT
438
/*Stop reclaim flow interrupts */
439
tasklet_kill(&iwl_sfdb_em->reclaim_flow);
442
IWL_SFDB_LOG("SFDB Freed");
447
* This function initializes a TFD queue and configures FH with the base
448
* address of this queue.
449
* Allocates a DMA memory for the PCIe TFD queue.
451
* @param queue_id - the number of queue.
453
void iwl_sfdb_em_init_queue(u8 queue_id)
456
struct iwl_tfd_em_queue *q = SFDB_GET_QUEUE(queue_id);
459
BUG_ON(queue_id >= SFDB_NUM_QUEUES);
461
/* Allocate pci TFDs*/
462
IWL_SFDB_LOG("Initializing queue %d - %s Allocated",
464
(!q->pci_tfds.addr) ? "Not" : "Already");
466
/* If this pointer has been allocated before, just zero the memory.
467
* This pointer is zeroed on sfdb init - so if it's not zero it means
468
* that the memory was already allocated */
469
if (!q->pci_tfds.addr) {
470
ret = iwl_sfdb_em_alloc_dma_ptr(&q->pci_tfds,
471
sizeof(struct iwl_tfd) * SFDB_TFD_NUM_ENTRIES);
473
IWL_SFDB_LOG_ERR("Failed to allocate DMA memory (%d)",
478
memset(q->pci_tfds.addr, 0,
479
sizeof(struct iwl_tfd) * SFDB_TFD_NUM_ENTRIES);
482
/* Reset the queue */
483
iwl_sfdb_em_reset_queue(queue_id);
485
/*Configure FH with the TFD ring address of the Q */
486
iwl_sfdb_em_config_hw(queue_id);
491
* Writes the given value to the queues tfd entry in the Byte Count table.
493
* @ param queue_id - The queue id to update the byte count value.
494
* @ param tfd_entry - The tfd entry in the queue to which we update the bc.
495
* @ param value - The value to write to BC_TABLE[queue_id][tfd_entry]
497
void iwl_sfdb_em_write_bc(u8 queue_id, u8 tfd_entry, __le16 value)
499
struct iwl_sfdb_em_bc_tbl *tbl =
500
(struct iwl_sfdb_em_bc_tbl *)iwl_sfdb_em->bc_tables.addr +
504
IWL_SFDB_LOG("Writing BC to queue %d, tfd %d , BC value %d",
505
queue_id, tfd_entry, value);
507
tbl->sfdb_queue_bc_table[SFDB_QUEUE_PTR(tfd_entry)] = value;
508
tbl->sfdb_queue_bc_table[SFDB_TFD_NUM_ENTRIES +
509
SFDB_QUEUE_PTR(tfd_entry)] = value;
514
* Writes the given value to the LUT table in the tfd entry.
516
* @ param queue_id - The queue id to update the LUT value.
517
* @ param tfd_entry - The tfd entry in the queue to which we update the LUT.
518
* @ param value - The value to write to LUT_TABLE[queue_id][tfd_entry]
520
void iwl_sfdb_em_write_lut_value(u8 queue_id, u8 tfd_entry, u16 value)
522
struct iwl_tfd_em_queue *q = SFDB_GET_QUEUE(queue_id);
525
BUG_ON(queue_id >= SFDB_NUM_QUEUES);
527
IWL_SFDB_LOG("Writing LUT value to queue %d, tfd %d , LUT value %d",
528
queue_id, tfd_entry, value);
530
q->lut_table[tfd_entry] = value;
536
* Frees all TFDs in the queue up to (but not including) given tfd_entry.
537
* Note that tfd_entry is a pointer to the queue (like the read pointer),
538
* not an index in the TFD pool.
540
* @param queue_id - The number of queue.
541
* @param tfd_index - The index of the TFD in the TFD pool
543
void iwl_sfdb_em_release_tfds(u8 queue_id, u8 tfd_entry)
546
struct iwl_tfd_em_queue *q = SFDB_GET_QUEUE(queue_id);
549
BUG_ON(queue_id >= SFDB_NUM_QUEUES);
551
read = SFDB_QUEUE_PTR(q->read_ptr);
553
"Releasing TFDs: queue %d, from slot %d (read pointer) until %d (inclusive)\n",
554
queue_id, read, tfd_entry);
556
/* This increment will make the release until the
557
original tfd_entry inclusive. */
558
tfd_entry = SFDB_QUEUE_PTR(tfd_entry + 1);
560
while (read != tfd_entry) {
561
iwl_sfdb_em_deattach_tfd(queue_id, read);
562
SFDB_INC_PTR(q->read_ptr);
563
read = SFDB_QUEUE_PTR(q->read_ptr);
570
* Sets the next free entry in the lut of the queue
571
* to point to IDI TFD index from the pool.
573
* @param queue_id - The number of queue.
574
* @param tfd_index - The index of the TFD in the TFD pool
578
void iwl_sfdb_em_attach_tfd(u8 queue_id, u8 tfd_index)
581
struct iwl_tfd_em_queue *q = SFDB_GET_QUEUE(queue_id);
582
u32 write_ptr = SFDB_QUEUE_PTR(q->write_ptr);
583
struct iwl_tfd *pcie_tfd =
584
(struct iwl_tfd *)q->pci_tfds.addr + write_ptr;
585
struct iwl_sfdb_idi_tfd *idi_tfd =
586
(struct iwl_sfdb_idi_tfd *)iwl_sfdb_em_get_idi_tfd(tfd_index);
589
BUG_ON(queue_id >= SFDB_NUM_QUEUES);
591
IWL_SFDB_LOG("Attaching TFD %u to queue %u in slot %u",
592
tfd_index, queue_id, write_ptr);
593
memset(pcie_tfd, 0, sizeof(struct iwl_tfd));
595
for (i = 0; i < idi_tfd->numTbs; ++i) {
596
iwl_sfdb_em_convert_tb(&idi_tfd->tbs[i], &pcie_tfd->tbs[i], i);
604
* This function deattach TFD from the queue.
605
* Because we use a PCIe queue, there is no "de-attaching" as removing the
606
* TFD, but only invalidating the relevant index in tfd_indices (telling that no
607
* TFD in the pool now referenced to that slot in the queue).
609
* @param U08 : queue_id -- the number of queue
610
* @param U08 : tfdEntry -- the entry in the TFD queue
612
void iwl_sfdb_em_deattach_tfd(u8 queue_id, u8 tfd_entry)
614
struct iwl_tfd_em_queue *q = SFDB_GET_QUEUE(queue_id);
616
BUG_ON(queue_id >= SFDB_NUM_QUEUES);
618
IWL_SFDB_LOG("Deattaching TFD %u from queue %u",
619
tfd_entry, queue_id);
620
q->lut_table[tfd_entry] = SFDB_INVALID_ENTRY;
622
/* Invalidating BC */
623
iwl_sfdb_em_write_bc(queue_id, tfd_entry, cpu_to_le16(1));
628
#ifdef CPTCFG_IWLWIFI_TRANS_UT
631
* Get device command from the latest packet in the given queue id.
633
static struct iwl_device_cmd *iwl_sfdb_em_get_current_cmd(u8 queue_id)
635
struct iwl_tfd_em_queue *q = SFDB_GET_QUEUE(queue_id);
636
u32 write_ptr = SFDB_QUEUE_PTR(q->write_ptr);
637
struct iwl_sfdb_idi_tfd *idi_tfd;
642
BUG_ON(queue_id >= SFDB_NUM_QUEUES);
645
tfd_index = q->lut_table[write_ptr];
646
idi_tfd = (struct iwl_sfdb_idi_tfd *)iwl_sfdb_em_get_idi_tfd(tfd_index);
647
virt_addr = (void *)iwl_sfdb_em_get_idi_tb(idi_tfd->tbs[0].tb_addr);
648
return (struct iwl_device_cmd *)virt_addr;
652
* Calls the IDI reclaim flow.
655
static void iwl_sfdb_em_dispatch_reclaim_emu(unsigned long data)
657
struct iwl_rx_cmd_buffer *rxcb = (struct iwl_rx_cmd_buffer *)data;
659
/* Call the mock reclaim flow in tasklet context */
660
iwl_idi_tx_handle_dispatch_emu(iwl_sfdb_em->trans, rxcb);
667
* Reclaim flow emulation for the integration.
669
static void iwl_sfdb_em_test_reclaim(u8 queue_id)
671
struct iwl_rx_cmd_buffer *rxcb;
672
struct iwl_rx_packet *pkt;
673
struct iwl_device_cmd *dev_cmd;
674
struct iwl_idi_trans_rx *trans_rx =
675
IWL_TRANS_GET_IDI_TRANS_RX(iwl_sfdb_em->trans);
676
struct iwl_trans_slv *trans_slv =
677
IWL_TRANS_GET_SLV_TRANS(iwl_sfdb_em->trans);
679
/* Alloc RX command buffer */
680
rxcb = kzalloc(sizeof(struct iwl_rx_cmd_buffer), GFP_KERNEL);
682
IWL_SFDB_LOG_ERR("Can't allocate rxcb");
686
/* Alloc and zero page for command buffer */
687
rxcb->_page = alloc_pages((GFP_KERNEL | __GFP_COMP | __GFP_ZERO),
688
trans_slv->rx_page_order);
690
IWL_SFDB_LOG_ERR("Can't allocate rxcb->page");
695
/* extract last device cmd from TB */
696
dev_cmd = iwl_sfdb_em_get_current_cmd(queue_id);
698
/* Update packet in local rxcb */
699
pkt = rxb_addr(rxcb);
700
pkt->hdr.cmd = dev_cmd->hdr.cmd;
701
pkt->hdr.sequence = dev_cmd->hdr.sequence;
703
/* Call mock reclaim flow in tasklet context*/
704
spin_lock(&iwl_sfdb_em->gate);
705
tasklet_unlock_wait(&iwl_sfdb_em->reclaim_flow);
706
iwl_sfdb_em->reclaim_flow.data = (unsigned long)rxcb;
707
tasklet_schedule(&iwl_sfdb_em->reclaim_flow);
708
spin_unlock(&iwl_sfdb_em->gate);
710
#endif /* CPTCFG_IWLWIFI_TRANS_UT */
713
* Increments the write pointer and updates the SCD register.
715
* @param queue_id - The number of queue.
717
void iwl_sfdb_em_inc_write_ptr(u8 queue_id)
719
struct iwl_tfd_em_queue *q = SFDB_GET_QUEUE(queue_id);
722
BUG_ON(queue_id >= SFDB_NUM_QUEUES);
724
IWL_SFDB_LOG("Incrementing WRITE pointer on queue %d, Old %d",
726
iwl_sfdb_em_get_write_ptr(queue_id));
728
#ifdef CPTCFG_IWLWIFI_TRANS_UT
729
iwl_sfdb_em_test_reclaim(queue_id);
730
SFDB_INC_PTR(q->write_ptr);
732
SFDB_INC_PTR(q->write_ptr);
733
iwl_sfdb_em_hw_set_write_ptr(queue_id, SFDB_SCD_PTR(q->write_ptr));
739
* Gets the write pointer of the given queue.
741
* @param queue_id - The number of queue.
743
* Returns the write pointer of the queue.
745
u32 iwl_sfdb_em_get_write_ptr(u8 queue_id)
747
struct iwl_tfd_em_queue *q = SFDB_GET_QUEUE(queue_id);
749
BUG_ON(queue_id >= SFDB_NUM_QUEUES);
752
return SFDB_SCD_PTR(q->write_ptr);
756
* Update Write pointer of Scheduler for queue_id
758
* @param queue_id - The number of queue
759
* @param index - The index to set the write pointer
761
void iwl_sfdb_em_hw_set_write_ptr(u8 queue_id, u32 index)
763
/* TODO: does the same assumptions of PCI hold here?
764
PCI code assumes that after setting CSR_GP_CNTRL this function will
765
be called again, and this time it will update the write pointer */
768
BUG_ON(queue_id >= SFDB_NUM_QUEUES);
770
iwl_write32(iwl_sfdb_em->trans, HBUS_TARG_WRPTR,
771
(u32)index | ((u32)queue_id << 8));
772
IWL_SFDB_LOG("HW write pointer set to %d on Queue %d, requested %d",
773
iwl_sfdb_em_get_write_ptr(queue_id),
781
* Returns the read pointer of the queue
783
* @param queue_id - the number of queue.
785
* Returns the read pointer of the given queue.
787
u8 iwl_sfdb_em_get_read_ptr(u8 queue_id)
789
struct iwl_tfd_em_queue *q = SFDB_GET_QUEUE(queue_id);
791
BUG_ON(queue_id >= SFDB_NUM_QUEUES);
794
return SFDB_SCD_PTR(q->read_ptr);
798
* Update read pointer of Scheduler for queue_id
800
* @param queue_id - The number of queue
801
* @param index - The index to set the read pointer
803
void iwl_sfdb_em_hw_set_read_ptr(u8 queue_id, u8 index)
805
struct iwl_tfd_em_queue *q = SFDB_GET_QUEUE(queue_id);
807
BUG_ON(queue_id >= SFDB_NUM_QUEUES);
809
IWL_SFDB_LOG("Setting READ pointer on Q %d to %d", queue_id, index);
811
iwl_write_prph(iwl_sfdb_em->trans,
812
SCD_QUEUE_RDPTR(queue_id),
818
* This function updates the byte count table for this queue and index
820
* @param queue_id - the number of queue
821
* @param byte_cnt - the number of bytes for this frame
825
void iwl_sfdb_em_update_byte_count(u8 queue_id, __le16 byte_cnt)
827
struct iwl_tfd_em_queue *q = SFDB_GET_QUEUE(queue_id);
829
BUG_ON(queue_id >= SFDB_NUM_QUEUES);
831
iwl_sfdb_em_write_bc(queue_id, SFDB_QUEUE_PTR(q->write_ptr), byte_cnt);
836
* Configures the LMAC (FH/SCD) for using this queue
838
* @param queue_id - The number of queue
840
void iwl_sfdb_em_config_hw(u8 queue_id)
842
struct iwl_tfd_em_queue *q = SFDB_GET_QUEUE(queue_id);
844
BUG_ON(queue_id >= SFDB_NUM_QUEUES);
846
IWL_SFDB_LOG("Configure HW to use queue %d", queue_id);
847
iwl_write_direct32(iwl_sfdb_em->trans,
848
FH_MEM_CBBC_QUEUE(queue_id),
849
q->pci_tfds.dma >> 8);
855
* This function sets the context data for the queue
857
* @queue_id - the number of queue
861
void iwl_sfdb_em_set_ctx_data(u8 queue_id, u32 scd_base_addr)
863
iwl_trans_write_mem32(iwl_sfdb_em->trans, scd_base_addr +
864
SCD_CONTEXT_QUEUE_OFFSET(queue_id), 0);
865
iwl_trans_write_mem32(iwl_sfdb_em->trans, scd_base_addr +
866
SCD_CONTEXT_QUEUE_OFFSET(queue_id) +
869
SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) &
870
SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) |
872
SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
873
SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK));
877
* This function sets the status of this queue (to SCD status register)
879
* @queueId - the number of queue
880
* @isActive - is the queue active
881
* @isPan - is the queue for PAN
882
* @txFifo - the Q->Fifo mapping
886
void iwl_sfdb_em_set_status(u8 queue_id, u32 is_active,
887
u32 is_pan, u32 tx_fifo)
889
iwl_write_prph(iwl_sfdb_em->trans, SCD_QUEUE_STATUS_BITS(queue_id),
890
(is_active << SCD_QUEUE_STTS_REG_POS_ACTIVE) |
891
(tx_fifo << SCD_QUEUE_STTS_REG_POS_TXF) |
892
(1 << SCD_QUEUE_STTS_REG_POS_WSL) |
893
(is_pan << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN) |
894
SCD_QUEUE_STTS_REG_MSK);
898
* This function returns the status of this queue (from SCD status register)
900
* @queueId- The number of queue.
902
u32 iwl_sfdb_em_get_status(u8 queue_id)
904
return iwl_idi_tg_read32(iwl_sfdb_em->trans,
905
SCD_QUEUE_STATUS_BITS(queue_id));
909
* Returns if the queue is aggregated.
911
* @param queue_id - The number of queue
913
* Returns TRUE if the queue is active, FALSE otherwise.
915
bool iwl_sfdb_em_queue_is_aggregated(u8 queue_id)
917
struct iwl_tfd_em_queue *q = SFDB_GET_QUEUE(queue_id);
918
BUG_ON(queue_id >= SFDB_NUM_QUEUES);
919
return q->is_aggregated;