Author: jfv
Date: Sun Jul  8 20:39:00 2012
New Revision: 238263
URL: http://svn.freebsd.org/changeset/base/238263

Log:
  MFC of 238149
  
  Approved by:re

Modified:
  stable/9/sys/dev/ixgbe/ixgbe.c
  stable/9/sys/dev/ixgbe/ixgbe_82598.c
  stable/9/sys/dev/ixgbe/ixgbe_82598.h
  stable/9/sys/dev/ixgbe/ixgbe_82599.c
  stable/9/sys/dev/ixgbe/ixgbe_api.c
  stable/9/sys/dev/ixgbe/ixgbe_api.h
  stable/9/sys/dev/ixgbe/ixgbe_common.c
  stable/9/sys/dev/ixgbe/ixgbe_common.h
  stable/9/sys/dev/ixgbe/ixgbe_osdep.h
  stable/9/sys/dev/ixgbe/ixgbe_phy.c
  stable/9/sys/dev/ixgbe/ixgbe_type.h
  stable/9/sys/dev/ixgbe/ixgbe_vf.c
  stable/9/sys/dev/ixgbe/ixgbe_x540.c
  stable/9/sys/dev/ixgbe/ixv.c
Directory Properties:
  stable/9/sys/   (props changed)
  stable/9/sys/dev/   (props changed)
  stable/9/sys/dev/ixgbe/   (props changed)

Modified: stable/9/sys/dev/ixgbe/ixgbe.c
==============================================================================
--- stable/9/sys/dev/ixgbe/ixgbe.c      Sun Jul  8 20:35:56 2012        
(r238262)
+++ stable/9/sys/dev/ixgbe/ixgbe.c      Sun Jul  8 20:39:00 2012        
(r238263)
@@ -47,7 +47,7 @@ int             ixgbe_display_debug_stat
 /*********************************************************************
  *  Driver version
  *********************************************************************/
-char ixgbe_driver_version[] = "2.4.5";
+char ixgbe_driver_version[] = "2.4.8";
 
 /*********************************************************************
  *  PCI Device ID Table
@@ -80,8 +80,10 @@ static ixgbe_vendor_info_t ixgbe_vendor_
        {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_T3_LOM, 0, 0, 0},
        {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_COMBO_BACKPLANE, 0, 0, 0},
        {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_BACKPLANE_FCOE, 0, 0, 0},
+       {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_SF2, 0, 0, 0},
        {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_FCOE, 0, 0, 0},
        {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599EN_SFP, 0, 0, 0},
+       {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540T1, 0, 0, 0},
        {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540T, 0, 0, 0},
        /* required last entry */
        {0, 0, 0, 0, 0}
@@ -242,10 +244,6 @@ TUNABLE_INT("hw.ixgbe.max_interrupt_rate
 static int ixgbe_rx_process_limit = 128;
 TUNABLE_INT("hw.ixgbe.rx_process_limit", &ixgbe_rx_process_limit);
 
-/* Flow control setting, default to full */
-static int ixgbe_flow_control = ixgbe_fc_full;
-TUNABLE_INT("hw.ixgbe.flow_control", &ixgbe_flow_control);
-
 /*
 ** Smart speed setting, default to on
 ** this only works as a compile option
@@ -526,28 +524,25 @@ ixgbe_attach(device_t dev)
                goto err_late;
        }
 
-       /* Get Hardware Flow Control setting */
-       hw->fc.requested_mode = ixgbe_fc_full;
-       adapter->fc = hw->fc.requested_mode;
-       hw->fc.pause_time = IXGBE_FC_PAUSE;
-       hw->fc.low_water = IXGBE_FC_LO;
-       hw->fc.high_water[0] = IXGBE_FC_HI;
-       hw->fc.send_xon = TRUE;
-
        error = ixgbe_init_hw(hw);
-       if (error == IXGBE_ERR_EEPROM_VERSION) {
+       switch (error) {
+       case IXGBE_ERR_EEPROM_VERSION:
                device_printf(dev, "This device is a pre-production adapter/"
                    "LOM.  Please be aware there may be issues associated "
                    "with your hardware.\n If you are experiencing problems "
                    "please contact your Intel or hardware representative "
                    "who provided you with this hardware.\n");
-       } else if (error == IXGBE_ERR_SFP_NOT_SUPPORTED)
+               break;
+       case IXGBE_ERR_SFP_NOT_SUPPORTED:
                device_printf(dev,"Unsupported SFP+ Module\n");
-
-       if (error) {
                error = EIO;
                device_printf(dev,"Hardware Initialization Failure\n");
                goto err_late;
+       case IXGBE_ERR_SFP_NOT_PRESENT:
+               device_printf(dev,"No SFP+ Module found\n");
+               /* falls thru */
+       default:
+               break;
        }
 
        /* Detect and set physical type */
@@ -1234,7 +1229,7 @@ ixgbe_init_locked(struct adapter *adapte
 #ifdef IXGBE_FDIR
        /* Init Flow director */
        if (hw->mac.type != ixgbe_mac_82598EB) {
-               u32 hdrm = 64 << fdir_pballoc;
+               u32 hdrm = 32 << fdir_pballoc;
 
                hw->mac.ops.setup_rxpba(hw, 0, hdrm, PBA_STRATEGY_EQUAL);
                ixgbe_init_fdir_signature_82599(&adapter->hw, fdir_pballoc);
@@ -1260,6 +1255,35 @@ ixgbe_init_locked(struct adapter *adapte
        /* Config/Enable Link */
        ixgbe_config_link(adapter);
 
+       /* Hardware Packet Buffer & Flow Control setup */
+       {
+               u32 rxpb, frame, size, tmp;
+
+               frame = adapter->max_frame_size;
+
+               /* Calculate High Water */
+               if (hw->mac.type == ixgbe_mac_X540)
+                       tmp = IXGBE_DV_X540(frame, frame);
+               else
+                       tmp = IXGBE_DV(frame, frame);
+               size = IXGBE_BT2KB(tmp);
+               rxpb = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)) >> 10;
+               hw->fc.high_water[0] = rxpb - size;
+
+               /* Now calculate Low Water */
+               if (hw->mac.type == ixgbe_mac_X540)
+                       tmp = IXGBE_LOW_DV_X540(frame);
+               else
+                       tmp = IXGBE_LOW_DV(frame);
+               hw->fc.low_water[0] = IXGBE_BT2KB(tmp);
+               
+               adapter->fc = hw->fc.requested_mode = ixgbe_fc_full;
+               hw->fc.pause_time = IXGBE_FC_PAUSE;
+               hw->fc.send_xon = TRUE;
+       }
+       /* Initialize the FC settings */
+       ixgbe_start_hw(hw);
+
        /* And now turn on interrupts */
        ixgbe_enable_intr(adapter);
 
@@ -1549,10 +1573,8 @@ ixgbe_msix_link(void *arg)
                        /* This is probably overkill :) */
                        if (!atomic_cmpset_int(&adapter->fdir_reinit, 0, 1))
                                return;
-                       /* Clear the interrupt */
-                       IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_FLOW_DIR);
-                       /* Turn off the interface */
-                       adapter->ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+                       /* Disable the interrupt */
+                       IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EICR_FLOW_DIR);
                        taskqueue_enqueue(adapter->tq, &adapter->fdir_task);
                } else
 #endif
@@ -2055,6 +2077,8 @@ ixgbe_update_link_status(struct adapter 
                                    ((adapter->link_speed == 128)? 10:1),
                                    "Full Duplex");
                        adapter->link_active = TRUE;
+                       /* Update any Flow Control changes */
+                       ixgbe_fc_enable(&adapter->hw);
                        if_link_state_change(ifp, LINK_STATE_UP);
                }
        } else { /* Link down */
@@ -3062,7 +3086,7 @@ ixgbe_initialize_transmit_units(struct a
                        txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(i));
                        break;
                 }
-               txctrl &= ~IXGBE_DCA_TXCTRL_TX_WB_RO_EN;
+               txctrl &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN;
                switch (hw->mac.type) {
                case ixgbe_mac_82598EB:
                        IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(i), txctrl);
@@ -5057,6 +5081,8 @@ ixgbe_reinit_fdir(void *context, int pen
                return;
        ixgbe_reinit_fdir_tables_82599(&adapter->hw);
        adapter->fdir_reinit = 0;
+       /* re-enable flow director interrupts */
+       IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, IXGBE_EIMS_FLOW_DIR);
        /* Restart the interface */
        ifp->if_drv_flags |= IFF_DRV_RUNNING;
        return;
@@ -5614,8 +5640,9 @@ ixgbe_set_flowcntl(SYSCTL_HANDLER_ARGS)
                default:
                        adapter->hw.fc.requested_mode = ixgbe_fc_none;
        }
-
-       ixgbe_fc_enable(&adapter->hw, 0);
+       /* Don't autoneg if forcing a value */
+       adapter->hw.fc.disable_fc_autoneg = TRUE;
+       ixgbe_fc_enable(&adapter->hw);
        return error;
 }
 
@@ -5631,9 +5658,9 @@ ixgbe_add_rx_process_limit(struct adapte
 
 /*
 ** Control link advertise speed:
-**     0 - normal
 **     1 - advertise only 1G
 **     2 - advertise 100Mb
+**     3 - advertise normal
 */
 static int
 ixgbe_set_advertise(SYSCTL_HANDLER_ARGS)
@@ -5647,13 +5674,15 @@ ixgbe_set_advertise(SYSCTL_HANDLER_ARGS)
        adapter = (struct adapter *) arg1;
        dev = adapter->dev;
        hw = &adapter->hw;
-       last = hw->phy.autoneg_advertised;
+       last = adapter->advertise;
 
        error = sysctl_handle_int(oidp, &adapter->advertise, 0, req);
-
        if ((error) || (adapter->advertise == -1))
                return (error);
 
+       if (adapter->advertise == last) /* no change */
+               return (0);
+
        if (!((hw->phy.media_type == ixgbe_media_type_copper) ||
             (hw->phy.multispeed_fiber)))
                return (error);
@@ -5667,11 +5696,10 @@ ixgbe_set_advertise(SYSCTL_HANDLER_ARGS)
                 speed = IXGBE_LINK_SPEED_1GB_FULL;
        else if (adapter->advertise == 2)
                 speed = IXGBE_LINK_SPEED_100_FULL;
-       else
+       else if (adapter->advertise == 3)
                 speed = IXGBE_LINK_SPEED_1GB_FULL |
                        IXGBE_LINK_SPEED_10GB_FULL;
-
-       if (speed == last) /* no change */
+       else /* bogus value */
                return (error);
 
        hw->mac.autotry_restart = TRUE;

Modified: stable/9/sys/dev/ixgbe/ixgbe_82598.c
==============================================================================
--- stable/9/sys/dev/ixgbe/ixgbe_82598.c        Sun Jul  8 20:35:56 2012        
(r238262)
+++ stable/9/sys/dev/ixgbe/ixgbe_82598.c        Sun Jul  8 20:39:00 2012        
(r238263)
@@ -104,31 +104,6 @@ out:
 }
 
 /**
- *  ixgbe_get_pcie_msix_count_82598 - Gets MSI-X vector count
- *  @hw: pointer to hardware structure
- *
- *  Read PCIe configuration space, and get the MSI-X vector count from
- *  the capabilities table.
- **/
-u32 ixgbe_get_pcie_msix_count_82598(struct ixgbe_hw *hw)
-{
-       u32 msix_count = 18;
-
-       DEBUGFUNC("ixgbe_get_pcie_msix_count_82598");
-
-       if (hw->mac.msix_vectors_from_pcie) {
-               msix_count = IXGBE_READ_PCIE_WORD(hw,
-                                                 IXGBE_PCIE_MSIX_82598_CAPS);
-               msix_count &= IXGBE_PCIE_MSIX_TBL_SZ_MASK;
-
-               /* MSI-X count is zero-based in HW, so increment to give
-                * proper value */
-               msix_count++;
-       }
-       return msix_count;
-}
-
-/**
  *  ixgbe_init_ops_82598 - Inits func ptrs and MAC type
  *  @hw: pointer to hardware structure
  *
@@ -176,7 +151,7 @@ s32 ixgbe_init_ops_82598(struct ixgbe_hw
        mac->rx_pb_size         = 512;
        mac->max_tx_queues      = 32;
        mac->max_rx_queues      = 64;
-       mac->max_msix_vectors   = ixgbe_get_pcie_msix_count_82598(hw);
+       mac->max_msix_vectors   = ixgbe_get_pcie_msix_count_generic(hw);
 
        /* SFP+ Module */
        phy->ops.read_i2c_eeprom = &ixgbe_read_i2c_eeprom_82598;
@@ -280,15 +255,15 @@ s32 ixgbe_start_hw_82598(struct ixgbe_hw
        for (i = 0; ((i < hw->mac.max_tx_queues) &&
             (i < IXGBE_DCA_MAX_QUEUES_82598)); i++) {
                regval = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(i));
-               regval &= ~IXGBE_DCA_TXCTRL_TX_WB_RO_EN;
+               regval &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN;
                IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(i), regval);
        }
 
        for (i = 0; ((i < hw->mac.max_rx_queues) &&
             (i < IXGBE_DCA_MAX_QUEUES_82598)); i++) {
                regval = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i));
-               regval &= ~(IXGBE_DCA_RXCTRL_DESC_WRO_EN |
-                           IXGBE_DCA_RXCTRL_DESC_HSRO_EN);
+               regval &= ~(IXGBE_DCA_RXCTRL_DATA_WRO_EN |
+                           IXGBE_DCA_RXCTRL_HEAD_WRO_EN);
                IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval);
        }
 
@@ -416,21 +391,41 @@ out:
 /**
  *  ixgbe_fc_enable_82598 - Enable flow control
  *  @hw: pointer to hardware structure
- *  @packetbuf_num: packet buffer number (0-7)
  *
  *  Enable flow control according to the current settings.
  **/
-s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num)
+s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw)
 {
        s32 ret_val = IXGBE_SUCCESS;
        u32 fctrl_reg;
        u32 rmcs_reg;
        u32 reg;
+       u32 fcrtl, fcrth;
        u32 link_speed = 0;
+       int i;
        bool link_up;
 
        DEBUGFUNC("ixgbe_fc_enable_82598");
 
+       /* Validate the water mark configuration */
+       if (!hw->fc.pause_time) {
+               ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
+               goto out;
+       }
+
+       /* Low water mark of zero causes XOFF floods */
+       for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) {
+               if ((hw->fc.current_mode & ixgbe_fc_tx_pause) &&
+                   hw->fc.high_water[i]) {
+                       if (!hw->fc.low_water[i] ||
+                           hw->fc.low_water[i] >= hw->fc.high_water[i]) {
+                               DEBUGOUT("Invalid water mark configuration\n");
+                               ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
+                               goto out;
+                       }
+               }
+       }
+
        /*
         * On 82598 having Rx FC on causes resets while doing 1G
         * so if it's on turn it off once we know link_speed. For
@@ -452,9 +447,7 @@ s32 ixgbe_fc_enable_82598(struct ixgbe_h
        }
 
        /* Negotiate the fc mode to use */
-       ret_val = ixgbe_fc_autoneg(hw);
-       if (ret_val == IXGBE_ERR_FLOW_CONTROL)
-               goto out;
+       ixgbe_fc_autoneg(hw);
 
        /* Disable any previous flow control settings */
        fctrl_reg = IXGBE_READ_REG(hw, IXGBE_FCTRL);
@@ -516,28 +509,27 @@ s32 ixgbe_fc_enable_82598(struct ixgbe_h
        IXGBE_WRITE_REG(hw, IXGBE_RMCS, rmcs_reg);
 
        /* Set up and enable Rx high/low water mark thresholds, enable XON. */
-       if (hw->fc.current_mode & ixgbe_fc_tx_pause) {
-               reg = hw->fc.low_water << 6;
-               if (hw->fc.send_xon)
-                       reg |= IXGBE_FCRTL_XONE;
-
-               IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num), reg);
-
-               reg = hw->fc.high_water[packetbuf_num] << 6;
-               reg |= IXGBE_FCRTH_FCEN;
+       for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) {
+               if ((hw->fc.current_mode & ixgbe_fc_tx_pause) &&
+                   hw->fc.high_water[i]) {
+                       fcrtl = (hw->fc.low_water[i] << 10) | IXGBE_FCRTL_XONE;
+                       fcrth = (hw->fc.high_water[i] << 10) | IXGBE_FCRTH_FCEN;
+                       IXGBE_WRITE_REG(hw, IXGBE_FCRTL(i), fcrtl);
+                       IXGBE_WRITE_REG(hw, IXGBE_FCRTH(i), fcrth);
+               } else {
+                       IXGBE_WRITE_REG(hw, IXGBE_FCRTL(i), 0);
+                       IXGBE_WRITE_REG(hw, IXGBE_FCRTH(i), 0);
+               }
 
-               IXGBE_WRITE_REG(hw, IXGBE_FCRTH(packetbuf_num), reg);
        }
 
        /* Configure pause time (2 TCs per register) */
-       reg = IXGBE_READ_REG(hw, IXGBE_FCTTV(packetbuf_num / 2));
-       if ((packetbuf_num & 1) == 0)
-               reg = (reg & 0xFFFF0000) | hw->fc.pause_time;
-       else
-               reg = (reg & 0x0000FFFF) | (hw->fc.pause_time << 16);
-       IXGBE_WRITE_REG(hw, IXGBE_FCTTV(packetbuf_num / 2), reg);
+       reg = hw->fc.pause_time * 0x00010001;
+       for (i = 0; i < (IXGBE_DCB_MAX_TRAFFIC_CLASS / 2); i++)
+               IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg);
 
