Commit 96a6497b authored by Sara Sharon's avatar Sara Sharon Committed by Emmanuel Grumbach

iwlwifi: pcie: add 9000 series multi queue rx DMA support

The 9000 series introduces several changes in the device
DMA operation.
As the device now supports multi-queue rx, several DMA channels
should be configured.
The flows of providing the device with the allocated RBDs now
changes as well - the device maintains a separate table of used
and free table.

The hardware may use the free table to feed RBDs to any queue.
This requires maintaing a shared table to map returned RBDs to
the original RXB - for that purpose the VID is introduced - an
internal identifier of the RB placed in the lower 12 bits and
returned by HW in the used data.

Another change is the support of 64 bit DMA address.
Signed-off-by: default avatarSara Sharon <sara.sharon@intel.com>
Signed-off-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
parent 78485054
...@@ -138,7 +138,8 @@ static const struct iwl_tt_params iwl9000_tt_params = { ...@@ -138,7 +138,8 @@ static const struct iwl_tt_params iwl9000_tt_params = {
.smem_offset = IWL9000_SMEM_OFFSET, \ .smem_offset = IWL9000_SMEM_OFFSET, \
.smem_len = IWL9000_SMEM_LEN, \ .smem_len = IWL9000_SMEM_LEN, \
.thermal_params = &iwl9000_tt_params, \ .thermal_params = &iwl9000_tt_params, \
.apmg_not_supported = true .apmg_not_supported = true, \
.mq_rx_supported = true
const struct iwl_cfg iwl9260_2ac_cfg = { const struct iwl_cfg iwl9260_2ac_cfg = {
.name = "Intel(R) Dual Band Wireless AC 9260", .name = "Intel(R) Dual Band Wireless AC 9260",
......
...@@ -311,6 +311,7 @@ struct iwl_pwr_tx_backoff { ...@@ -311,6 +311,7 @@ struct iwl_pwr_tx_backoff {
* @dccm2_len: length of the second DCCM * @dccm2_len: length of the second DCCM
* @smem_offset: offset from which the SMEM begins * @smem_offset: offset from which the SMEM begins
* @smem_len: the length of SMEM * @smem_len: the length of SMEM
* @mq_rx_supported: multi-queue rx support
* *
* We enable the driver to be backward compatible wrt. hardware features. * We enable the driver to be backward compatible wrt. hardware features.
* API differences in uCode shouldn't be handled here but through TLVs * API differences in uCode shouldn't be handled here but through TLVs
...@@ -362,6 +363,7 @@ struct iwl_cfg { ...@@ -362,6 +363,7 @@ struct iwl_cfg {
const u32 smem_len; const u32 smem_len;
const struct iwl_tt_params *thermal_params; const struct iwl_tt_params *thermal_params;
bool apmg_not_supported; bool apmg_not_supported;
bool mq_rx_supported;
}; };
/* /*
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY * GPL LICENSE SUMMARY
* *
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2015 Intel Deutschland GmbH
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
...@@ -31,6 +32,7 @@ ...@@ -31,6 +32,7 @@
* BSD LICENSE * BSD LICENSE
* *
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2015 Intel Deutschland GmbH
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
...@@ -312,6 +314,77 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(unsigned int chnl) ...@@ -312,6 +314,77 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(unsigned int chnl)
#define FH_MEM_TFDIB_REG1_ADDR_BITSHIFT 28 #define FH_MEM_TFDIB_REG1_ADDR_BITSHIFT 28
#define FH_MEM_TB_MAX_LENGTH (0x00020000) #define FH_MEM_TB_MAX_LENGTH (0x00020000)
/* 9000 rx series registers */
#define RFH_Q0_FRBDCB_BA_LSB 0xA08000 /* 64 bit address */
#define RFH_Q_FRBDCB_BA_LSB(q) (RFH_Q0_FRBDCB_BA_LSB + (q) * 8)
/* Write index table */
#define RFH_Q0_FRBDCB_WIDX 0xA08080
#define RFH_Q_FRBDCB_WIDX(q) (RFH_Q0_FRBDCB_WIDX + (q) * 4)
/* Read index table */
#define RFH_Q0_FRBDCB_RIDX 0xA080C0
#define RFH_Q_FRBDCB_RIDX(q) (RFH_Q0_FRBDCB_RIDX + (q) * 4)
/* Used list table */
#define RFH_Q0_URBDCB_BA_LSB 0xA08100 /* 64 bit address */
#define RFH_Q_URBDCB_BA_LSB(q) (RFH_Q0_URBDCB_BA_LSB + (q) * 8)
/* Write index table */
#define RFH_Q0_URBDCB_WIDX 0xA08180
#define RFH_Q_URBDCB_WIDX(q) (RFH_Q0_URBDCB_WIDX + (q) * 4)
#define RFH_Q0_URBDCB_VAID 0xA081C0
#define RFH_Q_URBDCB_VAID(q) (RFH_Q0_URBDCB_VAID + (q) * 4)
/* stts */
#define RFH_Q0_URBD_STTS_WPTR_LSB 0xA08200 /*64 bits address */
#define RFH_Q_URBD_STTS_WPTR_LSB(q) (RFH_Q0_URBD_STTS_WPTR_LSB + (q) * 8)
#define RFH_Q0_ORB_WPTR_LSB 0xA08280
#define RFH_Q_ORB_WPTR_LSB(q) (RFH_Q0_ORB_WPTR_LSB + (q) * 8)
#define RFH_RBDBUF_RBD0_LSB 0xA08300
#define RFH_RBDBUF_RBD_LSB(q) (RFH_RBDBUF_RBD0_LSB + (q) * 8)
/* DMA configuration */
#define RFH_RXF_DMA_CFG 0xA09820
/* RB size */
#define RFH_RXF_DMA_RB_SIZE_MASK (0x000F0000) /* bits 16-19 */
#define RFH_RXF_DMA_RB_SIZE_POS 16
#define RFH_RXF_DMA_RB_SIZE_1K (0x1 << RFH_RXF_DMA_RB_SIZE_POS)
#define RFH_RXF_DMA_RB_SIZE_2K (0x2 << RFH_RXF_DMA_RB_SIZE_POS)
#define RFH_RXF_DMA_RB_SIZE_4K (0x4 << RFH_RXF_DMA_RB_SIZE_POS)
#define RFH_RXF_DMA_RB_SIZE_8K (0x8 << RFH_RXF_DMA_RB_SIZE_POS)
#define RFH_RXF_DMA_RB_SIZE_12K (0x9 << RFH_RXF_DMA_RB_SIZE_POS)
#define RFH_RXF_DMA_RB_SIZE_16K (0xA << RFH_RXF_DMA_RB_SIZE_POS)
#define RFH_RXF_DMA_RB_SIZE_20K (0xB << RFH_RXF_DMA_RB_SIZE_POS)
#define RFH_RXF_DMA_RB_SIZE_24K (0xC << RFH_RXF_DMA_RB_SIZE_POS)
#define RFH_RXF_DMA_RB_SIZE_28K (0xD << RFH_RXF_DMA_RB_SIZE_POS)
#define RFH_RXF_DMA_RB_SIZE_32K (0xE << RFH_RXF_DMA_RB_SIZE_POS)
/* RB Circular Buffer size:defines the table sizes in RBD units */
#define RFH_RXF_DMA_RBDCB_SIZE_MASK (0x00F00000) /* bits 20-23 */
#define RFH_RXF_DMA_RBDCB_SIZE_POS 20
#define RFH_RXF_DMA_RBDCB_SIZE_8 (0x3 << RFH_RXF_DMA_RBDCB_SIZE_POS)
#define RFH_RXF_DMA_RBDCB_SIZE_16 (0x4 << RFH_RXF_DMA_RBDCB_SIZE_POS)
#define RFH_RXF_DMA_RBDCB_SIZE_32 (0x5 << RFH_RXF_DMA_RBDCB_SIZE_POS)
#define RFH_RXF_DMA_RBDCB_SIZE_64 (0x7 << RFH_RXF_DMA_RBDCB_SIZE_POS)
#define RFH_RXF_DMA_RBDCB_SIZE_128 (0x7 << RFH_RXF_DMA_RBDCB_SIZE_POS)
#define RFH_RXF_DMA_RBDCB_SIZE_256 (0x8 << RFH_RXF_DMA_RBDCB_SIZE_POS)
#define RFH_RXF_DMA_RBDCB_SIZE_512 (0x9 << RFH_RXF_DMA_RBDCB_SIZE_POS)
#define RFH_RXF_DMA_RBDCB_SIZE_1024 (0xA << RFH_RXF_DMA_RBDCB_SIZE_POS)
#define RFH_RXF_DMA_RBDCB_SIZE_2048 (0xB << RFH_RXF_DMA_RBDCB_SIZE_POS)
#define RFH_RXF_DMA_MIN_RB_SIZE_MASK (0x03000000) /* bit 24-25 */
#define RFH_RXF_DMA_MIN_RB_SIZE_POS 24
#define RFH_RXF_DMA_MIN_RB_4_8 (3 << RFH_RXF_DMA_MIN_RB_SIZE_POS)
#define RFH_RXF_DMA_SINGLE_FRAME_MASK (0x20000000) /* bit 29 */
#define RFH_DMA_EN_MASK (0xC0000000) /* bits 30-31*/
#define RFH_DMA_EN_ENABLE_VAL BIT(31)
#define RFH_RXF_RXQ_ACTIVE 0xA0980C
#define RFH_GEN_CFG 0xA09800
#define RFH_GEN_CFG_DEFAULT_RXQ_NUM_MASK 0xF00
#define RFH_GEN_CFG_SERVICE_DMA_SNOOP BIT(0)
#define RFH_GEN_CFG_RFH_DMA_SNOOP BIT(1)
#define DEFAULT_RXQ_NUM 8
/* end of 9000 rx series registers */
/* TFDB Area - TFDs buffer table */ /* TFDB Area - TFDs buffer table */
#define FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK (0xFFFFFFFF) #define FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK (0xFFFFFFFF)
#define FH_TFDIB_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0x900) #define FH_TFDIB_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0x900)
...@@ -434,6 +507,10 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(unsigned int chnl) ...@@ -434,6 +507,10 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(unsigned int chnl)
*/ */
#define FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN (0x00000002) #define FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN (0x00000002)
#define MQ_RX_TABLE_SIZE 512
#define MQ_RX_TABLE_MASK (MQ_RX_TABLE_SIZE - 1)
#define MQ_RX_POOL_SIZE MQ_RX_TABLE_MASK
#define RX_QUEUE_SIZE 256 #define RX_QUEUE_SIZE 256
#define RX_QUEUE_MASK 255 #define RX_QUEUE_MASK 255
#define RX_QUEUE_SIZE_LOG 8 #define RX_QUEUE_SIZE_LOG 8
......
...@@ -56,7 +56,6 @@ ...@@ -56,7 +56,6 @@
#define RX_NUM_QUEUES 1 #define RX_NUM_QUEUES 1
#define RX_POST_REQ_ALLOC 2 #define RX_POST_REQ_ALLOC 2
#define RX_CLAIM_REQ_ALLOC 8 #define RX_CLAIM_REQ_ALLOC 8
#define RX_POOL_SIZE ((RX_CLAIM_REQ_ALLOC - RX_POST_REQ_ALLOC) * RX_NUM_QUEUES)
#define RX_PENDING_WATERMARK 16 #define RX_PENDING_WATERMARK 16
struct iwl_host_cmd; struct iwl_host_cmd;
...@@ -64,9 +63,16 @@ struct iwl_host_cmd; ...@@ -64,9 +63,16 @@ struct iwl_host_cmd;
/*This file includes the declaration that are internal to the /*This file includes the declaration that are internal to the
* trans_pcie layer */ * trans_pcie layer */
/**
* struct iwl_rx_mem_buffer
* @page_dma: bus address of rxb page
* @page: driver's pointer to the rxb page
* @vid: index of this rxb in the global table
*/
struct iwl_rx_mem_buffer { struct iwl_rx_mem_buffer {
dma_addr_t page_dma; dma_addr_t page_dma;
struct page *page; struct page *page;
u16 vid;
struct list_head list; struct list_head list;
}; };
...@@ -90,8 +96,12 @@ struct isr_statistics { ...@@ -90,8 +96,12 @@ struct isr_statistics {
/** /**
* struct iwl_rxq - Rx queue * struct iwl_rxq - Rx queue
* @bd: driver's pointer to buffer of receive buffer descriptors (rbd) * @id: queue index
* @bd: driver's pointer to buffer of receive buffer descriptors (rbd).
* Address size is 32 bit in pre-9000 devices and 64 bit in 9000 devices.
* @bd_dma: bus address of buffer of receive buffer descriptors (rbd) * @bd_dma: bus address of buffer of receive buffer descriptors (rbd)
* @ubd: driver's pointer to buffer of used receive buffer descriptors (rbd)
* @ubd_dma: physical address of buffer of used receive buffer descriptors (rbd)
* @read: Shared index to newest available Rx buffer * @read: Shared index to newest available Rx buffer
* @write: Shared index to oldest written Rx packet * @write: Shared index to oldest written Rx packet
* @free_count: Number of pre-allocated buffers in rx_free * @free_count: Number of pre-allocated buffers in rx_free
...@@ -103,18 +113,22 @@ struct isr_statistics { ...@@ -103,18 +113,22 @@ struct isr_statistics {
* @rb_stts: driver's pointer to receive buffer status * @rb_stts: driver's pointer to receive buffer status
* @rb_stts_dma: bus address of receive buffer status * @rb_stts_dma: bus address of receive buffer status
* @lock: * @lock:
* @queue: actual rx queue * @queue: actual rx queue. Not used for multi-rx queue.
* *
* NOTE: rx_free and rx_used are used as a FIFO for iwl_rx_mem_buffers * NOTE: rx_free and rx_used are used as a FIFO for iwl_rx_mem_buffers
*/ */
struct iwl_rxq { struct iwl_rxq {
__le32 *bd; int id;
void *bd;
dma_addr_t bd_dma; dma_addr_t bd_dma;
__le32 *used_bd;
dma_addr_t used_bd_dma;
u32 read; u32 read;
u32 write; u32 write;
u32 free_count; u32 free_count;
u32 used_count; u32 used_count;
u32 write_actual; u32 write_actual;
u32 queue_size;
struct list_head rx_free; struct list_head rx_free;
struct list_head rx_used; struct list_head rx_used;
bool need_update; bool need_update;
...@@ -126,7 +140,6 @@ struct iwl_rxq { ...@@ -126,7 +140,6 @@ struct iwl_rxq {
/** /**
* struct iwl_rb_allocator - Rx allocator * struct iwl_rb_allocator - Rx allocator
* @pool: initial pool of allocator
* @req_pending: number of requests the allcator had not processed yet * @req_pending: number of requests the allcator had not processed yet
* @req_ready: number of requests honored and ready for claiming * @req_ready: number of requests honored and ready for claiming
* @rbd_allocated: RBDs with pages allocated and ready to be handled to * @rbd_allocated: RBDs with pages allocated and ready to be handled to
...@@ -138,7 +151,6 @@ struct iwl_rxq { ...@@ -138,7 +151,6 @@ struct iwl_rxq {
* @rx_alloc: work struct for background calls * @rx_alloc: work struct for background calls
*/ */
struct iwl_rb_allocator { struct iwl_rb_allocator {
struct iwl_rx_mem_buffer pool[RX_POOL_SIZE];
atomic_t req_pending; atomic_t req_pending;
atomic_t req_ready; atomic_t req_ready;
struct list_head rbd_allocated; struct list_head rbd_allocated;
...@@ -297,6 +309,7 @@ struct iwl_tso_hdr_page { ...@@ -297,6 +309,7 @@ struct iwl_tso_hdr_page {
* struct iwl_trans_pcie - PCIe transport specific data * struct iwl_trans_pcie - PCIe transport specific data
* @rxq: all the RX queue data * @rxq: all the RX queue data
* @rx_pool: initial pool of iwl_rx_mem_buffer for all the queues * @rx_pool: initial pool of iwl_rx_mem_buffer for all the queues
* @global_table: table mapping received VID from hw to rxb
* @rba: allocator for RX replenishing * @rba: allocator for RX replenishing
* @drv - pointer to iwl_drv * @drv - pointer to iwl_drv
* @trans: pointer to the generic transport area * @trans: pointer to the generic transport area
...@@ -324,7 +337,8 @@ struct iwl_tso_hdr_page { ...@@ -324,7 +337,8 @@ struct iwl_tso_hdr_page {
*/ */
struct iwl_trans_pcie { struct iwl_trans_pcie {
struct iwl_rxq *rxq; struct iwl_rxq *rxq;
struct iwl_rx_mem_buffer rx_pool[RX_QUEUE_SIZE]; struct iwl_rx_mem_buffer rx_pool[MQ_RX_POOL_SIZE];
struct iwl_rx_mem_buffer *global_table[MQ_RX_TABLE_SIZE];
struct iwl_rb_allocator rba; struct iwl_rb_allocator rba;
struct iwl_trans *trans; struct iwl_trans *trans;
struct iwl_drv *drv; struct iwl_drv *drv;
......
...@@ -2403,7 +2403,8 @@ static struct iwl_trans_dump_data ...@@ -2403,7 +2403,8 @@ static struct iwl_trans_dump_data
u32 len, num_rbs; u32 len, num_rbs;
u32 monitor_len; u32 monitor_len;
int i, ptr; int i, ptr;
bool dump_rbs = test_bit(STATUS_FW_ERROR, &trans->status); bool dump_rbs = test_bit(STATUS_FW_ERROR, &trans->status) &&
!trans->cfg->mq_rx_supported;
/* transport dump header */ /* transport dump header */
len = sizeof(*dump_data); len = sizeof(*dump_data);
...@@ -2562,7 +2563,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, ...@@ -2562,7 +2563,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
struct iwl_trans_pcie *trans_pcie; struct iwl_trans_pcie *trans_pcie;
struct iwl_trans *trans; struct iwl_trans *trans;
u16 pci_cmd; u16 pci_cmd;
int ret; int ret, addr_size;
trans = iwl_trans_alloc(sizeof(struct iwl_trans_pcie), trans = iwl_trans_alloc(sizeof(struct iwl_trans_pcie),
&pdev->dev, cfg, &trans_ops_pcie, 0); &pdev->dev, cfg, &trans_ops_pcie, 0);
...@@ -2600,11 +2601,17 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, ...@@ -2600,11 +2601,17 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
PCIE_LINK_STATE_CLKPM); PCIE_LINK_STATE_CLKPM);
} }
if (cfg->mq_rx_supported)
addr_size = 64;
else
addr_size = 36;
pci_set_master(pdev); pci_set_master(pdev);
ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(36)); ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(addr_size));
if (!ret) if (!ret)
ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(36)); ret = pci_set_consistent_dma_mask(pdev,
DMA_BIT_MASK(addr_size));
if (ret) { if (ret) {
ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
if (!ret) if (!ret)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment