Skip to content

Commit

Permalink
ice: Add support for new PHY types
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Anirudh Venkataramanan authored and Jeff Kirsher committed Jan 15, 2019
1 parent cf909e1 commit aef7414
Show file tree
Hide file tree
Showing 7 changed files with 418 additions and 23 deletions.
39 changes: 38 additions & 1 deletion drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_* */
Expand Down Expand Up @@ -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) */
Expand Down
124 changes: 113 additions & 11 deletions drivers/net/ethernet/intel/ice/ice_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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) {
Expand All @@ -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:
Expand All @@ -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:
Expand All @@ -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;
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
}
}

/**
Expand Down Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion drivers/net/ethernet/intel/ice/ice_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Loading

0 comments on commit aef7414

Please sign in to comment.