Author: jfv
Date: Fri Apr 10 00:05:46 2009
New Revision: 190872
URL: http://svn.freebsd.org/changeset/base/190872

Log:
  This delta syncs the em and igb drivers with Intel,
  adds header split and SCTP support into the igb driver.
  Various small improvements and fixes.
  
  MFC after: 2 weeks

Modified:
  head/sys/dev/e1000/e1000_80003es2lan.c
  head/sys/dev/e1000/e1000_82540.c
  head/sys/dev/e1000/e1000_82541.c
  head/sys/dev/e1000/e1000_82571.c
  head/sys/dev/e1000/e1000_82575.c
  head/sys/dev/e1000/e1000_82575.h
  head/sys/dev/e1000/e1000_api.c
  head/sys/dev/e1000/e1000_api.h
  head/sys/dev/e1000/e1000_defines.h
  head/sys/dev/e1000/e1000_hw.h
  head/sys/dev/e1000/e1000_ich8lan.c
  head/sys/dev/e1000/e1000_ich8lan.h
  head/sys/dev/e1000/e1000_mac.c
  head/sys/dev/e1000/e1000_mac.h
  head/sys/dev/e1000/e1000_nvm.c
  head/sys/dev/e1000/e1000_nvm.h
  head/sys/dev/e1000/e1000_phy.c
  head/sys/dev/e1000/e1000_phy.h
  head/sys/dev/e1000/e1000_regs.h
  head/sys/dev/e1000/if_em.c
  head/sys/dev/e1000/if_igb.c
  head/sys/dev/e1000/if_igb.h

Modified: head/sys/dev/e1000/e1000_80003es2lan.c
==============================================================================
--- head/sys/dev/e1000/e1000_80003es2lan.c      Thu Apr  9 20:57:35 2009        
(r190871)
+++ head/sys/dev/e1000/e1000_80003es2lan.c      Fri Apr 10 00:05:46 2009        
(r190872)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2008, Intel Corporation 
+  Copyright (c) 2001-2009, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -43,9 +43,7 @@ static s32  e1000_init_phy_params_80003e
 static s32  e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw);
 static s32  e1000_init_mac_params_80003es2lan(struct e1000_hw *hw);
 static s32  e1000_acquire_phy_80003es2lan(struct e1000_hw *hw);
-static s32  e1000_acquire_mac_csr_80003es2lan(struct e1000_hw *hw);
 static void e1000_release_phy_80003es2lan(struct e1000_hw *hw);
-static void e1000_release_mac_csr_80003es2lan(struct e1000_hw *hw);
 static s32  e1000_acquire_nvm_80003es2lan(struct e1000_hw *hw);
 static void e1000_release_nvm_80003es2lan(struct e1000_hw *hw);
 static s32  e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
@@ -276,6 +274,8 @@ static s32 e1000_init_mac_params_80003es
        mac->ops.mta_set = e1000_mta_set_generic;
        /* read mac address */
        mac->ops.read_mac_addr = e1000_read_mac_addr_80003es2lan;
+       /* ID LED init */
+       mac->ops.id_led_init = e1000_id_led_init_generic;
        /* blink LED */
        mac->ops.blink_led = e1000_blink_led_generic;
        /* setup LED */
@@ -802,17 +802,16 @@ static s32 e1000_get_cable_length_80003e
 
        index = phy_data & GG82563_DSPD_CABLE_LENGTH;
 
-       if (index < GG82563_CABLE_LENGTH_TABLE_SIZE + 5) {
-               phy->min_cable_length = e1000_gg82563_cable_length_table[index];
-               phy->max_cable_length =
-                                e1000_gg82563_cable_length_table[index+5];
-
-               phy->cable_length = (phy->min_cable_length +
-                                    phy->max_cable_length) / 2;
-       } else {
+       if (index >= GG82563_CABLE_LENGTH_TABLE_SIZE + 5) {
                ret_val = E1000_ERR_PHY;
+               goto out;
        }
 
+       phy->min_cable_length = e1000_gg82563_cable_length_table[index];
+       phy->max_cable_length = e1000_gg82563_cable_length_table[index+5];
+
+       phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
+
 out:
        return ret_val;
 }
