ix: Update to Intel ix-2.8.2
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Tue, 1 Dec 2015 03:07:40 +0000 (11:07 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Thu, 3 Dec 2015 09:05:59 +0000 (17:05 +0800)
This update adds more chips support.

Local changes:
Fix ifmedia support.  Now media change (force 10G-SR and 1G-SX) works
properly at least on my 82599 w/ DAC; though "autoselect" is still
the recommended mode.

31 files changed:
share/man/man4/ix.4
sys/conf/files
sys/dev/netif/ix/Makefile
sys/dev/netif/ix/if_ix.c
sys/dev/netif/ix/if_ix.h
sys/dev/netif/ix/ixgbe_82598.c
sys/dev/netif/ix/ixgbe_82598.h
sys/dev/netif/ix/ixgbe_82599.c
sys/dev/netif/ix/ixgbe_82599.h
sys/dev/netif/ix/ixgbe_api.c
sys/dev/netif/ix/ixgbe_api.h
sys/dev/netif/ix/ixgbe_common.c
sys/dev/netif/ix/ixgbe_common.h
sys/dev/netif/ix/ixgbe_dcb.c
sys/dev/netif/ix/ixgbe_dcb.h
sys/dev/netif/ix/ixgbe_dcb_82598.c
sys/dev/netif/ix/ixgbe_dcb_82598.h
sys/dev/netif/ix/ixgbe_dcb_82599.c
sys/dev/netif/ix/ixgbe_dcb_82599.h
sys/dev/netif/ix/ixgbe_mbx.c
sys/dev/netif/ix/ixgbe_mbx.h
sys/dev/netif/ix/ixgbe_osdep.h
sys/dev/netif/ix/ixgbe_phy.c
sys/dev/netif/ix/ixgbe_phy.h
sys/dev/netif/ix/ixgbe_type.h
sys/dev/netif/ix/ixgbe_vf.c
sys/dev/netif/ix/ixgbe_vf.h
sys/dev/netif/ix/ixgbe_x540.c
sys/dev/netif/ix/ixgbe_x540.h
sys/dev/netif/ix/ixgbe_x550.c [new file with mode: 0644]
sys/dev/netif/ix/ixgbe_x550.h [new file with mode: 0644]

index 54ac18c..68f39a6 100644 (file)
@@ -153,6 +153,20 @@ controller chips:
 .Pp
 .Bl -bullet -compact
 .It
+Intel 82599EB 10 Gigabit Ethernet Controller
+.It
+Intel 82598EB 10 Gigabit Ethernet Controller
+.It
+Intel Ethernet Converged Network Adapter X520-SR1
+.It
+Intel Ethernet Converged Network Adapter X520-SR2
+.It
+Intel Ethernet Converged Network Adapter X520-DA2
+.It
+Intel Ethernet Converged Network Adapter X520-LR1
+.It
+Intel 82599ES 10 Gigabit Ethernet Controller
+.It
 Intel 10 Gigabit AF DA Dual Port Server Adapter
 .It
 Intel 10 Gigabit AT Server Adapter
@@ -167,29 +181,27 @@ Intel 10 Gigabit XF SR Dual Port Server Adapter
 .It
 Intel 10 Gigabit XF SR Server Adapter
 .It
-Intel 82598 10 Gigabit Ethernet Controller
+Intel Ethernet Converged Network Adapter X540-T1
 .It
-Intel 82599 10 Gigabit Ethernet Controller
+Intel Ethernet Converged Network Adapter X540-T2
 .It
 Intel Ethernet Controller X540-AT2
 .It
-Intel Ethernet Converged Network Adapter X520 Series
+Intel 82599EN 10 Gigabit Ethernet Controller
 .It
-Intel Ethernet Converged Network Adapter X540-T1
-.It
-Intel Ethernet Converged Network Adapter X540-T2
+Intel Ethernet Converged Network Adapter X520-DA1
 .It
-Intel Ethernet Server Adapter X520 Series
+Intel Ethernet Converged Network Adapter X520-DA4
 .It
-Intel Ethernet Server Adapter X520-DA2
+Intel Ethernet Converged Network Adapter X520-QDA1
 .It
-Intel Ethernet Server Adapter X520-LR1
+Intel Ethernet Converged Network Adapter X520-T2
 .It
-Intel Ethernet Server Adapter X520-SR1
+Intel Ethernet Controller X710-AM2
 .It
-Intel Ethernet Server Adapter X520-SR2
+Intel Ethernet Converged Network Adapter X710-DA2
 .It
-Intel Ethernet Server Adapter X520-T2
+Intel Ethernet Converged Network Adapter X710-DA4
 .El
 .Sh TUNABLES
 Tunables can be set at the
index fe35058..dbad8a8 100644 (file)
@@ -386,6 +386,7 @@ dev/netif/ix/ixgbe_mbx.c    optional ix
 dev/netif/ix/ixgbe_phy.c       optional ix
 dev/netif/ix/ixgbe_vf.c                optional ix
 dev/netif/ix/ixgbe_x540.c      optional ix
+dev/netif/ix/ixgbe_x550.c      optional ix
 dev/netif/ig_hal/e1000_80003es2lan.c   optional ig_hal
 dev/netif/ig_hal/e1000_82540.c optional ig_hal
 dev/netif/ig_hal/e1000_82541.c optional ig_hal
index 531a9da..821b916 100644 (file)
@@ -5,7 +5,7 @@ SRCS    += opt_ix.h opt_ifpoll.h
 
 SRCS   += ixgbe_common.c ixgbe_api.c ixgbe_phy.c ixgbe_vf.c ixgbe_mbx.c
 SRCS   += ixgbe_dcb.c ixgbe_dcb_82598.c ixgbe_dcb_82599.c
-SRCS   += ixgbe_82598.c ixgbe_82599.c ixgbe_x540.c
+SRCS   += ixgbe_82598.c ixgbe_82599.c ixgbe_x540.c ixgbe_x550.c
 
 .ifndef BUILDING_WITH_KERNEL
 
index e5315a3..e807fa2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001-2013, Intel Corporation 
+ * Copyright (c) 2001-2014, Intel Corporation 
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without 
@@ -71,6 +71,8 @@
 #include <dev/netif/ix/ixgbe_api.h>
 #include <dev/netif/ix/if_ix.h>
 
+#define IX_IFM_DEFAULT         (IFM_ETHER | IFM_AUTO)
+
 #ifdef IX_RSS_DEBUG
 #define IX_RSS_DPRINTF(sc, lvl, fmt, ...) \
 do { \
@@ -83,7 +85,7 @@ do { \
 
 #define IX_NAME                        "Intel(R) PRO/10GbE "
 #define IX_DEVICE(id) \
-       { IXGBE_VENDOR_ID, IXGBE_DEV_ID_##id, IX_NAME #id }
+       { IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_##id, IX_NAME #id }
 #define IX_DEVICE_NULL         { 0, 0, NULL }
 
 static struct ix_device {
@@ -114,7 +116,13 @@ static struct ix_device {
        IX_DEVICE(82599_SFP_FCOE),
        IX_DEVICE(82599EN_SFP),
        IX_DEVICE(82599_SFP_SF_QP),
+       IX_DEVICE(82599_QSFP_SF_QP),
        IX_DEVICE(X540T),
+       IX_DEVICE(X540T1),
+       IX_DEVICE(X550T),
+       IX_DEVICE(X550EM_X_KR),
+       IX_DEVICE(X550EM_X_KX4),
+       IX_DEVICE(X550EM_X_10G_T),
 
        /* required last entry */
        IX_DEVICE_NULL
@@ -160,9 +168,6 @@ static int  ix_sysctl_rxtx_intr_rate(SYSCTL_HANDLER_ARGS);
 static int     ix_sysctl_rx_intr_rate(SYSCTL_HANDLER_ARGS);
 static int     ix_sysctl_tx_intr_rate(SYSCTL_HANDLER_ARGS);
 static int     ix_sysctl_sts_intr_rate(SYSCTL_HANDLER_ARGS);
-#ifdef foo
-static int     ix_sysctl_advspeed(SYSCTL_HANDLER_ARGS);
-#endif
 #if 0
 static void     ix_add_hw_stats(struct ix_softc *);
 #endif
@@ -241,13 +246,17 @@ static void       ix_msix_status(void *);
 static void    ix_config_link(struct ix_softc *);
 static boolean_t ix_sfp_probe(struct ix_softc *);
 static boolean_t ix_is_sfp(const struct ixgbe_hw *);
-static void    ix_setup_optics(struct ix_softc *);
 static void    ix_update_link_status(struct ix_softc *);
 static void    ix_handle_link(struct ix_softc *);
 static void    ix_handle_mod(struct ix_softc *);
 static void    ix_handle_msf(struct ix_softc *);
+static void    ix_handle_phy(struct ix_softc *);
+static int     ix_powerdown(struct ix_softc *);
+static void    ix_config_flowctrl(struct ix_softc *);
+static void    ix_config_dmac(struct ix_softc *);
+static void    ix_init_media(struct ix_softc *);
 
-/* XXX Shared code structure requires this for the moment */
+/* XXX Missing shared code prototype */
 extern void ixgbe_stop_mac_link_on_d3_82599(struct ixgbe_hw *);
 
 static device_method_t ix_methods[] = {
@@ -355,7 +364,7 @@ ix_attach(device_t dev)
 
        ixgbe_set_mac_type(hw);
 
-       /* Pick up the 82599 and VF settings */
+       /* Pick up the 82599 */
        if (hw->mac.type != ixgbe_mac_82598EB)
                hw->phy.smart_speed = ix_smart_speed;
 
@@ -499,13 +508,12 @@ ix_attach(device_t dev)
                device_printf(dev, "No SFP+ Module found\n");
        }
 
-       /* Detect and set physical type */
-       ix_setup_optics(sc);
-
+       sc->ifm_media = IX_IFM_DEFAULT;
        /* Get default flow control settings */
        device_getenv_string(dev, "flow_ctrl", flowctrl, sizeof(flowctrl),
            ix_flowctrl);
-       sc->ifm_flowctrl = ifmedia_str2ethfc(flowctrl);
+       sc->ifm_media |= ifmedia_str2ethfc(flowctrl);
+       sc->advspeed = IXGBE_LINK_SPEED_UNKNOWN;
 
        /* Setup OS specific network interface */
        ix_setup_ifp(sc);
@@ -522,11 +530,12 @@ ix_attach(device_t dev)
        /* Initialize statistics */
        ix_update_stats(sc);
 
-       /*
-        * Check PCIE slot type/speed/width
-        */
+       /* Check PCIE slot type/speed/width */
        ix_slot_info(sc);
 
+       /* Save initial wake up filter configuration */
+       sc->wufc = IXGBE_READ_REG(hw, IXGBE_WUFC);
+
        /* Let hardware know driver is loaded */
        ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
        ctrl_ext |= IXGBE_CTRL_EXT_DRV_LOAD;
@@ -549,7 +558,7 @@ ix_detach(device_t dev)
 
                ifnet_serialize_all(ifp);
 
-               ix_stop(sc);
+               ix_powerdown(sc);
                ix_teardown_intr(sc, sc->intr_cnt);
 
                ifnet_deserialize_all(ifp);
@@ -594,7 +603,7 @@ ix_shutdown(device_t dev)
        struct ifnet *ifp = &sc->arpcom.ac_if;
 
        ifnet_serialize_all(ifp);
-       ix_stop(sc);
+       ix_powerdown(sc);
        ifnet_deserialize_all(ifp);
 
        return 0;
@@ -668,12 +677,11 @@ ix_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr)
 
        switch (command) {
        case SIOCSIFMTU:
-               if (ifr->ifr_mtu > IX_MAX_FRAME_SIZE - ETHER_HDR_LEN) {
+               if (ifr->ifr_mtu > IX_MAX_MTU) {
                        error = EINVAL;
                } else {
                        ifp->if_mtu = ifr->ifr_mtu;
-                       sc->max_frame_size =
-                           ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;
+                       sc->max_frame_size = ifp->if_mtu + IX_MTU_HDR;
                        ix_init(sc);
                }
                break;
@@ -774,7 +782,6 @@ ix_init(void *xsc)
        struct ix_softc *sc = xsc;
        struct ifnet *ifp = &sc->arpcom.ac_if;
        struct ixgbe_hw *hw = &sc->hw;
-       uint32_t rxpb, frame, size, tmp;
        uint32_t gpie, rxctrl;
        int i, error;
        boolean_t polling;
@@ -824,15 +831,20 @@ ix_init(void *xsc)
        gpie = IXGBE_READ_REG(hw, IXGBE_GPIE);
 
        /* Enable Fan Failure Interrupt */
-       gpie |= IXGBE_SDP1_GPIEN;
+       gpie |= IXGBE_SDP1_GPIEN_BY_MAC(hw);
 
        /* Add for Module detection */
        if (hw->mac.type == ixgbe_mac_82599EB)
                gpie |= IXGBE_SDP2_GPIEN;
 
-       /* Thermal Failure Detection */
-       if (hw->mac.type == ixgbe_mac_X540)
-               gpie |= IXGBE_SDP0_GPIEN;
+       /*
+        * Thermal Failure Detection (X540)
+        * Link Detection (X552)
+        */
+       if (hw->mac.type == ixgbe_mac_X540 ||
+           hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP ||
+           hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T)
+               gpie |= IXGBE_SDP0_GPIEN_X540;
 
        if (sc->intr_type == PCI_INTR_TYPE_MSIX) {
                /* Enable Enhanced MSIX mode */
@@ -846,6 +858,7 @@ ix_init(void *xsc)
        if (ifp->if_mtu > ETHERMTU) {
                uint32_t mhadd;
 
+               /* aka IXGBE_MAXFRS on 82599 and newer */
                mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD);
                mhadd &= ~IXGBE_MHADD_MFS_MASK;
                mhadd |= sc->max_frame_size << IXGBE_MHADD_MFS_SHIFT;
@@ -908,9 +921,6 @@ ix_init(void *xsc)
                    sc->rx_rings[0].rx_ndesc - 1);
        }
 
-       /* Set up VLAN support and filter */
-       ix_set_vlan(sc);
-
        /* Enable Receive engine */
        rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
        if (hw->mac.type == ixgbe_mac_82598EB)
@@ -993,38 +1003,18 @@ ix_init(void *xsc)
        /* Config/Enable Link */
        ix_config_link(sc);
 
-       /*
-        * Hardware Packet Buffer & Flow Control setup
-        */
-       frame = sc->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);
-
-       hw->fc.requested_mode = ix_ifmedia2fc(sc->ifm_flowctrl);
-       if (sc->ifm_flowctrl & IFM_ETH_FORCEPAUSE)
-               hw->fc.disable_fc_autoneg = TRUE;
-       else
-               hw->fc.disable_fc_autoneg = FALSE;
-       hw->fc.pause_time = IX_FC_PAUSE;
-       hw->fc.send_xon = TRUE;
+       /* Hardware Packet Buffer & Flow Control setup */
+       ix_config_flowctrl(sc);
 
        /* Initialize the FC settings */
        ixgbe_start_hw(hw);
 
+       /* Set up VLAN support and filter */
+       ix_set_vlan(sc);
+
+       /* Setup DMA Coalescing */
+       ix_config_dmac(sc);
+
        /*
         * Only enable interrupts if we are not polling, make sure
         * they are off otherwise.
@@ -1097,6 +1087,8 @@ static void
 ix_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
 {
        struct ix_softc *sc = ifp->if_softc;
+       struct ifmedia *ifm = &sc->media;
+       int layer;
 
        ix_update_link_status(sc);
 
@@ -1104,29 +1096,112 @@ ix_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
        ifmr->ifm_active = IFM_ETHER;
 
        if (!sc->link_active) {
-               ifmr->ifm_active |= IFM_NONE;
+               if (IFM_SUBTYPE(ifm->ifm_media) != IFM_AUTO)
+                       ifmr->ifm_active |= ifm->ifm_media;
+               else
+                       ifmr->ifm_active |= IFM_NONE;
                return;
        }
-
        ifmr->ifm_status |= IFM_ACTIVE;
 
-       switch (sc->link_speed) {
-       case IXGBE_LINK_SPEED_100_FULL:
-               ifmr->ifm_active |= IFM_100_TX | IFM_FDX;
-               break;
-       case IXGBE_LINK_SPEED_1GB_FULL:
-               ifmr->ifm_active |= IFM_1000_SX | IFM_FDX;
-               break;
-       case IXGBE_LINK_SPEED_10GB_FULL:
-               ifmr->ifm_active |= sc->optics | IFM_FDX;
-               break;
-       default:
-               ifmr->ifm_active |= IFM_NONE;
-               return;
+       layer = ixgbe_get_supported_physical_layer(&sc->hw);
+
+       if ((layer & IXGBE_PHYSICAL_LAYER_10GBASE_T) ||
+           (layer & IXGBE_PHYSICAL_LAYER_1000BASE_T) ||
+           (layer & IXGBE_PHYSICAL_LAYER_100BASE_TX)) {
+               switch (sc->link_speed) {
+               case IXGBE_LINK_SPEED_10GB_FULL:
+                       ifmr->ifm_active |= IFM_10G_T | IFM_FDX;
+                       break;
+               case IXGBE_LINK_SPEED_1GB_FULL:
+                       ifmr->ifm_active |= IFM_1000_T | IFM_FDX;
+                       break;
+               case IXGBE_LINK_SPEED_100_FULL:
+                       ifmr->ifm_active |= IFM_100_TX | IFM_FDX;
+                       break;
+               }
+       } else if ((layer & IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU) ||
+           (layer & IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA)) {
+               switch (sc->link_speed) {
+               case IXGBE_LINK_SPEED_10GB_FULL:
+                       ifmr->ifm_active |= IFM_10G_TWINAX | IFM_FDX;
+                       break;
+               }
+       } else if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LR) {
+               switch (sc->link_speed) {
+               case IXGBE_LINK_SPEED_10GB_FULL:
+                       ifmr->ifm_active |= IFM_10G_LR | IFM_FDX;
+                       break;
+               case IXGBE_LINK_SPEED_1GB_FULL:
+                       ifmr->ifm_active |= IFM_1000_LX | IFM_FDX;
+                       break;
+               }
+       } else if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LRM) {
+               switch (sc->link_speed) {
+               case IXGBE_LINK_SPEED_10GB_FULL:
+                       ifmr->ifm_active |= IFM_10G_LRM | IFM_FDX;
+                       break;
+               case IXGBE_LINK_SPEED_1GB_FULL:
+                       ifmr->ifm_active |= IFM_1000_LX | IFM_FDX;
+                       break;
+               }
+       } else if ((layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR) ||
+           (layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX)) {
+               switch (sc->link_speed) {
+               case IXGBE_LINK_SPEED_10GB_FULL:
+                       ifmr->ifm_active |= IFM_10G_SR | IFM_FDX;
+                       break;
+               case IXGBE_LINK_SPEED_1GB_FULL:
+                       ifmr->ifm_active |= IFM_1000_SX | IFM_FDX;
+                       break;
+               }
+       } else if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_CX4) {
+               switch (sc->link_speed) {
+               case IXGBE_LINK_SPEED_10GB_FULL:
+                       ifmr->ifm_active |= IFM_10G_CX4 | IFM_FDX;
+                       break;
+               }
+       } else if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) {
+               /*
+                * XXX: These need to use the proper media types once
+                * they're added.
+                */
+               switch (sc->link_speed) {
+               case IXGBE_LINK_SPEED_10GB_FULL:
+                       ifmr->ifm_active |= IFM_10G_SR | IFM_FDX;
+                       break;
+               case IXGBE_LINK_SPEED_2_5GB_FULL:
+                       ifmr->ifm_active |= IFM_2500_SX | IFM_FDX;
+                       break;
+               case IXGBE_LINK_SPEED_1GB_FULL:
+                       ifmr->ifm_active |= IFM_1000_CX | IFM_FDX;
+                       break;
+               }
+       } else if ((layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4) ||
+           (layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX)) {
+               /*
+                * XXX: These need to use the proper media types once
+                * they're added.
+                */
+               switch (sc->link_speed) {
+               case IXGBE_LINK_SPEED_10GB_FULL:
+                       ifmr->ifm_active |= IFM_10G_CX4 | IFM_FDX;
+                       break;
+               case IXGBE_LINK_SPEED_2_5GB_FULL:
+                       ifmr->ifm_active |= IFM_2500_SX | IFM_FDX;
+                       break;
+               case IXGBE_LINK_SPEED_1GB_FULL:
+                       ifmr->ifm_active |= IFM_1000_CX | IFM_FDX;
+                       break;
+               }
        }
 
-       if (sc->ifm_flowctrl & IFM_ETH_FORCEPAUSE)
-               ifmr->ifm_active |= IFM_ETH_FORCEPAUSE;
+       /* If nothing is recognized... */
+       if (IFM_SUBTYPE(ifmr->ifm_active) == 0)
+               ifmr->ifm_active |= IFM_NONE;
+
+       if (sc->ifm_media & IFM_ETH_FORCEPAUSE)
+               ifmr->ifm_active |= (sc->ifm_media & IFM_ETH_FCMASK);
 
        switch (sc->hw.fc.current_mode) {
        case ixgbe_fc_full:
@@ -1148,25 +1223,62 @@ ix_media_change(struct ifnet *ifp)
 {
        struct ix_softc *sc = ifp->if_softc;
        struct ifmedia *ifm = &sc->media;
+       struct ixgbe_hw *hw = &sc->hw;
 
        if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
-               return EINVAL;
+               return (EINVAL);
+
+       if (hw->phy.media_type == ixgbe_media_type_backplane ||
+           hw->mac.ops.setup_link == NULL) {
+               if ((ifm->ifm_media ^ sc->ifm_media) & IFM_ETH_FCMASK) {
+                       /* Only flow control setting changes are allowed */
+                       return (EOPNOTSUPP);
+               }
+       }
 
        switch (IFM_SUBTYPE(ifm->ifm_media)) {
        case IFM_AUTO:
-               sc->hw.phy.autoneg_advertised =
-                   IXGBE_LINK_SPEED_100_FULL |
-                   IXGBE_LINK_SPEED_1GB_FULL |
-                   IXGBE_LINK_SPEED_10GB_FULL;
+               sc->advspeed = IXGBE_LINK_SPEED_UNKNOWN;
                break;
+
+       case IFM_10G_T:
+       case IFM_10G_LRM:
+       case IFM_10G_SR:        /* XXX also KR */
+       case IFM_10G_LR:
+       case IFM_10G_CX4:       /* XXX also KX4 */
+       case IFM_10G_TWINAX:
+               sc->advspeed = IXGBE_LINK_SPEED_10GB_FULL;
+               break;
+
+       case IFM_1000_T:
+       case IFM_1000_LX:
+       case IFM_1000_SX:
+       case IFM_1000_CX:       /* XXX is KX */
+               sc->advspeed = IXGBE_LINK_SPEED_1GB_FULL;
+               break;
+
+       case IFM_100_TX:
+               sc->advspeed = IXGBE_LINK_SPEED_100_FULL;
+               break;
+
        default:
-               if_printf(ifp, "Only auto media type\n");
+               if (bootverbose) {
+                       if_printf(ifp, "Invalid media type %d!\n",
+                           ifm->ifm_media);
+               }
                return EINVAL;
        }
-       sc->ifm_flowctrl = ifm->ifm_media & IFM_ETH_FCMASK;
+       sc->ifm_media = ifm->ifm_media;
 
+#if 0
+       if (hw->mac.ops.setup_link != NULL) {
+               hw->mac.autotry_restart = TRUE;
+               hw->mac.ops.setup_link(hw, sc->advspeed, TRUE);
+       }
+#else
        if (ifp->if_flags & IFF_RUNNING)
                ix_init(sc);
+#endif
        return 0;
 }
 
@@ -1461,6 +1573,9 @@ ix_update_link_status(struct ix_softc *sc)
                                }
                        }
 
+                       /* Update DMA coalescing config */
+                       ix_config_dmac(sc);
+
                        sc->link_active = TRUE;
 
                        ifp->if_link_state = LINK_STATE_UP;
@@ -1521,58 +1636,6 @@ ix_stop(struct ix_softc *sc)
                ix_free_rx_ring(&sc->rx_rings[i]);
 }
 
-static void
-ix_setup_optics(struct ix_softc *sc)
-{
-       struct ixgbe_hw *hw = &sc->hw;
-       int layer;
-
-       layer = ixgbe_get_supported_physical_layer(hw);
-
-       if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T) {
-               sc->optics = IFM_10G_T;
-               return;
-       }
-
-       if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_T) {
-               sc->optics = IFM_1000_T;
-               return;
-       }
-
-       if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX) {
-               sc->optics = IFM_1000_SX;
-               return;
-       }
-
-       if (layer & (IXGBE_PHYSICAL_LAYER_10GBASE_LR |
-           IXGBE_PHYSICAL_LAYER_10GBASE_LRM)) {
-               sc->optics = IFM_10G_LR;
-               return;
-       }
-
-       if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR) {
-               sc->optics = IFM_10G_SR;
-               return;
-       }
-
-       if (layer & IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU) {
-               sc->optics = IFM_10G_TWINAX;
-               return;
-       }
-
-       if (layer & (IXGBE_PHYSICAL_LAYER_10GBASE_KX4 |
-           IXGBE_PHYSICAL_LAYER_10GBASE_CX4)) {
-               sc->optics = IFM_10G_CX4;
-               return;
-       }
-
-       /*
-        * If we get here just set the default.
-        * XXX this probably is wrong.
-        */
-       sc->optics = IFM_AUTO;
-}
-
 static void
 ix_setup_ifp(struct ix_softc *sc)
 {
@@ -1637,20 +1700,8 @@ ix_setup_ifp(struct ix_softc *sc)
                ifsq_watchdog_init(&txr->tx_watchdog, ifsq, ix_watchdog);
        }
 
-       /*
-        * Specify the media types supported by this adapter and register
-        * callbacks to update media and link information
-        */
-       ifmedia_add(&sc->media, IFM_ETHER | sc->optics | IFM_FDX, 0, NULL);
-       if (hw->device_id == IXGBE_DEV_ID_82598AT) {
-               if (sc->optics != IFM_1000_T) {
-                       ifmedia_add(&sc->media,
-                           IFM_ETHER | IFM_1000_T | IFM_FDX, 0, NULL);
-               }
-       }
-       if (sc->optics != IFM_AUTO)
-               ifmedia_add(&sc->media, IFM_ETHER | IFM_AUTO, 0, NULL);
-       ifmedia_set(&sc->media, IFM_ETHER | IFM_AUTO | sc->ifm_flowctrl);
+       /* Specify the media types supported by this adapter */
+       ix_init_media(sc);
 }
 
 static boolean_t
@@ -1663,6 +1714,10 @@ ix_is_sfp(const struct ixgbe_hw *hw)
        case ixgbe_phy_sfp_unknown:
        case ixgbe_phy_sfp_passive_tyco:
        case ixgbe_phy_sfp_passive_unknown:
+       case ixgbe_phy_qsfp_passive_unknown:
+       case ixgbe_phy_qsfp_active_unknown:
+       case ixgbe_phy_qsfp_intel:
+       case ixgbe_phy_qsfp_unknown:
                return TRUE;
        default:
                return FALSE;
@@ -1694,7 +1749,10 @@ ix_config_link(struct ix_softc *sc)
                                return;
                }
 
-               autoneg = hw->phy.autoneg_advertised;
+               if (sc->advspeed != IXGBE_LINK_SPEED_UNKNOWN)
+                       autoneg = sc->advspeed;
+               else
+                       autoneg = hw->phy.autoneg_advertised;
                if (!autoneg && hw->mac.ops.get_link_capabilities != NULL) {
                        bool negotiate;
 
@@ -2416,20 +2474,21 @@ ix_init_rx_unit(struct ix_softc *sc)
 {
        struct ixgbe_hw *hw = &sc->hw;
        struct ifnet *ifp = &sc->arpcom.ac_if;
-       uint32_t bufsz, rxctrl, fctrl, rxcsum, hlreg;
+       uint32_t bufsz, fctrl, rxcsum, hlreg;
        int i;
 
        /*
         * Make sure receives are disabled while setting up the descriptor ring
         */
-       rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
-       IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl & ~IXGBE_RXCTRL_RXEN);
+       ixgbe_disable_rx(hw);
 
        /* Enable broadcasts */
        fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL);
        fctrl |= IXGBE_FCTRL_BAM;
-       fctrl |= IXGBE_FCTRL_DPF;
-       fctrl |= IXGBE_FCTRL_PMCF;
+       if (hw->mac.type == ixgbe_mac_82598EB) {
+               fctrl |= IXGBE_FCTRL_DPF;
+               fctrl |= IXGBE_FCTRL_PMCF;
+       }
        IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl);
 
        /* Set for Jumbo Frames? */
@@ -2466,20 +2525,20 @@ ix_init_rx_unit(struct ix_softc *sc)
                srrctl |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF;
                if (sc->rx_ring_inuse > 1) {
                        /* See the commend near ix_enable_rx_drop() */
-                       if (sc->ifm_flowctrl &
+                       if (sc->ifm_media &
                            (IFM_ETH_RXPAUSE | IFM_ETH_TXPAUSE)) {
                                srrctl &= ~IXGBE_SRRCTL_DROP_EN;
                                if (i == 0 && bootverbose) {
                                        if_printf(ifp, "flow control %s, "
                                            "disable RX drop\n",
-                                           ix_ifmedia2str(sc->ifm_flowctrl));
+                                           ix_ifmedia2str(sc->ifm_media));
                                }
                        } else {
                                srrctl |= IXGBE_SRRCTL_DROP_EN;
                                if (i == 0 && bootverbose) {
                                        if_printf(ifp, "flow control %s, "
                                            "enable RX drop\n",
-                                           ix_ifmedia2str(sc->ifm_flowctrl));
+                                           ix_ifmedia2str(sc->ifm_media));
                                }
                        }
                }
@@ -2500,7 +2559,7 @@ ix_init_rx_unit(struct ix_softc *sc)
         */
        if (IX_ENABLE_HWRSS(sc)) {
                uint8_t key[IX_NRSSRK * IX_RSSRK_SIZE];
-               int j, r;
+               int j, r, nreta;
 
                /*
                 * NOTE:
@@ -2523,12 +2582,24 @@ ix_init_rx_unit(struct ix_softc *sc)
                        IXGBE_WRITE_REG(hw, IXGBE_RSSRK(i), rssrk);
                }
 
+               /* Table size will differ based on MAC */
+               switch (hw->mac.type) {
+               case ixgbe_mac_X550:
+               case ixgbe_mac_X550EM_x:
+               case ixgbe_mac_X550EM_a:
+                       nreta = IX_NRETA_X550;
+                       break;
+               default:
+                       nreta = IX_NRETA;
+                       break;
+               }
+
                /*
                 * Configure RSS redirect table in following fashion:
                 * (hash & ring_cnt_mask) == rdr_table[(hash & rdr_table_mask)]
                 */
                r = 0;
-               for (j = 0; j < IX_NRETA; ++j) {
+               for (j = 0; j < nreta; ++j) {
                        uint32_t reta = 0;
 
                        for (i = 0; i < IX_RETA_SIZE; ++i) {
@@ -2539,7 +2610,12 @@ ix_init_rx_unit(struct ix_softc *sc)
                                ++r;
                        }
                        IX_RSS_DPRINTF(sc, 1, "reta 0x%08x\n", reta);
-                       IXGBE_WRITE_REG(hw, IXGBE_RETA(j), reta);
+                       if (j < IX_NRETA) {
+                               IXGBE_WRITE_REG(hw, IXGBE_RETA(j), reta);
+                       } else {
+                               IXGBE_WRITE_REG(hw, IXGBE_ERETA(j - IX_NRETA),
+                                   reta);
+                       }
                }
 
                /*
@@ -2857,10 +2933,12 @@ ix_enable_intr(struct ix_softc *sc)
        if (hw->device_id == IXGBE_DEV_ID_82598AT)
                sc->intr_mask |= IXGBE_EIMS_GPI_SDP1;
 
-       switch (sc->hw.mac.type) {
+       switch (hw->mac.type) {
        case ixgbe_mac_82599EB:
                sc->intr_mask |= IXGBE_EIMS_ECC;
+               /* Temperature sensor on some adapters */
                sc->intr_mask |= IXGBE_EIMS_GPI_SDP0;
+               /* SFP+ (RX_LOS_N & MOD_ABS_N) */
                sc->intr_mask |= IXGBE_EIMS_GPI_SDP1;
                sc->intr_mask |= IXGBE_EIMS_GPI_SDP2;
                break;
@@ -2871,6 +2949,18 @@ ix_enable_intr(struct ix_softc *sc)
                fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM);
                if (fwsm & IXGBE_FWSM_TS_ENABLED)
                        sc->intr_mask |= IXGBE_EIMS_TS;
+               break;
+
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_a:
+       case ixgbe_mac_X550EM_x:
+               sc->intr_mask |= IXGBE_EIMS_ECC;
+               /* MAC thermal sensor is automatically enabled */
+               sc->intr_mask |= IXGBE_EIMS_TS;
+               /* Some devices use SDP0 for important information */
+               if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP ||
+                   hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T)
+                       sc->intr_mask |= IXGBE_EIMS_GPI_SDP0_BY_MAC(hw);
                /* FALL THROUGH */
        default:
                break;
@@ -2966,6 +3056,10 @@ ix_slot_info(struct ix_softc *sc)
        /* For most devices simply call the shared code routine */
        if (hw->device_id != IXGBE_DEV_ID_82599_SFP_SF_QP) {
                ixgbe_get_bus_info(hw);
+               /* These devices don't use PCI-E */
+               if (hw->mac.type == ixgbe_mac_X550EM_x ||
+                   hw->mac.type == ixgbe_mac_X550EM_a)
+                       return;
                goto display;
        }
 
@@ -3077,6 +3171,9 @@ ix_set_ivar(struct ix_softc *sc, uint8_t entry, uint8_t vector,
 
        case ixgbe_mac_82599EB:
        case ixgbe_mac_X540:
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_a:
+       case ixgbe_mac_X550EM_x:
                if (type == -1) { /* MISC IVAR */
                        index = (entry & 1) * 8;
                        ivar = IXGBE_READ_REG(hw, IXGBE_IVAR_MISC);
@@ -3090,7 +3187,7 @@ ix_set_ivar(struct ix_softc *sc, uint8_t entry, uint8_t vector,
                        ivar |= (vector << index);
                        IXGBE_WRITE_REG(hw, IXGBE_IVAR(entry >> 1), ivar);
                }
-
+               /* FALL THROUGH */
        default:
                break;
        }
@@ -3121,8 +3218,6 @@ ix_sfp_probe(struct ix_softc *sc)
 
                /* We now have supported optics */
                sc->sfp_probe = FALSE;
-               /* Set the optics type so system reports correctly */
-               ix_setup_optics(sc);
 
                return TRUE;
        }
@@ -3169,7 +3264,13 @@ ix_handle_msf(struct ix_softc *sc)
        struct ixgbe_hw *hw = &sc->hw;
        uint32_t autoneg;
 
-       autoneg = hw->phy.autoneg_advertised;
+       hw->phy.ops.identify_sfp(hw);
+       ix_init_media(sc);
+
+       if (sc->advspeed != IXGBE_LINK_SPEED_UNKNOWN)
+               autoneg = sc->advspeed;
+       else
+               autoneg = hw->phy.autoneg_advertised;
        if (!autoneg && hw->mac.ops.get_link_capabilities != NULL) {
                bool negotiate;
 
@@ -3179,6 +3280,23 @@ ix_handle_msf(struct ix_softc *sc)
                hw->mac.ops.setup_link(hw, autoneg, TRUE);
 }
 
+static void
+ix_handle_phy(struct ix_softc *sc)
+{
+       struct ixgbe_hw *hw = &sc->hw;
+       int error;
+
+       error = hw->phy.ops.handle_lasi(hw);
+       if (error == IXGBE_ERR_OVERTEMP) {
+               if_printf(&sc->arpcom.ac_if,
+                   "CRITICAL: EXTERNAL PHY OVER TEMP!!  "
+                   "PHY will downshift to lower power state!\n");
+       } else if (error) {
+               if_printf(&sc->arpcom.ac_if,
+                   "Error handling LASI interrupt: %d\n", error);
+       }
+}
+
 static void
 ix_update_stats(struct ix_softc *sc)
 {
@@ -3193,39 +3311,6 @@ ix_update_stats(struct ix_softc *sc)
        sc->stats.errbc += IXGBE_READ_REG(hw, IXGBE_ERRBC);
        sc->stats.mspdc += IXGBE_READ_REG(hw, IXGBE_MSPDC);
 
-       /*
-        * Note: These are for the 8 possible traffic classes, which
-        * in current implementation is unused, therefore only 0 should
-        * read real data.
-        */
-       for (i = 0; i < 8; i++) {
-               uint32_t mp;
-
-               mp = IXGBE_READ_REG(hw, IXGBE_MPC(i));
-               /* missed_rx tallies misses for the gprc workaround */
-               missed_rx += mp;
-               /* global total per queue */
-               sc->stats.mpc[i] += mp;
-
-               /* Running comprehensive total for stats display */
-               total_missed_rx += sc->stats.mpc[i];
-
-               if (hw->mac.type == ixgbe_mac_82598EB) {
-                       sc->stats.rnbc[i] += IXGBE_READ_REG(hw, IXGBE_RNBC(i));
-                       sc->stats.qbtc[i] += IXGBE_READ_REG(hw, IXGBE_QBTC(i));
-                       sc->stats.qbrc[i] += IXGBE_READ_REG(hw, IXGBE_QBRC(i));
-                       sc->stats.pxonrxc[i] +=
-                           IXGBE_READ_REG(hw, IXGBE_PXONRXC(i));
-               } else {
-                       sc->stats.pxonrxc[i] +=
-                           IXGBE_READ_REG(hw, IXGBE_PXONRXCNT(i));
-               }
-               sc->stats.pxontxc[i] += IXGBE_READ_REG(hw, IXGBE_PXONTXC(i));
-               sc->stats.pxofftxc[i] += IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(i));
-               sc->stats.pxoffrxc[i] += IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i));
-               sc->stats.pxon2offc[i] +=
-                   IXGBE_READ_REG(hw, IXGBE_PXON2OFFCNT(i));
-       }
        for (i = 0; i < 16; i++) {
                sc->stats.qprc[i] += IXGBE_READ_REG(hw, IXGBE_QPRC(i));
                sc->stats.qptc[i] += IXGBE_READ_REG(hw, IXGBE_QPTC(i));
@@ -3532,80 +3617,6 @@ ix_disable_rx_drop(struct ix_softc *sc)
        }
 }
 
-#ifdef foo
-/* XXX not working properly w/ 82599 connected w/ DAC */
-/* XXX only work after the interface is up */
-static int
-ix_sysctl_advspeed(SYSCTL_HANDLER_ARGS)
-{
-       struct ix_softc *sc = (struct ix_softc *)arg1;
-       struct ifnet *ifp = &sc->arpcom.ac_if;
-       struct ixgbe_hw *hw = &sc->hw;
-       ixgbe_link_speed speed;
-       int error, advspeed;
-
-       advspeed = sc->advspeed;
-       error = sysctl_handle_int(oidp, &advspeed, 0, req);
-       if (error || req->newptr == NULL)
-               return error;
-
-       if (!(hw->phy.media_type == ixgbe_media_type_copper ||
-           hw->phy.multispeed_fiber))
-               return EOPNOTSUPP;
-       if (hw->mac.ops.setup_link == NULL)
-               return EOPNOTSUPP;
-
-       switch (advspeed) {
-       case 0: /* auto */
-               speed = IXGBE_LINK_SPEED_UNKNOWN;
-               break;
-
-       case 1: /* 1Gb */
-               speed = IXGBE_LINK_SPEED_1GB_FULL;
-               break;
-
-       case 2: /* 100Mb */
-               speed = IXGBE_LINK_SPEED_100_FULL;
-               break;
-
-       case 3: /* 1Gb/10Gb */
-               speed = IXGBE_LINK_SPEED_1GB_FULL |
-                   IXGBE_LINK_SPEED_10GB_FULL;
-               break;
-
-       default:
-               return EINVAL;
-       }
-
-       ifnet_serialize_all(ifp);
-
-       if (sc->advspeed == advspeed) /* no change */
-               goto done;
-
-       if ((speed & IXGBE_LINK_SPEED_100_FULL) &&
-           hw->mac.type != ixgbe_mac_X540) {
-               error = EOPNOTSUPP;
-               goto done;
-       }
-
-       sc->advspeed = advspeed;
-
-       if ((ifp->if_flags & IFF_RUNNING) == 0)
-               goto done;
-
-       if (speed == IXGBE_LINK_SPEED_UNKNOWN) {
-               ix_config_link(sc);
-       } else {
-               hw->mac.autotry_restart = TRUE;
-               hw->mac.ops.setup_link(hw, speed, sc->link_up);
-       }
-
-done:
-       ifnet_deserialize_all(ifp);
-       return error;
-}
-#endif
-
 static void
 ix_setup_serialize(struct ix_softc *sc)
 {
@@ -4053,19 +4064,6 @@ do { \
        }
 #endif
 
-#ifdef foo
-       /*
-        * Allow a kind of speed control by forcing the autoneg
-        * advertised speed list to only a certain value, this
-        * supports 1G on 82599 devices, and 100Mb on X540.
-        */
-       SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree),
-           OID_AUTO, "advspeed", CTLTYPE_INT | CTLFLAG_RW,
-           sc, 0, ix_sysctl_advspeed, "I",
-           "advertised link speed, "
-           "0 - auto, 1 - 1Gb, 2 - 100Mb, 3 - 1Gb/10Gb");
-#endif
-
 #if 0
        ix_add_hw_stats(sc);
 #endif
@@ -4737,22 +4735,37 @@ ix_intr_status(struct ix_softc *sc, uint32_t eicr)
        if (hw->mac.type != ixgbe_mac_82598EB) {
                if (eicr & IXGBE_EICR_ECC)
                        if_printf(&sc->arpcom.ac_if, "ECC ERROR!!  Reboot!!\n");
-               else if (eicr & IXGBE_EICR_GPI_SDP1)
+
+               /* Check for over temp condition */
+               if (eicr & IXGBE_EICR_TS) {
+                       if_printf(&sc->arpcom.ac_if, "CRITICAL: OVER TEMP!!  "
+                           "PHY IS SHUT DOWN!!  Shutdown!!\n");
+               }
+       }
+
+       if (ix_is_sfp(hw)) {
+               uint32_t mod_mask;
+
+               /* Pluggable optics-related interrupt */
+               if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP)
+                       mod_mask = IXGBE_EICR_GPI_SDP0_X540;
+               else
+                       mod_mask = IXGBE_EICR_GPI_SDP2_BY_MAC(hw);
+               if (eicr & IXGBE_EICR_GPI_SDP1_BY_MAC(hw))
                        ix_handle_msf(sc);
-               else if (eicr & IXGBE_EICR_GPI_SDP2)
+               else if (eicr & mod_mask)
                        ix_handle_mod(sc);
-       } 
+       }
 
        /* Check for fan failure */
        if (hw->device_id == IXGBE_DEV_ID_82598AT &&
            (eicr & IXGBE_EICR_GPI_SDP1))
                if_printf(&sc->arpcom.ac_if, "FAN FAILURE!!  Replace!!\n");
 
-       /* Check for over temp condition */
-       if (hw->mac.type == ixgbe_mac_X540 && (eicr & IXGBE_EICR_TS)) {
-               if_printf(&sc->arpcom.ac_if, "OVER TEMP!!  "
-                   "PHY IS SHUT DOWN!!  Reboot\n");
-       }
+       /* External PHY interrupt */
+       if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T &&
+           (eicr & IXGBE_EICR_GPI_SDP0_X540))
+               ix_handle_phy(sc);
 }
 
 static void
@@ -5011,3 +5024,237 @@ ix_fc2str(enum ixgbe_fc_mode fc)
                return IFM_ETH_FC_NONE;
        }
 }
+
+static int
+ix_powerdown(struct ix_softc *sc)
+{
+       struct ixgbe_hw *hw = &sc->hw;
+       int error = 0;
+
+       /* Limit power managment flow to X550EM baseT */
+       if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T &&
+           hw->phy.ops.enter_lplu) {
+               /* Turn off support for APM wakeup. (Using ACPI instead) */
+               IXGBE_WRITE_REG(hw, IXGBE_GRC,
+                   IXGBE_READ_REG(hw, IXGBE_GRC) & ~(uint32_t)2);
+
+               /*
+                * Clear Wake Up Status register to prevent any previous wakeup
+                * events from waking us up immediately after we suspend.
+                */
+               IXGBE_WRITE_REG(hw, IXGBE_WUS, 0xffffffff);
+
+               /*
+                * Program the Wakeup Filter Control register with user filter
+                * settings
+                */
+               IXGBE_WRITE_REG(hw, IXGBE_WUFC, sc->wufc);
+
+               /* Enable wakeups and power management in Wakeup Control */
+               IXGBE_WRITE_REG(hw, IXGBE_WUC,
+                   IXGBE_WUC_WKEN | IXGBE_WUC_PME_EN);
+
+               /* X550EM baseT adapters need a special LPLU flow */
+               hw->phy.reset_disable = true;
+               ix_stop(sc);
+               error = hw->phy.ops.enter_lplu(hw);
+               if (error) {
+                       if_printf(&sc->arpcom.ac_if,
+                           "Error entering LPLU: %d\n", error);
+               }
+               hw->phy.reset_disable = false;
+       } else {
+               /* Just stop for other adapters */
+               ix_stop(sc);
+       }
+       return error;
+}
+
+static void
+ix_config_flowctrl(struct ix_softc *sc)
+{
+       struct ixgbe_hw *hw = &sc->hw;
+       uint32_t rxpb, frame, size, tmp;
+
+       frame = sc->max_frame_size;
+
+       /* Calculate High Water */
+       switch (hw->mac.type) {
+       case ixgbe_mac_X540:
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_a:
+       case ixgbe_mac_X550EM_x:
+               tmp = IXGBE_DV_X540(frame, frame);
+               break;
+       default:
+               tmp = IXGBE_DV(frame, frame);
+               break;
+       }
+       size = IXGBE_BT2KB(tmp);
+       rxpb = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)) >> 10;
+       hw->fc.high_water[0] = rxpb - size;
+
+       /* Now calculate Low Water */
+       switch (hw->mac.type) {
+       case ixgbe_mac_X540:
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_a:
+       case ixgbe_mac_X550EM_x:
+               tmp = IXGBE_LOW_DV_X540(frame);
+               break;
+       default:
+               tmp = IXGBE_LOW_DV(frame);
+               break;
+       }
+       hw->fc.low_water[0] = IXGBE_BT2KB(tmp);
+
+       hw->fc.requested_mode = ix_ifmedia2fc(sc->ifm_media);
+       if (sc->ifm_media & IFM_ETH_FORCEPAUSE)
+               hw->fc.disable_fc_autoneg = TRUE;
+       else
+               hw->fc.disable_fc_autoneg = FALSE;
+       hw->fc.pause_time = IX_FC_PAUSE;
+       hw->fc.send_xon = TRUE;
+}
+
+static void
+ix_config_dmac(struct ix_softc *sc)
+{
+       struct ixgbe_hw *hw = &sc->hw;
+       struct ixgbe_dmac_config *dcfg = &hw->mac.dmac_config;
+
+       if (hw->mac.type < ixgbe_mac_X550 || !hw->mac.ops.dmac_config)
+               return;
+
+       if ((dcfg->watchdog_timer ^ sc->dmac) ||
+           (dcfg->link_speed ^ sc->link_speed)) {
+               dcfg->watchdog_timer = sc->dmac;
+               dcfg->fcoe_en = false;
+               dcfg->link_speed = sc->link_speed;
+               dcfg->num_tcs = 1;
+
+               if (bootverbose) {
+                       if_printf(&sc->arpcom.ac_if, "dmac settings: "
+                           "watchdog %d, link speed %d\n",
+                           dcfg->watchdog_timer, dcfg->link_speed);
+               }
+
+               hw->mac.ops.dmac_config(hw);
+       }
+}
+
+static void
+ix_init_media(struct ix_softc *sc)
+{
+       struct ixgbe_hw *hw = &sc->hw;
+       int layer, msf_ifm = IFM_NONE;
+
+       ifmedia_removeall(&sc->media);
+
+       layer = ixgbe_get_supported_physical_layer(hw);
+
+       /*
+        * Media types with matching DragonFlyBSD media defines
+        */
+       if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T) {
+               ifmedia_add_nodup(&sc->media, IFM_ETHER | IFM_10G_T | IFM_FDX,
+                   0, NULL);
+       }
+       if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_T) {
+               ifmedia_add_nodup(&sc->media, IFM_ETHER | IFM_1000_T | IFM_FDX,
+                   0, NULL);
+       }
+       if (layer & IXGBE_PHYSICAL_LAYER_100BASE_TX) {
+               ifmedia_add_nodup(&sc->media, IFM_ETHER | IFM_100_TX | IFM_FDX,
+                   0, NULL);
+               /* No half-duplex support */
+       }
+
+       if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LR) {
+               ifmedia_add_nodup(&sc->media, IFM_ETHER | IFM_10G_LR | IFM_FDX,
+                   0, NULL);
+               msf_ifm = IFM_1000_LX;
+       }
+       if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LRM) {
+               ifmedia_add_nodup(&sc->media, IFM_ETHER | IFM_10G_LRM | IFM_FDX,
+                   0, NULL);
+               msf_ifm = IFM_1000_LX;
+       }
+       if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR) {
+               ifmedia_add_nodup(&sc->media, IFM_ETHER | IFM_10G_SR | IFM_FDX,
+                   0, NULL);
+               msf_ifm = IFM_1000_SX;
+       }
+
+       /* Add media for multispeed fiber */
+       if (ix_is_sfp(hw) && hw->phy.multispeed_fiber && msf_ifm != IFM_NONE) {
+               uint32_t linkcap;
+               bool autoneg;
+
+               hw->mac.ops.get_link_capabilities(hw, &linkcap, &autoneg);
+               if (linkcap & IXGBE_LINK_SPEED_1GB_FULL)
+                       ifmedia_add_nodup(&sc->media,
+                           IFM_ETHER | msf_ifm | IFM_FDX, 0, NULL);
+       }
+
+       if ((layer & IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU) ||
+           (layer & IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA)) {
+               ifmedia_add_nodup(&sc->media,
+                   IFM_ETHER | IFM_10G_TWINAX | IFM_FDX, 0, NULL);
+       }
+       if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_CX4) {
+               ifmedia_add_nodup(&sc->media, IFM_ETHER | IFM_10G_CX4 | IFM_FDX,
+                   0, NULL);
+       }
+       if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX) {
+               ifmedia_add_nodup(&sc->media, IFM_ETHER | IFM_1000_SX | IFM_FDX,
+                   0, NULL);
+       }
+
+       /*
+        * XXX Other (no matching DragonFlyBSD media type):
+        * To workaround this, we'll assign these completely
+        * inappropriate media types.
+        */
+       if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) {
+               if_printf(&sc->arpcom.ac_if, "Media supported: 10GbaseKR\n");
+               if_printf(&sc->arpcom.ac_if, "10GbaseKR mapped to 10GbaseSR\n");
+               ifmedia_add_nodup(&sc->media, IFM_ETHER | IFM_10G_SR | IFM_FDX,
+                   0, NULL);
+       }
+       if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4) {
+               if_printf(&sc->arpcom.ac_if, "Media supported: 10GbaseKX4\n");
+               if_printf(&sc->arpcom.ac_if,
+                   "10GbaseKX4 mapped to 10GbaseCX4\n");
+               ifmedia_add_nodup(&sc->media, IFM_ETHER | IFM_10G_CX4 | IFM_FDX,
+                   0, NULL);
+       }
+       if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) {
+               if_printf(&sc->arpcom.ac_if, "Media supported: 1000baseKX\n");
+               if_printf(&sc->arpcom.ac_if,
+                   "1000baseKX mapped to 1000baseCX\n");
+               ifmedia_add_nodup(&sc->media, IFM_ETHER | IFM_1000_CX | IFM_FDX,
+                   0, NULL);
+       }
+       if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_BX) {
+               /* Someday, someone will care about you... */
+               if_printf(&sc->arpcom.ac_if,
+                   "Media supported: 1000baseBX, ignored\n");
+       }
+
+       /* XXX we probably don't need this */
+       if (hw->device_id == IXGBE_DEV_ID_82598AT) {
+               ifmedia_add_nodup(&sc->media,
+                   IFM_ETHER | IFM_1000_T | IFM_FDX, 0, NULL);
+       }
+
+       ifmedia_add_nodup(&sc->media, IFM_ETHER | IFM_AUTO, 0, NULL);
+
+       if (ifmedia_tryset(&sc->media, sc->ifm_media)) {
+               int flowctrl = (sc->ifm_media & IFM_ETH_FCMASK);
+
+               sc->advspeed = IXGBE_LINK_SPEED_UNKNOWN;
+               sc->ifm_media = IX_IFM_DEFAULT | flowctrl;
+               ifmedia_set(&sc->media, sc->ifm_media);
+       }
+}
index 3476b5d..069cf99 100644 (file)
 /* Alignment for rings */
 #define IX_DBA_ALIGN           128
 
-#define IX_MAX_FRAME_SIZE      0x3F00
+#define IX_MAX_FRAME_SIZE      9728
+#define IX_MTU_HDR             (ETHER_HDR_LEN + ETHER_CRC_LEN + EVL_ENCAPLEN)
+#define IX_MAX_MTU             (IX_MAX_FRAME_SIZE - IX_MTU_HDR)
+
 
 /* Flow control constants */
 #define IX_FC_PAUSE            0xFFFF
                                 key[(i) * IX_RSSRK_SIZE + 2] << 16 | \
                                 key[(i) * IX_RSSRK_SIZE + 3] << 24)
 #define IX_NRETA               32
+#define IX_NRETA_X550          128
 #define IX_RETA_SIZE           4
 
 /*
@@ -302,8 +306,7 @@ struct ix_softc {
        struct callout          timer;
        int                     timer_cpuid;
 
-       uint32_t                optics;
-       int                     ifm_flowctrl;   /* IFM_ETH_ */
+       int                     ifm_media;      /* IFM_ */
        uint32_t                link_speed;
        bool                    link_up;
        boolean_t               sfp_probe;      /* plyggable optics */
@@ -337,6 +340,8 @@ struct ix_softc {
 
        int                     if_flags;
        int                     advspeed;       /* advertised link speeds */
+       uint32_t                wufc;           /* power management */
+       uint16_t                dmac;           /* DMA coalescing */
        uint16_t                max_frame_size;
        int16_t                 sts_msix_vec;   /* status MSI-X vector */
 
index e32f270..39cded3 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2013, Intel Corporation 
+  Copyright (c) 2001-2014, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
 #include "ixgbe_common.h"
 #include "ixgbe_phy.h"
 
+#define IXGBE_82598_MAX_TX_QUEUES 32
+#define IXGBE_82598_MAX_RX_QUEUES 64
+#define IXGBE_82598_RAR_ENTRIES   16
+#define IXGBE_82598_MC_TBL_SIZE  128
+#define IXGBE_82598_VFT_TBL_SIZE 128
+#define IXGBE_82598_RX_PB_SIZE   512
+
 static s32 ixgbe_get_link_capabilities_82598(struct ixgbe_hw *hw,
                                             ixgbe_link_speed *speed,
                                             bool *autoneg);
@@ -121,47 +128,48 @@ s32 ixgbe_init_ops_82598(struct ixgbe_hw *hw)
        ret_val = ixgbe_init_ops_generic(hw);
 
        /* PHY */
-       phy->ops.init = &ixgbe_init_phy_ops_82598;
+       phy->ops.init = ixgbe_init_phy_ops_82598;
 
        /* MAC */
-       mac->ops.start_hw = &ixgbe_start_hw_82598;
-       mac->ops.enable_relaxed_ordering = &ixgbe_enable_relaxed_ordering_82598;
-       mac->ops.reset_hw = &ixgbe_reset_hw_82598;
-       mac->ops.get_media_type = &ixgbe_get_media_type_82598;
+       mac->ops.start_hw = ixgbe_start_hw_82598;
+       mac->ops.enable_relaxed_ordering = ixgbe_enable_relaxed_ordering_82598;
+       mac->ops.reset_hw = ixgbe_reset_hw_82598;
+       mac->ops.get_media_type = ixgbe_get_media_type_82598;
        mac->ops.get_supported_physical_layer =
-                               &ixgbe_get_supported_physical_layer_82598;
-       mac->ops.read_analog_reg8 = &ixgbe_read_analog_reg8_82598;
-       mac->ops.write_analog_reg8 = &ixgbe_write_analog_reg8_82598;
-       mac->ops.set_lan_id = &ixgbe_set_lan_id_multi_port_pcie_82598;
+                               ixgbe_get_supported_physical_layer_82598;
+       mac->ops.read_analog_reg8 = ixgbe_read_analog_reg8_82598;
+       mac->ops.write_analog_reg8 = ixgbe_write_analog_reg8_82598;
+       mac->ops.set_lan_id = ixgbe_set_lan_id_multi_port_pcie_82598;
+       mac->ops.enable_rx_dma = ixgbe_enable_rx_dma_82598;
 
        /* RAR, Multicast, VLAN */
-       mac->ops.set_vmdq = &ixgbe_set_vmdq_82598;
-       mac->ops.clear_vmdq = &ixgbe_clear_vmdq_82598;
-       mac->ops.set_vfta = &ixgbe_set_vfta_82598;
+       mac->ops.set_vmdq = ixgbe_set_vmdq_82598;
+       mac->ops.clear_vmdq = ixgbe_clear_vmdq_82598;
+       mac->ops.set_vfta = ixgbe_set_vfta_82598;
        mac->ops.set_vlvf = NULL;
-       mac->ops.clear_vfta = &ixgbe_clear_vfta_82598;
+       mac->ops.clear_vfta = ixgbe_clear_vfta_82598;
 
        /* Flow Control */
-       mac->ops.fc_enable = &ixgbe_fc_enable_82598;
-
-       mac->mcft_size          = 128;
-       mac->vft_size           = 128;
-       mac->num_rar_entries    = 16;
-       mac->rx_pb_size         = 512;
-       mac->max_tx_queues      = 32;
-       mac->max_rx_queues      = 64;
+       mac->ops.fc_enable = ixgbe_fc_enable_82598;
+
+       mac->mcft_size          = IXGBE_82598_MC_TBL_SIZE;
+       mac->vft_size           = IXGBE_82598_VFT_TBL_SIZE;
+       mac->num_rar_entries    = IXGBE_82598_RAR_ENTRIES;
+       mac->rx_pb_size         = IXGBE_82598_RX_PB_SIZE;
+       mac->max_rx_queues      = IXGBE_82598_MAX_RX_QUEUES;
+       mac->max_tx_queues      = IXGBE_82598_MAX_TX_QUEUES;
        mac->max_msix_vectors   = ixgbe_get_pcie_msix_count_generic(hw);
 
        /* SFP+ Module */
-       phy->ops.read_i2c_eeprom = &ixgbe_read_i2c_eeprom_82598;
-       phy->ops.read_i2c_sff8472 = &ixgbe_read_i2c_sff8472_82598;
+       phy->ops.read_i2c_eeprom = ixgbe_read_i2c_eeprom_82598;
+       phy->ops.read_i2c_sff8472 = ixgbe_read_i2c_sff8472_82598;
 
        /* Link */
-       mac->ops.check_link = &ixgbe_check_mac_link_82598;
-       mac->ops.setup_link = &ixgbe_setup_mac_link_82598;
+       mac->ops.check_link = ixgbe_check_mac_link_82598;
+       mac->ops.setup_link = ixgbe_setup_mac_link_82598;
        mac->ops.flap_tx_laser = NULL;
-       mac->ops.get_link_capabilities = &ixgbe_get_link_capabilities_82598;
-       mac->ops.setup_rxpba = &ixgbe_set_rxpba_82598;
+       mac->ops.get_link_capabilities = ixgbe_get_link_capabilities_82598;
+       mac->ops.setup_rxpba = ixgbe_set_rxpba_82598;
 
        /* Manageability interface */
        mac->ops.set_fw_drv_ver = NULL;
@@ -194,20 +202,20 @@ s32 ixgbe_init_phy_ops_82598(struct ixgbe_hw *hw)
 
        /* Overwrite the link function pointers if copper PHY */
        if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) {
-               mac->ops.setup_link = &ixgbe_setup_copper_link_82598;
+               mac->ops.setup_link = ixgbe_setup_copper_link_82598;
                mac->ops.get_link_capabilities =
-                               &ixgbe_get_copper_link_capabilities_generic;
+                               ixgbe_get_copper_link_capabilities_generic;
        }
 
        switch (hw->phy.type) {
        case ixgbe_phy_tn:
-               phy->ops.setup_link = &ixgbe_setup_phy_link_tnx;
-               phy->ops.check_link = &ixgbe_check_phy_link_tnx;
+               phy->ops.setup_link = ixgbe_setup_phy_link_tnx;
+               phy->ops.check_link = ixgbe_check_phy_link_tnx;
                phy->ops.get_firmware_version =
-                                       &ixgbe_get_phy_firmware_version_tnx;
+                                       ixgbe_get_phy_firmware_version_tnx;
                break;
        case ixgbe_phy_nl:
-               phy->ops.reset = &ixgbe_reset_phy_nl;
+               phy->ops.reset = ixgbe_reset_phy_nl;
 
                /* Call SFP+ identify routine to get the SFP+ module type */
                ret_val = phy->ops.identify_sfp(hw);
@@ -252,6 +260,8 @@ s32 ixgbe_start_hw_82598(struct ixgbe_hw *hw)
        DEBUGFUNC("ixgbe_start_hw_82598");
 
        ret_val = ixgbe_start_hw_generic(hw);
+       if (ret_val)
+               return ret_val;
 
        /* Disable relaxed ordering */
        for (i = 0; ((i < hw->mac.max_tx_queues) &&
@@ -270,8 +280,7 @@ s32 ixgbe_start_hw_82598(struct ixgbe_hw *hw)
        }
 
        /* set the completion timeout for interface */
-       if (ret_val == IXGBE_SUCCESS)
-               ixgbe_set_pcie_completion_timeout(hw);
+       ixgbe_set_pcie_completion_timeout(hw);
 
        return ret_val;
 }
@@ -1409,6 +1418,20 @@ static void ixgbe_set_rxpba_82598(struct ixgbe_hw *hw, int num_pb,
        /* Setup Tx packet buffer sizes */
        for (i = 0; i < IXGBE_MAX_PACKET_BUFFERS; i++)
                IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), IXGBE_TXPBSIZE_40KB);
+}
+
+/**
+ *  ixgbe_enable_rx_dma_82598 - Enable the Rx DMA unit
+ *  @hw: pointer to hardware structure
+ *  @regval: register value to write to RXCTRL
+ *
+ *  Enables the Rx DMA unit
+ **/
+s32 ixgbe_enable_rx_dma_82598(struct ixgbe_hw *hw, u32 regval)
+{
+       DEBUGFUNC("ixgbe_enable_rx_dma_82598");
 
-       return;
+       IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, regval);
+
+       return IXGBE_SUCCESS;
 }
index 16cd2ee..621be41 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2013, Intel Corporation 
+  Copyright (c) 2001-2014, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -49,4 +49,5 @@ u32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw);
 s32 ixgbe_init_phy_ops_82598(struct ixgbe_hw *hw);
 void ixgbe_set_lan_id_multi_port_pcie_82598(struct ixgbe_hw *hw);
 void ixgbe_set_pcie_completion_timeout(struct ixgbe_hw *hw);
+s32 ixgbe_enable_rx_dma_82598(struct ixgbe_hw *hw, u32 regval);
 #endif /* _IXGBE_82598_H_ */
index 3cc8cd7..d8acf83 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2013, Intel Corporation 
+  Copyright (c) 2001-2014, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
 #include "ixgbe_common.h"
 #include "ixgbe_phy.h"
 
+#define IXGBE_82599_MAX_TX_QUEUES 128
+#define IXGBE_82599_MAX_RX_QUEUES 128
+#define IXGBE_82599_RAR_ENTRIES   128
+#define IXGBE_82599_MC_TBL_SIZE   128
+#define IXGBE_82599_VFT_TBL_SIZE  128
+#define IXGBE_82599_RX_PB_SIZE   512
+
 static s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw,
                                         ixgbe_link_speed speed,
                                         bool autoneg_wait_to_complete);
@@ -46,25 +53,10 @@ static s32 ixgbe_read_eeprom_82599(struct ixgbe_hw *hw,
                                   u16 offset, u16 *data);
 static s32 ixgbe_read_eeprom_buffer_82599(struct ixgbe_hw *hw, u16 offset,
                                          u16 words, u16 *data);
-
-static bool ixgbe_mng_enabled(struct ixgbe_hw *hw)
-{
-       u32 fwsm, manc, factps;
-
-       fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM);
-       if ((fwsm & IXGBE_FWSM_MODE_MASK) != IXGBE_FWSM_FW_MODE_PT)
-               return FALSE;
-
-       manc = IXGBE_READ_REG(hw, IXGBE_MANC);
-       if (!(manc & IXGBE_MANC_RCV_TCO_EN))
-               return FALSE;
-
-       factps = IXGBE_READ_REG(hw, IXGBE_FACTPS);
-       if (factps & IXGBE_FACTPS_MNGCG)
-               return FALSE;
-
-       return TRUE;
-}
+static s32 ixgbe_read_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset,
+                                       u8 dev_addr, u8 *data);
+static s32 ixgbe_write_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset,
+                                       u8 dev_addr, u8 data);
 
 void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw)
 {
@@ -77,12 +69,12 @@ void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw)
         * and MNG not enabled
         */
        if ((mac->ops.get_media_type(hw) == ixgbe_media_type_fiber) &&
-           !hw->mng_fw_enabled) {
+           !ixgbe_mng_enabled(hw)) {
                mac->ops.disable_tx_laser =
-                                      &ixgbe_disable_tx_laser_multispeed_fiber;
+                                      ixgbe_disable_tx_laser_multispeed_fiber;
                mac->ops.enable_tx_laser =
-                                       &ixgbe_enable_tx_laser_multispeed_fiber;
-               mac->ops.flap_tx_laser = &ixgbe_flap_tx_laser_multispeed_fiber;
+                                       ixgbe_enable_tx_laser_multispeed_fiber;
+               mac->ops.flap_tx_laser = ixgbe_flap_tx_laser_multispeed_fiber;
 
        } else {
                mac->ops.disable_tx_laser = NULL;
@@ -92,15 +84,21 @@ void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw)
 
        if (hw->phy.multispeed_fiber) {
                /* Set up dual speed SFP+ support */
-               mac->ops.setup_link = &ixgbe_setup_mac_link_multispeed_fiber;
+               mac->ops.setup_link = ixgbe_setup_mac_link_multispeed_fiber;
+               mac->ops.setup_mac_link = ixgbe_setup_mac_link_82599;
+               mac->ops.set_rate_select_speed =
+                                              ixgbe_set_hard_rate_select_speed;
+               if (ixgbe_get_media_type(hw) == ixgbe_media_type_fiber_fixed)
+                       mac->ops.set_rate_select_speed =
+                                              ixgbe_set_soft_rate_select_speed;
        } else {
                if ((ixgbe_get_media_type(hw) == ixgbe_media_type_backplane) &&
                     (hw->phy.smart_speed == ixgbe_smart_speed_auto ||
                      hw->phy.smart_speed == ixgbe_smart_speed_on) &&
                      !ixgbe_verify_lesm_fw_enabled_82599(hw)) {
-                       mac->ops.setup_link = &ixgbe_setup_mac_link_smartspeed;
+                       mac->ops.setup_link = ixgbe_setup_mac_link_smartspeed;
                } else {
-                       mac->ops.setup_link = &ixgbe_setup_mac_link_82599;
+                       mac->ops.setup_link = ixgbe_setup_mac_link_82599;
                }
        }
 }
@@ -119,9 +117,27 @@ s32 ixgbe_init_phy_ops_82599(struct ixgbe_hw *hw)
        struct ixgbe_mac_info *mac = &hw->mac;
        struct ixgbe_phy_info *phy = &hw->phy;
        s32 ret_val = IXGBE_SUCCESS;
+       u32 esdp;
 
        DEBUGFUNC("ixgbe_init_phy_ops_82599");
 
+       if (hw->device_id == IXGBE_DEV_ID_82599_QSFP_SF_QP) {
+               /* Store flag indicating I2C bus access control unit. */
+               hw->phy.qsfp_shared_i2c_bus = TRUE;
+
+               /* Initialize access to QSFP+ I2C bus */
+               esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
+               esdp |= IXGBE_ESDP_SDP0_DIR;
+               esdp &= ~IXGBE_ESDP_SDP1_DIR;
+               esdp &= ~IXGBE_ESDP_SDP0;
+               esdp &= ~IXGBE_ESDP_SDP0_NATIVE;
+               esdp &= ~IXGBE_ESDP_SDP1_NATIVE;
+               IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
+               IXGBE_WRITE_FLUSH(hw);
+
+               phy->ops.read_i2c_byte = ixgbe_read_i2c_byte_82599;
+               phy->ops.write_i2c_byte = ixgbe_write_i2c_byte_82599;
+       }
        /* Identify the PHY or SFP module */
        ret_val = phy->ops.identify(hw);
        if (ret_val == IXGBE_ERR_SFP_NOT_SUPPORTED)
@@ -134,18 +150,18 @@ s32 ixgbe_init_phy_ops_82599(struct ixgbe_hw *hw)
 
        /* If copper media, overwrite with copper function pointers */
        if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) {
-               mac->ops.setup_link = &ixgbe_setup_copper_link_82599;
+               mac->ops.setup_link = ixgbe_setup_copper_link_82599;
                mac->ops.get_link_capabilities =
-                                 &ixgbe_get_copper_link_capabilities_generic;
+                                 ixgbe_get_copper_link_capabilities_generic;
        }
 
-       /* Set necessary function pointers based on phy type */
+       /* Set necessary function pointers based on PHY type */
        switch (hw->phy.type) {
        case ixgbe_phy_tn:
-               phy->ops.setup_link = &ixgbe_setup_phy_link_tnx;
-               phy->ops.check_link = &ixgbe_check_phy_link_tnx;
+               phy->ops.setup_link = ixgbe_setup_phy_link_tnx;
+               phy->ops.check_link = ixgbe_check_phy_link_tnx;
                phy->ops.get_firmware_version =
-                            &ixgbe_get_phy_firmware_version_tnx;
+                            ixgbe_get_phy_firmware_version_tnx;
                break;
        default:
                break;
@@ -158,7 +174,6 @@ s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw)
 {
        s32 ret_val = IXGBE_SUCCESS;
        u16 list_offset, data_offset, data_value;
-       bool got_lock = FALSE;
 
        DEBUGFUNC("ixgbe_setup_sfp_modules_82599");
 
@@ -191,35 +206,15 @@ s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw)
 
                /* Release the semaphore */
                hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
-               /* Delay obtaining semaphore again to allow FW access */
-               msec_delay(hw->eeprom.semaphore_delay);
-
-               /* Need SW/FW semaphore around AUTOC writes if LESM on,
-                * likewise reset_pipeline requires lock as it also writes
-                * AUTOC.
+               /* Delay obtaining semaphore again to allow FW access
+                * prot_autoc_write uses the semaphore too.
                 */
-               if (ixgbe_verify_lesm_fw_enabled_82599(hw)) {
-                       ret_val = hw->mac.ops.acquire_swfw_sync(hw,
-                                                       IXGBE_GSSR_MAC_CSR_SM);
-                       if (ret_val != IXGBE_SUCCESS) {
-                               ret_val = IXGBE_ERR_SWFW_SYNC;
-                               goto setup_sfp_out;
-                       }
-
-                       got_lock = TRUE;
-               }
+               msec_delay(hw->eeprom.semaphore_delay);
 
                /* Restart DSP and set SFI mode */
-               IXGBE_WRITE_REG(hw, IXGBE_AUTOC, ((hw->mac.orig_autoc) |
-                               IXGBE_AUTOC_LMS_10G_SERIAL));
-               hw->mac.cached_autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
-               ret_val = ixgbe_reset_pipeline_82599(hw);
-
-               if (got_lock) {
-                       hw->mac.ops.release_swfw_sync(hw,
-                                                     IXGBE_GSSR_MAC_CSR_SM);
-                       got_lock = FALSE;
-               }
+               ret_val = hw->mac.ops.prot_autoc_write(hw,
+                       hw->mac.orig_autoc | IXGBE_AUTOC_LMS_10G_SERIAL,
+                       FALSE);
 
                if (ret_val) {
                        DEBUGOUT("sfp module setup not complete\n");
@@ -242,6 +237,79 @@ setup_sfp_err:
        return IXGBE_ERR_PHY;
 }
 
+/**
+ *  prot_autoc_read_82599 - Hides MAC differences needed for AUTOC read
+ *  @hw: pointer to hardware structure
+ *  @locked: Return the if we locked for this read.
+ *  @reg_val: Value we read from AUTOC
+ *
+ *  For this part (82599) we need to wrap read-modify-writes with a possible
+ *  FW/SW lock.  It is assumed this lock will be freed with the next
+ *  prot_autoc_write_82599().
+ */
+s32 prot_autoc_read_82599(struct ixgbe_hw *hw, bool *locked, u32 *reg_val)
+{
+       s32 ret_val;
+
+       *locked = FALSE;
+        /* If LESM is on then we need to hold the SW/FW semaphore. */
+       if (ixgbe_verify_lesm_fw_enabled_82599(hw)) {
+               ret_val = hw->mac.ops.acquire_swfw_sync(hw,
+                                       IXGBE_GSSR_MAC_CSR_SM);
+               if (ret_val != IXGBE_SUCCESS)
+                       return IXGBE_ERR_SWFW_SYNC;
+
+               *locked = TRUE;
+       }
+
+       *reg_val = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+       return IXGBE_SUCCESS;
+}
+
+/**
+ * prot_autoc_write_82599 - Hides MAC differences needed for AUTOC write
+ * @hw: pointer to hardware structure
+ * @reg_val: value to write to AUTOC
+ * @locked: bool to indicate whether the SW/FW lock was already taken by
+ *           previous proc_autoc_read_82599.
+ *
+ * This part (82599) may need to hold the SW/FW lock around all writes to
+ * AUTOC. Likewise after a write we need to do a pipeline reset.
+ */
+s32 prot_autoc_write_82599(struct ixgbe_hw *hw, u32 autoc, bool locked)
+{
+       s32 ret_val = IXGBE_SUCCESS;
+
+       /* Blocked by MNG FW so bail */
+       if (ixgbe_check_reset_blocked(hw))
+               goto out;
+
+       /* We only need to get the lock if:
+        *  - We didn't do it already (in the read part of a read-modify-write)
+        *  - LESM is enabled.
+        */
+       if (!locked && ixgbe_verify_lesm_fw_enabled_82599(hw)) {
+               ret_val = hw->mac.ops.acquire_swfw_sync(hw,
+                                       IXGBE_GSSR_MAC_CSR_SM);
+               if (ret_val != IXGBE_SUCCESS)
+                       return IXGBE_ERR_SWFW_SYNC;
+
+               locked = TRUE;
+       }
+
+       IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc);
+       ret_val = ixgbe_reset_pipeline_82599(hw);
+
+out:
+       /* Free the SW/FW semaphore as we either grabbed it here or
+        * already had it when this function was called.
+        */
+       if (locked)
+               hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
+
+       return ret_val;
+}
+
 /**
  *  ixgbe_init_ops_82599 - Inits func ptrs and MAC type
  *  @hw: pointer to hardware structure
@@ -263,53 +331,55 @@ s32 ixgbe_init_ops_82599(struct ixgbe_hw *hw)
        ret_val = ixgbe_init_ops_generic(hw);
 
        /* PHY */
-       phy->ops.identify = &ixgbe_identify_phy_82599;
-       phy->ops.init = &ixgbe_init_phy_ops_82599;
+       phy->ops.identify = ixgbe_identify_phy_82599;
+       phy->ops.init = ixgbe_init_phy_ops_82599;
 
        /* MAC */
-       mac->ops.reset_hw = &ixgbe_reset_hw_82599;
-       mac->ops.enable_relaxed_ordering = &ixgbe_enable_relaxed_ordering_gen2;
-       mac->ops.get_media_type = &ixgbe_get_media_type_82599;
+       mac->ops.reset_hw = ixgbe_reset_hw_82599;
+       mac->ops.enable_relaxed_ordering = ixgbe_enable_relaxed_ordering_gen2;
+       mac->ops.get_media_type = ixgbe_get_media_type_82599;
        mac->ops.get_supported_physical_layer =
-                                   &ixgbe_get_supported_physical_layer_82599;
-       mac->ops.disable_sec_rx_path = &ixgbe_disable_sec_rx_path_generic;
-       mac->ops.enable_sec_rx_path = &ixgbe_enable_sec_rx_path_generic;
-       mac->ops.enable_rx_dma = &ixgbe_enable_rx_dma_82599;
-       mac->ops.read_analog_reg8 = &ixgbe_read_analog_reg8_82599;
-       mac->ops.write_analog_reg8 = &ixgbe_write_analog_reg8_82599;
-       mac->ops.start_hw = &ixgbe_start_hw_82599;
-       mac->ops.get_san_mac_addr = &ixgbe_get_san_mac_addr_generic;
-       mac->ops.set_san_mac_addr = &ixgbe_set_san_mac_addr_generic;
-       mac->ops.get_device_caps = &ixgbe_get_device_caps_generic;
-       mac->ops.get_wwn_prefix = &ixgbe_get_wwn_prefix_generic;
-       mac->ops.get_fcoe_boot_status = &ixgbe_get_fcoe_boot_status_generic;
+                                   ixgbe_get_supported_physical_layer_82599;
+       mac->ops.disable_sec_rx_path = ixgbe_disable_sec_rx_path_generic;
+       mac->ops.enable_sec_rx_path = ixgbe_enable_sec_rx_path_generic;
+       mac->ops.enable_rx_dma = ixgbe_enable_rx_dma_82599;
+       mac->ops.read_analog_reg8 = ixgbe_read_analog_reg8_82599;
+       mac->ops.write_analog_reg8 = ixgbe_write_analog_reg8_82599;
+       mac->ops.start_hw = ixgbe_start_hw_82599;
+       mac->ops.get_san_mac_addr = ixgbe_get_san_mac_addr_generic;
+       mac->ops.set_san_mac_addr = ixgbe_set_san_mac_addr_generic;
+       mac->ops.get_device_caps = ixgbe_get_device_caps_generic;
+       mac->ops.get_wwn_prefix = ixgbe_get_wwn_prefix_generic;
+       mac->ops.get_fcoe_boot_status = ixgbe_get_fcoe_boot_status_generic;
+       mac->ops.prot_autoc_read = prot_autoc_read_82599;
+       mac->ops.prot_autoc_write = prot_autoc_write_82599;
 
        /* 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->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;
-       mac->ops.set_vfta = &ixgbe_set_vfta_generic;
-       mac->ops.set_vlvf = &ixgbe_set_vlvf_generic;
-       mac->ops.clear_vfta = &ixgbe_clear_vfta_generic;
-       mac->ops.init_uta_tables = &ixgbe_init_uta_tables_generic;
-       mac->ops.setup_sfp = &ixgbe_setup_sfp_modules_82599;
-       mac->ops.set_mac_anti_spoofing = &ixgbe_set_mac_anti_spoofing;
-       mac->ops.set_vlan_anti_spoofing = &ixgbe_set_vlan_anti_spoofing;
+       mac->ops.set_vfta = ixgbe_set_vfta_generic;
+       mac->ops.set_vlvf = ixgbe_set_vlvf_generic;
+       mac->ops.clear_vfta = ixgbe_clear_vfta_generic;
+       mac->ops.init_uta_tables = ixgbe_init_uta_tables_generic;
+       mac->ops.setup_sfp = ixgbe_setup_sfp_modules_82599;
+       mac->ops.set_mac_anti_spoofing = ixgbe_set_mac_anti_spoofing;
+       mac->ops.set_vlan_anti_spoofing = ixgbe_set_vlan_anti_spoofing;
 
        /* Link */
-       mac->ops.get_link_capabilities = &ixgbe_get_link_capabilities_82599;
-       mac->ops.check_link = &ixgbe_check_mac_link_generic;
-       mac->ops.setup_rxpba = &ixgbe_set_rxpba_generic;
+       mac->ops.get_link_capabilities = ixgbe_get_link_capabilities_82599;
+       mac->ops.check_link = ixgbe_check_mac_link_generic;
+       mac->ops.setup_rxpba = ixgbe_set_rxpba_generic;
        ixgbe_init_mac_link_ops_82599(hw);
 
-       mac->mcft_size          = 128;
-       mac->vft_size           = 128;
-       mac->num_rar_entries    = 128;
-       mac->rx_pb_size         = 512;
-       mac->max_tx_queues      = 128;
-       mac->max_rx_queues      = 128;
+       mac->mcft_size          = IXGBE_82599_MC_TBL_SIZE;
+       mac->vft_size           = IXGBE_82599_VFT_TBL_SIZE;
+       mac->num_rar_entries    = IXGBE_82599_RAR_ENTRIES;
+       mac->rx_pb_size         = IXGBE_82599_RX_PB_SIZE;
+       mac->max_rx_queues      = IXGBE_82599_MAX_RX_QUEUES;
+       mac->max_tx_queues      = IXGBE_82599_MAX_TX_QUEUES;
        mac->max_msix_vectors   = ixgbe_get_pcie_msix_count_generic(hw);
 
        mac->arc_subsystem_valid = (IXGBE_READ_REG(hw, IXGBE_FWSM) &
@@ -318,17 +388,14 @@ s32 ixgbe_init_ops_82599(struct ixgbe_hw *hw)
        hw->mbx.ops.init_params = ixgbe_init_mbx_params_pf;
 
        /* EEPROM */
-       eeprom->ops.read = &ixgbe_read_eeprom_82599;
-       eeprom->ops.read_buffer = &ixgbe_read_eeprom_buffer_82599;
+       eeprom->ops.read = ixgbe_read_eeprom_82599;
+       eeprom->ops.read_buffer = ixgbe_read_eeprom_buffer_82599;
 
        /* Manageability interface */
-       mac->ops.set_fw_drv_ver = &ixgbe_set_fw_drv_ver_generic;
-
+       mac->ops.set_fw_drv_ver = ixgbe_set_fw_drv_ver_generic;
 
-       mac->ops.get_rtrup2tc = &ixgbe_dcb_get_rtrup2tc_generic;
 
-       /* Cache if MNG FW is up */
-       hw->mng_fw_enabled = ixgbe_mng_enabled(hw);
+       mac->ops.get_rtrup2tc = ixgbe_dcb_get_rtrup2tc_generic;
 
        return ret_val;
 }
@@ -354,6 +421,8 @@ s32 ixgbe_get_link_capabilities_82599(struct ixgbe_hw *hw,
        /* 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_lx_core0 ||
+           hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_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;
@@ -429,7 +498,14 @@ s32 ixgbe_get_link_capabilities_82599(struct ixgbe_hw *hw,
        if (hw->phy.multispeed_fiber) {
                *speed |= IXGBE_LINK_SPEED_10GB_FULL |
                          IXGBE_LINK_SPEED_1GB_FULL;
-               *autoneg = TRUE;
+
+               /* QSFP must not enable full auto-negotiation
+                * Limited autoneg is enabled at 1G
+                */
+               if (hw->phy.media_type == ixgbe_media_type_fiber_qsfp)
+                       *autoneg = FALSE;
+               else
+                       *autoneg = TRUE;
        }
 
 out:
@@ -482,6 +558,9 @@ enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw)
        case IXGBE_DEV_ID_82599_T3_LOM:
                media_type = ixgbe_media_type_copper;
                break;
+       case IXGBE_DEV_ID_82599_QSFP_SF_QP:
+               media_type = ixgbe_media_type_fiber_qsfp;
+               break;
        case IXGBE_DEV_ID_82599_BYPASS:
                media_type = ixgbe_media_type_fiber_fixed;
                hw->phy.multispeed_fiber = TRUE;
@@ -509,8 +588,8 @@ void ixgbe_stop_mac_link_on_d3_82599(struct ixgbe_hw *hw)
        DEBUGFUNC("ixgbe_stop_mac_link_on_d3_82599");
        ixgbe_read_eeprom(hw, IXGBE_EEPROM_CTRL_2, &ee_ctrl_2);
 
-       if (!hw->mng_fw_enabled && !hw->wol_enabled &&
-               ee_ctrl_2 & IXGBE_EEPROM_CCD_BIT) {
+       if (!ixgbe_mng_present(hw) && !hw->wol_enabled &&
+           ee_ctrl_2 & IXGBE_EEPROM_CCD_BIT) {
                autoc2_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
                autoc2_reg |= IXGBE_AUTOC2_LINK_DISABLE_ON_D3_MASK;
                IXGBE_WRITE_REG(hw, IXGBE_AUTOC2, autoc2_reg);
@@ -597,7 +676,11 @@ void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
 {
        u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
 
-       /* Disable tx laser; allow 100us to go dark per spec */
+       /* Blocked by MNG FW so bail */
+       if (ixgbe_check_reset_blocked(hw))
+               return;
+
+       /* Disable Tx laser; allow 100us to go dark per spec */
        esdp_reg |= IXGBE_ESDP_SDP3;
        IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
        IXGBE_WRITE_FLUSH(hw);
@@ -616,7 +699,7 @@ void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
 {
        u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
 
-       /* Enable tx laser; allow 100ms to light up */
+       /* Enable Tx laser; allow 100ms to light up */
        esdp_reg &= ~IXGBE_ESDP_SDP3;
        IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
        IXGBE_WRITE_FLUSH(hw);
@@ -630,7 +713,7 @@ void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
  *  When the driver changes the link speeds that it can support,
  *  it sets autotry_restart to TRUE to indicate that we need to
  *  initiate a new autotry session with the link partner.  To do
- *  so, we set the speed then disable and re-enable the tx laser, to
+ *  so, we set the speed then disable and re-enable the Tx laser, to
  *  alert the link partner that it also needs to restart autotry on its
  *  end.  This is consistent with TRUE clause 37 autoneg, which also
  *  involves a loss of signal.
@@ -639,6 +722,10 @@ void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
 {
        DEBUGFUNC("ixgbe_flap_tx_laser_multispeed_fiber");
 
+       /* Blocked by MNG FW so bail */
+       if (ixgbe_check_reset_blocked(hw))
+               return;
+
        if (hw->mac.autotry_restart) {
                ixgbe_disable_tx_laser_multispeed_fiber(hw);
                ixgbe_enable_tx_laser_multispeed_fiber(hw);
@@ -647,229 +734,32 @@ void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
 }
 
 /**
- *  ixgbe_set_fiber_fixed_speed - Set module link speed for fixed fiber
+ *  ixgbe_set_hard_rate_select_speed - Set module link speed
  *  @hw: pointer to hardware structure
  *  @speed: link speed to set
  *
- *  We set the module speed differently for fixed fiber.  For other
- *  multi-speed devices we don't have an error value so here if we
- *  detect an error we just log it and exit.
+ *  Set module link speed via RS0/RS1 rate select pins.
  */
-static void ixgbe_set_fiber_fixed_speed(struct ixgbe_hw *hw,
+void ixgbe_set_hard_rate_select_speed(struct ixgbe_hw *hw,
                                        ixgbe_link_speed speed)
 {
-       s32 status;
-       u8 rs, eeprom_data;
+       u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
 
        switch (speed) {
        case IXGBE_LINK_SPEED_10GB_FULL:
-               /* one bit mask same as setting on */
-               rs = IXGBE_SFF_SOFT_RS_SELECT_10G;
+               esdp_reg |= (IXGBE_ESDP_SDP5_DIR | IXGBE_ESDP_SDP5);
                break;
        case IXGBE_LINK_SPEED_1GB_FULL:
-               rs = IXGBE_SFF_SOFT_RS_SELECT_1G;
+               esdp_reg &= ~IXGBE_ESDP_SDP5;
+               esdp_reg |= IXGBE_ESDP_SDP5_DIR;
                break;
        default:
                DEBUGOUT("Invalid fixed module speed\n");
                return;
        }
 
-       /* Set RS0 */
-       status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB,
-                                          IXGBE_I2C_EEPROM_DEV_ADDR2,
-                                          &eeprom_data);
-       if (status) {
-               DEBUGOUT("Failed to read Rx Rate Select RS0\n");
-               goto out;
-       }
-
-       eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) & rs;
-
-       status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB,
-                                           IXGBE_I2C_EEPROM_DEV_ADDR2,
-                                           eeprom_data);
-       if (status) {
-               DEBUGOUT("Failed to write Rx Rate Select RS0\n");
-               goto out;
-       }
-
-       /* Set RS1 */
-       status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_ESCB,
-                                          IXGBE_I2C_EEPROM_DEV_ADDR2,
-                                          &eeprom_data);
-       if (status) {
-               DEBUGOUT("Failed to read Rx Rate Select RS1\n");
-               goto out;
-       }
-
-       eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) & rs;
-
-       status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_ESCB,
-                                           IXGBE_I2C_EEPROM_DEV_ADDR2,
-                                           eeprom_data);
-       if (status) {
-               DEBUGOUT("Failed to write Rx Rate Select RS1\n");
-               goto out;
-       }
-out:
-       return;
-}
-
-/**
- *  ixgbe_setup_mac_link_multispeed_fiber - Set MAC link speed
- *  @hw: pointer to hardware structure
- *  @speed: new link speed
- *  @autoneg_wait_to_complete: TRUE when waiting for completion is needed
- *
- *  Set the link speed in the AUTOC register and restarts link.
- **/
-s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
-                                    ixgbe_link_speed speed,
-                                    bool autoneg_wait_to_complete)
-{
-       s32 status = IXGBE_SUCCESS;
-       ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN;
-       ixgbe_link_speed highest_link_speed = IXGBE_LINK_SPEED_UNKNOWN;
-       u32 speedcnt = 0;
-       u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
-       u32 i = 0;
-       bool autoneg, link_up = FALSE;
-
-       DEBUGFUNC("ixgbe_setup_mac_link_multispeed_fiber");
-
-       /* Mask off requested but non-supported speeds */
-       status = ixgbe_get_link_capabilities(hw, &link_speed, &autoneg);
-       if (status != IXGBE_SUCCESS)
-               return status;
-
-       speed &= link_speed;
-
-       /*
-        * Try each speed one by one, highest priority first.  We do this in
-        * software because 10gb fiber doesn't support speed autonegotiation.
-        */
-       if (speed & IXGBE_LINK_SPEED_10GB_FULL) {
-               speedcnt++;
-               highest_link_speed = IXGBE_LINK_SPEED_10GB_FULL;
-
-               /* If we already have link at this speed, just jump out */
-               status = ixgbe_check_link(hw, &link_speed, &link_up, FALSE);
-               if (status != IXGBE_SUCCESS)
-                       return status;
-
-               if ((link_speed == IXGBE_LINK_SPEED_10GB_FULL) && link_up)
-                       goto out;
-
-               /* Set the module link speed */
-               if (hw->phy.media_type == ixgbe_media_type_fiber_fixed) {
-                       ixgbe_set_fiber_fixed_speed(hw,
-                                                   IXGBE_LINK_SPEED_10GB_FULL);
-               } else {
-                       esdp_reg |= (IXGBE_ESDP_SDP5_DIR | IXGBE_ESDP_SDP5);
-                       IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
-                       IXGBE_WRITE_FLUSH(hw);
-               }
-
-               /* Allow module to change analog characteristics (1G->10G) */
-               msec_delay(40);
-
-               status = ixgbe_setup_mac_link_82599(hw,
-                                                   IXGBE_LINK_SPEED_10GB_FULL,
-                                                   autoneg_wait_to_complete);
-               if (status != IXGBE_SUCCESS)
-                       return status;
-
-               /* Flap the tx laser if it has not already been done */
-               ixgbe_flap_tx_laser(hw);
-
-               /*
-                * Wait for the controller to acquire link.  Per IEEE 802.3ap,
-                * Section 73.10.2, we may have to wait up to 500ms if KR is
-                * attempted.  82599 uses the same timing for 10g SFI.
-                */
-               for (i = 0; i < 5; i++) {
-                       /* Wait for the link partner to also set speed */
-                       msec_delay(100);
-
-                       /* If we have link, just jump out */
-                       status = ixgbe_check_link(hw, &link_speed,
-                                                 &link_up, FALSE);
-                       if (status != IXGBE_SUCCESS)
-                               return status;
-
-                       if (link_up)
-                               goto out;
-               }
-       }
-
-       if (speed & IXGBE_LINK_SPEED_1GB_FULL) {
-               speedcnt++;
-               if (highest_link_speed == IXGBE_LINK_SPEED_UNKNOWN)
-                       highest_link_speed = IXGBE_LINK_SPEED_1GB_FULL;
-
-               /* If we already have link at this speed, just jump out */
-               status = ixgbe_check_link(hw, &link_speed, &link_up, FALSE);
-               if (status != IXGBE_SUCCESS)
-                       return status;
-
-               if ((link_speed == IXGBE_LINK_SPEED_1GB_FULL) && link_up)
-                       goto out;
-
-               /* Set the module link speed */
-               if (hw->phy.media_type == ixgbe_media_type_fiber_fixed) {
-                       ixgbe_set_fiber_fixed_speed(hw,
-                                                   IXGBE_LINK_SPEED_1GB_FULL);
-               } else {
-                       esdp_reg &= ~IXGBE_ESDP_SDP5;
-                       esdp_reg |= IXGBE_ESDP_SDP5_DIR;
-                       IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
-                       IXGBE_WRITE_FLUSH(hw);
-               }
-
-               /* Allow module to change analog characteristics (10G->1G) */
-               msec_delay(40);
-
-               status = ixgbe_setup_mac_link_82599(hw,
-                                                   IXGBE_LINK_SPEED_1GB_FULL,
-                                                   autoneg_wait_to_complete);
-               if (status != IXGBE_SUCCESS)
-                       return status;
-
-               /* Flap the tx laser if it has not already been done */
-               ixgbe_flap_tx_laser(hw);
-
-               /* Wait for the link partner to also set speed */
-               msec_delay(100);
-
-               /* If we have link, just jump out */
-               status = ixgbe_check_link(hw, &link_speed, &link_up, FALSE);
-               if (status != IXGBE_SUCCESS)
-                       return status;
-
-               if (link_up)
-                       goto out;
-       }
-
-       /*
-        * We didn't get link.  Configure back to the highest speed we tried,
-        * (if there was more than one).  We call ourselves back with just the
-        * single highest speed that the user requested.
-        */
-       if (speedcnt > 1)
-               status = ixgbe_setup_mac_link_multispeed_fiber(hw,
-                       highest_link_speed, autoneg_wait_to_complete);
-
-out:
-       /* Set autoneg_advertised value based on input link speed */
-       hw->phy.autoneg_advertised = 0;
-
-       if (speed & IXGBE_LINK_SPEED_10GB_FULL)
-               hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL;
-
-       if (speed & IXGBE_LINK_SPEED_1GB_FULL)
-               hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL;
-
-       return status;
+       IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
+       IXGBE_WRITE_FLUSH(hw);
 }
 
 /**
@@ -998,14 +888,15 @@ s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
 {
        bool autoneg = FALSE;
        s32 status = IXGBE_SUCCESS;
-       u32 autoc, pma_pmd_1g, link_mode, start_autoc;
+       u32 pma_pmd_1g, link_mode;
+       u32 current_autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); /* holds the value of AUTOC register at this current point in time */
+       u32 orig_autoc = 0; /* holds the cached value of AUTOC register */
+       u32 autoc = current_autoc; /* Temporary variable used for comparison purposes */
        u32 autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
-       u32 orig_autoc = 0;
        u32 pma_pmd_10g_serial = autoc2 & IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_MASK;
        u32 links_reg;
        u32 i;
        ixgbe_link_speed link_capabilities = IXGBE_LINK_SPEED_UNKNOWN;
-       bool got_lock = FALSE;
 
        DEBUGFUNC("ixgbe_setup_mac_link_82599");
 
@@ -1023,12 +914,10 @@ s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
 
        /* Use stored value (EEPROM defaults) of AUTOC to find KR/KX4 support*/
        if (hw->mac.orig_link_settings_stored)
-               autoc = hw->mac.orig_autoc;
+               orig_autoc = hw->mac.orig_autoc;
        else
-               autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+               orig_autoc = autoc;
 
-       orig_autoc = autoc;
-       start_autoc = hw->mac.cached_autoc;
        link_mode = autoc & IXGBE_AUTOC_LMS_MASK;
        pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK;
 
@@ -1061,39 +950,18 @@ s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
                if ((speed == IXGBE_LINK_SPEED_1GB_FULL) &&
                    (pma_pmd_1g == IXGBE_AUTOC_1G_SFI)) {
                        autoc &= ~IXGBE_AUTOC_LMS_MASK;
-                       if (autoneg)
+                       if (autoneg || hw->phy.type == ixgbe_phy_qsfp_intel)
                                autoc |= IXGBE_AUTOC_LMS_1G_AN;
                        else
                                autoc |= IXGBE_AUTOC_LMS_1G_LINK_NO_AN;
                }
        }
 
-       if (autoc != start_autoc) {
-               /* Need SW/FW semaphore around AUTOC writes if LESM is on,
-                * likewise reset_pipeline requires us to hold this lock as
-                * it also writes to AUTOC.
-                */
-               if (ixgbe_verify_lesm_fw_enabled_82599(hw)) {
-                       status = hw->mac.ops.acquire_swfw_sync(hw,
-                                                       IXGBE_GSSR_MAC_CSR_SM);
-                       if (status != IXGBE_SUCCESS) {
-                               status = IXGBE_ERR_SWFW_SYNC;
-                               goto out;
-                       }
-
-                       got_lock = TRUE;
-               }
-
+       if (autoc != current_autoc) {
                /* Restart link */
-               IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc);
-               hw->mac.cached_autoc = autoc;
-               ixgbe_reset_pipeline_82599(hw);
-
-               if (got_lock) {
-                       hw->mac.ops.release_swfw_sync(hw,
-                                                     IXGBE_GSSR_MAC_CSR_SM);
-                       got_lock = FALSE;
-               }
+               status = hw->mac.ops.prot_autoc_write(hw, autoc, FALSE);
+               if (status != IXGBE_SUCCESS)
+                       goto out;
 
                /* Only poll for autoneg to complete if specified to do so */
                if (autoneg_wait_to_complete) {
@@ -1161,7 +1029,8 @@ s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw)
 {
        ixgbe_link_speed link_speed;
        s32 status;
-       u32 ctrl, i, autoc2;
+       u32 ctrl = 0;
+       u32 i, autoc, autoc2;
        u32 curr_lms;
        bool link_up = FALSE;
 
@@ -1197,11 +1066,7 @@ s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw)
                hw->phy.ops.reset(hw);
 
        /* remember AUTOC from before we reset */
-       if (hw->mac.cached_autoc)
-               curr_lms = hw->mac.cached_autoc & IXGBE_AUTOC_LMS_MASK;
-       else
-               curr_lms = IXGBE_READ_REG(hw, IXGBE_AUTOC) &
-                                         IXGBE_AUTOC_LMS_MASK;
+       curr_lms = IXGBE_READ_REG(hw, IXGBE_AUTOC) & IXGBE_AUTOC_LMS_MASK;
 
 mac_reset_top:
        /*
@@ -1221,7 +1086,7 @@ mac_reset_top:
        IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl);
        IXGBE_WRITE_FLUSH(hw);
 
-       /* Poll for reset bit to self-clear indicating reset is complete */
+       /* Poll for reset bit to self-clear meaning reset is complete */
        for (i = 0; i < 10; i++) {
                usec_delay(1);
                ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
@@ -1238,8 +1103,8 @@ mac_reset_top:
 
        /*
         * Double resets are required for recovery from certain error
-        * conditions.  Between resets, it is necessary to stall to allow time
-        * for any pending HW events to complete.
+        * conditions.  Between resets, it is necessary to stall to
+        * allow time for any pending HW events to complete.
         */
        if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
                hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
@@ -1251,7 +1116,7 @@ mac_reset_top:
         * stored off yet.  Otherwise restore the stored original
         * values since the reset operation sets back to defaults.
         */
-       hw->mac.cached_autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+       autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
        autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
 
        /* Enable link if disabled in NVM */
@@ -1262,7 +1127,7 @@ mac_reset_top:
        }
 
        if (hw->mac.orig_link_settings_stored == FALSE) {
-               hw->mac.orig_autoc = hw->mac.cached_autoc;
+               hw->mac.orig_autoc = autoc;
                hw->mac.orig_autoc2 = autoc2;
                hw->mac.orig_link_settings_stored = TRUE;
        } else {
@@ -1273,36 +1138,18 @@ mac_reset_top:
                 * Likewise if we support WoL we don't want change the
                 * LMS state.
                 */
-               if ((hw->phy.multispeed_fiber && hw->mng_fw_enabled) ||
+               if ((hw->phy.multispeed_fiber && ixgbe_mng_enabled(hw)) ||
                    hw->wol_enabled)
                        hw->mac.orig_autoc =
                                (hw->mac.orig_autoc & ~IXGBE_AUTOC_LMS_MASK) |
                                curr_lms;
 
-               if (hw->mac.cached_autoc != hw->mac.orig_autoc) {
-                       /* Need SW/FW semaphore around AUTOC writes if LESM is
-                        * on, likewise reset_pipeline requires us to hold
-                        * this lock as it also writes to AUTOC.
-                        */
-                       bool got_lock = FALSE;
-                       if (ixgbe_verify_lesm_fw_enabled_82599(hw)) {
-                               status = hw->mac.ops.acquire_swfw_sync(hw,
-                                                       IXGBE_GSSR_MAC_CSR_SM);
-                               if (status != IXGBE_SUCCESS) {
-                                       status = IXGBE_ERR_SWFW_SYNC;
-                                       goto reset_hw_out;
-                               }
-
-                               got_lock = TRUE;
-                       }
-
-                       IXGBE_WRITE_REG(hw, IXGBE_AUTOC, hw->mac.orig_autoc);
-                       hw->mac.cached_autoc = hw->mac.orig_autoc;
-                       ixgbe_reset_pipeline_82599(hw);
-
-                       if (got_lock)
-                               hw->mac.ops.release_swfw_sync(hw,
-                                                     IXGBE_GSSR_MAC_CSR_SM);
+               if (autoc != hw->mac.orig_autoc) {
+                       status = hw->mac.ops.prot_autoc_write(hw,
+                                                       hw->mac.orig_autoc,
+                                                       FALSE);
+                       if (status != IXGBE_SUCCESS)
+                               goto reset_hw_out;
                }
 
                if ((autoc2 & IXGBE_AUTOC2_UPPER_MASK) !=
@@ -1348,14 +1195,35 @@ reset_hw_out:
        return status;
 }
 
+/**
+ * ixgbe_fdir_check_cmd_complete - poll to check whether FDIRCMD is complete
+ * @hw: pointer to hardware structure
+ * @fdircmd: current value of FDIRCMD register
+ */
+static s32 ixgbe_fdir_check_cmd_complete(struct ixgbe_hw *hw, u32 *fdircmd)
+{
+       int i;
+
+       for (i = 0; i < IXGBE_FDIRCMD_CMD_POLL; i++) {
+               *fdircmd = IXGBE_READ_REG(hw, IXGBE_FDIRCMD);
+               if (!(*fdircmd & IXGBE_FDIRCMD_CMD_MASK))
+                       return IXGBE_SUCCESS;
+               usec_delay(10);
+       }
+
+       return IXGBE_ERR_FDIR_CMD_INCOMPLETE;
+}
+
 /**
  *  ixgbe_reinit_fdir_tables_82599 - Reinitialize Flow Director tables.
  *  @hw: pointer to hardware structure
  **/
 s32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw)
 {
+       s32 err;
        int i;
        u32 fdirctrl = IXGBE_READ_REG(hw, IXGBE_FDIRCTRL);
+       u32 fdircmd;
        fdirctrl &= ~IXGBE_FDIRCTRL_INIT_DONE;
 
        DEBUGFUNC("ixgbe_reinit_fdir_tables_82599");
@@ -1364,16 +1232,10 @@ s32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw)
         * Before starting reinitialization process,
         * FDIRCMD.CMD must be zero.
         */
-       for (i = 0; i < IXGBE_FDIRCMD_CMD_POLL; i++) {
-               if (!(IXGBE_READ_REG(hw, IXGBE_FDIRCMD) &
-                     IXGBE_FDIRCMD_CMD_MASK))
-                       break;
-               usec_delay(10);
-       }
-       if (i >= IXGBE_FDIRCMD_CMD_POLL) {
-               DEBUGOUT("Flow Director previous command isn't complete, "
-                        "aborting table re-initialization.\n");
-               return IXGBE_ERR_FDIR_REINIT_FAILED;
+       err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd);
+       if (err) {
+               DEBUGOUT("Flow Director previous command did not complete, aborting table re-initialization.\n");
+               return err;
        }
 
        IXGBE_WRITE_REG(hw, IXGBE_FDIRFREE, 0);
@@ -1497,8 +1359,10 @@ s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 fdirctrl)
  *  @hw: pointer to hardware structure
  *  @fdirctrl: value to write to flow director control register, initially
  *          contains just the value of the Rx packet buffer allocation
+ *  @cloud_mode: TRUE - cloud mode, FALSE - other mode
  **/
-s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 fdirctrl)
+s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 fdirctrl,
+                       bool cloud_mode)
 {
        DEBUGFUNC("ixgbe_init_fdir_perfect_82599");
 
@@ -1518,6 +1382,10 @@ s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 fdirctrl)
                    (0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT) |
                    (4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT);
 
+       if (cloud_mode)
+               fdirctrl |=(IXGBE_FDIRCTRL_FILTERMODE_CLOUD <<
+                                       IXGBE_FDIRCTRL_FILTERMODE_SHIFT);
+
        /* write hashes and fdirctrl register, poll for completion */
        ixgbe_fdir_enable_82599(hw, fdirctrl);
 
@@ -1546,14 +1414,14 @@ do { \
                bucket_hash ^= hi_hash_dword >> n; \
        else if (IXGBE_ATR_SIGNATURE_HASH_KEY & (0x01 << (n + 16))) \
                sig_hash ^= hi_hash_dword << (16 - n); \
-} while (0);
+} while (0)
 
 /**
  *  ixgbe_atr_compute_sig_hash_82599 - Compute the signature hash
  *  @stream: input bitstream to compute the hash on
  *
  *  This function is almost identical to the function above but contains
- *  several optomizations such as unwinding all of the loops, letting the
+ *  several optimizations such as unwinding all of the loops, letting the
  *  compiler work out all of the conditional ifs since the keys are static
  *  defines, and computing two keys at once since the hashed dword stream
  *  will be the same for both keys.
@@ -1582,7 +1450,7 @@ u32 ixgbe_atr_compute_sig_hash_82599(union ixgbe_atr_hash_dword input,
        /*
         * apply flow ID/VM pool/VLAN ID bits to lo hash dword, we had to
         * delay this because bit 0 of the stream should not be processed
-        * so we do not add the vlan until after bit 0 was processed
+        * so we do not add the VLAN until after bit 0 was processed
         */
        lo_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan << 16);
 
@@ -1620,22 +1488,32 @@ u32 ixgbe_atr_compute_sig_hash_82599(union ixgbe_atr_hash_dword input,
  *  @input: unique input dword
  *  @common: compressed common input dword
  *  @queue: queue index to direct traffic to
+ *
+ * Note that the tunnel bit in input must not be set when the hardware
+ * tunneling support does not exist.
  **/
 s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
                                          union ixgbe_atr_hash_dword input,
                                          union ixgbe_atr_hash_dword common,
                                          u8 queue)
 {
-       u64  fdirhashcmd;
-       u32  fdircmd;
+       u64 fdirhashcmd;
+       u8 flow_type;
+       bool tunnel;
+       u32 fdircmd;
+       s32 err;
 
        DEBUGFUNC("ixgbe_fdir_add_signature_filter_82599");
 
        /*
         * Get the flow_type in order to program FDIRCMD properly
         * lowest 2 bits are FDIRCMD.L4TYPE, third lowest bit is FDIRCMD.IPV6
+        * fifth is FDIRCMD.TUNNEL_FILTER
         */
-       switch (input.formatted.flow_type) {
+       tunnel = !!(input.formatted.flow_type & IXGBE_ATR_L4TYPE_TUNNEL_MASK);
+       flow_type = input.formatted.flow_type &
+                   (IXGBE_ATR_L4TYPE_TUNNEL_MASK - 1);
+       switch (flow_type) {
        case IXGBE_ATR_FLOW_TYPE_TCPV4:
        case IXGBE_ATR_FLOW_TYPE_UDPV4:
        case IXGBE_ATR_FLOW_TYPE_SCTPV4:
@@ -1651,8 +1529,10 @@ s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
        /* configure FDIRCMD register */
        fdircmd = IXGBE_FDIRCMD_CMD_ADD_FLOW | IXGBE_FDIRCMD_FILTER_UPDATE |
                  IXGBE_FDIRCMD_LAST | IXGBE_FDIRCMD_QUEUE_EN;
-       fdircmd |= input.formatted.flow_type << IXGBE_FDIRCMD_FLOW_TYPE_SHIFT;
+       fdircmd |= (u32)flow_type << IXGBE_FDIRCMD_FLOW_TYPE_SHIFT;
        fdircmd |= (u32)queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT;
+       if (tunnel)
+               fdircmd |= IXGBE_FDIRCMD_TUNNEL_FILTER;
 
        /*
         * The lower 32-bits of fdirhashcmd is for FDIRHASH, the upper 32-bits
@@ -1662,6 +1542,12 @@ s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
        fdirhashcmd |= ixgbe_atr_compute_sig_hash_82599(input, common);
        IXGBE_WRITE_REG64(hw, IXGBE_FDIRHASH, fdirhashcmd);
 
+       err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd);
+       if (err) {
+               DEBUGOUT("Flow Director command did not complete!\n");
+               return err;
+       }
+
        DEBUGOUT2("Tx Queue=%x hash=%x\n", queue, (u32)fdirhashcmd);
 
        return IXGBE_SUCCESS;
@@ -1674,14 +1560,14 @@ do { \
                bucket_hash ^= lo_hash_dword >> n; \
        if (IXGBE_ATR_BUCKET_HASH_KEY & (0x01 << (n + 16))) \
                bucket_hash ^= hi_hash_dword >> n; \
-} while (0);
+} while (0)
 
 /**
  *  ixgbe_atr_compute_perfect_hash_82599 - Compute the perfect filter hash
  *  @atr_input: input bitstream to compute the hash on
  *  @input_mask: mask for the input bitstream
  *
- *  This function serves two main purposes.  First it applys the input_mask
+ *  This function serves two main purposes.  First it applies the input_mask
  *  to the atr_input resulting in a cleaned up atr_input data stream.
  *  Secondly it computes the hash and stores it in the bkt_hash field at
  *  the end of the input byte stream.  This way it will be available for
@@ -1693,34 +1579,20 @@ void ixgbe_atr_compute_perfect_hash_82599(union ixgbe_atr_input *input,
 
        u32 hi_hash_dword, lo_hash_dword, flow_vm_vlan;
        u32 bucket_hash = 0;
+       u32 hi_dword = 0;
+       u32 i = 0;
 
        /* Apply masks to input data */
-       input->dword_stream[0]  &= input_mask->dword_stream[0];
-       input->dword_stream[1]  &= input_mask->dword_stream[1];
-       input->dword_stream[2]  &= input_mask->dword_stream[2];
-       input->dword_stream[3]  &= input_mask->dword_stream[3];
-       input->dword_stream[4]  &= input_mask->dword_stream[4];
-       input->dword_stream[5]  &= input_mask->dword_stream[5];
-       input->dword_stream[6]  &= input_mask->dword_stream[6];
-       input->dword_stream[7]  &= input_mask->dword_stream[7];
-       input->dword_stream[8]  &= input_mask->dword_stream[8];
-       input->dword_stream[9]  &= input_mask->dword_stream[9];
-       input->dword_stream[10] &= input_mask->dword_stream[10];
+       for (i = 0; i < 14; i++)
+               input->dword_stream[i]  &= input_mask->dword_stream[i];
 
        /* record the flow_vm_vlan bits as they are a key part to the hash */
        flow_vm_vlan = IXGBE_NTOHL(input->dword_stream[0]);
 
        /* generate common hash dword */
-       hi_hash_dword = IXGBE_NTOHL(input->dword_stream[1] ^
-                                   input->dword_stream[2] ^
-                                   input->dword_stream[3] ^
-                                   input->dword_stream[4] ^
-                                   input->dword_stream[5] ^
-                                   input->dword_stream[6] ^
-                                   input->dword_stream[7] ^
-                                   input->dword_stream[8] ^
-                                   input->dword_stream[9] ^
-                                   input->dword_stream[10]);
+       for (i = 1; i <= 13; i++)
+               hi_dword ^= input->dword_stream[i];
+       hi_hash_dword = IXGBE_NTOHL(hi_dword);
 
        /* low dword is word swapped version of common */
        lo_hash_dword = (hi_hash_dword >> 16) | (hi_hash_dword << 16);
@@ -1734,26 +1606,13 @@ void ixgbe_atr_compute_perfect_hash_82599(union ixgbe_atr_input *input,
        /*
         * apply flow ID/VM pool/VLAN ID bits to lo hash dword, we had to
         * delay this because bit 0 of the stream should not be processed
-        * so we do not add the vlan until after bit 0 was processed
+        * so we do not add the VLAN until after bit 0 was processed
         */
        lo_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan << 16);
 
        /* Process remaining 30 bit of the key */
-       IXGBE_COMPUTE_BKT_HASH_ITERATION(1);
-       IXGBE_COMPUTE_BKT_HASH_ITERATION(2);
-       IXGBE_COMPUTE_BKT_HASH_ITERATION(3);
-       IXGBE_COMPUTE_BKT_HASH_ITERATION(4);
-       IXGBE_COMPUTE_BKT_HASH_ITERATION(5);
-       IXGBE_COMPUTE_BKT_HASH_ITERATION(6);
-       IXGBE_COMPUTE_BKT_HASH_ITERATION(7);
-       IXGBE_COMPUTE_BKT_HASH_ITERATION(8);
-       IXGBE_COMPUTE_BKT_HASH_ITERATION(9);
-       IXGBE_COMPUTE_BKT_HASH_ITERATION(10);
-       IXGBE_COMPUTE_BKT_HASH_ITERATION(11);
-       IXGBE_COMPUTE_BKT_HASH_ITERATION(12);
-       IXGBE_COMPUTE_BKT_HASH_ITERATION(13);
-       IXGBE_COMPUTE_BKT_HASH_ITERATION(14);
-       IXGBE_COMPUTE_BKT_HASH_ITERATION(15);
+       for (i = 1; i <= 15; i++)
+               IXGBE_COMPUTE_BKT_HASH_ITERATION(i);
 
        /*
         * Limit hash to 13 bits since max bucket count is 8K.
@@ -1763,7 +1622,7 @@ void ixgbe_atr_compute_perfect_hash_82599(union ixgbe_atr_input *input,
 }
 
 /**
- *  ixgbe_get_fdirtcpm_82599 - generate a tcp port from atr_input_masks
+ *  ixgbe_get_fdirtcpm_82599 - generate a TCP port from atr_input_masks
  *  @input_mask: mask to be bit swapped
  *
  *  The source and destination port masks for flow director are bit swapped
@@ -1800,12 +1659,12 @@ static u32 ixgbe_get_fdirtcpm_82599(union ixgbe_atr_input *input_mask)
        IXGBE_NTOHS(((u16)(_value) >> 8) | ((u16)(_value) << 8))
 
 s32 ixgbe_fdir_set_input_mask_82599(struct ixgbe_hw *hw,
-                                   union ixgbe_atr_input *input_mask)
+                                   union ixgbe_atr_input *input_mask, bool cloud_mode)
 {
        /* mask IPv6 since it is currently not supported */
        u32 fdirm = IXGBE_FDIRM_DIPv6;
        u32 fdirtcpm;
-
+       u32 fdirip6m;
        DEBUGFUNC("ixgbe_fdir_set_atr_input_mask_82599");
 
        /*
@@ -1878,59 +1737,147 @@ s32 ixgbe_fdir_set_input_mask_82599(struct ixgbe_hw *hw,
                return IXGBE_ERR_CONFIG;
        }
 
-       /* Now mask VM pool and destination IPv6 - bits 5 and 2 */
-       IXGBE_WRITE_REG(hw, IXGBE_FDIRM, fdirm);
+       if (cloud_mode) {
+               fdirm |= IXGBE_FDIRM_L3P;
+               fdirip6m = ((u32) 0xFFFFU << IXGBE_FDIRIP6M_DIPM_SHIFT);
+               fdirip6m |= IXGBE_FDIRIP6M_ALWAYS_MASK;
+
+               switch (input_mask->formatted.inner_mac[0] & 0xFF) {
+               case 0x00:
+                       /* Mask inner MAC, fall through */
+                       fdirip6m |= IXGBE_FDIRIP6M_INNER_MAC;
+               case 0xFF:
+                       break;
+               default:
+                       DEBUGOUT(" Error on inner_mac byte mask\n");
+                       return IXGBE_ERR_CONFIG;
+               }
+
+               switch (input_mask->formatted.tni_vni & 0xFFFFFFFF) {
+               case 0x0:
+                       /* Mask vxlan id */
+                       fdirip6m |= IXGBE_FDIRIP6M_TNI_VNI;
+                       break;
+               case 0x00FFFFFF:
+                       fdirip6m |= IXGBE_FDIRIP6M_TNI_VNI_24;
+                       break;
+               case 0xFFFFFFFF:
+                       break;
+               default:
+                       DEBUGOUT(" Error on TNI/VNI byte mask\n");
+                       return IXGBE_ERR_CONFIG;
+               }
+
+               switch (input_mask->formatted.tunnel_type & 0xFFFF) {
+               case 0x0:
+                       /* Mask turnnel type, fall through */
+                       fdirip6m |= IXGBE_FDIRIP6M_TUNNEL_TYPE;
+               case 0xFFFF:
+                       break;
+               default:
+                       DEBUGOUT(" Error on tunnel type byte mask\n");
+                       return IXGBE_ERR_CONFIG;
+               }
+               IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIP6M, fdirip6m);
 
-       /* store the TCP/UDP port masks, bit reversed from port layout */
-       fdirtcpm = ixgbe_get_fdirtcpm_82599(input_mask);
+               /* Set all bits in FDIRTCPM, FDIRUDPM, FDIRSIP4M and
+                * FDIRDIP4M in cloud mode to allow L3/L3 packets to
+                * tunnel.
+                */
+               IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, 0xFFFFFFFF);
+               IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, 0xFFFFFFFF);
+               IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRDIP4M, 0xFFFFFFFF);
+               IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIP4M, 0xFFFFFFFF);
+       }
 
-       /* write both the same so that UDP and TCP use the same mask */
-       IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, ~fdirtcpm);
-       IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, ~fdirtcpm);
+       /* Now mask VM pool and destination IPv6 - bits 5 and 2 */
+       IXGBE_WRITE_REG(hw, IXGBE_FDIRM, fdirm);
 
-       /* store source and destination IP masks (big-enian) */
-       IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIP4M,
-                            ~input_mask->formatted.src_ip[0]);
-       IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRDIP4M,
-                            ~input_mask->formatted.dst_ip[0]);
+       if (!cloud_mode) {
+               /* store the TCP/UDP port masks, bit reversed from port
+                * layout */
+               fdirtcpm = ixgbe_get_fdirtcpm_82599(input_mask);
+
+               /* write both the same so that UDP and TCP use the same mask */
+               IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, ~fdirtcpm);
+               IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, ~fdirtcpm);
+               /* also use it for SCTP */
+               switch (hw->mac.type) {
+               case ixgbe_mac_X550:
+               case ixgbe_mac_X550EM_x:
+               case ixgbe_mac_X550EM_a:
+                       IXGBE_WRITE_REG(hw, IXGBE_FDIRSCTPM, ~fdirtcpm);
+                       break;
+               default:
+                       break;
+               }
 
+               /* store source and destination IP masks (big-enian) */
+               IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIP4M,
+                                    ~input_mask->formatted.src_ip[0]);
+               IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRDIP4M,
+                                    ~input_mask->formatted.dst_ip[0]);
+       }
        return IXGBE_SUCCESS;
 }
 
 s32 ixgbe_fdir_write_perfect_filter_82599(struct ixgbe_hw *hw,
                                          union ixgbe_atr_input *input,
-                                         u16 soft_id, u8 queue)
+                                         u16 soft_id, u8 queue, bool cloud_mode)
 {
        u32 fdirport, fdirvlan, fdirhash, fdircmd;
+       u32 addr_low, addr_high;
+       u32 cloud_type = 0;
+       s32 err;
 
        DEBUGFUNC("ixgbe_fdir_write_perfect_filter_82599");
+       if (!cloud_mode) {
+               /* currently IPv6 is not supported, must be programmed with 0 */
+               IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(0),
+                                    input->formatted.src_ip[0]);
+               IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(1),
+                                    input->formatted.src_ip[1]);
+               IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(2),
+                                    input->formatted.src_ip[2]);
+
+               /* record the source address (big-endian) */
+               IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIPSA,
+                       input->formatted.src_ip[0]);
+
+               /* record the first 32 bits of the destination address
+                * (big-endian) */
+               IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIPDA,
+                       input->formatted.dst_ip[0]);
+
+               /* record source and destination port (little-endian)*/
+               fdirport = IXGBE_NTOHS(input->formatted.dst_port);
+               fdirport <<= IXGBE_FDIRPORT_DESTINATION_SHIFT;
+               fdirport |= IXGBE_NTOHS(input->formatted.src_port);
+               IXGBE_WRITE_REG(hw, IXGBE_FDIRPORT, fdirport);
+       }
 
-       /* currently IPv6 is not supported, must be programmed with 0 */
-       IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(0),
-                            input->formatted.src_ip[0]);
-       IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(1),
-                            input->formatted.src_ip[1]);
-       IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(2),
-                            input->formatted.src_ip[2]);
-
-       /* record the source address (big-endian) */
-       IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIPSA, input->formatted.src_ip[0]);
-
-       /* record the first 32 bits of the destination address (big-endian) */
-       IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIPDA, input->formatted.dst_ip[0]);
-
-       /* record source and destination port (little-endian)*/
-       fdirport = IXGBE_NTOHS(input->formatted.dst_port);
-       fdirport <<= IXGBE_FDIRPORT_DESTINATION_SHIFT;
-       fdirport |= IXGBE_NTOHS(input->formatted.src_port);
-       IXGBE_WRITE_REG(hw, IXGBE_FDIRPORT, fdirport);
-
-       /* record vlan (little-endian) and flex_bytes(big-endian) */
+       /* record VLAN (little-endian) and flex_bytes(big-endian) */
        fdirvlan = IXGBE_STORE_AS_BE16(input->formatted.flex_bytes);
        fdirvlan <<= IXGBE_FDIRVLAN_FLEX_SHIFT;
        fdirvlan |= IXGBE_NTOHS(input->formatted.vlan_id);
        IXGBE_WRITE_REG(hw, IXGBE_FDIRVLAN, fdirvlan);
 
+       if (cloud_mode) {
+               if (input->formatted.tunnel_type != 0)
+                       cloud_type = 0x80000000;
+
+               addr_low = ((u32)input->formatted.inner_mac[0] |
+                               ((u32)input->formatted.inner_mac[1] << 8) |
+                               ((u32)input->formatted.inner_mac[2] << 16) |
+                               ((u32)input->formatted.inner_mac[3] << 24));
+               addr_high = ((u32)input->formatted.inner_mac[4] |
+                               ((u32)input->formatted.inner_mac[5] << 8));
+               cloud_type |= addr_high;
+               IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(0), addr_low);
+               IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(1), cloud_type);
+               IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(2), input->formatted.tni_vni);
+       }
+
        /* configure FDIRHASH register */
        fdirhash = input->formatted.bkt_hash;
        fdirhash |= soft_id << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT;
@@ -1947,11 +1894,18 @@ s32 ixgbe_fdir_write_perfect_filter_82599(struct ixgbe_hw *hw,
                  IXGBE_FDIRCMD_LAST | IXGBE_FDIRCMD_QUEUE_EN;
        if (queue == IXGBE_FDIR_DROP_QUEUE)
                fdircmd |= IXGBE_FDIRCMD_DROP;
+       if (input->formatted.flow_type & IXGBE_ATR_L4TYPE_TUNNEL_MASK)
+               fdircmd |= IXGBE_FDIRCMD_TUNNEL_FILTER;
        fdircmd |= input->formatted.flow_type << IXGBE_FDIRCMD_FLOW_TYPE_SHIFT;
        fdircmd |= (u32)queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT;
        fdircmd |= (u32)input->formatted.vm_pool << IXGBE_FDIRCMD_VT_POOL_SHIFT;
 
        IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, fdircmd);
+       err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd);
+       if (err) {
+               DEBUGOUT("Flow Director command did not complete!\n");
+               return err;
+       }
 
        return IXGBE_SUCCESS;
 }
@@ -1961,9 +1915,8 @@ s32 ixgbe_fdir_erase_perfect_filter_82599(struct ixgbe_hw *hw,
                                          u16 soft_id)
 {
        u32 fdirhash;
-       u32 fdircmd = 0;
-       u32 retry_count;
-       s32 err = IXGBE_SUCCESS;
+       u32 fdircmd;
+       s32 err;
 
        /* configure FDIRHASH register */
        fdirhash = input->formatted.bkt_hash;
@@ -1976,18 +1929,12 @@ s32 ixgbe_fdir_erase_perfect_filter_82599(struct ixgbe_hw *hw,
        /* Query if filter is present */
        IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, IXGBE_FDIRCMD_CMD_QUERY_REM_FILT);
 
-       for (retry_count = 10; retry_count; retry_count--) {
-               /* allow 10us for query to process */
-               usec_delay(10);
-               /* verify query completed successfully */
-               fdircmd = IXGBE_READ_REG(hw, IXGBE_FDIRCMD);
-               if (!(fdircmd & IXGBE_FDIRCMD_CMD_MASK))
-                       break;
+       err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd);
+       if (err) {
+               DEBUGOUT("Flow Director command did not complete!\n");
+               return err;
        }
 
-       if (!retry_count)
-               err = IXGBE_ERR_FDIR_REINIT_FAILED;
-
        /* if filter exists in hardware then remove it */
        if (fdircmd & IXGBE_FDIRCMD_FILTER_VALID) {
                IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);
@@ -1996,7 +1943,7 @@ s32 ixgbe_fdir_erase_perfect_filter_82599(struct ixgbe_hw *hw,
                                IXGBE_FDIRCMD_CMD_REMOVE_FLOW);
        }
 
-       return err;
+       return IXGBE_SUCCESS;
 }
 
 /**
@@ -2013,7 +1960,7 @@ s32 ixgbe_fdir_erase_perfect_filter_82599(struct ixgbe_hw *hw,
 s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
                                        union ixgbe_atr_input *input,
                                        union ixgbe_atr_input *input_mask,
-                                       u16 soft_id, u8 queue)
+                                       u16 soft_id, u8 queue, bool cloud_mode)
 {
        s32 err = IXGBE_ERR_CONFIG;
 
@@ -2025,6 +1972,7 @@ s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
         */
        switch (input->formatted.flow_type) {
        case IXGBE_ATR_FLOW_TYPE_IPV4:
+       case IXGBE_ATR_FLOW_TYPE_TUNNELED_IPV4:
                input_mask->formatted.flow_type = IXGBE_ATR_L4TYPE_IPV6_MASK;
                if (input->formatted.dst_port || input->formatted.src_port) {
                        DEBUGOUT(" Error on src/dst port\n");
@@ -2032,12 +1980,15 @@ s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
                }
                break;
        case IXGBE_ATR_FLOW_TYPE_SCTPV4:
+       case IXGBE_ATR_FLOW_TYPE_TUNNELED_SCTPV4:
                if (input->formatted.dst_port || input->formatted.src_port) {
                        DEBUGOUT(" Error on src/dst port\n");
                        return IXGBE_ERR_CONFIG;
                }
        case IXGBE_ATR_FLOW_TYPE_TCPV4:
+       case IXGBE_ATR_FLOW_TYPE_TUNNELED_TCPV4:
        case IXGBE_ATR_FLOW_TYPE_UDPV4:
+       case IXGBE_ATR_FLOW_TYPE_TUNNELED_UDPV4:
                input_mask->formatted.flow_type = IXGBE_ATR_L4TYPE_IPV6_MASK |
                                                  IXGBE_ATR_L4TYPE_MASK;
                break;
@@ -2047,7 +1998,7 @@ s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
        }
 
        /* program input mask into the HW */
-       err = ixgbe_fdir_set_input_mask_82599(hw, input_mask);
+       err = ixgbe_fdir_set_input_mask_82599(hw, input_mask, cloud_mode);
        if (err)
                return err;
 
@@ -2056,7 +2007,7 @@ s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
 
        /* program filters to filter memory */
        return ixgbe_fdir_write_perfect_filter_82599(hw, input,
-                                                    soft_id, queue);
+                                                    soft_id, queue, cloud_mode);
 }
 
 /**
@@ -2146,7 +2097,7 @@ out:
  **/
 s32 ixgbe_identify_phy_82599(struct ixgbe_hw *hw)
 {
-       s32 status = IXGBE_ERR_PHY_ADDR_INVALID;
+       s32 status;
 
        DEBUGFUNC("ixgbe_identify_phy_82599");
 
@@ -2155,7 +2106,7 @@ s32 ixgbe_identify_phy_82599(struct ixgbe_hw *hw)
        if (status != IXGBE_SUCCESS) {
                /* 82599 10GBASE-T requires an external PHY */
                if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_copper)
-                       goto out;
+                       return status;
                else
                        status = ixgbe_identify_module_generic(hw);
        }
@@ -2163,14 +2114,13 @@ s32 ixgbe_identify_phy_82599(struct ixgbe_hw *hw)
        /* Set PHY type none if no PHY detected */
        if (hw->phy.type == ixgbe_phy_unknown) {
                hw->phy.type = ixgbe_phy_none;
-               status = IXGBE_SUCCESS;
+               return IXGBE_SUCCESS;
        }
 
        /* Return error if SFP module has been detected but is not supported */
        if (hw->phy.type == ixgbe_phy_sfp_unsupported)
-               status = IXGBE_ERR_SFP_NOT_SUPPORTED;
+               return IXGBE_ERR_SFP_NOT_SUPPORTED;
 
-out:
        return status;
 }
 
@@ -2189,8 +2139,6 @@ u32 ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw)
        u32 pma_pmd_10g_parallel = autoc & IXGBE_AUTOC_10G_PMA_PMD_MASK;
        u32 pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK;
        u16 ext_ability = 0;
-       u8 comp_codes_10g = 0;
-       u8 comp_codes_1g = 0;
 
        DEBUGFUNC("ixgbe_get_support_physical_layer_82599");
 
@@ -2258,40 +2206,7 @@ sfp_check:
        /* SFP check must be done last since DA modules are sometimes used to
         * test KR mode -  we need to id KR mode correctly before SFP module.
         * Call identify_sfp because the pluggable module may have changed */
-       hw->phy.ops.identify_sfp(hw);
-       if (hw->phy.sfp_type == ixgbe_sfp_type_not_present)
-               goto out;
-
-       switch (hw->phy.type) {
-       case ixgbe_phy_sfp_passive_tyco:
-       case ixgbe_phy_sfp_passive_unknown:
-               physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU;
-               break;
-       case ixgbe_phy_sfp_ftl_active:
-       case ixgbe_phy_sfp_active_unknown:
-               physical_layer = IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA;
-               break;
-       case ixgbe_phy_sfp_avago:
-       case ixgbe_phy_sfp_ftl:
-       case ixgbe_phy_sfp_intel:
-       case ixgbe_phy_sfp_unknown:
-               hw->phy.ops.read_i2c_eeprom(hw,
-                     IXGBE_SFF_1GBE_COMP_CODES, &comp_codes_1g);
-               hw->phy.ops.read_i2c_eeprom(hw,
-                     IXGBE_SFF_10GBE_COMP_CODES, &comp_codes_10g);
-               if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)
-                       physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR;
-               else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)
-                       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;
-       }
-
+       physical_layer = ixgbe_get_supported_phy_sfp_layer_generic(hw);
 out:
        return physical_layer;
 }
@@ -2317,7 +2232,10 @@ s32 ixgbe_enable_rx_dma_82599(struct ixgbe_hw *hw, u32 regval)
 
        hw->mac.ops.disable_sec_rx_path(hw);
 
-       IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, regval);
+       if (regval & IXGBE_RXCTRL_RXEN)
+               ixgbe_enable_rx(hw);
+       else
+               ixgbe_disable_rx(hw);
 
        hw->mac.ops.enable_sec_rx_path(hw);
 
@@ -2325,7 +2243,7 @@ s32 ixgbe_enable_rx_dma_82599(struct ixgbe_hw *hw, u32 regval)
 }
 
 /**
- *  ixgbe_verify_fw_version_82599 - verify fw version for 82599
+ *  ixgbe_verify_fw_version_82599 - verify FW version for 82599
  *  @hw: pointer to hardware structure
  *
  *  Verifies that installed the firmware version is 0.6 or higher
@@ -2419,7 +2337,7 @@ bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw)
            (fw_lesm_param_offset == 0) || (fw_lesm_param_offset == 0xFFFF))
                goto out;
 
-       /* get the lesm state word */
+       /* get the LESM state word */
        status = hw->eeprom.ops.read(hw, (fw_lesm_param_offset +
                                     IXGBE_FW_LESM_STATE_1),
                                     &fw_lesm_state);
@@ -2504,7 +2422,7 @@ static s32 ixgbe_read_eeprom_82599(struct ixgbe_hw *hw,
  *  @hw: pointer to hardware structure
  *
  * Reset pipeline by asserting Restart_AN together with LMS change to ensure
- * full pipeline reset
+ * full pipeline reset.  This function assumes the SW/FW lock is held.
  **/
 s32 ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw)
 {
@@ -2520,10 +2438,11 @@ s32 ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw)
                IXGBE_WRITE_FLUSH(hw);
        }
 
-       autoc_reg = hw->mac.cached_autoc;
+       autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
        autoc_reg |= IXGBE_AUTOC_AN_RESTART;
        /* Write AUTOC register with toggled LMS[2] bit and Restart_AN */
-       IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg ^ IXGBE_AUTOC_LMS_1G_AN);
+       IXGBE_WRITE_REG(hw, IXGBE_AUTOC,
+                       autoc_reg ^ (0x4 << IXGBE_AUTOC_LMS_SHIFT));
        /* Wait for AN to leave state 0 */
        for (i = 0; i < 10; i++) {
                msec_delay(4);
@@ -2548,5 +2467,116 @@ reset_pipeline_out:
        return ret_val;
 }
 
+/**
+ *  ixgbe_read_i2c_byte_82599 - Reads 8 bit word over I2C
+ *  @hw: pointer to hardware structure
+ *  @byte_offset: byte offset to read
+ *  @data: value read
+ *
+ *  Performs byte read operation to SFP module's EEPROM over I2C interface at
+ *  a specified device address.
+ **/
+static s32 ixgbe_read_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset,
+                               u8 dev_addr, u8 *data)
+{
+       u32 esdp;
+       s32 status;
+       s32 timeout = 200;
+
+       DEBUGFUNC("ixgbe_read_i2c_byte_82599");
+
+       if (hw->phy.qsfp_shared_i2c_bus == TRUE) {
+               /* Acquire I2C bus ownership. */
+               esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
+               esdp |= IXGBE_ESDP_SDP0;
+               IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
+               IXGBE_WRITE_FLUSH(hw);
+
+               while (timeout) {
+                       esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
+                       if (esdp & IXGBE_ESDP_SDP1)
+                               break;
+
+                       msec_delay(5);
+                       timeout--;
+               }
+
+               if (!timeout) {
+                       DEBUGOUT("Driver can't access resource,"
+                                " acquiring I2C bus timeout.\n");
+                       status = IXGBE_ERR_I2C;
+                       goto release_i2c_access;
+               }
+       }
+
+       status = ixgbe_read_i2c_byte_generic(hw, byte_offset, dev_addr, data);
+
+release_i2c_access:
+
+       if (hw->phy.qsfp_shared_i2c_bus == TRUE) {
+               /* Release I2C bus ownership. */
+               esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
+               esdp &= ~IXGBE_ESDP_SDP0;
+               IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
+               IXGBE_WRITE_FLUSH(hw);
+       }
+
+       return status;
+}
+
+/**
+ *  ixgbe_write_i2c_byte_82599 - Writes 8 bit word over I2C
+ *  @hw: pointer to hardware structure
+ *  @byte_offset: byte offset to write
+ *  @data: value to write
+ *
+ *  Performs byte write operation to SFP module's EEPROM over I2C interface at
+ *  a specified device address.
+ **/
+static s32 ixgbe_write_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset,
+                                u8 dev_addr, u8 data)
+{
+       u32 esdp;
+       s32 status;
+       s32 timeout = 200;
+
+       DEBUGFUNC("ixgbe_write_i2c_byte_82599");
+
+       if (hw->phy.qsfp_shared_i2c_bus == TRUE) {
+               /* Acquire I2C bus ownership. */
+               esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
+               esdp |= IXGBE_ESDP_SDP0;
+               IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
+               IXGBE_WRITE_FLUSH(hw);
+
+               while (timeout) {
+                       esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
+                       if (esdp & IXGBE_ESDP_SDP1)
+                               break;
+
+                       msec_delay(5);
+                       timeout--;
+               }
+
+               if (!timeout) {
+                       DEBUGOUT("Driver can't access resource,"
+                                " acquiring I2C bus timeout.\n");
+                       status = IXGBE_ERR_I2C;
+                       goto release_i2c_access;
+               }
+       }
+
+       status = ixgbe_write_i2c_byte_generic(hw, byte_offset, dev_addr, data);
 
+release_i2c_access:
 
+       if (hw->phy.qsfp_shared_i2c_bus == TRUE) {
+               /* Release I2C bus ownership. */
+               esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
+               esdp &= ~IXGBE_ESDP_SDP0;
+               IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
+               IXGBE_WRITE_FLUSH(hw);
+       }
+
+       return status;
+}
index a77d153..8c973ac 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2013, Intel Corporation 
+  Copyright (c) 2001-2014, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -41,9 +41,8 @@ enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw);
 void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
 void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
 void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
-s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
-                                         ixgbe_link_speed speed,
-                                         bool autoneg_wait_to_complete);
+void ixgbe_set_hard_rate_select_speed(struct ixgbe_hw *hw,
+                                       ixgbe_link_speed speed);
 s32 ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw,
                                    ixgbe_link_speed speed,
                                    bool autoneg_wait_to_complete);
@@ -61,4 +60,6 @@ s32 ixgbe_identify_phy_82599(struct ixgbe_hw *hw);
 s32 ixgbe_init_phy_ops_82599(struct ixgbe_hw *hw);
 u32 ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw);
 s32 ixgbe_enable_rx_dma_82599(struct ixgbe_hw *hw, u32 regval);
+s32 prot_autoc_read_82599(struct ixgbe_hw *hw, bool *locked, u32 *reg_val);
+s32 prot_autoc_write_82599(struct ixgbe_hw *hw, u32 reg_val, bool locked);
 #endif /* _IXGBE_82599_H_ */
index 925866b..3c7de9e 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2013, Intel Corporation 
+  Copyright (c) 2001-2014, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -78,13 +78,23 @@ s32 ixgbe_init_shared_code(struct ixgbe_hw *hw)
        case ixgbe_mac_82599EB:
                status = ixgbe_init_ops_82599(hw);
                break;
+       case ixgbe_mac_X540:
+               status = ixgbe_init_ops_X540(hw);
+               break;
+       case ixgbe_mac_X550:
+               status = ixgbe_init_ops_X550(hw);
+               break;
+       case ixgbe_mac_X550EM_x:
+       case ixgbe_mac_X550EM_a:
+               status = ixgbe_init_ops_X550EM(hw);
+               break;
        case ixgbe_mac_82599_vf:
        case ixgbe_mac_X540_vf:
+       case ixgbe_mac_X550_vf:
+       case ixgbe_mac_X550EM_x_vf:
+       case ixgbe_mac_X550EM_a_vf:
                status = ixgbe_init_ops_vf(hw);
                break;
-       case ixgbe_mac_X540:
-               status = ixgbe_init_ops_X540(hw);
-               break;
        default:
                status = IXGBE_ERR_DEVICE_NOT_SUPPORTED;
                break;
@@ -138,6 +148,7 @@ s32 ixgbe_set_mac_type(struct ixgbe_hw *hw)
        case IXGBE_DEV_ID_82599_SFP_EM:
        case IXGBE_DEV_ID_82599_SFP_SF2:
        case IXGBE_DEV_ID_82599_SFP_SF_QP:
+       case IXGBE_DEV_ID_82599_QSFP_SF_QP:
        case IXGBE_DEV_ID_82599EN_SFP:
        case IXGBE_DEV_ID_82599_CX4:
        case IXGBE_DEV_ID_82599_BYPASS:
@@ -153,9 +164,43 @@ s32 ixgbe_set_mac_type(struct ixgbe_hw *hw)
                hw->mac.type = ixgbe_mac_X540_vf;
                break;
        case IXGBE_DEV_ID_X540T:
+       case IXGBE_DEV_ID_X540T1:
        case IXGBE_DEV_ID_X540_BYPASS:
                hw->mac.type = ixgbe_mac_X540;
                break;
+       case IXGBE_DEV_ID_X550T:
+               hw->mac.type = ixgbe_mac_X550;
+               break;
+       case IXGBE_DEV_ID_X550EM_X_KX4:
+       case IXGBE_DEV_ID_X550EM_X_KR:
+       case IXGBE_DEV_ID_X550EM_X_10G_T:
+       case IXGBE_DEV_ID_X550EM_X_1G_T:
+       case IXGBE_DEV_ID_X550EM_X_SFP:
+               hw->mac.type = ixgbe_mac_X550EM_x;
+               break;
+       case IXGBE_DEV_ID_X550EM_A_KR:
+       case IXGBE_DEV_ID_X550EM_A_KR_L:
+       case IXGBE_DEV_ID_X550EM_A_SFP_N:
+       case IXGBE_DEV_ID_X550EM_A_1G_T:
+       case IXGBE_DEV_ID_X550EM_A_1G_T_L:
+       case IXGBE_DEV_ID_X550EM_A_10G_T:
+       case IXGBE_DEV_ID_X550EM_A_QSFP:
+       case IXGBE_DEV_ID_X550EM_A_QSFP_N:
+       case IXGBE_DEV_ID_X550EM_A_SFP:
+               hw->mac.type = ixgbe_mac_X550EM_a;
+               break;
+       case IXGBE_DEV_ID_X550_VF:
+       case IXGBE_DEV_ID_X550_VF_HV:
+               hw->mac.type = ixgbe_mac_X550_vf;
+               break;
+       case IXGBE_DEV_ID_X550EM_X_VF:
+       case IXGBE_DEV_ID_X550EM_X_VF_HV:
+               hw->mac.type = ixgbe_mac_X550EM_x_vf;
+               break;
+       case IXGBE_DEV_ID_X550EM_A_VF:
+       case IXGBE_DEV_ID_X550EM_A_VF_HV:
+               hw->mac.type = ixgbe_mac_X550EM_a_vf;
+               break;
        default:
                ret_val = IXGBE_ERR_DEVICE_NOT_SUPPORTED;
                ERROR_REPORT2(IXGBE_ERROR_UNSUPPORTED,
@@ -511,6 +556,20 @@ s32 ixgbe_setup_phy_link(struct ixgbe_hw *hw)
                               IXGBE_NOT_IMPLEMENTED);
 }
 
+/**
+ * ixgbe_setup_internal_phy - Configure integrated PHY
+ * @hw: pointer to hardware structure
+ *
+ * Reconfigure the integrated PHY in order to enable talk to the external PHY.
+ * Returns success if not implemented, since nothing needs to be done in this
+ * case.
+ */
+s32 ixgbe_setup_internal_phy(struct ixgbe_hw *hw)
+{
+       return ixgbe_call_func(hw, hw->phy.ops.setup_internal_link, (hw),
+                              IXGBE_SUCCESS);
+}
+
 /**
  *  ixgbe_check_phy_link - Determine link and speed status
  *  @hw: pointer to hardware structure
@@ -540,6 +599,17 @@ s32 ixgbe_setup_phy_link_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed,
                               IXGBE_NOT_IMPLEMENTED);
 }
 
+/**
+ * ixgbe_set_phy_power - Control the phy power state
+ * @hw: pointer to hardware structure
+ * @on: TRUE for on, FALSE for off
+ */
+s32 ixgbe_set_phy_power(struct ixgbe_hw *hw, bool on)
+{
+       return ixgbe_call_func(hw, hw->phy.ops.set_phy_power, (hw, on),
+                              IXGBE_NOT_IMPLEMENTED);
+}
+
 /**
  *  ixgbe_check_link - Get link and speed status
  *  @hw: pointer to hardware structure
@@ -608,6 +678,22 @@ s32 ixgbe_setup_link(struct ixgbe_hw *hw, ixgbe_link_speed speed,
                               IXGBE_NOT_IMPLEMENTED);
 }
 
+/**
+ *  ixgbe_setup_mac_link - Set link speed
+ *  @hw: pointer to hardware structure
+ *  @speed: new link speed
+ *
+ *  Configures link settings.  Restarts the link.
+ *  Performs autonegotiation if needed.
+ **/
+s32 ixgbe_setup_mac_link(struct ixgbe_hw *hw, ixgbe_link_speed speed,
+                        bool autoneg_wait_to_complete)
+{
+       return ixgbe_call_func(hw, hw->mac.ops.setup_mac_link, (hw, speed,
+                              autoneg_wait_to_complete),
+                              IXGBE_NOT_IMPLEMENTED);
+}
+
 /**
  *  ixgbe_get_link_capabilities - Returns link capabilities
  *  @hw: pointer to hardware structure
@@ -1001,6 +1087,18 @@ s32 ixgbe_fc_enable(struct ixgbe_hw *hw)
                               IXGBE_NOT_IMPLEMENTED);
 }
 
+/**
+ *  ixgbe_setup_fc - Set up flow control
+ *  @hw: pointer to hardware structure
+ *
+ *  Called at init time to set up flow control.
+ **/
+s32 ixgbe_setup_fc(struct ixgbe_hw *hw)
+{
+       return ixgbe_call_func(hw, hw->mac.ops.setup_fc, (hw),
+               IXGBE_NOT_IMPLEMENTED);
+}
+
 /**
  * ixgbe_set_fw_drv_ver - Try to send the driver version number FW
  * @hw: pointer to hardware structure
@@ -1018,6 +1116,194 @@ s32 ixgbe_set_fw_drv_ver(struct ixgbe_hw *hw, u8 maj, u8 min, u8 build,
 
 
 
+/**
+ *  ixgbe_dmac_config - Configure DMA Coalescing registers.
+ *  @hw: pointer to hardware structure
+ *
+ *  Configure DMA coalescing. If enabling dmac, dmac is activated.
+ *  When disabling dmac, dmac enable dmac bit is cleared.
+ **/
+s32 ixgbe_dmac_config(struct ixgbe_hw *hw)
+{
+       return ixgbe_call_func(hw, hw->mac.ops.dmac_config, (hw),
+                               IXGBE_NOT_IMPLEMENTED);
+}
+
+/**
+ *  ixgbe_dmac_update_tcs - Configure DMA Coalescing registers.
+ *  @hw: pointer to hardware structure
+ *
+ *  Disables dmac, updates per TC settings, and then enable dmac.
+ **/
+s32 ixgbe_dmac_update_tcs(struct ixgbe_hw *hw)
+{
+       return ixgbe_call_func(hw, hw->mac.ops.dmac_update_tcs, (hw),
+                               IXGBE_NOT_IMPLEMENTED);
+}
+
+/**
+ *  ixgbe_dmac_config_tcs - Configure DMA Coalescing registers.
+ *  @hw: pointer to hardware structure
+ *
+ *  Configure DMA coalescing threshold per TC and set high priority bit for
+ *  FCOE TC. The dmac enable bit must be cleared before configuring.
+ **/
+s32 ixgbe_dmac_config_tcs(struct ixgbe_hw *hw)
+{
+       return ixgbe_call_func(hw, hw->mac.ops.dmac_config_tcs, (hw),
+                               IXGBE_NOT_IMPLEMENTED);
+}
+
+/**
+ *  ixgbe_setup_eee - Enable/disable EEE support
+ *  @hw: pointer to the HW structure
+ *  @enable_eee: boolean flag to enable EEE
+ *
+ *  Enable/disable EEE based on enable_ee flag.
+ *  Auto-negotiation must be started after BASE-T EEE bits in PHY register 7.3C
+ *  are modified.
+ *
+ **/
+s32 ixgbe_setup_eee(struct ixgbe_hw *hw, bool enable_eee)
+{
+       return ixgbe_call_func(hw, hw->mac.ops.setup_eee, (hw, enable_eee),
+                       IXGBE_NOT_IMPLEMENTED);
+}
+
+/**
+ * ixgbe_set_source_address_pruning - Enable/Disable source address pruning
+ * @hw: pointer to hardware structure
+ * @enbale: enable or disable source address pruning
+ * @pool: Rx pool - Rx pool to toggle source address pruning
+ **/
+void ixgbe_set_source_address_pruning(struct ixgbe_hw *hw, bool enable,
+                                     unsigned int pool)
+{
+       if (hw->mac.ops.set_source_address_pruning)
+               hw->mac.ops.set_source_address_pruning(hw, enable, pool);
+}
+
+/**
+ *  ixgbe_set_ethertype_anti_spoofing - Enable/Disable Ethertype anti-spoofing
+ *  @hw: pointer to hardware structure
+ *  @enable: enable or disable switch for Ethertype anti-spoofing
+ *  @vf: Virtual Function pool - VF Pool to set for Ethertype anti-spoofing
+ *
+ **/
+void ixgbe_set_ethertype_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf)
+{
+       if (hw->mac.ops.set_ethertype_anti_spoofing)
+               hw->mac.ops.set_ethertype_anti_spoofing(hw, enable, vf);
+}
+
+/**
+ *  ixgbe_read_iosf_sb_reg - Read 32 bit PHY register
+ *  @hw: pointer to hardware structure
+ *  @reg_addr: 32 bit address of PHY register to read
+ *  @device_type: type of device you want to communicate with
+ *  @phy_data: Pointer to read data from PHY register
+ *
+ *  Reads a value from a specified PHY register
+ **/
+s32 ixgbe_read_iosf_sb_reg(struct ixgbe_hw *hw, u32 reg_addr,
+                          u32 device_type, u32 *phy_data)
+{
+       return ixgbe_call_func(hw, hw->mac.ops.read_iosf_sb_reg, (hw, reg_addr,
+                              device_type, phy_data), IXGBE_NOT_IMPLEMENTED);
+}
+
+/**
+ *  ixgbe_write_iosf_sb_reg - Write 32 bit register through IOSF Sideband
+ *  @hw: pointer to hardware structure
+ *  @reg_addr: 32 bit PHY register to write
+ *  @device_type: type of device you want to communicate with
+ *  @phy_data: Data to write to the PHY register
+ *
+ *  Writes a value to specified PHY register
+ **/
+s32 ixgbe_write_iosf_sb_reg(struct ixgbe_hw *hw, u32 reg_addr,
+                           u32 device_type, u32 phy_data)
+{
+       return ixgbe_call_func(hw, hw->mac.ops.write_iosf_sb_reg, (hw, reg_addr,
+                              device_type, phy_data), IXGBE_NOT_IMPLEMENTED);
+}
+
+/**
+ *  ixgbe_disable_mdd - Disable malicious driver detection
+ *  @hw: pointer to hardware structure
+ *
+ **/
+void ixgbe_disable_mdd(struct ixgbe_hw *hw)
+{
+       if (hw->mac.ops.disable_mdd)
+               hw->mac.ops.disable_mdd(hw);
+}
+
+/**
+ *  ixgbe_enable_mdd - Enable malicious driver detection
+ *  @hw: pointer to hardware structure
+ *
+ **/
+void ixgbe_enable_mdd(struct ixgbe_hw *hw)
+{
+       if (hw->mac.ops.enable_mdd)
+               hw->mac.ops.enable_mdd(hw);
+}
+
+/**
+ *  ixgbe_mdd_event - Handle malicious driver detection event
+ *  @hw: pointer to hardware structure
+ *  @vf_bitmap: vf bitmap of malicious vfs
+ *
+ **/
+void ixgbe_mdd_event(struct ixgbe_hw *hw, u32 *vf_bitmap)
+{
+       if (hw->mac.ops.mdd_event)
+               hw->mac.ops.mdd_event(hw, vf_bitmap);
+}
+
+/**
+ *  ixgbe_restore_mdd_vf - Restore VF that was disabled during malicious driver
+ *  detection event
+ *  @hw: pointer to hardware structure
+ *  @vf: vf index
+ *
+ **/
+void ixgbe_restore_mdd_vf(struct ixgbe_hw *hw, u32 vf)
+{
+       if (hw->mac.ops.restore_mdd_vf)
+               hw->mac.ops.restore_mdd_vf(hw, vf);
+}
+
+/**
+ *  ixgbe_enter_lplu - Transition to low power states
+ *  @hw: pointer to hardware structure
+ *
+ * Configures Low Power Link Up on transition to low power states
+ * (from D0 to non-D0).
+ **/
+s32 ixgbe_enter_lplu(struct ixgbe_hw *hw)
+{
+       return ixgbe_call_func(hw, hw->phy.ops.enter_lplu, (hw),
+                               IXGBE_NOT_IMPLEMENTED);
+}
+
+/**
+ * ixgbe_handle_lasi - Handle external Base T PHY interrupt
+ * @hw: pointer to hardware structure
+ *
+ * Handle external Base T PHY interrupt. If high temperature
+ * failure alarm then return error, else if link status change
+ * then setup internal/external PHY link
+ *
+ * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature
+ * failure alarm, else return PHY access status.
+ */
+s32 ixgbe_handle_lasi(struct ixgbe_hw *hw)
+{
+       return ixgbe_call_func(hw, hw->phy.ops.handle_lasi, (hw),
+                               IXGBE_NOT_IMPLEMENTED);
+}
 
 /**
  *  ixgbe_read_analog_reg8 - Reads 8 bit analog register
@@ -1064,6 +1350,7 @@ s32 ixgbe_init_uta_tables(struct ixgbe_hw *hw)
  *  ixgbe_read_i2c_byte - Reads 8 bit word over I2C at specified device address
  *  @hw: pointer to hardware structure
  *  @byte_offset: byte offset to read
+ *  @dev_addr: I2C bus address to read from
  *  @data: value read
  *
  *  Performs byte read operation to SFP module's EEPROM over I2C interface.
@@ -1075,10 +1362,60 @@ s32 ixgbe_read_i2c_byte(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr,
                               dev_addr, data), IXGBE_NOT_IMPLEMENTED);
 }
 
+/**
+ *  ixgbe_read_i2c_byte_unlocked - Reads 8 bit word via I2C from device address
+ *  @hw: pointer to hardware structure
+ *  @byte_offset: byte offset to read
+ *  @dev_addr: I2C bus address to read from
+ *  @data: value read
+ *
+ *  Performs byte read operation to SFP module's EEPROM over I2C interface.
+ **/
+s32 ixgbe_read_i2c_byte_unlocked(struct ixgbe_hw *hw, u8 byte_offset,
+                                u8 dev_addr, u8 *data)
+{
+       return ixgbe_call_func(hw, hw->phy.ops.read_i2c_byte_unlocked,
+                              (hw, byte_offset, dev_addr, data),
+                              IXGBE_NOT_IMPLEMENTED);
+}
+
+/**
+ * ixgbe_read_i2c_combined - Perform I2C read combined operation
+ * @hw: pointer to the hardware structure
+ * @addr: I2C bus address to read from
+ * @reg: I2C device register to read from
+ * @val: pointer to location to receive read value
+ *
+ * Returns an error code on error.
+ */
+s32 ixgbe_read_i2c_combined(struct ixgbe_hw *hw, u8 addr, u16 reg, u16 *val)
+{
+       return ixgbe_call_func(hw, hw->phy.ops.read_i2c_combined, (hw, addr,
+                              reg, val), IXGBE_NOT_IMPLEMENTED);
+}
+
+/**
+ * ixgbe_read_i2c_combined_unlocked - Perform I2C read combined operation
+ * @hw: pointer to the hardware structure
+ * @addr: I2C bus address to read from
+ * @reg: I2C device register to read from
+ * @val: pointer to location to receive read value
+ *
+ * Returns an error code on error.
+ **/
+s32 ixgbe_read_i2c_combined_unlocked(struct ixgbe_hw *hw, u8 addr, u16 reg,
+                                    u16 *val)
+{
+       return ixgbe_call_func(hw, hw->phy.ops.read_i2c_combined_unlocked,
+                              (hw, addr, reg, val),
+                              IXGBE_NOT_IMPLEMENTED);
+}
+
 /**
  *  ixgbe_write_i2c_byte - Writes 8 bit word over I2C
  *  @hw: pointer to hardware structure
  *  @byte_offset: byte offset to write
+ *  @dev_addr: I2C bus address to write to
  *  @data: value to write
  *
  *  Performs byte write operation to SFP module's EEPROM over I2C interface
@@ -1091,6 +1428,55 @@ s32 ixgbe_write_i2c_byte(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr,
                               dev_addr, data), IXGBE_NOT_IMPLEMENTED);
 }
 
+/**
+ *  ixgbe_write_i2c_byte_unlocked - Writes 8 bit word over I2C
+ *  @hw: pointer to hardware structure
+ *  @byte_offset: byte offset to write
+ *  @dev_addr: I2C bus address to write to
+ *  @data: value to write
+ *
+ *  Performs byte write operation to SFP module's EEPROM over I2C interface
+ *  at a specified device address.
+ **/
+s32 ixgbe_write_i2c_byte_unlocked(struct ixgbe_hw *hw, u8 byte_offset,
+                                 u8 dev_addr, u8 data)
+{
+       return ixgbe_call_func(hw, hw->phy.ops.write_i2c_byte_unlocked,
+                              (hw, byte_offset, dev_addr, data),
+                              IXGBE_NOT_IMPLEMENTED);
+}
+
+/**
+ * ixgbe_write_i2c_combined - Perform I2C write combined operation
+ * @hw: pointer to the hardware structure
+ * @addr: I2C bus address to write to
+ * @reg: I2C device register to write to
+ * @val: value to write
+ *
+ * Returns an error code on error.
+ */
+s32 ixgbe_write_i2c_combined(struct ixgbe_hw *hw, u8 addr, u16 reg, u16 val)
+{
+       return ixgbe_call_func(hw, hw->phy.ops.write_i2c_combined, (hw, addr,
+                              reg, val), IXGBE_NOT_IMPLEMENTED);
+}
+
+/**
+ * ixgbe_write_i2c_combined_unlocked - Perform I2C write combined operation
+ * @hw: pointer to the hardware structure
+ * @addr: I2C bus address to write to
+ * @reg: I2C device register to write to
+ * @val: value to write
+ *
+ * Returns an error code on error.
+ **/
+s32 ixgbe_write_i2c_combined_unlocked(struct ixgbe_hw *hw, u8 addr, u16 reg,
+                                     u16 val)
+{
+       return ixgbe_call_func(hw, hw->phy.ops.write_i2c_combined_unlocked,
+                              (hw, addr, reg, val), IXGBE_NOT_IMPLEMENTED);
+}
+
 /**
  *  ixgbe_write_i2c_eeprom - Writes 8 bit EEPROM word over I2C interface
  *  @hw: pointer to hardware structure
@@ -1179,7 +1565,7 @@ s32 ixgbe_enable_sec_rx_path(struct ixgbe_hw *hw)
  *  Acquires the SWFW semaphore through SW_FW_SYNC register for the specified
  *  function (CSR, PHY0, PHY1, EEPROM, Flash)
  **/
-s32 ixgbe_acquire_swfw_semaphore(struct ixgbe_hw *hw, u16 mask)
+s32 ixgbe_acquire_swfw_semaphore(struct ixgbe_hw *hw, u32 mask)
 {
        return ixgbe_call_func(hw, hw->mac.ops.acquire_swfw_sync,
                               (hw, mask), IXGBE_NOT_IMPLEMENTED);
@@ -1193,9 +1579,34 @@ s32 ixgbe_acquire_swfw_semaphore(struct ixgbe_hw *hw, u16 mask)
  *  Releases the SWFW semaphore through SW_FW_SYNC register for the specified
  *  function (CSR, PHY0, PHY1, EEPROM, Flash)
  **/
-void ixgbe_release_swfw_semaphore(struct ixgbe_hw *hw, u16 mask)
+void ixgbe_release_swfw_semaphore(struct ixgbe_hw *hw, u32 mask)
 {
        if (hw->mac.ops.release_swfw_sync)
                hw->mac.ops.release_swfw_sync(hw, mask);
 }
 
+
+void ixgbe_disable_rx(struct ixgbe_hw *hw)
+{
+       if (hw->mac.ops.disable_rx)
+               hw->mac.ops.disable_rx(hw);
+}
+
+void ixgbe_enable_rx(struct ixgbe_hw *hw)
+{
+       if (hw->mac.ops.enable_rx)
+               hw->mac.ops.enable_rx(hw);
+}
+
+/**
+ *  ixgbe_set_rate_select_speed - Set module link speed
+ *  @hw: pointer to hardware structure
+ *  @speed: link speed to set
+ *
+ *  Set module link speed via the rate select.
+ */
+void ixgbe_set_rate_select_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed)
+{
+       if (hw->mac.ops.set_rate_select_speed)
+               hw->mac.ops.set_rate_select_speed(hw, speed);
+}
index 91023ae..1fef064 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2013, Intel Corporation 
+  Copyright (c) 2001-2014, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -44,6 +44,8 @@ s32 ixgbe_init_shared_code(struct ixgbe_hw *hw);
 extern s32 ixgbe_init_ops_82598(struct ixgbe_hw *hw);
 extern s32 ixgbe_init_ops_82599(struct ixgbe_hw *hw);
 extern s32 ixgbe_init_ops_X540(struct ixgbe_hw *hw);
+extern s32 ixgbe_init_ops_X550(struct ixgbe_hw *hw);
+extern s32 ixgbe_init_ops_X550EM(struct ixgbe_hw *hw);
 extern s32 ixgbe_init_ops_vf(struct ixgbe_hw *hw);
 
 s32 ixgbe_set_mac_type(struct ixgbe_hw *hw);
@@ -69,17 +71,21 @@ s32 ixgbe_write_phy_reg(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type,
                        u16 phy_data);
 
 s32 ixgbe_setup_phy_link(struct ixgbe_hw *hw);
+s32 ixgbe_setup_internal_phy(struct ixgbe_hw *hw);
 s32 ixgbe_check_phy_link(struct ixgbe_hw *hw,
                         ixgbe_link_speed *speed,
                         bool *link_up);
 s32 ixgbe_setup_phy_link_speed(struct ixgbe_hw *hw,
                               ixgbe_link_speed speed,
                               bool autoneg_wait_to_complete);
+s32 ixgbe_set_phy_power(struct ixgbe_hw *, bool on);
 void ixgbe_disable_tx_laser(struct ixgbe_hw *hw);
 void ixgbe_enable_tx_laser(struct ixgbe_hw *hw);
 void ixgbe_flap_tx_laser(struct ixgbe_hw *hw);
 s32 ixgbe_setup_link(struct ixgbe_hw *hw, ixgbe_link_speed speed,
                     bool autoneg_wait_to_complete);
+s32 ixgbe_setup_mac_link(struct ixgbe_hw *hw, ixgbe_link_speed speed,
+                        bool autoneg_wait_to_complete);
 s32 ixgbe_check_link(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
                     bool *link_up, bool link_up_wait_to_complete);
 s32 ixgbe_get_link_capabilities(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
@@ -123,6 +129,7 @@ s32 ixgbe_set_vfta(struct ixgbe_hw *hw, u32 vlan,
 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 ixgbe_setup_fc(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);
@@ -139,16 +146,17 @@ s32 ixgbe_enable_sec_rx_path(struct ixgbe_hw *hw);
 s32 ixgbe_mng_fw_enabled(struct ixgbe_hw *hw);
 s32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw);
 s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 fdirctrl);
-s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 fdirctrl);
+s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 fdirctrl,
+                                       bool cloud_mode);
 s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
                                          union ixgbe_atr_hash_dword input,
                                          union ixgbe_atr_hash_dword common,
                                          u8 queue);
 s32 ixgbe_fdir_set_input_mask_82599(struct ixgbe_hw *hw,
-                                   union ixgbe_atr_input *input_mask);
+                                   union ixgbe_atr_input *input_mask, bool cloud_mode);
 s32 ixgbe_fdir_write_perfect_filter_82599(struct ixgbe_hw *hw,
                                          union ixgbe_atr_input *input,
-                                         u16 soft_id, u8 queue);
+                                         u16 soft_id, u8 queue, bool cloud_mode);
 s32 ixgbe_fdir_erase_perfect_filter_82599(struct ixgbe_hw *hw,
                                          union ixgbe_atr_input *input,
                                          u16 soft_id);
@@ -156,7 +164,8 @@ s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
                                        union ixgbe_atr_input *input,
                                        union ixgbe_atr_input *mask,
                                        u16 soft_id,
-                                       u8 queue);
+                                       u8 queue,
+                                       bool cloud_mode);
 void ixgbe_atr_compute_perfect_hash_82599(union ixgbe_atr_input *input,
                                          union ixgbe_atr_input *mask);
 u32 ixgbe_atr_compute_sig_hash_82599(union ixgbe_atr_hash_dword input,
@@ -164,16 +173,47 @@ u32 ixgbe_atr_compute_sig_hash_82599(union ixgbe_atr_hash_dword input,
 bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw);
 s32 ixgbe_read_i2c_byte(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr,
                        u8 *data);
+s32 ixgbe_read_i2c_byte_unlocked(struct ixgbe_hw *hw, u8 byte_offset,
+                                u8 dev_addr, u8 *data);
+s32 ixgbe_read_i2c_combined(struct ixgbe_hw *hw, u8 addr, u16 reg, u16 *val);
+s32 ixgbe_read_i2c_combined_unlocked(struct ixgbe_hw *hw, u8 addr, u16 reg,
+                                    u16 *val);
 s32 ixgbe_write_i2c_byte(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr,
                         u8 data);
+s32 ixgbe_write_i2c_byte_unlocked(struct ixgbe_hw *hw, u8 byte_offset,
+                                 u8 dev_addr, u8 data);
+s32 ixgbe_write_i2c_combined(struct ixgbe_hw *hw, u8 addr, u16 reg, u16 val);
+s32 ixgbe_write_i2c_combined_unlocked(struct ixgbe_hw *hw, u8 addr, u16 reg,
+                                     u16 val);
 s32 ixgbe_write_i2c_eeprom(struct ixgbe_hw *hw, u8 byte_offset, u8 eeprom_data);
 s32 ixgbe_get_san_mac_addr(struct ixgbe_hw *hw, u8 *san_mac_addr);
 s32 ixgbe_set_san_mac_addr(struct ixgbe_hw *hw, u8 *san_mac_addr);
 s32 ixgbe_get_device_caps(struct ixgbe_hw *hw, u16 *device_caps);
-s32 ixgbe_acquire_swfw_semaphore(struct ixgbe_hw *hw, u16 mask);
-void ixgbe_release_swfw_semaphore(struct ixgbe_hw *hw, u16 mask);
+s32 ixgbe_acquire_swfw_semaphore(struct ixgbe_hw *hw, u32 mask);
+void ixgbe_release_swfw_semaphore(struct ixgbe_hw *hw, u32 mask);
 s32 ixgbe_get_wwn_prefix(struct ixgbe_hw *hw, u16 *wwnn_prefix,
                         u16 *wwpn_prefix);
 s32 ixgbe_get_fcoe_boot_status(struct ixgbe_hw *hw, u16 *bs);
+s32 ixgbe_dmac_config(struct ixgbe_hw *hw);
+s32 ixgbe_dmac_update_tcs(struct ixgbe_hw *hw);
+s32 ixgbe_dmac_config_tcs(struct ixgbe_hw *hw);
+s32 ixgbe_setup_eee(struct ixgbe_hw *hw, bool enable_eee);
+void ixgbe_set_source_address_pruning(struct ixgbe_hw *hw, bool enable,
+                                     unsigned int vf);
+void ixgbe_set_ethertype_anti_spoofing(struct ixgbe_hw *hw, bool enable,
+                                      int vf);
+s32 ixgbe_read_iosf_sb_reg(struct ixgbe_hw *hw, u32 reg_addr,
+                       u32 device_type, u32 *phy_data);
+s32 ixgbe_write_iosf_sb_reg(struct ixgbe_hw *hw, u32 reg_addr,
+                       u32 device_type, u32 phy_data);
+void ixgbe_disable_mdd(struct ixgbe_hw *hw);
+void ixgbe_enable_mdd(struct ixgbe_hw *hw);
+void ixgbe_mdd_event(struct ixgbe_hw *hw, u32 *vf_bitmap);
+void ixgbe_restore_mdd_vf(struct ixgbe_hw *hw, u32 vf);
+s32 ixgbe_enter_lplu(struct ixgbe_hw *hw);
+s32 ixgbe_handle_lasi(struct ixgbe_hw *hw);
+void ixgbe_set_rate_select_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed);
+void ixgbe_disable_rx(struct ixgbe_hw *hw);
+void ixgbe_enable_rx(struct ixgbe_hw *hw);
 
 #endif /* _IXGBE_API_H_ */
index 52f0ffa..0ed2047 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2013, Intel Corporation 
+  Copyright (c) 2001-2014, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -75,62 +75,67 @@ s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw)
        DEBUGFUNC("ixgbe_init_ops_generic");
 
        /* EEPROM */
-       eeprom->ops.init_params = &ixgbe_init_eeprom_params_generic;
+       eeprom->ops.init_params = ixgbe_init_eeprom_params_generic;
        /* If EEPROM is valid (bit 8 = 1), use EERD otherwise use bit bang */
        if (eec & IXGBE_EEC_PRES) {
-               eeprom->ops.read = &ixgbe_read_eerd_generic;
-               eeprom->ops.read_buffer = &ixgbe_read_eerd_buffer_generic;
+               eeprom->ops.read = ixgbe_read_eerd_generic;
+               eeprom->ops.read_buffer = ixgbe_read_eerd_buffer_generic;
        } else {
-               eeprom->ops.read = &ixgbe_read_eeprom_bit_bang_generic;
+               eeprom->ops.read = ixgbe_read_eeprom_bit_bang_generic;
                eeprom->ops.read_buffer =
-                                &ixgbe_read_eeprom_buffer_bit_bang_generic;
+                                ixgbe_read_eeprom_buffer_bit_bang_generic;
        }
-       eeprom->ops.write = &ixgbe_write_eeprom_generic;
-       eeprom->ops.write_buffer = &ixgbe_write_eeprom_buffer_bit_bang_generic;
+       eeprom->ops.write = ixgbe_write_eeprom_generic;
+       eeprom->ops.write_buffer = ixgbe_write_eeprom_buffer_bit_bang_generic;
        eeprom->ops.validate_checksum =
-                                     &ixgbe_validate_eeprom_checksum_generic;
-       eeprom->ops.update_checksum = &ixgbe_update_eeprom_checksum_generic;
-       eeprom->ops.calc_checksum = &ixgbe_calc_eeprom_checksum_generic;
+                                     ixgbe_validate_eeprom_checksum_generic;
+       eeprom->ops.update_checksum = ixgbe_update_eeprom_checksum_generic;
+       eeprom->ops.calc_checksum = ixgbe_calc_eeprom_checksum_generic;
 
        /* MAC */
-       mac->ops.init_hw = &ixgbe_init_hw_generic;
+       mac->ops.init_hw = ixgbe_init_hw_generic;
        mac->ops.reset_hw = NULL;
-       mac->ops.start_hw = &ixgbe_start_hw_generic;
-       mac->ops.clear_hw_cntrs = &ixgbe_clear_hw_cntrs_generic;
+       mac->ops.start_hw = ixgbe_start_hw_generic;
+       mac->ops.clear_hw_cntrs = ixgbe_clear_hw_cntrs_generic;
        mac->ops.get_media_type = NULL;
        mac->ops.get_supported_physical_layer = NULL;
-       mac->ops.enable_rx_dma = &ixgbe_enable_rx_dma_generic;
-       mac->ops.get_mac_addr = &ixgbe_get_mac_addr_generic;
-       mac->ops.stop_adapter = &ixgbe_stop_adapter_generic;
-       mac->ops.get_bus_info = &ixgbe_get_bus_info_generic;
-       mac->ops.set_lan_id = &ixgbe_set_lan_id_multi_port_pcie;
-       mac->ops.acquire_swfw_sync = &ixgbe_acquire_swfw_sync;
-       mac->ops.release_swfw_sync = &ixgbe_release_swfw_sync;
+       mac->ops.enable_rx_dma = ixgbe_enable_rx_dma_generic;
+       mac->ops.get_mac_addr = ixgbe_get_mac_addr_generic;
+       mac->ops.stop_adapter = ixgbe_stop_adapter_generic;
+       mac->ops.get_bus_info = ixgbe_get_bus_info_generic;
+       mac->ops.set_lan_id = ixgbe_set_lan_id_multi_port_pcie;
+       mac->ops.acquire_swfw_sync = ixgbe_acquire_swfw_sync;
+       mac->ops.release_swfw_sync = ixgbe_release_swfw_sync;
+       mac->ops.prot_autoc_read = prot_autoc_read_generic;
+       mac->ops.prot_autoc_write = prot_autoc_write_generic;
 
        /* LEDs */
-       mac->ops.led_on = &ixgbe_led_on_generic;
-       mac->ops.led_off = &ixgbe_led_off_generic;
-       mac->ops.blink_led_start = &ixgbe_blink_led_start_generic;
-       mac->ops.blink_led_stop = &ixgbe_blink_led_stop_generic;
+       mac->ops.led_on = ixgbe_led_on_generic;
+       mac->ops.led_off = ixgbe_led_off_generic;
+       mac->ops.blink_led_start = ixgbe_blink_led_start_generic;
+       mac->ops.blink_led_stop = ixgbe_blink_led_stop_generic;
 
        /* RAR, Multicast, VLAN */
-       mac->ops.set_rar = &ixgbe_set_rar_generic;
-       mac->ops.clear_rar = &ixgbe_clear_rar_generic;
+       mac->ops.set_rar = ixgbe_set_rar_generic;
+       mac->ops.clear_rar = ixgbe_clear_rar_generic;
        mac->ops.insert_mac_addr = NULL;
        mac->ops.set_vmdq = NULL;
        mac->ops.clear_vmdq = NULL;
-       mac->ops.init_rx_addrs = &ixgbe_init_rx_addrs_generic;
-       mac->ops.update_uc_addr_list = &ixgbe_update_uc_addr_list_generic;
-       mac->ops.update_mc_addr_list = &ixgbe_update_mc_addr_list_generic;
-       mac->ops.enable_mc = &ixgbe_enable_mc_generic;
-       mac->ops.disable_mc = &ixgbe_disable_mc_generic;
+       mac->ops.init_rx_addrs = ixgbe_init_rx_addrs_generic;
+       mac->ops.update_uc_addr_list = ixgbe_update_uc_addr_list_generic;
+       mac->ops.update_mc_addr_list = ixgbe_update_mc_addr_list_generic;
+       mac->ops.enable_mc = ixgbe_enable_mc_generic;
+       mac->ops.disable_mc = ixgbe_disable_mc_generic;
        mac->ops.clear_vfta = NULL;
        mac->ops.set_vfta = NULL;
        mac->ops.set_vlvf = NULL;
        mac->ops.init_uta_tables = NULL;
+       mac->ops.enable_rx = ixgbe_enable_rx_generic;
+       mac->ops.disable_rx = ixgbe_disable_rx_generic;
 
        /* Flow Control */
-       mac->ops.fc_enable = &ixgbe_fc_enable_generic;
+       mac->ops.fc_enable = ixgbe_fc_enable_generic;
+       mac->ops.setup_fc = ixgbe_setup_fc_generic;
 
        /* Link */
        mac->ops.get_link_capabilities = NULL;
@@ -162,6 +167,7 @@ bool ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
 
        switch (hw->phy.media_type) {
        case ixgbe_media_type_fiber_fixed:
+       case ixgbe_media_type_fiber_qsfp:
        case ixgbe_media_type_fiber:
                hw->mac.ops.check_link(hw, &speed, &link_up, FALSE);
                /* if link is down, assume supported */
@@ -179,7 +185,10 @@ bool ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
                switch (hw->device_id) {
                case IXGBE_DEV_ID_82599_T3_LOM:
                case IXGBE_DEV_ID_X540T:
+               case IXGBE_DEV_ID_X540T1:
                case IXGBE_DEV_ID_X540_BYPASS:
+               case IXGBE_DEV_ID_X550T:
+               case IXGBE_DEV_ID_X550EM_X_10G_T:
                        supported = TRUE;
                        break;
                default:
@@ -196,24 +205,21 @@ bool ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
 }
 
 /**
- *  ixgbe_setup_fc - Set up flow control
+ *  ixgbe_setup_fc_generic - 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 ixgbe_setup_fc_generic(struct ixgbe_hw *hw)
 {
        s32 ret_val = IXGBE_SUCCESS;
        u32 reg = 0, reg_bp = 0;
        u16 reg_cu = 0;
-       bool got_lock = FALSE;
+       bool locked = FALSE;
 
-       DEBUGFUNC("ixgbe_setup_fc");
+       DEBUGFUNC("ixgbe_setup_fc_generic");
 
-       /*
-        * Validate the requested mode.  Strict IEEE mode does not allow
-        * ixgbe_fc_rx_pause because it will cause us to fail at UNH.
-        */
+       /* Validate the requested mode */
        if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
                ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED,
                           "ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
@@ -234,11 +240,18 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw)
         * we link at 10G, the 1G advertisement is harmless and vice versa.
         */
        switch (hw->phy.media_type) {
+       case ixgbe_media_type_backplane:
+               /* some MAC's need RMW protection on AUTOC */
+               ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &reg_bp);
+               if (ret_val != IXGBE_SUCCESS)
+                       goto out;
+
+               /* only backplane uses autoc so fall though */
        case ixgbe_media_type_fiber_fixed:
+       case ixgbe_media_type_fiber_qsfp:
        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,
@@ -310,7 +323,7 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw)
                break;
        }
 
-       if (hw->mac.type != ixgbe_mac_X540) {
+       if (hw->mac.type < ixgbe_mac_X540) {
                /*
                 * Enable auto-negotiation between the MAC & PHY;
                 * the MAC will advertise clause 37 flow control.
@@ -333,35 +346,16 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw)
         */
        if (hw->phy.media_type == ixgbe_media_type_backplane) {
                reg_bp |= IXGBE_AUTOC_AN_RESTART;
-               /* Need the SW/FW semaphore around AUTOC writes if 82599 and
-                * LESM is on, likewise reset_pipeline requries the lock as
-                * it also writes AUTOC.
-                */
-               if ((hw->mac.type == ixgbe_mac_82599EB) &&
-                   ixgbe_verify_lesm_fw_enabled_82599(hw)) {
-                       ret_val = hw->mac.ops.acquire_swfw_sync(hw,
-                                                       IXGBE_GSSR_MAC_CSR_SM);
-                       if (ret_val != IXGBE_SUCCESS) {
-                               ret_val = IXGBE_ERR_SWFW_SYNC;
-                               goto out;
-                       }
-                       got_lock = TRUE;
-               }
-
-               IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_bp);
-               if (hw->mac.type == ixgbe_mac_82599EB)
-                       ixgbe_reset_pipeline_82599(hw);
-
-               if (got_lock)
-                       hw->mac.ops.release_swfw_sync(hw,
-                                                     IXGBE_GSSR_MAC_CSR_SM);
+               ret_val = hw->mac.ops.prot_autoc_write(hw, reg_bp, locked);
+               if (ret_val)
+                       goto out;
        } else if ((hw->phy.media_type == ixgbe_media_type_copper) &&
                    (ixgbe_device_supports_autoneg_fc(hw))) {
                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);
+       DEBUGOUT1("Set up FC; PCS1GLCTL = 0x%08X\n", reg);
 out:
        return ret_val;
 }
