OSDN Git Service

ice: Add support for new PHY types
authorAnirudh Venkataramanan <anirudh.venkataramanan@intel.com>
Wed, 19 Dec 2018 18:03:33 +0000 (10:03 -0800)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Tue, 15 Jan 2019 20:38:44 +0000 (12:38 -0800)
This patch adds code for the detection and operation of several
additional PHY types that support higher link speeds.

Signed-off-by: Anirudh Venkataramanan <anirudh.venkataramanan@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
drivers/net/ethernet/intel/ice/ice_common.c
drivers/net/ethernet/intel/ice/ice_common.h
drivers/net/ethernet/intel/ice/ice_ethtool.c
drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h
drivers/net/ethernet/intel/ice/ice_sriov.c
drivers/net/ethernet/intel/ice/ice_type.h

index 526224e..242c784 100644 (file)
@@ -847,7 +847,42 @@ struct ice_aqc_get_phy_caps {
 #define ICE_PHY_TYPE_LOW_40GBASE_KR4           BIT_ULL(33)
 #define ICE_PHY_TYPE_LOW_40G_XLAUI_AOC_ACC     BIT_ULL(34)
 #define ICE_PHY_TYPE_LOW_40G_XLAUI             BIT_ULL(35)
+#define ICE_PHY_TYPE_LOW_50GBASE_CR2           BIT_ULL(36)
+#define ICE_PHY_TYPE_LOW_50GBASE_SR2           BIT_ULL(37)
+#define ICE_PHY_TYPE_LOW_50GBASE_LR2           BIT_ULL(38)
+#define ICE_PHY_TYPE_LOW_50GBASE_KR2           BIT_ULL(39)
+#define ICE_PHY_TYPE_LOW_50G_LAUI2_AOC_ACC     BIT_ULL(40)
+#define ICE_PHY_TYPE_LOW_50G_LAUI2             BIT_ULL(41)
+#define ICE_PHY_TYPE_LOW_50G_AUI2_AOC_ACC      BIT_ULL(42)
+#define ICE_PHY_TYPE_LOW_50G_AUI2              BIT_ULL(43)
+#define ICE_PHY_TYPE_LOW_50GBASE_CP            BIT_ULL(44)
+#define ICE_PHY_TYPE_LOW_50GBASE_SR            BIT_ULL(45)
+#define ICE_PHY_TYPE_LOW_50GBASE_FR            BIT_ULL(46)
+#define ICE_PHY_TYPE_LOW_50GBASE_LR            BIT_ULL(47)
+#define ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4       BIT_ULL(48)
+#define ICE_PHY_TYPE_LOW_50G_AUI1_AOC_ACC      BIT_ULL(49)
+#define ICE_PHY_TYPE_LOW_50G_AUI1              BIT_ULL(50)
+#define ICE_PHY_TYPE_LOW_100GBASE_CR4          BIT_ULL(51)
+#define ICE_PHY_TYPE_LOW_100GBASE_SR4          BIT_ULL(52)
+#define ICE_PHY_TYPE_LOW_100GBASE_LR4          BIT_ULL(53)
+#define ICE_PHY_TYPE_LOW_100GBASE_KR4          BIT_ULL(54)
+#define ICE_PHY_TYPE_LOW_100G_CAUI4_AOC_ACC    BIT_ULL(55)
+#define ICE_PHY_TYPE_LOW_100G_CAUI4            BIT_ULL(56)
+#define ICE_PHY_TYPE_LOW_100G_AUI4_AOC_ACC     BIT_ULL(57)
+#define ICE_PHY_TYPE_LOW_100G_AUI4             BIT_ULL(58)
+#define ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4      BIT_ULL(59)
+#define ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4      BIT_ULL(60)
+#define ICE_PHY_TYPE_LOW_100GBASE_CP2          BIT_ULL(61)
+#define ICE_PHY_TYPE_LOW_100GBASE_SR2          BIT_ULL(62)
+#define ICE_PHY_TYPE_LOW_100GBASE_DR           BIT_ULL(63)
 #define ICE_PHY_TYPE_LOW_MAX_INDEX             63
+/* The second set of defines is for phy_type_high. */
+#define ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4    BIT_ULL(0)
+#define ICE_PHY_TYPE_HIGH_100G_CAUI2_AOC_ACC   BIT_ULL(1)
+#define ICE_PHY_TYPE_HIGH_100G_CAUI2           BIT_ULL(2)
+#define ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC    BIT_ULL(3)
+#define ICE_PHY_TYPE_HIGH_100G_AUI2            BIT_ULL(4)
+#define ICE_PHY_TYPE_HIGH_MAX_INDEX            19
 
 struct ice_aqc_get_phy_caps_data {
        __le64 phy_type_low; /* Use values from ICE_PHY_TYPE_LOW_* */
@@ -1025,10 +1060,12 @@ struct ice_aqc_get_link_status_data {
 #define ICE_AQ_LINK_SPEED_20GB         BIT(6)
 #define ICE_AQ_LINK_SPEED_25GB         BIT(7)
 #define ICE_AQ_LINK_SPEED_40GB         BIT(8)
+#define ICE_AQ_LINK_SPEED_50GB         BIT(9)
+#define ICE_AQ_LINK_SPEED_100GB                BIT(10)
 #define ICE_AQ_LINK_SPEED_UNKNOWN      BIT(15)
        __le32 reserved3; /* Aligns next field to 8-byte boundary */
        __le64 phy_type_low; /* Use values from ICE_PHY_TYPE_LOW_* */
-       __le64 reserved4;
+       __le64 phy_type_high; /* Use values from ICE_PHY_TYPE_HIGH_* */
 };
 
 /* Set event mask command (direct 0x0613) */
index 1969574..ab308fc 100644 (file)
@@ -165,8 +165,10 @@ ice_aq_get_phy_caps(struct ice_port_info *pi, bool qual_mods, u8 report_mode,
        cmd->param0 |= cpu_to_le16(report_mode);
        status = ice_aq_send_cmd(pi->hw, &desc, pcaps, pcaps_size, cd);
 
-       if (!status && report_mode == ICE_AQC_REPORT_TOPO_CAP)
+       if (!status && report_mode == ICE_AQC_REPORT_TOPO_CAP) {
                pi->phy.phy_type_low = le64_to_cpu(pcaps->phy_type_low);
+               pi->phy.phy_type_high = le64_to_cpu(pcaps->phy_type_high);
+       }
 
        return status;
 }
@@ -183,6 +185,9 @@ static enum ice_media_type ice_get_media_type(struct ice_port_info *pi)
                return ICE_MEDIA_UNKNOWN;
 
        hw_link_info = &pi->phy.link_info;
+       if (hw_link_info->phy_type_low && hw_link_info->phy_type_high)
+               /* If more than one media type is selected, report unknown */
+               return ICE_MEDIA_UNKNOWN;
 
        if (hw_link_info->phy_type_low) {
                switch (hw_link_info->phy_type_low) {
@@ -196,6 +201,15 @@ static enum ice_media_type ice_get_media_type(struct ice_port_info *pi)
                case ICE_PHY_TYPE_LOW_25G_AUI_C2C:
                case ICE_PHY_TYPE_LOW_40GBASE_SR4:
                case ICE_PHY_TYPE_LOW_40GBASE_LR4:
+               case ICE_PHY_TYPE_LOW_50GBASE_SR2:
+               case ICE_PHY_TYPE_LOW_50GBASE_LR2:
+               case ICE_PHY_TYPE_LOW_50GBASE_SR:
+               case ICE_PHY_TYPE_LOW_50GBASE_FR:
+               case ICE_PHY_TYPE_LOW_50GBASE_LR:
+               case ICE_PHY_TYPE_LOW_100GBASE_SR4:
+               case ICE_PHY_TYPE_LOW_100GBASE_LR4:
+               case ICE_PHY_TYPE_LOW_100GBASE_SR2:
+               case ICE_PHY_TYPE_LOW_100GBASE_DR:
                        return ICE_MEDIA_FIBER;
                case ICE_PHY_TYPE_LOW_100BASE_TX:
                case ICE_PHY_TYPE_LOW_1000BASE_T:
@@ -209,6 +223,11 @@ static enum ice_media_type ice_get_media_type(struct ice_port_info *pi)
                case ICE_PHY_TYPE_LOW_25GBASE_CR_S:
                case ICE_PHY_TYPE_LOW_25GBASE_CR1:
                case ICE_PHY_TYPE_LOW_40GBASE_CR4:
+               case ICE_PHY_TYPE_LOW_50GBASE_CR2:
+               case ICE_PHY_TYPE_LOW_50GBASE_CP:
+               case ICE_PHY_TYPE_LOW_100GBASE_CR4:
+               case ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4:
+               case ICE_PHY_TYPE_LOW_100GBASE_CP2:
                        return ICE_MEDIA_DA;
                case ICE_PHY_TYPE_LOW_1000BASE_KX:
                case ICE_PHY_TYPE_LOW_2500BASE_KX:
@@ -219,10 +238,18 @@ static enum ice_media_type ice_get_media_type(struct ice_port_info *pi)
                case ICE_PHY_TYPE_LOW_25GBASE_KR1:
                case ICE_PHY_TYPE_LOW_25GBASE_KR_S:
                case ICE_PHY_TYPE_LOW_40GBASE_KR4:
+               case ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4:
+               case ICE_PHY_TYPE_LOW_50GBASE_KR2:
+               case ICE_PHY_TYPE_LOW_100GBASE_KR4:
+               case ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4:
+                       return ICE_MEDIA_BACKPLANE;
+               }
+       } else {
+               switch (hw_link_info->phy_type_high) {
+               case ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4:
                        return ICE_MEDIA_BACKPLANE;
                }
        }
-
        return ICE_MEDIA_UNKNOWN;
 }
 
@@ -274,6 +301,7 @@ ice_aq_get_link_info(struct ice_port_info *pi, bool ena_lse,
        /* update current link status information */
        hw_link_info->link_speed = le16_to_cpu(link_data.link_speed);
        hw_link_info->phy_type_low = le64_to_cpu(link_data.phy_type_low);
+       hw_link_info->phy_type_high = le64_to_cpu(link_data.phy_type_high);
        *hw_media_type = ice_get_media_type(pi);
        hw_link_info->link_info = link_data.link_info;
        hw_link_info->an_info = link_data.an_info;
@@ -1707,16 +1735,20 @@ void ice_clear_pxe_mode(struct ice_hw *hw)
 /**
  * ice_get_link_speed_based_on_phy_type - returns link speed
  * @phy_type_low: lower part of phy_type
+ * @phy_type_high: higher part of phy_type
  *
- * This helper function will convert a phy_type_low to its corresponding link
+ * This helper function will convert an entry in phy type structure
+ * [phy_type_low, phy_type_high] to its corresponding link speed.
+ * Note: In the structure of [phy_type_low, phy_type_high], there should
+ * be one bit set, as this function will convert one phy type to its
  * speed.
- * Note: In the structure of phy_type_low, there should be one bit set, as
- * this function will convert one phy type to its speed.
  * If no bit gets set, ICE_LINK_SPEED_UNKNOWN will be returned
  * If more than one bit gets set, ICE_LINK_SPEED_UNKNOWN will be returned
  */
-static u16 ice_get_link_speed_based_on_phy_type(u64 phy_type_low)
+static u16
+ice_get_link_speed_based_on_phy_type(u64 phy_type_low, u64 phy_type_high)
 {
+       u16 speed_phy_type_high = ICE_AQ_LINK_SPEED_UNKNOWN;
        u16 speed_phy_type_low = ICE_AQ_LINK_SPEED_UNKNOWN;
 
        switch (phy_type_low) {
@@ -1770,41 +1802,110 @@ static u16 ice_get_link_speed_based_on_phy_type(u64 phy_type_low)
        case ICE_PHY_TYPE_LOW_40G_XLAUI:
                speed_phy_type_low = ICE_AQ_LINK_SPEED_40GB;
                break;
+       case ICE_PHY_TYPE_LOW_50GBASE_CR2:
+       case ICE_PHY_TYPE_LOW_50GBASE_SR2:
+       case ICE_PHY_TYPE_LOW_50GBASE_LR2:
+       case ICE_PHY_TYPE_LOW_50GBASE_KR2:
+       case ICE_PHY_TYPE_LOW_50G_LAUI2_AOC_ACC:
+       case ICE_PHY_TYPE_LOW_50G_LAUI2:
+       case ICE_PHY_TYPE_LOW_50G_AUI2_AOC_ACC:
+       case ICE_PHY_TYPE_LOW_50G_AUI2:
+       case ICE_PHY_TYPE_LOW_50GBASE_CP:
+       case ICE_PHY_TYPE_LOW_50GBASE_SR:
+       case ICE_PHY_TYPE_LOW_50GBASE_FR:
+       case ICE_PHY_TYPE_LOW_50GBASE_LR:
+       case ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4:
+       case ICE_PHY_TYPE_LOW_50G_AUI1_AOC_ACC:
+       case ICE_PHY_TYPE_LOW_50G_AUI1:
+               speed_phy_type_low = ICE_AQ_LINK_SPEED_50GB;
+               break;
+       case ICE_PHY_TYPE_LOW_100GBASE_CR4:
+       case ICE_PHY_TYPE_LOW_100GBASE_SR4:
+       case ICE_PHY_TYPE_LOW_100GBASE_LR4:
+       case ICE_PHY_TYPE_LOW_100GBASE_KR4:
+       case ICE_PHY_TYPE_LOW_100G_CAUI4_AOC_ACC:
+       case ICE_PHY_TYPE_LOW_100G_CAUI4:
+       case ICE_PHY_TYPE_LOW_100G_AUI4_AOC_ACC:
+       case ICE_PHY_TYPE_LOW_100G_AUI4:
+       case ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4:
+       case ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4:
+       case ICE_PHY_TYPE_LOW_100GBASE_CP2:
+       case ICE_PHY_TYPE_LOW_100GBASE_SR2:
+       case ICE_PHY_TYPE_LOW_100GBASE_DR:
+               speed_phy_type_low = ICE_AQ_LINK_SPEED_100GB;
+               break;
        default:
                speed_phy_type_low = ICE_AQ_LINK_SPEED_UNKNOWN;
                break;
        }
 
-       return speed_phy_type_low;
+       switch (phy_type_high) {
+       case ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4:
+       case ICE_PHY_TYPE_HIGH_100G_CAUI2_AOC_ACC:
+       case ICE_PHY_TYPE_HIGH_100G_CAUI2:
+       case ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC:
+       case ICE_PHY_TYPE_HIGH_100G_AUI2:
+               speed_phy_type_high = ICE_AQ_LINK_SPEED_100GB;
+               break;
+       default:
+               speed_phy_type_high = ICE_AQ_LINK_SPEED_UNKNOWN;
+               break;
+       }
+
+       if (speed_phy_type_low == ICE_AQ_LINK_SPEED_UNKNOWN &&
+           speed_phy_type_high == ICE_AQ_LINK_SPEED_UNKNOWN)
+               return ICE_AQ_LINK_SPEED_UNKNOWN;
+       else if (speed_phy_type_low != ICE_AQ_LINK_SPEED_UNKNOWN &&
+                speed_phy_type_high != ICE_AQ_LINK_SPEED_UNKNOWN)
+               return ICE_AQ_LINK_SPEED_UNKNOWN;
+       else if (speed_phy_type_low != ICE_AQ_LINK_SPEED_UNKNOWN &&
+                speed_phy_type_high == ICE_AQ_LINK_SPEED_UNKNOWN)
+               return speed_phy_type_low;
+       else
+               return speed_phy_type_high;
 }
 
 /**
  * ice_update_phy_type
  * @phy_type_low: pointer to the lower part of phy_type
+ * @phy_type_high: pointer to the higher part of phy_type
  * @link_speeds_bitmap: targeted link speeds bitmap
  *
  * Note: For the link_speeds_bitmap structure, you can check it at
  * [ice_aqc_get_link_status->link_speed]. Caller can pass in
  * link_speeds_bitmap include multiple speeds.
  *
- * The value of phy_type_low will present a certain link speed. This helper
- * function will turn on bits in the phy_type_low based on the value of
+ * Each entry in this [phy_type_low, phy_type_high] structure will
+ * present a certain link speed. This helper function will turn on bits
+ * in [phy_type_low, phy_type_high] structure based on the value of
  * link_speeds_bitmap input parameter.
  */
-void ice_update_phy_type(u64 *phy_type_low, u16 link_speeds_bitmap)
+void
+ice_update_phy_type(u64 *phy_type_low, u64 *phy_type_high,
+                   u16 link_speeds_bitmap)
 {
        u16 speed = ICE_AQ_LINK_SPEED_UNKNOWN;
+       u64 pt_high;
        u64 pt_low;
        int index;
 
        /* We first check with low part of phy_type */
        for (index = 0; index <= ICE_PHY_TYPE_LOW_MAX_INDEX; index++) {
                pt_low = BIT_ULL(index);
-               speed = ice_get_link_speed_based_on_phy_type(pt_low);
+               speed = ice_get_link_speed_based_on_phy_type(pt_low, 0);
 
                if (link_speeds_bitmap & speed)
                        *phy_type_low |= BIT_ULL(index);
        }
+
+       /* We then check with high part of phy_type */
+       for (index = 0; index <= ICE_PHY_TYPE_HIGH_MAX_INDEX; index++) {
+               pt_high = BIT_ULL(index);
+               speed = ice_get_link_speed_based_on_phy_type(0, pt_high);
+
+               if (link_speeds_bitmap & speed)
+                       *phy_type_high |= BIT_ULL(index);
+       }
 }
 
 /**
@@ -1936,6 +2037,7 @@ ice_set_fc(struct ice_port_info *pi, u8 *aq_failures, bool ena_auto_link_update)
                if (ena_auto_link_update)
                        cfg.caps |= ICE_AQ_PHY_ENA_AUTO_LINK_UPDT;
                /* Copy over all the old settings */
+               cfg.phy_type_high = pcaps->phy_type_high;
                cfg.phy_type_low = pcaps->phy_type_low;
                cfg.low_power_ctrl = pcaps->low_power_ctrl;
                cfg.eee_cap = pcaps->eee_cap;
index 81c1bb7..17e2187 100644 (file)
@@ -72,7 +72,8 @@ ice_aq_get_phy_caps(struct ice_port_info *pi, bool qual_mods, u8 report_mode,
                    struct ice_aqc_get_phy_caps_data *caps,
                    struct ice_sq_cd *cd);
 void
-ice_update_phy_type(u64 *phy_type_low, u16 link_speeds_bitmap);
+ice_update_phy_type(u64 *phy_type_low, u64 *phy_type_high,
+                   u16 link_speeds_bitmap);
 enum ice_status
 ice_aq_manage_mac_write(struct ice_hw *hw, u8 *mac_addr, u8 flags,
                        struct ice_sq_cd *cd);
index 1f6a5f0..a82f020 100644 (file)
@@ -493,16 +493,20 @@ ice_get_ethtool_stats(struct net_device *netdev,
  * @netdev: network interface device structure
  * @ks: ethtool link ksettings struct to fill out
  */
-static void ice_phy_type_to_ethtool(struct net_device *netdev,
-                                   struct ethtool_link_ksettings *ks)
+static void
+ice_phy_type_to_ethtool(struct net_device *netdev,
+                       struct ethtool_link_ksettings *ks)
 {
        struct ice_netdev_priv *np = netdev_priv(netdev);
        struct ice_link_status *hw_link_info;
+       bool need_add_adv_mode = false;
        struct ice_vsi *vsi = np->vsi;
+       u64 phy_types_high;
        u64 phy_types_low;
 
        hw_link_info = &vsi->port_info->phy.link_info;
        phy_types_low = vsi->port_info->phy.phy_type_low;
+       phy_types_high = vsi->port_info->phy.phy_type_high;
 
        ethtool_link_ksettings_zero_link_mode(ks, supported);
        ethtool_link_ksettings_zero_link_mode(ks, advertising);
@@ -651,6 +655,95 @@ static void ice_phy_type_to_ethtool(struct net_device *netdev,
                        ethtool_link_ksettings_add_link_mode(ks, advertising,
                                                             40000baseLR4_Full);
        }
+       if (phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_CR2 ||
+           phy_types_low & ICE_PHY_TYPE_LOW_50G_LAUI2_AOC_ACC ||
+           phy_types_low & ICE_PHY_TYPE_LOW_50G_LAUI2 ||
+           phy_types_low & ICE_PHY_TYPE_LOW_50G_AUI2_AOC_ACC ||
+           phy_types_low & ICE_PHY_TYPE_LOW_50G_AUI2 ||
+           phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_CP ||
+           phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_SR ||
+           phy_types_low & ICE_PHY_TYPE_LOW_50G_AUI1_AOC_ACC ||
+           phy_types_low & ICE_PHY_TYPE_LOW_50G_AUI1) {
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    50000baseCR2_Full);
+               if (hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_50GB)
+                       ethtool_link_ksettings_add_link_mode(ks, advertising,
+                                                            50000baseCR2_Full);
+       }
+       if (phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_KR2 ||
+           phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4) {
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    50000baseKR2_Full);
+               if (hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_50GB)
+                       ethtool_link_ksettings_add_link_mode(ks, advertising,
+                                                            50000baseKR2_Full);
+       }
+       if (phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_SR2 ||
+           phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_LR2 ||
+           phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_FR ||
+           phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_LR) {
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    50000baseSR2_Full);
+               if (hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_50GB)
+                       ethtool_link_ksettings_add_link_mode(ks, advertising,
+                                                            50000baseSR2_Full);
+       }
+       if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CR4 ||
+           phy_types_low & ICE_PHY_TYPE_LOW_100G_CAUI4_AOC_ACC ||
+           phy_types_low & ICE_PHY_TYPE_LOW_100G_CAUI4 ||
+           phy_types_low & ICE_PHY_TYPE_LOW_100G_AUI4_AOC_ACC ||
+           phy_types_low & ICE_PHY_TYPE_LOW_100G_AUI4 ||
+           phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4 ||
+           phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CP2  ||
+           phy_types_high & ICE_PHY_TYPE_HIGH_100G_CAUI2_AOC_ACC ||
+           phy_types_high & ICE_PHY_TYPE_HIGH_100G_CAUI2 ||
+           phy_types_high & ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC ||
+           phy_types_high & ICE_PHY_TYPE_HIGH_100G_AUI2) {
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    100000baseCR4_Full);
+               if (hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_100GB)
+                       need_add_adv_mode = true;
+       }
+       if (need_add_adv_mode) {
+               need_add_adv_mode = false;
+               ethtool_link_ksettings_add_link_mode(ks, advertising,
+                                                    100000baseCR4_Full);
+       }
+       if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_SR4 ||
+           phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_SR2) {
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    100000baseSR4_Full);
+               if (hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_100GB)
+                       need_add_adv_mode = true;
+       }
+       if (need_add_adv_mode) {
+               need_add_adv_mode = false;
+               ethtool_link_ksettings_add_link_mode(ks, advertising,
+                                                    100000baseSR4_Full);
+       }
+       if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_LR4 ||
+           phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_DR) {
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    100000baseLR4_ER4_Full);
+               if (hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_100GB)
+                       need_add_adv_mode = true;
+       }
+       if (need_add_adv_mode) {
+               need_add_adv_mode = false;
+               ethtool_link_ksettings_add_link_mode(ks, advertising,
+                                                    100000baseLR4_ER4_Full);
+       }
+       if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_KR4 ||
+           phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4 ||
+           phy_types_high & ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4) {
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    100000baseKR4_Full);
+               if (hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_100GB)
+                       need_add_adv_mode = true;
+       }
+       if (need_add_adv_mode)
+               ethtool_link_ksettings_add_link_mode(ks, advertising,
+                                                    100000baseKR4_Full);
 
        /* Autoneg PHY types */
        if (phy_types_low & ICE_PHY_TYPE_LOW_100BASE_TX ||
@@ -676,6 +769,24 @@ static void ice_phy_type_to_ethtool(struct net_device *netdev,
                ethtool_link_ksettings_add_link_mode(ks, advertising,
                                                     Autoneg);
        }
+       if (phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_CR2 ||
+           phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_KR2 ||
+           phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_CP ||
+           phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4) {
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    Autoneg);
+               ethtool_link_ksettings_add_link_mode(ks, advertising,
+                                                    Autoneg);
+       }
+       if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CR4 ||
+           phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_KR4 ||
+           phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4 ||
+           phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CP2) {
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    Autoneg);
+               ethtool_link_ksettings_add_link_mode(ks, advertising,
+                                                    Autoneg);
+       }
 }
 
 #define TEST_SET_BITS_TIMEOUT  50
