Merge branch '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/next-queue

Tony Nguyen says:

====================
100GbE Intel Wired LAN Driver Updates 2020-07-23

This series contains updates to ice driver only.

Jake refactors ice_discover_caps() to reduce the number of AdminQ calls
made. Splits ice_parse_caps() to separate functions to update function
and device capabilities separately to allow for updating outside of
initialization.

Akeem adds power management support.

Paul G refactors FC and FEC code to aid in restoring of PHY settings
on media insertion. Implements lenient mode and link override support.
Adds link debug info and formats existing debug info to be more
readable. Adds support to check and report additional autoneg
capabilities. Implements the capability to detect media cage in order to
differentiate AUI types as Direct Attach or backplane.

Bruce implements Total Port Shutdown for devices that support it.

Lev renames low_power_ctrl field to lower_power_ctrl_an to be more
descriptive of the field.

Doug reports AOC types as media type fiber.

Paul S adds code to handle 1G SGMII PHY type.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2020-07-24 16:39:28 -07:00
commit aab99b62b4
13 changed files with 2342 additions and 667 deletions

View File

@ -222,6 +222,8 @@ enum ice_state {
__ICE_OICR_INTR_DIS, /* Global OICR interrupt disabled */
__ICE_MDD_VF_PRINT_PENDING, /* set when MDD event handle */
__ICE_VF_RESETS_DISABLED, /* disable resets during ice_remove */
__ICE_LINK_DEFAULT_OVERRIDE_PENDING,
__ICE_PHY_INIT_COMPLETE,
__ICE_STATE_NBITS /* must be last */
};
@ -357,12 +359,14 @@ enum ice_pf_flags {
ICE_FLAG_FD_ENA,
ICE_FLAG_ADV_FEATURES,
ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA,
ICE_FLAG_TOTAL_PORT_SHUTDOWN_ENA,
ICE_FLAG_NO_MEDIA,
ICE_FLAG_FW_LLDP_AGENT,
ICE_FLAG_ETHTOOL_CTXT, /* set when ethtool holds RTNL lock */
ICE_FLAG_LEGACY_RX,
ICE_FLAG_VF_TRUE_PROMISC_ENA,
ICE_FLAG_MDD_AUTO_RESET_VF,
ICE_FLAG_LINK_LENIENT_MODE_ENA,
ICE_PF_FLAGS_NBITS /* must be last */
};
@ -423,6 +427,8 @@ struct ice_pf {
u16 empr_count; /* EMP reset count */
u16 pfr_count; /* PF reset count */
u8 wol_ena : 1; /* software state of WoL */
u32 wakeup_reason; /* last wakeup reason */
struct ice_hw_port_stats stats;
struct ice_hw_port_stats stats_prev;
struct ice_hw hw;
@ -435,6 +441,10 @@ struct ice_pf {
u32 tx_timeout_recovery_level;
char int_name[ICE_INT_NAME_STR_LEN];
u32 sw_int_count;
__le64 nvm_phy_type_lo; /* NVM PHY type low */
__le64 nvm_phy_type_hi; /* NVM PHY type high */
struct ice_link_default_override_tlv link_dflt_override;
};
struct ice_netdev_priv {
@ -568,6 +578,7 @@ int ice_schedule_reset(struct ice_pf *pf, enum ice_reset_req reset);
void ice_print_link_msg(struct ice_vsi *vsi, bool isup);
const char *ice_stat_str(enum ice_status stat_err);
const char *ice_aq_str(enum ice_aq_err aq_err);
bool ice_is_wol_supported(struct ice_pf *pf);
int
ice_fdir_write_fltr(struct ice_pf *pf, struct ice_fdir_fltr *input, bool add,
bool is_tun);

View File

@ -961,8 +961,11 @@ struct ice_aqc_get_phy_caps_data {
#define ICE_AQC_GET_PHY_EN_MOD_QUAL BIT(5)
#define ICE_AQC_PHY_EN_AUTO_FEC BIT(7)
#define ICE_AQC_PHY_CAPS_MASK ICE_M(0xff, 0)
u8 low_power_ctrl;
u8 low_power_ctrl_an;
#define ICE_AQC_PHY_EN_D3COLD_LOW_POWER_AUTONEG BIT(0)
#define ICE_AQC_PHY_AN_EN_CLAUSE28 BIT(1)
#define ICE_AQC_PHY_AN_EN_CLAUSE73 BIT(2)
#define ICE_AQC_PHY_AN_EN_CLAUSE37 BIT(3)
__le16 eee_cap;
#define ICE_AQC_PHY_EEE_EN_100BASE_TX BIT(0)
#define ICE_AQC_PHY_EEE_EN_1000BASE_T BIT(1)
@ -983,12 +986,14 @@ struct ice_aqc_get_phy_caps_data {
#define ICE_AQC_PHY_FEC_25G_RS_CLAUSE91_EN BIT(6)
#define ICE_AQC_PHY_FEC_25G_KR_CLAUSE74_EN BIT(7)
#define ICE_AQC_PHY_FEC_MASK ICE_M(0xdf, 0)
u8 rsvd1; /* Byte 35 reserved */
u8 module_compliance_enforcement;
#define ICE_AQC_MOD_ENFORCE_STRICT_MODE BIT(0)
u8 extended_compliance_code;
#define ICE_MODULE_TYPE_TOTAL_BYTE 3
u8 module_type[ICE_MODULE_TYPE_TOTAL_BYTE];
#define ICE_AQC_MOD_TYPE_BYTE0_SFP_PLUS 0xA0
#define ICE_AQC_MOD_TYPE_BYTE0_QSFP_PLUS 0x80
#define ICE_AQC_MOD_TYPE_IDENT 1
#define ICE_AQC_MOD_TYPE_BYTE1_SFP_PLUS_CU_PASSIVE BIT(0)
#define ICE_AQC_MOD_TYPE_BYTE1_SFP_PLUS_CU_ACTIVE BIT(1)
#define ICE_AQC_MOD_TYPE_BYTE1_10G_BASE_SR BIT(4)
@ -1032,11 +1037,11 @@ struct ice_aqc_set_phy_cfg_data {
#define ICE_AQ_PHY_ENA_AUTO_LINK_UPDT BIT(5)
#define ICE_AQ_PHY_ENA_LESM BIT(6)
#define ICE_AQ_PHY_ENA_AUTO_FEC BIT(7)
u8 low_power_ctrl;
u8 low_power_ctrl_an;
__le16 eee_cap; /* Value from ice_aqc_get_phy_caps */
__le16 eeer_value;
u8 link_fec_opt; /* Use defines from ice_aqc_get_phy_caps */
u8 rsvd1;
u8 module_compliance_enforcement;
};
/* Set MAC Config command data structure (direct 0x0603) */
@ -1147,6 +1152,7 @@ struct ice_aqc_get_link_status_data {
#define ICE_AQ_LINK_PWR_QSFP_CLASS_3 2
#define ICE_AQ_LINK_PWR_QSFP_CLASS_4 3
__le16 link_speed;
#define ICE_AQ_LINK_SPEED_M 0x7FF
#define ICE_AQ_LINK_SPEED_10MB BIT(0)
#define ICE_AQ_LINK_SPEED_100MB BIT(1)
#define ICE_AQ_LINK_SPEED_1000MB BIT(2)
@ -1189,6 +1195,57 @@ struct ice_aqc_set_mac_lb {
u8 reserved[15];
};
struct ice_aqc_link_topo_addr {
u8 lport_num;
u8 lport_num_valid;
#define ICE_AQC_LINK_TOPO_PORT_NUM_VALID BIT(0)
u8 node_type_ctx;
#define ICE_AQC_LINK_TOPO_NODE_TYPE_S 0
#define ICE_AQC_LINK_TOPO_NODE_TYPE_M (0xF << ICE_AQC_LINK_TOPO_NODE_TYPE_S)
#define ICE_AQC_LINK_TOPO_NODE_TYPE_PHY 0
#define ICE_AQC_LINK_TOPO_NODE_TYPE_GPIO_CTRL 1
#define ICE_AQC_LINK_TOPO_NODE_TYPE_MUX_CTRL 2
#define ICE_AQC_LINK_TOPO_NODE_TYPE_LED_CTRL 3
#define ICE_AQC_LINK_TOPO_NODE_TYPE_LED 4
#define ICE_AQC_LINK_TOPO_NODE_TYPE_THERMAL 5
#define ICE_AQC_LINK_TOPO_NODE_TYPE_CAGE 6
#define ICE_AQC_LINK_TOPO_NODE_TYPE_MEZZ 7
#define ICE_AQC_LINK_TOPO_NODE_TYPE_ID_EEPROM 8
#define ICE_AQC_LINK_TOPO_NODE_CTX_S 4
#define ICE_AQC_LINK_TOPO_NODE_CTX_M \
(0xF << ICE_AQC_LINK_TOPO_NODE_CTX_S)
#define ICE_AQC_LINK_TOPO_NODE_CTX_GLOBAL 0
#define ICE_AQC_LINK_TOPO_NODE_CTX_BOARD 1
#define ICE_AQC_LINK_TOPO_NODE_CTX_PORT 2
#define ICE_AQC_LINK_TOPO_NODE_CTX_NODE 3
#define ICE_AQC_LINK_TOPO_NODE_CTX_PROVIDED 4
#define ICE_AQC_LINK_TOPO_NODE_CTX_OVERRIDE 5
u8 index;
__le16 handle;
#define ICE_AQC_LINK_TOPO_HANDLE_S 0
#define ICE_AQC_LINK_TOPO_HANDLE_M (0x3FF << ICE_AQC_LINK_TOPO_HANDLE_S)
/* Used to decode the handle field */
#define ICE_AQC_LINK_TOPO_HANDLE_BRD_TYPE_M BIT(9)
#define ICE_AQC_LINK_TOPO_HANDLE_BRD_TYPE_LOM BIT(9)
#define ICE_AQC_LINK_TOPO_HANDLE_BRD_TYPE_MEZZ 0
#define ICE_AQC_LINK_TOPO_HANDLE_NODE_S 0
/* In case of a Mezzanine type */
#define ICE_AQC_LINK_TOPO_HANDLE_MEZZ_NODE_M \
(0x3F << ICE_AQC_LINK_TOPO_HANDLE_NODE_S)
#define ICE_AQC_LINK_TOPO_HANDLE_MEZZ_S 6
#define ICE_AQC_LINK_TOPO_HANDLE_MEZZ_M (0x7 << ICE_AQC_LINK_TOPO_HANDLE_MEZZ_S)
/* In case of a LOM type */
#define ICE_AQC_LINK_TOPO_HANDLE_LOM_NODE_M \
(0x1FF << ICE_AQC_LINK_TOPO_HANDLE_NODE_S)
};
/* Get Link Topology Handle (direct, 0x06E0) */
struct ice_aqc_get_link_topo {
struct ice_aqc_link_topo_addr addr;
u8 node_part_num;
u8 rsvd[9];
};
/* Set Port Identification LED (direct, 0x06E9) */
struct ice_aqc_set_port_id_led {
u8 lport_num;
@ -1759,6 +1816,7 @@ struct ice_aq_desc {
struct ice_aqc_set_event_mask set_event_mask;
struct ice_aqc_get_link_status get_link_status;
struct ice_aqc_event_lan_overflow lan_overflow;
struct ice_aqc_get_link_topo get_link_topo;
} params;
};
@ -1858,6 +1916,7 @@ enum ice_adminq_opc {
ice_aqc_opc_get_link_status = 0x0607,
ice_aqc_opc_set_event_mask = 0x0613,
ice_aqc_opc_set_mac_lb = 0x0620,
ice_aqc_opc_get_link_topo = 0x06E0,
ice_aqc_opc_set_port_id_led = 0x06E9,
ice_aqc_opc_sff_eeprom = 0x06EE,

File diff suppressed because it is too large Load Diff

View File

@ -98,17 +98,33 @@ ice_aq_manage_mac_write(struct ice_hw *hw, const u8 *mac_addr, u8 flags,
struct ice_sq_cd *cd);
enum ice_status ice_clear_pf_cfg(struct ice_hw *hw);
enum ice_status
ice_aq_set_phy_cfg(struct ice_hw *hw, u8 lport,
ice_aq_set_phy_cfg(struct ice_hw *hw, struct ice_port_info *pi,
struct ice_aqc_set_phy_cfg_data *cfg, struct ice_sq_cd *cd);
bool ice_fw_supports_link_override(struct ice_hw *hw);
enum ice_status
ice_get_link_default_override(struct ice_link_default_override_tlv *ldo,
struct ice_port_info *pi);
bool ice_is_phy_caps_an_enabled(struct ice_aqc_get_phy_caps_data *caps);
enum ice_fc_mode ice_caps_to_fc_mode(u8 caps);
enum ice_fec_mode ice_caps_to_fec_mode(u8 caps, u8 fec_options);
enum ice_status
ice_set_fc(struct ice_port_info *pi, u8 *aq_failures,
bool ena_auto_link_update);
enum ice_status
ice_cfg_phy_fc(struct ice_port_info *pi, struct ice_aqc_set_phy_cfg_data *cfg,
enum ice_fc_mode fc);
bool
ice_phy_caps_equals_cfg(struct ice_aqc_get_phy_caps_data *caps,
struct ice_aqc_set_phy_cfg_data *cfg);
void
ice_cfg_phy_fec(struct ice_aqc_set_phy_cfg_data *cfg, enum ice_fec_mode fec);
void
ice_copy_phy_caps_to_cfg(struct ice_aqc_get_phy_caps_data *caps,
ice_copy_phy_caps_to_cfg(struct ice_port_info *pi,
struct ice_aqc_get_phy_caps_data *caps,
struct ice_aqc_set_phy_cfg_data *cfg);
enum ice_status
ice_cfg_phy_fec(struct ice_port_info *pi, struct ice_aqc_set_phy_cfg_data *cfg,
enum ice_fec_mode fec);
enum ice_status
ice_aq_set_link_restart_an(struct ice_port_info *pi, bool ena_link,
struct ice_sq_cd *cd);
enum ice_status

View File

@ -966,12 +966,8 @@ static int ice_set_fec_cfg(struct net_device *netdev, enum ice_fec_mode req_fec)
{
struct ice_netdev_priv *np = netdev_priv(netdev);
struct ice_aqc_set_phy_cfg_data config = { 0 };
struct ice_aqc_get_phy_caps_data *caps;
struct ice_vsi *vsi = np->vsi;
u8 sw_cfg_caps, sw_cfg_fec;
struct ice_port_info *pi;
enum ice_status status;
int err = 0;
pi = vsi->port_info;
if (!pi)
@ -983,54 +979,26 @@ static int ice_set_fec_cfg(struct net_device *netdev, enum ice_fec_mode req_fec)
return -EOPNOTSUPP;
}
/* Get last SW configuration */
caps = kzalloc(sizeof(*caps), GFP_KERNEL);
if (!caps)
return -ENOMEM;
/* Proceed only if requesting different FEC mode */
if (pi->phy.curr_user_fec_req == req_fec)
return 0;
status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_SW_CFG,
caps, NULL);
if (status) {
err = -EAGAIN;
goto done;
}
/* Copy the current user PHY configuration. The current user PHY
* configuration is initialized during probe from PHY capabilities
* software mode, and updated on set PHY configuration.
*/
memcpy(&config, &pi->phy.curr_user_phy_cfg, sizeof(config));
/* Copy SW configuration returned from PHY caps to PHY config */
ice_copy_phy_caps_to_cfg(caps, &config);
sw_cfg_caps = caps->caps;
sw_cfg_fec = caps->link_fec_options;
ice_cfg_phy_fec(pi, &config, req_fec);
config.caps |= ICE_AQ_PHY_ENA_AUTO_LINK_UPDT;
/* Get toloplogy caps, then copy PHY FEC topoloy caps to PHY config */
memset(caps, 0, sizeof(*caps));
if (ice_aq_set_phy_cfg(pi->hw, pi, &config, NULL))
return -EAGAIN;
status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_TOPO_CAP,
caps, NULL);
if (status) {
err = -EAGAIN;
goto done;
}
/* Save requested FEC config */
pi->phy.curr_user_fec_req = req_fec;
config.caps |= (caps->caps & ICE_AQC_PHY_EN_AUTO_FEC);
config.link_fec_opt = caps->link_fec_options;
ice_cfg_phy_fec(&config, req_fec);
/* If FEC mode has changed, then set PHY configuration and enable AN. */
if ((config.caps & ICE_AQ_PHY_ENA_AUTO_FEC) !=
(sw_cfg_caps & ICE_AQC_PHY_EN_AUTO_FEC) ||
config.link_fec_opt != sw_cfg_fec) {
if (caps->caps & ICE_AQC_PHY_AN_MODE)
config.caps |= ICE_AQ_PHY_ENA_AUTO_LINK_UPDT;
status = ice_aq_set_phy_cfg(pi->hw, pi->lport, &config, NULL);
if (status)
err = -EAGAIN;
}
done:
kfree(caps);
return err;
return 0;
}
/**
@ -1228,6 +1196,17 @@ static int ice_set_priv_flags(struct net_device *netdev, u32 flags)
bitmap_xor(change_flags, pf->flags, orig_flags, ICE_PF_FLAGS_NBITS);
/* Do not allow change to link-down-on-close when Total Port Shutdown
* is enabled.
*/
if (test_bit(ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA, change_flags) &&
test_bit(ICE_FLAG_TOTAL_PORT_SHUTDOWN_ENA, pf->flags)) {
dev_err(dev, "Setting link-down-on-close not supported on this port\n");
set_bit(ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA, pf->flags);
ret = -EINVAL;
goto ethtool_exit;
}
if (test_bit(ICE_FLAG_FW_LLDP_AGENT, change_flags)) {
if (!test_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags)) {
enum ice_status status;
@ -1315,6 +1294,7 @@ static int ice_set_priv_flags(struct net_device *netdev, u32 flags)
change_bit(ICE_FLAG_VF_TRUE_PROMISC_ENA, pf->flags);
ret = -EAGAIN;
}
ethtool_exit:
clear_bit(ICE_FLAG_ETHTOOL_CTXT, pf->flags);
return ret;
}
@ -1419,6 +1399,77 @@ ice_get_ethtool_stats(struct net_device *netdev,
}
}
#define ICE_PHY_TYPE_LOW_MASK_MIN_1G (ICE_PHY_TYPE_LOW_100BASE_TX | \
ICE_PHY_TYPE_LOW_100M_SGMII)
#define ICE_PHY_TYPE_LOW_MASK_MIN_25G (ICE_PHY_TYPE_LOW_MASK_MIN_1G | \
ICE_PHY_TYPE_LOW_1000BASE_T | \
ICE_PHY_TYPE_LOW_1000BASE_SX | \
ICE_PHY_TYPE_LOW_1000BASE_LX | \
ICE_PHY_TYPE_LOW_1000BASE_KX | \
ICE_PHY_TYPE_LOW_1G_SGMII | \
ICE_PHY_TYPE_LOW_2500BASE_T | \
ICE_PHY_TYPE_LOW_2500BASE_X | \
ICE_PHY_TYPE_LOW_2500BASE_KX | \
ICE_PHY_TYPE_LOW_5GBASE_T | \
ICE_PHY_TYPE_LOW_5GBASE_KR | \
ICE_PHY_TYPE_LOW_10GBASE_T | \
ICE_PHY_TYPE_LOW_10G_SFI_DA | \
ICE_PHY_TYPE_LOW_10GBASE_SR | \
ICE_PHY_TYPE_LOW_10GBASE_LR | \
ICE_PHY_TYPE_LOW_10GBASE_KR_CR1 | \
ICE_PHY_TYPE_LOW_10G_SFI_AOC_ACC | \
ICE_PHY_TYPE_LOW_10G_SFI_C2C)
#define ICE_PHY_TYPE_LOW_MASK_100G (ICE_PHY_TYPE_LOW_100GBASE_CR4 | \
ICE_PHY_TYPE_LOW_100GBASE_SR4 | \
ICE_PHY_TYPE_LOW_100GBASE_LR4 | \
ICE_PHY_TYPE_LOW_100GBASE_KR4 | \
ICE_PHY_TYPE_LOW_100G_CAUI4_AOC_ACC | \
ICE_PHY_TYPE_LOW_100G_CAUI4 | \
ICE_PHY_TYPE_LOW_100G_AUI4_AOC_ACC | \
ICE_PHY_TYPE_LOW_100G_AUI4 | \
ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4 | \
ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4 | \
ICE_PHY_TYPE_LOW_100GBASE_CP2 | \
ICE_PHY_TYPE_LOW_100GBASE_SR2 | \
ICE_PHY_TYPE_LOW_100GBASE_DR)
#define ICE_PHY_TYPE_HIGH_MASK_100G (ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4 | \
ICE_PHY_TYPE_HIGH_100G_CAUI2_AOC_ACC |\
ICE_PHY_TYPE_HIGH_100G_CAUI2 | \
ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC | \
ICE_PHY_TYPE_HIGH_100G_AUI2)
/**
* ice_mask_min_supported_speeds
* @phy_types_high: PHY type high
* @phy_types_low: PHY type low to apply minimum supported speeds mask
*
* Apply minimum supported speeds mask to PHY type low. These are the speeds
* for ethtool supported link mode.
*/
static
void ice_mask_min_supported_speeds(u64 phy_types_high, u64 *phy_types_low)
{
/* if QSFP connection with 100G speed, minimum supported speed is 25G */
if (*phy_types_low & ICE_PHY_TYPE_LOW_MASK_100G ||
phy_types_high & ICE_PHY_TYPE_HIGH_MASK_100G)
*phy_types_low &= ~ICE_PHY_TYPE_LOW_MASK_MIN_25G;
else
*phy_types_low &= ~ICE_PHY_TYPE_LOW_MASK_MIN_1G;
}
#define ice_ethtool_advertise_link_mode(aq_link_speed, ethtool_link_mode) \
do { \
if (req_speeds & (aq_link_speed) || \
(!req_speeds && \
(adv_phy_type_lo & phy_type_mask_lo || \
adv_phy_type_hi & phy_type_mask_hi))) \
ethtool_link_ksettings_add_link_mode(ks, advertising,\
ethtool_link_mode); \
} while (0)
/**
* ice_phy_type_to_ethtool - convert the phy_types to ethtool link modes
* @netdev: network interface device structure
@ -1429,277 +1480,312 @@ 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;
struct ice_pf *pf = vsi->back;
u64 phy_type_mask_lo = 0;
u64 phy_type_mask_hi = 0;
u64 adv_phy_type_lo = 0;
u64 adv_phy_type_hi = 0;
u64 phy_types_high = 0;
u64 phy_types_low = 0;
u16 req_speeds;
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;
req_speeds = vsi->port_info->phy.link_info.req_speeds;
/* Check if lenient mode is supported and enabled, or in strict mode.
*
* In lenient mode the Supported link modes are the PHY types without
* media. The Advertising link mode is either 1. the user requested
* speed, 2. the override PHY mask, or 3. the PHY types with media.
*
* In strict mode Supported link mode are the PHY type with media,
* and Advertising link modes are the media PHY type or the speed
* requested by user.
*/
if (test_bit(ICE_FLAG_LINK_LENIENT_MODE_ENA, pf->flags)) {
struct ice_link_default_override_tlv *ldo;
ldo = &pf->link_dflt_override;
phy_types_low = le64_to_cpu(pf->nvm_phy_type_lo);
phy_types_high = le64_to_cpu(pf->nvm_phy_type_hi);
ice_mask_min_supported_speeds(phy_types_high, &phy_types_low);
/* If override enabled and PHY mask set, then
* Advertising link mode is the intersection of the PHY
* types without media and the override PHY mask.
*/
if (ldo->options & ICE_LINK_OVERRIDE_EN &&
(ldo->phy_type_low || ldo->phy_type_high)) {
adv_phy_type_lo =
le64_to_cpu(pf->nvm_phy_type_lo) &
ldo->phy_type_low;
adv_phy_type_hi =
le64_to_cpu(pf->nvm_phy_type_hi) &
ldo->phy_type_high;
}
} else {
phy_types_low = vsi->port_info->phy.phy_type_low;
phy_types_high = vsi->port_info->phy.phy_type_high;
}
/* If Advertising link mode PHY type is not using override PHY type,
* then use PHY type with media.
*/
if (!adv_phy_type_lo && !adv_phy_type_hi) {
adv_phy_type_lo = vsi->port_info->phy.phy_type_low;
adv_phy_type_hi = vsi->port_info->phy.phy_type_high;
}
ethtool_link_ksettings_zero_link_mode(ks, supported);
ethtool_link_ksettings_zero_link_mode(ks, advertising);
if (phy_types_low & ICE_PHY_TYPE_LOW_100BASE_TX ||
phy_types_low & ICE_PHY_TYPE_LOW_100M_SGMII) {
phy_type_mask_lo = ICE_PHY_TYPE_LOW_100BASE_TX |
ICE_PHY_TYPE_LOW_100M_SGMII;
if (phy_types_low & phy_type_mask_lo) {
ethtool_link_ksettings_add_link_mode(ks, supported,
100baseT_Full);
if (!hw_link_info->req_speeds ||
hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_100MB)
ethtool_link_ksettings_add_link_mode(ks, advertising,
100baseT_Full);
ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_100MB,
100baseT_Full);
}
if (phy_types_low & ICE_PHY_TYPE_LOW_1000BASE_T ||
phy_types_low & ICE_PHY_TYPE_LOW_1G_SGMII) {
phy_type_mask_lo = ICE_PHY_TYPE_LOW_1000BASE_T |
ICE_PHY_TYPE_LOW_1G_SGMII;
if (phy_types_low & phy_type_mask_lo) {
ethtool_link_ksettings_add_link_mode(ks, supported,
1000baseT_Full);
if (!hw_link_info->req_speeds ||
hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_1000MB)
ethtool_link_ksettings_add_link_mode(ks, advertising,
1000baseT_Full);
ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_1000MB,
1000baseT_Full);
}
if (phy_types_low & ICE_PHY_TYPE_LOW_1000BASE_KX) {
phy_type_mask_lo = ICE_PHY_TYPE_LOW_1000BASE_KX;
if (phy_types_low & phy_type_mask_lo) {
ethtool_link_ksettings_add_link_mode(ks, supported,
1000baseKX_Full);
if (!hw_link_info->req_speeds ||
hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_1000MB)
ethtool_link_ksettings_add_link_mode(ks, advertising,
1000baseKX_Full);
ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_1000MB,
1000baseKX_Full);
}
if (phy_types_low & ICE_PHY_TYPE_LOW_1000BASE_SX ||
phy_types_low & ICE_PHY_TYPE_LOW_1000BASE_LX) {
phy_type_mask_lo = ICE_PHY_TYPE_LOW_1000BASE_SX |
ICE_PHY_TYPE_LOW_1000BASE_LX;
if (phy_types_low & phy_type_mask_lo) {
ethtool_link_ksettings_add_link_mode(ks, supported,
1000baseX_Full);
if (!hw_link_info->req_speeds ||
hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_1000MB)
ethtool_link_ksettings_add_link_mode(ks, advertising,
1000baseX_Full);
ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_1000MB,
1000baseX_Full);
}
if (phy_types_low & ICE_PHY_TYPE_LOW_2500BASE_T) {
phy_type_mask_lo = ICE_PHY_TYPE_LOW_2500BASE_T;
if (phy_types_low & phy_type_mask_lo) {
ethtool_link_ksettings_add_link_mode(ks, supported,
2500baseT_Full);
if (!hw_link_info->req_speeds ||
hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_2500MB)
ethtool_link_ksettings_add_link_mode(ks, advertising,
2500baseT_Full);
ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_2500MB,
2500baseT_Full);
}
if (phy_types_low & ICE_PHY_TYPE_LOW_2500BASE_X ||
phy_types_low & ICE_PHY_TYPE_LOW_2500BASE_KX) {
phy_type_mask_lo = ICE_PHY_TYPE_LOW_2500BASE_X |
ICE_PHY_TYPE_LOW_2500BASE_KX;
if (phy_types_low & phy_type_mask_lo) {
ethtool_link_ksettings_add_link_mode(ks, supported,
2500baseX_Full);
if (!hw_link_info->req_speeds ||
hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_2500MB)
ethtool_link_ksettings_add_link_mode(ks, advertising,
2500baseX_Full);
ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_2500MB,
2500baseX_Full);
}
if (phy_types_low & ICE_PHY_TYPE_LOW_5GBASE_T ||
phy_types_low & ICE_PHY_TYPE_LOW_5GBASE_KR) {
phy_type_mask_lo = ICE_PHY_TYPE_LOW_5GBASE_T |
ICE_PHY_TYPE_LOW_5GBASE_KR;
if (phy_types_low & phy_type_mask_lo) {
ethtool_link_ksettings_add_link_mode(ks, supported,
5000baseT_Full);
if (!hw_link_info->req_speeds ||
hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_5GB)
ethtool_link_ksettings_add_link_mode(ks, advertising,
5000baseT_Full);
ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_5GB,
5000baseT_Full);
}
if (phy_types_low & ICE_PHY_TYPE_LOW_10GBASE_T ||
phy_types_low & ICE_PHY_TYPE_LOW_10G_SFI_DA ||
phy_types_low & ICE_PHY_TYPE_LOW_10G_SFI_AOC_ACC ||
phy_types_low & ICE_PHY_TYPE_LOW_10G_SFI_C2C) {
phy_type_mask_lo = ICE_PHY_TYPE_LOW_10GBASE_T |
ICE_PHY_TYPE_LOW_10G_SFI_DA |
ICE_PHY_TYPE_LOW_10G_SFI_AOC_ACC |
ICE_PHY_TYPE_LOW_10G_SFI_C2C;
if (phy_types_low & phy_type_mask_lo) {
ethtool_link_ksettings_add_link_mode(ks, supported,
10000baseT_Full);
if (!hw_link_info->req_speeds ||
hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_10GB)
ethtool_link_ksettings_add_link_mode(ks, advertising,
10000baseT_Full);
ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_10GB,
10000baseT_Full);
}
if (phy_types_low & ICE_PHY_TYPE_LOW_10GBASE_KR_CR1) {
phy_type_mask_lo = ICE_PHY_TYPE_LOW_10GBASE_KR_CR1;
if (phy_types_low & phy_type_mask_lo) {
ethtool_link_ksettings_add_link_mode(ks, supported,
10000baseKR_Full);
if (!hw_link_info->req_speeds ||
hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_10GB)
ethtool_link_ksettings_add_link_mode(ks, advertising,
10000baseKR_Full);
ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_10GB,
10000baseKR_Full);
}
if (phy_types_low & ICE_PHY_TYPE_LOW_10GBASE_SR) {
phy_type_mask_lo = ICE_PHY_TYPE_LOW_10GBASE_SR;
if (phy_types_low & phy_type_mask_lo) {
ethtool_link_ksettings_add_link_mode(ks, supported,
10000baseSR_Full);
if (!hw_link_info->req_speeds ||
hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_10GB)
ethtool_link_ksettings_add_link_mode(ks, advertising,
10000baseSR_Full);
ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_10GB,
10000baseSR_Full);
}
if (phy_types_low & ICE_PHY_TYPE_LOW_10GBASE_LR) {
phy_type_mask_lo = ICE_PHY_TYPE_LOW_10GBASE_LR;
if (phy_types_low & phy_type_mask_lo) {
ethtool_link_ksettings_add_link_mode(ks, supported,
10000baseLR_Full);
if (!hw_link_info->req_speeds ||
hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_10GB)
ethtool_link_ksettings_add_link_mode(ks, advertising,
10000baseLR_Full);
ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_10GB,
10000baseLR_Full);
}
if (phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_T ||
phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_CR ||
phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_CR_S ||
phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_CR1 ||
phy_types_low & ICE_PHY_TYPE_LOW_25G_AUI_AOC_ACC ||
phy_types_low & ICE_PHY_TYPE_LOW_25G_AUI_C2C) {
phy_type_mask_lo = ICE_PHY_TYPE_LOW_25GBASE_T |
ICE_PHY_TYPE_LOW_25GBASE_CR |
ICE_PHY_TYPE_LOW_25GBASE_CR_S |
ICE_PHY_TYPE_LOW_25GBASE_CR1 |
ICE_PHY_TYPE_LOW_25G_AUI_AOC_ACC |
ICE_PHY_TYPE_LOW_25G_AUI_C2C;
if (phy_types_low & phy_type_mask_lo) {
ethtool_link_ksettings_add_link_mode(ks, supported,
25000baseCR_Full);
if (!hw_link_info->req_speeds ||
hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_25GB)
ethtool_link_ksettings_add_link_mode(ks, advertising,
25000baseCR_Full);
ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_25GB,
25000baseCR_Full);
}
if (phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_SR ||
phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_LR) {
phy_type_mask_lo = ICE_PHY_TYPE_LOW_25GBASE_SR |
ICE_PHY_TYPE_LOW_25GBASE_LR;
if (phy_types_low & phy_type_mask_lo) {
ethtool_link_ksettings_add_link_mode(ks, supported,
25000baseSR_Full);
if (!hw_link_info->req_speeds ||
hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_25GB)
ethtool_link_ksettings_add_link_mode(ks, advertising,
25000baseSR_Full);
ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_25GB,
25000baseSR_Full);
}
if (phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_KR ||
phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_KR_S ||
phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_KR1) {
phy_type_mask_lo = ICE_PHY_TYPE_LOW_25GBASE_KR |
ICE_PHY_TYPE_LOW_25GBASE_KR_S |
ICE_PHY_TYPE_LOW_25GBASE_KR1;
if (phy_types_low & phy_type_mask_lo) {
ethtool_link_ksettings_add_link_mode(ks, supported,
25000baseKR_Full);
if (!hw_link_info->req_speeds ||
hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_25GB)
ethtool_link_ksettings_add_link_mode(ks, advertising,
25000baseKR_Full);
ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_25GB,
25000baseKR_Full);
}
if (phy_types_low & ICE_PHY_TYPE_LOW_40GBASE_KR4) {
phy_type_mask_lo = ICE_PHY_TYPE_LOW_40GBASE_KR4;
if (phy_types_low & phy_type_mask_lo) {
ethtool_link_ksettings_add_link_mode(ks, supported,
40000baseKR4_Full);
if (!hw_link_info->req_speeds ||
hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_40GB)
ethtool_link_ksettings_add_link_mode(ks, advertising,
40000baseKR4_Full);
ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_40GB,
40000baseKR4_Full);
}
if (phy_types_low & ICE_PHY_TYPE_LOW_40GBASE_CR4 ||
phy_types_low & ICE_PHY_TYPE_LOW_40G_XLAUI_AOC_ACC ||
phy_types_low & ICE_PHY_TYPE_LOW_40G_XLAUI) {
phy_type_mask_lo = ICE_PHY_TYPE_LOW_40GBASE_CR4 |
ICE_PHY_TYPE_LOW_40G_XLAUI_AOC_ACC |
ICE_PHY_TYPE_LOW_40G_XLAUI;
if (phy_types_low & phy_type_mask_lo) {
ethtool_link_ksettings_add_link_mode(ks, supported,
40000baseCR4_Full);
if (!hw_link_info->req_speeds ||
hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_40GB)
ethtool_link_ksettings_add_link_mode(ks, advertising,
40000baseCR4_Full);
ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_40GB,
40000baseCR4_Full);
}
if (phy_types_low & ICE_PHY_TYPE_LOW_40GBASE_SR4) {
phy_type_mask_lo = ICE_PHY_TYPE_LOW_40GBASE_SR4;
if (phy_types_low & phy_type_mask_lo) {
ethtool_link_ksettings_add_link_mode(ks, supported,
40000baseSR4_Full);
if (!hw_link_info->req_speeds ||
hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_40GB)
ethtool_link_ksettings_add_link_mode(ks, advertising,
40000baseSR4_Full);
ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_40GB,
40000baseSR4_Full);
}
if (phy_types_low & ICE_PHY_TYPE_LOW_40GBASE_LR4) {
phy_type_mask_lo = ICE_PHY_TYPE_LOW_40GBASE_LR4;
if (phy_types_low & phy_type_mask_lo) {
ethtool_link_ksettings_add_link_mode(ks, supported,
40000baseLR4_Full);
if (!hw_link_info->req_speeds ||
hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_40GB)
ethtool_link_ksettings_add_link_mode(ks, advertising,
40000baseLR4_Full);
ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_40GB,
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) {
phy_type_mask_lo = ICE_PHY_TYPE_LOW_50GBASE_CR2 |
ICE_PHY_TYPE_LOW_50G_LAUI2_AOC_ACC |
ICE_PHY_TYPE_LOW_50G_LAUI2 |
ICE_PHY_TYPE_LOW_50G_AUI2_AOC_ACC |
ICE_PHY_TYPE_LOW_50G_AUI2 |
ICE_PHY_TYPE_LOW_50GBASE_CP |
ICE_PHY_TYPE_LOW_50GBASE_SR |
ICE_PHY_TYPE_LOW_50G_AUI1_AOC_ACC |
ICE_PHY_TYPE_LOW_50G_AUI1;
if (phy_types_low & phy_type_mask_lo) {
ethtool_link_ksettings_add_link_mode(ks, supported,
50000baseCR2_Full);
if (!hw_link_info->req_speeds ||
hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_50GB)
ethtool_link_ksettings_add_link_mode(ks, advertising,
50000baseCR2_Full);
ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_50GB,
50000baseCR2_Full);
}
if (phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_KR2 ||
phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4) {
phy_type_mask_lo = ICE_PHY_TYPE_LOW_50GBASE_KR2 |
ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4;
if (phy_types_low & phy_type_mask_lo) {
ethtool_link_ksettings_add_link_mode(ks, supported,
50000baseKR2_Full);
if (!hw_link_info->req_speeds ||
hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_50GB)
ethtool_link_ksettings_add_link_mode(ks, advertising,
50000baseKR2_Full);
ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_50GB,
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) {
phy_type_mask_lo = ICE_PHY_TYPE_LOW_50GBASE_SR2 |
ICE_PHY_TYPE_LOW_50GBASE_LR2 |
ICE_PHY_TYPE_LOW_50GBASE_FR |
ICE_PHY_TYPE_LOW_50GBASE_LR;
if (phy_types_low & phy_type_mask_lo) {
ethtool_link_ksettings_add_link_mode(ks, supported,
50000baseSR2_Full);
if (!hw_link_info->req_speeds ||
hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_50GB)
ethtool_link_ksettings_add_link_mode(ks, advertising,
50000baseSR2_Full);
ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_50GB,
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) {
phy_type_mask_lo = ICE_PHY_TYPE_LOW_100GBASE_CR4 |
ICE_PHY_TYPE_LOW_100G_CAUI4_AOC_ACC |
ICE_PHY_TYPE_LOW_100G_CAUI4 |
ICE_PHY_TYPE_LOW_100G_AUI4_AOC_ACC |
ICE_PHY_TYPE_LOW_100G_AUI4 |
ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4 |
ICE_PHY_TYPE_LOW_100GBASE_CP2;
phy_type_mask_hi = ICE_PHY_TYPE_HIGH_100G_CAUI2_AOC_ACC |
ICE_PHY_TYPE_HIGH_100G_CAUI2 |
ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC |
ICE_PHY_TYPE_HIGH_100G_AUI2;
if (phy_types_low & phy_type_mask_lo ||
phy_types_high & phy_type_mask_hi) {
ethtool_link_ksettings_add_link_mode(ks, supported,
100000baseCR4_Full);
if (!hw_link_info->req_speeds ||
hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_100GB)
need_add_adv_mode = true;
ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_100GB,
100000baseCR4_Full);
}
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) {
phy_type_mask_lo = ICE_PHY_TYPE_LOW_100GBASE_SR4 |
ICE_PHY_TYPE_LOW_100GBASE_SR2;
if (phy_types_low & phy_type_mask_lo) {
ethtool_link_ksettings_add_link_mode(ks, supported,
100000baseSR4_Full);
if (!hw_link_info->req_speeds ||
hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_100GB)
need_add_adv_mode = true;
ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_100GB,
100000baseSR4_Full);
}
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) {
phy_type_mask_lo = ICE_PHY_TYPE_LOW_100GBASE_LR4 |
ICE_PHY_TYPE_LOW_100GBASE_DR;
if (phy_types_low & phy_type_mask_lo) {
ethtool_link_ksettings_add_link_mode(ks, supported,
100000baseLR4_ER4_Full);
if (!hw_link_info->req_speeds ||
hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_100GB)
need_add_adv_mode = true;
ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_100GB,
100000baseLR4_ER4_Full);
}
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) {
phy_type_mask_lo = ICE_PHY_TYPE_LOW_100GBASE_KR4 |
ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4;
phy_type_mask_hi = ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4;
if (phy_types_low & phy_type_mask_lo ||
phy_types_high & phy_type_mask_hi) {
ethtool_link_ksettings_add_link_mode(ks, supported,
100000baseKR4_Full);
if (!hw_link_info->req_speeds ||
hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_100GB)
need_add_adv_mode = true;
ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_100GB,
100000baseKR4_Full);
}
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 ||
@ -2127,18 +2213,18 @@ 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);
struct ethtool_link_ksettings safe_ks, copy_ks;
struct ice_aqc_get_phy_caps_data *abilities;
u8 autoneg, timeout = TEST_SET_BITS_TIMEOUT;
u16 adv_link_speed, curr_link_speed, idx;
struct ice_aqc_set_phy_cfg_data config;
struct ice_pf *pf = np->vsi->back;
struct ice_port_info *p;
u8 autoneg_changed = 0;
enum ice_status status;
u64 phy_type_high;
u64 phy_type_low;
u64 phy_type_high = 0;
u64 phy_type_low = 0;
int err = 0;
bool linkup;
@ -2162,6 +2248,18 @@ ice_set_link_ksettings(struct net_device *netdev,
p->phy.link_info.link_info & ICE_AQ_LINK_UP)
return -EOPNOTSUPP;
abilities = kzalloc(sizeof(*abilities), GFP_KERNEL);
if (!abilities)
return -ENOMEM;
/* Get the PHY capabilities based on media */
status = ice_aq_get_phy_caps(p, false, ICE_AQC_REPORT_TOPO_CAP,
abilities, NULL);
if (status) {
err = -EAGAIN;
goto done;
}
/* copy the ksettings to copy_ks to avoid modifying the original */
memcpy(&copy_ks, ks, sizeof(copy_ks));
@ -2178,8 +2276,12 @@ ice_set_link_ksettings(struct net_device *netdev,
*/
if (!bitmap_subset(copy_ks.link_modes.advertising,
safe_ks.link_modes.supported,
__ETHTOOL_LINK_MODE_MASK_NBITS))
return -EINVAL;
__ETHTOOL_LINK_MODE_MASK_NBITS)) {
if (!test_bit(ICE_FLAG_LINK_LENIENT_MODE_ENA, pf->flags))
netdev_info(netdev, "The selected speed is not supported by the current media. Please select a link speed that is supported by the current media.\n");
err = -EINVAL;
goto done;
}
/* get our own copy of the bits to check against */
memset(&safe_ks, 0, sizeof(safe_ks));
@ -2196,33 +2298,27 @@ ice_set_link_ksettings(struct net_device *netdev,
/* If copy_ks.base and safe_ks.base are not the same now, then they are
* trying to set something that we do not support.
*/
if (memcmp(&copy_ks.base, &safe_ks.base, sizeof(copy_ks.base)))
return -EOPNOTSUPP;
while (test_and_set_bit(__ICE_CFG_BUSY, pf->state)) {
timeout--;
if (!timeout)
return -EBUSY;
usleep_range(TEST_SET_BITS_SLEEP_MIN, TEST_SET_BITS_SLEEP_MAX);
}
abilities = kzalloc(sizeof(*abilities), GFP_KERNEL);
if (!abilities)
return -ENOMEM;
/* Get the current PHY config */
status = ice_aq_get_phy_caps(p, false, ICE_AQC_REPORT_SW_CFG, abilities,
NULL);
if (status) {
err = -EAGAIN;
if (memcmp(&copy_ks.base, &safe_ks.base, sizeof(copy_ks.base))) {
err = -EOPNOTSUPP;
goto done;
}
/* Copy abilities to config in case autoneg is not set below */
memset(&config, 0, sizeof(config));
config.caps = abilities->caps & ~ICE_AQC_PHY_AN_MODE;
if (abilities->caps & ICE_AQC_PHY_AN_MODE)
config.caps |= ICE_AQ_PHY_ENA_AUTO_LINK_UPDT;
while (test_and_set_bit(__ICE_CFG_BUSY, pf->state)) {
timeout--;
if (!timeout) {
err = -EBUSY;
goto done;
}
usleep_range(TEST_SET_BITS_SLEEP_MIN, TEST_SET_BITS_SLEEP_MAX);
}
/* Copy the current user PHY configuration. The current user PHY
* configuration is initialized during probe from PHY capabilities
* software mode, and updated on set PHY configuration.
*/
memcpy(&config, &p->phy.curr_user_phy_cfg, sizeof(config));
config.caps |= ICE_AQ_PHY_ENA_AUTO_LINK_UPDT;
/* Check autoneg */
err = ice_setup_autoneg(p, &safe_ks, &config, autoneg, &autoneg_changed,
@ -2257,29 +2353,44 @@ ice_set_link_ksettings(struct net_device *netdev,
goto done;
}
/* copy over the rest of the abilities */
config.low_power_ctrl = abilities->low_power_ctrl;
config.eee_cap = abilities->eee_cap;
config.eeer_value = abilities->eeer_value;
config.link_fec_opt = abilities->link_fec_options;
/* save the requested speeds */
p->phy.link_info.req_speeds = adv_link_speed;
/* set link and auto negotiation so changes take effect */
config.caps |= ICE_AQ_PHY_ENA_LINK;
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 {
/* check if there is a PHY type for the requested advertised speed */
if (!(phy_type_low || phy_type_high)) {
netdev_info(netdev, "The selected speed is not supported by the current media. Please select a link speed that is supported by the current media.\n");
err = -EAGAIN;
netdev_info(netdev, "Nothing changed. No PHY_TYPE is corresponded to advertised link speed.\n");
goto done;
}
/* intersect requested advertised speed PHY types with media PHY types
* for set PHY configuration
*/
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;
if (!(config.phy_type_high || config.phy_type_low)) {
/* If there is no intersection and lenient mode is enabled, then
* intersect the requested advertised speed with NVM media type
* PHY types.
*/
if (test_bit(ICE_FLAG_LINK_LENIENT_MODE_ENA, pf->flags)) {
config.phy_type_high = cpu_to_le64(phy_type_high) &
pf->nvm_phy_type_hi;
config.phy_type_low = cpu_to_le64(phy_type_low) &
pf->nvm_phy_type_lo;
} else {
netdev_info(netdev, "The selected speed is not supported by the current media. Please select a link speed that is supported by the current media.\n");
err = -EAGAIN;
goto done;
}
}
/* If link is up put link down */
if (p->phy.link_info.link_info & ICE_AQ_LINK_UP) {
/* Tell the OS link is going down, the link will go
@ -2291,12 +2402,15 @@ ice_set_link_ksettings(struct net_device *netdev,
}
/* make the aq call */
status = ice_aq_set_phy_cfg(&pf->hw, lport, &config, NULL);
status = ice_aq_set_phy_cfg(&pf->hw, p, &config, NULL);
if (status) {
netdev_info(netdev, "Set phy config failed,\n");
err = -EAGAIN;
goto done;
}
/* Save speed request */
p->phy.curr_user_speed_req = adv_link_speed;
done:
kfree(abilities);
clear_bit(__ICE_CFG_BUSY, pf->state);
@ -2873,8 +2987,8 @@ ice_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause)
if (status)
goto out;
pause->autoneg = ((pcaps->caps & ICE_AQC_PHY_AN_MODE) ?
AUTONEG_ENABLE : AUTONEG_DISABLE);
pause->autoneg = ice_is_phy_caps_an_enabled(pcaps) ? AUTONEG_ENABLE :
AUTONEG_DISABLE;
if (dcbx_cfg->pfc.pfcena)
/* PFC enabled so report LFC as off */
@ -2942,8 +3056,8 @@ ice_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause)
return -EIO;
}
is_an = ((pcaps->caps & ICE_AQC_PHY_AN_MODE) ?
AUTONEG_ENABLE : AUTONEG_DISABLE);
is_an = ice_is_phy_caps_an_enabled(pcaps) ? AUTONEG_ENABLE :
AUTONEG_DISABLE;
kfree(pcaps);
@ -3322,6 +3436,58 @@ static int ice_set_channels(struct net_device *dev, struct ethtool_channels *ch)
return 0;
}
/**
* ice_get_wol - get current Wake on LAN configuration
* @netdev: network interface device structure
* @wol: Ethtool structure to retrieve WoL settings
*/
static void ice_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
{
struct ice_netdev_priv *np = netdev_priv(netdev);
struct ice_pf *pf = np->vsi->back;
if (np->vsi->type != ICE_VSI_PF)
netdev_warn(netdev, "Wake on LAN is not supported on this interface!\n");
/* Get WoL settings based on the HW capability */
if (ice_is_wol_supported(pf)) {
wol->supported = WAKE_MAGIC;
wol->wolopts = pf->wol_ena ? WAKE_MAGIC : 0;
} else {
wol->supported = 0;
wol->wolopts = 0;
}
}
/**
* ice_set_wol - set Wake on LAN on supported device
* @netdev: network interface device structure
* @wol: Ethtool structure to set WoL
*/
static int ice_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
{
struct ice_netdev_priv *np = netdev_priv(netdev);
struct ice_vsi *vsi = np->vsi;
struct ice_pf *pf = vsi->back;
if (vsi->type != ICE_VSI_PF || !ice_is_wol_supported(pf))
return -EOPNOTSUPP;
/* only magic packet is supported */
if (wol->wolopts && wol->wolopts != WAKE_MAGIC)
return -EOPNOTSUPP;
/* Set WoL only if there is a new value */
if (pf->wol_ena != !!wol->wolopts) {
pf->wol_ena = !!wol->wolopts;
device_set_wakeup_enable(ice_pf_to_dev(pf), pf->wol_ena);
netdev_dbg(netdev, "WoL magic packet %sabled\n",
pf->wol_ena ? "en" : "dis");
}
return 0;
}
enum ice_container_type {
ICE_RX_CONTAINER,
ICE_TX_CONTAINER,
@ -3805,6 +3971,8 @@ static const struct ethtool_ops ice_ethtool_ops = {
.get_drvinfo = ice_get_drvinfo,
.get_regs_len = ice_get_regs_len,
.get_regs = ice_get_regs,
.get_wol = ice_get_wol,
.set_wol = ice_set_wol,
.get_msglevel = ice_get_msglevel,
.set_msglevel = ice_set_msglevel,
.self_test = ice_self_test,
@ -3847,6 +4015,8 @@ static const struct ethtool_ops ice_ethtool_safe_mode_ops = {
.get_drvinfo = ice_get_drvinfo,
.get_regs_len = ice_get_regs_len,
.get_regs = ice_get_regs,
.get_wol = ice_get_wol,
.set_wol = ice_set_wol,
.get_msglevel = ice_get_msglevel,
.set_msglevel = ice_set_msglevel,
.get_link = ethtool_op_get_link,

View File

@ -367,6 +367,15 @@
#define VSIQF_FD_CNT_FD_GCNT_M ICE_M(0x3FFF, 0)
#define VSIQF_HKEY_MAX_INDEX 12
#define VSIQF_HLUT_MAX_INDEX 15
#define PFPM_APM 0x000B8080
#define PFPM_APM_APME_M BIT(0)
#define PFPM_WUFC 0x0009DC00
#define PFPM_WUFC_MAG_M BIT(1)
#define PFPM_WUS 0x0009DB80
#define PFPM_WUS_LNKC_M BIT(0)
#define PFPM_WUS_MAG_M BIT(1)
#define PFPM_WUS_MNG_M BIT(3)
#define PFPM_WUS_FW_RST_WK_M BIT(31)
#define VFINT_DYN_CTLN(_i) (0x00003800 + ((_i) * 4))
#define VFINT_DYN_CTLN_CLEARPBA_M BIT(1)
#define PRTRPB_RDPC 0x000AC260

View File

@ -1467,6 +1467,30 @@ static void ice_vsi_set_rss_flow_fld(struct ice_vsi *vsi)
vsi_num, ice_stat_str(status));
}
/**
* ice_pf_state_is_nominal - checks the PF for nominal state
* @pf: pointer to PF to check
*
* Check the PF's state for a collection of bits that would indicate
* the PF is in a state that would inhibit normal operation for
* driver functionality.
*
* Returns true if PF is in a nominal state, false otherwise
*/
bool ice_pf_state_is_nominal(struct ice_pf *pf)
{
DECLARE_BITMAP(check_bits, __ICE_STATE_NBITS) = { 0 };
if (!pf)
return false;
bitmap_set(check_bits, 0, __ICE_STATE_NOMINAL_CHECK_BITS);
if (bitmap_intersects(pf->state, check_bits, __ICE_STATE_NBITS))
return false;
return true;
}
/**
* ice_update_eth_stats - Update VSI-specific ethernet statistics counters
* @vsi: the VSI to be updated

View File

@ -8,6 +8,8 @@
const char *ice_vsi_type_str(enum ice_vsi_type vsi_type);
bool ice_pf_state_is_nominal(struct ice_pf *pf);
void ice_update_eth_stats(struct ice_vsi *vsi);
int ice_vsi_cfg_rxqs(struct ice_vsi *vsi);

View File

@ -612,6 +612,7 @@ static void ice_print_topo_conflict(struct ice_vsi *vsi)
void ice_print_link_msg(struct ice_vsi *vsi, bool isup)
{
struct ice_aqc_get_phy_caps_data *caps;
const char *an_advertised;
enum ice_status status;
const char *fec_req;
const char *speed;
@ -710,6 +711,7 @@ void ice_print_link_msg(struct ice_vsi *vsi, bool isup)
caps = kzalloc(sizeof(*caps), GFP_KERNEL);
if (!caps) {
fec_req = "Unknown";
an_advertised = "Unknown";
goto done;
}
@ -718,6 +720,8 @@ void ice_print_link_msg(struct ice_vsi *vsi, bool isup)
if (status)
netdev_info(vsi->netdev, "Get phy capability failed.\n");
an_advertised = ice_is_phy_caps_an_enabled(caps) ? "On" : "Off";
if (caps->link_fec_options & ICE_AQC_PHY_FEC_25G_RS_528_REQ ||
caps->link_fec_options & ICE_AQC_PHY_FEC_25G_RS_544_REQ)
fec_req = "RS-FEC";
@ -730,8 +734,8 @@ void ice_print_link_msg(struct ice_vsi *vsi, bool isup)
kfree(caps);
done:
netdev_info(vsi->netdev, "NIC Link is up %sbps Full Duplex, Requested FEC: %s, Negotiated FEC: %s, Autoneg: %s, Flow Control: %s\n",
speed, fec_req, fec, an, fc);
netdev_info(vsi->netdev, "NIC Link is up %sbps Full Duplex, Requested FEC: %s, Negotiated FEC: %s, Autoneg Advertised: %s, Autoneg Negotiated: %s, Flow Control: %s\n",
speed, fec_req, fec, an_advertised, an, fc);
ice_print_topo_conflict(vsi);
}
@ -796,10 +800,6 @@ ice_link_event(struct ice_pf *pf, struct ice_port_info *pi, bool link_up,
dev_dbg(dev, "Failed to update link status and re-enable link events for port %d\n",
pi->lport);
/* if the old link up/down and speed is the same as the new */
if (link_up == old_link && link_speed == old_link_speed)
return result;
vsi = ice_get_main_vsi(pf);
if (!vsi || !vsi->port_info)
return -EINVAL;
@ -817,6 +817,10 @@ ice_link_event(struct ice_pf *pf, struct ice_port_info *pi, bool link_up,
}
}
/* if the old link up/down and speed is the same as the new */
if (link_up == old_link && link_speed == old_link_speed)
return result;
ice_dcb_rebuild(pf);
ice_vsi_link_event(vsi, link_up);
ice_print_link_msg(vsi, link_up);
@ -1129,10 +1133,15 @@ static void ice_service_task_complete(struct ice_pf *pf)
/**
* ice_service_task_stop - stop service task and cancel works
* @pf: board private structure
*
* Return 0 if the __ICE_SERVICE_DIS bit was not already set,
* 1 otherwise.
*/
static void ice_service_task_stop(struct ice_pf *pf)
static int ice_service_task_stop(struct ice_pf *pf)
{
set_bit(__ICE_SERVICE_DIS, pf->state);
int ret;
ret = test_and_set_bit(__ICE_SERVICE_DIS, pf->state);
if (pf->serv_tmr.function)
del_timer_sync(&pf->serv_tmr);
@ -1140,6 +1149,7 @@ static void ice_service_task_stop(struct ice_pf *pf)
cancel_work_sync(&pf->serv_task);
clear_bit(__ICE_SERVICE_SCHED, pf->state);
return ret;
}
/**
@ -1374,25 +1384,23 @@ static int ice_force_phys_link_state(struct ice_vsi *vsi, bool link_up)
link_up == !!(pi->phy.link_info.link_info & ICE_AQ_LINK_UP))
goto out;
cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
/* Use the current user PHY configuration. The current user PHY
* configuration is initialized during probe from PHY capabilities
* software mode, and updated on set PHY configuration.
*/
cfg = kmemdup(&pi->phy.curr_user_phy_cfg, sizeof(*cfg), GFP_KERNEL);
if (!cfg) {
retcode = -ENOMEM;
goto out;
}
cfg->phy_type_low = pcaps->phy_type_low;
cfg->phy_type_high = pcaps->phy_type_high;
cfg->caps = pcaps->caps | ICE_AQ_PHY_ENA_AUTO_LINK_UPDT;
cfg->low_power_ctrl = pcaps->low_power_ctrl;
cfg->eee_cap = pcaps->eee_cap;
cfg->eeer_value = pcaps->eeer_value;
cfg->link_fec_opt = pcaps->link_fec_options;
cfg->caps |= ICE_AQ_PHY_ENA_AUTO_LINK_UPDT;
if (link_up)
cfg->caps |= ICE_AQ_PHY_ENA_LINK;
else
cfg->caps &= ~ICE_AQ_PHY_ENA_LINK;
retcode = ice_aq_set_phy_cfg(&vsi->back->hw, pi->lport, cfg, NULL);
retcode = ice_aq_set_phy_cfg(&vsi->back->hw, pi, cfg, NULL);
if (retcode) {
dev_err(dev, "Failed to set phy config, VSI %d error %d\n",
vsi->vsi_num, retcode);
@ -1406,8 +1414,312 @@ out:
}
/**
* ice_check_media_subtask - Check for media; bring link up if detected.
* ice_init_nvm_phy_type - Initialize the NVM PHY type
* @pi: port info structure
*
* Initialize nvm_phy_type_[low|high] for link lenient mode support
*/
static int ice_init_nvm_phy_type(struct ice_port_info *pi)
{
struct ice_aqc_get_phy_caps_data *pcaps;
struct ice_pf *pf = pi->hw->back;
enum ice_status status;
int err = 0;
pcaps = kzalloc(sizeof(*pcaps), GFP_KERNEL);
if (!pcaps)
return -ENOMEM;
status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_NVM_CAP, pcaps,
NULL);
if (status) {
dev_err(ice_pf_to_dev(pf), "Get PHY capability failed.\n");
err = -EIO;
goto out;
}
pf->nvm_phy_type_hi = pcaps->phy_type_high;
pf->nvm_phy_type_lo = pcaps->phy_type_low;
out:
kfree(pcaps);
return err;
}
/**
* ice_init_link_dflt_override - Initialize link default override
* @pi: port info structure
*
* Initialize link default override and PHY total port shutdown during probe
*/
static void ice_init_link_dflt_override(struct ice_port_info *pi)
{
struct ice_link_default_override_tlv *ldo;
struct ice_pf *pf = pi->hw->back;
ldo = &pf->link_dflt_override;
if (ice_get_link_default_override(ldo, pi))
return;
if (!(ldo->options & ICE_LINK_OVERRIDE_PORT_DIS))
return;
/* Enable Total Port Shutdown (override/replace link-down-on-close
* ethtool private flag) for ports with Port Disable bit set.
*/
set_bit(ICE_FLAG_TOTAL_PORT_SHUTDOWN_ENA, pf->flags);
set_bit(ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA, pf->flags);
}
/**
* ice_init_phy_cfg_dflt_override - Initialize PHY cfg default override settings
* @pi: port info structure
*
* If default override is enabled, initialized the user PHY cfg speed and FEC
* settings using the default override mask from the NVM.
*
* The PHY should only be configured with the default override settings the
* first time media is available. The __ICE_LINK_DEFAULT_OVERRIDE_PENDING state
* is used to indicate that the user PHY cfg default override is initialized
* and the PHY has not been configured with the default override settings. The
* state is set here, and cleared in ice_configure_phy the first time the PHY is
* configured.
*/
static void ice_init_phy_cfg_dflt_override(struct ice_port_info *pi)
{
struct ice_link_default_override_tlv *ldo;
struct ice_aqc_set_phy_cfg_data *cfg;
struct ice_phy_info *phy = &pi->phy;
struct ice_pf *pf = pi->hw->back;
ldo = &pf->link_dflt_override;
/* If link default override is enabled, use to mask NVM PHY capabilities
* for speed and FEC default configuration.
*/
cfg = &phy->curr_user_phy_cfg;
if (ldo->phy_type_low || ldo->phy_type_high) {
cfg->phy_type_low = pf->nvm_phy_type_lo &
cpu_to_le64(ldo->phy_type_low);
cfg->phy_type_high = pf->nvm_phy_type_hi &
cpu_to_le64(ldo->phy_type_high);
}
cfg->link_fec_opt = ldo->fec_options;
phy->curr_user_fec_req = ICE_FEC_AUTO;
set_bit(__ICE_LINK_DEFAULT_OVERRIDE_PENDING, pf->state);
}
/**
* ice_init_phy_user_cfg - Initialize the PHY user configuration
* @pi: port info structure
*
* Initialize the current user PHY configuration, speed, FEC, and FC requested
* mode to default. The PHY defaults are from get PHY capabilities topology
* with media so call when media is first available. An error is returned if
* called when media is not available. The PHY initialization completed state is
* set here.
*
* These configurations are used when setting PHY
* configuration. The user PHY configuration is updated on set PHY
* configuration. Returns 0 on success, negative on failure
*/
static int ice_init_phy_user_cfg(struct ice_port_info *pi)
{
struct ice_aqc_get_phy_caps_data *pcaps;
struct ice_phy_info *phy = &pi->phy;
struct ice_pf *pf = pi->hw->back;
enum ice_status status;
struct ice_vsi *vsi;
int err = 0;
if (!(phy->link_info.link_info & ICE_AQ_MEDIA_AVAILABLE))
return -EIO;
vsi = ice_get_main_vsi(pf);
if (!vsi)
return -EINVAL;
pcaps = kzalloc(sizeof(*pcaps), GFP_KERNEL);
if (!pcaps)
return -ENOMEM;
status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_TOPO_CAP, pcaps,
NULL);
if (status) {
dev_err(ice_pf_to_dev(pf), "Get PHY capability failed.\n");
err = -EIO;
goto err_out;
}
ice_copy_phy_caps_to_cfg(pi, pcaps, &pi->phy.curr_user_phy_cfg);
/* check if lenient mode is supported and enabled */
if (ice_fw_supports_link_override(&vsi->back->hw) &&
!(pcaps->module_compliance_enforcement &
ICE_AQC_MOD_ENFORCE_STRICT_MODE)) {
set_bit(ICE_FLAG_LINK_LENIENT_MODE_ENA, pf->flags);
/* if link default override is enabled, initialize user PHY
* configuration with link default override values
*/
if (pf->link_dflt_override.options & ICE_LINK_OVERRIDE_EN) {
ice_init_phy_cfg_dflt_override(pi);
goto out;
}
}
/* if link default override is not enabled, initialize PHY using
* topology with media
*/
phy->curr_user_fec_req = ice_caps_to_fec_mode(pcaps->caps,
pcaps->link_fec_options);
phy->curr_user_fc_req = ice_caps_to_fc_mode(pcaps->caps);
out:
phy->curr_user_speed_req = ICE_AQ_LINK_SPEED_M;
set_bit(__ICE_PHY_INIT_COMPLETE, pf->state);
err_out:
kfree(pcaps);
return err;
}
/**
* ice_configure_phy - configure PHY
* @vsi: VSI of PHY
*
* Set the PHY configuration. If the current PHY configuration is the same as
* the curr_user_phy_cfg, then do nothing to avoid link flap. Otherwise
* configure the based get PHY capabilities for topology with media.
*/
static int ice_configure_phy(struct ice_vsi *vsi)
{
struct device *dev = ice_pf_to_dev(vsi->back);
struct ice_aqc_get_phy_caps_data *pcaps;
struct ice_aqc_set_phy_cfg_data *cfg;
struct ice_port_info *pi;
enum ice_status status;
int err = 0;
pi = vsi->port_info;
if (!pi)
return -EINVAL;
/* Ensure we have media as we cannot configure a medialess port */
if (!(pi->phy.link_info.link_info & ICE_AQ_MEDIA_AVAILABLE))
return -EPERM;
ice_print_topo_conflict(vsi);
if (vsi->port_info->phy.link_info.topo_media_conflict ==
ICE_AQ_LINK_TOPO_UNSUPP_MEDIA)
return -EPERM;
if (test_bit(ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA, vsi->back->flags))
return ice_force_phys_link_state(vsi, true);
pcaps = kzalloc(sizeof(*pcaps), GFP_KERNEL);
if (!pcaps)
return -ENOMEM;
/* Get current PHY config */
status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_SW_CFG, pcaps,
NULL);
if (status) {
dev_err(dev, "Failed to get PHY configuration, VSI %d error %s\n",
vsi->vsi_num, ice_stat_str(status));
err = -EIO;
goto done;
}
/* If PHY enable link is configured and configuration has not changed,
* there's nothing to do
*/
if (pcaps->caps & ICE_AQC_PHY_EN_LINK &&
ice_phy_caps_equals_cfg(pcaps, &pi->phy.curr_user_phy_cfg))
goto done;
/* Use PHY topology as baseline for configuration */
memset(pcaps, 0, sizeof(*pcaps));
status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_TOPO_CAP, pcaps,
NULL);
if (status) {
dev_err(dev, "Failed to get PHY topology, VSI %d error %s\n",
vsi->vsi_num, ice_stat_str(status));
err = -EIO;
goto done;
}
cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
if (!cfg) {
err = -ENOMEM;
goto done;
}
ice_copy_phy_caps_to_cfg(pi, pcaps, cfg);
/* Speed - If default override pending, use curr_user_phy_cfg set in
* ice_init_phy_user_cfg_ldo.
*/
if (test_and_clear_bit(__ICE_LINK_DEFAULT_OVERRIDE_PENDING,
vsi->back->state)) {
cfg->phy_type_low = pi->phy.curr_user_phy_cfg.phy_type_low;
cfg->phy_type_high = pi->phy.curr_user_phy_cfg.phy_type_high;
} else {
u64 phy_low = 0, phy_high = 0;
ice_update_phy_type(&phy_low, &phy_high,
pi->phy.curr_user_speed_req);
cfg->phy_type_low = pcaps->phy_type_low & cpu_to_le64(phy_low);
cfg->phy_type_high = pcaps->phy_type_high &
cpu_to_le64(phy_high);
}
/* Can't provide what was requested; use PHY capabilities */
if (!cfg->phy_type_low && !cfg->phy_type_high) {
cfg->phy_type_low = pcaps->phy_type_low;
cfg->phy_type_high = pcaps->phy_type_high;
}
/* FEC */
ice_cfg_phy_fec(pi, cfg, pi->phy.curr_user_fec_req);
/* Can't provide what was requested; use PHY capabilities */
if (cfg->link_fec_opt !=
(cfg->link_fec_opt & pcaps->link_fec_options)) {
cfg->caps |= pcaps->caps & ICE_AQC_PHY_EN_AUTO_FEC;
cfg->link_fec_opt = pcaps->link_fec_options;
}
/* Flow Control - always supported; no need to check against
* capabilities
*/
ice_cfg_phy_fc(pi, cfg, pi->phy.curr_user_fc_req);
/* Enable link and link update */
cfg->caps |= ICE_AQ_PHY_ENA_AUTO_LINK_UPDT | ICE_AQ_PHY_ENA_LINK;
status = ice_aq_set_phy_cfg(&vsi->back->hw, pi, cfg, NULL);
if (status) {
dev_err(dev, "Failed to set phy config, VSI %d error %s\n",
vsi->vsi_num, ice_stat_str(status));
err = -EIO;
}
kfree(cfg);
done:
kfree(pcaps);
return err;
}
/**
* ice_check_media_subtask - Check for media
* @pf: pointer to PF struct
*
* If media is available, then initialize PHY user configuration if it is not
* been, and configure the PHY if the interface is up.
*/
static void ice_check_media_subtask(struct ice_pf *pf)
{
@ -1415,15 +1727,12 @@ static void ice_check_media_subtask(struct ice_pf *pf)
struct ice_vsi *vsi;
int err;
vsi = ice_get_main_vsi(pf);
if (!vsi)
/* No need to check for media if it's already present */
if (!test_bit(ICE_FLAG_NO_MEDIA, pf->flags))
return;
/* No need to check for media if it's already present or the interface
* is down
*/
if (!test_bit(ICE_FLAG_NO_MEDIA, pf->flags) ||
test_bit(__ICE_DOWN, vsi->state))
vsi = ice_get_main_vsi(pf);
if (!vsi)
return;
/* Refresh link info and check if media is present */
@ -1433,10 +1742,19 @@ static void ice_check_media_subtask(struct ice_pf *pf)
return;
if (pi->phy.link_info.link_info & ICE_AQ_MEDIA_AVAILABLE) {
err = ice_force_phys_link_state(vsi, true);
if (err)
if (!test_bit(__ICE_PHY_INIT_COMPLETE, pf->state))
ice_init_phy_user_cfg(pi);
/* PHY settings are reset on media insertion, reconfigure
* PHY to preserve settings.
*/
if (test_bit(__ICE_DOWN, vsi->state) &&
test_bit(ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA, vsi->back->flags))
return;
clear_bit(ICE_FLAG_NO_MEDIA, pf->flags);
err = ice_configure_phy(vsi);
if (!err)
clear_bit(ICE_FLAG_NO_MEDIA, pf->flags);
/* A Link Status Event will be generated; the event handler
* will complete bringing the interface up
@ -2940,6 +3258,27 @@ static int ice_init_interrupt_scheme(struct ice_pf *pf)
return 0;
}
/**
* ice_is_wol_supported - get NVM state of WoL
* @pf: board private structure
*
* Check if WoL is supported based on the HW configuration.
* Returns true if NVM supports and enables WoL for this port, false otherwise
*/
bool ice_is_wol_supported(struct ice_pf *pf)
{
struct ice_hw *hw = &pf->hw;
u16 wol_ctrl;
/* A bit set to 1 in the NVM Software Reserved Word 2 (WoL control
* word) indicates WoL is not supported on the corresponding PF ID.
*/
if (ice_read_sr_word(hw, ICE_SR_NVM_WOL_CFG, &wol_ctrl))
return false;
return !(BIT(hw->pf_id) & wol_ctrl);
}
/**
* ice_vsi_recfg_qs - Change the number of queues on a VSI
* @vsi: VSI being changed
@ -3287,6 +3626,33 @@ dflt_pkg_load:
release_firmware(firmware);
}
/**
* ice_print_wake_reason - show the wake up cause in the log
* @pf: pointer to the PF struct
*/
static void ice_print_wake_reason(struct ice_pf *pf)
{
u32 wus = pf->wakeup_reason;
const char *wake_str;
/* if no wake event, nothing to print */
if (!wus)
return;
if (wus & PFPM_WUS_LNKC_M)
wake_str = "Link\n";
else if (wus & PFPM_WUS_MAG_M)
wake_str = "Magic Packet\n";
else if (wus & PFPM_WUS_MNG_M)
wake_str = "Management\n";
else if (wus & PFPM_WUS_FW_RST_WK_M)
wake_str = "Firmware Reset\n";
else
wake_str = "Unknown\n";
dev_info(ice_pf_to_dev(pf), "Wake reason: %s", wake_str);
}
/**
* ice_probe - Device initialization routine
* @pdev: PCI device information struct
@ -3468,8 +3834,53 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent)
goto err_alloc_sw_unroll;
}
err = ice_init_nvm_phy_type(pf->hw.port_info);
if (err) {
dev_err(dev, "ice_init_nvm_phy_type failed: %d\n", err);
goto err_alloc_sw_unroll;
}
err = ice_update_link_info(pf->hw.port_info);
if (err) {
dev_err(dev, "ice_update_link_info failed: %d\n", err);
goto err_alloc_sw_unroll;
}
ice_init_link_dflt_override(pf->hw.port_info);
/* if media available, initialize PHY settings */
if (pf->hw.port_info->phy.link_info.link_info &
ICE_AQ_MEDIA_AVAILABLE) {
err = ice_init_phy_user_cfg(pf->hw.port_info);
if (err) {
dev_err(dev, "ice_init_phy_user_cfg failed: %d\n", err);
goto err_alloc_sw_unroll;
}
if (!test_bit(ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA, pf->flags)) {
struct ice_vsi *vsi = ice_get_main_vsi(pf);
if (vsi)
ice_configure_phy(vsi);
}
} else {
set_bit(ICE_FLAG_NO_MEDIA, pf->flags);
}
ice_verify_cacheline_size(pf);
/* Save wakeup reason register for later use */
pf->wakeup_reason = rd32(hw, PFPM_WUS);
/* check for a power management event */
ice_print_wake_reason(pf);
/* clear wake status, all bits */
wr32(hw, PFPM_WUS, U32_MAX);
/* Disable WoL at init, wait for user to enable */
device_set_wakeup_enable(dev, false);
/* If no DDP driven features have to be setup, we are done with probe */
if (ice_is_safe_mode(pf))
goto probe_done;
@ -3514,9 +3925,72 @@ err_init_pf_unroll:
err_exit_unroll:
ice_devlink_unregister(pf);
pci_disable_pcie_error_reporting(pdev);
pci_disable_device(pdev);
return err;
}
/**
* ice_set_wake - enable or disable Wake on LAN
* @pf: pointer to the PF struct
*
* Simple helper for WoL control
*/
static void ice_set_wake(struct ice_pf *pf)
{
struct ice_hw *hw = &pf->hw;
bool wol = pf->wol_ena;
/* clear wake state, otherwise new wake events won't fire */
wr32(hw, PFPM_WUS, U32_MAX);
/* enable / disable APM wake up, no RMW needed */
wr32(hw, PFPM_APM, wol ? PFPM_APM_APME_M : 0);
/* set magic packet filter enabled */
wr32(hw, PFPM_WUFC, wol ? PFPM_WUFC_MAG_M : 0);
}
/**
* ice_setup_magic_mc_wake - setup device to wake on multicast magic packet
* @pf: pointer to the PF struct
*
* Issue firmware command to enable multicast magic wake, making
* sure that any locally administered address (LAA) is used for
* wake, and that PF reset doesn't undo the LAA.
*/
static void ice_setup_mc_magic_wake(struct ice_pf *pf)
{
struct device *dev = ice_pf_to_dev(pf);
struct ice_hw *hw = &pf->hw;
enum ice_status status;
u8 mac_addr[ETH_ALEN];
struct ice_vsi *vsi;
u8 flags;
if (!pf->wol_ena)
return;
vsi = ice_get_main_vsi(pf);
if (!vsi)
return;
/* Get current MAC address in case it's an LAA */
if (vsi->netdev)
ether_addr_copy(mac_addr, vsi->netdev->dev_addr);
else
ether_addr_copy(mac_addr, vsi->port_info->mac.perm_addr);
flags = ICE_AQC_MAN_MAC_WR_MC_MAG_EN |
ICE_AQC_MAN_MAC_UPDATE_LAA_WOL |
ICE_AQC_MAN_MAC_WR_WOL_LAA_PFR_KEEP;
status = ice_aq_manage_mac_write(hw, mac_addr, flags, NULL);
if (status)
dev_err(dev, "Failed to enable Multicast Magic Packet wake, err %s aq_err %s\n",
ice_stat_str(status),
ice_aq_str(hw->adminq.sq_last_status));
}
/**
* ice_remove - Device removal routine
* @pdev: PCI device information struct
@ -3546,8 +4020,10 @@ static void ice_remove(struct pci_dev *pdev)
mutex_destroy(&(&pf->hw)->fdir_fltr_lock);
if (!ice_is_safe_mode(pf))
ice_remove_arfs(pf);
ice_setup_mc_magic_wake(pf);
ice_devlink_destroy_port(pf);
ice_vsi_release_all(pf);
ice_set_wake(pf);
ice_free_irq_msix_misc(pf);
ice_for_each_vsi(pf, i) {
if (!pf->vsi[i])
@ -3567,8 +4043,230 @@ static void ice_remove(struct pci_dev *pdev)
pci_wait_for_pending_transaction(pdev);
ice_clear_interrupt_scheme(pf);
pci_disable_pcie_error_reporting(pdev);
pci_disable_device(pdev);
}
/**
* ice_shutdown - PCI callback for shutting down device
* @pdev: PCI device information struct
*/
static void ice_shutdown(struct pci_dev *pdev)
{
struct ice_pf *pf = pci_get_drvdata(pdev);
ice_remove(pdev);
if (system_state == SYSTEM_POWER_OFF) {
pci_wake_from_d3(pdev, pf->wol_ena);
pci_set_power_state(pdev, PCI_D3hot);
}
}
#ifdef CONFIG_PM
/**
* ice_prepare_for_shutdown - prep for PCI shutdown
* @pf: board private structure
*
* Inform or close all dependent features in prep for PCI device shutdown
*/
static void ice_prepare_for_shutdown(struct ice_pf *pf)
{
struct ice_hw *hw = &pf->hw;
u32 v;
/* Notify VFs of impending reset */
if (ice_check_sq_alive(hw, &hw->mailboxq))
ice_vc_notify_reset(pf);
dev_dbg(ice_pf_to_dev(pf), "Tearing down internal switch for shutdown\n");
/* disable the VSIs and their queues that are not already DOWN */
ice_pf_dis_all_vsi(pf, false);
ice_for_each_vsi(pf, v)
if (pf->vsi[v])
pf->vsi[v]->vsi_num = 0;
ice_shutdown_all_ctrlq(hw);
}
/**
* ice_reinit_interrupt_scheme - Reinitialize interrupt scheme
* @pf: board private structure to reinitialize
*
* This routine reinitialize interrupt scheme that was cleared during
* power management suspend callback.
*
* This should be called during resume routine to re-allocate the q_vectors
* and reacquire interrupts.
*/
static int ice_reinit_interrupt_scheme(struct ice_pf *pf)
{
struct device *dev = ice_pf_to_dev(pf);
int ret, v;
/* Since we clear MSIX flag during suspend, we need to
* set it back during resume...
*/
ret = ice_init_interrupt_scheme(pf);
if (ret) {
dev_err(dev, "Failed to re-initialize interrupt %d\n", ret);
return ret;
}
/* Remap vectors and rings, after successful re-init interrupts */
ice_for_each_vsi(pf, v) {
if (!pf->vsi[v])
continue;
ret = ice_vsi_alloc_q_vectors(pf->vsi[v]);
if (ret)
goto err_reinit;
ice_vsi_map_rings_to_vectors(pf->vsi[v]);
}
ret = ice_req_irq_msix_misc(pf);
if (ret) {
dev_err(dev, "Setting up misc vector failed after device suspend %d\n",
ret);
goto err_reinit;
}
return 0;
err_reinit:
while (v--)
if (pf->vsi[v])
ice_vsi_free_q_vectors(pf->vsi[v]);
return ret;
}
/**
* ice_suspend
* @dev: generic device information structure
*
* Power Management callback to quiesce the device and prepare
* for D3 transition.
*/
static int ice_suspend(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct ice_pf *pf;
int disabled, v;
pf = pci_get_drvdata(pdev);
if (!ice_pf_state_is_nominal(pf)) {
dev_err(dev, "Device is not ready, no need to suspend it\n");
return -EBUSY;
}
/* Stop watchdog tasks until resume completion.
* Even though it is most likely that the service task is
* disabled if the device is suspended or down, the service task's
* state is controlled by a different state bit, and we should
* store and honor whatever state that bit is in at this point.
*/
disabled = ice_service_task_stop(pf);
/* Already suspended?, then there is nothing to do */
if (test_and_set_bit(__ICE_SUSPENDED, pf->state)) {
if (!disabled)
ice_service_task_restart(pf);
return 0;
}
if (test_bit(__ICE_DOWN, pf->state) ||
ice_is_reset_in_progress(pf->state)) {
dev_err(dev, "can't suspend device in reset or already down\n");
if (!disabled)
ice_service_task_restart(pf);
return 0;
}
ice_setup_mc_magic_wake(pf);
ice_prepare_for_shutdown(pf);
ice_set_wake(pf);
/* Free vectors, clear the interrupt scheme and release IRQs
* for proper hibernation, especially with large number of CPUs.
* Otherwise hibernation might fail when mapping all the vectors back
* to CPU0.
*/
ice_free_irq_msix_misc(pf);
ice_for_each_vsi(pf, v) {
if (!pf->vsi[v])
continue;
ice_vsi_free_q_vectors(pf->vsi[v]);
}
ice_clear_interrupt_scheme(pf);
pci_wake_from_d3(pdev, pf->wol_ena);
pci_set_power_state(pdev, PCI_D3hot);
return 0;
}
/**
* ice_resume - PM callback for waking up from D3
* @dev: generic device information structure
*/
static int ice_resume(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
enum ice_reset_req reset_type;
struct ice_pf *pf;
struct ice_hw *hw;
int ret;
pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
pci_save_state(pdev);
if (!pci_device_is_present(pdev))
return -ENODEV;
ret = pci_enable_device_mem(pdev);
if (ret) {
dev_err(dev, "Cannot enable device after suspend\n");
return ret;
}
pf = pci_get_drvdata(pdev);
hw = &pf->hw;
pf->wakeup_reason = rd32(hw, PFPM_WUS);
ice_print_wake_reason(pf);
/* We cleared the interrupt scheme when we suspended, so we need to
* restore it now to resume device functionality.
*/
ret = ice_reinit_interrupt_scheme(pf);
if (ret)
dev_err(dev, "Cannot restore interrupt scheme: %d\n", ret);
clear_bit(__ICE_DOWN, pf->state);
/* Now perform PF reset and rebuild */
reset_type = ICE_RESET_PFR;
/* re-enable service task for reset, but allow reset to schedule it */
clear_bit(__ICE_SERVICE_DIS, pf->state);
if (ice_schedule_reset(pf, reset_type))
dev_err(dev, "Reset during resume failed.\n");
clear_bit(__ICE_SUSPENDED, pf->state);
ice_service_task_restart(pf);
/* Restart the service task */
mod_timer(&pf->serv_tmr, round_jiffies(jiffies + pf->serv_tmr_period));
return 0;
}
#endif /* CONFIG_PM */
/**
* ice_pci_err_detected - warning that PCI error has been detected
* @pdev: PCI device information struct
@ -3734,6 +4432,8 @@ static const struct pci_device_id ice_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, ice_pci_tbl);
static __maybe_unused SIMPLE_DEV_PM_OPS(ice_pm_ops, ice_suspend, ice_resume);
static const struct pci_error_handlers ice_pci_err_handler = {
.error_detected = ice_pci_err_detected,
.slot_reset = ice_pci_err_slot_reset,
@ -3747,6 +4447,10 @@ static struct pci_driver ice_driver = {
.id_table = ice_pci_tbl,
.probe = ice_probe,
.remove = ice_remove,
#ifdef CONFIG_PM
.driver.pm = &ice_pm_ops,
#endif /* CONFIG_PM */
.shutdown = ice_shutdown,
.sriov_configure = ice_sriov_configure,
.err_handler = &ice_pci_err_handler
};
@ -5659,20 +6363,30 @@ int ice_open(struct net_device *netdev)
/* Set PHY if there is media, otherwise, turn off PHY */
if (pi->phy.link_info.link_info & ICE_AQ_MEDIA_AVAILABLE) {
err = ice_force_phys_link_state(vsi, true);
clear_bit(ICE_FLAG_NO_MEDIA, pf->flags);
if (!test_bit(__ICE_PHY_INIT_COMPLETE, pf->state)) {
err = ice_init_phy_user_cfg(pi);
if (err) {
netdev_err(netdev, "Failed to initialize PHY settings, error %d\n",
err);
return err;
}
}
err = ice_configure_phy(vsi);
if (err) {
netdev_err(netdev, "Failed to set physical link up, error %d\n",
err);
return err;
}
} else {
set_bit(ICE_FLAG_NO_MEDIA, pf->flags);
err = ice_aq_set_link_restart_an(pi, false, NULL);
if (err) {
netdev_err(netdev, "Failed to set PHY state, VSI %d error %d\n",
vsi->vsi_num, err);
return err;
}
set_bit(ICE_FLAG_NO_MEDIA, vsi->back->flags);
}
err = ice_vsi_open(vsi);

View File

@ -172,8 +172,7 @@ void ice_release_nvm(struct ice_hw *hw)
*
* Reads one 16 bit word from the Shadow RAM using the ice_read_sr_word_aq.
*/
static enum ice_status
ice_read_sr_word(struct ice_hw *hw, u16 offset, u16 *data)
enum ice_status ice_read_sr_word(struct ice_hw *hw, u16 offset, u16 *data)
{
enum ice_status status;
@ -197,7 +196,7 @@ ice_read_sr_word(struct ice_hw *hw, u16 offset, u16 *data)
* Area (PFA) and returns the TLV pointer and length. The caller can
* use these to read the variable length TLV value.
*/
static enum ice_status
enum ice_status
ice_get_pfa_module_tlv(struct ice_hw *hw, u16 *module_tlv, u16 *module_tlv_len,
u16 module_type)
{

View File

@ -11,6 +11,10 @@ enum ice_status
ice_read_flat_nvm(struct ice_hw *hw, u32 offset, u32 *length, u8 *data,
bool read_shadow_ram);
enum ice_status
ice_get_pfa_module_tlv(struct ice_hw *hw, u16 *module_tlv, u16 *module_tlv_len,
u16 module_type);
enum ice_status
ice_read_pba_string(struct ice_hw *hw, u8 *pba_num, u32 pba_num_size);
enum ice_status ice_init_nvm(struct ice_hw *hw);
enum ice_status ice_read_sr_word(struct ice_hw *hw, u16 offset, u16 *data);
#endif /* _ICE_NVM_H_ */

View File

@ -87,6 +87,12 @@ enum ice_fc_mode {
ICE_FC_DFLT
};
enum ice_phy_cache_mode {
ICE_FC_MODE = 0,
ICE_SPEED_MODE,
ICE_FEC_MODE
};
enum ice_fec_mode {
ICE_FEC_NONE = 0,
ICE_FEC_RS,
@ -94,6 +100,14 @@ enum ice_fec_mode {
ICE_FEC_AUTO
};
struct ice_phy_cache_mode_data {
union {
enum ice_fec_mode curr_user_fec_req;
enum ice_fc_mode curr_user_fc_req;
u16 curr_user_speed_req;
} data;
};
enum ice_set_fc_aq_failures {
ICE_SET_FC_AQ_FAIL_NONE = 0,
ICE_SET_FC_AQ_FAIL_GET,
@ -104,6 +118,7 @@ enum ice_set_fc_aq_failures {
/* Various MAC types */
enum ice_mac_type {
ICE_MAC_UNKNOWN = 0,
ICE_MAC_E810,
ICE_MAC_GENERIC,
};
@ -160,6 +175,13 @@ struct ice_phy_info {
u64 phy_type_high;
enum ice_media_type media_type;
u8 get_link_info;
/* Please refer to struct ice_aqc_get_link_status_data to get
* detail of enable bit in curr_user_speed_req
*/
u16 curr_user_speed_req;
enum ice_fec_mode curr_user_fec_req;
enum ice_fc_mode curr_user_fc_req;
struct ice_aqc_set_phy_cfg_data curr_user_phy_cfg;
};
/* protocol enumeration for filters */
@ -293,6 +315,28 @@ struct ice_nvm_info {
u8 blank_nvm_mode; /* is NVM empty (no FW present) */
};
struct ice_link_default_override_tlv {
u8 options;
#define ICE_LINK_OVERRIDE_OPT_M 0x3F
#define ICE_LINK_OVERRIDE_STRICT_MODE BIT(0)
#define ICE_LINK_OVERRIDE_EPCT_DIS BIT(1)
#define ICE_LINK_OVERRIDE_PORT_DIS BIT(2)
#define ICE_LINK_OVERRIDE_EN BIT(3)
#define ICE_LINK_OVERRIDE_AUTO_LINK_DIS BIT(4)
#define ICE_LINK_OVERRIDE_EEE_EN BIT(5)
u8 phy_config;
#define ICE_LINK_OVERRIDE_PHY_CFG_S 8
#define ICE_LINK_OVERRIDE_PHY_CFG_M (0xC3 << ICE_LINK_OVERRIDE_PHY_CFG_S)
#define ICE_LINK_OVERRIDE_PAUSE_M 0x3
#define ICE_LINK_OVERRIDE_LESM_EN BIT(6)
#define ICE_LINK_OVERRIDE_AUTO_FEC_EN BIT(7)
u8 fec_options;
#define ICE_LINK_OVERRIDE_FEC_OPT_M 0xFF
u8 rsvd1;
u64 phy_type_low;
u64 phy_type_high;
};
#define ICE_NVM_VER_LEN 32
/* netlist version information */
@ -444,6 +488,7 @@ struct ice_dcb_app_priority_table {
#define ICE_APP_SEL_ETHTYPE 0x1
#define ICE_APP_SEL_TCPIP 0x2
#define ICE_CEE_APP_SEL_ETHTYPE 0x0
#define ICE_SR_LINK_DEFAULT_OVERRIDE_PTR 0x134
#define ICE_CEE_APP_SEL_TCPIP 0x1
struct ice_dcbx_cfg {
@ -709,6 +754,7 @@ struct ice_hw_port_stats {
/* Checksum and Shadow RAM pointers */
#define ICE_SR_BOOT_CFG_PTR 0x132
#define ICE_SR_NVM_WOL_CFG 0x19
#define ICE_NVM_OROM_VER_OFF 0x02
#define ICE_SR_PBA_BLOCK_PTR 0x16
#define ICE_SR_NVM_DEV_STARTER_VER 0x18
@ -726,6 +772,17 @@ struct ice_hw_port_stats {
#define ICE_OROM_VER_MASK (0xff << ICE_OROM_VER_SHIFT)
#define ICE_SR_PFA_PTR 0x40
#define ICE_SR_SECTOR_SIZE_IN_WORDS 0x800
/* Link override related */
#define ICE_SR_PFA_LINK_OVERRIDE_WORDS 10
#define ICE_SR_PFA_LINK_OVERRIDE_PHY_WORDS 4
#define ICE_SR_PFA_LINK_OVERRIDE_OFFSET 2
#define ICE_SR_PFA_LINK_OVERRIDE_FEC_OFFSET 1
#define ICE_SR_PFA_LINK_OVERRIDE_PHY_OFFSET 2
#define ICE_FW_API_LINK_OVERRIDE_MAJ 1
#define ICE_FW_API_LINK_OVERRIDE_MIN 5
#define ICE_FW_API_LINK_OVERRIDE_PATCH 2
#define ICE_SR_WORDS_IN_1KB 512
/* Hash redirection LUT for VSI - maximum array size */

View File

@ -1592,31 +1592,6 @@ err_unroll_intr:
return ret;
}
/**
* ice_pf_state_is_nominal - checks the PF for nominal state
* @pf: pointer to PF to check
*
* Check the PF's state for a collection of bits that would indicate
* the PF is in a state that would inhibit normal operation for
* driver functionality.
*
* Returns true if PF is in a nominal state.
* Returns false otherwise
*/
static bool ice_pf_state_is_nominal(struct ice_pf *pf)
{
DECLARE_BITMAP(check_bits, __ICE_STATE_NBITS) = { 0 };
if (!pf)
return false;
bitmap_set(check_bits, 0, __ICE_STATE_NOMINAL_CHECK_BITS);
if (bitmap_intersects(pf->state, check_bits, __ICE_STATE_NBITS))
return false;
return true;
}
/**
* ice_pci_sriov_ena - Enable or change number of VFs
* @pf: pointer to the PF structure