Commit 3d6114e7 authored by Jesse Brandeburg's avatar Jesse Brandeburg Committed by David S. Miller

e1000: remove races when changing mtu

this patch fixes a bug that occurs when routing packets and simultaneously
changing the mtu.  the rx_buffer_len variable is used during the rx cleanup
and if that changes on the fly without stopping traffic bad things happen
Signed-off-by: default avatarJesse Brandeburg <jesse.brandeburg@intel.com>
Signed-off-by: default avatarDon Skidmore <donald.c.skidmore@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8fce4731
...@@ -3141,6 +3141,13 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu) ...@@ -3141,6 +3141,13 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
break; break;
} }
while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
msleep(1);
/* e1000_down has a dependency on max_frame_size */
hw->max_frame_size = max_frame;
if (netif_running(netdev))
e1000_down(adapter);
/* NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN /* NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN
* means we reserve 2 more, this pushes us to allocate from the next * means we reserve 2 more, this pushes us to allocate from the next
* larger slab size. * larger slab size.
...@@ -3169,11 +3176,16 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu) ...@@ -3169,11 +3176,16 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
(max_frame == MAXIMUM_ETHERNET_VLAN_SIZE))) (max_frame == MAXIMUM_ETHERNET_VLAN_SIZE)))
adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE; adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
printk(KERN_INFO "e1000: %s changing MTU from %d to %d\n",
netdev->name, netdev->mtu, new_mtu);
netdev->mtu = new_mtu; netdev->mtu = new_mtu;
hw->max_frame_size = max_frame;
if (netif_running(netdev)) if (netif_running(netdev))
e1000_reinit_locked(adapter); e1000_up(adapter);
else
e1000_reset(adapter);
clear_bit(__E1000_RESETTING, &adapter->flags);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment