ath10k: protect src_ring state with ce_lock in tx_sg()
authorMichal Kazior <michal.kazior@tieto.com>
Mon, 26 May 2014 10:02:58 +0000 (12:02 +0200)
committerKalle Valo <kvalo@qca.qualcomm.com>
Tue, 27 May 2014 09:32:02 +0000 (12:32 +0300)
It was possible to read invalid state of CE ring
buffer indexes. This could lead to scatter-gather
transfer failure in mid-way and crash firmware
later by leaving garbage data on the ring.

Reported-By: Avery Pennarun <apenwarr@gmail.com>
Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
drivers/net/wireless/ath/ath10k/pci.c

index 71ab110a4c4d2486e607d62f9fcf00151e1ea303..b1eb9153c7f48e35f5f49605b0268380642bb17f 100644 (file)
@@ -762,13 +762,17 @@ static int ath10k_pci_hif_tx_sg(struct ath10k *ar, u8 pipe_id,
        struct ath10k_pci_pipe *pci_pipe = &ar_pci->pipe_info[pipe_id];
        struct ath10k_ce_pipe *ce_pipe = pci_pipe->ce_hdl;
        struct ath10k_ce_ring *src_ring = ce_pipe->src_ring;
-       unsigned int nentries_mask = src_ring->nentries_mask;
-       unsigned int sw_index = src_ring->sw_index;
-       unsigned int write_index = src_ring->write_index;
+       unsigned int nentries_mask;
+       unsigned int sw_index;
+       unsigned int write_index;
        int err, i;
 
        spin_lock_bh(&ar_pci->ce_lock);
 
+       nentries_mask = src_ring->nentries_mask;
+       sw_index = src_ring->sw_index;
+       write_index = src_ring->write_index;
+
        if (unlikely(CE_RING_DELTA(nentries_mask,
                                   write_index, sw_index - 1) < n_items)) {
                err = -ENOBUFS;