]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/commitdiff
e1000: fix flow control thresholds
authorJesse Brandeburg <jesse.brandeburg@intel.com>
Mon, 6 Jul 2009 10:45:01 +0000 (10:45 +0000)
committerDavid S. Miller <davem@davemloft.net>
Tue, 7 Jul 2009 01:07:52 +0000 (18:07 -0700)
when testing the jumbo frames with pages patch, the stats would
show rx_missed errors (dropped packets) even when connected to a
link partner with flow control enabled.

this indicates that for this MTU (9000) the flow control
thresholds are not adjusting correctly.

In fact, before this change, the FCRTH (xoff threshold) is 36864
when the fifo size is only 40000, with 9000 byte MTU.

fix it so that we at least have room for one frame after we send
the xoff.

Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/e1000/e1000_hw.c
drivers/net/e1000/e1000_hw.h
drivers/net/e1000/e1000_main.c

index e1a3fc1303ee9c52d7a3098f1b94e60b230ac210..1e5ae112d57a179e5c71fb8b0d3795c6fcfec9b3 100644 (file)
@@ -1955,7 +1955,7 @@ static s32 e1000_setup_copper_link(struct e1000_hw *hw)
     s32 ret_val;
     u16 i;
     u16 phy_data;
-    u16 reg_data;
+    u16 reg_data = 0;
 
     DEBUGFUNC("e1000_setup_copper_link");
 
index 99fce2c5dd26b21b0b4e6ff7d6a96d10e8e29758..a8866bdbb671b6ffbc3dd1ecd07dafe0550f5419 100644 (file)
@@ -523,11 +523,8 @@ s32 e1000_check_phy_reset_block(struct e1000_hw *hw);
 
 /* The sizes (in bytes) of a ethernet packet */
 #define ENET_HEADER_SIZE             14
-#define MAXIMUM_ETHERNET_FRAME_SIZE  1518 /* With FCS */
 #define MINIMUM_ETHERNET_FRAME_SIZE  64   /* With FCS */
 #define ETHERNET_FCS_SIZE            4
-#define MAXIMUM_ETHERNET_PACKET_SIZE \
-    (MAXIMUM_ETHERNET_FRAME_SIZE - ETHERNET_FCS_SIZE)
 #define MINIMUM_ETHERNET_PACKET_SIZE \
     (MINIMUM_ETHERNET_FRAME_SIZE - ETHERNET_FCS_SIZE)
 #define CRC_LENGTH                   ETHERNET_FCS_SIZE
