Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/next...
authorDavid S. Miller <davem@davemloft.net>
Wed, 2 Sep 2015 03:17:17 +0000 (20:17 -0700)
committerDavid S. Miller <davem@davemloft.net>
Wed, 2 Sep 2015 03:17:17 +0000 (20:17 -0700)
Jeff Kirsher says:

====================
Intel Wired LAN Driver Updates 2015-09-01

This series contains updates to i40e, ixgbe and ixgbevf.

Anjali fixes a bug in i40e where the port is not receiving multicast or VLAN
tagged packets in promiscuous mode.  Which can occur when a software bridge
is created on top of the device.

Don adds support in ixgbe that indicates the presence of management firmware.
Added support for entering low power link up state on devices that support
it when the device is closing or suspending.  Updated the driver to report
unknown bus speed and width since IOSF does not report a PCIe bus speed or
width for X550 devices.  Also added the new bus type for integrated I/O
interface (IOSF).  Cleaned up of redundant code in ixgbe.

Mark adds support for UDP-encapsulation transmit checksum and for VXLAN
receive offloads.  Introduces a helper function to do the register access
and processing to avoid needless PHY access on copper PHYs.  Added support
for reporting 2.5G link speed.  Fixed warnings resulting from redundant
initializations of the get_bus_info field.

Maninder Singh updates the ixgbe driver to use kzalloc instead of kcalloc
for allocation of one thing.

Tom Barbette adds support for ethtool to change the rxfh indirection table
and/or key using ethtool interface.

Emil resolves an issue where users were not able to dynamically set number
of queues for 82598 via ethtool -L.

Alex Williamson removes bimodal SR-IOV disabling behavior since it is
confusing to users and results in a state where the PF is broken for other
uses unless the user sets sriov_numvfs to zero prior to unbinding the
device.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
12 files changed:
drivers/net/ethernet/intel/i40e/i40e.h
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe.h
drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c

index 05df21c..e746279 100644 (file)
@@ -372,6 +372,7 @@ struct i40e_pf {
 #ifdef CONFIG_DEBUG_FS
        struct dentry *i40e_dbg_pf;
 #endif /* CONFIG_DEBUG_FS */
+       bool cur_promisc;
 
        u16 instance; /* A unique number per i40e_pf instance in the system */
 
index a97f193..851c1a1 100644 (file)
@@ -1937,15 +1937,35 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
                cur_promisc = (!!(vsi->current_netdev_flags & IFF_PROMISC) ||
                               test_bit(__I40E_FILTER_OVERFLOW_PROMISC,
                                        &vsi->state));
-               ret = i40e_aq_set_vsi_unicast_promiscuous(&vsi->back->hw,
+               if (vsi->type == I40E_VSI_MAIN && pf->lan_veb != I40E_NO_VEB) {
+                       /* set defport ON for Main VSI instead of true promisc
+                        * this way we will get all unicast/multicast and VLAN
+                        * promisc behavior but will not get VF or VMDq traffic
+                        * replicated on the Main VSI.
+                        */
+                       if (pf->cur_promisc != cur_promisc) {
+                               pf->cur_promisc = cur_promisc;
+                               i40e_do_reset_safe(pf,
+                                               BIT(__I40E_PF_RESET_REQUESTED));
+                       }
+               } else {
+                       ret = i40e_aq_set_vsi_unicast_promiscuous(
+                                                         &vsi->back->hw,
                                                          vsi->seid,
                                                          cur_promisc, NULL);
-               if (ret)
-                       dev_info(&pf->pdev->dev,
-                                "set uni promisc failed, err %s, aq_err %s\n",
-                                i40e_stat_str(&pf->hw, ret),
-                                i40e_aq_str(&pf->hw,
-                                            pf->hw.aq.asq_last_status));
+                       if (ret)
+                               dev_info(&pf->pdev->dev,
+                                        "set unicast promisc failed, err %d, aq_err %d\n",
+                                        ret, pf->hw.aq.asq_last_status);
+                       ret = i40e_aq_set_vsi_multicast_promiscuous(
+                                                         &vsi->back->hw,
+                                                         vsi->seid,
+                                                         cur_promisc, NULL);
+                       if (ret)
+                               dev_info(&pf->pdev->dev,
+                                        "set multicast promisc failed, err %d, aq_err %d\n",
+                                        ret, pf->hw.aq.asq_last_status);
+               }
                ret = i40e_aq_set_vsi_broadcast(&vsi->back->hw,
                                                vsi->seid,
                                                cur_promisc, NULL);
@@ -4001,6 +4021,7 @@ static void i40e_vsi_close(struct i40e_vsi *vsi)
        i40e_vsi_free_irq(vsi);
        i40e_vsi_free_tx_resources(vsi);
        i40e_vsi_free_rx_resources(vsi);
+       vsi->current_netdev_flags = 0;
 }
 
 /**
@@ -9312,7 +9333,7 @@ void i40e_veb_release(struct i40e_veb *veb)
 static int i40e_add_veb(struct i40e_veb *veb, struct i40e_vsi *vsi)
 {
        struct i40e_pf *pf = veb->pf;
-       bool is_default = false;
+       bool is_default = veb->pf->cur_promisc;
        bool is_cloud = false;
        int ret;
 
index ac3ac2a..edf1fb9 100644 (file)
@@ -630,6 +630,7 @@ struct ixgbe_adapter {
 #define IXGBE_FLAG_FCOE_ENABLED                 (u32)(1 << 21)
 #define IXGBE_FLAG_SRIOV_CAPABLE                (u32)(1 << 22)
 #define IXGBE_FLAG_SRIOV_ENABLED                (u32)(1 << 23)
+#define IXGBE_FLAG_VXLAN_OFFLOAD_CAPABLE       BIT(24)
 
        u32 flags2;
 #define IXGBE_FLAG2_RSC_CAPABLE                 (u32)(1 << 0)
@@ -644,6 +645,9 @@ struct ixgbe_adapter {
 #define IXGBE_FLAG2_RSS_FIELD_IPV6_UDP         (u32)(1 << 9)
 #define IXGBE_FLAG2_PTP_PPS_ENABLED            (u32)(1 << 10)
 #define IXGBE_FLAG2_PHY_INTERRUPT              (u32)(1 << 11)
+#ifdef CONFIG_IXGBE_VXLAN
+#define IXGBE_FLAG2_VXLAN_REREG_NEEDED         BIT(12)
+#endif
 
        /* Tx fast path data */
        int num_tx_queues;
@@ -757,7 +761,9 @@ struct ixgbe_adapter {
        u32 timer_event_accumulator;
        u32 vferr_refcount;
        struct ixgbe_mac_addr *mac_table;
+#ifdef CONFIG_IXGBE_VXLAN
        u16 vxlan_port;
+#endif
        struct kobject *info_kobj;
 #ifdef CONFIG_IXGBE_HWMON
        struct hwmon_buff *ixgbe_hwmon_buff;
@@ -967,4 +973,5 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
                                  struct ixgbe_adapter *adapter,
                                  struct ixgbe_ring *tx_ring);
 u32 ixgbe_rss_indir_tbl_entries(struct ixgbe_adapter *adapter);
+void ixgbe_store_reta(struct ixgbe_adapter *adapter);
 #endif /* _IXGBE_H_ */
index b1e364d..dd7062f 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2014 Intel Corporation.
+  Copyright(c) 1999 - 2015 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -504,16 +504,12 @@ static enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw)
  **/
 static void ixgbe_stop_mac_link_on_d3_82599(struct ixgbe_hw *hw)
 {
-       u32 autoc2_reg, fwsm;
+       u32 autoc2_reg;
        u16 ee_ctrl_2 = 0;
 
        hw->eeprom.ops.read(hw, IXGBE_EEPROM_CTRL_2, &ee_ctrl_2);
 
-       /* Check to see if MNG FW could be enabled */
-       fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM(hw));
-
-       if (((fwsm & IXGBE_FWSM_MODE_MASK) != IXGBE_FWSM_FW_MODE_PT) &&
-           !hw->wol_enabled &&
+       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;
@@ -1245,6 +1241,25 @@ mac_reset_top:
        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 0;
+               udelay(10);
+       }
+
+       return IXGBE_ERR_FDIR_CMD_INCOMPLETE;
+}
+
 /**
  *  ixgbe_reinit_fdir_tables_82599 - Reinitialize Flow Director tables.
  *  @hw: pointer to hardware structure
@@ -1253,6 +1268,8 @@ s32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw)
 {
        int i;
        u32 fdirctrl = IXGBE_READ_REG(hw, IXGBE_FDIRCTRL);
+       u32 fdircmd;
+       s32 err;
 
        fdirctrl &= ~IXGBE_FDIRCTRL_INIT_DONE;
 
@@ -1260,15 +1277,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;
-               udelay(10);
-       }
-       if (i >= IXGBE_FDIRCMD_CMD_POLL) {
-               hw_dbg(hw, "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) {
+               hw_dbg(hw, "Flow Director previous command did not complete, aborting table re-initialization.\n");
+               return err;
        }
 
        IXGBE_WRITE_REG(hw, IXGBE_FDIRFREE, 0);
@@ -1507,20 +1519,28 @@ static 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;
 
        /*
         * Get the flow_type in order to program FDIRCMD properly
         * lowest 2 bits are FDIRCMD.L4TYPE, third lowest bit is FDIRCMD.IPV6
         */
-       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:
@@ -1536,8 +1556,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
@@ -1758,6 +1780,7 @@ s32 ixgbe_fdir_write_perfect_filter_82599(struct ixgbe_hw *hw,
                                          u16 soft_id, u8 queue)
 {
        u32 fdirport, fdirvlan, fdirhash, fdircmd;
+       s32 err;
 
        /* currently IPv6 is not supported, must be programmed with 0 */
        IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(0),
@@ -1806,6 +1829,11 @@ s32 ixgbe_fdir_write_perfect_filter_82599(struct ixgbe_hw *hw,
        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) {
+               hw_dbg(hw, "Flow Director command did not complete!\n");
+               return err;
+       }
 
        return 0;
 }
@@ -1815,9 +1843,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 = 0;
+       u32 fdircmd;
+       s32 err;
 
        /* configure FDIRHASH register */
        fdirhash = input->formatted.bkt_hash;
@@ -1830,18 +1857,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 */
-               udelay(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) {
+               hw_dbg(hw, "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);
@@ -1850,7 +1871,7 @@ s32 ixgbe_fdir_erase_perfect_filter_82599(struct ixgbe_hw *hw,
                                IXGBE_FDIRCMD_CMD_REMOVE_FLOW);
        }
 
-       return err;
+       return 0;
 }
 
 /**
index 4c1c267..3f56a80 100644 (file)
@@ -3905,3 +3905,18 @@ void ixgbe_enable_rx_generic(struct ixgbe_hw *hw)
                }
        }
 }
+
+/** 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(hw));
+       fwsm &= IXGBE_FWSM_MODE_MASK;
+       return fwsm == IXGBE_FWSM_FW_MODE_PT;
+}
index ec015fe..2f779f3 100644 (file)
@@ -113,6 +113,7 @@ s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min,
 s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer,
                                 u32 length, u32 timeout, bool return_data);
 void ixgbe_clear_tx_pending(struct ixgbe_hw *hw);
+bool ixgbe_mng_present(struct ixgbe_hw *hw);
 bool ixgbe_mng_enabled(struct ixgbe_hw *hw);
 
 void ixgbe_set_rxpba_generic(struct ixgbe_hw *hw, int num_pb,
index f7aeb56..ab2edc8 100644 (file)
@@ -166,6 +166,8 @@ static int ixgbe_get_settings(struct net_device *netdev,
        /* set the supported link speeds */
        if (supported_link & IXGBE_LINK_SPEED_10GB_FULL)
                ecmd->supported |= SUPPORTED_10000baseT_Full;
+       if (supported_link & IXGBE_LINK_SPEED_2_5GB_FULL)
+               ecmd->supported |= SUPPORTED_2500baseX_Full;
        if (supported_link & IXGBE_LINK_SPEED_1GB_FULL)
                ecmd->supported |= SUPPORTED_1000baseT_Full;
        if (supported_link & IXGBE_LINK_SPEED_100_FULL)
@@ -177,6 +179,8 @@ static int ixgbe_get_settings(struct net_device *netdev,
                        ecmd->advertising |= ADVERTISED_100baseT_Full;
                if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL)
                        ecmd->advertising |= ADVERTISED_10000baseT_Full;