@@ -687,13 +798,15 @@ static void ice_phy_type_to_ethtool(struct net_device *netdev,
  * @ks: ethtool ksettings to fill in
  * @netdev: network interface device structure
  */
-static void ice_get_settings_link_up(struct ethtool_link_ksettings *ks,
-                                    struct net_device *netdev)
+static void
+ice_get_settings_link_up(struct ethtool_link_ksettings *ks,
+                        struct net_device *netdev)
 {
        struct ice_netdev_priv *np = netdev_priv(netdev);
        struct ethtool_link_ksettings cap_ksettings;
        struct ice_link_status *link_info;
        struct ice_vsi *vsi = np->vsi;
+       bool unrecog_phy_high = false;
        bool unrecog_phy_low = false;
 
        link_info = &vsi->port_info->phy.link_info;
@@ -855,14 +968,116 @@ static void ice_get_settings_link_up(struct ethtool_link_ksettings *ks,
                ethtool_link_ksettings_add_link_mode(ks, advertising,
                                                     40000baseKR4_Full);
                break;
+       case ICE_PHY_TYPE_LOW_50GBASE_CR2:
+       case ICE_PHY_TYPE_LOW_50GBASE_CP:
+               ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg);
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    50000baseCR2_Full);
+               ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg);
+               ethtool_link_ksettings_add_link_mode(ks, advertising,
+                                                    50000baseCR2_Full);
+               break;
+       case ICE_PHY_TYPE_LOW_50G_LAUI2_AOC_ACC:
+       case ICE_PHY_TYPE_LOW_50G_LAUI2:
+       case ICE_PHY_TYPE_LOW_50G_AUI2_AOC_ACC:
+       case ICE_PHY_TYPE_LOW_50G_AUI2:
+       case ICE_PHY_TYPE_LOW_50GBASE_SR:
+       case ICE_PHY_TYPE_LOW_50G_AUI1_AOC_ACC:
+       case ICE_PHY_TYPE_LOW_50G_AUI1:
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    50000baseCR2_Full);
+               break;
+       case ICE_PHY_TYPE_LOW_50GBASE_KR2:
+       case ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4:
+               ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg);
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    50000baseKR2_Full);
+               ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg);
+               ethtool_link_ksettings_add_link_mode(ks, advertising,
+                                                    50000baseKR2_Full);
+               break;
+       case ICE_PHY_TYPE_LOW_50GBASE_SR2:
+       case ICE_PHY_TYPE_LOW_50GBASE_LR2:
+       case ICE_PHY_TYPE_LOW_50GBASE_FR:
+       case ICE_PHY_TYPE_LOW_50GBASE_LR:
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    50000baseSR2_Full);
+               break;
+       case ICE_PHY_TYPE_LOW_100GBASE_CR4:
+               ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg);
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    100000baseCR4_Full);
+               ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg);
+               ethtool_link_ksettings_add_link_mode(ks, advertising,
+                                                    100000baseCR4_Full);
+               break;
+       case ICE_PHY_TYPE_LOW_100G_CAUI4_AOC_ACC:
+       case ICE_PHY_TYPE_LOW_100G_CAUI4:
+       case ICE_PHY_TYPE_LOW_100G_AUI4_AOC_ACC:
+       case ICE_PHY_TYPE_LOW_100G_AUI4:
+       case ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4:
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    100000baseCR4_Full);
+               break;
+       case ICE_PHY_TYPE_LOW_100GBASE_CP2:
+               ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg);
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    100000baseCR4_Full);
+               ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg);
+               ethtool_link_ksettings_add_link_mode(ks, advertising,
+                                                    100000baseCR4_Full);
+               break;
+       case ICE_PHY_TYPE_LOW_100GBASE_SR4:
+       case ICE_PHY_TYPE_LOW_100GBASE_SR2:
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    100000baseSR4_Full);
+               break;
+       case ICE_PHY_TYPE_LOW_100GBASE_LR4:
+       case ICE_PHY_TYPE_LOW_100GBASE_DR:
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    100000baseLR4_ER4_Full);
+               break;
+       case ICE_PHY_TYPE_LOW_100GBASE_KR4:
+       case ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4:
+               ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg);
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    100000baseKR4_Full);
+               ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg);
+               ethtool_link_ksettings_add_link_mode(ks, advertising,
+                                                    100000baseKR4_Full);
+               break;
        default:
                unrecog_phy_low = true;
        }
 