index f2db9e2069e778d830638b8bc34a2bc232b59c3c..d7df00c2dbd6ea0f97f3819878b1d815c02d6a42 100644 (file)
@@ -641,8 +641,8 @@ void e1000_reset(struct e1000_adapter *adapter)
 {
        struct e1000_hw *hw = &adapter->hw;
        u32 pba = 0, tx_space, min_tx_space, min_rx_space;
-       u16 fc_high_water_mark = E1000_FC_HIGH_DIFF;
        bool legacy_pba_adjust = false;
+       u16 hwm;
 
        /* Repartition Pba for greater than 9k mtu
         * To take effect CTRL.RST is required.
@@ -686,7 +686,7 @@ void e1000_reset(struct e1000_adapter *adapter)
        }
 
        if (legacy_pba_adjust) {
-               if (adapter->netdev->mtu > E1000_RXBUFFER_8192)
+               if (hw->max_frame_size > E1000_RXBUFFER_8192)
                        pba -= 8; /* allocate more FIFO for Tx */
 
                if (hw->mac_type == e1000_82547) {
@@ -696,14 +696,14 @@ void e1000_reset(struct e1000_adapter *adapter)
                                (E1000_PBA_40K - pba) << E1000_PBA_BYTES_SHIFT;
                        atomic_set(&adapter->tx_fifo_stall, 0);
                }
-       } else if (hw->max_frame_size > MAXIMUM_ETHERNET_FRAME_SIZE) {
+       } else if (hw->max_frame_size >  ETH_FRAME_LEN + ETH_FCS_LEN) {
                /* adjust PBA for jumbo frames */
                ew32(PBA, pba);
 
                /* To maintain wire speed transmits, the Tx FIFO should be
-                * large enough to accomodate two full transmit packets,
+                * large enough to accommodate two full transmit packets,
                 * rounded up to the next 1KB and expressed in KB.  Likewise,
-                * the Rx FIFO should be large enough to accomodate at least
+                * the Rx FIFO should be large enough to accommodate at least
                 * one full receive packet and is similarly rounded up and
                 * expressed in KB. */
                pba = er32(PBA);
@@ -711,13 +711,17 @@ void e1000_reset(struct e1000_adapter *adapter)
                tx_space = pba >> 16;
                /* lower 16 bits has Rx packet buffer allocation size in KB */
                pba &= 0xffff;
-               /* don't include ethernet FCS because hardware appends/strips */
-               min_rx_space = adapter->netdev->mtu + ENET_HEADER_SIZE +
-                              VLAN_TAG_SIZE;
-               min_tx_space = min_rx_space;
-               min_tx_space *= 2;
+               /*
+                * the tx fifo also stores 16 bytes of information about the tx
+                * but don't include ethernet FCS because hardware appends it
+                */
+               min_tx_space = (hw->max_frame_size +
+                               sizeof(struct e1000_tx_desc) -
+                               ETH_FCS_LEN) * 2;
                min_tx_space = ALIGN(min_tx_space, 1024);
                min_tx_space >>= 10;
+               /* software strips receive CRC, so leave room for it */
+               min_rx_space = hw->max_frame_size;
                min_rx_space = ALIGN(min_rx_space, 1024);
                min_rx_space >>= 10;
 
@@ -754,19 +758,21 @@ void e1000_reset(struct e1000_adapter *adapter)
 
        ew32(PBA, pba);
 
-       /* flow control settings */
-       /* Set the FC high water mark to 90% of the FIFO size.
-        * Required to clear last 3 LSB */
-       fc_high_water_mark = ((pba * 9216)/10) & 0xFFF8;
-       /* We can't use 90% on small FIFOs because the remainder
-        * would be less than 1 full frame.  In this case, we size
-        * it to allow at least a full frame above the high water
-        *  mark. */
-       if (pba < E1000_PBA_16K)
-               fc_high_water_mark = (pba * 1024) - 1600;
-
-       hw->fc_high_water = fc_high_water_mark;
-       hw->fc_low_water = fc_high_water_mark - 8;
+       /*
+        * flow control settings:
+        * The high water mark must be low enough to fit one full frame
+        * (or the size used for early receive) above it in the Rx FIFO.
+        * Set it to the lower of:
+        * - 90% of the Rx FIFO size, and
+        * - the full Rx FIFO size minus the early receive size (for parts
+        *   with ERT support assuming ERT set to E1000_ERT_2048), or
+        * - the full Rx FIFO size minus one full frame
+        */
+       hwm = min(((pba << 10) * 9 / 10),
+                 ((pba << 10) - hw->max_frame_size));
+
+       hw->fc_high_water = hwm & 0xFFF8;       /* 8-byte granularity */
+       hw->fc_low_water = hw->fc_high_water - 8;
        hw->fc_pause_time = E1000_FC_PAUSE_TIME;
        hw->fc_send_xon = 1;
        hw->fc = hw->original_fc;
@@ -3474,7 +3480,7 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
        switch (hw->mac_type) {
        case e1000_undefined ... e1000_82542_rev2_1:
        case e1000_ich8lan:
-               if (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) {
+               if (max_frame > (ETH_FRAME_LEN + ETH_FCS_LEN)) {
                        DPRINTK(PROBE, ERR, "Jumbo Frames not supported.\n");
                        return -EINVAL;
                }
@@ -3487,7 +3493,7 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
                                  &eeprom_data);
                if ((hw->device_id != E1000_DEV_ID_82573L) ||
                    (eeprom_data & EEPROM_WORD1A_ASPM_MASK)) {
-                       if (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) {
+                       if (max_frame > (ETH_FRAME_LEN + ETH_FCS_LEN)) {
                                DPRINTK(PROBE, ERR,
                                        "Jumbo Frames not supported.\n");
                                return -EINVAL;
@@ -3535,7 +3541,7 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
 
        /* adjust allocation if LPE protects us, and we aren't using SBP */
        if (!hw->tbi_compatibility_on &&
-           ((max_frame == MAXIMUM_ETHERNET_FRAME_SIZE) ||
+           ((max_frame == (ETH_FRAME_LEN + ETH_FCS_LEN)) ||
             (max_frame == MAXIMUM_ETHERNET_VLAN_SIZE)))
                adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;