Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/ice/ice_lib.c
Show First 20 Lines • Show All 137 Lines • ▼ Show 20 Lines | ice_apply_saved_fc_req_to_cfg(struct ice_port_info *pi, | ||||
struct ice_aqc_set_phy_cfg_data *cfg); | struct ice_aqc_set_phy_cfg_data *cfg); | ||||
static void | static void | ||||
ice_print_ldo_tlv(struct ice_softc *sc, | ice_print_ldo_tlv(struct ice_softc *sc, | ||||
struct ice_link_default_override_tlv *tlv); | struct ice_link_default_override_tlv *tlv); | ||||
static void | static void | ||||
ice_sysctl_speeds_to_aq_phy_types(u16 sysctl_speeds, u64 *phy_type_low, | ice_sysctl_speeds_to_aq_phy_types(u16 sysctl_speeds, u64 *phy_type_low, | ||||
u64 *phy_type_high); | u64 *phy_type_high); | ||||
static int | static int | ||||
ice_intersect_media_types_with_caps(struct ice_softc *sc, u64 *phy_type_low, | ice_intersect_media_types_with_caps(struct ice_softc *sc, u16 sysctl_speeds, | ||||
u64 *phy_type_high); | u64 *phy_type_low, u64 *phy_type_high); | ||||
static int | static int | ||||
ice_get_auto_speeds(struct ice_softc *sc, u64 *phy_type_low, | ice_get_auto_speeds(struct ice_softc *sc, u64 *phy_type_low, | ||||
u64 *phy_type_high); | u64 *phy_type_high); | ||||
static void | static void | ||||
ice_apply_supported_speed_filter(u64 *phy_type_low, u64 *phy_type_high); | ice_apply_supported_speed_filter(u64 *phy_type_low, u64 *phy_type_high); | ||||
static enum ice_status | static enum ice_status | ||||
ice_get_phy_types(struct ice_softc *sc, u64 *phy_type_low, u64 *phy_type_high); | ice_get_phy_types(struct ice_softc *sc, u64 *phy_type_low, u64 *phy_type_high); | ||||
▲ Show 20 Lines • Show All 1,227 Lines • ▼ Show 20 Lines | |||||
* @vsi: the VSI to configure | * @vsi: the VSI to configure | ||||
* | * | ||||
* Configure the device Tx queues through firmware AdminQ commands. After | * Configure the device Tx queues through firmware AdminQ commands. After | ||||
* this, Tx queues will be ready for transmit. | * this, Tx queues will be ready for transmit. | ||||
*/ | */ | ||||
int | int | ||||
ice_cfg_vsi_for_tx(struct ice_vsi *vsi) | ice_cfg_vsi_for_tx(struct ice_vsi *vsi) | ||||
{ | { | ||||
struct ice_aqc_add_tx_qgrp qg = { 0 }; | struct ice_aqc_add_tx_qgrp *qg; | ||||
struct ice_hw *hw = &vsi->sc->hw; | struct ice_hw *hw = &vsi->sc->hw; | ||||
device_t dev = vsi->sc->dev; | device_t dev = vsi->sc->dev; | ||||
enum ice_status status; | enum ice_status status; | ||||
int i, err; | int i; | ||||
u16 pf_q; | int err = 0; | ||||
u16 qg_size, pf_q; | |||||
qg.num_txqs = 1; | qg_size = ice_struct_size(qg, txqs, 1); | ||||
qg = (struct ice_aqc_add_tx_qgrp *)malloc(qg_size, M_ICE, M_NOWAIT|M_ZERO); | |||||
if (!qg) | |||||
return (ENOMEM); | |||||
qg->num_txqs = 1; | |||||
for (i = 0; i < vsi->num_tx_queues; i++) { | for (i = 0; i < vsi->num_tx_queues; i++) { | ||||
struct ice_tlan_ctx tlan_ctx = { 0 }; | struct ice_tlan_ctx tlan_ctx = { 0 }; | ||||
struct ice_tx_queue *txq = &vsi->tx_queues[i]; | struct ice_tx_queue *txq = &vsi->tx_queues[i]; | ||||
pf_q = vsi->tx_qmap[txq->me]; | pf_q = vsi->tx_qmap[txq->me]; | ||||
qg.txqs[0].txq_id = htole16(pf_q); | qg->txqs[0].txq_id = htole16(pf_q); | ||||
err = ice_setup_tx_ctx(txq, &tlan_ctx, pf_q); | err = ice_setup_tx_ctx(txq, &tlan_ctx, pf_q); | ||||
if (err) | if (err) | ||||
return err; | goto free_txqg; | ||||
ice_set_ctx((u8 *)&tlan_ctx, qg.txqs[0].txq_ctx, | ice_set_ctx(hw, (u8 *)&tlan_ctx, qg->txqs[0].txq_ctx, | ||||
ice_tlan_ctx_info); | ice_tlan_ctx_info); | ||||
status = ice_ena_vsi_txq(hw->port_info, vsi->idx, 0, | status = ice_ena_vsi_txq(hw->port_info, vsi->idx, 0, | ||||
i, 1, &qg, sizeof(qg), NULL); | i, 1, qg, qg_size, NULL); | ||||
if (status) { | if (status) { | ||||
device_printf(dev, | device_printf(dev, | ||||
"Failed to set LAN Tx queue context, err %s aq_err %s\n", | "Failed to set LAN Tx queue context, err %s aq_err %s\n", | ||||
ice_status_str(status), ice_aq_str(hw->adminq.sq_last_status)); | ice_status_str(status), ice_aq_str(hw->adminq.sq_last_status)); | ||||
return (ENODEV); | err = ENODEV; | ||||
goto free_txqg; | |||||
} | } | ||||
/* Keep track of the Tx queue TEID */ | /* Keep track of the Tx queue TEID */ | ||||
if (pf_q == le16toh(qg.txqs[0].txq_id)) | if (pf_q == le16toh(qg->txqs[0].txq_id)) | ||||
txq->q_teid = le32toh(qg.txqs[0].q_teid); | txq->q_teid = le32toh(qg->txqs[0].q_teid); | ||||
} | } | ||||
return (0); | free_txqg: | ||||
free(qg, M_ICE); | |||||
return (err); | |||||
} | } | ||||
/** | /** | ||||
* ice_setup_rx_ctx - Setup an Rx context structure for a receive queue | * ice_setup_rx_ctx - Setup an Rx context structure for a receive queue | ||||
* @rxq: the receive queue to program | * @rxq: the receive queue to program | ||||
* | * | ||||
* Setup an Rx queue context structure and program it into the hardware | * Setup an Rx queue context structure and program it into the hardware | ||||
* registers. This is a necessary step for enabling the Rx queue. | * registers. This is a necessary step for enabling the Rx queue. | ||||
▲ Show 20 Lines • Show All 901 Lines • ▼ Show 20 Lines | #define ICE_PF_STAT32(name, location) \ | ||||
ICE_PF_STAT40(GLPRT_GORC, eth.rx_bytes); | ICE_PF_STAT40(GLPRT_GORC, eth.rx_bytes); | ||||
ICE_PF_STAT40(GLPRT_UPRC, eth.rx_unicast); | ICE_PF_STAT40(GLPRT_UPRC, eth.rx_unicast); | ||||
ICE_PF_STAT40(GLPRT_MPRC, eth.rx_multicast); | ICE_PF_STAT40(GLPRT_MPRC, eth.rx_multicast); | ||||
ICE_PF_STAT40(GLPRT_BPRC, eth.rx_broadcast); | ICE_PF_STAT40(GLPRT_BPRC, eth.rx_broadcast); | ||||
ICE_PF_STAT40(GLPRT_GOTC, eth.tx_bytes); | ICE_PF_STAT40(GLPRT_GOTC, eth.tx_bytes); | ||||
ICE_PF_STAT40(GLPRT_UPTC, eth.tx_unicast); | ICE_PF_STAT40(GLPRT_UPTC, eth.tx_unicast); | ||||
ICE_PF_STAT40(GLPRT_MPTC, eth.tx_multicast); | ICE_PF_STAT40(GLPRT_MPTC, eth.tx_multicast); | ||||
ICE_PF_STAT40(GLPRT_BPTC, eth.tx_broadcast); | ICE_PF_STAT40(GLPRT_BPTC, eth.tx_broadcast); | ||||
/* This stat register doesn't have an lport */ | |||||
ice_stat_update32(hw, PRTRPB_RDPC, | |||||
sc->stats.offsets_loaded, | |||||
&prev_ps->eth.rx_discards, &cur_ps->eth.rx_discards); | |||||
ICE_PF_STAT32(GLPRT_TDOLD, tx_dropped_link_down); | ICE_PF_STAT32(GLPRT_TDOLD, tx_dropped_link_down); | ||||
ICE_PF_STAT40(GLPRT_PRC64, rx_size_64); | ICE_PF_STAT40(GLPRT_PRC64, rx_size_64); | ||||
ICE_PF_STAT40(GLPRT_PRC127, rx_size_127); | ICE_PF_STAT40(GLPRT_PRC127, rx_size_127); | ||||
ICE_PF_STAT40(GLPRT_PRC255, rx_size_255); | ICE_PF_STAT40(GLPRT_PRC255, rx_size_255); | ||||
ICE_PF_STAT40(GLPRT_PRC511, rx_size_511); | ICE_PF_STAT40(GLPRT_PRC511, rx_size_511); | ||||
ICE_PF_STAT40(GLPRT_PRC1023, rx_size_1023); | ICE_PF_STAT40(GLPRT_PRC1023, rx_size_1023); | ||||
ICE_PF_STAT40(GLPRT_PRC1522, rx_size_1522); | ICE_PF_STAT40(GLPRT_PRC1522, rx_size_1522); | ||||
▲ Show 20 Lines • Show All 449 Lines • ▼ Show 20 Lines | if (sysctl_speeds & ICE_AQ_LINK_SPEED_100GB) { | ||||
*phy_type_low |= ICE_PHYS_100GB_LOW; | *phy_type_low |= ICE_PHYS_100GB_LOW; | ||||
*phy_type_high |= ICE_PHYS_100GB_HIGH; | *phy_type_high |= ICE_PHYS_100GB_HIGH; | ||||
} | } | ||||
} | } | ||||
/** | /** | ||||
* ice_intersect_media_types_with_caps - Restrict input AQ PHY flags | * ice_intersect_media_types_with_caps - Restrict input AQ PHY flags | ||||
* @sc: driver private structure | * @sc: driver private structure | ||||
* @sysctl_speeds: current SW configuration of PHY types | |||||
* @phy_type_low: input/output flag set for low PHY types | * @phy_type_low: input/output flag set for low PHY types | ||||
* @phy_type_high: input/output flag set for high PHY types | * @phy_type_high: input/output flag set for high PHY types | ||||
* | * | ||||
* Intersects the input PHY flags with PHY flags retrieved from the adapter to | * Intersects the input PHY flags with PHY flags retrieved from the adapter to | ||||
* ensure the flags are compatible. | * ensure the flags are compatible. | ||||
* | * | ||||
* @returns 0 on success, EIO if an AQ command fails, or EINVAL if input PHY | * @returns 0 on success, EIO if an AQ command fails, or EINVAL if input PHY | ||||
* types have no intersection with TOPO_CAPS and the adapter is in non-lenient | * types have no intersection with TOPO_CAPS and the adapter is in non-lenient | ||||
* mode | * mode | ||||
*/ | */ | ||||
static int | static int | ||||
ice_intersect_media_types_with_caps(struct ice_softc *sc, u64 *phy_type_low, | ice_intersect_media_types_with_caps(struct ice_softc *sc, u16 sysctl_speeds, | ||||
u64 *phy_type_high) | u64 *phy_type_low, u64 *phy_type_high) | ||||
{ | { | ||||
struct ice_aqc_get_phy_caps_data pcaps = { 0 }; | |||||
struct ice_port_info *pi = sc->hw.port_info; | |||||
device_t dev = sc->dev; | device_t dev = sc->dev; | ||||
enum ice_status status; | enum ice_status status; | ||||
u64 temp_phy_low, temp_phy_high; | |||||
u64 final_phy_low, final_phy_high; | |||||
u16 topo_speeds; | |||||
u64 new_phy_low, new_phy_high; | status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_TOPO_CAP, | ||||
&pcaps, NULL); | |||||
status = ice_get_phy_types(sc, &new_phy_low, &new_phy_high); | |||||
if (status != ICE_SUCCESS) { | if (status != ICE_SUCCESS) { | ||||
/* Function already prints appropriate error message */ | device_printf(dev, | ||||
"%s: ice_aq_get_phy_caps (TOPO_CAP) failed; status %s, aq_err %s\n", | |||||
__func__, ice_status_str(status), | |||||
ice_aq_str(sc->hw.adminq.sq_last_status)); | |||||
return (EIO); | return (EIO); | ||||
} | } | ||||
ice_apply_supported_speed_filter(&new_phy_low, &new_phy_high); | final_phy_low = le64toh(pcaps.phy_type_low); | ||||
final_phy_high = le64toh(pcaps.phy_type_high); | |||||
new_phy_low &= *phy_type_low; | topo_speeds = ice_aq_phy_types_to_sysctl_speeds(final_phy_low, | ||||
new_phy_high &= *phy_type_high; | final_phy_high); | ||||
if (new_phy_low == 0 && new_phy_high == 0) { | /* | ||||
* If the user specifies a subset of speeds the media is already | |||||
* capable of supporting, then we're good to go. | |||||
*/ | |||||
if ((sysctl_speeds & topo_speeds) == sysctl_speeds) | |||||
goto intersect_final; | |||||
temp_phy_low = final_phy_low; | |||||
temp_phy_high = final_phy_high; | |||||
/* | |||||
* Otherwise, we'll have to use the superset if Lenient Mode is | |||||
* supported. | |||||
*/ | |||||
if (ice_is_bit_set(sc->feat_en, ICE_FEATURE_LENIENT_LINK_MODE)) { | |||||
/* | |||||
* Start with masks that _don't_ include the PHY types | |||||
* discovered by the TOPO_CAP. | |||||
*/ | |||||
ice_sysctl_speeds_to_aq_phy_types(topo_speeds, &final_phy_low, | |||||
&final_phy_high); | |||||
final_phy_low = ~final_phy_low; | |||||
final_phy_high = ~final_phy_high; | |||||
/* Get the PHY types the NVM says we can support */ | |||||
status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_NVM_CAP, | |||||
&pcaps, NULL); | |||||
if (status != ICE_SUCCESS) { | |||||
device_printf(dev, | device_printf(dev, | ||||
"%s: ice_aq_get_phy_caps (NVM_CAP) failed; status %s, aq_err %s\n", | |||||
__func__, ice_status_str(status), | |||||
ice_aq_str(sc->hw.adminq.sq_last_status)); | |||||
return (status); | |||||
} | |||||
/* | |||||
* Clear out the unsupported PHY types, including those | |||||
* from TOPO_CAP. | |||||
*/ | |||||
final_phy_low &= le64toh(pcaps.phy_type_low); | |||||
final_phy_high &= le64toh(pcaps.phy_type_high); | |||||
/* | |||||
* Include PHY types from TOPO_CAP (which may be a subset | |||||
* of the types the NVM specifies). | |||||
*/ | |||||
final_phy_low |= temp_phy_low; | |||||
final_phy_high |= temp_phy_high; | |||||
} | |||||
intersect_final: | |||||
if (ice_is_bit_set(sc->feat_en, ICE_FEATURE_LENIENT_LINK_MODE)) | |||||
ice_apply_supported_speed_filter(&final_phy_low, &final_phy_high); | |||||
ice_sysctl_speeds_to_aq_phy_types(sysctl_speeds, &temp_phy_low, | |||||
&temp_phy_high); | |||||
final_phy_low &= temp_phy_low; | |||||
final_phy_high &= temp_phy_high; | |||||
if (final_phy_low == 0 && final_phy_high == 0) { | |||||
device_printf(dev, | |||||
"The selected speed is not supported by the current media. Please select a link speed that is supported by the current media.\n"); | "The selected speed is not supported by the current media. Please select a link speed that is supported by the current media.\n"); | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
/* Overwrite input phy_type values and return */ | /* Overwrite input phy_type values and return */ | ||||
*phy_type_low = new_phy_low; | *phy_type_low = final_phy_low; | ||||
*phy_type_high = new_phy_high; | *phy_type_high = final_phy_high; | ||||
return (0); | return (0); | ||||
} | } | ||||
/** | /** | ||||
* ice_get_auto_speeds - Get PHY type flags for "auto" speed | * ice_get_auto_speeds - Get PHY type flags for "auto" speed | ||||
* @sc: driver private structure | * @sc: driver private structure | ||||
* @phy_type_low: output low PHY type flags | * @phy_type_low: output low PHY type flags | ||||
▲ Show 20 Lines • Show All 97 Lines • ▼ Show 20 Lines | ice_sysctl_advertise_speed(SYSCTL_HANDLER_ARGS) | ||||
* or apply an override if one is specified in the NVM. | * or apply an override if one is specified in the NVM. | ||||
*/ | */ | ||||
if (sysctl_speeds == 0) { | if (sysctl_speeds == 0) { | ||||
error = ice_get_auto_speeds(sc, &phy_low, &phy_high); | error = ice_get_auto_speeds(sc, &phy_low, &phy_high); | ||||
if (error) | if (error) | ||||
/* Function already prints appropriate error message */ | /* Function already prints appropriate error message */ | ||||
return (error); | return (error); | ||||
} else { | } else { | ||||
ice_sysctl_speeds_to_aq_phy_types(sysctl_speeds, &phy_low, &phy_high); | error = ice_intersect_media_types_with_caps(sc, sysctl_speeds, | ||||
error = ice_intersect_media_types_with_caps(sc, &phy_low, &phy_high); | &phy_low, &phy_high); | ||||
if (error) | if (error) | ||||
/* Function already prints appropriate error message */ | /* Function already prints appropriate error message */ | ||||
return (error); | return (error); | ||||
} | } | ||||
sysctl_speeds = ice_aq_phy_types_to_sysctl_speeds(phy_low, phy_high); | sysctl_speeds = ice_aq_phy_types_to_sysctl_speeds(phy_low, phy_high); | ||||
/* Cache new user setting for speeds */ | /* Cache new user setting for speeds */ | ||||
pi->phy.curr_user_speed_req = sysctl_speeds; | pi->phy.curr_user_speed_req = sysctl_speeds; | ||||
/* Setup new PHY config with new input PHY types */ | /* Setup new PHY config with new input PHY types */ | ||||
ice_copy_phy_caps_to_cfg(pi, &pcaps, &cfg); | ice_copy_phy_caps_to_cfg(pi, &pcaps, &cfg); | ||||
cfg.phy_type_low = phy_low; | cfg.phy_type_low = phy_low; | ||||
cfg.phy_type_high = phy_high; | cfg.phy_type_high = phy_high; | ||||
cfg.caps |= ICE_AQ_PHY_ENA_AUTO_LINK_UPDT; | cfg.caps |= ICE_AQ_PHY_ENA_AUTO_LINK_UPDT | ICE_AQ_PHY_ENA_LINK; | ||||
status = ice_aq_set_phy_cfg(hw, pi, &cfg, NULL); | status = ice_aq_set_phy_cfg(hw, pi, &cfg, NULL); | ||||
if (status != ICE_SUCCESS) { | if (status != ICE_SUCCESS) { | ||||
/* Don't indicate failure if there's no media in the port -- the sysctl | /* Don't indicate failure if there's no media in the port -- the sysctl | ||||
* handler has saved the value and will apply it when media is inserted. | * handler has saved the value and will apply it when media is inserted. | ||||
*/ | */ | ||||
if (status == ICE_ERR_AQ_ERROR && | if (status == ICE_ERR_AQ_ERROR && | ||||
hw->adminq.sq_last_status == ICE_AQ_RC_EBUSY) { | hw->adminq.sq_last_status == ICE_AQ_RC_EBUSY) { | ||||
▲ Show 20 Lines • Show All 759 Lines • ▼ Show 20 Lines | if (fw_lldp_enabled == false) { | ||||
if (status && hw->adminq.sq_last_status != ICE_AQ_RC_EPERM) { | if (status && hw->adminq.sq_last_status != ICE_AQ_RC_EPERM) { | ||||
device_printf(dev, | device_printf(dev, | ||||
"%s: ice_aq_stop_lldp failed; status %s, aq_err %s\n", | "%s: ice_aq_stop_lldp failed; status %s, aq_err %s\n", | ||||
__func__, ice_status_str(status), | __func__, ice_status_str(status), | ||||
ice_aq_str(hw->adminq.sq_last_status)); | ice_aq_str(hw->adminq.sq_last_status)); | ||||
return (EIO); | return (EIO); | ||||
} | } | ||||
ice_aq_set_dcb_parameters(hw, true, NULL); | ice_aq_set_dcb_parameters(hw, true, NULL); | ||||
hw->port_info->is_sw_lldp = true; | hw->port_info->qos_cfg.is_sw_lldp = true; | ||||
ice_add_rx_lldp_filter(sc); | ice_add_rx_lldp_filter(sc); | ||||
} else { | } else { | ||||
ice_del_rx_lldp_filter(sc); | |||||
retry_start_lldp: | retry_start_lldp: | ||||
status = ice_aq_start_lldp(hw, true, NULL); | status = ice_aq_start_lldp(hw, true, NULL); | ||||
if (status) { | if (status) { | ||||
switch (hw->adminq.sq_last_status) { | switch (hw->adminq.sq_last_status) { | ||||
/* EEXIST is returned if the LLDP agent is already started */ | /* EEXIST is returned if the LLDP agent is already started */ | ||||
case ICE_AQ_RC_EEXIST: | case ICE_AQ_RC_EEXIST: | ||||
break; | break; | ||||
case ICE_AQ_RC_EAGAIN: | case ICE_AQ_RC_EAGAIN: | ||||
/* Retry command after a 2 second wait */ | /* Retry command after a 2 second wait */ | ||||
if (retried_start_lldp == false) { | if (retried_start_lldp == false) { | ||||
retried_start_lldp = true; | retried_start_lldp = true; | ||||
pause("slldp", ICE_START_LLDP_RETRY_WAIT); | pause("slldp", ICE_START_LLDP_RETRY_WAIT); | ||||
goto retry_start_lldp; | goto retry_start_lldp; | ||||
} | } | ||||
/* Fallthrough */ | /* Fallthrough */ | ||||
default: | default: | ||||
device_printf(dev, | device_printf(dev, | ||||
"%s: ice_aq_start_lldp failed; status %s, aq_err %s\n", | "%s: ice_aq_start_lldp failed; status %s, aq_err %s\n", | ||||
__func__, ice_status_str(status), | __func__, ice_status_str(status), | ||||
ice_aq_str(hw->adminq.sq_last_status)); | ice_aq_str(hw->adminq.sq_last_status)); | ||||
return (EIO); | return (EIO); | ||||
} | } | ||||
} | } | ||||
hw->port_info->is_sw_lldp = false; | hw->port_info->qos_cfg.is_sw_lldp = false; | ||||
ice_del_rx_lldp_filter(sc); | |||||
} | } | ||||
return (error); | return (error); | ||||
} | } | ||||
/** | /** | ||||
* ice_add_device_sysctls - add device specific dynamic sysctls | * ice_add_device_sysctls - add device specific dynamic sysctls | ||||
* @sc: device private structure | * @sc: device private structure | ||||
▲ Show 20 Lines • Show All 181 Lines • ▼ Show 20 Lines | |||||
* ice_add_sysctls_eth_stats - Add sysctls for ethernet statistics | * ice_add_sysctls_eth_stats - Add sysctls for ethernet statistics | ||||
* @ctx: sysctl ctx to use | * @ctx: sysctl ctx to use | ||||
* @parent: the parent node to add sysctls under | * @parent: the parent node to add sysctls under | ||||
* @stats: the ethernet stats structure to source values from | * @stats: the ethernet stats structure to source values from | ||||
* | * | ||||
* Adds statistics sysctls for the ethernet statistics of the MAC or a VSI. | * Adds statistics sysctls for the ethernet statistics of the MAC or a VSI. | ||||
* Will add them under the parent node specified. | * Will add them under the parent node specified. | ||||
* | * | ||||
* Note that rx_discards and tx_errors are only meaningful for VSIs and not | * Note that tx_errors is only meaningful for VSIs and not the global MAC/PF | ||||
* the global MAC/PF statistics, so they are not included here. | * statistics, so it is not included here. Similarly, rx_discards has different | ||||
* descriptions for VSIs and MAC/PF stats, so it is also not included here. | |||||
*/ | */ | ||||
void | void | ||||
ice_add_sysctls_eth_stats(struct sysctl_ctx_list *ctx, | ice_add_sysctls_eth_stats(struct sysctl_ctx_list *ctx, | ||||
struct sysctl_oid *parent, | struct sysctl_oid *parent, | ||||
struct ice_eth_stats *stats) | struct ice_eth_stats *stats) | ||||
{ | { | ||||
const struct ice_sysctl_info ctls[] = { | const struct ice_sysctl_info ctls[] = { | ||||
/* Rx Stats */ | /* Rx Stats */ | ||||
▲ Show 20 Lines • Show All 200 Lines • ▼ Show 20 Lines | hw_node = SYSCTL_ADD_NODE(ctx, vsi_list, OID_AUTO, "hw", CTLFLAG_RD, | ||||
NULL, "VSI Hardware Statistics"); | NULL, "VSI Hardware Statistics"); | ||||
hw_list = SYSCTL_CHILDREN(hw_node); | hw_list = SYSCTL_CHILDREN(hw_node); | ||||
/* Add the ethernet statistics for this VSI */ | /* Add the ethernet statistics for this VSI */ | ||||
ice_add_sysctls_eth_stats(ctx, hw_node, &vsi->hw_stats.cur); | ice_add_sysctls_eth_stats(ctx, hw_node, &vsi->hw_stats.cur); | ||||
SYSCTL_ADD_U64(ctx, hw_list, OID_AUTO, "rx_discards", | SYSCTL_ADD_U64(ctx, hw_list, OID_AUTO, "rx_discards", | ||||
CTLFLAG_RD | CTLFLAG_STATS, &vsi->hw_stats.cur.rx_discards, | CTLFLAG_RD | CTLFLAG_STATS, &vsi->hw_stats.cur.rx_discards, | ||||
0, "Discarded Rx Packets"); | 0, "Discarded Rx Packets (see rx_errors or rx_no_desc)"); | ||||
SYSCTL_ADD_U64(ctx, hw_list, OID_AUTO, "rx_errors", | SYSCTL_ADD_U64(ctx, hw_list, OID_AUTO, "rx_errors", | ||||
CTLFLAG_RD | CTLFLAG_STATS, &vsi->hw_stats.cur.rx_errors, | CTLFLAG_RD | CTLFLAG_STATS, &vsi->hw_stats.cur.rx_errors, | ||||
0, "Rx Packets Discarded Due To Error"); | 0, "Rx Packets Discarded Due To Error"); | ||||
SYSCTL_ADD_U64(ctx, hw_list, OID_AUTO, "rx_no_desc", | SYSCTL_ADD_U64(ctx, hw_list, OID_AUTO, "rx_no_desc", | ||||
CTLFLAG_RD | CTLFLAG_STATS, &vsi->hw_stats.cur.rx_no_desc, | CTLFLAG_RD | CTLFLAG_STATS, &vsi->hw_stats.cur.rx_no_desc, | ||||
0, "Rx Packets Discarded Due To Lack Of Descriptors"); | 0, "Rx Packets Discarded Due To Lack Of Descriptors"); | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | const struct ice_sysctl_info ctls[] = { | ||||
{&stats->rx_size_1023, "rx_frames_512_1023", "512-1023 byte frames received"}, | {&stats->rx_size_1023, "rx_frames_512_1023", "512-1023 byte frames received"}, | ||||
{&stats->rx_size_1522, "rx_frames_1024_1522", "1024-1522 byte frames received"}, | {&stats->rx_size_1522, "rx_frames_1024_1522", "1024-1522 byte frames received"}, | ||||
{&stats->rx_size_big, "rx_frames_big", "1523-9522 byte frames received"}, | {&stats->rx_size_big, "rx_frames_big", "1523-9522 byte frames received"}, | ||||
{&stats->rx_undersize, "rx_undersize", "Undersized packets received"}, | {&stats->rx_undersize, "rx_undersize", "Undersized packets received"}, | ||||
{&stats->rx_fragments, "rx_fragmented", "Fragmented packets received"}, | {&stats->rx_fragments, "rx_fragmented", "Fragmented packets received"}, | ||||
{&stats->rx_oversize, "rx_oversized", "Oversized packets received"}, | {&stats->rx_oversize, "rx_oversized", "Oversized packets received"}, | ||||
{&stats->rx_jabber, "rx_jabber", "Received Jabber"}, | {&stats->rx_jabber, "rx_jabber", "Received Jabber"}, | ||||
{&stats->rx_len_errors, "rx_length_errors", "Receive Length Errors"}, | {&stats->rx_len_errors, "rx_length_errors", "Receive Length Errors"}, | ||||
{&stats->eth.rx_discards, "rx_discards", | |||||
"Discarded Rx Packets by Port (shortage of storage space)"}, | |||||
/* Packet Transmission Stats */ | /* Packet Transmission Stats */ | ||||
{&stats->tx_size_64, "tx_frames_64", "64 byte frames transmitted"}, | {&stats->tx_size_64, "tx_frames_64", "64 byte frames transmitted"}, | ||||
{&stats->tx_size_127, "tx_frames_65_127", "65-127 byte frames transmitted"}, | {&stats->tx_size_127, "tx_frames_65_127", "65-127 byte frames transmitted"}, | ||||
{&stats->tx_size_255, "tx_frames_128_255", "128-255 byte frames transmitted"}, | {&stats->tx_size_255, "tx_frames_128_255", "128-255 byte frames transmitted"}, | ||||
{&stats->tx_size_511, "tx_frames_256_511", "256-511 byte frames transmitted"}, | {&stats->tx_size_511, "tx_frames_256_511", "256-511 byte frames transmitted"}, | ||||
{&stats->tx_size_1023, "tx_frames_512_1023", "512-1023 byte frames transmitted"}, | {&stats->tx_size_1023, "tx_frames_512_1023", "512-1023 byte frames transmitted"}, | ||||
{&stats->tx_size_1522, "tx_frames_1024_1522", "1024-1522 byte frames transmitted"}, | {&stats->tx_size_1522, "tx_frames_1024_1522", "1024-1522 byte frames transmitted"}, | ||||
{&stats->tx_size_big, "tx_frames_big", "1523-9522 byte frames transmitted"}, | {&stats->tx_size_big, "tx_frames_big", "1523-9522 byte frames transmitted"}, | ||||
▲ Show 20 Lines • Show All 2,380 Lines • ▼ Show 20 Lines | ice_set_pci_link_status_data(struct ice_hw *hw, u16 link_status) | ||||
case ice_pcie_lnk_x32: | case ice_pcie_lnk_x32: | ||||
hw->bus.width = (enum ice_pcie_link_width)reg; | hw->bus.width = (enum ice_pcie_link_width)reg; | ||||
break; | break; | ||||
default: | default: | ||||
hw->bus.width = ice_pcie_lnk_width_unknown; | hw->bus.width = ice_pcie_lnk_width_unknown; | ||||
break; | break; | ||||
} | } | ||||
reg = (link_status & PCIEM_LINK_STA_SPEED) + 0x14; | reg = (link_status & PCIEM_LINK_STA_SPEED) + 0x13; | ||||
switch (reg) { | switch (reg) { | ||||
case ice_pcie_speed_2_5GT: | case ice_pcie_speed_2_5GT: | ||||
case ice_pcie_speed_5_0GT: | case ice_pcie_speed_5_0GT: | ||||
case ice_pcie_speed_8_0GT: | case ice_pcie_speed_8_0GT: | ||||
case ice_pcie_speed_16_0GT: | case ice_pcie_speed_16_0GT: | ||||
hw->bus.speed = (enum ice_pcie_bus_speed)reg; | hw->bus.speed = (enum ice_pcie_bus_speed)reg; | ||||
break; | break; | ||||
▲ Show 20 Lines • Show All 176 Lines • ▼ Show 20 Lines | ice_init_dcb_setup(struct ice_softc *sc) | ||||
/* Don't do anything if DCB isn't supported */ | /* Don't do anything if DCB isn't supported */ | ||||
if (!hw->func_caps.common_cap.dcb) { | if (!hw->func_caps.common_cap.dcb) { | ||||
device_printf(dev, "%s: No DCB support\n", | device_printf(dev, "%s: No DCB support\n", | ||||
__func__); | __func__); | ||||
return; | return; | ||||
} | } | ||||
hw->port_info->dcbx_status = ice_get_dcbx_status(hw); | hw->port_info->qos_cfg.dcbx_status = ice_get_dcbx_status(hw); | ||||
if (hw->port_info->dcbx_status != ICE_DCBX_STATUS_DONE && | if (hw->port_info->qos_cfg.dcbx_status != ICE_DCBX_STATUS_DONE && | ||||
hw->port_info->dcbx_status != ICE_DCBX_STATUS_IN_PROGRESS) { | hw->port_info->qos_cfg.dcbx_status != ICE_DCBX_STATUS_IN_PROGRESS) { | ||||
/* | /* | ||||
* Start DCBX agent, but not LLDP. The return value isn't | * Start DCBX agent, but not LLDP. The return value isn't | ||||
* checked here because a more detailed dcbx agent status is | * checked here because a more detailed dcbx agent status is | ||||
* retrieved and checked in ice_init_dcb() and below. | * retrieved and checked in ice_init_dcb() and below. | ||||
*/ | */ | ||||
ice_aq_start_stop_dcbx(hw, true, &dcbx_agent_status, NULL); | ice_aq_start_stop_dcbx(hw, true, &dcbx_agent_status, NULL); | ||||
} | } | ||||
/* This sets hw->port_info->is_sw_lldp */ | /* This sets hw->port_info->qos_cfg.is_sw_lldp */ | ||||
status = ice_init_dcb(hw, true); | status = ice_init_dcb(hw, true); | ||||
/* If there is an error, then FW LLDP is not in a usable state */ | /* If there is an error, then FW LLDP is not in a usable state */ | ||||
if (status != 0 && status != ICE_ERR_NOT_READY) { | if (status != 0 && status != ICE_ERR_NOT_READY) { | ||||
/* Don't print an error message if the return code from the AQ | /* Don't print an error message if the return code from the AQ | ||||
* cmd performed in ice_init_dcb() is is EPERM; that means the | * cmd performed in ice_init_dcb() is is EPERM; that means the | ||||
* FW LLDP engine is disabled, and that is a valid state. | * FW LLDP engine is disabled, and that is a valid state. | ||||
*/ | */ | ||||
if (!(status == ICE_ERR_AQ_ERROR && | if (!(status == ICE_ERR_AQ_ERROR && | ||||
hw->adminq.sq_last_status == ICE_AQ_RC_EPERM)) { | hw->adminq.sq_last_status == ICE_AQ_RC_EPERM)) { | ||||
device_printf(dev, "DCB init failed, err %s aq_err %s\n", | device_printf(dev, "DCB init failed, err %s aq_err %s\n", | ||||
ice_status_str(status), | ice_status_str(status), | ||||
ice_aq_str(hw->adminq.sq_last_status)); | ice_aq_str(hw->adminq.sq_last_status)); | ||||
} | } | ||||
hw->port_info->dcbx_status = ICE_DCBX_STATUS_NOT_STARTED; | hw->port_info->qos_cfg.dcbx_status = ICE_DCBX_STATUS_NOT_STARTED; | ||||
} | } | ||||
switch (hw->port_info->dcbx_status) { | switch (hw->port_info->qos_cfg.dcbx_status) { | ||||
case ICE_DCBX_STATUS_DIS: | case ICE_DCBX_STATUS_DIS: | ||||
ice_debug(hw, ICE_DBG_DCB, "DCBX disabled\n"); | ice_debug(hw, ICE_DBG_DCB, "DCBX disabled\n"); | ||||
break; | break; | ||||
case ICE_DCBX_STATUS_NOT_STARTED: | case ICE_DCBX_STATUS_NOT_STARTED: | ||||
ice_debug(hw, ICE_DBG_DCB, "DCBX not started\n"); | ice_debug(hw, ICE_DBG_DCB, "DCBX not started\n"); | ||||
break; | break; | ||||
case ICE_DCBX_STATUS_MULTIPLE_PEERS: | case ICE_DCBX_STATUS_MULTIPLE_PEERS: | ||||
ice_debug(hw, ICE_DBG_DCB, "DCBX detected multiple peers\n"); | ice_debug(hw, ICE_DBG_DCB, "DCBX detected multiple peers\n"); | ||||
break; | break; | ||||
default: | default: | ||||
break; | break; | ||||
} | } | ||||
/* LLDP disabled in FW */ | /* LLDP disabled in FW */ | ||||
if (hw->port_info->is_sw_lldp) { | if (hw->port_info->qos_cfg.is_sw_lldp) { | ||||
ice_add_rx_lldp_filter(sc); | ice_add_rx_lldp_filter(sc); | ||||
device_printf(dev, "Firmware LLDP agent disabled\n"); | device_printf(dev, "Firmware LLDP agent disabled\n"); | ||||
} else { | |||||
ice_del_rx_lldp_filter(sc); | |||||
} | } | ||||
} | } | ||||
/** | /** | ||||
* ice_handle_mib_change_event - helper function to log LLDP MIB change events | * ice_handle_mib_change_event - helper function to log LLDP MIB change events | ||||
* @sc: device softc | * @sc: device softc | ||||
* @event: event received on a control queue | * @event: event received on a control queue | ||||
* | * | ||||
▲ Show 20 Lines • Show All 207 Lines • ▼ Show 20 Lines | |||||
ice_add_rx_lldp_filter(struct ice_softc *sc) | ice_add_rx_lldp_filter(struct ice_softc *sc) | ||||
{ | { | ||||
struct ice_list_head ethertype_list; | struct ice_list_head ethertype_list; | ||||
struct ice_vsi *vsi = &sc->pf_vsi; | struct ice_vsi *vsi = &sc->pf_vsi; | ||||
struct ice_hw *hw = &sc->hw; | struct ice_hw *hw = &sc->hw; | ||||
device_t dev = sc->dev; | device_t dev = sc->dev; | ||||
enum ice_status status; | enum ice_status status; | ||||
int err; | int err; | ||||
u16 vsi_num; | |||||
/* | |||||
* If FW is new enough, use a direct AQ command to perform the filter | |||||
* addition. | |||||
*/ | |||||
if (ice_fw_supports_lldp_fltr_ctrl(hw)) { | |||||
vsi_num = ice_get_hw_vsi_num(hw, vsi->idx); | |||||
status = ice_lldp_fltr_add_remove(hw, vsi_num, true); | |||||
if (status) { | |||||
device_printf(dev, | |||||
"Failed to add Rx LLDP filter, err %s aq_err %s\n", | |||||
ice_status_str(status), | |||||
ice_aq_str(hw->adminq.sq_last_status)); | |||||
} else | |||||
ice_set_state(&sc->state, | |||||
ICE_STATE_LLDP_RX_FLTR_FROM_DRIVER); | |||||
return; | |||||
} | |||||
INIT_LIST_HEAD(ðertype_list); | INIT_LIST_HEAD(ðertype_list); | ||||
/* Forward Rx LLDP frames to the stack */ | /* Forward Rx LLDP frames to the stack */ | ||||
err = ice_add_ethertype_to_list(vsi, ðertype_list, | err = ice_add_ethertype_to_list(vsi, ðertype_list, | ||||
ETHERTYPE_LLDP_FRAMES, | ETHERTYPE_LLDP_FRAMES, | ||||
ICE_FLTR_RX, ICE_FWD_TO_VSI); | ICE_FLTR_RX, ICE_FWD_TO_VSI); | ||||
if (err) { | if (err) { | ||||
device_printf(dev, | device_printf(dev, | ||||
"Failed to add Rx LLDP filter, err %s\n", | "Failed to add Rx LLDP filter, err %s\n", | ||||
ice_err_str(err)); | ice_err_str(err)); | ||||
goto free_ethertype_list; | goto free_ethertype_list; | ||||
} | } | ||||
status = ice_add_eth_mac(hw, ðertype_list); | status = ice_add_eth_mac(hw, ðertype_list); | ||||
if (status == ICE_ERR_ALREADY_EXISTS) { | if (status && status != ICE_ERR_ALREADY_EXISTS) { | ||||
; /* Don't complain if we try to add a filter that already exists */ | |||||
} else if (status) { | |||||
device_printf(dev, | device_printf(dev, | ||||
"Failed to add Rx LLDP filter, err %s aq_err %s\n", | "Failed to add Rx LLDP filter, err %s aq_err %s\n", | ||||
ice_status_str(status), | ice_status_str(status), | ||||
ice_aq_str(hw->adminq.sq_last_status)); | ice_aq_str(hw->adminq.sq_last_status)); | ||||
} else { | |||||
/* | |||||
* If status == ICE_ERR_ALREADY_EXISTS, we won't treat an | |||||
* already existing filter as an error case. | |||||
*/ | |||||
ice_set_state(&sc->state, ICE_STATE_LLDP_RX_FLTR_FROM_DRIVER); | |||||
} | } | ||||
free_ethertype_list: | free_ethertype_list: | ||||
ice_free_fltr_list(ðertype_list); | ice_free_fltr_list(ðertype_list); | ||||
} | } | ||||
/** | /** | ||||
* ice_del_rx_lldp_filter - Remove ethertype filter for Rx LLDP frames | * ice_del_rx_lldp_filter - Remove ethertype filter for Rx LLDP frames | ||||
* @sc: the device private structure | * @sc: the device private structure | ||||
* | * | ||||
* Remove the switch filter forwarding LLDP frames to the main PF VSI, called | * Remove the switch filter forwarding LLDP frames to the main PF VSI, called | ||||
* when the firmware LLDP agent is enabled, to stop routing LLDP frames to the | * when the firmware LLDP agent is enabled, to stop routing LLDP frames to the | ||||
* stack. | * stack. | ||||
*/ | */ | ||||
static void | static void | ||||
ice_del_rx_lldp_filter(struct ice_softc *sc) | ice_del_rx_lldp_filter(struct ice_softc *sc) | ||||
{ | { | ||||
struct ice_list_head ethertype_list; | struct ice_list_head ethertype_list; | ||||
struct ice_vsi *vsi = &sc->pf_vsi; | struct ice_vsi *vsi = &sc->pf_vsi; | ||||
struct ice_hw *hw = &sc->hw; | struct ice_hw *hw = &sc->hw; | ||||
device_t dev = sc->dev; | device_t dev = sc->dev; | ||||
enum ice_status status; | enum ice_status status; | ||||
int err; | int err; | ||||
u16 vsi_num; | |||||
/* | |||||
* Only in the scenario where the driver added the filter during | |||||
* this session (while the driver was loaded) would we be able to | |||||
* delete this filter. | |||||
*/ | |||||
if (!ice_test_state(&sc->state, ICE_STATE_LLDP_RX_FLTR_FROM_DRIVER)) | |||||
return; | |||||
/* | |||||
* If FW is new enough, use a direct AQ command to perform the filter | |||||
* removal. | |||||
*/ | |||||
if (ice_fw_supports_lldp_fltr_ctrl(hw)) { | |||||
vsi_num = ice_get_hw_vsi_num(hw, vsi->idx); | |||||
status = ice_lldp_fltr_add_remove(hw, vsi_num, false); | |||||
if (status) { | |||||
device_printf(dev, | |||||
"Failed to remove Rx LLDP filter, err %s aq_err %s\n", | |||||
ice_status_str(status), | |||||
ice_aq_str(hw->adminq.sq_last_status)); | |||||
} | |||||
return; | |||||
} | |||||
INIT_LIST_HEAD(ðertype_list); | INIT_LIST_HEAD(ðertype_list); | ||||
/* Remove filter forwarding Rx LLDP frames to the stack */ | /* Remove filter forwarding Rx LLDP frames to the stack */ | ||||
err = ice_add_ethertype_to_list(vsi, ðertype_list, | err = ice_add_ethertype_to_list(vsi, ðertype_list, | ||||
ETHERTYPE_LLDP_FRAMES, | ETHERTYPE_LLDP_FRAMES, | ||||
ICE_FLTR_RX, ICE_FWD_TO_VSI); | ICE_FLTR_RX, ICE_FWD_TO_VSI); | ||||
if (err) { | if (err) { | ||||
device_printf(dev, | device_printf(dev, | ||||
▲ Show 20 Lines • Show All 514 Lines • ▼ Show 20 Lines | |||||
* and SFF-8024 (both). | * and SFF-8024 (both). | ||||
*/ | */ | ||||
int | int | ||||
ice_read_sff_eeprom(struct ice_softc *sc, u16 dev_addr, u16 offset, u8* data, u16 length) | ice_read_sff_eeprom(struct ice_softc *sc, u16 dev_addr, u16 offset, u8* data, u16 length) | ||||
{ | { | ||||
struct ice_hw *hw = &sc->hw; | struct ice_hw *hw = &sc->hw; | ||||
int error = 0, retries = 0; | int error = 0, retries = 0; | ||||
enum ice_status status; | enum ice_status status; | ||||
u16 lport; | |||||
if (length > 16) | if (length > 16) | ||||
return (EINVAL); | return (EINVAL); | ||||
if (ice_test_state(&sc->state, ICE_STATE_RECOVERY_MODE)) | if (ice_test_state(&sc->state, ICE_STATE_RECOVERY_MODE)) | ||||
return (ENOSYS); | return (ENOSYS); | ||||
if (ice_test_state(&sc->state, ICE_STATE_NO_MEDIA)) | if (ice_test_state(&sc->state, ICE_STATE_NO_MEDIA)) | ||||
return (ENXIO); | return (ENXIO); | ||||
/* Set bit to indicate lport value is valid */ | |||||
lport = hw->port_info->lport | (0x1 << 8); | |||||
do { | do { | ||||
status = ice_aq_sff_eeprom(hw, lport, dev_addr, | status = ice_aq_sff_eeprom(hw, 0, dev_addr, | ||||
offset, 0, 0, data, length, | offset, 0, 0, data, length, | ||||
false, NULL); | false, NULL); | ||||
if (!status) { | if (!status) { | ||||
error = 0; | error = 0; | ||||
break; | break; | ||||
} | } | ||||
if (status == ICE_ERR_AQ_ERROR && | if (status == ICE_ERR_AQ_ERROR && | ||||
hw->adminq.sq_last_status == ICE_AQ_RC_EBUSY) { | hw->adminq.sq_last_status == ICE_AQ_RC_EBUSY) { | ||||
▲ Show 20 Lines • Show All 272 Lines • ▼ Show 20 Lines | device_printf(dev, | ||||
ice_aq_str(sc->hw.adminq.sq_last_status)); | ice_aq_str(sc->hw.adminq.sq_last_status)); | ||||
return (status); | return (status); | ||||
} | } | ||||
*phy_type_low = le64toh(pcaps.phy_type_low); | *phy_type_low = le64toh(pcaps.phy_type_low); | ||||
*phy_type_high = le64toh(pcaps.phy_type_high); | *phy_type_high = le64toh(pcaps.phy_type_high); | ||||
return (ICE_SUCCESS); | return (ICE_SUCCESS); | ||||
} | |||||
/** | |||||
* ice_set_default_local_lldp_mib - Set Local LLDP MIB to default settings | |||||
* @sc: device softc structure | |||||
* | |||||
* This function needs to be called after link up; it makes sure the FW | |||||
* has certain PFC/DCB settings. This is intended to workaround a FW behavior | |||||
* where these settings seem to be cleared on link up. | |||||
*/ | |||||
void | |||||
ice_set_default_local_lldp_mib(struct ice_softc *sc) | |||||
{ | |||||
struct ice_dcbx_cfg *dcbcfg; | |||||
struct ice_hw *hw = &sc->hw; | |||||
struct ice_port_info *pi; | |||||
device_t dev = sc->dev; | |||||
enum ice_status status; | |||||
pi = hw->port_info; | |||||
dcbcfg = &pi->qos_cfg.local_dcbx_cfg; | |||||
/* This value is only 3 bits; 8 TCs maps to 0 */ | |||||
u8 maxtcs = hw->func_caps.common_cap.maxtc & ICE_IEEE_ETS_MAXTC_M; | |||||
/** | |||||
* Setup the default settings used by the driver for the Set Local | |||||
* LLDP MIB Admin Queue command (0x0A08). (1TC w/ 100% BW, ETS, no | |||||
* PFC). | |||||
*/ | |||||
memset(dcbcfg, 0, sizeof(*dcbcfg)); | |||||
dcbcfg->etscfg.willing = 1; | |||||
dcbcfg->etscfg.tcbwtable[0] = 100; | |||||
dcbcfg->etscfg.maxtcs = maxtcs; | |||||
dcbcfg->etsrec.willing = 1; | |||||
dcbcfg->etsrec.tcbwtable[0] = 100; | |||||
dcbcfg->etsrec.maxtcs = maxtcs; | |||||
dcbcfg->pfc.willing = 1; | |||||
dcbcfg->pfc.pfccap = maxtcs; | |||||
status = ice_set_dcb_cfg(pi); | |||||
if (status) | |||||
device_printf(dev, | |||||
"Error setting Local LLDP MIB: %s aq_err %s\n", | |||||
ice_status_str(status), | |||||
ice_aq_str(hw->adminq.sq_last_status)); | |||||
} | } |