@@ -892,7 +891,7 @@ static s32 e1000_reset_hw_80003es2lan(st
        E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
        icr = E1000_READ_REG(hw, E1000_ICR);
 
-       e1000_check_alt_mac_addr_generic(hw);
+       ret_val = e1000_check_alt_mac_addr_generic(hw);
 
 out:
        return ret_val;
@@ -916,7 +915,7 @@ static s32 e1000_init_hw_80003es2lan(str
        e1000_initialize_hw_bits_80003es2lan(hw);
 
        /* Initialize identification LED */
-       ret_val = e1000_id_led_init_generic(hw);
+       ret_val = mac->ops.id_led_init(hw);
        if (ret_val) {
                DEBUGOUT("Error initializing identification LED\n");
                /* This is not fatal and we should not stop init due to this */
@@ -1104,9 +1103,9 @@ static s32 e1000_copper_link_setup_gg825
 
        /* Bypass Rx and Tx FIFO's */
        ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
-                               E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL,
-                               E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS |
-                                       E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS);
+                                       E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL,
+                                       E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS |
+                                       E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS);
        if (ret_val)
                goto out;
 
@@ -1147,22 +1146,19 @@ static s32 e1000_copper_link_setup_gg825
        if (!(hw->mac.ops.check_mng_mode(hw))) {
                /* Enable Electrical Idle on the PHY */
                data |= GG82563_PMCR_ENABLE_ELECTRICAL_IDLE;
-               ret_val = hw->phy.ops.write_reg(hw,
-                                               GG82563_PHY_PWR_MGMT_CTRL,
+               ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_PWR_MGMT_CTRL,
                                                data);
                if (ret_val)
                        goto out;
-               ret_val = hw->phy.ops.read_reg(hw,
-                                              GG82563_PHY_KMRN_MODE_CTRL,
-                                              &data);
-                       if (ret_val)
-                               goto out;
+
+               ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
+                                              &data);
+               if (ret_val)
+                       goto out;
 
                data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
-               ret_val = hw->phy.ops.write_reg(hw,
-                                               GG82563_PHY_KMRN_MODE_CTRL,
+               ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
                                                data);
-
                if (ret_val)
                        goto out;
        }
@@ -1261,7 +1257,6 @@ static s32 e1000_cfg_on_link_up_80003es2
        DEBUGFUNC("e1000_configure_on_link_up");
 
        if (hw->phy.media_type == e1000_media_type_copper) {
-
                ret_val = e1000_get_speed_and_duplex_copper_generic(hw,
                                                                    &speed,
                                                                    &duplex);
@@ -1393,7 +1388,8 @@ out:
  *  using the kumeran interface.  The information retrieved is stored in data.
  *  Release the semaphore before exiting.
  **/
-s32 e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, u16 *data)
+static s32 e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
+                                           u16 *data)
 {
        u32 kmrnctrlsta;
        s32 ret_val = E1000_SUCCESS;
@@ -1429,7 +1425,8 @@ out:
  *  at the offset using the kumeran interface.  Release semaphore
  *  before exiting.
  **/
-s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, u16 data)
+static s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
+                                            u16 data)
 {
        u32 kmrnctrlsta;
        s32 ret_val = E1000_SUCCESS;
@@ -1461,9 +1458,19 @@ static s32 e1000_read_mac_addr_80003es2l
        s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_read_mac_addr_80003es2lan");
-       if (e1000_check_alt_mac_addr_generic(hw))
-               ret_val = e1000_read_mac_addr_generic(hw);
 
+       /*
+        * If there's an alternate MAC address place it in RAR0
+        * so that it will override the Si installed default perm
+        * address.
+        */
+       ret_val = e1000_check_alt_mac_addr_generic(hw);
+       if (ret_val)
+               goto out;
+
+       ret_val = e1000_read_mac_addr_generic(hw);
+
+out:
        return ret_val;
 }
 

