When configuring the rx part of the interface, the e1000_main.c module
enables receive on the adapter before it has initialised the buffer
addresses. The resulting race with the arrival of the first packet can lead
to the adapter and the driver having different ideas about where the next
packet is meant to go, resulting in the failure of the network to function.
In practice, the window is narrow, and this may rarely if ever cause
problems with real hardware. However VirtualBox is capable of delivering a
packet from the virtual adapter is soon as receive is enabled, and this
does indeed cause the network to fail to work. The situation arises if
there are broadcast packets in the host network near the time when receive
is enabled.
I propose the following patch to address the condition. It moves the task
of initialising the buffers (done in two places) to the e1000_configure_rx
function where it can be done before received is enabled. I have confirmed
that this corrects the problem with VirtualBox, but I do not have the
required hardware to test it in a non-virtualised environment.
--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -389,7 +389,6 @@ static void e1000_release_manageability(struct
e1000_adapter *adapter)
static void e1000_configure(struct e1000_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
- int i;
e1000_set_rx_mode(netdev);
@@ -399,15 +398,6 @@ static void e1000_configure(struct e1000_adapter *adapter)
e1000_configure_tx(adapter);
e1000_setup_rctl(adapter);
e1000_configure_rx(adapter);
- /* call E1000_DESC_UNUSED which always leaves
- * at least 1 descriptor unused to make sure
- * next_to_use != next_to_clean
- */
- for (i = 0; i < adapter->num_rx_queues; i++) {
- struct e1000_rx_ring *ring = &adapter->rx_ring[i];
- adapter->alloc_rx_buf(adapter, ring,
- E1000_DESC_UNUSED(ring));
- }
}
int e1000_up(struct e1000_adapter *adapter)
@@ -1860,6 +1850,7 @@ static void e1000_configure_rx(struct e1000_adapter
*adapter)
u64 rdba;
struct e1000_hw *hw = &adapter->hw;
u32 rdlen, rctl, rxcsum;
+ int i;
if (adapter->netdev->mtu > ETH_DATA_LEN) {
rdlen = adapter->rx_ring[0].count *
@@ -1916,6 +1907,16 @@ static void e1000_configure_rx(struct e1000_adapter
*adapter)
ew32(RXCSUM, rxcsum);
}
+ /* call E1000_DESC_UNUSED which always leaves
+ * at least 1 descriptor unused to make sure
+ * next_to_use != next_to_clean
+ */
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ struct e1000_rx_ring *ring = &adapter->rx_ring[i];
+ adapter->alloc_rx_buf(adapter, ring,
+ E1000_DESC_UNUSED(ring));
+ }
+
/* Enable Receives */
ew32(RCTL, rctl | E1000_RCTL_EN);
}
@@ -2187,10 +2188,7 @@ static void e1000_leave_82542_rst(struct
e1000_adapter *adapter)
e1000_pci_set_mwi(hw);
if (netif_running(netdev)) {
- /* No need to loop, because 82542 supports only 1 queue */
- struct e1000_rx_ring *ring = &adapter->rx_ring[0];
e1000_configure_rx(adapter);
- adapter->alloc_rx_buf(adapter, ring, E1000_DESC_UNUSED(ring));
}
}
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
E1000-devel mailing list
E1000-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/e1000-devel
To learn more about Intel® Ethernet, visit
http://communities.intel.com/community/wired