aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/intel/e1000/e1000_main.c
diff options
context:
space:
mode:
authorDmitriy Vyukov <dvyukov@google.com>2015-09-08 10:52:44 +0200
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2015-12-12 23:09:48 -0800
commit9eab46b7cb8d0b0dcf014bf7b25e0e72b9e4d929 (patch)
tree33d44739cb702dddf3d371285c3ff4b24f134c7e /drivers/net/ethernet/intel/e1000/e1000_main.c
parentigb: add 88E1543 initialization code (diff)
downloadlinux-dev-9eab46b7cb8d0b0dcf014bf7b25e0e72b9e4d929.tar.xz
linux-dev-9eab46b7cb8d0b0dcf014bf7b25e0e72b9e4d929.zip
e1000: fix data race between tx_ring->next_to_clean
e1000_clean_tx_irq cleans buffers and sets tx_ring->next_to_clean, then e1000_xmit_frame reuses the cleaned buffers. But there are no memory barriers when buffers gets recycled, so the recycled buffers can be corrupted. Use smp_store_release to update tx_ring->next_to_clean and smp_load_acquire to read tx_ring->next_to_clean to properly hand off buffers from e1000_clean_tx_irq to e1000_xmit_frame. The data race was found with KernelThreadSanitizer (KTSAN). Signed-off-by: Dmitry Vyukov <dvyukov@google.com> Tested-by: Aaron Brown <aaron.f.brown@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to '')
-rw-r--r--drivers/net/ethernet/intel/e1000/e1000_main.c5
1 files changed, 4 insertions, 1 deletions
diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
index fd7be860c201..068023595d84 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -3876,7 +3876,10 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
eop_desc = E1000_TX_DESC(*tx_ring, eop);
}
- tx_ring->next_to_clean = i;
+ /* Synchronize with E1000_DESC_UNUSED called from e1000_xmit_frame,
+ * which will reuse the cleaned buffers.
+ */
+ smp_store_release(&tx_ring->next_to_clean, i);
netdev_completed_queue(netdev, pkts_compl, bytes_compl);