Skip to content

Commit

Permalink
iwlagn: move rx transport functions to iwl-trans-rx-pcie.c
Browse files Browse the repository at this point in the history
Also create a new file: iwl-trans-int-pcie.h which will include
the non static functions that are shared among the current pcie transport layer.

Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
  • Loading branch information
Emmanuel Grumbach authored and Wey-Yi Guy committed Jul 16, 2011
1 parent 4caab32 commit ab697a9
Show file tree
Hide file tree
Showing 9 changed files with 799 additions and 725 deletions.
2 changes: 1 addition & 1 deletion drivers/net/wireless/iwlwifi/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ iwlagn-objs += iwl-6000.o
iwlagn-objs += iwl-1000.o
iwlagn-objs += iwl-2000.o
iwlagn-objs += iwl-pci.o
iwlagn-objs += iwl-trans.o
iwlagn-objs += iwl-trans.o iwl-trans-rx-pcie.o

iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
iwlagn-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o
Expand Down
226 changes: 1 addition & 225 deletions drivers/net/wireless/iwlwifi/iwl-agn-lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -628,56 +628,6 @@ struct iwl_mod_params iwlagn_mod_params = {
/* the rest are 0 by default */
};

int iwlagn_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
{
u32 rb_size;
const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */
u32 rb_timeout = 0; /* FIXME: RX_RB_TIMEOUT for all devices? */

rb_timeout = RX_RB_TIMEOUT;

if (iwlagn_mod_params.amsdu_size_8K)
rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K;
else
rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K;

/* Stop Rx DMA */
iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);

/* Reset driver's Rx queue write index */
iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0);

/* Tell device where to find RBD circular buffer in DRAM */
iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG,
(u32)(rxq->bd_dma >> 8));

/* Tell device where in DRAM to update its Rx status */
iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG,
rxq->rb_stts_dma >> 4);

/* Enable Rx DMA
* FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY is set because of HW bug in
* the credit mechanism in 5000 HW RX FIFO
* Direct rx interrupts to hosts
* Rx buffer size 4 or 8k
* RB timeout 0x10
* 256 RBDs
*/
iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG,
FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY |
FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK |
rb_size|
(rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)|
(rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS));

/* Set interrupt coalescing timer to default (2048 usecs) */
iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF);

return 0;
}

static void iwlagn_set_pwr_vmain(struct iwl_priv *priv)
{
/*
Expand All @@ -695,10 +645,10 @@ static void iwlagn_set_pwr_vmain(struct iwl_priv *priv)
~APMG_PS_CTRL_MSK_PWR_SRC);
}

/*TODO: this function should move to transport layer */
int iwlagn_hw_nic_init(struct iwl_priv *priv)
{
unsigned long flags;
struct iwl_rx_queue *rxq = &priv->rxq;

/* nic_init */
spin_lock_irqsave(&priv->lock, flags);
Expand All @@ -716,17 +666,6 @@ int iwlagn_hw_nic_init(struct iwl_priv *priv)
/* Allocate the RX queue, or reset if it is already allocated */
trans_rx_init(priv);

iwlagn_rx_replenish(priv);

iwlagn_rx_init(priv, rxq);

spin_lock_irqsave(&priv->lock, flags);

rxq->need_update = 1;
iwl_rx_queue_update_write_ptr(priv, rxq);

spin_unlock_irqrestore(&priv->lock, flags);

/* Allocate or reset and init all Tx and Command queues */
if (trans_tx_init(priv))
return -ENOMEM;
Expand All @@ -742,169 +681,6 @@ int iwlagn_hw_nic_init(struct iwl_priv *priv)
return 0;
}

/**
* iwlagn_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr
*/
static inline __le32 iwlagn_dma_addr2rbd_ptr(struct iwl_priv *priv,
dma_addr_t dma_addr)
{
return cpu_to_le32((u32)(dma_addr >> 8));
}

/**
* iwlagn_rx_queue_restock - refill RX queue from pre-allocated pool
*
* If there are slots in the RX queue that need to be restocked,
* and we have free pre-allocated buffers, fill the ranks as much
* as we can, pulling from rx_free.
*
* This moves the 'write' index forward to catch up with 'processed', and
* also updates the memory address in the firmware to reference the new
* target buffer.
*/
void iwlagn_rx_queue_restock(struct iwl_priv *priv)
{
struct iwl_rx_queue *rxq = &priv->rxq;
struct list_head *element;
struct iwl_rx_mem_buffer *rxb;
unsigned long flags;

spin_lock_irqsave(&rxq->lock, flags);
while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) {
/* The overwritten rxb must be a used one */
rxb = rxq->queue[rxq->write];
BUG_ON(rxb && rxb->page);

/* Get next free Rx buffer, remove from free list */
element = rxq->rx_free.next;
rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
list_del(element);

/* Point to Rx buffer via next RBD in circular buffer */
rxq->bd[rxq->write] = iwlagn_dma_addr2rbd_ptr(priv,
rxb->page_dma);
rxq->queue[rxq->write] = rxb;
rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
rxq->free_count--;
}
spin_unlock_irqrestore(&rxq->lock, flags);
/* If the pre-allocated buffer pool is dropping low, schedule to
* refill it */
if (rxq->free_count <= RX_LOW_WATERMARK)
queue_work(priv->workqueue, &priv->rx_replenish);


/* If we've added more space for the firmware to place data, tell it.
* Increment device's write pointer in multiples of 8. */
if (rxq->write_actual != (rxq->write & ~0x7)) {
spin_lock_irqsave(&rxq->lock, flags);
rxq->need_update = 1;
spin_unlock_irqrestore(&rxq->lock, flags);
iwl_rx_queue_update_write_ptr(priv, rxq);
}
}

