[rt2x00-users] [PATCH] rt2x00: Fix race between dma mapping and clearing rx entries in rt2800pci
Ivo Van Doorn
ivdoorn at gmail.com
Mon Sep 20 08:50:07 UTC 2010
On Fri, Sep 17, 2010 at 3:10 PM, Helmut Schaa
<helmut.schaa at googlemail.com> wrote:
> During rx, rt2x00lib calls rt2800pci_fill_rxdone to read the RX
> descriptor. At that time the skb is already dma unmapped but no new skb
> was dma mapped for this entry again. However, rt2800pci_fill_rxdone also
> moves the hw rx queue index, marking this entry to be available for
> reuse. Since no new skb was dma mapped and also the previous skb was
> unmapped this might lead to strange hw behavior.
>
> To fix this issue move the hw rx queue index increment to
> rt2800pci_clear_entry where a new skb was already dma mapped and can be
> safely used by the hw.
>
> Signed-off-by: Helmut Schaa <helmut.schaa at googlemail.com>
Applied.
Thanks
> ---
>
> I don't know if this was triggering anywhere but I've noticed this while
> debugging a stuck RX queue problem (which unfortunately is still there after
> this patch).
>
> Helmut
>
> drivers/net/wireless/rt2x00/rt2800pci.c | 15 ++++++++-------
> 1 files changed, 8 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
> index 3806454..85a134c 100644
> --- a/drivers/net/wireless/rt2x00/rt2800pci.c
> +++ b/drivers/net/wireless/rt2x00/rt2800pci.c
> @@ -241,6 +241,7 @@ static void rt2800pci_clear_entry(struct queue_entry *entry)
> {
> struct queue_entry_priv_pci *entry_priv = entry->priv_data;
> struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
> + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
> u32 word;
>
> if (entry->queue->qid == QID_RX) {
> @@ -251,6 +252,13 @@ static void rt2800pci_clear_entry(struct queue_entry *entry)
> rt2x00_desc_read(entry_priv->desc, 1, &word);
> rt2x00_set_field32(&word, RXD_W1_DMA_DONE, 0);
> rt2x00_desc_write(entry_priv->desc, 1, word);
> +
> + /*
> + * Set RX IDX in register to inform hardware that we have
> + * handled this entry and it is available for reuse again.
> + */
> + rt2800_register_write(rt2x00dev, RX_CRX_IDX,
> + entry->entry_idx);
> } else {
> rt2x00_desc_read(entry_priv->desc, 1, &word);
> rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 1);
> @@ -599,7 +607,6 @@ static void rt2800pci_kill_tx_queue(struct data_queue *queue)
> static void rt2800pci_fill_rxdone(struct queue_entry *entry,
> struct rxdone_entry_desc *rxdesc)
> {
> - struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
> struct queue_entry_priv_pci *entry_priv = entry->priv_data;
> __le32 *rxd = entry_priv->desc;
> u32 word;
> @@ -641,12 +648,6 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry,
> * Process the RXWI structure that is at the start of the buffer.
> */
> rt2800_process_rxwi(entry, rxdesc);
> -
> - /*
> - * Set RX IDX in register to inform hardware that we have handled
> - * this entry and it is available for reuse again.
> - */
> - rt2800_register_write(rt2x00dev, RX_CRX_IDX, entry->entry_idx);
> }
>
> /*
> --
> 1.7.1
>
>
> _______________________________________________
> users mailing list
> users at rt2x00.serialmonkey.com
> http://rt2x00.serialmonkey.com/mailman/listinfo/users_rt2x00.serialmonkey.com
>
More information about the users
mailing list