@@ -575,7 +569,7 @@ s32 ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw)
                }
        }
 
-       if (hw->mac.type == ixgbe_mac_X540) {
+       if (hw->mac.type == ixgbe_mac_X550 || hw->mac.type == ixgbe_mac_X540) {
                if (hw->phy.id == 0)
                        ixgbe_identify_phy(hw);
                hw->phy.ops.read_reg(hw, IXGBE_PCRC8ECL,
@@ -793,7 +787,7 @@ s32 ixgbe_read_pba_raw(struct ixgbe_hw *hw, u16 *eeprom_buf,
                                return ret_val;
                } else {
                        if (eeprom_buf_size > (u32)(pba->word[1] +
-                                             pba->pba_block[0])) {
+                                             pba_block_size)) {
                                memcpy(pba->pba_block,
                                       &eeprom_buf[pba->word[1]],
                                       pba_block_size * sizeof(u16));
@@ -965,7 +959,8 @@ void ixgbe_set_pci_config_data_generic(struct ixgbe_hw *hw, u16 link_status)
 {
        struct ixgbe_mac_info *mac = &hw->mac;
 
-       hw->bus.type = ixgbe_bus_type_pci_express;
+       if (hw->bus.type == ixgbe_bus_type_unknown)
+               hw->bus.type = ixgbe_bus_type_pci_express;
 
        switch (link_status & IXGBE_PCI_LINK_WIDTH) {
        case IXGBE_PCI_LINK_WIDTH_1:
@@ -1071,7 +1066,7 @@ s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw)
        hw->adapter_stopped = TRUE;
 
        /* Disable the receive unit */
-       IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, 0);
+       ixgbe_disable_rx(hw);
 
        /* Clear interrupt mask to stop interrupts from being generated */
        IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_IRQ_CLEAR_MASK);
@@ -1096,7 +1091,7 @@ s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw)
        msec_delay(2);
 
        /*
-        * Prevent the PCI-E bus from from hanging by disabling PCI-E master
+        * Prevent the PCI-E bus from hanging by disabling PCI-E master
         * access and verify no pending requests
         */
        return ixgbe_disable_pcie_master(hw);
@@ -1903,7 +1898,7 @@ static s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw)
 
                usec_delay(5);
                ixgbe_standby_eeprom(hw);
-       }
+       };
 
        /*
         * On some parts, SPI write time could vary from 0-20mSec on 3.3V
@@ -1989,7 +1984,7 @@ static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data,
                 * EEPROM
                 */
                mask = mask >> 1;
-       }
+       };
 
        /* We leave the "DI" bit set to "0" when we leave this routine. */
        eec &= ~IXGBE_EEC_DI;
@@ -2107,8 +2102,10 @@ static void ixgbe_release_eeprom(struct ixgbe_hw *hw)
 /**
  *  ixgbe_calc_eeprom_checksum_generic - Calculates and returns the checksum
  *  @hw: pointer to hardware structure
+ *
+ *  Returns a negative error code on error, or the 16-bit checksum
  **/
-u16 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw)
+s32 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw)
 {
        u16 i;
        u16 j;
@@ -2121,33 +2118,44 @@ u16 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw)
 
        /* Include 0x0-0x3F in the checksum */
        for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) {
-               if (hw->eeprom.ops.read(hw, i, &word) != IXGBE_SUCCESS) {
+               if (hw->eeprom.ops.read(hw, i, &word)) {
                        DEBUGOUT("EEPROM read failed\n");
-                       break;
+                       return IXGBE_ERR_EEPROM;
                }
                checksum += word;
        }
 
        /* Include all data from pointers except for the fw pointer */
        for (i = IXGBE_PCIE_ANALOG_PTR; i < IXGBE_FW_PTR; i++) {
-               hw->eeprom.ops.read(hw, i, &pointer);
+               if (hw->eeprom.ops.read(hw, i, &pointer)) {
+                       DEBUGOUT("EEPROM read failed\n");
+                       return IXGBE_ERR_EEPROM;
+               }
+
+               /* If the pointer seems invalid */
+               if (pointer == 0xFFFF || pointer == 0)
+                       continue;
 
-               /* Make sure the pointer seems valid */
-               if (pointer != 0xFFFF && pointer != 0) {
-                       hw->eeprom.ops.read(hw, pointer, &length);
+               if (hw->eeprom.ops.read(hw, pointer, &length)) {
+                       DEBUGOUT("EEPROM read failed\n");
+                       return IXGBE_ERR_EEPROM;
+               }
+
+               if (length == 0xFFFF || length == 0)
+                       continue;
 
-                       if (length != 0xFFFF && length != 0) {
-                               for (j = pointer+1; j <= pointer+length; j++) {
-                                       hw->eeprom.ops.read(hw, j, &word);
-                                       checksum += word;
-                               }
+               for (j = pointer + 1; j <= pointer + length; j++) {
+                       if (hw->eeprom.ops.read(hw, j, &word)) {
+                               DEBUGOUT("EEPROM read failed\n");
+                               return IXGBE_ERR_EEPROM;
                        }
+                       checksum += word;
                }
        }
 
        checksum = (u16)IXGBE_EEPROM_SUM - checksum;
 
-       return checksum;
+       return (s32)checksum;
 }
 
 /**
@@ -2167,32 +2175,38 @@ s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw,
 
        DEBUGFUNC("ixgbe_validate_eeprom_checksum_generic");
 
-       /*
-        * Read the first word from the EEPROM. If this times out or fails, do
+       /* Read the first word from the EEPROM. If this times out or fails, do
         * not continue or we could be in for a very long wait while every
         * EEPROM read fails
         */
        status = hw->eeprom.ops.read(hw, 0, &checksum);
+       if (status) {
+               DEBUGOUT("EEPROM read failed\n");
+               return status;
+       }
 
-       if (status == IXGBE_SUCCESS) {
-               checksum = hw->eeprom.ops.calc_checksum(hw);
-
-               hw->eeprom.ops.read(hw, IXGBE_EEPROM_CHECKSUM, &read_checksum);
+       status = hw->eeprom.ops.calc_checksum(hw);
+       if (status < 0)
+               return status;
 
-               /*
-                * Verify read checksum from EEPROM is the same as
-                * calculated checksum
-                */
-               if (read_checksum != checksum)
-                       status = IXGBE_ERR_EEPROM_CHECKSUM;
+       checksum = (u16)(status & 0xffff);
 
-               /* If the user cares, return the calculated checksum */
-               if (checksum_val)
-                       *checksum_val = checksum;
-       } else {
+       status = hw->eeprom.ops.read(hw, IXGBE_EEPROM_CHECKSUM, &read_checksum);
+       if (status) {
                DEBUGOUT("EEPROM read failed\n");
+               return status;
        }
 
+       /* Verify read checksum from EEPROM is the same as
+        * calculated checksum
+        */
+       if (read_checksum != checksum)
+               status = IXGBE_ERR_EEPROM_CHECKSUM;
+
+       /* If the user cares, return the calculated checksum */
+       if (checksum_val)
+               *checksum_val = checksum;
+
        return status;
 }
 
@@ -2207,21 +2221,24 @@ s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw)
 
        DEBUGFUNC("ixgbe_update_eeprom_checksum_generic");
 
-       /*
-        * Read the first word from the EEPROM. If this times out or fails, do
+       /* Read the first word from the EEPROM. If this times out or fails, do
         * not continue or we could be in for a very long wait while every
         * EEPROM read fails
         */
        status = hw->eeprom.ops.read(hw, 0, &checksum);
-
-       if (status == IXGBE_SUCCESS) {
-               checksum = hw->eeprom.ops.calc_checksum(hw);
-               status = hw->eeprom.ops.write(hw, IXGBE_EEPROM_CHECKSUM,
-                                             checksum);
-       } else {
+       if (status) {
                DEBUGOUT("EEPROM read failed\n");
+               return status;
        }
 
+       status = hw->eeprom.ops.calc_checksum(hw);
+       if (status < 0)
+               return status;
+
+       checksum = (u16)(status & 0xffff);
+
+       status = hw->eeprom.ops.write(hw, IXGBE_EEPROM_CHECKSUM, checksum);
+
        return status;
 }
 
@@ -2793,10 +2810,11 @@ s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw)
                        /*
                         * 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.
+                        * to the Rx packet buffer size - 24KB.  This allows
+                        * the Tx switch to function even under heavy Rx
+                        * workloads.
                         */
-                       fcrth = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)) - 32;
+                       fcrth = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)) - 24576;
                }
 
                IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), fcrth);
@@ -2886,10 +2904,9 @@ static s32 ixgbe_fc_autoneg_fiber(struct ixgbe_hw *hw)
         */
 
        linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA);
-       if ((linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0 ||
-           (linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT)) {
-               ERROR_REPORT1(IXGBE_ERROR_POLLING,
-                            "Auto-Negotiation did not complete or timed out");
+       if ((!!(linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) ||
+           (!!(linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) {
+               DEBUGOUT("Auto-Negotiation did not complete or timed out\n");
                goto out;
        }
 
@@ -2924,16 +2941,14 @@ static s32 ixgbe_fc_autoneg_backplane(struct ixgbe_hw *hw)
         */
        links = IXGBE_READ_REG(hw, IXGBE_LINKS);
        if ((links & IXGBE_LINKS_KX_AN_COMP) == 0) {
-               ERROR_REPORT1(IXGBE_ERROR_POLLING,
-                            "Auto-Negotiation did not complete");
+               DEBUGOUT("Auto-Negotiation did not complete\n");
                goto out;
        }
 
        if (hw->mac.type == ixgbe_mac_82599EB) {
                links2 = IXGBE_READ_REG(hw, IXGBE_LINKS2);
                if ((links2 & IXGBE_LINKS2_AN_SUPPORTED) == 0) {
-                       ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED,
-                                    "Link partner is not AN enabled");
+                       DEBUGOUT("Link partner is not AN enabled\n");
                        goto out;
                }
        }
@@ -3012,6 +3027,7 @@ void ixgbe_fc_autoneg(struct ixgbe_hw *hw)
        switch (hw->phy.media_type) {
        /* Autoneg flow control on fiber adapters */
        case ixgbe_media_type_fiber_fixed:
+       case ixgbe_media_type_fiber_qsfp:
        case ixgbe_media_type_fiber:
                if (speed == IXGBE_LINK_SPEED_1GB_FULL)
                        ret_val = ixgbe_fc_autoneg_fiber(hw);
@@ -3101,6 +3117,7 @@ s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw)
 {
        s32 status = IXGBE_SUCCESS;
        u32 i, poll;
+       u16 value;
 
        DEBUGFUNC("ixgbe_disable_pcie_master");
 
@@ -3108,7 +3125,8 @@ s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw)
        IXGBE_WRITE_REG(hw, IXGBE_CTRL, IXGBE_CTRL_GIO_DIS);
 
        /* Exit if master requests are blocked */
-       if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO))
+       if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO) ||
+           IXGBE_REMOVED(hw->hw_addr))
                goto out;
 
        /* Poll for master request bit to clear */
@@ -3136,8 +3154,10 @@ s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw)
        poll = ixgbe_pcie_timeout_poll(hw);
        for (i = 0; i < poll; i++) {
                usec_delay(100);
-               if (!(IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_STATUS) &
-                   IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING))
+               value = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_STATUS);
+               if (IXGBE_REMOVED(hw->hw_addr))
+                       goto out;
+               if (!(value & IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING))
                        goto out;
        }
 
@@ -3157,7 +3177,7 @@ out:
  *  Acquires the SWFW semaphore through the GSSR register for the specified
  *  function (CSR, PHY0, PHY1, EEPROM, Flash)
  **/
-s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask)
+s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u32 mask)
 {
        u32 gssr = 0;
        u32 swmask = mask;
@@ -3204,7 +3224,7 @@ s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask)
  *  Releases the SWFW semaphore through the GSSR register for the specified
  *  function (CSR, PHY0, PHY1, EEPROM, Flash)
  **/
-void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u16 mask)
+void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u32 mask)
 {
        u32 gssr;
        u32 swmask = mask;
@@ -3257,6 +3277,37 @@ s32 ixgbe_disable_sec_rx_path_generic(struct ixgbe_hw *hw)
        return IXGBE_SUCCESS;
 }
 
+/**
+ *  prot_autoc_read_generic - Hides MAC differences needed for AUTOC read
+ *  @hw: pointer to hardware structure
+ *  @reg_val: Value we read from AUTOC
+ *
+ *  The default case requires no protection so just to the register read.
+ */
+s32 prot_autoc_read_generic(struct ixgbe_hw *hw, bool *locked, u32 *reg_val)
+{
+       *locked = FALSE;
+       *reg_val = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+       return IXGBE_SUCCESS;
+}
+
+/**
+ * prot_autoc_write_generic - Hides MAC differences needed for AUTOC write
+ * @hw: pointer to hardware structure
+ * @reg_val: value to write to AUTOC
+ * @locked: bool to indicate whether the SW/FW lock was already taken by
+ *           previous read.
+ *
+ * The default case requires no protection so just to the register write.
+ */
+s32 prot_autoc_write_generic(struct ixgbe_hw *hw, u32 reg_val, bool locked)
+{
+       UNREFERENCED_1PARAMETER(locked);
+
+       IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_val);
+       return IXGBE_SUCCESS;
+}
+
 /**
  *  ixgbe_enable_sec_rx_path_generic - Enables the receive data path
  *  @hw: pointer to hardware structure
@@ -3288,7 +3339,10 @@ s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval)
 {
        DEBUGFUNC("ixgbe_enable_rx_dma_generic");
 
-       IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, regval);
+       if (regval & IXGBE_RXCTRL_RXEN)
+               ixgbe_enable_rx(hw);
+       else
+               ixgbe_disable_rx(hw);
 
        return IXGBE_SUCCESS;
 }
@@ -3302,9 +3356,10 @@ s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index)
 {
        ixgbe_link_speed speed = 0;
        bool link_up = 0;
-       u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+       u32 autoc_reg = 0;
        u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
        s32 ret_val = IXGBE_SUCCESS;
+       bool locked = FALSE;
 
        DEBUGFUNC("ixgbe_blink_led_start_generic");
 
@@ -3315,29 +3370,18 @@ s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index)
        hw->mac.ops.check_link(hw, &speed, &link_up, FALSE);
 
        if (!link_up) {
-               /* Need the SW/FW semaphore around AUTOC writes if 82599 and
-                * LESM is on.
-                */
-               bool got_lock = FALSE;
-               if ((hw->mac.type == ixgbe_mac_82599EB) &&
-                   ixgbe_verify_lesm_fw_enabled_82599(hw)) {
-                       ret_val = hw->mac.ops.acquire_swfw_sync(hw,
-                                                       IXGBE_GSSR_MAC_CSR_SM);
-                       if (ret_val != IXGBE_SUCCESS) {
-                               ret_val = IXGBE_ERR_SWFW_SYNC;
-                               goto out;
-                       }
-                       got_lock = TRUE;
-               }
+               ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg);
+               if (ret_val != IXGBE_SUCCESS)
+                       goto out;
 
                autoc_reg |= IXGBE_AUTOC_AN_RESTART;
                autoc_reg |= IXGBE_AUTOC_FLU;
-               IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
-               IXGBE_WRITE_FLUSH(hw);
 
-               if (got_lock)
-                       hw->mac.ops.release_swfw_sync(hw,
-                                                     IXGBE_GSSR_MAC_CSR_SM);
+               ret_val = hw->mac.ops.prot_autoc_write(hw, autoc_reg, locked);
+               if (ret_val != IXGBE_SUCCESS)
+                       goto out;
+
+               IXGBE_WRITE_FLUSH(hw);
                msec_delay(10);
        }
 
@@ -3357,36 +3401,23 @@ out:
  **/
 s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index)
 {
-       u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+       u32 autoc_reg = 0;
        u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
        s32 ret_val = IXGBE_SUCCESS;
-       bool got_lock = FALSE;
+       bool locked = FALSE;
 
        DEBUGFUNC("ixgbe_blink_led_stop_generic");
-       /* Need the SW/FW semaphore around AUTOC writes if 82599 and
-        * LESM is on.
-        */
-       if ((hw->mac.type == ixgbe_mac_82599EB) &&
-           ixgbe_verify_lesm_fw_enabled_82599(hw)) {
-               ret_val = hw->mac.ops.acquire_swfw_sync(hw,
-                                               IXGBE_GSSR_MAC_CSR_SM);
-               if (ret_val != IXGBE_SUCCESS) {
-                       ret_val = IXGBE_ERR_SWFW_SYNC;
-                       goto out;
-               }
-               got_lock = TRUE;
-       }
 
+       ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg);
+       if (ret_val != IXGBE_SUCCESS)
+               goto out;
 
        autoc_reg &= ~IXGBE_AUTOC_FLU;
        autoc_reg |= IXGBE_AUTOC_AN_RESTART;
-       IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
 
-       if (hw->mac.type == ixgbe_mac_82599EB)
-               ixgbe_reset_pipeline_82599(hw);
-
-       if (got_lock)
-               hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
+       ret_val = hw->mac.ops.prot_autoc_write(hw, autoc_reg, locked);
+       if (ret_val != IXGBE_SUCCESS)
+               goto out;
 
        led_reg &= ~IXGBE_LED_MODE_MASK(index);
        led_reg &= ~IXGBE_LED_BLINK(index);
@@ -3541,6 +3572,9 @@ u16 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw)
                break;
        case ixgbe_mac_82599EB:
        case ixgbe_mac_X540:
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_x:
+       case ixgbe_mac_X550EM_a:
                pcie_offset = IXGBE_PCIE_MSIX_82599_CAPS;
                max_msix_count = IXGBE_MAX_MSIX_VECTORS_82599;
                break;
@@ -3550,6 +3584,8 @@ u16 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw)
 
        DEBUGFUNC("ixgbe_get_pcie_msix_count_generic");
        msix_count = IXGBE_READ_PCIE_WORD(hw, pcie_offset);
+       if (IXGBE_REMOVED(hw->hw_addr))
+               msix_count = 0;
        msix_count &= IXGBE_PCIE_MSIX_TBL_SZ_MASK;
 
        /* MSI-X count is zero-based in HW */
@@ -3653,6 +3689,9 @@ s32 ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
        mpsar_lo = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar));
        mpsar_hi = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar));
 
+       if (IXGBE_REMOVED(hw->hw_addr))
+               goto done;
+
        if (!mpsar_lo && !mpsar_hi)
                goto done;
 
@@ -4048,17 +4087,27 @@ s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
                        *link_up = FALSE;
        }
 
-       if ((links_reg & IXGBE_LINKS_SPEED_82599) ==
-           IXGBE_LINKS_SPEED_10G_82599)
+       switch (links_reg & IXGBE_LINKS_SPEED_82599) {
+       case IXGBE_LINKS_SPEED_10G_82599:
                *speed = IXGBE_LINK_SPEED_10GB_FULL;
-       else if ((links_reg & IXGBE_LINKS_SPEED_82599) ==
-                IXGBE_LINKS_SPEED_1G_82599)
+               if (hw->mac.type >= ixgbe_mac_X550) {
+                       if (links_reg & IXGBE_LINKS_SPEED_NON_STD)
+                               *speed = IXGBE_LINK_SPEED_2_5GB_FULL;
+               }
+               break;
+       case IXGBE_LINKS_SPEED_1G_82599:
                *speed = IXGBE_LINK_SPEED_1GB_FULL;
-       else if ((links_reg & IXGBE_LINKS_SPEED_82599) ==
-                IXGBE_LINKS_SPEED_100_82599)
+               break;
+       case IXGBE_LINKS_SPEED_100_82599:
                *speed = IXGBE_LINK_SPEED_100_FULL;
-       else
+               if (hw->mac.type >= ixgbe_mac_X550) {
+                       if (links_reg & IXGBE_LINKS_SPEED_NON_STD)
+                               *speed = IXGBE_LINK_SPEED_5GB_FULL;
+               }
+               break;
+       default:
                *speed = IXGBE_LINK_SPEED_UNKNOWN;
+       }
 
        return IXGBE_SUCCESS;
 }
@@ -4216,7 +4265,7 @@ void ixgbe_set_mac_anti_spoofing(struct ixgbe_hw *hw, bool enable, int pf)
  *  ixgbe_set_vlan_anti_spoofing - Enable/Disable VLAN anti-spoofing
  *  @hw: pointer to hardware structure
  *  @enable: enable or disable switch for VLAN anti-spoofing
- *  @pf: Virtual Function pool - VF Pool to set for VLAN anti-spoofing
+ *  @vf: Virtual Function pool - VF Pool to set for VLAN anti-spoofing
  *
  **/
 void ixgbe_set_vlan_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf)
@@ -4310,41 +4359,51 @@ u8 ixgbe_calculate_checksum(u8 *buffer, u32 length)
  *  @buffer: contains the command to write and where the return status will
  *   be placed
  *  @length: length of buffer, must be multiple of 4 bytes
+ *  @timeout: time in ms to wait for command completion
+ *  @return_data: read and return data from the buffer (TRUE) or not (FALSE)
+ *   Needed because FW structures are big endian and decoding of
+ *   these fields can be 8 bit or 16 bit based on command. Decoding
+ *   is not easily understood without making a table of commands.
+ *   So we will leave this up to the caller to read back the data
+ *   in these cases.
  *
  *  Communicates with the manageability block.  On success return IXGBE_SUCCESS
  *  else return IXGBE_ERR_HOST_INTERFACE_COMMAND.
  **/
 s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer,
-                                u32 length)
+                                u32 length, u32 timeout, bool return_data)
 {
-       u32 hicr, i, bi;
+       u32 hicr, i, bi, fwsts;
        u32 hdr_size = sizeof(struct ixgbe_hic_hdr);
-       u8 buf_len, dword_len;
-
-       s32 ret_val = IXGBE_SUCCESS;
+       u16 buf_len;
+       u16 dword_len;
 
        DEBUGFUNC("ixgbe_host_interface_command");
 
-       if (length == 0 || length & 0x3 ||
-           length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) {
-               DEBUGOUT("Buffer length failure.\n");
-               ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
-               goto out;
+       if (length == 0 || length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) {
+               DEBUGOUT1("Buffer length failure buffersize=%d.\n", length);
+               return IXGBE_ERR_HOST_INTERFACE_COMMAND;
        }
+       /* Set bit 9 of FWSTS clearing FW reset indication */
+       fwsts = IXGBE_READ_REG(hw, IXGBE_FWSTS);
+       IXGBE_WRITE_REG(hw, IXGBE_FWSTS, fwsts | IXGBE_FWSTS_FWRI);
 
        /* Check that the host interface is enabled. */
        hicr = IXGBE_READ_REG(hw, IXGBE_HICR);
        if ((hicr & IXGBE_HICR_EN) == 0) {
                DEBUGOUT("IXGBE_HOST_EN bit disabled.\n");
-               ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
-               goto out;
+               return IXGBE_ERR_HOST_INTERFACE_COMMAND;
+       }
+
+       /* Calculate length in DWORDs. We must be DWORD aligned */
+       if ((length % (sizeof(u32))) != 0) {
+               DEBUGOUT("Buffer length failure, not aligned to dword");
+               return IXGBE_ERR_INVALID_ARGUMENT;
        }
 
-       /* Calculate length in DWORDs */
        dword_len = length >> 2;
 
-       /*
-        * The device driver writes the relevant command block
+       /* The device driver writes the relevant command block
         * into the ram area.
         */
        for (i = 0; i < dword_len; i++)
@@ -4354,21 +4413,24 @@ s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer,
        /* Setting this bit tells the ARC that a new command is pending. */
        IXGBE_WRITE_REG(hw, IXGBE_HICR, hicr | IXGBE_HICR_C);
 
-       for (i = 0; i < IXGBE_HI_COMMAND_TIMEOUT; i++) {
+       for (i = 0; i < timeout; i++) {
                hicr = IXGBE_READ_REG(hw, IXGBE_HICR);
                if (!(hicr & IXGBE_HICR_C))
                        break;
                msec_delay(1);
        }
 
-       /* Check command successful completion. */
-       if (i == IXGBE_HI_COMMAND_TIMEOUT ||
-           (!(IXGBE_READ_REG(hw, IXGBE_HICR) & IXGBE_HICR_SV))) {
-               DEBUGOUT("Command has failed with no status valid.\n");
-               ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
-               goto out;
+       /* Check command completion */
+       if ((timeout != 0 && i == timeout) ||
+           !(IXGBE_READ_REG(hw, IXGBE_HICR) & IXGBE_HICR_SV)) {
+               ERROR_REPORT1(IXGBE_ERROR_CAUTION,
+                            "Command has failed with no status valid.\n");
+               return IXGBE_ERR_HOST_INTERFACE_COMMAND;
        }
 
+       if (!return_data)
+               return 0;
+
        /* Calculate length in DWORDs */
        dword_len = hdr_size >> 2;
 
@@ -4381,25 +4443,23 @@ s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer,
        /* If there is any thing in data position pull it in */
        buf_len = ((struct ixgbe_hic_hdr *)buffer)->buf_len;
        if (buf_len == 0)
-               goto out;
+               return 0;
 
-       if (length < (buf_len + hdr_size)) {
+       if (length < buf_len + hdr_size) {
                DEBUGOUT("Buffer not large enough for reply message.\n");
-               ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
-               goto out;
+               return IXGBE_ERR_HOST_INTERFACE_COMMAND;
        }
 
        /* Calculate length in DWORDs, add 3 for odd lengths */
        dword_len = (buf_len + 3) >> 2;
 
-       /* Pull in the rest of the buffer (bi is where we left off)*/
+       /* Pull in the rest of the buffer (bi is where we left off) */
        for (; bi <= dword_len; bi++) {
                buffer[bi] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, bi);
                IXGBE_LE32_TO_CPUS(&buffer[bi]);
        }
 
-out:
-       return ret_val;
+       return 0;
 }
 
 /**
@@ -4446,7 +4506,9 @@ s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min,
 
        for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) {
                ret_val = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd,
-                                                      sizeof(fw_cmd));
+                                                      sizeof(fw_cmd),
+                                                      IXGBE_HI_COMMAND_TIMEOUT,
+                                                      TRUE);
                if (ret_val != IXGBE_SUCCESS)
                        continue;
 
@@ -4533,7 +4595,8 @@ void ixgbe_set_rxpba_generic(struct ixgbe_hw *hw, int num_pb, u32 headroom,
  **/
 void ixgbe_clear_tx_pending(struct ixgbe_hw *hw)
 {
-       u32 gcr_ext, hlreg0;
+       u32 gcr_ext, hlreg0, i, poll;
+       u16 value;
 
        /*
         * If double reset is not requested then all transactions should
@@ -4550,6 +4613,25 @@ void ixgbe_clear_tx_pending(struct ixgbe_hw *hw)
        hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);
        IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0 | IXGBE_HLREG0_LPBK);
 
+       /* Wait for a last completion before clearing buffers */
+       IXGBE_WRITE_FLUSH(hw);
+       msec_delay(3);
+
+       /*
+        * Before proceeding, make sure that the PCIe block does not have
+        * transactions pending.
+        */
+       poll = ixgbe_pcie_timeout_poll(hw);
+       for (i = 0; i < poll; i++) {
+               usec_delay(100);
+               value = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_STATUS);
+               if (IXGBE_REMOVED(hw->hw_addr))
+                       goto out;
+               if (!(value & IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING))
+                       goto out;
+       }
+
+out:
        /* initiate cleaning flow for buffers in the PCIe transaction layer */
        gcr_ext = IXGBE_READ_REG(hw, IXGBE_GCR_EXT);
        IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT,
@@ -4582,3 +4664,316 @@ void ixgbe_dcb_get_rtrup2tc_generic(struct ixgbe_hw *hw, u8 *map)
                        (reg >> (i * IXGBE_RTRUP2TC_UP_SHIFT));
        return;
 }
+
+void ixgbe_disable_rx_generic(struct ixgbe_hw *hw)
+{
+       u32 pfdtxgswc;
+       u32 rxctrl;
+
+       rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
+       if (rxctrl & IXGBE_RXCTRL_RXEN) {
+               if (hw->mac.type != ixgbe_mac_82598EB) {
+                       pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC);
+                       if (pfdtxgswc & IXGBE_PFDTXGSWC_VT_LBEN) {
+                               pfdtxgswc &= ~IXGBE_PFDTXGSWC_VT_LBEN;
+                               IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc);
+                               hw->mac.set_lben = TRUE;
+                       } else {
+                               hw->mac.set_lben = FALSE;
+                       }
+               }
+               rxctrl &= ~IXGBE_RXCTRL_RXEN;
+               IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl);
+       }
+}
+
+void ixgbe_enable_rx_generic(struct ixgbe_hw *hw)
+{
+       u32 pfdtxgswc;
+       u32 rxctrl;
+
+       rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
+       IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, (rxctrl | IXGBE_RXCTRL_RXEN));
+
+       if (hw->mac.type != ixgbe_mac_82598EB) {
+               if (hw->mac.set_lben) {
+                       pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC);
+                       pfdtxgswc |= IXGBE_PFDTXGSWC_VT_LBEN;
+                       IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc);
+                       hw->mac.set_lben = FALSE;
+               }
+       }
+}
+
+/**
+ * ixgbe_mng_present - returns TRUE when management capability is present
+ * @hw: pointer to hardware structure
+ */
+bool ixgbe_mng_present(struct ixgbe_hw *hw)
+{
+       u32 fwsm;
+
+       if (hw->mac.type < ixgbe_mac_82599EB)
+               return FALSE;
+
+       fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM);
+       fwsm &= IXGBE_FWSM_MODE_MASK;
+       return fwsm == IXGBE_FWSM_FW_MODE_PT;
+}
+
+/**
+ * ixgbe_mng_enabled - Is the manageability engine enabled?
+ * @hw: pointer to hardware structure
+ *
+ * Returns TRUE if the manageability engine is enabled.
+ **/
+bool ixgbe_mng_enabled(struct ixgbe_hw *hw)
+{
+       u32 fwsm, manc, factps;
+
+       fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM);
+       if ((fwsm & IXGBE_FWSM_MODE_MASK) != IXGBE_FWSM_FW_MODE_PT)
+               return FALSE;
+
+       manc = IXGBE_READ_REG(hw, IXGBE_MANC);
+       if (!(manc & IXGBE_MANC_RCV_TCO_EN))
+               return FALSE;
+
+       if (hw->mac.type <= ixgbe_mac_X540) {
+               factps = IXGBE_READ_REG(hw, IXGBE_FACTPS);
+               if (factps & IXGBE_FACTPS_MNGCG)
+                       return FALSE;
+       }
+
+       return TRUE;
+}
+
+/**
+ *  ixgbe_setup_mac_link_multispeed_fiber - Set MAC link speed
+ *  @hw: pointer to hardware structure
+ *  @speed: new link speed
+ *  @autoneg_wait_to_complete: TRUE when waiting for completion is needed
+ *
+ *  Set the link speed in the MAC and/or PHY register and restarts link.
+ **/
+s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
+                                         ixgbe_link_speed speed,
+                                         bool autoneg_wait_to_complete)
+{
+       ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN;
+       ixgbe_link_speed highest_link_speed = IXGBE_LINK_SPEED_UNKNOWN;
+       s32 status = IXGBE_SUCCESS;
+       u32 speedcnt = 0;
+       u32 i = 0;
+       bool autoneg, link_up = FALSE;
+
+       DEBUGFUNC("ixgbe_setup_mac_link_multispeed_fiber");
+
+       /* Mask off requested but non-supported speeds */
+       status = ixgbe_get_link_capabilities(hw, &link_speed, &autoneg);
+       if (status != IXGBE_SUCCESS)
+               return status;
+
+       speed &= link_speed;
+
+       /* Try each speed one by one, highest priority first.  We do this in
+        * software because 10Gb fiber doesn't support speed autonegotiation.
+        */
+       if (speed & IXGBE_LINK_SPEED_10GB_FULL) {
+               speedcnt++;
+               highest_link_speed = IXGBE_LINK_SPEED_10GB_FULL;
+
+               /* If we already have link at this speed, just jump out */
+               status = ixgbe_check_link(hw, &link_speed, &link_up, FALSE);
+               if (status != IXGBE_SUCCESS)
+                       return status;
+
+               if ((link_speed == IXGBE_LINK_SPEED_10GB_FULL) && link_up)
+                       goto out;
+
+               /* Set the module link speed */
+               switch (hw->phy.media_type) {
+               case ixgbe_media_type_fiber_fixed:
+               case ixgbe_media_type_fiber:
+                       ixgbe_set_rate_select_speed(hw,
+                                                   IXGBE_LINK_SPEED_10GB_FULL);
+                       break;
+               case ixgbe_media_type_fiber_qsfp:
+                       /* QSFP module automatically detects MAC link speed */
+                       break;
+               default:
+                       DEBUGOUT("Unexpected media type.\n");
+                       break;
+               }
+
+               /* Allow module to change analog characteristics (1G->10G) */
+               msec_delay(40);
+
+               status = ixgbe_setup_mac_link(hw,
+                                             IXGBE_LINK_SPEED_10GB_FULL,
+                                             autoneg_wait_to_complete);
+               if (status != IXGBE_SUCCESS)
+                       return status;
+
+               /* Flap the Tx laser if it has not already been done */
+               ixgbe_flap_tx_laser(hw);
+
+               /* Wait for the controller to acquire link.  Per IEEE 802.3ap,
+                * Section 73.10.2, we may have to wait up to 500ms if KR is
+                * attempted.  82599 uses the same timing for 10g SFI.
+                */
+               for (i = 0; i < 5; i++) {
+                       /* Wait for the link partner to also set speed */
+                       msec_delay(100);
+
+                       /* If we have link, just jump out */
+                       status = ixgbe_check_link(hw, &link_speed,
+                                                 &link_up, FALSE);
+                       if (status != IXGBE_SUCCESS)
+                               return status;
+
+                       if (link_up)
+                               goto out;
+               }
+       }
+
+       if (speed & IXGBE_LINK_SPEED_1GB_FULL) {
+               speedcnt++;
+               if (highest_link_speed == IXGBE_LINK_SPEED_UNKNOWN)
+                       highest_link_speed = IXGBE_LINK_SPEED_1GB_FULL;
+
+               /* If we already have link at this speed, just jump out */
+               status = ixgbe_check_link(hw, &link_speed, &link_up, FALSE);
+               if (status != IXGBE_SUCCESS)
+                       return status;
+
+               if ((link_speed == IXGBE_LINK_SPEED_1GB_FULL) && link_up)
+                       goto out;
+
+               /* Set the module link speed */
+               switch (hw->phy.media_type) {
+               case ixgbe_media_type_fiber_fixed:
+               case ixgbe_media_type_fiber:
+                       ixgbe_set_rate_select_speed(hw,
+                                                   IXGBE_LINK_SPEED_1GB_FULL);
+                       break;
+               case ixgbe_media_type_fiber_qsfp:
+                       /* QSFP module automatically detects link speed */
+                       break;
+               default:
+                       DEBUGOUT("Unexpected media type.\n");
+                       break;
+               }
+
+               /* Allow module to change analog characteristics (10G->1G) */
+               msec_delay(40);
+
+               status = ixgbe_setup_mac_link(hw,
+                                             IXGBE_LINK_SPEED_1GB_FULL,
+                                             autoneg_wait_to_complete);
+               if (status != IXGBE_SUCCESS)
+                       return status;
+
+               /* Flap the Tx laser if it has not already been done */
+               ixgbe_flap_tx_laser(hw);
+
+               /* Wait for the link partner to also set speed */
+               msec_delay(100);
+
+               /* If we have link, just jump out */
+               status = ixgbe_check_link(hw, &link_speed, &link_up, FALSE);
+               if (status != IXGBE_SUCCESS)
+                       return status;
+
+               if (link_up)
+                       goto out;
+       }
+
+       /* We didn't get link.  Configure back to the highest speed we tried,
+        * (if there was more than one).  We call ourselves back with just the
+        * single highest speed that the user requested.
+        */
+       if (speedcnt > 1)
+               status = ixgbe_setup_mac_link_multispeed_fiber(hw,
+                                                     highest_link_speed,
+                                                     autoneg_wait_to_complete);
+
+out:
+       /* Set autoneg_advertised value based on input link speed */
+       hw->phy.autoneg_advertised = 0;
+
+       if (speed & IXGBE_LINK_SPEED_10GB_FULL)
+               hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL;
+
+       if (speed & IXGBE_LINK_SPEED_1GB_FULL)
+               hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL;
+
+       return status;
+}
+
+/**
+ *  ixgbe_set_soft_rate_select_speed - Set module link speed
+ *  @hw: pointer to hardware structure
+ *  @speed: link speed to set
+ *
+ *  Set module link speed via the soft rate select.
+ */
+void ixgbe_set_soft_rate_select_speed(struct ixgbe_hw *hw,
+                                       ixgbe_link_speed speed)
+{
+       s32 status;
+       u8 rs, eeprom_data;
+
+       switch (speed) {
+       case IXGBE_LINK_SPEED_10GB_FULL:
+               /* one bit mask same as setting on */
+               rs = IXGBE_SFF_SOFT_RS_SELECT_10G;
+               break;
+       case IXGBE_LINK_SPEED_1GB_FULL:
+               rs = IXGBE_SFF_SOFT_RS_SELECT_1G;
+               break;
+       default:
+               DEBUGOUT("Invalid fixed module speed\n");
+               return;
+       }
+
+       /* Set RS0 */
+       status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB,
+                                          IXGBE_I2C_EEPROM_DEV_ADDR2,
+                                          &eeprom_data);
+       if (status) {
+               DEBUGOUT("Failed to read Rx Rate Select RS0\n");
+               goto out;
+       }
+
+       eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) | rs;
+
+       status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB,
+                                           IXGBE_I2C_EEPROM_DEV_ADDR2,
+                                           eeprom_data);
+       if (status) {
+               DEBUGOUT("Failed to write Rx Rate Select RS0\n");
+               goto out;
+       }
+
+       /* Set RS1 */
+       status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_ESCB,
+                                          IXGBE_I2C_EEPROM_DEV_ADDR2,
+                                          &eeprom_data);
+       if (status) {
+               DEBUGOUT("Failed to read Rx Rate Select RS1\n");
+               goto out;
+       }
+
+       eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) | rs;
+
+       status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_ESCB,
+                                           IXGBE_I2C_EEPROM_DEV_ADDR2,
+                                           eeprom_data);
+       if (status) {
+               DEBUGOUT("Failed to write Rx Rate Select RS1\n");
+               goto out;
+       }
+out:
+       return;
+}
index 7d1ee82..94c7f97 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2013, Intel Corporation 
+  Copyright (c) 2001-2014, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -41,6 +41,7 @@
                IXGBE_WRITE_REG(hw, reg, (u32) value); \
                IXGBE_WRITE_REG(hw, reg + 4, (u32) (value >> 32)); \
        } while (0)
