diff options
Diffstat (limited to 'kernel/drivers/net/ethernet/intel/e1000')
-rw-r--r-- | kernel/drivers/net/ethernet/intel/e1000/e1000.h | 7 | ||||
-rw-r--r-- | kernel/drivers/net/ethernet/intel/e1000/e1000_main.c | 5 |
2 files changed, 9 insertions, 3 deletions
diff --git a/kernel/drivers/net/ethernet/intel/e1000/e1000.h b/kernel/drivers/net/ethernet/intel/e1000/e1000.h index 69707108d..98fe5a2cd 100644 --- a/kernel/drivers/net/ethernet/intel/e1000/e1000.h +++ b/kernel/drivers/net/ethernet/intel/e1000/e1000.h @@ -213,8 +213,11 @@ struct e1000_rx_ring { }; #define E1000_DESC_UNUSED(R) \ - ((((R)->next_to_clean > (R)->next_to_use) \ - ? 0 : (R)->count) + (R)->next_to_clean - (R)->next_to_use - 1) +({ \ + unsigned int clean = smp_load_acquire(&(R)->next_to_clean); \ + unsigned int use = READ_ONCE((R)->next_to_use); \ + (clean > use ? 0 : (R)->count) + clean - use - 1; \ +}) #define E1000_RX_DESC_EXT(R, i) \ (&(((union e1000_rx_desc_extended *)((R).desc))[i])) diff --git a/kernel/drivers/net/ethernet/intel/e1000/e1000_main.c b/kernel/drivers/net/ethernet/intel/e1000/e1000_main.c index fd7be860c..068023595 100644 --- a/kernel/drivers/net/ethernet/intel/e1000/e1000_main.c +++ b/kernel/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); |