+               if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_2_5GB_FULL)
+                       ecmd->advertising |= ADVERTISED_2500baseX_Full;
                if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL)
                        ecmd->advertising |= ADVERTISED_1000baseT_Full;
        } else {
@@ -286,6 +290,9 @@ static int ixgbe_get_settings(struct net_device *netdev,
                case IXGBE_LINK_SPEED_10GB_FULL:
                        ethtool_cmd_speed_set(ecmd, SPEED_10000);
                        break;
+               case IXGBE_LINK_SPEED_2_5GB_FULL:
+                       ethtool_cmd_speed_set(ecmd, SPEED_2500);
+                       break;
                case IXGBE_LINK_SPEED_1GB_FULL:
                        ethtool_cmd_speed_set(ecmd, SPEED_1000);
                        break;
@@ -2868,6 +2875,14 @@ static int ixgbe_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
        return ret;
 }
 
+static int ixgbe_rss_indir_tbl_max(struct ixgbe_adapter *adapter)
+{
+       if (adapter->hw.mac.type < ixgbe_mac_X550)
+               return 16;
+       else
+               return 64;
+}
+
 static u32 ixgbe_get_rxfh_key_size(struct net_device *netdev)
 {
        struct ixgbe_adapter *adapter = netdev_priv(netdev);
@@ -2907,6 +2922,44 @@ static int ixgbe_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
        return 0;
 }
 
+static int ixgbe_set_rxfh(struct net_device *netdev, const u32 *indir,
+                         const u8 *key, const u8 hfunc)
+{
+       struct ixgbe_adapter *adapter = netdev_priv(netdev);
+       int i;
+       u32 reta_entries = ixgbe_rss_indir_tbl_entries(adapter);
+
+       if (hfunc)
+               return -EINVAL;
+
+       /* Fill out the redirection table */
+       if (indir) {
+               int max_queues = min_t(int, adapter->num_rx_queues,
+                                      ixgbe_rss_indir_tbl_max(adapter));
+
+               /*Allow at least 2 queues w/ SR-IOV.*/
+               if ((adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) &&
+                   (max_queues < 2))
+                       max_queues = 2;
+
+               /* Verify user input. */
+               for (i = 0; i < reta_entries; i++)
+                       if (indir[i] >= max_queues)
+                               return -EINVAL;
+
+               for (i = 0; i < reta_entries; i++)
+                       adapter->rss_indir_tbl[i] = indir[i];
+       }
+
+       /* Fill out the rss hash key */
+       if (key)
+               memcpy(adapter->rss_key, key, ixgbe_get_rxfh_key_size(netdev));
+
+       ixgbe_store_reta(adapter);
+
+       return 0;
+}
+
 static int ixgbe_get_ts_info(struct net_device *dev,
                             struct ethtool_ts_info *info)
 {
@@ -3159,6 +3212,7 @@ static const struct ethtool_ops ixgbe_ethtool_ops = {
        .get_rxfh_indir_size    = ixgbe_rss_indir_size,
        .get_rxfh_key_size      = ixgbe_get_rxfh_key_size,
        .get_rxfh               = ixgbe_get_rxfh,
+       .set_rxfh               = ixgbe_set_rxfh,
        .get_channels           = ixgbe_get_channels,
        .set_channels           = ixgbe_set_channels,
        .get_ts_info            = ixgbe_get_ts_info,
index ab28dc2..63b2cfe 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2014 Intel Corporation.
+  Copyright(c) 1999 - 2015 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -65,6 +65,9 @@
 #include "ixgbe_common.h"
 #include "ixgbe_dcb_82599.h"
 #include "ixgbe_sriov.h"
+#ifdef CONFIG_IXGBE_VXLAN
+#include <net/vxlan.h>
+#endif
 
 char ixgbe_driver_name[] = "ixgbe";
 static const char ixgbe_driver_string[] =
@@ -79,7 +82,7 @@ static char ixgbe_default_device_descr[] =
 #define DRV_VERSION "4.0.1-k"
 const char ixgbe_driver_version[] = DRV_VERSION;
 static const char ixgbe_copyright[] =
-                               "Copyright (c) 1999-2014 Intel Corporation.";
+                               "Copyright (c) 1999-2015 Intel Corporation.";
 
 static const char ixgbe_overheat_msg[] = "Network adapter has been stopped because it has over heated. Restart the computer. If the problem persists, power off the system and replace the adapter";
 
@@ -243,11 +246,19 @@ static inline bool ixgbe_pcie_from_parent(struct ixgbe_hw *hw)
 static void ixgbe_check_minimum_link(struct ixgbe_adapter *adapter,
                                     int expected_gts)
 {
+       struct ixgbe_hw *hw = &adapter->hw;
        int max_gts = 0;
        enum pci_bus_speed speed = PCI_SPEED_UNKNOWN;
        enum pcie_link_width width = PCIE_LNK_WIDTH_UNKNOWN;
        struct pci_dev *pdev;
 
+       /* Some devices are not connected over PCIe and thus do not negotiate
+        * speed. These devices do not have valid bus info, and thus any report
+        * we generate may not be correct.
+        */
+       if (hw->bus.type == ixgbe_bus_type_internal)
+               return;
+
        /* determine whether to use the parent device */
        if (ixgbe_pcie_from_parent(&adapter->hw))
                pdev = adapter->pdev->bus->parent->self;
@@ -1430,7 +1441,6 @@ static inline void ixgbe_rx_checksum(struct ixgbe_ring *ring,
            (hdr_info & cpu_to_le16(IXGBE_RXDADV_PKTTYPE_TUNNEL >> 16))) {
                encap_pkt = true;
                skb->encapsulation = 1;
-               skb->ip_summed = CHECKSUM_NONE;
        }
 
        /* if IP and error */
@@ -3303,7 +3313,7 @@ u32 ixgbe_rss_indir_tbl_entries(struct ixgbe_adapter *adapter)
  *
  * Write the RSS redirection table stored in adapter.rss_indir_tbl[] to HW.
  */
-static void ixgbe_store_reta(struct ixgbe_adapter *adapter)
+void ixgbe_store_reta(struct ixgbe_adapter *adapter)
 {
        u32 i, reta_entries = ixgbe_rss_indir_tbl_entries(adapter);
        struct ixgbe_hw *hw = &adapter->hw;
@@ -4261,6 +4271,21 @@ static void ixgbe_napi_disable_all(struct ixgbe_adapter *adapter)
        }
 }
 
+static void ixgbe_clear_vxlan_port(struct ixgbe_adapter *adapter)
+{
+       switch (adapter->hw.mac.type) {
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_x:
+               IXGBE_WRITE_REG(&adapter->hw, IXGBE_VXLANCTRL, 0);
+#ifdef CONFIG_IXGBE_VXLAN
+               adapter->vxlan_port = 0;
+#endif
+               break;
+       default:
+               break;
+       }
+}
+
 #ifdef CONFIG_IXGBE_DCB
 /**
  * ixgbe_configure_dcb - Configure DCB hardware
@@ -5301,6 +5326,9 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter)
        case ixgbe_mac_X550:
 #ifdef CONFIG_IXGBE_DCA
                adapter->flags &= ~IXGBE_FLAG_DCA_CAPABLE;
+#endif
+#ifdef CONFIG_IXGBE_VXLAN
+               adapter->flags |= IXGBE_FLAG_VXLAN_OFFLOAD_CAPABLE;
 #endif
                break;
        default:
@@ -5753,10 +5781,11 @@ static int ixgbe_open(struct net_device *netdev)
 
        ixgbe_up_complete(adapter);
 
-#if IS_ENABLED(CONFIG_IXGBE_VXLAN)
+       ixgbe_clear_vxlan_port(adapter);
+#ifdef CONFIG_IXGBE_VXLAN
        vxlan_get_rx_port(netdev);
-
 #endif
+
        return 0;
 
 err_set_queues:
@@ -5777,7 +5806,15 @@ static void ixgbe_close_suspend(struct ixgbe_adapter *adapter)
 {
        ixgbe_ptp_suspend(adapter);
 
-       ixgbe_down(adapter);
+       if (adapter->hw.phy.ops.enter_lplu) {
+               adapter->hw.phy.reset_disable = true;
+               ixgbe_down(adapter);
+               adapter->hw.phy.ops.enter_lplu(&adapter->hw);
+               adapter->hw.phy.reset_disable = false;
+       } else {
+               ixgbe_down(adapter);
+       }
+
        ixgbe_free_irq(adapter);
 
        ixgbe_free_all_tx_resources(adapter);
@@ -6343,6 +6380,7 @@ static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter)
        struct net_device *upper;
        struct list_head *iter;
        u32 link_speed = adapter->link_speed;
+       const char *speed_str;
        bool flow_rx, flow_tx;
 
        /* only continue if link was previously down */
@@ -6380,14 +6418,24 @@ static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter)
        if (test_bit(__IXGBE_PTP_RUNNING, &adapter->state))
                ixgbe_ptp_start_cyclecounter(adapter);
 
-       e_info(drv, "NIC Link is Up %s, Flow Control: %s\n",
-              (link_speed == IXGBE_LINK_SPEED_10GB_FULL ?
-              "10 Gbps" :
-              (link_speed == IXGBE_LINK_SPEED_1GB_FULL ?
-              "1 Gbps" :
-              (link_speed == IXGBE_LINK_SPEED_100_FULL ?
-              "100 Mbps" :
-              "unknown speed"))),
+       switch (link_speed) {
+       case IXGBE_LINK_SPEED_10GB_FULL:
+               speed_str = "10 Gbps";
+               break;
+       case IXGBE_LINK_SPEED_2_5GB_FULL:
+               speed_str = "2.5 Gbps";
+               break;
+       case IXGBE_LINK_SPEED_1GB_FULL:
+               speed_str = "1 Gbps";
+               break;
+       case IXGBE_LINK_SPEED_100_FULL:
+               speed_str = "100 Mbps";
+               break;
+       default:
+               speed_str = "unknown speed";
+               break;
+       }
+       e_info(drv, "NIC Link is Up %s, Flow Control: %s\n", speed_str,
               ((flow_rx && flow_tx) ? "RX/TX" :
               (flow_rx ? "RX" :
               (flow_tx ? "TX" : "None"))));
@@ -6816,6 +6864,12 @@ static void ixgbe_service_task(struct work_struct *work)
                ixgbe_service_event_complete(adapter);
                return;
        }
+#ifdef CONFIG_IXGBE_VXLAN
+       if (adapter->flags2 & IXGBE_FLAG2_VXLAN_REREG_NEEDED) {
+               adapter->flags2 &= ~IXGBE_FLAG2_VXLAN_REREG_NEEDED;
+               vxlan_get_rx_port(adapter->netdev);
+       }
+#endif /* CONFIG_IXGBE_VXLAN */
        ixgbe_reset_subtask(adapter);
        ixgbe_phy_interrupt_subtask(adapter);
        ixgbe_sfp_detection_subtask(adapter);
@@ -6912,31 +6966,55 @@ static void ixgbe_tx_csum(struct ixgbe_ring *tx_ring,
                if (!(first->tx_flags & IXGBE_TX_FLAGS_HW_VLAN) &&
                    !(first->tx_flags & IXGBE_TX_FLAGS_CC))
                        return;
+               vlan_macip_lens = skb_network_offset(skb) <<
+                                 IXGBE_ADVTXD_MACLEN_SHIFT;
        } else {
                u8 l4_hdr = 0;
-               switch (first->protocol) {
-               case htons(ETH_P_IP):
-                       vlan_macip_lens |= skb_network_header_len(skb);
+               union {
+                       struct iphdr *ipv4;
+                       struct ipv6hdr *ipv6;
+                       u8 *raw;
+               } network_hdr;
+               union {
+                       struct tcphdr *tcphdr;
+                       u8 *raw;
+               } transport_hdr;
+
+               if (skb->encapsulation) {
+                       network_hdr.raw = skb_inner_network_header(skb);
+                       transport_hdr.raw = skb_inner_transport_header(skb);
+                       vlan_macip_lens = skb_inner_network_offset(skb) <<
+                                         IXGBE_ADVTXD_MACLEN_SHIFT;
+               } else {
+                       network_hdr.raw = skb_network_header(skb);
+                       transport_hdr.raw = skb_transport_header(skb);
+                       vlan_macip_lens = skb_network_offset(skb) <<
+                                         IXGBE_ADVTXD_MACLEN_SHIFT;
+               }
+
+               /* use first 4 bits to determine IP version */
+               switch (network_hdr.ipv4->version) {
+               case IPVERSION:
+                       vlan_macip_lens |= transport_hdr.raw - network_hdr.raw;
                        type_tucmd |= IXGBE_ADVTXD_TUCMD_IPV4;
-                       l4_hdr = ip_hdr(skb)->protocol;
+                       l4_hdr = network_hdr.ipv4->protocol;
                        break;
-               case htons(ETH_P_IPV6):
-                       vlan_macip_lens |= skb_network_header_len(skb);
-                       l4_hdr = ipv6_hdr(skb)->nexthdr;
+               case 6:
+                       vlan_macip_lens |= transport_hdr.raw - network_hdr.raw;
+                       l4_hdr = network_hdr.ipv6->nexthdr;
                        break;
                default:
                        if (unlikely(net_ratelimit())) {
                                dev_warn(tx_ring->dev,
-                                "partial checksum but proto=%x!\n",
-                                first->protocol);
+                                        "partial checksum but version=%d\n",
+                                        network_hdr.ipv4->version);
                        }
-                       break;
                }
 
                switch (l4_hdr) {
                case IPPROTO_TCP:
                        type_tucmd |= IXGBE_ADVTXD_TUCMD_L4T_TCP;
-                       mss_l4len_idx = tcp_hdrlen(skb) <<
+                       mss_l4len_idx = (transport_hdr.tcphdr->doff * 4) <<
                                        IXGBE_ADVTXD_L4LEN_SHIFT;
                        break;
                case IPPROTO_SCTP:
@@ -6962,7 +7040,6 @@ static void ixgbe_tx_csum(struct ixgbe_ring *tx_ring,
        }
 
        /* vlan_macip_lens: MACLEN, VLAN tag */
-       vlan_macip_lens |= skb_network_offset(skb) << IXGBE_ADVTXD_MACLEN_SHIFT;
        vlan_macip_lens |= first->tx_flags & IXGBE_TX_FLAGS_VLAN_MASK;
 
        ixgbe_tx_ctxtdesc(tx_ring, vlan_macip_lens, 0,
@@ -7217,6 +7294,10 @@ static void ixgbe_atr(struct ixgbe_ring *ring,
                struct ipv6hdr *ipv6;
        } hdr;
        struct tcphdr *th;
+       struct sk_buff *skb;
+#ifdef CONFIG_IXGBE_VXLAN
+       u8 encap = false;
+#endif /* CONFIG_IXGBE_VXLAN */
        __be16 vlan_id;
 
        /* if ring doesn't have a interrupt vector, cannot perform ATR */
@@ -7230,16 +7311,36 @@ static void ixgbe_atr(struct ixgbe_ring *ring,
        ring->atr_count++;
 
        /* snag network header to get L4 type and address */
-       hdr.network = skb_network_header(first->skb);
+       skb = first->skb;
+       hdr.network = skb_network_header(skb);
+       if (skb->encapsulation) {
+#ifdef CONFIG_IXGBE_VXLAN
+               struct ixgbe_adapter *adapter = q_vector->adapter;
 
-       /* Currently only IPv4/IPv6 with TCP is supported */
-       if ((first->protocol != htons(ETH_P_IPV6) ||
-            hdr.ipv6->nexthdr != IPPROTO_TCP) &&
-           (first->protocol != htons(ETH_P_IP) ||
-            hdr.ipv4->protocol != IPPROTO_TCP))
+               if (!adapter->vxlan_port)
+                       return;
+               if (first->protocol != htons(ETH_P_IP) ||
+                   hdr.ipv4->version != IPVERSION ||
+                   hdr.ipv4->protocol != IPPROTO_UDP) {
+                       return;
+               }
+               if (ntohs(udp_hdr(skb)->dest) != adapter->vxlan_port)
+                       return;
+               encap = true;
+               hdr.network = skb_inner_network_header(skb);
+               th = inner_tcp_hdr(skb);
+#else
                return;
-
-       th = tcp_hdr(first->skb);
+#endif /* CONFIG_IXGBE_VXLAN */
+       } else {
+               /* Currently only IPv4/IPv6 with TCP is supported */
+               if ((first->protocol != htons(ETH_P_IPV6) ||
+                    hdr.ipv6->nexthdr != IPPROTO_TCP) &&
+                   (first->protocol != htons(ETH_P_IP) ||
+                    hdr.ipv4->protocol != IPPROTO_TCP))
+                       return;
+               th = tcp_hdr(skb);
+       }
 
        /* skip this packet since it is invalid or the socket is closing */
        if (!th || th->fin)
@@ -7288,6 +7389,11 @@ static void ixgbe_atr(struct ixgbe_ring *ring,
                             hdr.ipv6->daddr.s6_addr32[3];
        }
 
+#ifdef CONFIG_IXGBE_VXLAN
+       if (encap)
+               input.formatted.flow_type |= IXGBE_ATR_L4TYPE_TUNNEL_MASK;
+#endif /* CONFIG_IXGBE_VXLAN */
+
        /* This assumes the Rx queue and Tx queue are bound to the same CPU */
        ixgbe_fdir_add_signature_filter_82599(&q_vector->adapter->hw,
                                              input, common, ring->queue_index);
@@ -7753,9 +7859,10 @@ int ixgbe_setup_tc(struct net_device *dev, u8 tc)
        bool pools;
 
        /* Hardware supports up to 8 traffic classes */
-       if (tc > adapter->dcb_cfg.num_tcs.pg_tcs ||
-           (hw->mac.type == ixgbe_mac_82598EB &&
-            tc < MAX_TRAFFIC_CLASS))
+       if (tc > adapter->dcb_cfg.num_tcs.pg_tcs)
+               return -EINVAL;
+
+       if (hw->mac.type == ixgbe_mac_82598EB && tc && tc < MAX_TRAFFIC_CLASS)
                return -EINVAL;
 
        pools = (find_first_zero_bit(&adapter->fwd_bitmask, 32) > 1);
@@ -7914,12 +8021,23 @@ static int ixgbe_set_features(struct net_device *netdev,
                need_reset = true;
 
        netdev->features = features;
+
+#ifdef CONFIG_IXGBE_VXLAN
+       if ((adapter->flags & IXGBE_FLAG_VXLAN_OFFLOAD_CAPABLE)) {
+               if (features & NETIF_F_RXCSUM)
+                       adapter->flags2 |= IXGBE_FLAG2_VXLAN_REREG_NEEDED;
+               else
+                       ixgbe_clear_vxlan_port(adapter);
+       }
+#endif /* CONFIG_IXGBE_VXLAN */
+
        if (need_reset)
                ixgbe_do_reset(netdev);
 
        return 0;
 }
 
+#ifdef CONFIG_IXGBE_VXLAN
 /**
  * ixgbe_add_vxlan_port - Get notifications about VXLAN ports that come up
  * @dev: The port's netdev
@@ -7933,17 +8051,18 @@ static void ixgbe_add_vxlan_port(struct net_device *dev, sa_family_t sa_family,
        struct ixgbe_hw *hw = &adapter->hw;
        u16 new_port = ntohs(port);
 
+       if (!(adapter->flags & IXGBE_FLAG_VXLAN_OFFLOAD_CAPABLE))
+               return;
+
        if (sa_family == AF_INET6)
                return;
 
-       if (adapter->vxlan_port == new_port) {
-               netdev_info(dev, "Port %d already offloaded\n", new_port);
+       if (adapter->vxlan_port == new_port)
                return;
-       }
 
        if (adapter->vxlan_port) {
                netdev_info(dev,
-                           "Hit Max num of UDP ports, not adding port %d\n",
+                           "Hit Max num of VXLAN ports, not adding port %d\n",
                            new_port);
                return;
        }
@@ -7962,9 +8081,11 @@ static void ixgbe_del_vxlan_port(struct net_device *dev, sa_family_t sa_family,
                                 __be16 port)
 {
        struct ixgbe_adapter *adapter = netdev_priv(dev);
-       struct ixgbe_hw *hw = &adapter->hw;
        u16 new_port = ntohs(port);
 
+       if (!(adapter->flags & IXGBE_FLAG_VXLAN_OFFLOAD_CAPABLE))
+               return;
+
        if (sa_family == AF_INET6)
                return;
 
@@ -7974,9 +8095,10 @@ static void ixgbe_del_vxlan_port(struct net_device *dev, sa_family_t sa_family,
                return;
        }
 
-       adapter->vxlan_port = 0;
-       IXGBE_WRITE_REG(hw, IXGBE_VXLANCTRL, 0);
+       ixgbe_clear_vxlan_port(adapter);
+       adapter->flags2 |= IXGBE_FLAG2_VXLAN_REREG_NEEDED;
 }
+#endif /* CONFIG_IXGBE_VXLAN */
 
 static int ixgbe_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
                             struct net_device *dev,
@@ -8151,7 +8273,7 @@ static void *ixgbe_fwd_add(struct net_device *pdev, struct net_device *vdev)
            (adapter->num_rx_pools > IXGBE_MAX_MACVLANS))
                return ERR_PTR(-EBUSY);
 
-       fwd_adapter = kcalloc(1, sizeof(struct ixgbe_fwd_adapter), GFP_KERNEL);
+       fwd_adapter = kzalloc(sizeof(*fwd_adapter), GFP_KERNEL);
        if (!fwd_adapter)
                return ERR_PTR(-ENOMEM);
 
@@ -8207,6 +8329,21 @@ static void ixgbe_fwd_del(struct net_device *pdev, void *priv)
        kfree(fwd_adapter);
 }
 
+#define IXGBE_MAX_TUNNEL_HDR_LEN 80
+static netdev_features_t
+ixgbe_features_check(struct sk_buff *skb, struct net_device *dev,
+                    netdev_features_t features)
+{
+       if (!skb->encapsulation)
+               return features;
+
+       if (unlikely(skb_inner_mac_header(skb) - skb_transport_header(skb) >
+                    IXGBE_MAX_TUNNEL_HDR_LEN))
+               return features & ~NETIF_F_ALL_CSUM;
+
+       return features;
+}
+
 static const struct net_device_ops ixgbe_netdev_ops = {
        .ndo_open               = ixgbe_open,
        .ndo_stop               = ixgbe_close,
@@ -8252,8 +8389,11 @@ static const struct net_device_ops ixgbe_netdev_ops = {
        .ndo_bridge_getlink     = ixgbe_ndo_bridge_getlink,
        .ndo_dfwd_add_station   = ixgbe_fwd_add,
        .ndo_dfwd_del_station   = ixgbe_fwd_del,
+#ifdef CONFIG_IXGBE_VXLAN
        .ndo_add_vxlan_port     = ixgbe_add_vxlan_port,
        .ndo_del_vxlan_port     = ixgbe_del_vxlan_port,
+#endif /* CONFIG_IXGBE_VXLAN */
+       .ndo_features_check     = ixgbe_features_check,
 };
 
 /**
@@ -8613,17 +8753,24 @@ skip_sriov:
        netdev->vlan_features |= NETIF_F_IPV6_CSUM;
        netdev->vlan_features |= NETIF_F_SG;
 
+       netdev->hw_enc_features |= NETIF_F_SG | NETIF_F_IP_CSUM |
+                                  NETIF_F_IPV6_CSUM;
+
        netdev->priv_flags |= IFF_UNICAST_FLT;
        netdev->priv_flags |= IFF_SUPP_NOFCS;
 
+#ifdef CONFIG_IXGBE_VXLAN
        switch (adapter->hw.mac.type) {
        case ixgbe_mac_X550:
        case ixgbe_mac_X550EM_x:
-               netdev->hw_enc_features |= NETIF_F_RXCSUM;
+               netdev->hw_enc_features |= NETIF_F_RXCSUM |
+                                          NETIF_F_IP_CSUM |
+                                          NETIF_F_IPV6_CSUM;
                break;
        default:
                break;
        }
+#endif /* CONFIG_IXGBE_VXLAN */
 
 #ifdef CONFIG_IXGBE_DCB
        netdev->dcbnl_ops = &dcbnl_ops;
@@ -8710,9 +8857,10 @@ skip_sriov:
        hw->eeprom.ops.read(hw, 0x2d, &adapter->eeprom_verl);
 
        /* pick up the PCI bus settings for reporting later */
-       hw->mac.ops.get_bus_info(hw);
        if (ixgbe_pcie_from_parent(hw))
                ixgbe_get_parent_bus_info(adapter);
+       else
+                hw->mac.ops.get_bus_info(hw);
 
        /* calculate the expected PCIe bandwidth required for optimal
         * performance. Note that some older parts will never have enough
@@ -8875,12 +9023,7 @@ static void ixgbe_remove(struct pci_dev *pdev)
                unregister_netdev(netdev);
 
 #ifdef CONFIG_PCI_IOV
-       /*
-        * Only disable SR-IOV on unload if the user specified the now
-        * deprecated max_vfs module parameter.
-        */
-       if (max_vfs)
-               ixgbe_disable_sriov(adapter);
+       ixgbe_disable_sriov(adapter);
 #endif
        ixgbe_clear_interrupt_scheme(adapter);
 
index 526a20b..597d0b1 100644 (file)
@@ -243,9 +243,7 @@ s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw)
        u16 ext_ability = 0;
 
        if (!hw->phy.phy_semaphore_mask) {
-               hw->phy.lan_id = IXGBE_READ_REG(hw, IXGBE_STATUS) &
-                                IXGBE_STATUS_LAN_ID_1;
-               if (hw->phy.lan_id)
+               if (hw->bus.lan_id)
                        hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY1_SM;
                else
                        hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM;
@@ -608,12 +606,7 @@ s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
                                u32 device_type, u16 phy_data)
 {
        s32 status;
-       u32 gssr;
-
-       if (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)
-               gssr = IXGBE_GSSR_PHY1_SM;
-       else
-               gssr = IXGBE_GSSR_PHY0_SM;
+       u32 gssr = hw->phy.phy_semaphore_mask;
 
        if (hw->mac.ops.acquire_swfw_sync(hw, gssr) == 0) {
                status = ixgbe_write_phy_reg_mdi(hw, reg_addr, device_type,
@@ -737,39 +730,61 @@ s32 ixgbe_setup_phy_link_speed_generic(struct ixgbe_hw *hw,
 }
 
 /**
- * ixgbe_get_copper_link_capabilities_generic - Determines link capabilities
+ * ixgbe_get_copper_speeds_supported - Get copper link speed from phy
  * @hw: pointer to hardware structure
- * @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)
+static s32 ixgbe_get_copper_speeds_supported(struct ixgbe_hw *hw)
 {
-       s32 status;
        u16 speed_ability;
-
-       *speed = 0;
-       *autoneg = true;
+       s32 status;
 
        status = hw->phy.ops.read_reg(hw, MDIO_SPEED, MDIO_MMD_PMAPMD,
                                      &speed_ability);
+       if (status)
+               return status;
 
-       if (status == 0) {
-               if (speed_ability & MDIO_SPEED_10G)
-                       *speed |= IXGBE_LINK_SPEED_10GB_FULL;
-               if (speed_ability & MDIO_PMA_SPEED_1000)
-                       *speed |= IXGBE_LINK_SPEED_1GB_FULL;
-               if (speed_ability & MDIO_PMA_SPEED_100)
-                       *speed |= IXGBE_LINK_SPEED_100_FULL;
+       if (speed_ability & MDIO_SPEED_10G)
+               hw->phy.speeds_supported |= IXGBE_LINK_SPEED_10GB_FULL;
+       if (speed_ability & MDIO_PMA_SPEED_1000)
+               hw->phy.speeds_supported |= IXGBE_LINK_SPEED_1GB_FULL;
+       if (speed_ability & MDIO_PMA_SPEED_100)
+               hw->phy.speeds_supported |= IXGBE_LINK_SPEED_100_FULL;
+
+       switch (hw->mac.type) {
+       case ixgbe_mac_X550:
+               hw->phy.speeds_supported |= IXGBE_LINK_SPEED_2_5GB_FULL;
+               hw->phy.speeds_supported |= IXGBE_LINK_SPEED_5GB_FULL;
+               break;
+       case ixgbe_mac_X550EM_x:
+               hw->phy.speeds_supported &= ~IXGBE_LINK_SPEED_100_FULL;
+               break;
+       default:
+               break;
        }
 
-       /* Internal PHY does not support 100 Mbps */
-       if (hw->mac.type == ixgbe_mac_X550EM_x)
-               *speed &= ~IXGBE_LINK_SPEED_100_FULL;
+       return 0;
+}
+
+/**
+ * ixgbe_get_copper_link_capabilities_generic - Determines link capabilities
+ * @hw: pointer to hardware structure
+ * @speed: pointer to link speed
+ * @autoneg: boolean auto-negotiation value
+ */
+s32 ixgbe_get_copper_link_capabilities_generic(struct ixgbe_hw *hw,
+                                              ixgbe_link_speed *speed,
+                                              bool *autoneg)
+{
+       s32 status = 0;
+
+       *autoneg = true;
+       if (!hw->phy.speeds_supported)
+               status = ixgbe_get_copper_speeds_supported(hw);
 
+       *speed = hw->phy.speeds_supported;
        return status;
 }
 
index 4615a94..6368919 100644 (file)
@@ -848,6 +848,7 @@ struct ixgbe_thermal_sensor_data {
 #define IXGBE_MDIO_AUTO_NEG_LINK_STATUS        0x4 /* Indicates if link is up */
 
 #define IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_MASK 0x7 /* Speed/Duplex Mask */
+#define IXGBE_MDIO_AUTO_NEG_VEN_STAT_SPEED_MASK        0x6 /* Speed Mask */
 #define IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10M_HALF 0x0 /* 10Mb/s Half Duplex */
 #define IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10M_FULL 0x1 /* 10Mb/s Full Duplex */
 #define IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_100M_HALF 0x2 /* 100Mb/s H Duplex */
@@ -856,6 +857,24 @@ struct ixgbe_thermal_sensor_data {
 #define IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB_FULL 0x5 /* 1Gb/s Full Duplex */
 #define IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB_HALF 0x6 /* 10Gb/s Half Duplex */
 #define IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB_FULL 0x7 /* 10Gb/s Full Duplex */
+#define IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB  0x4 /* 1Gb/s */
+#define IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB 0x6 /* 10Gb/s */
+
+#define IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG   0x20    /* 10G Control Reg */
+#define IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG 0xC400        /* 1G Provisioning 1 */
+#define IXGBE_MII_AUTONEG_XNP_TX_REG           0x17    /* 1G XNP Transmit */
+#define IXGBE_MII_AUTONEG_ADVERTISE_REG                0x10    /* 100M Advertisement */
+#define IXGBE_MII_10GBASE_T_ADVERTISE          0x1000  /* full duplex, bit:12*/
+#define IXGBE_MII_1GBASE_T_ADVERTISE_XNP_TX    0x4000  /* full duplex, bit:14*/
+#define IXGBE_MII_1GBASE_T_ADVERTISE           0x8000  /* full duplex, bit:15*/
+#define IXGBE_MII_2_5GBASE_T_ADVERTISE         0x0400
+#define IXGBE_MII_5GBASE_T_ADVERTISE           0x0800
+#define IXGBE_MII_100BASE_T_ADVERTISE          0x0100  /* full duplex, bit:8 */
+#define IXGBE_MII_100BASE_T_ADVERTISE_HALF     0x0080  /* half duplex, bit:7 */
+#define IXGBE_MII_RESTART                      0x200
+#define IXGBE_MII_AUTONEG_COMPLETE             0x20
+#define IXGBE_MII_AUTONEG_LINK_UP              0x04
+#define IXGBE_MII_AUTONEG_REG                  0x0
 
 /* Management */
 #define IXGBE_MAVTV(_i) (0x05010 + ((_i) * 4)) /* 8 of these (0-7) */
@@ -1305,6 +1324,7 @@ struct ixgbe_thermal_sensor_data {
 #define IXGBE_MDIO_AUTO_NEG_CONTROL    0x0 /* AUTO_NEG Control Reg */
 #define IXGBE_MDIO_AUTO_NEG_STATUS     0x1 /* AUTO_NEG Status Reg */
 #define IXGBE_MDIO_AUTO_NEG_VENDOR_STAT        0xC800 /* AUTO_NEG Vendor Status Reg */
+#define IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM  0xCC00 /* AUTO_NEG Vendor TX Reg */
 #define IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM2 0xCC01 /* AUTO_NEG Vendor Tx Reg */
 #define IXGBE_MDIO_AUTO_NEG_VEN_LSC    0x1 /* AUTO_NEG Vendor Tx LSC */
 #define IXGBE_MDIO_AUTO_NEG_ADVT       0x10 /* AUTO_NEG Advt Reg */
@@ -1312,7 +1332,8 @@ struct ixgbe_thermal_sensor_data {
 #define IXGBE_MDIO_AUTO_NEG_EEE_ADVT   0x3C /* AUTO_NEG EEE Advt Reg */
 
 #define IXGBE_MDIO_PHY_SET_LOW_POWER_MODE       0x0800 /* Set low power mode */
-
+#define IXGBE_AUTO_NEG_LP_STATUS       0xE820 /* AUTO NEG Rx LP Status Reg */
+#define IXGBE_AUTO_NEG_LP_1000BASE_CAP 0x8000 /* AUTO NEG Rx LP 1000BaseT */
 #define IXGBE_MDIO_TX_VENDOR_ALARMS_3  0xCC02 /* Vendor Alarms 3 Reg */
 #define IXGBE_MDIO_TX_VENDOR_ALARMS_3_RST_MASK 0x3 /* PHY Reset Complete Mask */
 #define IXGBE_MDIO_GLOBAL_RES_PR_10 0xC479 /* Global Resv Provisioning 10 Reg */
@@ -2041,6 +2062,11 @@ enum {
 #define IXGBE_NVM_POLL_WRITE       1  /* Flag for polling for write complete */
 #define IXGBE_NVM_POLL_READ        0  /* Flag for polling for read complete */
 
+#define NVM_INIT_CTRL_3                        0x38
+#define NVM_INIT_CTRL_3_LPLU           0x8
+#define NVM_INIT_CTRL_3_D10GMP_PORT0   0x40
+#define NVM_INIT_CTRL_3_D10GMP_PORT1   0x100
+
 #define IXGBE_EEPROM_PAGE_SIZE_MAX       128
 #define IXGBE_EEPROM_RD_BUFFER_MAX_COUNT 512 /* EEPROM words # read in burst */
 #define IXGBE_EEPROM_WR_BUFFER_MAX_COUNT 256 /* EEPROM words # wr in burst */
@@ -2540,9 +2566,11 @@ enum ixgbe_fdir_pballoc_type {
 #define IXGBE_FDIRCMD_QUEUE_EN                  0x00008000
 #define IXGBE_FDIRCMD_FLOW_TYPE_SHIFT           5
 #define IXGBE_FDIRCMD_RX_QUEUE_SHIFT            16
+#define IXGBE_FDIRCMD_RX_TUNNEL_FILTER_SHIFT   23
 #define IXGBE_FDIRCMD_VT_POOL_SHIFT             24
 #define IXGBE_FDIR_INIT_DONE_POLL               10
 #define IXGBE_FDIRCMD_CMD_POLL                  10
+#define IXGBE_FDIRCMD_TUNNEL_FILTER            0x00800000
 
 #define IXGBE_FDIR_DROP_QUEUE                   127
 
@@ -2833,12 +2861,13 @@ typedef u32 ixgbe_link_speed;
 #define IXGBE_ATR_SIGNATURE_HASH_KEY 0x174D3614
 
 /* Software ATR input stream values and masks */
-#define IXGBE_ATR_HASH_MASK     0x7fff
-#define IXGBE_ATR_L4TYPE_MASK      0x3
-#define IXGBE_ATR_L4TYPE_UDP       0x1
-#define IXGBE_ATR_L4TYPE_TCP       0x2
-#define IXGBE_ATR_L4TYPE_SCTP      0x3
-#define IXGBE_ATR_L4TYPE_IPV6_MASK 0x4
+#define IXGBE_ATR_HASH_MASK            0x7fff
+#define IXGBE_ATR_L4TYPE_MASK          0x3
+#define IXGBE_ATR_L4TYPE_UDP           0x1
+#define IXGBE_ATR_L4TYPE_TCP           0x2
+#define IXGBE_ATR_L4TYPE_SCTP          0x3
+#define IXGBE_ATR_L4TYPE_IPV6_MASK     0x4
+#define IXGBE_ATR_L4TYPE_TUNNEL_MASK   0x10
 enum ixgbe_atr_flow_type {
        IXGBE_ATR_FLOW_TYPE_IPV4   = 0x0,
        IXGBE_ATR_FLOW_TYPE_UDPV4  = 0x1,
@@ -3035,9 +3064,8 @@ enum ixgbe_smart_speed {
 /* PCI bus types */
 enum ixgbe_bus_type {
        ixgbe_bus_type_unknown = 0,
-       ixgbe_bus_type_pci,
-       ixgbe_bus_type_pcix,
        ixgbe_bus_type_pci_express,
+       ixgbe_bus_type_internal,
        ixgbe_bus_type_reserved
 };
 
@@ -3298,6 +3326,7 @@ struct ixgbe_phy_operations {
        s32 (*write_i2c_combined)(struct ixgbe_hw *, u8 addr, u16 reg, u16 val);
        s32 (*check_overtemp)(struct ixgbe_hw *);
        s32 (*set_phy_power)(struct ixgbe_hw *, bool on);
+       s32 (*enter_lplu)(struct ixgbe_hw *);
        s32 (*handle_lasi)(struct ixgbe_hw *hw);
 };
 
@@ -3308,6 +3337,7 @@ struct ixgbe_eeprom_info {
        u16                             word_size;
        u16                             address_bits;
        u16                             word_page_size;
+       u16                             ctrl_word_3;
 };
 
 #define IXGBE_FLAGS_DOUBLE_RESET_REQUIRED      0x01
@@ -3351,10 +3381,10 @@ struct ixgbe_phy_info {
        bool                            sfp_setup_needed;
        u32                             revision;
        enum ixgbe_media_type           media_type;
-       u8                              lan_id;
        u32                             phy_semaphore_mask;
        bool                            reset_disable;
        ixgbe_autoneg_advertised        autoneg_advertised;
+       ixgbe_link_speed                speeds_supported;
        enum ixgbe_smart_speed          smart_speed;
        bool                            smart_speed_active;
        bool                            multispeed_fiber;
@@ -3460,8 +3490,13 @@ struct ixgbe_info {
 #define IXGBE_ERR_PBA_SECTION                   -31
 #define IXGBE_ERR_INVALID_ARGUMENT              -32
 #define IXGBE_ERR_HOST_INTERFACE_COMMAND        -33
+#define IXGBE_ERR_FDIR_CMD_INCOMPLETE          -38
 #define IXGBE_NOT_IMPLEMENTED                   0x7FFFFFFF
 
+#define IXGBE_FUSES0_GROUP(_i)         (0x11158 + ((_i) * 4))
+#define IXGBE_FUSES0_300MHZ            BIT(5)
+#define IXGBE_FUSES0_REV1              BIT(6)
+
 #define IXGBE_KRM_PORT_CAR_GEN_CTRL(P) ((P) ? 0x8010 : 0x4010)
 #define IXGBE_KRM_LINK_CTRL_1(P)       ((P) ? 0x820C : 0x420C)
 #define IXGBE_KRM_DSP_TXFFE_STATE_4(P) ((P) ? 0x8634 : 0x4634)
index 032a587..4e75843 100644 (file)
@@ -54,6 +54,11 @@ enum ixgbe_media_type ixgbe_get_media_type_X540(struct ixgbe_hw *hw)
 s32 ixgbe_get_invariants_X540(struct ixgbe_hw *hw)
 {
        struct ixgbe_mac_info *mac = &hw->mac;
+       struct ixgbe_phy_info *phy = &hw->phy;
+
+       /* set_phy_power was set by default to NULL */
+       if (!ixgbe_mng_present(hw))
+               phy->ops.set_phy_power = ixgbe_set_copper_phy_power;
 
        mac->mcft_size = IXGBE_X540_MC_TBL_SIZE;
        mac->vft_size = IXGBE_X540_VFT_TBL_SIZE;
index 7581da1..9fe9445 100644 (file)
 #include "ixgbe_common.h"
 #include "ixgbe_phy.h"
 
+static s32 ixgbe_get_invariants_X550_x(struct ixgbe_hw *hw)
+{
+       struct ixgbe_mac_info *mac = &hw->mac;
+       struct ixgbe_phy_info *phy = &hw->phy;
+
+       /* Start with X540 invariants, since so simular */
+       ixgbe_get_invariants_X540(hw);
+
+       if (mac->ops.get_media_type(hw) != ixgbe_media_type_copper)
+               phy->ops.set_phy_power = NULL;
+
+       return 0;
+}
+
 /** ixgbe_setup_mux_ctl - Setup ESDP register for I2C mux control
  *  @hw: pointer to hardware structure
  **/
@@ -597,6 +611,24 @@ static s32 ixgbe_update_flash_X550(struct ixgbe_hw *hw)
        return status;
 }
 
+/**
+ * ixgbe_get_bus_info_X550em - Set PCI bus info
+ * @hw: pointer to hardware structure
+ *
+ * Sets bus link width and speed to unknown because X550em is
+ * not a PCI device.
+ **/
+static s32 ixgbe_get_bus_info_X550em(struct ixgbe_hw *hw)
+{
+       hw->bus.type  = ixgbe_bus_type_internal;
+       hw->bus.width = ixgbe_bus_width_unknown;
+       hw->bus.speed = ixgbe_bus_speed_unknown;
+
+       hw->mac.ops.set_lan_id(hw);
+
+       return 0;
+}
+
 /** ixgbe_disable_rx_x550 - Disable RX unit
  *
  *  Enables the Rx DMA unit for x550
@@ -1444,6 +1476,144 @@ static s32 ixgbe_reset_phy_t_X550em(struct ixgbe_hw *hw)
        return ixgbe_enable_lasi_ext_t_x550em(hw);
 }
 
+/** ixgbe_get_lcd_x550em - Determine lowest common denominator
+ *  @hw: pointer to hardware structure
+ *  @lcd_speed: pointer to lowest common link speed
+ *
+ *  Determine lowest common link speed with link partner.
+ **/
+static s32 ixgbe_get_lcd_t_x550em(struct ixgbe_hw *hw,
+                                 ixgbe_link_speed *lcd_speed)
+{
+       u16 an_lp_status;
+       s32 status;
+       u16 word = hw->eeprom.ctrl_word_3;
+
+       *lcd_speed = IXGBE_LINK_SPEED_UNKNOWN;
+
+       status = hw->phy.ops.read_reg(hw, IXGBE_AUTO_NEG_LP_STATUS,
+                                     IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+                                     &an_lp_status);
+       if (status)
+               return status;
+
+       /* If link partner advertised 1G, return 1G */
+       if (an_lp_status & IXGBE_AUTO_NEG_LP_1000BASE_CAP) {
+               *lcd_speed = IXGBE_LINK_SPEED_1GB_FULL;
+               return status;
+       }
+
+       /* If 10G disabled for LPLU via NVM D10GMP, then return no valid LCD */
+       if ((hw->bus.lan_id && (word & NVM_INIT_CTRL_3_D10GMP_PORT1)) ||
+           (word & NVM_INIT_CTRL_3_D10GMP_PORT0))
+               return status;
+
+       /* Link partner not capable of lower speeds, return 10G */
+       *lcd_speed = IXGBE_LINK_SPEED_10GB_FULL;
+       return status;
+}
+
+/** ixgbe_enter_lplu_x550em - 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). Link is required to enter LPLU so avoid resetting
+ *  the X557 PHY immediately prior to entering LPLU.
+ **/
+static s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw)
+{
+       u16 an_10g_cntl_reg, autoneg_reg, speed;
+       s32 status;
+       ixgbe_link_speed lcd_speed;
+       u32 save_autoneg;
+       bool link_up;
+
+       /* SW LPLU not required on later HW revisions. */
+       if (IXGBE_FUSES0_REV1 & IXGBE_READ_REG(hw, IXGBE_FUSES0_GROUP(0)))
+               return 0;
+
+       /* If blocked by MNG FW, then don't restart AN */
+       if (ixgbe_check_reset_blocked(hw))
+               return 0;
+
+       status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
+       if (status)
+               return status;
+
+       status = hw->eeprom.ops.read(hw, NVM_INIT_CTRL_3,
+                                    &hw->eeprom.ctrl_word_3);
+       if (status)
+               return status;
+
+       /* If link is down, LPLU disabled in NVM, WoL disabled, or
+        * manageability disabled, then force link down by entering
+        * low power mode.
+        */
+       if (!link_up || !(hw->eeprom.ctrl_word_3 & NVM_INIT_CTRL_3_LPLU) ||
+           !(hw->wol_enabled || ixgbe_mng_present(hw)))
+               return ixgbe_set_copper_phy_power(hw, false);
+
+       /* Determine LCD */
+       status = ixgbe_get_lcd_t_x550em(hw, &lcd_speed);
+       if (status)
+               return status;
+
+       /* If no valid LCD link speed, then force link down and exit. */
+       if (lcd_speed == IXGBE_LINK_SPEED_UNKNOWN)
+               return ixgbe_set_copper_phy_power(hw, false);
+
+       status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT,
+                                     IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+                                     &speed);
+       if (status)
+               return status;
+
+       /* If no link now, speed is invalid so take link down */
+       status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
+       if (status)
+               return ixgbe_set_copper_phy_power(hw, false);
+
+       /* clear everything but the speed bits */
+       speed &= IXGBE_MDIO_AUTO_NEG_VEN_STAT_SPEED_MASK;
+
+       /* If current speed is already LCD, then exit. */
+       if (((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB) &&
+            (lcd_speed == IXGBE_LINK_SPEED_1GB_FULL)) ||
+           ((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB) &&
+            (lcd_speed == IXGBE_LINK_SPEED_10GB_FULL)))
+               return status;
+
+       /* Clear AN completed indication */
+       status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM,
+                                     IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+                                     &autoneg_reg);
+       if (status)
+               return status;
+
+       status = hw->phy.ops.read_reg(hw, IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG,
+                                     IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+                                     &an_10g_cntl_reg);
+       if (status)
+               return status;
+
+       status = hw->phy.ops.read_reg(hw,
+                                     IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
+                                     IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+                                     &autoneg_reg);
+       if (status)
+               return status;
+
+       save_autoneg = hw->phy.autoneg_advertised;
+
+       /* Setup link at least common link speed */
+       status = hw->mac.ops.setup_link(hw, lcd_speed, false);
+
+       /* restore autoneg from before setting lplu speed */
+       hw->phy.autoneg_advertised = save_autoneg;
+
+       return status;
+}
+
 /** ixgbe_init_phy_ops_X550em - PHY/SFP specific init
  *  @hw: pointer to hardware structure
  *
@@ -1514,6 +1684,11 @@ static s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw)
                        ret_val = ixgbe_setup_kr_speed_x550em(hw, speed);
                }
 
+               /* setup SW LPLU only for first revision */
+               if (!(IXGBE_FUSES0_REV1 & IXGBE_READ_REG(hw,
+                                                       IXGBE_FUSES0_GROUP(0))))
+                       phy->ops.enter_lplu = ixgbe_enter_lplu_t_x550em;
+
                phy->ops.handle_lasi = ixgbe_handle_lasi_ext_t_x550em;
                phy->ops.reset = ixgbe_reset_phy_t_X550em;
                break;
@@ -1760,7 +1935,6 @@ static void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw,
        .get_mac_addr                   = &ixgbe_get_mac_addr_generic, \
        .get_device_caps                = &ixgbe_get_device_caps_generic, \
        .stop_adapter                   = &ixgbe_stop_adapter_generic, \
-       .get_bus_info                   = &ixgbe_get_bus_info_generic, \
        .set_lan_id                     = &ixgbe_set_lan_id_multi_port_pcie, \
        .read_analog_reg8               = NULL, \
        .write_analog_reg8              = NULL, \
@@ -1809,6 +1983,7 @@ static struct ixgbe_mac_operations mac_ops_X550 = {
        .get_wwn_prefix         = &ixgbe_get_wwn_prefix_generic,
        .setup_link             = &ixgbe_setup_mac_link_X540,
        .get_link_capabilities  = &ixgbe_get_copper_link_capabilities_generic,
+       .get_bus_info           = &ixgbe_get_bus_info_generic,
        .setup_sfp              = NULL,
 };
 
@@ -1820,6 +1995,7 @@ static struct ixgbe_mac_operations mac_ops_X550EM_x = {
        .get_wwn_prefix         = NULL,
        .setup_link             = NULL, /* defined later */
        .get_link_capabilities  = &ixgbe_get_link_capabilities_X550em,
+       .get_bus_info           = &ixgbe_get_bus_info_X550em,
        .setup_sfp              = ixgbe_setup_sfp_modules_X550em,
 
 };
@@ -1855,7 +2031,7 @@ static struct ixgbe_eeprom_operations eeprom_ops_X550EM_x = {
        .read_reg               = &ixgbe_read_phy_reg_generic, \
        .write_reg              = &ixgbe_write_phy_reg_generic, \
        .setup_link             = &ixgbe_setup_phy_link_generic, \
-       .set_phy_power          = &ixgbe_set_copper_phy_power, \
+       .set_phy_power          = NULL, \
        .check_overtemp         = &ixgbe_tn_check_overtemp, \
        .get_firmware_version   = &ixgbe_get_phy_firmware_version_generic,
 
@@ -1893,7 +2069,7 @@ struct ixgbe_info ixgbe_X550_info = {
 
 struct ixgbe_info ixgbe_X550EM_x_info = {
        .mac                    = ixgbe_mac_X550EM_x,
-       .get_invariants         = &ixgbe_get_invariants_X540,
+       .get_invariants         = &ixgbe_get_invariants_X550_x,
        .mac_ops                = &mac_ops_X550EM_x,
        .eeprom_ops             = &eeprom_ops_X550EM_x,
        .phy_ops                = &phy_ops_X550EM_x,