+#define IXGBE_REMOVED(a) (0)
 #if !defined(NO_READ_PBA_RAW) || !defined(NO_WRITE_PBA_RAW)
 struct ixgbe_pba {
        u16 word[2];
@@ -89,7 +90,7 @@ s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
                                       u16 *data);
 s32 ixgbe_read_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
                                              u16 words, u16 *data);
-u16 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw);
+s32 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw);
 s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw,
                                           u16 *checksum_val);
 s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw);
@@ -113,12 +114,16 @@ s32 ixgbe_enable_sec_rx_path_generic(struct ixgbe_hw *hw);
 s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw);
 bool ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw);
 void ixgbe_fc_autoneg(struct ixgbe_hw *hw);
+s32 ixgbe_setup_fc_generic(struct ixgbe_hw *hw);
 
 s32 ixgbe_validate_mac_addr(u8 *mac_addr);
-s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask);
-void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u16 mask);
+s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u32 mask);
+void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u32 mask);
 s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw);
 
+s32 prot_autoc_read_generic(struct ixgbe_hw *hw, bool *, u32 *reg_val);
+s32 prot_autoc_write_generic(struct ixgbe_hw *hw, u32 reg_val, bool locked);
+
 s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index);
 s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index);
 
@@ -155,10 +160,20 @@ s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min,
                                 u8 build, u8 ver);
 u8 ixgbe_calculate_checksum(u8 *buffer, u32 length);
 s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer,
-                                u32 length);
+                                u32 length, u32 timeout, bool return_data);
+
 void ixgbe_clear_tx_pending(struct ixgbe_hw *hw);
 
 extern s32 ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw);
 extern void ixgbe_stop_mac_link_on_d3_82599(struct ixgbe_hw *hw);
-
+bool ixgbe_mng_present(struct ixgbe_hw *hw);
+bool ixgbe_mng_enabled(struct ixgbe_hw *hw);
+
+void ixgbe_disable_rx_generic(struct ixgbe_hw *hw);
+void ixgbe_enable_rx_generic(struct ixgbe_hw *hw);
+s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
+                                         ixgbe_link_speed speed,
+                                         bool autoneg_wait_to_complete);
+void ixgbe_set_soft_rate_select_speed(struct ixgbe_hw *hw,
+                                     ixgbe_link_speed speed);
 #endif /* IXGBE_COMMON */
index 149aad1..6f848e7 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2013, Intel Corporation 
+  Copyright (c) 2001-2014, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -394,6 +394,9 @@ s32 ixgbe_dcb_get_tc_stats(struct ixgbe_hw *hw, struct ixgbe_hw_stats *stats,
                break;
        case ixgbe_mac_82599EB:
        case ixgbe_mac_X540:
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_x:
+       case ixgbe_mac_X550EM_a:
 #if !defined(NO_82599_SUPPORT) || !defined(NO_X540_SUPPORT)
                ret = ixgbe_dcb_get_tc_stats_82599(hw, stats, tc_count);
                break;
@@ -422,6 +425,9 @@ s32 ixgbe_dcb_get_pfc_stats(struct ixgbe_hw *hw, struct ixgbe_hw_stats *stats,
                break;
        case ixgbe_mac_82599EB:
        case ixgbe_mac_X540:
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_x:
+       case ixgbe_mac_X550EM_a:
 #if !defined(NO_82599_SUPPORT) || !defined(NO_X540_SUPPORT)
                ret = ixgbe_dcb_get_pfc_stats_82599(hw, stats, tc_count);
                break;
@@ -461,6 +467,9 @@ s32 ixgbe_dcb_config_rx_arbiter_cee(struct ixgbe_hw *hw,
                break;
        case ixgbe_mac_82599EB:
        case ixgbe_mac_X540:
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_x:
+       case ixgbe_mac_X550EM_a:
 #if !defined(NO_82599_SUPPORT) || !defined(NO_X540_SUPPORT)
                ret = ixgbe_dcb_config_rx_arbiter_82599(hw, refill, max, bwgid,
                                                        tsa, map);
@@ -500,6 +509,9 @@ s32 ixgbe_dcb_config_tx_desc_arbiter_cee(struct ixgbe_hw *hw,
                break;
        case ixgbe_mac_82599EB:
        case ixgbe_mac_X540:
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_x:
+       case ixgbe_mac_X550EM_a:
 #if !defined(NO_82599_SUPPORT) || !defined(NO_X540_SUPPORT)
                ret = ixgbe_dcb_config_tx_desc_arbiter_82599(hw, refill, max,
                                                             bwgid, tsa);
@@ -541,6 +553,9 @@ s32 ixgbe_dcb_config_tx_data_arbiter_cee(struct ixgbe_hw *hw,
                break;
        case ixgbe_mac_82599EB:
        case ixgbe_mac_X540:
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_x:
+       case ixgbe_mac_X550EM_a:
 #if !defined(NO_82599_SUPPORT) || !defined(NO_X540_SUPPORT)
                ret = ixgbe_dcb_config_tx_data_arbiter_82599(hw, refill, max,
                                                             bwgid, tsa,
@@ -576,6 +591,9 @@ s32 ixgbe_dcb_config_pfc_cee(struct ixgbe_hw *hw,
                break;
        case ixgbe_mac_82599EB:
        case ixgbe_mac_X540:
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_x:
+       case ixgbe_mac_X550EM_a:
 #if !defined(NO_82599_SUPPORT) || !defined(NO_X540_SUPPORT)
                ret = ixgbe_dcb_config_pfc_82599(hw, pfc_en, map);
                break;
@@ -602,6 +620,9 @@ s32 ixgbe_dcb_config_tc_stats(struct ixgbe_hw *hw)
                break;
        case ixgbe_mac_82599EB:
        case ixgbe_mac_X540:
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_x:
+       case ixgbe_mac_X550EM_a:
 #if !defined(NO_82599_SUPPORT) || !defined(NO_X540_SUPPORT)
                ret = ixgbe_dcb_config_tc_stats_82599(hw, NULL);
                break;
@@ -647,6 +668,9 @@ s32 ixgbe_dcb_hw_config_cee(struct ixgbe_hw *hw,
                break;
        case ixgbe_mac_82599EB:
        case ixgbe_mac_X540:
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_x:
+       case ixgbe_mac_X550EM_a:
 #if !defined(NO_82599_SUPPORT) || !defined(NO_X540_SUPPORT)
                ixgbe_dcb_config_82599(hw, dcb_config);
                ret = ixgbe_dcb_hw_config_82599(hw, dcb_config->link_speed,
@@ -679,6 +703,9 @@ s32 ixgbe_dcb_config_pfc(struct ixgbe_hw *hw, u8 pfc_en, u8 *map)
                break;
        case ixgbe_mac_82599EB:
        case ixgbe_mac_X540:
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_x:
+       case ixgbe_mac_X550EM_a:
 #if !defined(NO_82599_SUPPORT) || !defined(NO_X540_SUPPORT)
                ret = ixgbe_dcb_config_pfc_82599(hw, pfc_en, map);
                break;
@@ -702,6 +729,9 @@ s32 ixgbe_dcb_hw_config(struct ixgbe_hw *hw, u16 *refill, u16 *max,
                break;
        case ixgbe_mac_82599EB:
        case ixgbe_mac_X540:
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_x:
+       case ixgbe_mac_X550EM_a:
 #if !defined(NO_82599_SUPPORT) || !defined(NO_X540_SUPPORT)
                ixgbe_dcb_config_rx_arbiter_82599(hw, refill, max, bwg_id,
                                                  tsa, map);
index 05e548e..878bbf8 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2013, Intel Corporation 
+  Copyright (c) 2001-2014, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -35,7 +35,6 @@
 #ifndef _IXGBE_DCB_H_
 #define _IXGBE_DCB_H_
 
-
 #include "ixgbe_type.h"
 
 /* DCB defines */
index aee808f..a5a090d 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2013, Intel Corporation 
+  Copyright (c) 2001-2014, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -347,6 +347,8 @@ s32 ixgbe_dcb_hw_config_82598(struct ixgbe_hw *hw, int link_speed,
                              u16 *refill, u16 *max, u8 *bwg_id,
                              u8 *tsa)
 {
+       UNREFERENCED_1PARAMETER(link_speed);
+
        ixgbe_dcb_config_rx_arbiter_82598(hw, refill, max, tsa);
        ixgbe_dcb_config_tx_desc_arbiter_82598(hw, refill, max, bwg_id,
                                               tsa);
index 9b634a3..47f19f6 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2013, Intel Corporation 
+  Copyright (c) 2001-2014, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
index 085ca0c..0232d3c 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2013, Intel Corporation 
+  Copyright (c) 2001-2014, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -299,7 +299,7 @@ s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw, u8 pfc_en, u8 *map)
         */
        reg &= ~(IXGBE_MFLCN_RPFCE_MASK | IXGBE_MFLCN_RFCE);
 
-       if (hw->mac.type == ixgbe_mac_X540)
+       if (hw->mac.type >= ixgbe_mac_X540)
                reg |= pfc_en << IXGBE_MFLCN_RPFCE_SHIFT;
 
        if (pfc_en)
@@ -329,7 +329,14 @@ s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw, u8 pfc_en, u8 *map)
                        fcrtl = (hw->fc.low_water[i] << 10) | IXGBE_FCRTL_XONE;
                        IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), fcrtl);
                } else {
-                       reg = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)) - 32;
+                       /*
+                        * In order to prevent Tx hangs when the internal Tx
+                        * switch is enabled we must set the high water mark
+                        * to the Rx packet buffer size - 24KB.  This allows
+                        * the Tx switch to function even under heavy Rx
+                        * workloads.
+                        */
+                       reg = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)) - 24576;
                        IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), 0);
                }
 
@@ -573,6 +580,7 @@ s32 ixgbe_dcb_hw_config_82599(struct ixgbe_hw *hw, int link_speed,
                              u16 *refill, u16 *max, u8 *bwg_id, u8 *tsa,
                              u8 *map)
 {
+       UNREFERENCED_1PARAMETER(link_speed);
 
        ixgbe_dcb_config_rx_arbiter_82599(hw, refill, max, bwg_id, tsa,
                                          map);
index 91428c0..7702dc9 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2013, Intel Corporation 
+  Copyright (c) 2001-2014, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
index 33994d4..067bba0 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2013, Intel Corporation 
+  Copyright (c) 2001-2014, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -605,6 +605,9 @@ static s32 ixgbe_check_for_rst_pf(struct ixgbe_hw *hw, u16 vf_number)
        case ixgbe_mac_82599EB:
                vflre = IXGBE_READ_REG(hw, IXGBE_VFLRE(reg_offset));
                break;
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_x:
+       case ixgbe_mac_X550EM_a:
        case ixgbe_mac_X540:
                vflre = IXGBE_READ_REG(hw, IXGBE_VFLREC(reg_offset));
                break;
@@ -740,6 +743,9 @@ void ixgbe_init_mbx_params_pf(struct ixgbe_hw *hw)
        struct ixgbe_mbx_info *mbx = &hw->mbx;
 
        if (hw->mac.type != ixgbe_mac_82599EB &&
+           hw->mac.type != ixgbe_mac_X550 &&
+           hw->mac.type != ixgbe_mac_X550EM_x &&
+           hw->mac.type != ixgbe_mac_X550EM_a &&
            hw->mac.type != ixgbe_mac_X540)
                return;
 
index adcba9e..2cffb8a 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2013, Intel Corporation 
+  Copyright (c) 2001-2014, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
index 763ce02..d7c49e8 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2013, Intel Corporation 
+  Copyright (c) 2001-2014, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -32,6 +32,7 @@
 ******************************************************************************/
 /*$FreeBSD$*/
 
+
 #ifndef _IXGBE_OS_H_
 #define _IXGBE_OS_H_
 
@@ -97,7 +98,7 @@
 #define PCI_COMMAND_REGISTER            PCIR_COMMAND
 
 /* Shared code dropped this define.. */
-#define IXGBE_VENDOR_ID                        0x8086
+#define IXGBE_INTEL_VENDOR_ID          0x8086
 
 /* Bunch of defines for shared code bogosity */
 #define UNREFERENCED_PARAMETER(_p)
 #define UNREFERENCED_3PARAMETER(_p, _q, _r)
 #define UNREFERENCED_4PARAMETER(_p, _q, _r, _s)
 
-
 #define IXGBE_NTOHL(_i)        ntohl(_i)
 #define IXGBE_NTOHS(_i)        ntohs(_i)
 
 /* XXX these need to be revisited */
-#define IXGBE_CPU_TO_LE32 le32toh
-#define IXGBE_LE32_TO_CPUS le32dec
+#define IXGBE_CPU_TO_LE32 htole32
+#define IXGBE_LE32_TO_CPUS(x)
+#define IXGBE_CPU_TO_BE16 htobe16
+#define IXGBE_CPU_TO_BE32 htobe32
 
 typedef uint8_t                u8;
 typedef int8_t         s8;
@@ -121,7 +123,9 @@ typedef int16_t             s16;
 typedef uint32_t       u32;
 typedef int32_t                s32;
 typedef uint64_t       u64;
+#ifndef __bool_true_false_are_defined
 typedef boolean_t      bool;
+#endif
 
 /* shared code requires this */
 #define __le16  u16
@@ -172,10 +176,11 @@ ixgbe_bcopy(void *_src, void *_dst, int l)
        return (0);
 }
 
-struct ixgbe_osdep {
-       bus_space_tag_t         mem_bus_space_tag;
-       bus_space_handle_t      mem_bus_space_handle;
-       device_t                dev;
+struct ixgbe_osdep
+{
+       bus_space_tag_t    mem_bus_space_tag;
+       bus_space_handle_t mem_bus_space_handle;
+       struct device     *dev;
 };
 
 /* These routines are needed by the shared code */
@@ -186,12 +191,27 @@ extern u16 ixgbe_read_pci_cfg(struct ixgbe_hw *, u32);
 extern void ixgbe_write_pci_cfg(struct ixgbe_hw *, u32, u16);
 #define IXGBE_WRITE_PCIE_WORD ixgbe_write_pci_cfg
 
-#define IXGBE_WRITE_FLUSH(a) IXGBE_READ_REG(a, IXGBE_STATUS)
+static __inline uint32_t
+ixgbe_read_reg_osdep(struct ixgbe_osdep *osdep, uint32_t reg)
+{
+       uint32_t value;
+       int count = 0;
 
-#define IXGBE_READ_REG(a, reg) (\
-   bus_space_read_4( ((struct ixgbe_osdep *)(a)->back)->mem_bus_space_tag, \
-                     ((struct ixgbe_osdep *)(a)->back)->mem_bus_space_handle, \
-                     reg))
+       do {
+               value = bus_space_read_4(osdep->mem_bus_space_tag,
+                   osdep->mem_bus_space_handle, reg);
+       } while (value == 0xdeadbeef && ++count < 10);
+
+       if (count > 1)
+               device_printf(osdep->dev, "%d register reads @ 0x%8x\n",
+                   count, reg);
+
+       return value;
+}
+
+#define IXGBE_READ_REG(a, reg) ixgbe_read_reg_osdep((a)->back, reg)
+
+#define IXGBE_WRITE_FLUSH(a) IXGBE_READ_REG(a, IXGBE_STATUS)
 
 #define IXGBE_WRITE_REG(a, reg, value) (\
    bus_space_write_4( ((struct ixgbe_osdep *)(a)->back)->mem_bus_space_tag, \
@@ -209,4 +229,5 @@ extern void ixgbe_write_pci_cfg(struct ixgbe_hw *, u32, u16);
                       ((struct ixgbe_osdep *)(a)->back)->mem_bus_space_handle, \
                       (reg + ((offset) << 2)), value))
 
+
 #endif /* _IXGBE_OS_H_ */
index cb237fd..ef32905 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2013, Intel Corporation 
+  Copyright (c) 2001-2014, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -46,10 +46,267 @@ static s32 ixgbe_clock_out_i2c_bit(struct ixgbe_hw *hw, bool data);
 static void ixgbe_raise_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl);
 static void ixgbe_lower_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl);
 static s32 ixgbe_set_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl, bool data);
-static bool ixgbe_get_i2c_data(u32 *i2cctl);
+static bool ixgbe_get_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl);
 static s32 ixgbe_read_i2c_sff8472_generic(struct ixgbe_hw *hw, u8 byte_offset,
                                          u8 *sff8472_data);
 
+/**
+ * ixgbe_out_i2c_byte_ack - Send I2C byte with ack
+ * @hw: pointer to the hardware structure
+ * @byte: byte to send
+ *
+ * Returns an error code on error.
+ */
+static s32 ixgbe_out_i2c_byte_ack(struct ixgbe_hw *hw, u8 byte)
+{
+       s32 status;
+
+       status = ixgbe_clock_out_i2c_byte(hw, byte);
+       if (status)
+               return status;
+       return ixgbe_get_i2c_ack(hw);
+}
+
+/**
+ * ixgbe_in_i2c_byte_ack - Receive an I2C byte and send ack
+ * @hw: pointer to the hardware structure
+ * @byte: pointer to a u8 to receive the byte
+ *
+ * Returns an error code on error.
+ */
+static s32 ixgbe_in_i2c_byte_ack(struct ixgbe_hw *hw, u8 *byte)
+{
+       s32 status;
+
+       status = ixgbe_clock_in_i2c_byte(hw, byte);
+       if (status)
+               return status;
+       /* ACK */
+       return ixgbe_clock_out_i2c_bit(hw, FALSE);
+}
+
+/**
+ * ixgbe_ones_comp_byte_add - Perform one's complement addition
+ * @add1 - addend 1
+ * @add2 - addend 2
+ *
+ * Returns one's complement 8-bit sum.
+ */
+static u8 ixgbe_ones_comp_byte_add(u8 add1, u8 add2)
+{
+       u16 sum = add1 + add2;
+
+       sum = (sum & 0xFF) + (sum >> 8);
+       return sum & 0xFF;
+}
+
+/**
+ * ixgbe_read_i2c_combined_generic_int - Perform I2C read combined operation
+ * @hw: pointer to the hardware structure
+ * @addr: I2C bus address to read from
+ * @reg: I2C device register to read from
+ * @val: pointer to location to receive read value
+ * @lock: TRUE if to take and release semaphore
+ *
+ * Returns an error code on error.
+ */
+static s32 ixgbe_read_i2c_combined_generic_int(struct ixgbe_hw *hw, u8 addr,
+                                              u16 reg, u16 *val, bool lock)
+{
+       u32 swfw_mask = hw->phy.phy_semaphore_mask;
+       int max_retry = 10;
+       int retry = 0;
+       u8 csum_byte;
+       u8 high_bits;
+       u8 low_bits;
+       u8 reg_high;
+       u8 csum;
+
+       if (hw->mac.type >= ixgbe_mac_X550)
+               max_retry = 3;
+       reg_high = ((reg >> 7) & 0xFE) | 1;     /* Indicate read combined */
+       csum = ixgbe_ones_comp_byte_add(reg_high, reg & 0xFF);
+       csum = ~csum;
+       do {
+               if (lock && hw->mac.ops.acquire_swfw_sync(hw, swfw_mask))
+                       return IXGBE_ERR_SWFW_SYNC;
+               ixgbe_i2c_start(hw);
+               /* Device Address and write indication */
+               if (ixgbe_out_i2c_byte_ack(hw, addr))
+                       goto fail;
+               /* Write bits 14:8 */
+               if (ixgbe_out_i2c_byte_ack(hw, reg_high))
+                       goto fail;
+               /* Write bits 7:0 */
+               if (ixgbe_out_i2c_byte_ack(hw, reg & 0xFF))
+                       goto fail;
+               /* Write csum */
+               if (ixgbe_out_i2c_byte_ack(hw, csum))
+                       goto fail;
+               /* Re-start condition */
+               ixgbe_i2c_start(hw);
+               /* Device Address and read indication */
+               if (ixgbe_out_i2c_byte_ack(hw, addr | 1))
+                       goto fail;
+               /* Get upper bits */
+               if (ixgbe_in_i2c_byte_ack(hw, &high_bits))
+                       goto fail;
+               /* Get low bits */
+               if (ixgbe_in_i2c_byte_ack(hw, &low_bits))
+                       goto fail;
+               /* Get csum */
+               if (ixgbe_clock_in_i2c_byte(hw, &csum_byte))
+                       goto fail;
+               /* NACK */
+               if (ixgbe_clock_out_i2c_bit(hw, FALSE))
+                       goto fail;
+               ixgbe_i2c_stop(hw);
+               if (lock)
+                       hw->mac.ops.release_swfw_sync(hw, swfw_mask);
+               *val = (high_bits << 8) | low_bits;
+               return 0;
+
+fail:
+               ixgbe_i2c_bus_clear(hw);
+               if (lock)
+                       hw->mac.ops.release_swfw_sync(hw, swfw_mask);
+               retry++;
+               if (retry < max_retry)
+                       DEBUGOUT("I2C byte read combined error - Retrying.\n");
+               else
+                       DEBUGOUT("I2C byte read combined error.\n");
+       } while (retry < max_retry);
+
+       return IXGBE_ERR_I2C;
+}
+
+/**
+ * ixgbe_read_i2c_combined_generic - Perform I2C read combined operation
+ * @hw: pointer to the hardware structure
+ * @addr: I2C bus address to read from
+ * @reg: I2C device register to read from
+ * @val: pointer to location to receive read value
+ *
+ * Returns an error code on error.
+ **/
+static s32 ixgbe_read_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr,
+                                          u16 reg, u16 *val)
+{
+       return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, TRUE);
+}
+
+/**
+ * ixgbe_read_i2c_combined_generic_unlocked - Do I2C read combined operation
+ * @hw: pointer to the hardware structure
+ * @addr: I2C bus address to read from
+ * @reg: I2C device register to read from
+ * @val: pointer to location to receive read value
+ *
+ * Returns an error code on error.
+ **/
+static s32
+ixgbe_read_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, u8 addr,
+                                        u16 reg, u16 *val)
+{
+       return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, FALSE);
+}
+
+/**
+ * ixgbe_write_i2c_combined_generic_int - Perform I2C write combined operation
+ * @hw: pointer to the hardware structure
+ * @addr: I2C bus address to write to
+ * @reg: I2C device register to write to
+ * @val: value to write
+ * @lock: TRUE if to take and release semaphore
+ *
+ * Returns an error code on error.
+ */
+static s32 ixgbe_write_i2c_combined_generic_int(struct ixgbe_hw *hw, u8 addr,
+                                               u16 reg, u16 val, bool lock)
+{
+       u32 swfw_mask = hw->phy.phy_semaphore_mask;
+       int max_retry = 1;
+       int retry = 0;
+       u8 reg_high;
+       u8 csum;
+
+       reg_high = (reg >> 7) & 0xFE;   /* Indicate write combined */
+       csum = ixgbe_ones_comp_byte_add(reg_high, reg & 0xFF);
+       csum = ixgbe_ones_comp_byte_add(csum, val >> 8);
+       csum = ixgbe_ones_comp_byte_add(csum, val & 0xFF);
+       csum = ~csum;
+       do {
+               if (lock && hw->mac.ops.acquire_swfw_sync(hw, swfw_mask))
+                       return IXGBE_ERR_SWFW_SYNC;
+               ixgbe_i2c_start(hw);
+               /* Device Address and write indication */
+               if (ixgbe_out_i2c_byte_ack(hw, addr))
+                       goto fail;
+               /* Write bits 14:8 */
+               if (ixgbe_out_i2c_byte_ack(hw, reg_high))
+                       goto fail;
+               /* Write bits 7:0 */
+               if (ixgbe_out_i2c_byte_ack(hw, reg & 0xFF))
+                       goto fail;
+               /* Write data 15:8 */
+               if (ixgbe_out_i2c_byte_ack(hw, val >> 8))
+                       goto fail;
+               /* Write data 7:0 */
+               if (ixgbe_out_i2c_byte_ack(hw, val & 0xFF))
+                       goto fail;
+               /* Write csum */
+               if (ixgbe_out_i2c_byte_ack(hw, csum))
+                       goto fail;
+               ixgbe_i2c_stop(hw);
+               if (lock)
+                       hw->mac.ops.release_swfw_sync(hw, swfw_mask);
+               return 0;
+
+fail:
+               ixgbe_i2c_bus_clear(hw);
+               if (lock)
+                       hw->mac.ops.release_swfw_sync(hw, swfw_mask);
+               retry++;
+               if (retry < max_retry)
+                       DEBUGOUT("I2C byte write combined error - Retrying.\n");
+               else
+                       DEBUGOUT("I2C byte write combined error.\n");
+       } while (retry < max_retry);
+
+       return IXGBE_ERR_I2C;
+}
+
+/**
+ * ixgbe_write_i2c_combined_generic - Perform I2C write combined operation
+ * @hw: pointer to the hardware structure
+ * @addr: I2C bus address to write to
+ * @reg: I2C device register to write to
+ * @val: value to write
+ *
+ * Returns an error code on error.
+ **/
+static s32 ixgbe_write_i2c_combined_generic(struct ixgbe_hw *hw,
+                                           u8 addr, u16 reg, u16 val)
+{
+       return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, TRUE);
+}
+
+/**
+ * ixgbe_write_i2c_combined_generic_unlocked - Do I2C write combined operation
+ * @hw: pointer to the hardware structure
+ * @addr: I2C bus address to write to
+ * @reg: I2C device register to write to
+ * @val: value to write
+ *
+ * Returns an error code on error.
+ **/
+static s32
+ixgbe_write_i2c_combined_generic_unlocked(struct ixgbe_hw *hw,
+                                         u8 addr, u16 reg, u16 val)
+{
+       return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, FALSE);
+}
+
 /**
  *  ixgbe_init_phy_ops_generic - Inits PHY function ptrs
  *  @hw: pointer to the hardware structure
@@ -63,25 +320,34 @@ s32 ixgbe_init_phy_ops_generic(struct ixgbe_hw *hw)
        DEBUGFUNC("ixgbe_init_phy_ops_generic");
 
        /* PHY */
-       phy->ops.identify = &ixgbe_identify_phy_generic;
-       phy->ops.reset = &ixgbe_reset_phy_generic;
-       phy->ops.read_reg = &ixgbe_read_phy_reg_generic;
-       phy->ops.write_reg = &ixgbe_write_phy_reg_generic;
-       phy->ops.read_reg_mdi = &ixgbe_read_phy_reg_mdi;
-       phy->ops.write_reg_mdi = &ixgbe_write_phy_reg_mdi;
-       phy->ops.setup_link = &ixgbe_setup_phy_link_generic;
-       phy->ops.setup_link_speed = &ixgbe_setup_phy_link_speed_generic;
+       phy->ops.identify = ixgbe_identify_phy_generic;
+       phy->ops.reset = ixgbe_reset_phy_generic;
+       phy->ops.read_reg = ixgbe_read_phy_reg_generic;
+       phy->ops.write_reg = ixgbe_write_phy_reg_generic;
+       phy->ops.read_reg_mdi = ixgbe_read_phy_reg_mdi;
+       phy->ops.write_reg_mdi = ixgbe_write_phy_reg_mdi;
+       phy->ops.setup_link = ixgbe_setup_phy_link_generic;
+       phy->ops.setup_link_speed = ixgbe_setup_phy_link_speed_generic;
        phy->ops.check_link = NULL;
        phy->ops.get_firmware_version = ixgbe_get_phy_firmware_version_generic;
-       phy->ops.read_i2c_byte = &ixgbe_read_i2c_byte_generic;
-       phy->ops.write_i2c_byte = &ixgbe_write_i2c_byte_generic;
-       phy->ops.read_i2c_sff8472 = &ixgbe_read_i2c_sff8472_generic;
-       phy->ops.read_i2c_eeprom = &ixgbe_read_i2c_eeprom_generic;
-       phy->ops.write_i2c_eeprom = &ixgbe_write_i2c_eeprom_generic;
-       phy->ops.i2c_bus_clear = &ixgbe_i2c_bus_clear;
-       phy->ops.identify_sfp = &ixgbe_identify_module_generic;
+       phy->ops.read_i2c_byte = ixgbe_read_i2c_byte_generic;
+       phy->ops.write_i2c_byte = ixgbe_write_i2c_byte_generic;
+       phy->ops.read_i2c_sff8472 = ixgbe_read_i2c_sff8472_generic;
+       phy->ops.read_i2c_eeprom = ixgbe_read_i2c_eeprom_generic;
+       phy->ops.write_i2c_eeprom = ixgbe_write_i2c_eeprom_generic;
+       phy->ops.i2c_bus_clear = ixgbe_i2c_bus_clear;
+       phy->ops.identify_sfp = ixgbe_identify_module_generic;
        phy->sfp_type = ixgbe_sfp_type_unknown;
-       phy->ops.check_overtemp = &ixgbe_tn_check_overtemp;
+       phy->ops.read_i2c_combined = ixgbe_read_i2c_combined_generic;
+       phy->ops.write_i2c_combined = ixgbe_write_i2c_combined_generic;
+       phy->ops.read_i2c_combined_unlocked =
+                               ixgbe_read_i2c_combined_generic_unlocked;
+       phy->ops.write_i2c_combined_unlocked =
+                               ixgbe_write_i2c_combined_generic_unlocked;
+       phy->ops.read_i2c_byte_unlocked = ixgbe_read_i2c_byte_generic_unlocked;
+       phy->ops.write_i2c_byte_unlocked =
+                               ixgbe_write_i2c_byte_generic_unlocked;
+       phy->ops.check_overtemp = ixgbe_tn_check_overtemp;
        return IXGBE_SUCCESS;
 }
 
@@ -99,6 +365,13 @@ s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw)
 
        DEBUGFUNC("ixgbe_identify_phy_generic");
 
+       if (!hw->phy.phy_semaphore_mask) {
+               if (hw->bus.lan_id)
+                       hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY1_SM;
+               else
+                       hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM;
+       }
+
        if (hw->phy.type == ixgbe_phy_unknown) {
                for (phy_addr = 0; phy_addr < IXGBE_MAX_PHY_ADDR; phy_addr++) {
                        if (ixgbe_validate_phy_addr(hw, phy_addr)) {
@@ -126,11 +399,13 @@ s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw)
                                break;
                        }
                }
-               /* clear value if nothing found */
+
+               /* Certain media types do not have a phy so an address will not
+                * be found and the code will take this path.  Caller has to
+                * decide if it is an error or not.
+                */
                if (status != IXGBE_SUCCESS) {
                        hw->phy.addr = 0;
-                       ERROR_REPORT1(IXGBE_ERROR_SOFTWARE,
-                                    "Could not identify valid PHY address");
                }
        } else {
                status = IXGBE_SUCCESS;
@@ -139,6 +414,35 @@ s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw)
        return status;
 }
 
+/**
+ * ixgbe_check_reset_blocked - check status of MNG FW veto bit
+ * @hw: pointer to the hardware structure
+ *
+ * This function checks the MMNGC.MNG_VETO bit to see if there are
+ * any constraints on link from manageability.  For MAC's that don't
+ * have this bit just return faluse since the link can not be blocked
+ * via this method.
+ **/
+s32 ixgbe_check_reset_blocked(struct ixgbe_hw *hw)
+{
+       u32 mmngc;
+
+       DEBUGFUNC("ixgbe_check_reset_blocked");
+
+       /* If we don't have this bit, it can't be blocking */
+       if (hw->mac.type == ixgbe_mac_82598EB)
+               return FALSE;
+
+       mmngc = IXGBE_READ_REG(hw, IXGBE_MMNGC);
+       if (mmngc & IXGBE_MMNGC_MNG_VETO) {
+               ERROR_REPORT1(IXGBE_ERROR_SOFTWARE,
+                             "MNG_VETO bit detected.\n");
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
 /**
  *  ixgbe_validate_phy_addr - Determines phy address is valid
  *  @hw: pointer to hardware structure
@@ -204,6 +508,7 @@ enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id)
        case TN1010_PHY_ID:
                phy_type = ixgbe_phy_tn;
                break;
+       case X550_PHY_ID:
        case X540_PHY_ID:
                phy_type = ixgbe_phy_aq;
                break;
@@ -213,6 +518,9 @@ enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id)
        case ATH_PHY_ID:
                phy_type = ixgbe_phy_nl;
                break;
+       case X557_PHY_ID:
+               phy_type = ixgbe_phy_x550em_ext_t;
+               break;
        default:
                phy_type = ixgbe_phy_unknown;
                break;
@@ -245,6 +553,10 @@ s32 ixgbe_reset_phy_generic(struct ixgbe_hw *hw)
            (IXGBE_ERR_OVERTEMP == hw->phy.ops.check_overtemp(hw)))
                goto out;
 
+       /* Blocked by MNG FW so bail */
+       if (ixgbe_check_reset_blocked(hw))
+               goto out;
+
        /*
         * Perform soft PHY reset to the PHY_XS.
         * This will cause a soft reset to the PHY
@@ -368,15 +680,10 @@ s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
                               u32 device_type, u16 *phy_data)
 {
        s32 status;
-       u16 gssr;
+       u32 gssr = hw->phy.phy_semaphore_mask;
 
        DEBUGFUNC("ixgbe_read_phy_reg_generic");
 
-       if (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)
-               gssr = IXGBE_GSSR_PHY1_SM;
-       else
-               gssr = IXGBE_GSSR_PHY0_SM;
-
        if (hw->mac.ops.acquire_swfw_sync(hw, gssr) == IXGBE_SUCCESS) {
                status = ixgbe_read_phy_reg_mdi(hw, reg_addr, device_type,
                                                phy_data);
@@ -474,15 +781,10 @@ s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
                                u32 device_type, u16 phy_data)
 {
        s32 status;
-       u16 gssr;
+       u32 gssr = hw->phy.phy_semaphore_mask;
 
        DEBUGFUNC("ixgbe_write_phy_reg_generic");
 
-       if (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)
-               gssr = IXGBE_GSSR_PHY1_SM;
-       else
-               gssr = IXGBE_GSSR_PHY0_SM;
-
        if (hw->mac.ops.acquire_swfw_sync(hw, gssr) == IXGBE_SUCCESS) {
                status = ixgbe_write_phy_reg_mdi(hw, reg_addr, device_type,
                                                 phy_data);
@@ -495,16 +797,14 @@ s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
 }
 
 /**
- *  ixgbe_setup_phy_link_generic - Set and restart autoneg
+ *  ixgbe_setup_phy_link_generic - Set and restart auto-neg
  *  @hw: pointer to hardware structure
  *
- *  Restart autonegotiation and PHY and waits for completion.
+ *  Restart auto-negotiation and PHY and waits for completion.
  **/
 s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw)
 {
        s32 status = IXGBE_SUCCESS;
-       u32 time_out;
-       u32 max_time_out = 10;
        u16 autoneg_reg = IXGBE_MII_AUTONEG_REG;
        bool autoneg = FALSE;
        ixgbe_link_speed speed;
@@ -528,6 +828,44 @@ s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw)
                                      autoneg_reg);
        }
 
