From: reinette chatre <reinette.chatre@intel.com>
To: Jason Andryuk <jandryuk@gmail.com>
Cc: "Kolekar, Abhijeet" <abhijeet.kolekar@intel.com>,
Samuel Ortiz <samuel@sortiz.org>,
Tomas Winkler <tomasw@gmail.com>,
"linux-wireless@vger.kernel.org" <linux-wireless@vger.kernel.org>
Subject: Re: kernel BUG at drivers/net/wireless/iwlwifi/iwl3945-base.c:3127!
Date: Tue, 21 Apr 2009 08:42:49 -0700 [thread overview]
Message-ID: <1240328569.19630.2.camel@rc-desk> (raw)
In-Reply-To: <c4d76b3b0904201841m502cb3bbw45a0c5c1c52295ba@mail.gmail.com>
Hi Jason,
During our internal validation we found that the patch I sent to you
broke fragmentation on 5100 hardware. It took me a while to figure out
the problem and I was able to create a new patch last week. This patch
has just passed our internal validation so I will send it upstream asap.
Reinette
On Mon, 2009-04-20 at 18:41 -0700, Jason Andryuk wrote:
> Reinette,
>
> This patch never made it to wireless-testing.
>
> Jason
>
> On Tue, Mar 31, 2009 at 6:22 PM, reinette chatre
> <reinette.chatre@intel.com> wrote:
> > I addressed these issues as well as a few more that I uncovered while
> > digging into this.
> >
> > Could you please try this patch?
> >
> >
> > >From c152258435c047dfd7423e0279781c3fcb2f4e71 Mon Sep 17 00:00:00 2001
> > From: Reinette Chatre <reinette.chatre@intel.com>
> > Date: Tue, 31 Mar 2009 14:16:05 -0700
> > Subject: [PATCH] iwlwifi: DMA fixes
> >
> > A few issues wrt DMA were uncovered when using the driver with swiotlb.
> > - driver should not use memory after it has been mapped
> > - iwl3945's RX queue management cannot use all of iwlagn because
> > the size of the RX buffer is different. Revert back to using
> > iwl3945 specific routines that map/unmap memory.
> > - no need to "dma_syn_single_range_for_cpu" followed by pci_unmap_single,
> > we can just call pci_unmap_single initially
> > - only map the memory area that will be used by device. this is especially
> > relevant to the mapping of iwl_cmd. we should not map the entire
> > structure because the meta data at the beginning of structure contains
> > the address to be used later for unmapping. If the address to be used for
> > unmapping is stored in mapped data it creates a problem.
> > - ensure that _if_ memory needs to be modified after it is mapped that we
> > call _sync_single_for_cpu first, and then release it back to device with
> > _sync_single_for_device
> > - we mapped the wrong length of data for host commands, with mapped length
> > differing with length provided to device, fix that.
> >
> > Thanks to Jason Andryuk <jandryuk@gmail.com> for significant bisecting
> > help to find these issues.
> >
> > Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
> > CC: Jason Andryuk <jandryuk@gmail.com>
> > ---
> > drivers/net/wireless/iwlwifi/iwl-3945.c | 2 +-
> > drivers/net/wireless/iwlwifi/iwl-3945.h | 1 +
> > drivers/net/wireless/iwlwifi/iwl-agn.c | 11 +--
> > drivers/net/wireless/iwlwifi/iwl-dev.h | 4 +
> > drivers/net/wireless/iwlwifi/iwl-tx.c | 93 ++++++++++--------
> > drivers/net/wireless/iwlwifi/iwl3945-base.c | 144 +++++++++++++++++++--------
> > 6 files changed, 161 insertions(+), 94 deletions(-)
> >
> > diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
> > index d03f553..05cd499 100644
> > --- a/drivers/net/wireless/iwlwifi/iwl-3945.c
> > +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
> > @@ -1192,7 +1192,7 @@ int iwl3945_hw_nic_init(struct iwl_priv *priv)
> > return -ENOMEM;
> > }
> > } else
> > - iwl_rx_queue_reset(priv, rxq);
> > + iwl3945_rx_queue_reset(priv, rxq);
> >
> > iwl3945_rx_replenish(priv);
> >
> > diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h
> > index 29bc0d2..3213a63 100644
> > --- a/drivers/net/wireless/iwlwifi/iwl-3945.h
> > +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h
> > @@ -214,6 +214,7 @@ extern int iwl3945_calc_sig_qual(int rssi_dbm, int noise_dbm);
> > extern int iwl3945_tx_queue_init(struct iwl_priv *priv,
> > struct iwl_tx_queue *txq, int count, u32 id);
> > extern void iwl3945_rx_replenish(void *data);
> > +extern void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
> > extern void iwl3945_tx_queue_free(struct iwl_priv *priv, struct iwl_tx_queue *txq);
> > extern int iwl3945_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len,
> > const void *data);
> > diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
> > index 51f6a01..ea859f6 100644
> > --- a/drivers/net/wireless/iwlwifi/iwl-agn.c
> > +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
> > @@ -976,11 +976,9 @@ void iwl_rx_handle(struct iwl_priv *priv)
> >
> > rxq->queue[i] = NULL;
> >
> > - dma_sync_single_range_for_cpu(
> > - &priv->pci_dev->dev, rxb->real_dma_addr,
> > - rxb->aligned_dma_addr - rxb->real_dma_addr,
> > - priv->hw_params.rx_buf_size,
> > - PCI_DMA_FROMDEVICE);
> > + pci_unmap_single(priv->pci_dev, rxb->real_dma_addr,
> > + priv->hw_params.rx_buf_size + 256,
> > + PCI_DMA_FROMDEVICE);
> > pkt = (struct iwl_rx_packet *)rxb->skb->data;
> >
> > /* Reclaim a command buffer only if this packet is a response
> > @@ -1031,9 +1029,6 @@ void iwl_rx_handle(struct iwl_priv *priv)
> > rxb->skb = NULL;
> > }
> >
> > - pci_unmap_single(priv->pci_dev, rxb->real_dma_addr,
> > - priv->hw_params.rx_buf_size + 256,
> > - PCI_DMA_FROMDEVICE);
> > spin_lock_irqsave(&rxq->lock, flags);
> > list_add_tail(&rxb->list, &priv->rxq.rx_used);
> > spin_unlock_irqrestore(&rxq->lock, flags);
> > diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
> > index 0baae80..721c80f 100644
> > --- a/drivers/net/wireless/iwlwifi/iwl-dev.h
> > +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
> > @@ -360,12 +360,16 @@ struct iwl_host_cmd {
> >
> > /**
> > * struct iwl_rx_queue - Rx queue
> > + * @bd: driver's pointer to buffer of receive buffer descriptors (rbd)
> > + * @dma_addr: bus address of buffer of receive buffer descriptors (rbd)
> > * @read: Shared index to newest available Rx buffer
> > * @write: Shared index to oldest written Rx packet
> > * @free_count: Number of pre-allocated buffers in rx_free
> > * @rx_free: list of free SKBs for use
> > * @rx_used: List of Rx buffers with no SKB
> > * @need_update: flag to indicate we need to update read/write index
> > + * @rb_stts: driver's pointer to receive buffer status
> > + * @rb_stts_dma: bus address of receive buffer status
> > *
> > * NOTE: rx_free and rx_used are used as a FIFO for iwl_rx_mem_buffers
> > */
> > diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
> > index 57ea320..f85b47f 100644
> > --- a/drivers/net/wireless/iwlwifi/iwl-tx.c
> > +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
> > @@ -797,6 +797,22 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
> > /* Copy MAC header from skb into command buffer */
> > memcpy(tx_cmd->hdr, hdr, hdr_len);
> >
> > +
> > + /* Total # bytes to be transmitted */
> > + len = (u16)skb->len;
> > + tx_cmd->len = cpu_to_le16(len);
> > +
> > + if (info->control.hw_key)
> > + iwl_tx_cmd_build_hwcrypto(priv, info, tx_cmd, skb, sta_id);
> > +
> > + /* TODO need this for burst mode later on */
> > + iwl_tx_cmd_build_basic(priv, tx_cmd, info, hdr, sta_id);
> > +
> > + /* set is_hcca to 0; it probably will never be implemented */
> > + iwl_tx_cmd_build_rate(priv, tx_cmd, info, fc, sta_id, 0);
> > +
> > + iwl_update_tx_stats(priv, le16_to_cpu(fc), len);
> > +
> > /*
> > * Use the first empty entry in this queue's command buffer array
> > * to contain the Tx command and MAC header concatenated together
> > @@ -817,21 +833,30 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
> > else
> > len_org = 0;
> >
> > + /* Tell NIC about any 2-byte padding after MAC header */
> > + if (len_org)
> > + tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK;
> > +
> > /* Physical address of this Tx command's header (not MAC header!),
> > * within command buffer array. */
> > txcmd_phys = pci_map_single(priv->pci_dev,
> > - out_cmd, sizeof(struct iwl_cmd),
> > + &out_cmd->hdr, len,
> > PCI_DMA_BIDIRECTIONAL);
> > pci_unmap_addr_set(&out_cmd->meta, mapping, txcmd_phys);
> > - pci_unmap_len_set(&out_cmd->meta, len, sizeof(struct iwl_cmd));
> > + pci_unmap_len_set(&out_cmd->meta, len, len);
> > /* Add buffer containing Tx command and MAC(!) header to TFD's
> > * first entry */
> > - txcmd_phys += offsetof(struct iwl_cmd, hdr);
> > priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
> > txcmd_phys, len, 1, 0);
> >
> > - if (info->control.hw_key)
> > - iwl_tx_cmd_build_hwcrypto(priv, info, tx_cmd, skb, sta_id);
> > + if (!ieee80211_has_morefrags(hdr->frame_control)) {
> > + txq->need_update = 1;
> > + if (qc)
> > + priv->stations[sta_id].tid[tid].seq_number = seq_number;
> > + } else {
> > + wait_write_ptr = 1;
> > + txq->need_update = 0;
> > + }
> >
> > /* Set up TFD's 2nd entry to point directly to remainder of skb,
> > * if any (802.11 null frames have no payload). */
> > @@ -844,42 +869,26 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
> > 0, 0);
> > }
> >
> > - /* Tell NIC about any 2-byte padding after MAC header */
> > - if (len_org)
> > - tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK;
> > -
> > - /* Total # bytes to be transmitted */
> > - len = (u16)skb->len;
> > - tx_cmd->len = cpu_to_le16(len);
> > - /* TODO need this for burst mode later on */
> > - iwl_tx_cmd_build_basic(priv, tx_cmd, info, hdr, sta_id);
> > -
> > - /* set is_hcca to 0; it probably will never be implemented */
> > - iwl_tx_cmd_build_rate(priv, tx_cmd, info, fc, sta_id, 0);
> > -
> > - iwl_update_tx_stats(priv, le16_to_cpu(fc), len);
> > -
> > scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) +
> > - offsetof(struct iwl_tx_cmd, scratch);
> > + offsetof(struct iwl_tx_cmd, scratch);
> > +
> > + len = sizeof(struct iwl_tx_cmd) +
> > + sizeof(struct iwl_cmd_header) + hdr_len;
> > + /* take back ownership of DMA buffer to enable update */
> > + pci_dma_sync_single_for_cpu(priv->pci_dev, txcmd_phys,
> > + len, PCI_DMA_BIDIRECTIONAL);
> > tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys);
> > tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys);
> >
> > - if (!ieee80211_has_morefrags(hdr->frame_control)) {
> > - txq->need_update = 1;
> > - if (qc)
> > - priv->stations[sta_id].tid[tid].seq_number = seq_number;
> > - } else {
> > - wait_write_ptr = 1;
> > - txq->need_update = 0;
> > - }
> > -
> > iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd));
> > -
> > iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len);
> >
> > /* Set up entry for this TFD in Tx byte-count array */
> > priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, len);
> >
> > + pci_dma_sync_single_for_device(priv->pci_dev, txcmd_phys,
> > + len, PCI_DMA_BIDIRECTIONAL);
> > +
> > /* Tell device the write index *just past* this latest filled TFD */
> > q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
> > ret = iwl_txq_update_write_ptr(priv, txq);
> > @@ -966,18 +975,9 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
> > INDEX_TO_SEQ(q->write_ptr));
> > if (out_cmd->meta.flags & CMD_SIZE_HUGE)
> > out_cmd->hdr.sequence |= SEQ_HUGE_FRAME;
> > - len = (idx == TFD_CMD_SLOTS) ?
> > - IWL_MAX_SCAN_SIZE : sizeof(struct iwl_cmd);
> > -
> > - phys_addr = pci_map_single(priv->pci_dev, out_cmd,
> > - len, PCI_DMA_BIDIRECTIONAL);
> > - pci_unmap_addr_set(&out_cmd->meta, mapping, phys_addr);
> > - pci_unmap_len_set(&out_cmd->meta, len, len);
> > - phys_addr += offsetof(struct iwl_cmd, hdr);
> > + len = sizeof(struct iwl_cmd) - sizeof(struct iwl_cmd_meta);
> > + len += (idx == TFD_CMD_SLOTS) ? IWL_MAX_SCAN_SIZE : 0;
> >
> > - priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
> > - phys_addr, fix_size, 1,
> > - U32_PAD(cmd->len));
> >
> > #ifdef CONFIG_IWLWIFI_DEBUG
> > switch (out_cmd->hdr.cmd) {
> > @@ -1005,6 +1005,15 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
> > /* Set up entry in queue's byte count circular buffer */
> > priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, 0);
> >
> > + phys_addr = pci_map_single(priv->pci_dev, &out_cmd->hdr,
> > + fix_size, PCI_DMA_BIDIRECTIONAL);
> > + pci_unmap_addr_set(&out_cmd->meta, mapping, phys_addr);
> > + pci_unmap_len_set(&out_cmd->meta, len, fix_size);
> > +
> > + priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
> > + phys_addr, fix_size, 1,
> > + U32_PAD(cmd->len));
> > +
> > /* Increment and update queue's write index */
> > q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
> > ret = iwl_txq_update_write_ptr(priv, txq);
> > diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
> > index c29189b..c4c8943 100644
> > --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
> > +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
> > @@ -972,7 +972,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
> > dma_addr_t phys_addr;
> > dma_addr_t txcmd_phys;
> > int txq_id = skb_get_queue_mapping(skb);
> > - u16 len, idx, len_org, hdr_len;
> > + u16 len, idx, len_org, hdr_len; /* TODO: len_org is not used */
> > u8 id;
> > u8 unicast;
> > u8 sta_id;
> > @@ -1074,6 +1074,38 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
> > /* Copy MAC header from skb into command buffer */
> > memcpy(tx->hdr, hdr, hdr_len);
> >
> > +
> > + if (info->control.hw_key)
> > + iwl3945_build_tx_cmd_hwcrypto(priv, info, out_cmd, skb, sta_id);
> > +
> > + /* TODO need this for burst mode later on */
> > + iwl3945_build_tx_cmd_basic(priv, out_cmd, info, hdr, sta_id);
> > +
> > + /* set is_hcca to 0; it probably will never be implemented */
> > + iwl3945_hw_build_tx_cmd_rate(priv, out_cmd, info, hdr, sta_id, 0);
> > +
> > + /* Total # bytes to be transmitted */
> > + len = (u16)skb->len;
> > + tx->len = cpu_to_le16(len);
> > +
> > +
> > + tx->tx_flags &= ~TX_CMD_FLG_ANT_A_MSK;
> > + tx->tx_flags &= ~TX_CMD_FLG_ANT_B_MSK;
> > +
> > + if (!ieee80211_has_morefrags(hdr->frame_control)) {
> > + txq->need_update = 1;
> > + if (qc)
> > + priv->stations_39[sta_id].tid[tid].seq_number = seq_number;
> > + } else {
> > + wait_write_ptr = 1;
> > + txq->need_update = 0;
> > + }
> > +
> > + iwl_print_hex_dump(priv, IWL_DL_TX, tx, sizeof(*tx));
> > +
> > + iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx->hdr,
> > + ieee80211_hdrlen(fc));
> > +
> > /*
> > * Use the first empty entry in this queue's command buffer array
> > * to contain the Tx command and MAC header concatenated together
> > @@ -1096,22 +1128,18 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
> >
> > /* Physical address of this Tx command's header (not MAC header!),
> > * within command buffer array. */
> > - txcmd_phys = pci_map_single(priv->pci_dev,
> > - out_cmd, sizeof(struct iwl_cmd),
> > - PCI_DMA_TODEVICE);
> > + txcmd_phys = pci_map_single(priv->pci_dev, &out_cmd->hdr,
> > + len, PCI_DMA_TODEVICE);
> > + /* we do not map meta data ... so we can safely access address to
> > + * provide to unmap command*/
> > pci_unmap_addr_set(&out_cmd->meta, mapping, txcmd_phys);
> > - pci_unmap_len_set(&out_cmd->meta, len, sizeof(struct iwl_cmd));
> > - /* Add buffer containing Tx command and MAC(!) header to TFD's
> > - * first entry */
> > - txcmd_phys += offsetof(struct iwl_cmd, hdr);
> > + pci_unmap_len_set(&out_cmd->meta, len, len);
> >
> > /* Add buffer containing Tx command and MAC(!) header to TFD's
> > * first entry */
> > priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
> > txcmd_phys, len, 1, 0);
> >
> > - if (info->control.hw_key)
> > - iwl3945_build_tx_cmd_hwcrypto(priv, info, out_cmd, skb, sta_id);
> >
> > /* Set up TFD's 2nd entry to point directly to remainder of skb,
> > * if any (802.11 null frames have no payload). */
> > @@ -1124,32 +1152,6 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
> > 0, U32_PAD(len));
> > }
> >
> > - /* Total # bytes to be transmitted */
> > - len = (u16)skb->len;
> > - tx->len = cpu_to_le16(len);
> > -
> > - /* TODO need this for burst mode later on */
> > - iwl3945_build_tx_cmd_basic(priv, out_cmd, info, hdr, sta_id);
> > -
> > - /* set is_hcca to 0; it probably will never be implemented */
> > - iwl3945_hw_build_tx_cmd_rate(priv, out_cmd, info, hdr, sta_id, 0);
> > -
> > - tx->tx_flags &= ~TX_CMD_FLG_ANT_A_MSK;
> > - tx->tx_flags &= ~TX_CMD_FLG_ANT_B_MSK;
> > -
> > - if (!ieee80211_has_morefrags(hdr->frame_control)) {
> > - txq->need_update = 1;
> > - if (qc)
> > - priv->stations_39[sta_id].tid[tid].seq_number = seq_number;
> > - } else {
> > - wait_write_ptr = 1;
> > - txq->need_update = 0;
> > - }
> > -
> > - iwl_print_hex_dump(priv, IWL_DL_TX, tx, sizeof(*tx));
> > -
> > - iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx->hdr,
> > - ieee80211_hdrlen(fc));
> >
> > /* Tell device the write index *just past* this latest filled TFD */
> > q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
> > @@ -1661,6 +1663,37 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv)
> > spin_unlock_irqrestore(&rxq->lock, flags);
> > }
> >
> > +void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
> > +{
> > + unsigned long flags;
> > + int i;
> > + spin_lock_irqsave(&rxq->lock, flags);
> > + INIT_LIST_HEAD(&rxq->rx_free);
> > + INIT_LIST_HEAD(&rxq->rx_used);
> > + /* Fill the rx_used queue with _all_ of the Rx buffers */
> > + for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
> > + /* In the reset function, these buffers may have been allocated
> > + * to an SKB, so we need to unmap and free potential storage */
> > + if (rxq->pool[i].skb != NULL) {
> > + pci_unmap_single(priv->pci_dev,
> > + rxq->pool[i].real_dma_addr,
> > + priv->hw_params.rx_buf_size,
> > + PCI_DMA_FROMDEVICE);
> > + priv->alloc_rxb_skb--;
> > + dev_kfree_skb(rxq->pool[i].skb);
> > + rxq->pool[i].skb = NULL;
> > + }
> > + list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
> > + }
> > +
> > + /* Set us so that we have processed and used all buffers, but have
> > + * not restocked the Rx queue with fresh buffers */
> > + rxq->read = rxq->write = 0;
> > + rxq->free_count = 0;
> > + spin_unlock_irqrestore(&rxq->lock, flags);
> > +}
> > +EXPORT_SYMBOL(iwl3945_rx_queue_reset);
> > +
> > /*
> > * this should be called while priv->lock is locked
> > */
> > @@ -1685,6 +1718,34 @@ void iwl3945_rx_replenish(void *data)
> > spin_unlock_irqrestore(&priv->lock, flags);
> > }
> >
> > +/* Assumes that the skb field of the buffers in 'pool' is kept accurate.
> > + * If an SKB has been detached, the POOL needs to have its SKB set to NULL
> > + * This free routine walks the list of POOL entries and if SKB is set to
> > + * non NULL it is unmapped and freed
> > + */
> > +void iwl3945_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
> > +{
> > + int i;
> > + for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
> > + if (rxq->pool[i].skb != NULL) {
> > + pci_unmap_single(priv->pci_dev,
> > + rxq->pool[i].real_dma_addr,
> > + priv->hw_params.rx_buf_size,
> > + PCI_DMA_FROMDEVICE);
> > + dev_kfree_skb(rxq->pool[i].skb);
> > + }
> > + }
> > +
> > + pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd,
> > + rxq->dma_addr);
> > + pci_free_consistent(priv->pci_dev, sizeof(struct iwl_rb_status),
> > + rxq->rb_stts, rxq->rb_stts_dma);
> > + rxq->bd = NULL;
> > + rxq->rb_stts = NULL;
> > +}
> > +EXPORT_SYMBOL(iwl3945_rx_queue_free);
> > +
> > +
> > /* Convert linear signal-to-noise ratio into dB */
> > static u8 ratio2dB[100] = {
> > /* 0 1 2 3 4 5 6 7 8 9 */
> > @@ -1802,9 +1863,9 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)
> >
> > rxq->queue[i] = NULL;
> >
> > - pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->real_dma_addr,
> > - priv->hw_params.rx_buf_size,
> > - PCI_DMA_FROMDEVICE);
> > + pci_unmap_single(priv->pci_dev, rxb->real_dma_addr,
> > + priv->hw_params.rx_buf_size,
> > + PCI_DMA_FROMDEVICE);
> > pkt = (struct iwl_rx_packet *)rxb->skb->data;
> >
> > /* Reclaim a command buffer only if this packet is a response
> > @@ -1852,9 +1913,6 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)
> > rxb->skb = NULL;
> > }
> >
> > - pci_unmap_single(priv->pci_dev, rxb->real_dma_addr,
> > - priv->hw_params.rx_buf_size,
> > - PCI_DMA_FROMDEVICE);
> > spin_lock_irqsave(&rxq->lock, flags);
> > list_add_tail(&rxb->list, &priv->rxq.rx_used);
> > spin_unlock_irqrestore(&rxq->lock, flags);
> > @@ -5144,7 +5202,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
> > iwl3945_dealloc_ucode_pci(priv);
> >
> > if (priv->rxq.bd)
> > - iwl_rx_queue_free(priv, &priv->rxq);
> > + iwl3945_rx_queue_free(priv, &priv->rxq);
> > iwl3945_hw_txq_ctx_free(priv);
> >
> > iwl3945_unset_hw_params(priv);
> > --
> > 1.5.6.3
> >
> >
> >
> >
next prev parent reply other threads:[~2009-04-21 15:36 UTC|newest]
Thread overview: 56+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-01-18 0:06 kernel BUG at drivers/net/wireless/iwlwifi/iwl3945-base.c:3127! Deuce
2009-01-18 17:41 ` Deuce
2009-01-26 11:44 ` Samuel Ortiz
2009-01-27 3:13 ` Jason Andryuk
2009-01-27 3:35 ` Jason Andryuk
2009-01-27 16:24 ` Samuel Ortiz
2009-01-27 23:31 ` Jason Andryuk
2009-01-28 7:12 ` Tomas Winkler
2009-01-28 11:37 ` Samuel Ortiz
2009-01-28 11:52 ` Tomas Winkler
2009-01-28 12:12 ` Samuel Ortiz
2009-02-20 4:17 ` Jason Andryuk
2009-02-20 19:49 ` reinette chatre
2009-02-23 0:10 ` Jason Andryuk
2009-02-23 4:37 ` Jason Andryuk
2009-02-23 19:21 ` reinette chatre
2009-02-23 22:28 ` reinette chatre
2009-02-24 3:02 ` Jason Andryuk
2009-02-24 0:15 ` reinette chatre
2009-02-24 2:47 ` Jason Andryuk
2009-03-02 3:37 ` Jason Andryuk
2009-03-04 4:32 ` Jason Andryuk
2009-03-04 19:19 ` reinette chatre
2009-03-04 19:47 ` Jason Andryuk
2009-03-05 0:04 ` reinette chatre
2009-03-05 23:50 ` Jason Andryuk
2009-03-06 0:24 ` reinette chatre
2009-03-06 4:12 ` Jason Andryuk
2009-03-06 5:39 ` reinette chatre
2009-03-10 1:40 ` Jason Andryuk
2009-03-10 3:32 ` Jason Andryuk
2009-03-10 5:04 ` reinette chatre
2009-03-10 13:10 ` Jason Andryuk
2009-03-10 18:22 ` Abhijeet Kolekar
2009-03-11 3:11 ` Jason Andryuk
2009-03-11 2:57 ` Jason Andryuk
2009-03-11 3:40 ` Jason Andryuk
2009-03-13 3:31 ` Jason Andryuk
2009-03-16 12:10 ` Jason Andryuk
2009-03-17 1:44 ` Jason Andryuk
2009-03-19 1:52 ` Jason Andryuk
2009-03-20 1:22 ` Jason Andryuk
2009-03-20 20:39 ` Abhijeet Kolekar
2009-03-22 17:29 ` Jason Andryuk
2009-03-23 0:37 ` Jason Andryuk
2009-03-27 16:28 ` reinette chatre
2009-03-31 22:22 ` reinette chatre
2009-04-01 1:28 ` Jason Andryuk
2009-04-21 1:41 ` Jason Andryuk
2009-04-21 15:42 ` reinette chatre [this message]
-- strict thread matches above, loose matches on Subject: below --
2009-01-09 3:28 Deuce
2009-01-09 19:12 ` reinette chatre
2009-01-09 23:07 ` Deuce
2009-01-12 18:38 ` Samuel Ortiz
2009-01-13 3:12 ` Deuce
2009-01-13 4:37 ` Deuce
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1240328569.19630.2.camel@rc-desk \
--to=reinette.chatre@intel.com \
--cc=abhijeet.kolekar@intel.com \
--cc=jandryuk@gmail.com \
--cc=linux-wireless@vger.kernel.org \
--cc=samuel@sortiz.org \
--cc=tomasw@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).