-       IXGBE_WRITE_REG(hw, IXGBE_FCRTV, (hw->fc.pause_time >> 1));
+       /* Configure flow control refresh threshold value */
+       IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2);
 
 out:
        return ret_val;
@@ -1325,15 +1317,15 @@ void ixgbe_enable_relaxed_ordering_82598
        for (i = 0; ((i < hw->mac.max_tx_queues) &&
             (i < IXGBE_DCA_MAX_QUEUES_82598)); i++) {
                regval = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(i));
-               regval |= IXGBE_DCA_TXCTRL_TX_WB_RO_EN;
+               regval |= IXGBE_DCA_TXCTRL_DESC_WRO_EN;
                IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(i), regval);
        }
 
        for (i = 0; ((i < hw->mac.max_rx_queues) &&
             (i < IXGBE_DCA_MAX_QUEUES_82598)); i++) {
                regval = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i));
-               regval |= (IXGBE_DCA_RXCTRL_DESC_WRO_EN |
-                          IXGBE_DCA_RXCTRL_DESC_HSRO_EN);
+               regval |= IXGBE_DCA_RXCTRL_DATA_WRO_EN |
+                         IXGBE_DCA_RXCTRL_HEAD_WRO_EN;
                IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval);
        }
 

Modified: stable/9/sys/dev/ixgbe/ixgbe_82598.h
==============================================================================
--- stable/9/sys/dev/ixgbe/ixgbe_82598.h        Sun Jul  8 20:35:56 2012        
(r238262)
+++ stable/9/sys/dev/ixgbe/ixgbe_82598.h        Sun Jul  8 20:39:00 2012        
(r238263)
@@ -36,7 +36,7 @@
 #define _IXGBE_82598_H_
 
 u32 ixgbe_get_pcie_msix_count_82598(struct ixgbe_hw *hw);
-s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num);
+s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw);
 s32 ixgbe_start_hw_82598(struct ixgbe_hw *hw);
 void ixgbe_enable_relaxed_ordering_82598(struct ixgbe_hw *hw);
 s32 ixgbe_set_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq);