/**
* iwlagn_rx_replenish - Move all used packet from rx_used to rx_free
*
* When moving to rx_free an SKB is allocated for the slot.
*
* Also restock the Rx queue via iwl_rx_queue_restock.
* This is called as a scheduled work item (except for during initialization)
*/
void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority)
{
struct iwl_rx_queue *rxq = &priv->rxq;
struct list_head *element;
struct iwl_rx_mem_buffer *rxb;
struct page *page;
unsigned long flags;
gfp_t gfp_mask = priority;

while (1) {
spin_lock_irqsave(&rxq->lock, flags);
if (list_empty(&rxq->rx_used)) {
spin_unlock_irqrestore(&rxq->lock, flags);
return;
}
spin_unlock_irqrestore(&rxq->lock, flags);

if (rxq->free_count > RX_LOW_WATERMARK)
gfp_mask |= __GFP_NOWARN;

if (priv->hw_params.rx_page_order > 0)
gfp_mask |= __GFP_COMP;

/* Alloc a new receive buffer */
page = alloc_pages(gfp_mask, priv->hw_params.rx_page_order);
if (!page) {
if (net_ratelimit())
IWL_DEBUG_INFO(priv, "alloc_pages failed, "
"order: %d\n",
priv->hw_params.rx_page_order);

if ((rxq->free_count <= RX_LOW_WATERMARK) &&
net_ratelimit())
IWL_CRIT(priv, "Failed to alloc_pages with %s. Only %u free buffers remaining.\n",
priority == GFP_ATOMIC ? "GFP_ATOMIC" : "GFP_KERNEL",
rxq->free_count);
/* We don't reschedule replenish work here -- we will
* call the restock method and if it still needs
* more buffers it will schedule replenish */
return;
}

spin_lock_irqsave(&rxq->lock, flags);

if (list_empty(&rxq->rx_used)) {
spin_unlock_irqrestore(&rxq->lock, flags);
__free_pages(page, priv->hw_params.rx_page_order);
return;
}
element = rxq->rx_used.next;
rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
list_del(element);

spin_unlock_irqrestore(&rxq->lock, flags);

BUG_ON(rxb->page);
rxb->page = page;
/* Get physical address of the RB */
rxb->page_dma = dma_map_page(priv->bus.dev, page, 0,
PAGE_SIZE << priv->hw_params.rx_page_order,
DMA_FROM_DEVICE);
/* dma address must be no more than 36 bits */
BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36));
/* and also 256 byte aligned! */
BUG_ON(rxb->page_dma & DMA_BIT_MASK(8));

spin_lock_irqsave(&rxq->lock, flags);

list_add_tail(&rxb->list, &rxq->rx_free);
rxq->free_count++;

spin_unlock_irqrestore(&rxq->lock, flags);
}
}

void iwlagn_rx_replenish(struct iwl_priv *priv)
{
unsigned long flags;

iwlagn_rx_allocate(priv, GFP_KERNEL);

spin_lock_irqsave(&priv->lock, flags);
iwlagn_rx_queue_restock(priv);
spin_unlock_irqrestore(&priv->lock, flags);
}

void iwlagn_rx_replenish_now(struct iwl_priv *priv)
{
iwlagn_rx_allocate(priv, GFP_ATOMIC);

iwlagn_rx_queue_restock(priv);
}

int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band)
{
int idx = 0;
Expand Down
Loading

0 comments on commit ab697a9

Please sign in to comment.