Modified: head/sys/dev/e1000/e1000_82540.c
==============================================================================
--- head/sys/dev/e1000/e1000_82540.c    Thu Apr  9 20:57:35 2009        
(r190871)
+++ head/sys/dev/e1000/e1000_82540.c    Fri Apr 10 00:05:46 2009        
(r190872)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2008, Intel Corporation 
+  Copyright (c) 2001-2009, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -229,6 +229,8 @@ static s32 e1000_init_mac_params_82540(s
        mac->ops.clear_vfta = e1000_clear_vfta_generic;
        /* setting MTA */
        mac->ops.mta_set = e1000_mta_set_generic;
+       /* ID LED init */
+       mac->ops.id_led_init = e1000_id_led_init_generic;
        /* setup LED */
        mac->ops.setup_led = e1000_setup_led_generic;
        /* cleanup LED */
@@ -332,7 +334,7 @@ static s32 e1000_init_hw_82540(struct e1
        DEBUGFUNC("e1000_init_hw_82540");
 
        /* Initialize identification LED */
-       ret_val = e1000_id_led_init_generic(hw);
+       ret_val = mac->ops.id_led_init(hw);
        if (ret_val) {
                DEBUGOUT("Error initializing identification LED\n");
                /* This is not fatal and we should not stop init due to this */

Modified: head/sys/dev/e1000/e1000_82541.c
==============================================================================
--- head/sys/dev/e1000/e1000_82541.c    Thu Apr  9 20:57:35 2009        
(r190871)
+++ head/sys/dev/e1000/e1000_82541.c    Fri Apr 10 00:05:46 2009        
(r190872)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2008, Intel Corporation 
+  Copyright (c) 2001-2009, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -261,6 +261,8 @@ static s32 e1000_init_mac_params_82541(s
        mac->ops.clear_vfta = e1000_clear_vfta_generic;
        /* setting MTA */
        mac->ops.mta_set = e1000_mta_set_generic;
+       /* ID LED init */
+       mac->ops.id_led_init = e1000_id_led_init_generic;
        /* setup LED */
        mac->ops.setup_led = e1000_setup_led_82541;
        /* cleanup LED */
@@ -381,7 +383,7 @@ static s32 e1000_init_hw_82541(struct e1
        DEBUGFUNC("e1000_init_hw_82541");
 
        /* Initialize identification LED */
-       ret_val = e1000_id_led_init_generic(hw);
+       ret_val = mac->ops.id_led_init(hw);
        if (ret_val) {
                DEBUGOUT("Error initializing identification LED\n");
                /* This is not fatal and we should not stop init due to this */

Modified: head/sys/dev/e1000/e1000_82571.c
==============================================================================
--- head/sys/dev/e1000/e1000_82571.c    Thu Apr  9 20:57:35 2009        
(r190871)
+++ head/sys/dev/e1000/e1000_82571.c    Fri Apr 10 00:05:46 2009        
(r190872)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2008, Intel Corporation 
+  Copyright (c) 2001-2009, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -46,6 +46,7 @@
  * 82573E Gigabit Ethernet Controller (Copper)
  * 82573L Gigabit Ethernet Controller
  * 82574L Gigabit Network Connection
+ * 82574L Gigabit Network Connection
  */
 
 #include "e1000_api.h"
@@ -67,11 +68,9 @@ static s32  e1000_init_hw_82571(struct e
 static void e1000_clear_vfta_82571(struct e1000_hw *hw);
 static bool e1000_check_mng_mode_82574(struct e1000_hw *hw);
 static s32 e1000_led_on_82574(struct e1000_hw *hw);
-static void e1000_update_mc_addr_list_82571(struct e1000_hw *hw,
-                                           u8 *mc_addr_list, u32 mc_addr_count,
-                                           u32 rar_used_count, u32 rar_count);
 static s32  e1000_setup_link_82571(struct e1000_hw *hw);
 static s32  e1000_setup_copper_link_82571(struct e1000_hw *hw);
+static s32  e1000_check_for_serdes_link_82571(struct e1000_hw *hw);
 static s32  e1000_setup_fiber_serdes_link_82571(struct e1000_hw *hw);
 static s32  e1000_valid_led_default_82571(struct e1000_hw *hw, u16 *data);
 static void e1000_clear_hw_cntrs_82571(struct e1000_hw *hw);
@@ -330,7 +329,7 @@ static s32 e1000_init_mac_params_82571(s
                mac->ops.check_for_link = e1000_check_for_fiber_link_generic;
                break;
        case e1000_media_type_internal_serdes:
-               mac->ops.check_for_link = e1000_check_for_serdes_link_generic;
+               mac->ops.check_for_link = e1000_check_for_serdes_link_82571;
                break;
        default:
                ret_val = -E1000_ERR_CONFIG;
@@ -347,7 +346,7 @@ static s32 e1000_init_mac_params_82571(s
                break;
        }
        /* multicast address update */
-       mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_82571;
+       mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic;
        /* writing VFTA */
        mac->ops.write_vfta = e1000_write_vfta_generic;
        /* clearing VFTA */
@@ -356,6 +355,8 @@ static s32 e1000_init_mac_params_82571(s
        mac->ops.mta_set = e1000_mta_set_generic;
        /* read mac address */
        mac->ops.read_mac_addr = e1000_read_mac_addr_82571;
+       /* ID LED init */
+       mac->ops.id_led_init = e1000_id_led_init_generic;
        /* blink LED */
        mac->ops.blink_led = e1000_blink_led_generic;
        /* setup LED */
@@ -528,8 +529,14 @@ static s32 e1000_acquire_nvm_82571(struc
        if (ret_val)
                goto out;
 
-       if (hw->mac.type != e1000_82573 && hw->mac.type != e1000_82574)
+       switch (hw->mac.type) {
+       case e1000_82574:
+       case e1000_82573:
+               break;
+       default:
                ret_val = e1000_acquire_nvm_generic(hw);
+               break;
+       }
 
        if (ret_val)
                e1000_put_hw_semaphore_82571(hw);
@@ -876,7 +883,9 @@ static s32 e1000_reset_hw_82571(struct e
         * Must acquire the MDIO ownership before MAC reset.
         * Ownership defaults to firmware after a reset.
         */
-       if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) {
+       switch (hw->mac.type) {
+       case e1000_82574:
+       case e1000_82573:
                extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL);
                extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
 
@@ -892,6 +901,9 @@ static s32 e1000_reset_hw_82571(struct e
                        msec_delay(2);
                        i++;
                } while (i < MDIO_OWNERSHIP_TIMEOUT);
+               break;
+       default:
+               break;
        }
 
        ctrl = E1000_READ_REG(hw, E1000_CTRL);
@@ -917,15 +929,30 @@ static s32 e1000_reset_hw_82571(struct e
         * Need to wait for Phy configuration completion before accessing
         * NVM and Phy.
         */
-       if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574)
+
+       switch (hw->mac.type) {
+       case e1000_82574:
+       case e1000_82573:
                msec_delay(25);
+               break;
+       default:
+               break;
+       }
 
        /* Clear any pending interrupt events. */
        E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
        icr = E1000_READ_REG(hw, E1000_ICR);
 
-       if (!(e1000_check_alt_mac_addr_generic(hw)))
-               e1000_set_laa_state_82571(hw, TRUE);
+       /* Install any alternate MAC address into RAR0 */
+       ret_val = e1000_check_alt_mac_addr_generic(hw);
+       if (ret_val)
+               goto out;
+
+       e1000_set_laa_state_82571(hw, TRUE);
+
+       /* Reinitialize the 82571 serdes link state machine */
+       if (hw->phy.media_type == e1000_media_type_internal_serdes)
+               hw->mac.serdes_link_state = e1000_serdes_link_down;
 
 out:
        return ret_val;
@@ -949,7 +976,7 @@ static s32 e1000_init_hw_82571(struct e1
        e1000_initialize_hw_bits_82571(hw);
 
        /* Initialize identification LED */
-       ret_val = e1000_id_led_init_generic(hw);
+       ret_val = mac->ops.id_led_init(hw);
        if (ret_val) {
                DEBUGOUT("Error initializing identification LED\n");
                /* This is not fatal and we should not stop init due to this */
@@ -985,17 +1012,21 @@ static s32 e1000_init_hw_82571(struct e1
        E1000_WRITE_REG(hw, E1000_TXDCTL(0), reg_data);
 
        /* ...for both queues. */
-       if (mac->type != e1000_82573 && mac->type != e1000_82574) {
-               reg_data = E1000_READ_REG(hw, E1000_TXDCTL(1));
-               reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
-                          E1000_TXDCTL_FULL_TX_DESC_WB |
-                          E1000_TXDCTL_COUNT_DESC;
-               E1000_WRITE_REG(hw, E1000_TXDCTL(1), reg_data);
-       } else {
+       switch (mac->type) {
+       case e1000_82574:
+       case e1000_82573:
                e1000_enable_tx_pkt_filtering_generic(hw);
                reg_data = E1000_READ_REG(hw, E1000_GCR);
                reg_data |= E1000_GCR_L1_ACT_WITHOUT_L0S_RX;
                E1000_WRITE_REG(hw, E1000_GCR, reg_data);
+               break;
+       default:
+               reg_data = E1000_READ_REG(hw, E1000_TXDCTL(1));
+               reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
+                                       E1000_TXDCTL_FULL_TX_DESC_WB |
+                                       E1000_TXDCTL_COUNT_DESC;
+               E1000_WRITE_REG(hw, E1000_TXDCTL(1), reg_data);
+               break;
        }
 
        /*
@@ -1062,25 +1093,70 @@ static void e1000_initialize_hw_bits_825
        }
 
        /* Device Control */
-       if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) {
+
+       switch (hw->mac.type) {
+       case e1000_82574:
+       case e1000_82573:
                reg = E1000_READ_REG(hw, E1000_CTRL);
                reg &= ~(1 << 29);
                E1000_WRITE_REG(hw, E1000_CTRL, reg);
+               break;
+       default:
+               break;
        }
 
        /* Extended Device Control */
-       if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) {
+       switch (hw->mac.type) {
+       case e1000_82574:
+       case e1000_82573:
                reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
                reg &= ~(1 << 23);
                reg |= (1 << 22);
                E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg);
+               break;
+       default:
+               break;
        }
 
-       /* PCI-Ex Control Register */
-       if (hw->mac.type == e1000_82574) {
+
+       if (hw->mac.type == e1000_82571) {
+               reg = E1000_READ_REG(hw, E1000_PBA_ECC);
+               reg |= E1000_PBA_ECC_CORR_EN;
+               E1000_WRITE_REG(hw, E1000_PBA_ECC, reg);
+       }
+
+       /*
+        * Workaround for hardware errata.
+        * Ensure that DMA Dynamic Clock gating is disabled on 82571 and 82572
+        */
+
+       if ((hw->mac.type == e1000_82571) ||
+          (hw->mac.type == e1000_82572)) {
+               reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
+               reg &= ~E1000_CTRL_EXT_DMA_DYN_CLK_EN;
+               E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg);
+       }
+
+       /* PCI-Ex Control Registers */
+
+       switch (hw->mac.type) {
+       case e1000_82574:
                reg = E1000_READ_REG(hw, E1000_GCR);
                reg |= (1 << 22);
                E1000_WRITE_REG(hw, E1000_GCR, reg);
+               /*
+                * Workaround for hardware errata.
+                * apply workaround for hardware errata documented in errata
+                * docs Fixes issue where some error prone or unreliable PCIe
+                * completions are occurring, particularly with ASPM enabled.
+                * Without fix, issue can cause tx timeouts.
+                */
+               reg = E1000_READ_REG(hw, E1000_GCR2);
+               reg |= 1;
+               E1000_WRITE_REG(hw, E1000_GCR2, reg);
+               break;
+       default:
+               break;
        }
 
        return;
@@ -1102,31 +1178,38 @@ static void e1000_clear_vfta_82571(struc
 
        DEBUGFUNC("e1000_clear_vfta_82571");
 
-       if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) {
+       switch (hw->mac.type) {
+       case e1000_82574:
+       case e1000_82573:
                if (hw->mng_cookie.vlan_id != 0) {
                        /*
-                        * The VFTA is a 4096b bit-field, each identifying
-                        * a single VLAN ID.  The following operations
-                        * determine which 32b entry (i.e. offset) into the
-                        * array we want to set the VLAN ID (i.e. bit) of
-                        * the manageability unit.
-                        */
+                       *The VFTA is a 4096b bit-field, each identifying
+                       *a single VLAN ID.  The following operations
+                       *determine which 32b entry (i.e. offset) into the
+                       *array we want to set the VLAN ID (i.e. bit) of
+                       *the manageability unit.
+                       */
                        vfta_offset = (hw->mng_cookie.vlan_id >>
-                                      E1000_VFTA_ENTRY_SHIFT) &
-                                     E1000_VFTA_ENTRY_MASK;
+                               E1000_VFTA_ENTRY_SHIFT) & E1000_VFTA_ENTRY_MASK;
                        vfta_bit_in_reg = 1 << (hw->mng_cookie.vlan_id &
-                                              E1000_VFTA_ENTRY_BIT_SHIFT_MASK);
+                               E1000_VFTA_ENTRY_BIT_SHIFT_MASK);
                }
-       }
-       for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) {
-               /*
-                * If the offset we want to clear is the same offset of the
-                * manageability VLAN ID, then clear all bits except that of
-                * the manageability unit.
-                */
-               vfta_value = (offset == vfta_offset) ? vfta_bit_in_reg : 0;
-               E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, vfta_value);
-               E1000_WRITE_FLUSH(hw);
+
+               for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) 
{
+                       /*
+                       *If the offset we want to clear is the same offset of
+                       *the manageability VLAN ID, then clear all bits except
+                       *that of the manageability unit
+                       */
+                       vfta_value = (offset == vfta_offset) ?
+                                                       vfta_bit_in_reg : 0;
+                       E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset,
+                               vfta_value);
+                       E1000_WRITE_FLUSH(hw);
+               }
+               break;
+       default:
+               break;
        }
 }
 
@@ -1176,31 +1259,6 @@ static s32 e1000_led_on_82574(struct e10
        return E1000_SUCCESS;
 }
 
-/**
- *  e1000_update_mc_addr_list_82571 - Update Multicast addresses
- *  @hw: pointer to the HW structure
- *  @mc_addr_list: array of multicast addresses to program
- *  @mc_addr_count: number of multicast addresses to program
- *  @rar_used_count: the first RAR register free to program
- *  @rar_count: total number of supported Receive Address Registers
- *
- *  Updates the Receive Address Registers and Multicast Table Array.
- *  The caller must have a packed mc_addr_list of multicast addresses.
- *  The parameter rar_count will usually be hw->mac.rar_entry_count
- *  unless there are workarounds that change this.
- **/
-static void e1000_update_mc_addr_list_82571(struct e1000_hw *hw,
-                                           u8 *mc_addr_list, u32 mc_addr_count,
-                                           u32 rar_used_count, u32 rar_count)
-{
-       DEBUGFUNC("e1000_update_mc_addr_list_82571");
-
-       if (e1000_get_laa_state_82571(hw))
-               rar_count--;
-
-       e1000_update_mc_addr_list_generic(hw, mc_addr_list, mc_addr_count,
-                                         rar_used_count, rar_count);
-}
 
 /**
  *  e1000_setup_link_82571 - Setup flow control and link settings
@@ -1221,10 +1279,15 @@ static s32 e1000_setup_link_82571(struct
         * the default flow control setting, so we explicitly
         * set it to full.
         */
-       if ((hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) &&
-           hw->fc.requested_mode == e1000_fc_default)
-               hw->fc.requested_mode = e1000_fc_full;
-
+       switch (hw->mac.type) {
+       case e1000_82574:
+       case e1000_82573:
+               if (hw->fc.requested_mode == e1000_fc_default)
+                       hw->fc.requested_mode = e1000_fc_full;
+               break;
+       default:
+               break;
+       }
        return e1000_setup_link_generic(hw);
 }
 
@@ -1306,6 +1369,133 @@ static s32 e1000_setup_fiber_serdes_link
 }
 
 /**
+ *  e1000_check_for_serdes_link_82571 - Check for link (Serdes)
+ *  @hw: pointer to the HW structure
+ *
+ *  Checks for link up on the hardware.  If link is not up and we have
+ *  a signal, then we need to force link up.
+ **/
+s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
+{
+       struct e1000_mac_info *mac = &hw->mac;
+       u32 rxcw;
+       u32 ctrl;
+       u32 status;
+       s32 ret_val = E1000_SUCCESS;
+
+       DEBUGFUNC("e1000_check_for_serdes_link_82571");
+
+       ctrl = E1000_READ_REG(hw, E1000_CTRL);
+       status = E1000_READ_REG(hw, E1000_STATUS);
+       rxcw = E1000_READ_REG(hw, E1000_RXCW);
+
+       if ((rxcw & E1000_RXCW_SYNCH) && !(rxcw & E1000_RXCW_IV)) {
+
+               /* Receiver is synchronized with no invalid bits.  */
+               switch (mac->serdes_link_state) {
+               case e1000_serdes_link_autoneg_complete:
+                       if (!(status & E1000_STATUS_LU)) {
+                               /*
+                                * We have lost link, retry autoneg before
+                                * reporting link failure
+                                */
+                               mac->serdes_link_state =
+                                   e1000_serdes_link_autoneg_progress;
+                               DEBUGOUT("AN_UP     -> AN_PROG\n");
+                       }
+               break;
+
+               case e1000_serdes_link_forced_up:
+                       /*
+                        * If we are receiving /C/ ordered sets, re-enable
+                        * auto-negotiation in the TXCW register and disable
+                        * forced link in the Device Control register in an
+                        * attempt to auto-negotiate with our link partner.
+                        */
+                       if (rxcw & E1000_RXCW_C) {
+                               /* Enable autoneg, and unforce link up */
+                               E1000_WRITE_REG(hw, E1000_TXCW, mac->txcw);
+                               E1000_WRITE_REG(hw, E1000_CTRL,
+                                   (ctrl & ~E1000_CTRL_SLU));
+                               mac->serdes_link_state =
+                                   e1000_serdes_link_autoneg_progress;
+                               DEBUGOUT("FORCED_UP -> AN_PROG\n");
+                       }
+                       break;
+
+               case e1000_serdes_link_autoneg_progress:
+                       /*
+                        * If the LU bit is set in the STATUS register,
+                        * autoneg has completed sucessfully. If not,
+                        * try foring the link because the far end may be
+                        * available but not capable of autonegotiation.
+                        */
+                       if (status & E1000_STATUS_LU)  {
+                               mac->serdes_link_state =
+                                   e1000_serdes_link_autoneg_complete;
+                               DEBUGOUT("AN_PROG   -> AN_UP\n");
+                       } else {
+                               /*
+                                * Disable autoneg, force link up and
+                                * full duplex, and change state to forced
+                                */
+                               E1000_WRITE_REG(hw, E1000_TXCW,
+                                   (mac->txcw & ~E1000_TXCW_ANE));
+                               ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD);
+                               E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
+
+                               /* Configure Flow Control after link up. */
+                               ret_val =
+                                   e1000_config_fc_after_link_up_generic(hw);
+                               if (ret_val) {
+                                       DEBUGOUT("Error config flow control\n");
+                                       break;
+                               }
+                               mac->serdes_link_state =
+                                   e1000_serdes_link_forced_up;
+                               DEBUGOUT("AN_PROG   -> FORCED_UP\n");
+                       }
+                       mac->serdes_has_link = TRUE;
+                       break;
+
+               case e1000_serdes_link_down:
+               default:
+                       /* The link was down but the receiver has now gained
+                        * valid sync, so lets see if we can bring the link
+                        * up. */
+                       E1000_WRITE_REG(hw, E1000_TXCW, mac->txcw);
+                       E1000_WRITE_REG(hw, E1000_CTRL,
+                           (ctrl & ~E1000_CTRL_SLU));
+                       mac->serdes_link_state =
+                           e1000_serdes_link_autoneg_progress;
+                       DEBUGOUT("DOWN      -> AN_PROG\n");
+                       break;
+               }
+       } else {
+               if (!(rxcw & E1000_RXCW_SYNCH)) {
+                       mac->serdes_has_link = FALSE;
+                       mac->serdes_link_state = e1000_serdes_link_down;
+                       DEBUGOUT("ANYSTATE  -> DOWN\n");
+               } else {
+                       /*
+                        * We have sync, and can tolerate one
+                        * invalid (IV) codeword before declaring
+                        * link down, so reread to look again
+                        */
+                       usec_delay(10);
+                       rxcw = E1000_READ_REG(hw, E1000_RXCW);
+                       if (rxcw & E1000_RXCW_IV) {
+                               mac->serdes_link_state = e1000_serdes_link_down;
+                               mac->serdes_has_link = FALSE;
+                               DEBUGOUT("ANYSTATE  -> DOWN\n");
+                       }
+               }
+       }
+
+       return ret_val;
+}
+
+/**
  *  e1000_valid_led_default_82571 - Verify a valid default LED config
  *  @hw: pointer to the HW structure
  *  @data: pointer to the NVM (EEPROM)
@@ -1325,11 +1515,19 @@ static s32 e1000_valid_led_default_82571
                goto out;
        }
 
-       if ((hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) &&
-           *data == ID_LED_RESERVED_F746)
-               *data = ID_LED_DEFAULT_82573;
-       else if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF)
-               *data = ID_LED_DEFAULT;
+       switch (hw->mac.type) {
+       case e1000_82574:
+       case e1000_82573:
+               if(*data == ID_LED_RESERVED_F746)
+                       *data = ID_LED_DEFAULT_82573;
+               break;
+       default:
+               if (*data == ID_LED_RESERVED_0000 ||
+                       *data == ID_LED_RESERVED_FFFF)
+                       *data = ID_LED_DEFAULT;
+               break;
+       }
+
 out:
        return ret_val;
 }
@@ -1435,6 +1633,7 @@ out:
        return ret_val;
 }
 
+
 /**
  *  e1000_read_mac_addr_82571 - Read device MAC address
  *  @hw: pointer to the HW structure
@@ -1444,9 +1643,19 @@ static s32 e1000_read_mac_addr_82571(str
        s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_read_mac_addr_82571");
-       if (e1000_check_alt_mac_addr_generic(hw))
-               ret_val = e1000_read_mac_addr_generic(hw);
 
+       /*
+        * If there's an alternate MAC address place it in RAR0
+        * so that it will override the Si installed default perm
+        * address.
+        */
+       ret_val = e1000_check_alt_mac_addr_generic(hw);
+       if (ret_val)
+               goto out;
+
+       ret_val = e1000_read_mac_addr_generic(hw);
+
+out:
        return ret_val;
 }
 

Modified: head/sys/dev/e1000/e1000_82575.c
==============================================================================
--- head/sys/dev/e1000/e1000_82575.c    Thu Apr  9 20:57:35 2009        
(r190871)
+++ head/sys/dev/e1000/e1000_82575.c    Fri Apr 10 00:05:46 2009        
(r190872)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2008, Intel Corporation 
+  Copyright (c) 2001-2009, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -36,6 +36,7 @@
  * 82575EB Gigabit Network Connection
  * 82575EB Gigabit Backplane Connection
  * 82575GB Gigabit Network Connection
+ * 82575GB Gigabit Network Connection
  * 82576 Gigabit Network Connection
  */
 
@@ -75,11 +76,6 @@ static bool e1000_sgmii_active_82575(str
 static s32  e1000_reset_init_script_82575(struct e1000_hw *hw);
 static s32  e1000_read_mac_addr_82575(struct e1000_hw *hw);
 static void e1000_power_down_phy_copper_82575(struct e1000_hw *hw);
-
-static void e1000_init_rx_addrs_82575(struct e1000_hw *hw, u16 rar_count);
-static void e1000_update_mc_addr_list_82575(struct e1000_hw *hw,
-                                           u8 *mc_addr_list, u32 mc_addr_count,
-                                           u32 rar_used_count, u32 rar_count);
 void e1000_shutdown_fiber_serdes_link_82575(struct e1000_hw *hw);
 
 /**
@@ -281,13 +277,15 @@ static s32 e1000_init_mac_params_82575(s
        /* read mac address */
        mac->ops.read_mac_addr = e1000_read_mac_addr_82575;
        /* multicast address update */
-       mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_82575;
+       mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic;
        /* writing VFTA */
        mac->ops.write_vfta = e1000_write_vfta_generic;
        /* clearing VFTA */
        mac->ops.clear_vfta = e1000_clear_vfta_generic;
        /* setting MTA */
        mac->ops.mta_set = e1000_mta_set_generic;
+       /* ID LED init */
+       mac->ops.id_led_init = e1000_id_led_init_generic;
        /* blink LED */
        mac->ops.blink_led = e1000_blink_led_generic;
        /* setup LED */
@@ -854,11 +852,18 @@ static s32 e1000_check_for_link_82575(st
 
        /* SGMII link check is done through the PCS register. */
        if ((hw->phy.media_type != e1000_media_type_copper) ||
-           (e1000_sgmii_active_82575(hw)))
+           (e1000_sgmii_active_82575(hw))) {
                ret_val = e1000_get_pcs_speed_and_duplex_82575(hw, &speed,
                                                               &duplex);
-       else
+               /*
+                * Use this flag to determine if link needs to be checked or
+                * not.  If we have link clear the flag so that we do not
+                * continue to check for link.
+                */
+               hw->mac.get_link_status = !hw->mac.serdes_has_link;
+       } else {
                ret_val = e1000_check_for_copper_link_generic(hw);
+       }
 
        return ret_val;
 }
@@ -921,101 +926,6 @@ static s32 e1000_get_pcs_speed_and_duple
 }
 
 /**
- *  e1000_init_rx_addrs_82575 - Initialize receive address's
- *  @hw: pointer to the HW structure
- *  @rar_count: receive address registers
- *
- *  Setups the receive address registers by setting the base receive address
- *  register to the devices MAC address and clearing all the other receive
- *  address registers to 0.
- **/
-static void e1000_init_rx_addrs_82575(struct e1000_hw *hw, u16 rar_count)
-{
-       u32 i;
-       u8 addr[6] = {0,0,0,0,0,0};
-       /*
-        * This function is essentially the same as that of
-        * e1000_init_rx_addrs_generic. However it also takes care
-        * of the special case where the register offset of the
-        * second set of RARs begins elsewhere. This is implicitly taken care by
-        * function e1000_rar_set_generic.
-        */
-
-       DEBUGFUNC("e1000_init_rx_addrs_82575");
-
-       /* Setup the receive address */
-       DEBUGOUT("Programming MAC Address into RAR[0]\n");
-       hw->mac.ops.rar_set(hw, hw->mac.addr, 0);
-
-       /* Zero out the other (rar_entry_count - 1) receive addresses */
-       DEBUGOUT1("Clearing RAR[1-%u]\n", rar_count-1);
-       for (i = 1; i < rar_count; i++) {
-           hw->mac.ops.rar_set(hw, addr, i);
-       }
-}
-
-/**
- *  e1000_update_mc_addr_list_82575 - Update Multicast addresses
- *  @hw: pointer to the HW structure
- *  @mc_addr_list: array of multicast addresses to program
- *  @mc_addr_count: number of multicast addresses to program
- *  @rar_used_count: the first RAR register free to program
- *  @rar_count: total number of supported Receive Address Registers
- *
- *  Updates the Receive Address Registers and Multicast Table Array.
- *  The caller must have a packed mc_addr_list of multicast addresses.
- *  The parameter rar_count will usually be hw->mac.rar_entry_count
- *  unless there are workarounds that change this.
- **/
-static void e1000_update_mc_addr_list_82575(struct e1000_hw *hw,
-                                     u8 *mc_addr_list, u32 mc_addr_count,
-                                     u32 rar_used_count, u32 rar_count)
-{
-       u32 hash_value;
-       u32 i;
-       u8 addr[6] = {0,0,0,0,0,0};
-       /*
-        * This function is essentially the same as that of 
-        * e1000_update_mc_addr_list_generic. However it also takes care 
-        * of the special case where the register offset of the 
-        * second set of RARs begins elsewhere. This is implicitly taken care 
by 
-        * function e1000_rar_set_generic.
-        */
-
-       DEBUGFUNC("e1000_update_mc_addr_list_82575");
-
-       /*
-        * Load the first set of multicast addresses into the exact
-        * filters (RAR).  If there are not enough to fill the RAR
-        * array, clear the filters.
-        */
-       for (i = rar_used_count; i < rar_count; i++) {
-               if (mc_addr_count) {
-                       e1000_rar_set_generic(hw, mc_addr_list, i);
-                       mc_addr_count--;
-                       mc_addr_list += ETH_ADDR_LEN;
-               } else {
-                       e1000_rar_set_generic(hw, addr, i);
-               }
-       }
-
-       /* Clear the old settings from the MTA */
-       DEBUGOUT("Clearing MTA\n");
-       for (i = 0; i < hw->mac.mta_reg_count; i++) {
-               E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
-               E1000_WRITE_FLUSH(hw);
-       }
-
-       /* Load any remaining multicast addresses into the hash table. */
-       for (; mc_addr_count > 0; mc_addr_count--) {
-               hash_value = e1000_hash_mc_addr(hw, mc_addr_list);
-               DEBUGOUT1("Hash value = 0x%03X\n", hash_value);
-               hw->mac.ops.mta_set(hw, hash_value);
-               mc_addr_list += ETH_ADDR_LEN;
-       }
-}
-
-/**
  *  e1000_shutdown_fiber_serdes_link_82575 - Remove link during power down
  *  @hw: pointer to the HW structure
  *
@@ -1060,6 +970,253 @@ void e1000_shutdown_fiber_serdes_link_82
 }
 
 /**
+ *  e1000_vmdq_loopback_enable_pf- Enables VM to VM queue loopback replication
+ *  @hw: pointer to the HW structure
+ **/
+void e1000_vmdq_loopback_enable_pf(struct e1000_hw *hw)
+{
+       u32 reg;
+
+       reg = E1000_READ_REG(hw, E1000_DTXSWC);
+       reg |= E1000_DTXSWC_VMDQ_LOOPBACK_EN;
+       E1000_WRITE_REG(hw, E1000_DTXSWC, reg);
+}
+
+/**
+ *  e1000_vmdq_loopback_disable_pf - Disable VM to VM queue loopbk replication
+ *  @hw: pointer to the HW structure
+ **/
+void e1000_vmdq_loopback_disable_pf(struct e1000_hw *hw)
+{
+       u32 reg;
+
+       reg = E1000_READ_REG(hw, E1000_DTXSWC);
+       reg &= ~(E1000_DTXSWC_VMDQ_LOOPBACK_EN);
+       E1000_WRITE_REG(hw, E1000_DTXSWC, reg);
+}
+
+/**
+ *  e1000_vmdq_replication_enable_pf - Enable replication of brdcst & multicst
+ *  @hw: pointer to the HW structure
+ *
+ *  Enables replication of broadcast and multicast packets from the network
+ *  to VM's which have their respective broadcast and multicast accept
+ *  bits set in the VM Offload Register.  This gives the PF driver per
+ *  VM granularity control over which VM's get replicated broadcast traffic.
+ **/
+void e1000_vmdq_replication_enable_pf(struct e1000_hw *hw, u32 enables)
+{
+       u32 reg;
+       u32 i;
+
+       for (i = 0; i < MAX_NUM_VFS; i++) {
+               if (enables & (1 << i)) {
+                       reg = E1000_READ_REG(hw, E1000_VMOLR(i));
+                       reg |= (E1000_VMOLR_AUPE |
+                               E1000_VMOLR_BAM |
+                               E1000_VMOLR_MPME);
+                       E1000_WRITE_REG(hw, E1000_VMOLR(i), reg);
+               }
+       }
+
+       reg = E1000_READ_REG(hw, E1000_VT_CTL);
+       reg |= E1000_VT_CTL_VM_REPL_EN;
+       E1000_WRITE_REG(hw, E1000_VT_CTL, reg);
+}
+
+/**
+ *  e1000_vmdq_replication_disable_pf - Disable replication of brdcst & 
multicst
+ *  @hw: pointer to the HW structure
+ *
+ *  Disables replication of broadcast and multicast packets to the VM's.
+ **/
+void e1000_vmdq_replication_disable_pf(struct e1000_hw *hw)
+{
+       u32 reg;

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to