Skip to content

Commit

Permalink
Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/…
Browse files Browse the repository at this point in the history
…git/iwlwifi/iwlwifi-next
  • Loading branch information
John W. Linville committed Sep 24, 2012
2 parents 9b4e9e7 + 83f84d7 commit e5a8762
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 90 deletions.
4 changes: 2 additions & 2 deletions drivers/net/wireless/iwlwifi/dvm/ucode.c
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ static int iwl_alive_notify(struct iwl_priv *priv)
static int iwl_verify_sec_sparse(struct iwl_priv *priv,
const struct fw_desc *fw_desc)
{
__le32 *image = (__le32 *)fw_desc->v_addr;
__le32 *image = (__le32 *)fw_desc->data;
u32 len = fw_desc->len;
u32 val;
u32 i;
Expand All @@ -319,7 +319,7 @@ static int iwl_verify_sec_sparse(struct iwl_priv *priv,
static void iwl_print_mismatch_sec(struct iwl_priv *priv,
const struct fw_desc *fw_desc)
{
__le32 *image = (__le32 *)fw_desc->v_addr;
__le32 *image = (__le32 *)fw_desc->data;
u32 len = fw_desc->len;
u32 val;
u32 offs;
Expand Down
26 changes: 14 additions & 12 deletions drivers/net/wireless/iwlwifi/iwl-drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
#include <linux/dma-mapping.h>
#include <linux/firmware.h>
#include <linux/module.h>
#include <linux/vmalloc.h>

#include "iwl-drv.h"
#include "iwl-debug.h"
Expand Down Expand Up @@ -164,10 +165,8 @@ struct fw_sec {

static void iwl_free_fw_desc(struct iwl_drv *drv, struct fw_desc *desc)
{
if (desc->v_addr)
dma_free_coherent(drv->trans->dev, desc->len,
desc->v_addr, desc->p_addr);
desc->v_addr = NULL;
vfree(desc->data);
desc->data = NULL;
desc->len = 0;
}

Expand All @@ -186,21 +185,24 @@ static void iwl_dealloc_ucode(struct iwl_drv *drv)
}

static int iwl_alloc_fw_desc(struct iwl_drv *drv, struct fw_desc *desc,
struct fw_sec *sec)
struct fw_sec *sec)
{
if (!sec || !sec->size) {
desc->v_addr = NULL;
void *data;

desc->data = NULL;

if (!sec || !sec->size)
return -EINVAL;
}

desc->v_addr = dma_alloc_coherent(drv->trans->dev, sec->size,
&desc->p_addr, GFP_KERNEL);
if (!desc->v_addr)
data = vmalloc(sec->size);
if (!data)
return -ENOMEM;

desc->len = sec->size;
desc->offset = sec->offset;
memcpy(desc->v_addr, sec->data, sec->size);
memcpy(data, sec->data, desc->len);
desc->data = data;

return 0;
}

Expand Down
3 changes: 1 addition & 2 deletions drivers/net/wireless/iwlwifi/iwl-fw.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,7 @@ struct iwl_ucode_capabilities {

/* one for each uCode image (inst/data, init/runtime/wowlan) */
struct fw_desc {
dma_addr_t p_addr; /* hardware address */
void *v_addr; /* software address */
const void *data; /* vmalloc'ed data */
u32 len; /* size in bytes */
u32 offset; /* offset in the device */
};
Expand Down
13 changes: 0 additions & 13 deletions drivers/net/wireless/iwlwifi/pcie/drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -263,8 +263,6 @@ MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids);
/* PCI registers */
#define PCI_CFG_RETRY_TIMEOUT 0x041

#ifndef CONFIG_IWLWIFI_IDI

static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
const struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
Expand Down Expand Up @@ -307,8 +305,6 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
pci_set_drvdata(pdev, NULL);
}

#endif /* CONFIG_IWLWIFI_IDI */

#ifdef CONFIG_PM_SLEEP

static int iwl_pci_suspend(struct device *device)
Expand Down Expand Up @@ -353,15 +349,6 @@ static SIMPLE_DEV_PM_OPS(iwl_dev_pm_ops, iwl_pci_suspend, iwl_pci_resume);

#endif

#ifdef CONFIG_IWLWIFI_IDI
/*
* Defined externally in iwl-idi.c
*/
int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
void __devexit iwl_pci_remove(struct pci_dev *pdev);

#endif /* CONFIG_IWLWIFI_IDI */

static struct pci_driver iwl_pci_driver = {
.name = DRV_NAME,
.id_table = iwl_hw_card_ids,
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/iwlwifi/pcie/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ void iwl_trans_pcie_free(struct iwl_trans *trans);
******************************************************/
void iwl_bg_rx_replenish(struct work_struct *data);
void iwl_irq_tasklet(struct iwl_trans *trans);
void iwlagn_rx_replenish(struct iwl_trans *trans);
void iwl_rx_replenish(struct iwl_trans *trans);
void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans,
struct iwl_rx_queue *q);

Expand Down
75 changes: 44 additions & 31 deletions drivers/net/wireless/iwlwifi/pcie/rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,6 @@
#include "internal.h"
#include "iwl-op-mode.h"

#ifdef CONFIG_IWLWIFI_IDI
#include "iwl-amfh.h"
#endif

/******************************************************************************
*
* RX path functions
Expand Down Expand Up @@ -181,15 +177,15 @@ void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans,
}

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

/**
* iwlagn_rx_queue_restock - refill RX queue from pre-allocated pool
* iwl_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
Expand All @@ -199,14 +195,25 @@ static inline __le32 iwlagn_dma_addr2rbd_ptr(dma_addr_t dma_addr)
* also updates the memory address in the firmware to reference the new
* target buffer.
*/
static void iwlagn_rx_queue_restock(struct iwl_trans *trans)
static void iwl_rx_queue_restock(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_rx_queue *rxq = &trans_pcie->rxq;
struct list_head *element;
struct iwl_rx_mem_buffer *rxb;
unsigned long flags;

/*
* If the device isn't enabled - not need to try to add buffers...
* This can happen when we stop the device and still have an interrupt
* pending. We stop the APM before we sync the interrupts / tasklets
* because we have to (see comment there). On the other hand, since
* the APM is stopped, we cannot access the HW (in particular not prph).
* So don't try to restock if the APM has been already stopped.
*/
if (!test_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status))
return;

spin_lock_irqsave(&rxq->lock, flags);
while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) {
/* The overwritten rxb must be a used one */
Expand All @@ -219,7 +226,7 @@ static void iwlagn_rx_queue_restock(struct iwl_trans *trans)
list_del(element);

/* Point to Rx buffer via next RBD in circular buffer */
rxq->bd[rxq->write] = iwlagn_dma_addr2rbd_ptr(rxb->page_dma);
rxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(rxb->page_dma);
rxq->queue[rxq->write] = rxb;
rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
rxq->free_count--;
Expand All @@ -230,7 +237,6 @@ static void iwlagn_rx_queue_restock(struct iwl_trans *trans)
if (rxq->free_count <= RX_LOW_WATERMARK)
schedule_work(&trans_pcie->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)) {
Expand All @@ -241,15 +247,16 @@ static void iwlagn_rx_queue_restock(struct iwl_trans *trans)
}
}