-       if (unrecog_phy_low) {
+       switch (link_info->phy_type_high) {
+       case ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4:
+               ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg);
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    100000baseKR4_Full);
+               ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg);
+               ethtool_link_ksettings_add_link_mode(ks, advertising,
+                                                    100000baseKR4_Full);
+               break;
+       case ICE_PHY_TYPE_HIGH_100G_CAUI2_AOC_ACC:
+       case ICE_PHY_TYPE_HIGH_100G_CAUI2:
+       case ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC:
+       case ICE_PHY_TYPE_HIGH_100G_AUI2:
+               ethtool_link_ksettings_add_link_mode(ks, supported,
+                                                    100000baseCR4_Full);
+               break;
+       default:
+               unrecog_phy_high = true;
+       }
+
+       if (unrecog_phy_low && unrecog_phy_high) {
                /* if we got here and link is up something bad is afoot */
-               netdev_info(netdev, "WARNING: Unrecognized PHY_Low (0x%llx).\n",
+               netdev_info(netdev,
+                           "WARNING: Unrecognized PHY_Low (0x%llx).\n",
                            (u64)link_info->phy_type_low);
+               netdev_info(netdev,
+                           "WARNING: Unrecognized PHY_High (0x%llx).\n",
+                           (u64)link_info->phy_type_high);
        }
 
        /* Now that we've worked out everything that could be supported by the
@@ -874,6 +1089,12 @@ static void ice_get_settings_link_up(struct ethtool_link_ksettings *ks,
        ethtool_intersect_link_masks(ks, &cap_ksettings);
 
        switch (link_info->link_speed) {
+       case ICE_AQ_LINK_SPEED_100GB:
+               ks->base.speed = SPEED_100000;
+               break;
+       case ICE_AQ_LINK_SPEED_50GB:
+               ks->base.speed = SPEED_50000;
+               break;
        case ICE_AQ_LINK_SPEED_40GB:
                ks->base.speed = SPEED_40000;
                break;
@@ -1067,6 +1288,23 @@ ice_ksettings_find_adv_link_speed(const struct ethtool_link_ksettings *ks)
            ethtool_link_ksettings_test_link_mode(ks, advertising,
                                                  40000baseKR4_Full))
                adv_link_speed |= ICE_AQ_LINK_SPEED_40GB;
+       if (ethtool_link_ksettings_test_link_mode(ks, advertising,
+                                                 50000baseCR2_Full) ||
+           ethtool_link_ksettings_test_link_mode(ks, advertising,
+                                                 50000baseKR2_Full))
+               adv_link_speed |= ICE_AQ_LINK_SPEED_50GB;
+       if (ethtool_link_ksettings_test_link_mode(ks, advertising,
+                                                 50000baseSR2_Full))
+               adv_link_speed |= ICE_AQ_LINK_SPEED_50GB;
+       if (ethtool_link_ksettings_test_link_mode(ks, advertising,
+                                                 100000baseCR4_Full) ||
+           ethtool_link_ksettings_test_link_mode(ks, advertising,
+                                                 100000baseSR4_Full) ||
+           ethtool_link_ksettings_test_link_mode(ks, advertising,
+                                                 100000baseLR4_ER4_Full) ||
+           ethtool_link_ksettings_test_link_mode(ks, advertising,
+                                                 100000baseKR4_Full))
+               adv_link_speed |= ICE_AQ_LINK_SPEED_100GB;
 
        return adv_link_speed;
 }
@@ -1137,8 +1375,9 @@ ice_setup_autoneg(struct ice_port_info *p, struct ethtool_link_ksettings *ks,
  *
  * Set speed/duplex per media_types advertised/forced
  */
-static int ice_set_link_ksettings(struct net_device *netdev,
-                                 const struct ethtool_link_ksettings *ks)
+static int
+ice_set_link_ksettings(struct net_device *netdev,
+                      const struct ethtool_link_ksettings *ks)
 {
        u8 autoneg, timeout = TEST_SET_BITS_TIMEOUT, lport = 0;
        struct ice_netdev_priv *np = netdev_priv(netdev);
@@ -1150,6 +1389,7 @@ static int ice_set_link_ksettings(struct net_device *netdev,
        struct ice_port_info *p;
        u8 autoneg_changed = 0;
        enum ice_status status;
+       u64 phy_type_high;
        u64 phy_type_low;
        int err = 0;
        bool linkup;
@@ -1265,7 +1505,7 @@ static int ice_set_link_ksettings(struct net_device *netdev,
                adv_link_speed = curr_link_speed;
 
        /* Convert the advertise link speeds to their corresponded PHY_TYPE */
-       ice_update_phy_type(&phy_type_low, adv_link_speed);
+       ice_update_phy_type(&phy_type_low, &phy_type_high, adv_link_speed);
 
        if (!autoneg_changed && adv_link_speed == curr_link_speed) {
                netdev_info(netdev, "Nothing changed, exiting without setting anything.\n");
@@ -1284,7 +1524,9 @@ static int ice_set_link_ksettings(struct net_device *netdev,
        /* set link and auto negotiation so changes take effect */
        config.caps |= ICE_AQ_PHY_ENA_LINK;
 
-       if (phy_type_low) {
+       if (phy_type_low || phy_type_high) {
+               config.phy_type_high = cpu_to_le64(phy_type_high) &
+                       abilities->phy_type_high;
                config.phy_type_low = cpu_to_le64(phy_type_low) &
                        abilities->phy_type_low;
        } else {
index bd7c01d..ef4c79b 100644 (file)
@@ -489,5 +489,7 @@ static inline struct ice_rx_ptype_decoded ice_decode_rx_desc_ptype(u16 ptype)
 #define ICE_LINK_SPEED_20000MBPS       20000
 #define ICE_LINK_SPEED_25000MBPS       25000
 #define ICE_LINK_SPEED_40000MBPS       40000
+#define ICE_LINK_SPEED_50000MBPS       50000
+#define ICE_LINK_SPEED_100000MBPS      100000
 
 #endif /* _ICE_LAN_TX_RX_H_ */
index 533b989..d2db0d0 100644 (file)
@@ -85,6 +85,12 @@ u32 ice_conv_link_speed_to_virtchnl(bool adv_link_support, u16 link_speed)
                case ICE_AQ_LINK_SPEED_40GB:
                        speed = ICE_LINK_SPEED_40000MBPS;
                        break;
+               case ICE_AQ_LINK_SPEED_50GB:
+                       speed = ICE_LINK_SPEED_50000MBPS;
+                       break;
+               case ICE_AQ_LINK_SPEED_100GB:
+                       speed = ICE_LINK_SPEED_100000MBPS;
+                       break;
                default:
                        speed = ICE_LINK_SPEED_UNKNOWN;
                        break;
@@ -116,6 +122,9 @@ u32 ice_conv_link_speed_to_virtchnl(bool adv_link_support, u16 link_speed)
                        break;
                case ICE_AQ_LINK_SPEED_40GB:
                        /* fall through */
+               case ICE_AQ_LINK_SPEED_50GB:
+                       /* fall through */
+               case ICE_AQ_LINK_SPEED_100GB:
                        speed = (u32)VIRTCHNL_LINK_SPEED_40GB;
                        break;
                default:
index a078e2c..17086d5 100644 (file)
@@ -90,6 +90,7 @@ enum ice_vsi_type {
 struct ice_link_status {
        /* Refer to ice_aq_phy_type for bits definition */
        u64 phy_type_low;
+       u64 phy_type_high;
        u16 max_frame_size;
        u16 link_speed;
        u16 req_speeds;
@@ -118,6 +119,7 @@ struct ice_phy_info {
        struct ice_link_status link_info;
        struct ice_link_status link_info_old;
        u64 phy_type_low;
+       u64 phy_type_high;
        enum ice_media_type media_type;
        u8 get_link_info;
 };