Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

r8169: fix Rx index race between FIFO overflow recovery and NAPI handler.

Since 92fc43b4159b518f5baae57301f26d770b0834c9, rtl8169_tx_timeout ends up
resetting Rx and Tx indexes and thus racing with the NAPI handler via
-> rtl8169_hw_reset
-> rtl_hw_reset
-> rtl8169_init_ring_indexes

What about returning to the original state ?

rtl_hw_reset is only used by rtl8169_hw_reset and rtl8169_init_one.

The latter does not need rtl8169_init_ring_indexes because the indexes
still contain their original values from the newly allocated network
device private data area (i.e. 0).

rtl8169_hw_reset is used by:
1. rtl8169_down
Helper for rtl8169_close. rtl8169_open explicitely inits the indexes
anyway.
2. rtl8169_pcierr_interrupt
Indexes are set by rtl8169_reinit_task.
3. rtl8169_interrupt
rtl8169_hw_reset is needed when the device goes down. See 1.
4. rtl_shutdown
System shutdown handler. Indexes are irrelevant.
5. rtl8169_reset_task
Indexes must be set before rtl_hw_start is called.
6. rtl8169_tx_timeout
Indexes should not be set. This is the job of rtl8169_reset_task anyway.

The removal of rtl8169_hw_reset in rtl8169_tx_timeout and its move in
rtl8169_reset_task do not change the analysis.

Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
Cc: hayeswang <hayeswang@realtek.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

françois romieu and committed by
David S. Miller
c7c2c39b 811fd301

+3 -8
+3 -8
drivers/net/ethernet/realtek/r8169.c
··· 3935 3935 break; 3936 3936 udelay(100); 3937 3937 } 3938 - 3939 - rtl8169_init_ring_indexes(tp); 3940 3938 } 3941 3939 3942 3940 static int __devinit ··· 5393 5395 if (!netif_running(dev)) 5394 5396 goto out_unlock; 5395 5397 5398 + rtl8169_hw_reset(tp); 5399 + 5396 5400 rtl8169_wait_for_quiescence(dev); 5397 5401 5398 5402 for (i = 0; i < NUM_RX_DESC; i++) 5399 5403 rtl8169_mark_to_asic(tp->RxDescArray + i, rx_buf_sz); 5400 5404 5401 5405 rtl8169_tx_clear(tp); 5406 + rtl8169_init_ring_indexes(tp); 5402 5407 5403 - rtl8169_hw_reset(tp); 5404 5408 rtl_hw_start(dev); 5405 5409 netif_wake_queue(dev); 5406 5410 rtl8169_check_link_status(dev, tp, tp->mmio_addr); ··· 5413 5413 5414 5414 static void rtl8169_tx_timeout(struct net_device *dev) 5415 5415 { 5416 - struct rtl8169_private *tp = netdev_priv(dev); 5417 - 5418 - rtl8169_hw_reset(tp); 5419 - 5420 - /* Let's wait a bit while any (async) irq lands on */ 5421 5416 rtl8169_schedule_work(dev, rtl8169_reset_task); 5422 5417 } 5423 5418