Modified: stable/9/sys/dev/ixgbe/ixgbe_82599.c
==============================================================================
--- stable/9/sys/dev/ixgbe/ixgbe_82599.c        Sun Jul  8 20:35:56 2012        
(r238262)
+++ stable/9/sys/dev/ixgbe/ixgbe_82599.c        Sun Jul  8 20:39:00 2012        
(r238263)
@@ -243,6 +243,7 @@ s32 ixgbe_init_ops_82599(struct ixgbe_hw
 
        /* RAR, Multicast, VLAN */
        mac->ops.set_vmdq = &ixgbe_set_vmdq_generic;
+       mac->ops.set_vmdq_san_mac = &ixgbe_set_vmdq_san_mac_generic;
        mac->ops.clear_vmdq = &ixgbe_clear_vmdq_generic;
        mac->ops.insert_mac_addr = &ixgbe_insert_mac_addr_generic;
        mac->rar_highwater = 1;
@@ -304,7 +305,9 @@ s32 ixgbe_get_link_capabilities_82599(st
 
        /* Check if 1G SFP module. */
        if (hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core0 ||
-           hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core1) {
+           hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core1 ||
+           hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 ||
+           hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1) {
                *speed = IXGBE_LINK_SPEED_1GB_FULL;
                *negotiation = TRUE;
                goto out;
@@ -420,6 +423,7 @@ enum ixgbe_media_type ixgbe_get_media_ty
        case IXGBE_DEV_ID_82599_SFP:
        case IXGBE_DEV_ID_82599_SFP_FCOE:
        case IXGBE_DEV_ID_82599_SFP_EM:
+       case IXGBE_DEV_ID_82599_SFP_SF2:
        case IXGBE_DEV_ID_82599EN_SFP:
                media_type = ixgbe_media_type_fiber;
                break;
@@ -1088,6 +1092,9 @@ mac_reset_top:
                hw->mac.ops.set_rar(hw, hw->mac.num_rar_entries - 1,
                                    hw->mac.san_addr, 0, IXGBE_RAH_AV);
 
+               /* Save the SAN MAC RAR index */
+               hw->mac.san_mac_rar_index = hw->mac.num_rar_entries - 1;
+
                /* Reserve the last RAR for the SAN MAC address */
                hw->mac.num_rar_entries--;
        }
@@ -2037,6 +2044,8 @@ sfp_check:
                        physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR;
                else if (comp_codes_1g & IXGBE_SFF_1GBASET_CAPABLE)
                        physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_T;
+               else if (comp_codes_1g & IXGBE_SFF_1GBASESX_CAPABLE)
+                       physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_SX;
                break;
        default:
                break;
@@ -2233,3 +2242,4 @@ static s32 ixgbe_read_eeprom_82599(struc
        return ret_val;
 }
 
+

Modified: stable/9/sys/dev/ixgbe/ixgbe_api.c
==============================================================================
--- stable/9/sys/dev/ixgbe/ixgbe_api.c  Sun Jul  8 20:35:56 2012        
(r238262)
+++ stable/9/sys/dev/ixgbe/ixgbe_api.c  Sun Jul  8 20:39:00 2012        
(r238263)
@@ -118,6 +118,7 @@ s32 ixgbe_set_mac_type(struct ixgbe_hw *
                case IXGBE_DEV_ID_82599_BACKPLANE_FCOE:
                case IXGBE_DEV_ID_82599_SFP_FCOE:
                case IXGBE_DEV_ID_82599_SFP_EM:
+               case IXGBE_DEV_ID_82599_SFP_SF2:
                case IXGBE_DEV_ID_82599EN_SFP:
                case IXGBE_DEV_ID_82599_CX4:
                case IXGBE_DEV_ID_82599_T3_LOM:
@@ -130,6 +131,7 @@ s32 ixgbe_set_mac_type(struct ixgbe_hw *
                        hw->mac.type = ixgbe_mac_X540_vf;
                        break;
                case IXGBE_DEV_ID_X540T:
+               case IXGBE_DEV_ID_X540T1:
                        hw->mac.type = ixgbe_mac_X540;
                        break;
                default:
@@ -811,6 +813,18 @@ s32 ixgbe_set_vmdq(struct ixgbe_hw *hw, 
 {
        return ixgbe_call_func(hw, hw->mac.ops.set_vmdq, (hw, rar, vmdq),
                               IXGBE_NOT_IMPLEMENTED);
+
+}
+
+/**
+ *  ixgbe_set_vmdq_san_mac - Associate VMDq index 127 with a receive address
+ *  @hw: pointer to hardware structure
+ *  @vmdq: VMDq default pool index
+ **/
+s32 ixgbe_set_vmdq_san_mac(struct ixgbe_hw *hw, u32 vmdq)
+{
+       return ixgbe_call_func(hw, hw->mac.ops.set_vmdq_san_mac,
+                              (hw, vmdq), IXGBE_NOT_IMPLEMENTED);
 }
 
 /**
@@ -960,13 +974,12 @@ s32 ixgbe_set_vlvf(struct ixgbe_hw *hw, 
 /**
  *  ixgbe_fc_enable - Enable flow control
  *  @hw: pointer to hardware structure
- *  @packetbuf_num: packet buffer number (0-7)
  *
  *  Configures the flow control settings based on SW configuration.
  **/
-s32 ixgbe_fc_enable(struct ixgbe_hw *hw, s32 packetbuf_num)
+s32 ixgbe_fc_enable(struct ixgbe_hw *hw)
 {
-       return ixgbe_call_func(hw, hw->mac.ops.fc_enable, (hw, packetbuf_num),
+       return ixgbe_call_func(hw, hw->mac.ops.fc_enable, (hw),
                               IXGBE_NOT_IMPLEMENTED);
 }
 
@@ -1102,7 +1115,7 @@ u32 ixgbe_get_supported_physical_layer(s
 }
 
 /**
- *  ixgbe_enable_rx_dma - Enables Rx DMA unit, dependant on device specifics
+ *  ixgbe_enable_rx_dma - Enables Rx DMA unit, dependent on device specifics
  *  @hw: pointer to hardware structure
  *  @regval: bitfield to write to the Rx DMA register
  *

Modified: stable/9/sys/dev/ixgbe/ixgbe_api.h
==============================================================================
--- stable/9/sys/dev/ixgbe/ixgbe_api.h  Sun Jul  8 20:35:56 2012        
(r238262)
+++ stable/9/sys/dev/ixgbe/ixgbe_api.h  Sun Jul  8 20:39:00 2012        
(r238263)
@@ -104,6 +104,7 @@ s32 ixgbe_set_rar(struct ixgbe_hw *hw, u
                  u32 enable_addr);
 s32 ixgbe_clear_rar(struct ixgbe_hw *hw, u32 index);
 s32 ixgbe_set_vmdq(struct ixgbe_hw *hw, u32 rar, u32 vmdq);
+s32 ixgbe_set_vmdq_san_mac(struct ixgbe_hw *hw, u32 vmdq);
 s32 ixgbe_clear_vmdq(struct ixgbe_hw *hw, u32 rar, u32 vmdq);
 s32 ixgbe_init_rx_addrs(struct ixgbe_hw *hw);
 u32 ixgbe_get_num_rx_addrs(struct ixgbe_hw *hw);
@@ -120,7 +121,7 @@ s32 ixgbe_set_vfta(struct ixgbe_hw *hw, 
                   u32 vind, bool vlan_on);
 s32 ixgbe_set_vlvf(struct ixgbe_hw *hw, u32 vlan, u32 vind,
                   bool vlan_on, bool *vfta_changed);
-s32 ixgbe_fc_enable(struct ixgbe_hw *hw, s32 packetbuf_num);
+s32 ixgbe_fc_enable(struct ixgbe_hw *hw);
 s32 ixgbe_set_fw_drv_ver(struct ixgbe_hw *hw, u8 maj, u8 min, u8 build,
                         u8 ver);
 void ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr);

Modified: stable/9/sys/dev/ixgbe/ixgbe_common.c
==============================================================================
--- stable/9/sys/dev/ixgbe/ixgbe_common.c       Sun Jul  8 20:35:56 2012        
(r238262)
+++ stable/9/sys/dev/ixgbe/ixgbe_common.c       Sun Jul  8 20:39:00 2012        
(r238263)
@@ -51,13 +51,6 @@ static void ixgbe_release_eeprom(struct 
 static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr);
 static s32 ixgbe_get_san_mac_addr_offset(struct ixgbe_hw *hw,
                                         u16 *san_mac_offset);
-static s32 ixgbe_fc_autoneg_fiber(struct ixgbe_hw *hw);
-static s32 ixgbe_fc_autoneg_backplane(struct ixgbe_hw *hw);
-static s32 ixgbe_fc_autoneg_copper(struct ixgbe_hw *hw);
-static s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw);
-static s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg,
-                             u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm);
-static s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num);
 static s32 ixgbe_read_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset,
                                             u16 words, u16 *data);
 static s32 ixgbe_write_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset,
@@ -146,6 +139,177 @@ s32 ixgbe_init_ops_generic(struct ixgbe_
 }
 
 /**
+ *  ixgbe_device_supports_autoneg_fc - Check if phy supports autoneg flow
+ *  control
+ *  @hw: pointer to hardware structure
+ *
+ *  There are several phys that do not support autoneg flow control. This
+ *  function check the device id to see if the associated phy supports
+ *  autoneg flow control.
+ **/
+static s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
+{
+
+       DEBUGFUNC("ixgbe_device_supports_autoneg_fc");
+
+       switch (hw->device_id) {
+       case IXGBE_DEV_ID_X540T:
+       case IXGBE_DEV_ID_X540T1:
+               return IXGBE_SUCCESS;
+       case IXGBE_DEV_ID_82599_T3_LOM:
+               return IXGBE_SUCCESS;
+       default:
+               return IXGBE_ERR_FC_NOT_SUPPORTED;
+       }
+}
+
+/**
+ *  ixgbe_setup_fc - Set up flow control
+ *  @hw: pointer to hardware structure
+ *
+ *  Called at init time to set up flow control.
+ **/
+static s32 ixgbe_setup_fc(struct ixgbe_hw *hw)
+{
+       s32 ret_val = IXGBE_SUCCESS;
+       u32 reg = 0, reg_bp = 0;
+       u16 reg_cu = 0;
+
+       DEBUGFUNC("ixgbe_setup_fc");
+
+       /*
+        * Validate the requested mode.  Strict IEEE mode does not allow
+        * ixgbe_fc_rx_pause because it will cause us to fail at UNH.
+        */
+       if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
+               DEBUGOUT("ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
+               ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
+               goto out;
+       }
+
+       /*
+        * 10gig parts do not have a word in the EEPROM to determine the
+        * default flow control setting, so we explicitly set it to full.
+        */
+       if (hw->fc.requested_mode == ixgbe_fc_default)
+               hw->fc.requested_mode = ixgbe_fc_full;
+
+       /*
+        * Set up the 1G and 10G flow control advertisement registers so the
+        * HW will be able to do fc autoneg once the cable is plugged in.  If
+        * we link at 10G, the 1G advertisement is harmless and vice versa.
+        */
+       switch (hw->phy.media_type) {
+       case ixgbe_media_type_fiber:
+       case ixgbe_media_type_backplane:
+               reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
+               reg_bp = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+               break;
+       case ixgbe_media_type_copper:
+               hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT,
+                                    IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &reg_cu);
+               break;
+       default:
+               break;
+       }
+
+       /*
+        * The possible values of fc.requested_mode are:
+        * 0: Flow control is completely disabled
+        * 1: Rx flow control is enabled (we can receive pause frames,
+        *    but not send pause frames).
+        * 2: Tx flow control is enabled (we can send pause frames but
+        *    we do not support receiving pause frames).
+        * 3: Both Rx and Tx flow control (symmetric) are enabled.
+        * other: Invalid.
+        */
+       switch (hw->fc.requested_mode) {
+       case ixgbe_fc_none:
+               /* Flow control completely disabled by software override. */
+               reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
+               if (hw->phy.media_type == ixgbe_media_type_backplane)
+                       reg_bp &= ~(IXGBE_AUTOC_SYM_PAUSE |
+                                   IXGBE_AUTOC_ASM_PAUSE);
+               else if (hw->phy.media_type == ixgbe_media_type_copper)
+                       reg_cu &= ~(IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE);
+               break;
+       case ixgbe_fc_tx_pause:
+               /*
+                * Tx Flow control is enabled, and Rx Flow control is
+                * disabled by software override.
+                */
+               reg |= IXGBE_PCS1GANA_ASM_PAUSE;
+               reg &= ~IXGBE_PCS1GANA_SYM_PAUSE;
+               if (hw->phy.media_type == ixgbe_media_type_backplane) {
+                       reg_bp |= IXGBE_AUTOC_ASM_PAUSE;
+                       reg_bp &= ~IXGBE_AUTOC_SYM_PAUSE;
+               } else if (hw->phy.media_type == ixgbe_media_type_copper) {
+                       reg_cu |= IXGBE_TAF_ASM_PAUSE;
+                       reg_cu &= ~IXGBE_TAF_SYM_PAUSE;
+               }
+               break;
+       case ixgbe_fc_rx_pause:
+               /*
+                * Rx Flow control is enabled and Tx Flow control is
+                * disabled by software override. Since there really
+                * isn't a way to advertise that we are capable of RX
+                * Pause ONLY, we will advertise that we support both
+                * symmetric and asymmetric Rx PAUSE, as such we fall
+                * through to the fc_full statement.  Later, we will
+                * disable the adapter's ability to send PAUSE frames.
+                */
+       case ixgbe_fc_full:
+               /* Flow control (both Rx and Tx) is enabled by SW override. */
+               reg |= IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE;
+               if (hw->phy.media_type == ixgbe_media_type_backplane)
+                       reg_bp |= IXGBE_AUTOC_SYM_PAUSE |
+                                 IXGBE_AUTOC_ASM_PAUSE;
+               else if (hw->phy.media_type == ixgbe_media_type_copper)
+                       reg_cu |= IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE;
+               break;
+       default:
+               DEBUGOUT("Flow control param set incorrectly\n");
+               ret_val = IXGBE_ERR_CONFIG;
+               goto out;
+               break;
+       }
+
+       if (hw->mac.type != ixgbe_mac_X540) {
+               /*
+                * Enable auto-negotiation between the MAC & PHY;
+                * the MAC will advertise clause 37 flow control.
+                */
+               IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg);
+               reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL);
+
+               /* Disable AN timeout */
+               if (hw->fc.strict_ieee)
+                       reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN;
+
+               IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg);
+               DEBUGOUT1("Set up FC; PCS1GLCTL = 0x%08X\n", reg);
+       }
+
+       /*
+        * AUTOC restart handles negotiation of 1G and 10G on backplane
+        * and copper. There is no need to set the PCS1GCTL register.
+        *
+        */
+       if (hw->phy.media_type == ixgbe_media_type_backplane) {
+               reg_bp |= IXGBE_AUTOC_AN_RESTART;
+               IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_bp);
+       } else if ((hw->phy.media_type == ixgbe_media_type_copper) &&
+                   (ixgbe_device_supports_autoneg_fc(hw) == IXGBE_SUCCESS)) {
+               hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT,
+                                     IXGBE_MDIO_AUTO_NEG_DEV_TYPE, reg_cu);
+       }
+
+       DEBUGOUT1("Set up FC; IXGBE_AUTOC = 0x%08X\n", reg);
+out:
+       return ret_val;
+}
+
+/**
  *  ixgbe_start_hw_generic - Prepare hardware for Tx/Rx
  *  @hw: pointer to hardware structure
  *
@@ -156,6 +320,7 @@ s32 ixgbe_init_ops_generic(struct ixgbe_
  **/
 s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw)
 {
+       s32 ret_val;
        u32 ctrl_ext;
 
        DEBUGFUNC("ixgbe_start_hw_generic");
@@ -178,12 +343,15 @@ s32 ixgbe_start_hw_generic(struct ixgbe_
        IXGBE_WRITE_FLUSH(hw);
 
        /* Setup flow control */
-       ixgbe_setup_fc(hw, 0);
+       ret_val = ixgbe_setup_fc(hw);
+       if (ret_val != IXGBE_SUCCESS)
+               goto out;
 
        /* Clear adapter stopped flag */
        hw->adapter_stopped = FALSE;
 
-       return IXGBE_SUCCESS;
+out:
+       return ret_val;
 }
 
 /**
@@ -211,14 +379,14 @@ s32 ixgbe_start_hw_gen2(struct ixgbe_hw 
        /* Disable relaxed ordering */
        for (i = 0; i < hw->mac.max_tx_queues; i++) {
                regval = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(i));
-               regval &= ~IXGBE_DCA_TXCTRL_TX_WB_RO_EN;
+               regval &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN;
                IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(i), regval);
        }
 
        for (i = 0; i < hw->mac.max_rx_queues; i++) {
                regval = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i));
-               regval &= ~(IXGBE_DCA_RXCTRL_DESC_WRO_EN |
-                           IXGBE_DCA_RXCTRL_DESC_HSRO_EN);
+               regval &= ~(IXGBE_DCA_RXCTRL_DATA_WRO_EN |
+                           IXGBE_DCA_RXCTRL_HEAD_WRO_EN);
                IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval);
        }
 
@@ -583,6 +751,9 @@ s32 ixgbe_get_bus_info_generic(struct ix
        case IXGBE_PCI_LINK_SPEED_5000:
                hw->bus.speed = ixgbe_bus_speed_5000;
                break;
+       case IXGBE_PCI_LINK_SPEED_8000:
+               hw->bus.speed = ixgbe_bus_speed_8000;
+               break;
        default:
                hw->bus.speed = ixgbe_bus_speed_unknown;
                break;
@@ -2242,27 +2413,44 @@ s32 ixgbe_disable_mc_generic(struct ixgb
 /**
  *  ixgbe_fc_enable_generic - Enable flow control
  *  @hw: pointer to hardware structure
- *  @packetbuf_num: packet buffer number (0-7)
  *
  *  Enable flow control according to the current settings.
  **/
-s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packetbuf_num)
+s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw)
 {
        s32 ret_val = IXGBE_SUCCESS;
        u32 mflcn_reg, fccfg_reg;
        u32 reg;
        u32 fcrtl, fcrth;
+       int i;
 
        DEBUGFUNC("ixgbe_fc_enable_generic");
 
-       /* Negotiate the fc mode to use */
-       ret_val = ixgbe_fc_autoneg(hw);
-       if (ret_val == IXGBE_ERR_FLOW_CONTROL)
+       /* Validate the water mark configuration */
+       if (!hw->fc.pause_time) {
+               ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
                goto out;
+       }
+
+       /* Low water mark of zero causes XOFF floods */
+       for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) {
+               if ((hw->fc.current_mode & ixgbe_fc_tx_pause) &&
+                   hw->fc.high_water[i]) {
+                       if (!hw->fc.low_water[i] ||
+                           hw->fc.low_water[i] >= hw->fc.high_water[i]) {
+                               DEBUGOUT("Invalid water mark configuration\n");
+                               ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
+                               goto out;
+                       }
+               }
+       }
+
+       /* Negotiate the fc mode to use */
+       ixgbe_fc_autoneg(hw);
 
        /* Disable any previous flow control settings */
        mflcn_reg = IXGBE_READ_REG(hw, IXGBE_MFLCN);
-       mflcn_reg &= ~(IXGBE_MFLCN_RFCE | IXGBE_MFLCN_RPFCE);
+       mflcn_reg &= ~(IXGBE_MFLCN_RPFCE_MASK | IXGBE_MFLCN_RFCE);
 
        fccfg_reg = IXGBE_READ_REG(hw, IXGBE_FCCFG);
        fccfg_reg &= ~(IXGBE_FCCFG_TFCE_802_3X | IXGBE_FCCFG_TFCE_PRIORITY);
@@ -2319,120 +2507,110 @@ s32 ixgbe_fc_enable_generic(struct ixgbe
        IXGBE_WRITE_REG(hw, IXGBE_MFLCN, mflcn_reg);
        IXGBE_WRITE_REG(hw, IXGBE_FCCFG, fccfg_reg);
 
-       fcrth = hw->fc.high_water[packetbuf_num] << 10;
-       fcrtl = hw->fc.low_water << 10;
 
-       if (hw->fc.current_mode & ixgbe_fc_tx_pause) {
-               fcrth |= IXGBE_FCRTH_FCEN;
-               if (hw->fc.send_xon)
-                       fcrtl |= IXGBE_FCRTL_XONE;
-       }
+       /* Set up and enable Rx high/low water mark thresholds, enable XON. */
+       for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) {
+               if ((hw->fc.current_mode & ixgbe_fc_tx_pause) &&
+                   hw->fc.high_water[i]) {
+                       fcrtl = (hw->fc.low_water[i] << 10) | IXGBE_FCRTL_XONE;
+                       IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), fcrtl);
+                       fcrth = (hw->fc.high_water[i] << 10) | IXGBE_FCRTH_FCEN;
+               } else {
+                       IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), 0);
+                       /*
+                        * In order to prevent Tx hangs when the internal Tx
+                        * switch is enabled we must set the high water mark
+                        * to the maximum FCRTH value.  This allows the Tx
+                        * switch to function even under heavy Rx workloads.
+                        */
+                       fcrth = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)) - 32;
+               }
 