+       if (hw->mac.type == ixgbe_mac_X550) {
+               if (speed & IXGBE_LINK_SPEED_5GB_FULL) {
+                       /* Set or unset auto-negotiation 1G advertisement */
+                       hw->phy.ops.read_reg(hw,
+                               IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
+                               IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+                               &autoneg_reg);
+
+                       autoneg_reg &= ~IXGBE_MII_5GBASE_T_ADVERTISE;
+                       if (hw->phy.autoneg_advertised &
+                            IXGBE_LINK_SPEED_5GB_FULL)
+                               autoneg_reg |= IXGBE_MII_5GBASE_T_ADVERTISE;
+
+                       hw->phy.ops.write_reg(hw,
+                               IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
+                               IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+                               autoneg_reg);
+               }
+
+               if (speed & IXGBE_LINK_SPEED_2_5GB_FULL) {
+                       /* Set or unset auto-negotiation 1G advertisement */
+                       hw->phy.ops.read_reg(hw,
+                               IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
+                               IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+                               &autoneg_reg);
+
+                       autoneg_reg &= ~IXGBE_MII_2_5GBASE_T_ADVERTISE;
+                       if (hw->phy.autoneg_advertised &
+                           IXGBE_LINK_SPEED_2_5GB_FULL)
+                               autoneg_reg |= IXGBE_MII_2_5GBASE_T_ADVERTISE;
+
+                       hw->phy.ops.write_reg(hw,
+                               IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
+                               IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+                               autoneg_reg);
+               }
+       }
+
        if (speed & IXGBE_LINK_SPEED_1GB_FULL) {
                /* Set or unset auto-negotiation 1G advertisement */
                hw->phy.ops.read_reg(hw,
@@ -561,7 +899,11 @@ s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw)
                                      autoneg_reg);
        }
 
-       /* Restart PHY autonegotiation and wait for completion */
+       /* Blocked by MNG FW so don't reset PHY */
+       if (ixgbe_check_reset_blocked(hw))
+               return status;
+
+       /* Restart PHY auto-negotiation. */
        hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_CONTROL,
                             IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg);
 
@@ -570,25 +912,6 @@ s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw)
        hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_CONTROL,
                              IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_reg);
 
-       /* Wait for autonegotiation to finish */
-       for (time_out = 0; time_out < max_time_out; time_out++) {
-               usec_delay(10);
-               /* Restart PHY autonegotiation and wait for completion */
-               status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
-                                             IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
-                                             &autoneg_reg);
-
-               autoneg_reg &= IXGBE_MII_AUTONEG_COMPLETE;
-               if (autoneg_reg == IXGBE_MII_AUTONEG_COMPLETE)
-                       break;
-       }
-
-       if (time_out == max_time_out) {
-               status = IXGBE_ERR_LINK_SETUP;
-               ERROR_REPORT1(IXGBE_ERROR_POLLING,
-                            "PHY autonegotiation time out");
-       }
-
        return status;
 }
 
@@ -614,6 +937,12 @@ s32 ixgbe_setup_phy_link_speed_generic(struct ixgbe_hw *hw,
        if (speed & IXGBE_LINK_SPEED_10GB_FULL)
                hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL;
 
+       if (speed & IXGBE_LINK_SPEED_5GB_FULL)
+               hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_5GB_FULL;
+
+       if (speed & IXGBE_LINK_SPEED_2_5GB_FULL)
+               hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_2_5GB_FULL;
+
        if (speed & IXGBE_LINK_SPEED_1GB_FULL)
                hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL;
 
@@ -632,13 +961,14 @@ s32 ixgbe_setup_phy_link_speed_generic(struct ixgbe_hw *hw,
  *  @speed: pointer to link speed
  *  @autoneg: boolean auto-negotiation value
  *
- *  Determines the link capabilities by reading the AUTOC register.
+ *  Determines the supported link capabilities by reading the PHY auto
+ *  negotiation register.
  **/
 s32 ixgbe_get_copper_link_capabilities_generic(struct ixgbe_hw *hw,
                                               ixgbe_link_speed *speed,
                                               bool *autoneg)
 {
-       s32 status = IXGBE_ERR_LINK_SETUP;
+       s32 status;
        u16 speed_ability;
 
        DEBUGFUNC("ixgbe_get_copper_link_capabilities_generic");
@@ -659,6 +989,15 @@ s32 ixgbe_get_copper_link_capabilities_generic(struct ixgbe_hw *hw,
                        *speed |= IXGBE_LINK_SPEED_100_FULL;
        }
 
+       /* Internal PHY does not support 100 Mbps */
+       if (hw->mac.type == ixgbe_mac_X550EM_x)
+               *speed &= ~IXGBE_LINK_SPEED_100_FULL;
+
+       if (hw->mac.type == ixgbe_mac_X550) {
+               *speed |= IXGBE_LINK_SPEED_2_5GB_FULL;
+               *speed |= IXGBE_LINK_SPEED_5GB_FULL;
+       }
+
        return status;
 }
 
@@ -712,16 +1051,14 @@ s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
 }
 
 /**
- *     ixgbe_setup_phy_link_tnx - Set and restart autoneg
+ *     ixgbe_setup_phy_link_tnx - Set and restart auto-neg
  *     @hw: pointer to hardware structure
  *
- *     Restart autonegotiation and PHY and waits for completion.
+ *     Restart auto-negotiation and PHY and waits for completion.
  **/
 s32 ixgbe_setup_phy_link_tnx(struct ixgbe_hw *hw)
 {
        s32 status = IXGBE_SUCCESS;
-       u32 time_out;
-       u32 max_time_out = 10;
        u16 autoneg_reg = IXGBE_MII_AUTONEG_REG;
        bool autoneg = FALSE;
        ixgbe_link_speed speed;
@@ -775,7 +1112,11 @@ s32 ixgbe_setup_phy_link_tnx(struct ixgbe_hw *hw)
                                      autoneg_reg);
        }
 
-       /* Restart PHY autonegotiation and wait for completion */
+       /* Blocked by MNG FW so don't reset PHY */
+       if (ixgbe_check_reset_blocked(hw))
+               return status;
+
+       /* Restart PHY auto-negotiation. */
        hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_CONTROL,
                             IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg);
 
@@ -784,24 +1125,6 @@ s32 ixgbe_setup_phy_link_tnx(struct ixgbe_hw *hw)
        hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_CONTROL,
                              IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_reg);
 
-       /* Wait for autonegotiation to finish */
-       for (time_out = 0; time_out < max_time_out; time_out++) {
-               usec_delay(10);
-               /* Restart PHY autonegotiation and wait for completion */
-               status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
-                                             IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
-                                             &autoneg_reg);
-
-               autoneg_reg &= IXGBE_MII_AUTONEG_COMPLETE;
-               if (autoneg_reg == IXGBE_MII_AUTONEG_COMPLETE)
-                       break;
-       }
-
-       if (time_out == max_time_out) {
-               status = IXGBE_ERR_LINK_SETUP;
-               DEBUGOUT("ixgbe_setup_phy_link_tnx: time out");
-       }
-
        return status;
 }
 
@@ -813,7 +1136,7 @@ s32 ixgbe_setup_phy_link_tnx(struct ixgbe_hw *hw)
 s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw,
                                       u16 *firmware_version)
 {
-       s32 status = IXGBE_SUCCESS;
+       s32 status;
 
        DEBUGFUNC("ixgbe_get_phy_firmware_version_tnx");
 
@@ -832,7 +1155,7 @@ s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw,
 s32 ixgbe_get_phy_firmware_version_generic(struct ixgbe_hw *hw,
                                           u16 *firmware_version)
 {
-       s32 status = IXGBE_SUCCESS;
+       s32 status;
 
        DEBUGFUNC("ixgbe_get_phy_firmware_version_generic");
 
@@ -858,6 +1181,10 @@ s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw)
 
        DEBUGFUNC("ixgbe_reset_phy_nl");
 
+       /* Blocked by MNG FW so bail */
+       if (ixgbe_check_reset_blocked(hw))
+               goto out;
+
        hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL,
                             IXGBE_MDIO_PHY_XS_DEV_TYPE, &phy_data);
 
@@ -972,6 +1299,9 @@ s32 ixgbe_identify_module_generic(struct ixgbe_hw *hw)
                status = ixgbe_identify_sfp_module_generic(hw);
                break;
 
+       case ixgbe_media_type_fiber_qsfp:
+               status = ixgbe_identify_qsfp_module_generic(hw);
+               break;
 
        default:
                hw->phy.sfp_type = ixgbe_sfp_type_not_present;
@@ -1009,6 +1339,9 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
                goto out;
        }
 
+       /* LAN ID is needed for I2C access */
+       hw->mac.ops.set_lan_id(hw);
+
        status = hw->phy.ops.read_i2c_eeprom(hw,
                                             IXGBE_SFF_IDENTIFIER,
                                             &identifier);
@@ -1016,9 +1349,6 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
        if (status != IXGBE_SUCCESS)
                goto err_read_i2c_eeprom;
 
-       /* LAN ID is needed for sfp_type determination */
-       hw->mac.ops.set_lan_id(hw);
-
        if (identifier != IXGBE_SFF_IDENTIFIER_SFP) {
                hw->phy.type = ixgbe_phy_sfp_unsupported;
                status = IXGBE_ERR_SFP_NOT_SUPPORTED;
@@ -1068,7 +1398,7 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
                                hw->phy.sfp_type = ixgbe_sfp_type_lr;
                        else
                                hw->phy.sfp_type = ixgbe_sfp_type_unknown;
-               } else if (hw->mac.type == ixgbe_mac_82599EB) {
+               } else {
                        if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE) {
                                if (hw->bus.lan_id == 0)
                                        hw->phy.sfp_type =
@@ -1115,6 +1445,13 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
                                else
                                        hw->phy.sfp_type =
                                                ixgbe_sfp_type_1g_sx_core1;
+                       } else if (comp_codes_1g & IXGBE_SFF_1GBASELX_CAPABLE) {
+                               if (hw->bus.lan_id == 0)
+                                       hw->phy.sfp_type =
+                                               ixgbe_sfp_type_1g_lx_core0;
+                               else
+                                       hw->phy.sfp_type =
+                                               ixgbe_sfp_type_1g_lx_core1;
                        } else {
                                hw->phy.sfp_type = ixgbe_sfp_type_unknown;
                        }
@@ -1202,6 +1539,8 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
                if (comp_codes_10g == 0 &&
                    !(hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core1 ||
                      hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core0 ||
+                     hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 ||
+                     hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1 ||
                      hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 ||
                      hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1)) {
                        hw->phy.type = ixgbe_phy_sfp_unsupported;
@@ -1219,6 +1558,8 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
                if (!(enforce_sfp & IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP) &&
                    !(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_lx_core0 ||
+                     hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1 ||
                      hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 ||
                      hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1)) {
                        /* Make sure we're a supported PHY type */
@@ -1261,6 +1602,266 @@ err_read_i2c_eeprom:
        return IXGBE_ERR_SFP_NOT_PRESENT;
 }
 
+/**
+ *  ixgbe_get_supported_phy_sfp_layer_generic - Returns physical layer type
+ *  @hw: pointer to hardware structure
+ *
+ *  Determines physical layer capabilities of the current SFP.
+ */
+s32 ixgbe_get_supported_phy_sfp_layer_generic(struct ixgbe_hw *hw)
+{
+       u32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
+       u8 comp_codes_10g = 0;
+       u8 comp_codes_1g = 0;
+
+       DEBUGFUNC("ixgbe_get_supported_phy_sfp_layer_generic");
+
+       hw->phy.ops.identify_sfp(hw);
+       if (hw->phy.sfp_type == ixgbe_sfp_type_not_present)
+               return physical_layer;
+
+       switch (hw->phy.type) {
+       case ixgbe_phy_sfp_passive_tyco:
+       case ixgbe_phy_sfp_passive_unknown:
+       case ixgbe_phy_qsfp_passive_unknown:
+               physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU;
+               break;
+       case ixgbe_phy_sfp_ftl_active:
+       case ixgbe_phy_sfp_active_unknown:
+       case ixgbe_phy_qsfp_active_unknown:
+               physical_layer = IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA;
+               break;
+       case ixgbe_phy_sfp_avago:
+       case ixgbe_phy_sfp_ftl:
+       case ixgbe_phy_sfp_intel:
+       case ixgbe_phy_sfp_unknown:
+               hw->phy.ops.read_i2c_eeprom(hw,
+                     IXGBE_SFF_1GBE_COMP_CODES, &comp_codes_1g);
+               hw->phy.ops.read_i2c_eeprom(hw,
+                     IXGBE_SFF_10GBE_COMP_CODES, &comp_codes_10g);
+               if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)
+                       physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR;
+               else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)
+                       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;
+       case ixgbe_phy_qsfp_intel:
+       case ixgbe_phy_qsfp_unknown:
+               hw->phy.ops.read_i2c_eeprom(hw,
+                     IXGBE_SFF_QSFP_10GBE_COMP, &comp_codes_10g);
+               if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)
+                       physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR;
+               else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)
+                       physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR;
+               break;
+       default:
+               break;
+       }
+
+       return physical_layer;
+}
+
+/**
+ *  ixgbe_identify_qsfp_module_generic - Identifies QSFP modules
+ *  @hw: pointer to hardware structure
+ *
+ *  Searches for and identifies the QSFP module and assigns appropriate PHY type
+ **/
+s32 ixgbe_identify_qsfp_module_generic(struct ixgbe_hw *hw)
+{
+       s32 status = IXGBE_ERR_PHY_ADDR_INVALID;
+       u32 vendor_oui = 0;
+       enum ixgbe_sfp_type stored_sfp_type = hw->phy.sfp_type;
+       u8 identifier = 0;
+       u8 comp_codes_1g = 0;
+       u8 comp_codes_10g = 0;
+       u8 oui_bytes[3] = {0, 0, 0};
+       u16 enforce_sfp = 0;
+       u8 connector = 0;
+       u8 cable_length = 0;
+       u8 device_tech = 0;
+       bool active_cable = FALSE;
+
+       DEBUGFUNC("ixgbe_identify_qsfp_module_generic");
+
+       if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_fiber_qsfp) {
+               hw->phy.sfp_type = ixgbe_sfp_type_not_present;
+               status = IXGBE_ERR_SFP_NOT_PRESENT;
+               goto out;
+       }
+
+       /* LAN ID is needed for I2C access */
+       hw->mac.ops.set_lan_id(hw);
+
+       status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_IDENTIFIER,
+                                            &identifier);
+
+       if (status != IXGBE_SUCCESS)
+               goto err_read_i2c_eeprom;
+
+       if (identifier != IXGBE_SFF_IDENTIFIER_QSFP_PLUS) {
+               hw->phy.type = ixgbe_phy_sfp_unsupported;
+               status = IXGBE_ERR_SFP_NOT_SUPPORTED;
+               goto out;
+       }
+
+       hw->phy.id = identifier;
+
+       status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_QSFP_10GBE_COMP,
+                                            &comp_codes_10g);
+
+       if (status != IXGBE_SUCCESS)
+               goto err_read_i2c_eeprom;
+
+       status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_QSFP_1GBE_COMP,
+                                            &comp_codes_1g);
+
+       if (status != IXGBE_SUCCESS)
+               goto err_read_i2c_eeprom;
+
+       if (comp_codes_10g & IXGBE_SFF_QSFP_DA_PASSIVE_CABLE) {
+               hw->phy.type = ixgbe_phy_qsfp_passive_unknown;
+               if (hw->bus.lan_id == 0)
+                       hw->phy.sfp_type = ixgbe_sfp_type_da_cu_core0;
+               else
+                       hw->phy.sfp_type = ixgbe_sfp_type_da_cu_core1;
+       } else if (comp_codes_10g & (IXGBE_SFF_10GBASESR_CAPABLE |
+                                    IXGBE_SFF_10GBASELR_CAPABLE)) {
+               if (hw->bus.lan_id == 0)
+                       hw->phy.sfp_type = ixgbe_sfp_type_srlr_core0;
+               else
+                       hw->phy.sfp_type = ixgbe_sfp_type_srlr_core1;
+       } else {
+               if (comp_codes_10g & IXGBE_SFF_QSFP_DA_ACTIVE_CABLE)
+                       active_cable = TRUE;
+
+               if (!active_cable) {
+                       /* check for active DA cables that pre-date
+                        * SFF-8436 v3.6 */
+                       hw->phy.ops.read_i2c_eeprom(hw,
+                                       IXGBE_SFF_QSFP_CONNECTOR,
+                                       &connector);
+
+                       hw->phy.ops.read_i2c_eeprom(hw,
+                                       IXGBE_SFF_QSFP_CABLE_LENGTH,
+                                       &cable_length);
+
+                       hw->phy.ops.read_i2c_eeprom(hw,
+                                       IXGBE_SFF_QSFP_DEVICE_TECH,
+                                       &device_tech);
+
+                       if ((connector ==
+                                    IXGBE_SFF_QSFP_CONNECTOR_NOT_SEPARABLE) &&
+                           (cable_length > 0) &&
+                           ((device_tech >> 4) ==
+                                    IXGBE_SFF_QSFP_TRANSMITER_850NM_VCSEL))
+                               active_cable = TRUE;
+               }
+
+               if (active_cable) {
+                       hw->phy.type = ixgbe_phy_qsfp_active_unknown;
+                       if (hw->bus.lan_id == 0)
+                               hw->phy.sfp_type =
+                                               ixgbe_sfp_type_da_act_lmt_core0;
+                       else
+                               hw->phy.sfp_type =
+                                               ixgbe_sfp_type_da_act_lmt_core1;
+               } else {
+                       /* unsupported module type */
+                       hw->phy.type = ixgbe_phy_sfp_unsupported;
+                       status = IXGBE_ERR_SFP_NOT_SUPPORTED;
+                       goto out;
+               }
+       }
+
+       if (hw->phy.sfp_type != stored_sfp_type)
+               hw->phy.sfp_setup_needed = TRUE;
+
+       /* Determine if the QSFP+ PHY is dual speed or not. */
+       hw->phy.multispeed_fiber = FALSE;
+       if (((comp_codes_1g & IXGBE_SFF_1GBASESX_CAPABLE) &&
+          (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)) ||
+          ((comp_codes_1g & IXGBE_SFF_1GBASELX_CAPABLE) &&
+          (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)))
+               hw->phy.multispeed_fiber = TRUE;
+
+       /* Determine PHY vendor for optical modules */
+       if (comp_codes_10g & (IXGBE_SFF_10GBASESR_CAPABLE |
+                             IXGBE_SFF_10GBASELR_CAPABLE))  {
+               status = hw->phy.ops.read_i2c_eeprom(hw,
+                                           IXGBE_SFF_QSFP_VENDOR_OUI_BYTE0,
+                                           &oui_bytes[0]);
+
+               if (status != IXGBE_SUCCESS)
+                       goto err_read_i2c_eeprom;
+
+               status = hw->phy.ops.read_i2c_eeprom(hw,
+                                           IXGBE_SFF_QSFP_VENDOR_OUI_BYTE1,
+                                           &oui_bytes[1]);
+
+               if (status != IXGBE_SUCCESS)
+                       goto err_read_i2c_eeprom;
+
+               status = hw->phy.ops.read_i2c_eeprom(hw,
+                                           IXGBE_SFF_QSFP_VENDOR_OUI_BYTE2,
+                                           &oui_bytes[2]);
+
+               if (status != IXGBE_SUCCESS)
+                       goto err_read_i2c_eeprom;
+
+               vendor_oui =
+                 ((oui_bytes[0] << IXGBE_SFF_VENDOR_OUI_BYTE0_SHIFT) |
+                  (oui_bytes[1] << IXGBE_SFF_VENDOR_OUI_BYTE1_SHIFT) |
+                  (oui_bytes[2] << IXGBE_SFF_VENDOR_OUI_BYTE2_SHIFT));
+
+               if (vendor_oui == IXGBE_SFF_VENDOR_OUI_INTEL)
+                       hw->phy.type = ixgbe_phy_qsfp_intel;
+               else
+                       hw->phy.type = ixgbe_phy_qsfp_unknown;
+
+               ixgbe_get_device_caps(hw, &enforce_sfp);
+               if (!(enforce_sfp & IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP)) {
+                       /* Make sure we're a supported PHY type */
+                       if (hw->phy.type == ixgbe_phy_qsfp_intel) {
+                               status = IXGBE_SUCCESS;
+                       } else {
+                               if (hw->allow_unsupported_sfp == TRUE) {
+                                       EWARN(hw, "WARNING: Intel (R) Network "
+                                             "Connections are quality tested "
+                                             "using Intel (R) Ethernet Optics."
+                                             " Using untested modules is not "
+                                             "supported and may cause unstable"
+                                             " operation or damage to the "
+                                             "module or the adapter. Intel "
+                                             "Corporation is not responsible "
+                                             "for any harm caused by using "
+                                             "untested modules.\n", status);
+                                       status = IXGBE_SUCCESS;
+                               } else {
+                                       DEBUGOUT("QSFP module not supported\n");
+                                       hw->phy.type =
+                                               ixgbe_phy_sfp_unsupported;
+                                       status = IXGBE_ERR_SFP_NOT_SUPPORTED;
+                               }
+                       }
+               } else {
+                       status = IXGBE_SUCCESS;
+               }
+       }
+
+out:
+       return status;
+
+err_read_i2c_eeprom:
+       hw->phy.sfp_type = ixgbe_sfp_type_not_present;
+       hw->phy.id = 0;
+       hw->phy.type = ixgbe_phy_unknown;
+
+       return IXGBE_ERR_SFP_NOT_PRESENT;
+}
 
 
 /**
@@ -1296,10 +1897,12 @@ s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw,
         * SR modules
         */
        if (sfp_type == ixgbe_sfp_type_da_act_lmt_core0 ||
+           sfp_type == ixgbe_sfp_type_1g_lx_core0 ||
            sfp_type == ixgbe_sfp_type_1g_cu_core0 ||
            sfp_type == ixgbe_sfp_type_1g_sx_core0)
                sfp_type = ixgbe_sfp_type_srlr_core0;
        else if (sfp_type == ixgbe_sfp_type_da_act_lmt_core1 ||
+                sfp_type == ixgbe_sfp_type_1g_lx_core1 ||
                 sfp_type == ixgbe_sfp_type_1g_cu_core1 ||
                 sfp_type == ixgbe_sfp_type_1g_sx_core1)
                sfp_type = ixgbe_sfp_type_srlr_core1;
@@ -1409,37 +2012,50 @@ s32 ixgbe_write_i2c_eeprom_generic(struct ixgbe_hw *hw, u8 byte_offset,
 }
 
 /**
- *  ixgbe_read_i2c_byte_generic - Reads 8 bit word over I2C
+ * ixgbe_is_sfp_probe - Returns TRUE if SFP is being detected
+ * @hw: pointer to hardware structure
+ * @offset: eeprom offset to be read
+ * @addr: I2C address to be read
+ */
+static bool ixgbe_is_sfp_probe(struct ixgbe_hw *hw, u8 offset, u8 addr)
+{
+       if (addr == IXGBE_I2C_EEPROM_DEV_ADDR &&
+           offset == IXGBE_SFF_IDENTIFIER &&
+           hw->phy.sfp_type == ixgbe_sfp_type_not_present)
+               return TRUE;
+       return FALSE;
+}
+
+/**
+ *  ixgbe_read_i2c_byte_generic_int - Reads 8 bit word over I2C
  *  @hw: pointer to hardware structure
  *  @byte_offset: byte offset to read
  *  @data: value read
+ *  @lock: TRUE if to take and release semaphore
  *
  *  Performs byte read operation to SFP module's EEPROM over I2C interface at
  *  a specified device address.
  **/
-s32 ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset,
-                               u8 dev_addr, u8 *data)
+static s32 ixgbe_read_i2c_byte_generic_int(struct ixgbe_hw *hw, u8 byte_offset,
+                                          u8 dev_addr, u8 *data, bool lock)
 {
-       s32 status = IXGBE_SUCCESS;
+       s32 status;
        u32 max_retry = 10;
        u32 retry = 0;
-       u16 swfw_mask = 0;
+       u32 swfw_mask = hw->phy.phy_semaphore_mask;
        bool nack = 1;
        *data = 0;
 
        DEBUGFUNC("ixgbe_read_i2c_byte_generic");
 
-       if (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)
-               swfw_mask = IXGBE_GSSR_PHY1_SM;
-       else
-               swfw_mask = IXGBE_GSSR_PHY0_SM;
+       if (hw->mac.type >= ixgbe_mac_X550)
+               max_retry = 3;
+       if (ixgbe_is_sfp_probe(hw, byte_offset, dev_addr))
+               max_retry = IXGBE_SFP_DETECT_RETRIES;
 
        do {
-               if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask)
-                   != IXGBE_SUCCESS) {
-                       status = IXGBE_ERR_SWFW_SYNC;
-                       goto read_byte_out;
-               }
+               if (lock && hw->mac.ops.acquire_swfw_sync(hw, swfw_mask))
+                       return IXGBE_ERR_SWFW_SYNC;
 
                ixgbe_i2c_start(hw);
 
@@ -1480,12 +2096,16 @@ s32 ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset,
                        goto fail;
 
                ixgbe_i2c_stop(hw);
-               break;
+               if (lock)
+                       hw->mac.ops.release_swfw_sync(hw, swfw_mask);
+               return IXGBE_SUCCESS;
 
 fail:
                ixgbe_i2c_bus_clear(hw);
-               hw->mac.ops.release_swfw_sync(hw, swfw_mask);
-               msec_delay(100);
+               if (lock) {
+                       hw->mac.ops.release_swfw_sync(hw, swfw_mask);
+                       msec_delay(100);
+               }
                retry++;
                if (retry < max_retry)
                        DEBUGOUT("I2C byte read error - Retrying.\n");
@@ -1494,40 +2114,64 @@ fail:
 
        } while (retry < max_retry);
 
-       hw->mac.ops.release_swfw_sync(hw, swfw_mask);
-
-read_byte_out:
        return status;
 }
 
 /**
- *  ixgbe_write_i2c_byte_generic - Writes 8 bit word over I2C
+ *  ixgbe_read_i2c_byte_generic - Reads 8 bit word over I2C
+ *  @hw: pointer to hardware structure
+ *  @byte_offset: byte offset to read
+ *  @data: value read
+ *
+ *  Performs byte read operation to SFP module's EEPROM over I2C interface at
+ *  a specified device address.
+ **/
+s32 ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset,
+                               u8 dev_addr, u8 *data)
+{
+       return ixgbe_read_i2c_byte_generic_int(hw, byte_offset, dev_addr,
+                                              data, TRUE);
+}
+
+/**
+ *  ixgbe_read_i2c_byte_generic_unlocked - Reads 8 bit word over I2C
+ *  @hw: pointer to hardware structure
+ *  @byte_offset: byte offset to read
+ *  @data: value read
+ *
+ *  Performs byte read operation to SFP module's EEPROM over I2C interface at
+ *  a specified device address.
+ **/
+s32 ixgbe_read_i2c_byte_generic_unlocked(struct ixgbe_hw *hw, u8 byte_offset,
+                                        u8 dev_addr, u8 *data)
+{
+       return ixgbe_read_i2c_byte_generic_int(hw, byte_offset, dev_addr,
+                                              data, FALSE);
+}
+
+/**
+ *  ixgbe_write_i2c_byte_generic_int - Writes 8 bit word over I2C
  *  @hw: pointer to hardware structure
  *  @byte_offset: byte offset to write
  *  @data: value to write
+ *  @lock: TRUE if to take and release semaphore
  *
  *  Performs byte write operation to SFP module's EEPROM over I2C interface at
  *  a specified device address.
  **/
-s32 ixgbe_write_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset,
-                                u8 dev_addr, u8 data)
+static s32 ixgbe_write_i2c_byte_generic_int(struct ixgbe_hw *hw, u8 byte_offset,
+                                           u8 dev_addr, u8 data, bool lock)
 {
-       s32 status = IXGBE_SUCCESS;
+       s32 status;
        u32 max_retry = 1;
        u32 retry = 0;
-       u16 swfw_mask = 0;
+       u32 swfw_mask = hw->phy.phy_semaphore_mask;
 
        DEBUGFUNC("ixgbe_write_i2c_byte_generic");
 
-       if (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)
-               swfw_mask = IXGBE_GSSR_PHY1_SM;
-       else
-               swfw_mask = IXGBE_GSSR_PHY0_SM;
-
-       if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask) != IXGBE_SUCCESS) {
-               status = IXGBE_ERR_SWFW_SYNC;
-               goto write_byte_out;
-       }
+       if (lock && hw->mac.ops.acquire_swfw_sync(hw, swfw_mask) !=
+           IXGBE_SUCCESS)
+               return IXGBE_ERR_SWFW_SYNC;
 
        do {
                ixgbe_i2c_start(hw);
@@ -1557,7 +2201,9 @@ s32 ixgbe_write_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset,
                        goto fail;
 
                ixgbe_i2c_stop(hw);
-               break;
+               if (lock)
+                       hw->mac.ops.release_swfw_sync(hw, swfw_mask);
+               return IXGBE_SUCCESS;
 
 fail:
                ixgbe_i2c_bus_clear(hw);
@@ -1568,24 +2214,59 @@ fail:
                        DEBUGOUT("I2C byte write error.\n");
        } while (retry < max_retry);
 
-       hw->mac.ops.release_swfw_sync(hw, swfw_mask);
+       if (lock)
+               hw->mac.ops.release_swfw_sync(hw, swfw_mask);
 
-write_byte_out:
        return status;
 }
 
+/**
+ *  ixgbe_write_i2c_byte_generic - Writes 8 bit word over I2C
+ *  @hw: pointer to hardware structure
+ *  @byte_offset: byte offset to write
+ *  @data: value to write
+ *
+ *  Performs byte write operation to SFP module's EEPROM over I2C interface at
+ *  a specified device address.
+ **/
+s32 ixgbe_write_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset,
+                                u8 dev_addr, u8 data)
+{
+       return ixgbe_write_i2c_byte_generic_int(hw, byte_offset, dev_addr,
+                                               data, TRUE);
+}
+
+/**
+ *  ixgbe_write_i2c_byte_generic_unlocked - Writes 8 bit word over I2C
+ *  @hw: pointer to hardware structure
+ *  @byte_offset: byte offset to write
+ *  @data: value to write
+ *
+ *  Performs byte write operation to SFP module's EEPROM over I2C interface at
+ *  a specified device address.
+ **/
+s32 ixgbe_write_i2c_byte_generic_unlocked(struct ixgbe_hw *hw, u8 byte_offset,
+                                         u8 dev_addr, u8 data)
+{
+       return ixgbe_write_i2c_byte_generic_int(hw, byte_offset, dev_addr,
+                                               data, FALSE);
+}
+
 /**
  *  ixgbe_i2c_start - Sets I2C start condition
  *  @hw: pointer to hardware structure
  *
  *  Sets I2C start condition (High -> Low on SDA while SCL is High)
+ *  Set bit-bang mode on X550 hardware.
  **/
 static void ixgbe_i2c_start(struct ixgbe_hw *hw)
 {
-       u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL);
+       u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL_BY_MAC(hw));
 
        DEBUGFUNC("ixgbe_i2c_start");
 
+       i2cctl |= IXGBE_I2C_BB_EN_BY_MAC(hw);
+
        /* Start condition must begin with data and clock high */
        ixgbe_set_i2c_data(hw, &i2cctl, 1);
        ixgbe_raise_i2c_clk(hw, &i2cctl);
@@ -1610,10 +2291,15 @@ static void ixgbe_i2c_start(struct ixgbe_hw *hw)
  *  @hw: pointer to hardware structure
  *
  *  Sets I2C stop condition (Low -> High on SDA while SCL is High)
+ *  Disables bit-bang mode and negates data output enable on X550
+ *  hardware.
  **/
 static void ixgbe_i2c_stop(struct ixgbe_hw *hw)
 {
-       u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL);
+       u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL_BY_MAC(hw));
+       u32 data_oe_bit = IXGBE_I2C_DATA_OE_N_EN_BY_MAC(hw);
+       u32 clk_oe_bit = IXGBE_I2C_CLK_OE_N_EN_BY_MAC(hw);
+       u32 bb_en_bit = IXGBE_I2C_BB_EN_BY_MAC(hw);
 
        DEBUGFUNC("ixgbe_i2c_stop");
 
@@ -1628,6 +2314,13 @@ static void ixgbe_i2c_stop(struct ixgbe_hw *hw)
 
        /* bus free time between stop and start (4.7us)*/
        usec_delay(IXGBE_I2C_T_BUF);
+
+       if (bb_en_bit || data_oe_bit || clk_oe_bit) {
+               i2cctl &= ~bb_en_bit;
+               i2cctl |= data_oe_bit | clk_oe_bit;
+               IXGBE_WRITE_REG(hw, IXGBE_I2CCTL_BY_MAC(hw), i2cctl);
+               IXGBE_WRITE_FLUSH(hw);
+       }
 }
 
 /**
@@ -1644,6 +2337,7 @@ static s32 ixgbe_clock_in_i2c_byte(struct ixgbe_hw *hw, u8 *data)
 
        DEBUGFUNC("ixgbe_clock_in_i2c_byte");
 
+       *data = 0;
        for (i = 7; i >= 0; i--) {
                ixgbe_clock_in_i2c_bit(hw, &bit);
                *data |= bit << i;
@@ -1664,7 +2358,7 @@ static s32 ixgbe_clock_out_i2c_byte(struct ixgbe_hw *hw, u8 data)
        s32 status = IXGBE_SUCCESS;
        s32 i;
        u32 i2cctl;
-       bool bit = 0;
+       bool bit;
 
        DEBUGFUNC("ixgbe_clock_out_i2c_byte");
 
@@ -1677,9 +2371,10 @@ static s32 ixgbe_clock_out_i2c_byte(struct ixgbe_hw *hw, u8 data)
        }
 
        /* Release SDA line (set high) */
-       i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL);
-       i2cctl |= IXGBE_I2C_DATA_OUT;
-       IXGBE_WRITE_REG(hw, IXGBE_I2CCTL, i2cctl);
+       i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL_BY_MAC(hw));
+       i2cctl |= IXGBE_I2C_DATA_OUT_BY_MAC(hw);
+       i2cctl |= IXGBE_I2C_DATA_OE_N_EN_BY_MAC(hw);
+       IXGBE_WRITE_REG(hw, IXGBE_I2CCTL_BY_MAC(hw), i2cctl);
        IXGBE_WRITE_FLUSH(hw);
 
        return status;