/**
* 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.
/*
* iwl_rx_allocate - allocate a page for each used RBD
*
* Also restock the Rx queue via iwl_rx_queue_restock.
* This is called as a scheduled work item (except for during initialization)
* A used RBD is an Rx buffer that has been given to the stack. To use it again
* a page must be allocated and the RBD must point to the page. This function
* doesn't change the HW pointer but handles the list of pages that is used by
* iwl_rx_queue_restock. The latter function will update the HW to use the newly
* allocated buffers.
*/
static void iwlagn_rx_allocate(struct iwl_trans *trans, gfp_t priority)
static void iwl_rx_allocate(struct iwl_trans *trans, gfp_t priority)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_rx_queue *rxq = &trans_pcie->rxq;
Expand Down Expand Up @@ -328,31 +335,39 @@ static void iwlagn_rx_allocate(struct iwl_trans *trans, gfp_t priority)
}
}

void iwlagn_rx_replenish(struct iwl_trans *trans)
/*
* iwl_rx_replenish - Move all used buffers from rx_used to rx_free
*
* When moving to rx_free an page 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 iwl_rx_replenish(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
unsigned long flags;

iwlagn_rx_allocate(trans, GFP_KERNEL);
iwl_rx_allocate(trans, GFP_KERNEL);

spin_lock_irqsave(&trans_pcie->irq_lock, flags);
iwlagn_rx_queue_restock(trans);
iwl_rx_queue_restock(trans);
spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
}

static void iwlagn_rx_replenish_now(struct iwl_trans *trans)
static void iwl_rx_replenish_now(struct iwl_trans *trans)
{
iwlagn_rx_allocate(trans, GFP_ATOMIC);
iwl_rx_allocate(trans, GFP_ATOMIC);

iwlagn_rx_queue_restock(trans);
iwl_rx_queue_restock(trans);
}

void iwl_bg_rx_replenish(struct work_struct *data)
{
struct iwl_trans_pcie *trans_pcie =
container_of(data, struct iwl_trans_pcie, rx_replenish);

iwlagn_rx_replenish(trans_pcie->trans);
iwl_rx_replenish(trans_pcie->trans);
}

static void iwl_rx_handle_rxbuf(struct iwl_trans *trans,
Expand Down Expand Up @@ -530,7 +545,7 @@ static void iwl_rx_handle(struct iwl_trans *trans)
count++;
if (count >= 8) {
rxq->read = i;
iwlagn_rx_replenish_now(trans);
iwl_rx_replenish_now(trans);
count = 0;
}
}
Expand All @@ -539,9 +554,9 @@ static void iwl_rx_handle(struct iwl_trans *trans)
/* Backtrack one entry */
rxq->read = i;
if (fill_rx)
iwlagn_rx_replenish_now(trans);
iwl_rx_replenish_now(trans);
else
iwlagn_rx_queue_restock(trans);
iwl_rx_queue_restock(trans);
}

/**
Expand Down Expand Up @@ -723,11 +738,9 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
/* Disable periodic interrupt; we use it as just a one-shot. */
iwl_write8(trans, CSR_INT_PERIODIC_REG,
CSR_INT_PERIODIC_DIS);
#ifdef CONFIG_IWLWIFI_IDI
iwl_amfh_rx_handler();
#else

iwl_rx_handle(trans);
#endif

/*
* Enable periodic interrupt in 8 msec only if we received
* real RX interrupt (instead of just periodic int), to catch
Expand Down
Loading

0 comments on commit e5a8762

Please sign in to comment.