-       IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(packetbuf_num), fcrth);
-       IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(packetbuf_num), fcrtl);
+               IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), fcrth);
+       }
 
        /* Configure pause time (2 TCs per register) */
-       reg = IXGBE_READ_REG(hw, IXGBE_FCTTV(packetbuf_num / 2));
-       if ((packetbuf_num & 1) == 0)
-               reg = (reg & 0xFFFF0000) | hw->fc.pause_time;
-       else
-               reg = (reg & 0x0000FFFF) | (hw->fc.pause_time << 16);
-       IXGBE_WRITE_REG(hw, IXGBE_FCTTV(packetbuf_num / 2), reg);
+       reg = hw->fc.pause_time * 0x00010001;
+       for (i = 0; i < (IXGBE_DCB_MAX_TRAFFIC_CLASS / 2); i++)
+               IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg);
 
-       IXGBE_WRITE_REG(hw, IXGBE_FCRTV, (hw->fc.pause_time >> 1));
+       /* Configure flow control refresh threshold value */
+       IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2);
 
 out:
        return ret_val;
 }
 
 /**
- *  ixgbe_fc_autoneg - Configure flow control
+ *  ixgbe_negotiate_fc - Negotiate flow control
  *  @hw: pointer to hardware structure
+ *  @adv_reg: flow control advertised settings
+ *  @lp_reg: link partner's flow control settings
+ *  @adv_sym: symmetric pause bit in advertisement
+ *  @adv_asm: asymmetric pause bit in advertisement
+ *  @lp_sym: symmetric pause bit in link partner advertisement
+ *  @lp_asm: asymmetric pause bit in link partner advertisement
  *
- *  Compares our advertised flow control capabilities to those advertised by
- *  our link partner, and determines the proper flow control mode to use.
+ *  Find the intersection between advertised settings and link partner's
+ *  advertised settings
  **/
-s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw)
+static s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg,
+                             u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm)
 {
-       s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
-       ixgbe_link_speed speed;
-       bool link_up;
+       if ((!(adv_reg)) ||  (!(lp_reg)))
+               return IXGBE_ERR_FC_NOT_NEGOTIATED;
 
-       DEBUGFUNC("ixgbe_fc_autoneg");
+       if ((adv_reg & adv_sym) && (lp_reg & lp_sym)) {
+               /*
+                * Now we need to check if the user selected Rx ONLY
+                * of pause frames.  In this case, we had to advertise
+                * FULL flow control because we could not advertise RX
+                * ONLY. Hence, we must now check to see if we need to
+                * turn OFF the TRANSMISSION of PAUSE frames.
+                */
+               if (hw->fc.requested_mode == ixgbe_fc_full) {
+                       hw->fc.current_mode = ixgbe_fc_full;
+                       DEBUGOUT("Flow Control = FULL.\n");
+               } else {
+                       hw->fc.current_mode = ixgbe_fc_rx_pause;
+                       DEBUGOUT("Flow Control=RX PAUSE frames only\n");
+               }
+       } else if (!(adv_reg & adv_sym) && (adv_reg & adv_asm) &&
+                  (lp_reg & lp_sym) && (lp_reg & lp_asm)) {
+               hw->fc.current_mode = ixgbe_fc_tx_pause;
+               DEBUGOUT("Flow Control = TX PAUSE frames only.\n");
+       } else if ((adv_reg & adv_sym) && (adv_reg & adv_asm) &&
+                  !(lp_reg & lp_sym) && (lp_reg & lp_asm)) {
+               hw->fc.current_mode = ixgbe_fc_rx_pause;
+               DEBUGOUT("Flow Control = RX PAUSE frames only.\n");
+       } else {
+               hw->fc.current_mode = ixgbe_fc_none;
+               DEBUGOUT("Flow Control = NONE.\n");
+       }
+       return IXGBE_SUCCESS;
+}
 
-       if (hw->fc.disable_fc_autoneg)
-               goto out;
+/**
+ *  ixgbe_fc_autoneg_fiber - Enable flow control on 1 gig fiber
+ *  @hw: pointer to hardware structure
+ *
+ *  Enable flow control according on 1 gig fiber.
+ **/
+static s32 ixgbe_fc_autoneg_fiber(struct ixgbe_hw *hw)
+{
+       u32 pcs_anadv_reg, pcs_lpab_reg, linkstat;
+       s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
 
        /*
-        * AN should have completed when the cable was plugged in.
-        * Look for reasons to bail out.  Bail out if:
-        * - FC autoneg is disabled, or if
-        * - link is not up.
-        *
-        * Since we're being called from an LSC, link is already known to be up.
-        * So use link_up_wait_to_complete=FALSE.
-        */
-       hw->mac.ops.check_link(hw, &speed, &link_up, FALSE);
-       if (!link_up) {
-               ret_val = IXGBE_ERR_FLOW_CONTROL;
-               goto out;
-       }
-
-       switch (hw->phy.media_type) {
-       /* Autoneg flow control on fiber adapters */
-       case ixgbe_media_type_fiber:
-               if (speed == IXGBE_LINK_SPEED_1GB_FULL)
-                       ret_val = ixgbe_fc_autoneg_fiber(hw);
-               break;
-
-       /* Autoneg flow control on backplane adapters */
-       case ixgbe_media_type_backplane:
-               ret_val = ixgbe_fc_autoneg_backplane(hw);
-               break;
-
-       /* Autoneg flow control on copper adapters */
-       case ixgbe_media_type_copper:
-               if (ixgbe_device_supports_autoneg_fc(hw) == IXGBE_SUCCESS)
-                       ret_val = ixgbe_fc_autoneg_copper(hw);
-               break;
-
-       default:
-               break;
-       }
-
-out:
-       if (ret_val == IXGBE_SUCCESS) {
-               hw->fc.fc_was_autonegged = TRUE;

*** 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