wil6210: fix subtle race in wil_tx_vring
authorVladimir Kondratiev <qca_vkondrat@qca.qualcomm.com>
Thu, 11 Jul 2013 15:03:41 +0000 (18:03 +0300)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 22 Jul 2013 20:54:38 +0000 (16:54 -0400)
Finish all SW context modifications prior to notifying hardware

It used to be race condition: if HW finish Tx and issue Tx completion IRQ very fast,
prior to SW context update in wil_tx_vring, Tx completion will mis-handle descriptor, as
SW part will have no skb pointer stored.

Signed-off-by: Vladimir Kondratiev <qca_vkondrat@qca.qualcomm.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/ath/wil6210/txrx.c

index 44cdd2a3dff3e371a62717215a3ed80fc4a0fc74..2a9d56a5fd0c797e24744a76c9715faa050854e9 100644 (file)
@@ -712,6 +712,12 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
        d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_DMA_IT_POS);
        *_d = *d;
 
+       /* hold reference to skb
+        * to prevent skb release before accounting
+        * in case of immediate "tx done"
+        */
+       vring->ctx[i].skb = skb_get(skb);
+
        wil_hex_dump_txrx("Tx ", DUMP_PREFIX_NONE, 32, 4,
                          (const void *)d, sizeof(*d), false);
 
@@ -720,11 +726,6 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
        wil_dbg_txrx(wil, "Tx swhead %d -> %d\n", swhead, vring->swhead);
        trace_wil6210_tx(vring_index, swhead, skb->len, nr_frags);
        iowrite32(vring->swhead, wil->csr + HOSTADDR(vring->hwtail));
-       /* hold reference to skb
-        * to prevent skb release before accounting
-        * in case of immediate "tx done"
-        */
-       vring->ctx[i].skb = skb_get(skb);
 
        return 0;
  dma_error: