#include "mcdi_mon.h"
#endif
-#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
+#if EFX_OPTS_EF10()
#include "ef10_tlv_layout.h"
__out uint32_t *portp)
{
efx_mcdi_req_t req;
- uint8_t payload[MAX(MC_CMD_GET_PORT_ASSIGNMENT_IN_LEN,
- MC_CMD_GET_PORT_ASSIGNMENT_OUT_LEN)];
+ EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_PORT_ASSIGNMENT_IN_LEN,
+ MC_CMD_GET_PORT_ASSIGNMENT_OUT_LEN);
efx_rc_t rc;
- EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
- enp->en_family == EFX_FAMILY_MEDFORD ||
- enp->en_family == EFX_FAMILY_MEDFORD2);
+ EFSYS_ASSERT(EFX_FAMILY_IS_EF10(enp));
- (void) memset(payload, 0, sizeof (payload));
req.emr_cmd = MC_CMD_GET_PORT_ASSIGNMENT;
req.emr_in_buf = payload;
req.emr_in_length = MC_CMD_GET_PORT_ASSIGNMENT_IN_LEN;
efx_mcdi_get_port_modes(
__in efx_nic_t *enp,
__out uint32_t *modesp,
- __out_opt uint32_t *current_modep)
+ __out_opt uint32_t *current_modep,
+ __out_opt uint32_t *default_modep)
{
efx_mcdi_req_t req;
- uint8_t payload[MAX(MC_CMD_GET_PORT_MODES_IN_LEN,
- MC_CMD_GET_PORT_MODES_OUT_LEN)];
+ EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_PORT_MODES_IN_LEN,
+ MC_CMD_GET_PORT_MODES_OUT_LEN);
efx_rc_t rc;
- EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
- enp->en_family == EFX_FAMILY_MEDFORD ||
- enp->en_family == EFX_FAMILY_MEDFORD2);
+ EFSYS_ASSERT(EFX_FAMILY_IS_EF10(enp));
- (void) memset(payload, 0, sizeof (payload));
req.emr_cmd = MC_CMD_GET_PORT_MODES;
req.emr_in_buf = payload;
req.emr_in_length = MC_CMD_GET_PORT_MODES_IN_LEN;
GET_PORT_MODES_OUT_CURRENT_MODE);
}
+ if (default_modep != NULL) {
+ *default_modep = MCDI_OUT_DWORD(req,
+ GET_PORT_MODES_OUT_DEFAULT_MODE);
+ }
+
return (0);
fail3:
__checkReturn efx_rc_t
ef10_nic_get_port_mode_bandwidth(
- __in uint32_t port_mode,
+ __in efx_nic_t *enp,
__out uint32_t *bandwidth_mbpsp)
{
+ uint32_t port_modes;
+ uint32_t current_mode;
+ efx_port_t *epp = &(enp->en_port);
+
+ uint32_t single_lane;
+ uint32_t dual_lane;
+ uint32_t quad_lane;
uint32_t bandwidth;
efx_rc_t rc;
- switch (port_mode) {
- case TLV_PORT_MODE_10G:
- bandwidth = 10000;
+ if ((rc = efx_mcdi_get_port_modes(enp, &port_modes,
+ ¤t_mode, NULL)) != 0) {
+ /* No port mode info available. */
+ goto fail1;
+ }
+
+ if (epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_25000FDX))
+ single_lane = 25000;
+ else
+ single_lane = 10000;
+
+ if (epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_50000FDX))
+ dual_lane = 50000;
+ else
+ dual_lane = 20000;
+
+ if (epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_100000FDX))
+ quad_lane = 100000;
+ else
+ quad_lane = 40000;
+
+ switch (current_mode) {
+ case TLV_PORT_MODE_1x1_NA: /* mode 0 */
+ bandwidth = single_lane;
+ break;
+ case TLV_PORT_MODE_1x2_NA: /* mode 10 */
+ case TLV_PORT_MODE_NA_1x2: /* mode 11 */
+ bandwidth = dual_lane;
+ break;
+ case TLV_PORT_MODE_1x1_1x1: /* mode 2 */
+ bandwidth = single_lane + single_lane;
break;
- case TLV_PORT_MODE_10G_10G:
- bandwidth = 10000 * 2;
+ case TLV_PORT_MODE_4x1_NA: /* mode 4 */
+ case TLV_PORT_MODE_NA_4x1: /* mode 8 */
+ bandwidth = 4 * single_lane;
break;
- case TLV_PORT_MODE_10G_10G_10G_10G:
- case TLV_PORT_MODE_10G_10G_10G_10G_Q:
- case TLV_PORT_MODE_10G_10G_10G_10G_Q1_Q2:
- case TLV_PORT_MODE_10G_10G_10G_10G_Q2:
- bandwidth = 10000 * 4;
+ case TLV_PORT_MODE_2x1_2x1: /* mode 5 */
+ bandwidth = (2 * single_lane) + (2 * single_lane);
break;
- case TLV_PORT_MODE_40G:
- bandwidth = 40000;
+ case TLV_PORT_MODE_1x2_1x2: /* mode 12 */
+ bandwidth = dual_lane + dual_lane;
break;
- case TLV_PORT_MODE_40G_40G:
- bandwidth = 40000 * 2;
+ case TLV_PORT_MODE_1x2_2x1: /* mode 17 */
+ case TLV_PORT_MODE_2x1_1x2: /* mode 18 */
+ bandwidth = dual_lane + (2 * single_lane);
break;
- case TLV_PORT_MODE_40G_10G_10G:
- case TLV_PORT_MODE_10G_10G_40G:
- bandwidth = 40000 + (10000 * 2);
+ /* Legacy Medford-only mode. Do not use (see bug63270) */
+ case TLV_PORT_MODE_10G_10G_10G_10G_Q1_Q2: /* mode 9 */
+ bandwidth = 4 * single_lane;
+ break;
+ case TLV_PORT_MODE_1x4_NA: /* mode 1 */
+ case TLV_PORT_MODE_NA_1x4: /* mode 22 */
+ bandwidth = quad_lane;
+ break;
+ case TLV_PORT_MODE_2x2_NA: /* mode 13 */
+ case TLV_PORT_MODE_NA_2x2: /* mode 14 */
+ bandwidth = 2 * dual_lane;
+ break;
+ case TLV_PORT_MODE_1x4_2x1: /* mode 6 */
+ case TLV_PORT_MODE_2x1_1x4: /* mode 7 */
+ bandwidth = quad_lane + (2 * single_lane);
+ break;
+ case TLV_PORT_MODE_1x4_1x2: /* mode 15 */
+ case TLV_PORT_MODE_1x2_1x4: /* mode 16 */
+ bandwidth = quad_lane + dual_lane;
+ break;
+ case TLV_PORT_MODE_1x4_1x4: /* mode 3 */
+ bandwidth = quad_lane + quad_lane;
break;
default:
rc = EINVAL;
- goto fail1;
+ goto fail2;
}
*bandwidth_mbpsp = bandwidth;
return (0);
+fail2:
+ EFSYS_PROBE(fail2);
fail1:
EFSYS_PROBE1(fail1, efx_rc_t, rc);
return (rc);
}
-static __checkReturn efx_rc_t
+ __checkReturn efx_rc_t
efx_mcdi_vadaptor_alloc(
__in efx_nic_t *enp,
__in uint32_t port_id)
{
efx_mcdi_req_t req;
- uint8_t payload[MAX(MC_CMD_VADAPTOR_ALLOC_IN_LEN,
- MC_CMD_VADAPTOR_ALLOC_OUT_LEN)];
+ EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VADAPTOR_ALLOC_IN_LEN,
+ MC_CMD_VADAPTOR_ALLOC_OUT_LEN);
efx_rc_t rc;
- EFSYS_ASSERT3U(enp->en_vport_id, ==, EVB_PORT_ID_NULL);
-
- (void) memset(payload, 0, sizeof (payload));
req.emr_cmd = MC_CMD_VADAPTOR_ALLOC;
req.emr_in_buf = payload;
req.emr_in_length = MC_CMD_VADAPTOR_ALLOC_IN_LEN;
return (rc);
}
-static __checkReturn efx_rc_t
+ __checkReturn efx_rc_t
efx_mcdi_vadaptor_free(
__in efx_nic_t *enp,
__in uint32_t port_id)
{
efx_mcdi_req_t req;
- uint8_t payload[MAX(MC_CMD_VADAPTOR_FREE_IN_LEN,
- MC_CMD_VADAPTOR_FREE_OUT_LEN)];
+ EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VADAPTOR_FREE_IN_LEN,
+ MC_CMD_VADAPTOR_FREE_OUT_LEN);
efx_rc_t rc;
- (void) memset(payload, 0, sizeof (payload));
req.emr_cmd = MC_CMD_VADAPTOR_FREE;
req.emr_in_buf = payload;
req.emr_in_length = MC_CMD_VADAPTOR_FREE_IN_LEN;
__out_ecount_opt(6) uint8_t mac_addrp[6])
{
efx_mcdi_req_t req;
- uint8_t payload[MAX(MC_CMD_GET_MAC_ADDRESSES_IN_LEN,
- MC_CMD_GET_MAC_ADDRESSES_OUT_LEN)];
+ EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_MAC_ADDRESSES_IN_LEN,
+ MC_CMD_GET_MAC_ADDRESSES_OUT_LEN);
efx_rc_t rc;
- EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
- enp->en_family == EFX_FAMILY_MEDFORD ||
- enp->en_family == EFX_FAMILY_MEDFORD2);
+ EFSYS_ASSERT(EFX_FAMILY_IS_EF10(enp));
- (void) memset(payload, 0, sizeof (payload));
req.emr_cmd = MC_CMD_GET_MAC_ADDRESSES;
req.emr_in_buf = payload;
req.emr_in_length = MC_CMD_GET_MAC_ADDRESSES_IN_LEN;
__out_ecount_opt(6) uint8_t mac_addrp[6])
{
efx_mcdi_req_t req;
- uint8_t payload[MAX(MC_CMD_VPORT_GET_MAC_ADDRESSES_IN_LEN,
- MC_CMD_VPORT_GET_MAC_ADDRESSES_OUT_LENMAX)];
+ EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VPORT_GET_MAC_ADDRESSES_IN_LEN,
+ MC_CMD_VPORT_GET_MAC_ADDRESSES_OUT_LENMAX);
efx_rc_t rc;
- EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
- enp->en_family == EFX_FAMILY_MEDFORD ||
- enp->en_family == EFX_FAMILY_MEDFORD2);
+ EFSYS_ASSERT(EFX_FAMILY_IS_EF10(enp));
- (void) memset(payload, 0, sizeof (payload));
req.emr_cmd = MC_CMD_VPORT_GET_MAC_ADDRESSES;
req.emr_in_buf = payload;
req.emr_in_length = MC_CMD_VPORT_GET_MAC_ADDRESSES_IN_LEN;
__out uint32_t *dpcpu_freqp)
{
efx_mcdi_req_t req;
- uint8_t payload[MAX(MC_CMD_GET_CLOCK_IN_LEN,
- MC_CMD_GET_CLOCK_OUT_LEN)];
+ EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_CLOCK_IN_LEN,
+ MC_CMD_GET_CLOCK_OUT_LEN);
efx_rc_t rc;
- EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
- enp->en_family == EFX_FAMILY_MEDFORD ||
- enp->en_family == EFX_FAMILY_MEDFORD2);
+ EFSYS_ASSERT(EFX_FAMILY_IS_EF10(enp));
- (void) memset(payload, 0, sizeof (payload));
req.emr_cmd = MC_CMD_GET_CLOCK;
req.emr_in_buf = payload;
req.emr_in_length = MC_CMD_GET_CLOCK_IN_LEN;
__out uint32_t *end_paddingp)
{
efx_mcdi_req_t req;
- uint8_t payload[MAX(MC_CMD_GET_RXDP_CONFIG_IN_LEN,
- MC_CMD_GET_RXDP_CONFIG_OUT_LEN)];
+ EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_RXDP_CONFIG_IN_LEN,
+ MC_CMD_GET_RXDP_CONFIG_OUT_LEN);
uint32_t end_padding;
efx_rc_t rc;
- memset(payload, 0, sizeof (payload));
req.emr_cmd = MC_CMD_GET_RXDP_CONFIG;
req.emr_in_buf = payload;
req.emr_in_length = MC_CMD_GET_RXDP_CONFIG_IN_LEN;
__out_opt uint32_t *vf_nvecp)
{
efx_mcdi_req_t req;
- uint8_t payload[MAX(MC_CMD_GET_VECTOR_CFG_IN_LEN,
- MC_CMD_GET_VECTOR_CFG_OUT_LEN)];
+ EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_VECTOR_CFG_IN_LEN,
+ MC_CMD_GET_VECTOR_CFG_OUT_LEN);
efx_rc_t rc;
- (void) memset(payload, 0, sizeof (payload));
req.emr_cmd = MC_CMD_GET_VECTOR_CFG;
req.emr_in_buf = payload;
req.emr_in_length = MC_CMD_GET_VECTOR_CFG_IN_LEN;
__out uint32_t *vi_shiftp)
{
efx_mcdi_req_t req;
- uint8_t payload[MAX(MC_CMD_ALLOC_VIS_IN_LEN,
- MC_CMD_ALLOC_VIS_EXT_OUT_LEN)];
+ EFX_MCDI_DECLARE_BUF(payload, MC_CMD_ALLOC_VIS_IN_LEN,
+ MC_CMD_ALLOC_VIS_EXT_OUT_LEN);
efx_rc_t rc;
if (vi_countp == NULL) {
goto fail1;
}
- (void) memset(payload, 0, sizeof (payload));
req.emr_cmd = MC_CMD_ALLOC_VIS;
req.emr_in_buf = payload;
req.emr_in_length = MC_CMD_ALLOC_VIS_IN_LEN;
__out efx_piobuf_handle_t *handlep)
{
efx_mcdi_req_t req;
- uint8_t payload[MAX(MC_CMD_ALLOC_PIOBUF_IN_LEN,
- MC_CMD_ALLOC_PIOBUF_OUT_LEN)];
+ EFX_MCDI_DECLARE_BUF(payload, MC_CMD_ALLOC_PIOBUF_IN_LEN,
+ MC_CMD_ALLOC_PIOBUF_OUT_LEN);
efx_rc_t rc;
if (handlep == NULL) {
goto fail1;
}
- (void) memset(payload, 0, sizeof (payload));
req.emr_cmd = MC_CMD_ALLOC_PIOBUF;
req.emr_in_buf = payload;
req.emr_in_length = MC_CMD_ALLOC_PIOBUF_IN_LEN;
__in efx_piobuf_handle_t handle)
{
efx_mcdi_req_t req;
- uint8_t payload[MAX(MC_CMD_FREE_PIOBUF_IN_LEN,
- MC_CMD_FREE_PIOBUF_OUT_LEN)];
+ EFX_MCDI_DECLARE_BUF(payload, MC_CMD_FREE_PIOBUF_IN_LEN,
+ MC_CMD_FREE_PIOBUF_OUT_LEN);
efx_rc_t rc;
- (void) memset(payload, 0, sizeof (payload));
req.emr_cmd = MC_CMD_FREE_PIOBUF;
req.emr_in_buf = payload;
req.emr_in_length = MC_CMD_FREE_PIOBUF_IN_LEN;
__in efx_piobuf_handle_t handle)
{
efx_mcdi_req_t req;
- uint8_t payload[MAX(MC_CMD_LINK_PIOBUF_IN_LEN,
- MC_CMD_LINK_PIOBUF_OUT_LEN)];
+ EFX_MCDI_DECLARE_BUF(payload, MC_CMD_LINK_PIOBUF_IN_LEN,
+ MC_CMD_LINK_PIOBUF_OUT_LEN);
efx_rc_t rc;
- (void) memset(payload, 0, sizeof (payload));
req.emr_cmd = MC_CMD_LINK_PIOBUF;
req.emr_in_buf = payload;
req.emr_in_length = MC_CMD_LINK_PIOBUF_IN_LEN;
__in uint32_t vi_index)
{
efx_mcdi_req_t req;
- uint8_t payload[MAX(MC_CMD_UNLINK_PIOBUF_IN_LEN,
- MC_CMD_UNLINK_PIOBUF_OUT_LEN)];
+ EFX_MCDI_DECLARE_BUF(payload, MC_CMD_UNLINK_PIOBUF_IN_LEN,
+ MC_CMD_UNLINK_PIOBUF_OUT_LEN);
efx_rc_t rc;
- (void) memset(payload, 0, sizeof (payload));
req.emr_cmd = MC_CMD_UNLINK_PIOBUF;
req.emr_in_buf = payload;
req.emr_in_length = MC_CMD_UNLINK_PIOBUF_IN_LEN;
for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) {
handlep = &enp->en_arch.ef10.ena_piobuf_handle[i];
- efx_mcdi_free_piobuf(enp, *handlep);
+ (void) efx_mcdi_free_piobuf(enp, *handlep);
*handlep = EFX_PIOBUF_HANDLE_INVALID;
}
enp->en_arch.ef10.ena_piobuf_count = 0;
for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) {
handlep = &enp->en_arch.ef10.ena_piobuf_handle[i];
- efx_mcdi_free_piobuf(enp, *handlep);
+ (void) efx_mcdi_free_piobuf(enp, *handlep);
*handlep = EFX_PIOBUF_HANDLE_INVALID;
}
enp->en_arch.ef10.ena_piobuf_count = 0;
uint32_t buf, blk;
efx_rc_t rc;
- EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
- enp->en_family == EFX_FAMILY_MEDFORD ||
- enp->en_family == EFX_FAMILY_MEDFORD2);
+ EFSYS_ASSERT(EFX_FAMILY_IS_EF10(enp));
EFSYS_ASSERT(bufnump);
EFSYS_ASSERT(handlep);
EFSYS_ASSERT(blknump);
__out uint32_t *pf_countp)
{
efx_mcdi_req_t req;
- uint8_t payload[MAX(MC_CMD_GET_PF_COUNT_IN_LEN,
- MC_CMD_GET_PF_COUNT_OUT_LEN)];
+ EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_PF_COUNT_IN_LEN,
+ MC_CMD_GET_PF_COUNT_OUT_LEN);
efx_rc_t rc;
- (void) memset(payload, 0, sizeof (payload));
req.emr_cmd = MC_CMD_GET_PF_COUNT;
req.emr_in_buf = payload;
req.emr_in_length = MC_CMD_GET_PF_COUNT_IN_LEN;
{
efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
efx_mcdi_req_t req;
- uint8_t payload[MAX(MC_CMD_GET_CAPABILITIES_IN_LEN,
- MC_CMD_GET_CAPABILITIES_V4_OUT_LEN)];
+ EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_CAPABILITIES_IN_LEN,
+ MC_CMD_GET_CAPABILITIES_V5_OUT_LEN);
efx_rc_t rc;
if ((rc = ef10_mcdi_get_pf_count(enp, &encp->enc_hw_pf_count)) != 0)
goto fail1;
- (void) memset(payload, 0, sizeof (payload));
req.emr_cmd = MC_CMD_GET_CAPABILITIES;
req.emr_in_buf = payload;
req.emr_in_length = MC_CMD_GET_CAPABILITIES_IN_LEN;
req.emr_out_buf = payload;
- req.emr_out_length = MC_CMD_GET_CAPABILITIES_V4_OUT_LEN;
+ req.emr_out_length = MC_CMD_GET_CAPABILITIES_V5_OUT_LEN;
efx_mcdi_execute_quiet(enp, &req);
}
encp->enc_rx_prefix_size = 14;
+#if EFSYS_OPT_RX_SCALE
+ /* Check if the firmware supports additional RSS modes */
+ if (CAP_FLAGS1(req, ADDITIONAL_RSS_MODES))
+ encp->enc_rx_scale_additional_modes_supported = B_TRUE;
+ else
+ encp->enc_rx_scale_additional_modes_supported = B_FALSE;
+#endif /* EFSYS_OPT_RX_SCALE */
+
/* Check if the firmware supports TSO */
if (CAP_FLAGS1(req, TX_TSO))
encp->enc_fw_assisted_tso_enabled = B_TRUE;
encp->enc_fw_assisted_tso_v2_n_contexts = 0;
}
+ /* Check if the firmware supports FATSOv2 encap */
+ if (CAP_FLAGS2(req, TX_TSO_V2_ENCAP))
+ encp->enc_fw_assisted_tso_v2_encap_enabled = B_TRUE;
+ else
+ encp->enc_fw_assisted_tso_v2_encap_enabled = B_FALSE;
+
/* Check if the firmware has vadapter/vport/vswitch support */
if (CAP_FLAGS1(req, EVB))
encp->enc_datapath_cap_evb = B_TRUE;
else
encp->enc_datapath_cap_evb = B_FALSE;
+ /* Check if the firmware supports vport reconfiguration */
+ if (CAP_FLAGS1(req, VPORT_RECONFIGURE))
+ encp->enc_vport_reconfigure_supported = B_TRUE;
+ else
+ encp->enc_vport_reconfigure_supported = B_FALSE;
+
/* Check if the firmware supports VLAN insertion */
if (CAP_FLAGS1(req, TX_VLAN_INSERTION))
encp->enc_hw_tx_insert_vlan_enabled = B_TRUE;
else
encp->enc_rx_var_packed_stream_supported = B_FALSE;
+ /* Check if the firmware supports equal stride super-buffer mode */
+ if (CAP_FLAGS2(req, EQUAL_STRIDE_SUPER_BUFFER))
+ encp->enc_rx_es_super_buffer_supported = B_TRUE;
+ else
+ encp->enc_rx_es_super_buffer_supported = B_FALSE;
+
+ /* Check if the firmware supports FW subvariant w/o Tx checksumming */
+ if (CAP_FLAGS2(req, FW_SUBVARIANT_NO_TX_CSUM))
+ encp->enc_fw_subvariant_no_tx_csum_supported = B_TRUE;
+ else
+ encp->enc_fw_subvariant_no_tx_csum_supported = B_FALSE;
+
/* Check if the firmware supports set mac with running filters */
if (CAP_FLAGS1(req, VADAPTOR_PERMIT_SET_MAC_WHEN_FILTERS_INSTALLED))
encp->enc_allow_set_mac_with_installed_filters = B_TRUE;
else
encp->enc_init_evq_v2_supported = B_FALSE;
+ /*
+ * Check if the NO_CONT_EV mode for RX events is supported.
+ */
+ if (CAP_FLAGS2(req, INIT_RXQ_NO_CONT_EV))
+ encp->enc_no_cont_ev_mode_supported = B_TRUE;
+ else
+ encp->enc_no_cont_ev_mode_supported = B_FALSE;
+
+ /*
+ * Check if buffer size may and must be specified on INIT_RXQ.
+ * It may be always specified to efx_rx_qcreate(), but will be
+ * just kept libefx internal if MCDI does not support it.
+ */
+ if (CAP_FLAGS2(req, INIT_RXQ_WITH_BUFFER_SIZE))
+ encp->enc_init_rxq_with_buffer_size = B_TRUE;
+ else
+ encp->enc_init_rxq_with_buffer_size = B_FALSE;
+
/*
* Check if firmware-verified NVRAM updates must be used.
*
else
encp->enc_nvram_update_verify_result_supported = B_FALSE;
+ if (CAP_FLAGS2(req, NVRAM_UPDATE_POLL_VERIFY_RESULT))
+ encp->enc_nvram_update_poll_verify_result_supported = B_TRUE;
+ else
+ encp->enc_nvram_update_poll_verify_result_supported = B_FALSE;
+
+ /*
+ * Check if firmware update via the BUNDLE partition is supported
+ */
+ if (CAP_FLAGS2(req, BUNDLE_UPDATE))
+ encp->enc_nvram_bundle_update_supported = B_TRUE;
+ else
+ encp->enc_nvram_bundle_update_supported = B_FALSE;
+
/*
* Check if firmware provides packet memory and Rx datapath
* counters.
else
encp->enc_fec_counters = B_FALSE;
+ /* Check if the firmware provides head-of-line blocking counters */
+ if (CAP_FLAGS2(req, RXDP_HLB_IDLE))
+ encp->enc_hlb_counters = B_TRUE;
+ else
+ encp->enc_hlb_counters = B_FALSE;
+
+#if EFSYS_OPT_RX_SCALE
+ if (CAP_FLAGS1(req, RX_RSS_LIMITED)) {
+ /* Only one exclusive RSS context is available per port. */
+ encp->enc_rx_scale_max_exclusive_contexts = 1;
+
+ switch (enp->en_family) {
+ case EFX_FAMILY_MEDFORD2:
+ encp->enc_rx_scale_hash_alg_mask =
+ (1U << EFX_RX_HASHALG_TOEPLITZ);
+ break;
+
+ case EFX_FAMILY_MEDFORD:
+ case EFX_FAMILY_HUNTINGTON:
+ /*
+ * Packed stream firmware variant maintains a
+ * non-standard algorithm for hash computation.
+ * It implies explicit XORing together
+ * source + destination IP addresses (or last
+ * four bytes in the case of IPv6) and using the
+ * resulting value as the input to a Toeplitz hash.
+ */
+ encp->enc_rx_scale_hash_alg_mask =
+ (1U << EFX_RX_HASHALG_PACKED_STREAM);
+ break;
+
+ default:
+ rc = EINVAL;
+ goto fail5;
+ }
+
+ /* Port numbers cannot contribute to the hash value */
+ encp->enc_rx_scale_l4_hash_supported = B_FALSE;
+ } else {
+ /*
+ * Maximum number of exclusive RSS contexts.
+ * EF10 hardware supports 64 in total, but 6 are reserved
+ * for shared contexts. They are a global resource so
+ * not all may be available.
+ */
+ encp->enc_rx_scale_max_exclusive_contexts = 64 - 6;
+
+ encp->enc_rx_scale_hash_alg_mask =
+ (1U << EFX_RX_HASHALG_TOEPLITZ);
+
+ /*
+ * It is possible to use port numbers as
+ * the input data for hash computation.
+ */
+ encp->enc_rx_scale_l4_hash_supported = B_TRUE;
+ }
+#endif /* EFSYS_OPT_RX_SCALE */
+
+ /* Check if the firmware supports "FLAG" and "MARK" filter actions */
+ if (CAP_FLAGS2(req, FILTER_ACTION_FLAG))
+ encp->enc_filter_action_flag_supported = B_TRUE;
+ else
+ encp->enc_filter_action_flag_supported = B_FALSE;
+
+ if (CAP_FLAGS2(req, FILTER_ACTION_MARK))
+ encp->enc_filter_action_mark_supported = B_TRUE;
+ else
+ encp->enc_filter_action_mark_supported = B_FALSE;
+
+ /* Get maximum supported value for "MARK" filter action */
+ if (req.emr_out_length_used >= MC_CMD_GET_CAPABILITIES_V5_OUT_LEN)
+ encp->enc_filter_action_mark_max = MCDI_OUT_DWORD(req,
+ GET_CAPABILITIES_V5_OUT_FILTER_ACTION_MARK_MAX);
+ else
+ encp->enc_filter_action_mark_max = 0;
+
#undef CAP_FLAGS1
#undef CAP_FLAGS2
return (0);
+#if EFSYS_OPT_RX_SCALE
+fail5:
+ EFSYS_PROBE(fail5);
+#endif /* EFSYS_OPT_RX_SCALE */
fail4:
EFSYS_PROBE(fail4);
fail3:
}
+#define EFX_EXT_PORT_MAX 4
+#define EFX_EXT_PORT_NA 0xFF
+
/*
* Table of mapping schemes from port number to external number.
*
* port mapping (n:1)
* |
* v
- * External port number (normally 1-based)
+ * External port number (1-based)
* |
* fixed (1:1) or cable assembly (1:m)
* |
* how to determine which external cage/magjack corresponds to the port
* numbers used by the driver.
*
- * The count of adjacent port numbers that map to each external number,
- * and the offset in the numbering, is determined by the chip family and
- * current port mode.
+ * The count of consecutive port numbers that map to each external number,
+ * is determined by the chip family and the current port mode.
*
* For the Huntington family, the current port mode cannot be discovered,
* but a single mapping is used by all modes for a given chip variant,
static struct ef10_external_port_map_s {
efx_family_t family;
uint32_t modes_mask;
- int32_t count;
- int32_t offset;
+ uint8_t base_port[EFX_EXT_PORT_MAX];
} __ef10_external_port_mappings[] = {
/*
* Modes used by Huntington family controllers where each port
(1U << TLV_PORT_MODE_10G) | /* mode 0 */
(1U << TLV_PORT_MODE_10G_10G) | /* mode 2 */
(1U << TLV_PORT_MODE_10G_10G_10G_10G), /* mode 4 */
- 1, /* ports per cage */
- 1 /* first cage */
+ { 0, 1, 2, 3 }
},
/*
* Modes which for Huntington identify a chip variant where 2
(1U << TLV_PORT_MODE_40G_40G) | /* mode 3 */
(1U << TLV_PORT_MODE_40G_10G_10G) | /* mode 6 */
(1U << TLV_PORT_MODE_10G_10G_40G), /* mode 7 */
- 2, /* ports per cage */
- 1 /* first cage */
+ { 0, 2, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA }
},
/*
* Modes that on Medford allocate each port number to a separate
*/
{
EFX_FAMILY_MEDFORD,
- (1U << TLV_PORT_MODE_10G) | /* mode 0 */
- (1U << TLV_PORT_MODE_10G_10G), /* mode 2 */
- 1, /* ports per cage */
- 1 /* first cage */
+ (1U << TLV_PORT_MODE_1x1_NA) | /* mode 0 */
+ (1U << TLV_PORT_MODE_1x4_NA) | /* mode 1 */
+ (1U << TLV_PORT_MODE_1x1_1x1), /* mode 2 */
+ { 0, 1, 2, 3 }
},
/*
* Modes that on Medford allocate 2 adjacent port numbers to each
*/
{
EFX_FAMILY_MEDFORD,
- (1U << TLV_PORT_MODE_40G) | /* mode 1 */
- (1U << TLV_PORT_MODE_40G_40G) | /* mode 3 */
- (1U << TLV_PORT_MODE_40G_10G_10G) | /* mode 6 */
- (1U << TLV_PORT_MODE_10G_10G_40G) | /* mode 7 */
+ (1U << TLV_PORT_MODE_1x4_1x4) | /* mode 3 */
+ (1U << TLV_PORT_MODE_2x1_2x1) | /* mode 5 */
+ (1U << TLV_PORT_MODE_1x4_2x1) | /* mode 6 */
+ (1U << TLV_PORT_MODE_2x1_1x4) | /* mode 7 */
/* Do not use 10G_10G_10G_10G_Q1_Q2 (see bug63270) */
(1U << TLV_PORT_MODE_10G_10G_10G_10G_Q1_Q2), /* mode 9 */
- 2, /* ports per cage */
- 1 /* first cage */
+ { 0, 2, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA }
},
/*
- * Modes that on Medford allocate 4 adjacent port numbers to each
- * connector, starting on cage 1.
+ * Modes that on Medford allocate 4 adjacent port numbers to
+ * cage 1.
* port 0 -> cage 1
* port 1 -> cage 1
* port 2 -> cage 1
*/
{
EFX_FAMILY_MEDFORD,
- (1U << TLV_PORT_MODE_10G_10G_10G_10G_Q) | /* mode 5 */
/* Do not use 10G_10G_10G_10G_Q1 (see bug63270) */
- (1U << TLV_PORT_MODE_10G_10G_10G_10G_Q1), /* mode 4 */
- 4, /* ports per cage */
- 1 /* first cage */
+ (1U << TLV_PORT_MODE_4x1_NA), /* mode 4 */
+ { 0, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA }
},
/*
- * Modes that on Medford allocate 4 adjacent port numbers to each
- * connector, starting on cage 2.
+ * Modes that on Medford allocate 4 adjacent port numbers to
+ * cage 2.
* port 0 -> cage 2
* port 1 -> cage 2
* port 2 -> cage 2
*/
{
EFX_FAMILY_MEDFORD,
- (1U << TLV_PORT_MODE_10G_10G_10G_10G_Q2), /* mode 8 */
- 4, /* ports per cage */
- 2 /* first cage */
+ (1U << TLV_PORT_MODE_NA_4x1), /* mode 8 */
+ { EFX_EXT_PORT_NA, 0, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA }
+ },
+ /*
+ * Modes that on Medford2 allocate each port number to a separate
+ * cage.
+ * port 0 -> cage 1
+ * port 1 -> cage 2
+ * port 2 -> cage 3
+ * port 3 -> cage 4
+ */
+ {
+ EFX_FAMILY_MEDFORD2,
+ (1U << TLV_PORT_MODE_1x1_NA) | /* mode 0 */
+ (1U << TLV_PORT_MODE_1x4_NA) | /* mode 1 */
+ (1U << TLV_PORT_MODE_1x1_1x1) | /* mode 2 */
+ (1U << TLV_PORT_MODE_1x4_1x4) | /* mode 3 */
+ (1U << TLV_PORT_MODE_1x2_NA) | /* mode 10 */
+ (1U << TLV_PORT_MODE_1x2_1x2) | /* mode 12 */
+ (1U << TLV_PORT_MODE_1x4_1x2) | /* mode 15 */
+ (1U << TLV_PORT_MODE_1x2_1x4), /* mode 16 */
+ { 0, 1, 2, 3 }
+ },
+ /*
+ * Modes that on Medford2 allocate 1 port to cage 1 and the rest
+ * to cage 2.
+ * port 0 -> cage 1
+ * port 1 -> cage 2
+ * port 2 -> cage 2
+ */
+ {
+ EFX_FAMILY_MEDFORD2,
+ (1U << TLV_PORT_MODE_1x2_2x1) | /* mode 17 */
+ (1U << TLV_PORT_MODE_1x4_2x1), /* mode 6 */
+ { 0, 1, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA }
+ },
+ /*
+ * Modes that on Medford2 allocate 2 adjacent port numbers to cage 1
+ * and the rest to cage 2.
+ * port 0 -> cage 1
+ * port 1 -> cage 1
+ * port 2 -> cage 2
+ * port 3 -> cage 2
+ */
+ {
+ EFX_FAMILY_MEDFORD2,
+ (1U << TLV_PORT_MODE_2x1_2x1) | /* mode 4 */
+ (1U << TLV_PORT_MODE_2x1_1x4) | /* mode 7 */
+ (1U << TLV_PORT_MODE_2x2_NA) | /* mode 13 */
+ (1U << TLV_PORT_MODE_2x1_1x2), /* mode 18 */
+ { 0, 2, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA }
+ },
+ /*
+ * Modes that on Medford2 allocate up to 4 adjacent port numbers
+ * to cage 1.
+ * port 0 -> cage 1
+ * port 1 -> cage 1
+ * port 2 -> cage 1
+ * port 3 -> cage 1
+ */
+ {
+ EFX_FAMILY_MEDFORD2,
+ (1U << TLV_PORT_MODE_4x1_NA), /* mode 5 */
+ { 0, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA }
+ },
+ /*
+ * Modes that on Medford2 allocate up to 4 adjacent port numbers
+ * to cage 2.
+ * port 0 -> cage 2
+ * port 1 -> cage 2
+ * port 2 -> cage 2
+ * port 3 -> cage 2
+ */
+ {
+ EFX_FAMILY_MEDFORD2,
+ (1U << TLV_PORT_MODE_NA_4x1) | /* mode 8 */
+ (1U << TLV_PORT_MODE_NA_1x2) | /* mode 11 */
+ (1U << TLV_PORT_MODE_NA_2x2), /* mode 14 */
+ { EFX_EXT_PORT_NA, 0, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA }
},
};
uint32_t port_modes;
uint32_t matches;
uint32_t current;
- int32_t count = 1; /* Default 1-1 mapping */
- int32_t offset = 1; /* Default starting external port number */
+ struct ef10_external_port_map_s *mapp = NULL;
+ int ext_index = port; /* Default 1-1 mapping */
- if ((rc = efx_mcdi_get_port_modes(enp, &port_modes, ¤t)) != 0) {
+ if ((rc = efx_mcdi_get_port_modes(enp, &port_modes, ¤t,
+ NULL)) != 0) {
/*
* No current port mode information (i.e. Huntington)
* - infer mapping from available modes
*/
if ((rc = efx_mcdi_get_port_modes(enp,
- &port_modes, NULL)) != 0) {
+ &port_modes, NULL, NULL)) != 0) {
/*
* No port mode information available
* - use default mapping
* there will be multiple matches. The mapping on the
* last match is used.
*/
- count = eepmp->count;
- offset = eepmp->offset;
+ mapp = eepmp;
port_modes &= ~matches;
}
}
}
out:
+ if (mapp != NULL) {
+ /*
+ * External ports are assigned a sequence of consecutive
+ * port numbers, so find the one with the closest base_port.
+ */
+ uint32_t delta = EFX_EXT_PORT_NA;
+
+ for (i = 0; i < EFX_EXT_PORT_MAX; i++) {
+ uint32_t base = mapp->base_port[i];
+ if ((base != EFX_EXT_PORT_NA) && (base <= port)) {
+ if ((port - base) < delta) {
+ delta = (port - base);
+ ext_index = i;
+ }
+ }
+ }
+ }
+ *external_portp = (uint8_t)(ext_index + 1);
+
+ return (0);
+
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+ return (rc);
+}
+
+static __checkReturn efx_rc_t
+ef10_set_workaround_bug26807(
+ __in efx_nic_t *enp)
+{
+ efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
+ uint32_t flags;
+ efx_rc_t rc;
+
/*
- * Scale as required by last matched mode and then convert to
- * correctly offset numbering
+ * If the bug26807 workaround is enabled, then firmware has enabled
+ * support for chained multicast filters. Firmware will reset (FLR)
+ * functions which have filters in the hardware filter table when the
+ * workaround is enabled/disabled.
+ *
+ * We must recheck if the workaround is enabled after inserting the
+ * first hardware filter, in case it has been changed since this check.
*/
- *external_portp = (uint8_t)((port / count) + offset);
+ rc = efx_mcdi_set_workaround(enp, MC_CMD_WORKAROUND_BUG26807,
+ B_TRUE, &flags);
+ if (rc == 0) {
+ encp->enc_bug26807_workaround = B_TRUE;
+ if (flags & (1 << MC_CMD_WORKAROUND_EXT_OUT_FLR_DONE_LBN)) {
+ /*
+ * Other functions had installed filters before the
+ * workaround was enabled, and they have been reset
+ * by firmware.
+ */
+ EFSYS_PROBE(bug26807_workaround_flr_done);
+ /* FIXME: bump MC warm boot count ? */
+ }
+ } else if (rc == EACCES) {
+ /*
+ * Unprivileged functions cannot enable the workaround in older
+ * firmware.
+ */
+ encp->enc_bug26807_workaround = B_FALSE;
+ } else if ((rc == ENOTSUP) || (rc == ENOENT)) {
+ encp->enc_bug26807_workaround = B_FALSE;
+ } else {
+ goto fail1;
+ }
+
return (0);
fail1:
/* EFX MCDI interface uses one-based port numbers */
emip->emi_port = port + 1;
+ encp->enc_assigned_port = port;
+
if ((rc = ef10_external_port_mapping(enp, port,
&encp->enc_external_port)) != 0)
goto fail2;
if ((rc = efx_mcdi_get_phy_cfg(enp)) != 0)
goto fail6;
+ /*
+ * Firmware with support for *_FEC capability bits does not
+ * report that the corresponding *_FEC_REQUESTED bits are supported.
+ * Add them here so that drivers understand that they are supported.
+ */
+ if (epp->ep_phy_cap_mask & (1u << EFX_PHY_CAP_BASER_FEC))
+ epp->ep_phy_cap_mask |=
+ (1u << EFX_PHY_CAP_BASER_FEC_REQUESTED);
+ if (epp->ep_phy_cap_mask & (1u << EFX_PHY_CAP_RS_FEC))
+ epp->ep_phy_cap_mask |=
+ (1u << EFX_PHY_CAP_RS_FEC_REQUESTED);
+ if (epp->ep_phy_cap_mask & (1u << EFX_PHY_CAP_25G_BASER_FEC))
+ epp->ep_phy_cap_mask |=
+ (1u << EFX_PHY_CAP_25G_BASER_FEC_REQUESTED);
+
/* Obtain the default PHY advertised capabilities */
if ((rc = ef10_phy_get_link(enp, &els)) != 0)
goto fail7;
- epp->ep_default_adv_cap_mask = els.els_adv_cap_mask;
- epp->ep_adv_cap_mask = els.els_adv_cap_mask;
+ epp->ep_default_adv_cap_mask = els.epls.epls_adv_cap_mask;
+ epp->ep_adv_cap_mask = els.epls.epls_adv_cap_mask;
/* Check capabilities of running datapath firmware */
if ((rc = ef10_get_datapath_caps(enp)) != 0)
/* Alignment for WPTR updates */
encp->enc_rx_push_align = EF10_RX_WPTR_ALIGN;
- /*
- * Maximum number of exclusive RSS contexts. EF10 hardware supports 64
- * in total, but 6 are reserved for shared contexts. They are a global
- * resource so not all may be available.
- */
- encp->enc_rx_scale_max_exclusive_contexts = 64 - 6;
-
encp->enc_tx_dma_desc_size_max = EFX_MASK32(ESF_DZ_RX_KER_BYTE_CNT);
/* No boundary crossing limits */
encp->enc_tx_dma_desc_boundary = 0;
encp->enc_rxq_limit = EFX_RXQ_LIMIT_TARGET;
encp->enc_txq_limit = EFX_TXQ_LIMIT_TARGET;
- encp->enc_buftbl_limit = 0xFFFFFFFF;
+ encp->enc_buftbl_limit = UINT32_MAX;
/* Get interrupt vector limits */
if ((rc = efx_mcdi_get_vector_cfg(enp, &base, &nvec, NULL)) != 0) {
goto fail10;
encp->enc_privilege_mask = mask;
+ if ((rc = ef10_set_workaround_bug26807(enp)) != 0)
+ goto fail11;
+
/* Get remaining controller-specific board config */
if ((rc = enop->eno_board_cfg(enp)) != 0)
if (rc != EACCES)
- goto fail11;
+ goto fail12;
return (0);
+fail12:
+ EFSYS_PROBE(fail12);
fail11:
EFSYS_PROBE(fail11);
fail10:
efx_drv_cfg_t *edcp = &(enp->en_drv_cfg);
efx_rc_t rc;
- EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
- enp->en_family == EFX_FAMILY_MEDFORD ||
- enp->en_family == EFX_FAMILY_MEDFORD2);
+ EFSYS_ASSERT(EFX_FAMILY_IS_EF10(enp));
/* Read and clear any assertion state */
if ((rc = efx_mcdi_read_assertion(enp)) != 0)
__in efx_nic_t *enp)
{
efx_mcdi_req_t req;
- uint8_t payload[MAX(MC_CMD_ENTITY_RESET_IN_LEN,
- MC_CMD_ENTITY_RESET_OUT_LEN)];
+ EFX_MCDI_DECLARE_BUF(payload, MC_CMD_ENTITY_RESET_IN_LEN,
+ MC_CMD_ENTITY_RESET_OUT_LEN);
efx_rc_t rc;
/* ef10_nic_reset() is called to recover from BADASSERT failures. */
if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
goto fail2;
- (void) memset(payload, 0, sizeof (payload));
req.emr_cmd = MC_CMD_ENTITY_RESET;
req.emr_in_buf = payload;
req.emr_in_length = MC_CMD_ENTITY_RESET_IN_LEN;
return (rc);
}
+static __checkReturn efx_rc_t
+ef10_upstream_port_vadaptor_alloc(
+ __in efx_nic_t *enp)
+{
+ uint32_t retry;
+ uint32_t delay_us;
+ efx_rc_t rc;
+
+ /*
+ * On a VF, this may fail with MC_CMD_ERR_NO_EVB_PORT (ENOENT) if the PF
+ * driver has yet to bring up the EVB port. See bug 56147. In this case,
+ * retry the request several times after waiting a while. The wait time
+ * between retries starts small (10ms) and exponentially increases.
+ * Total wait time is a little over two seconds. Retry logic in the
+ * client driver may mean this whole loop is repeated if it continues to
+ * fail.
+ */
+ retry = 0;
+ delay_us = 10000;
+ while ((rc = efx_mcdi_vadaptor_alloc(enp, EVB_PORT_ID_ASSIGNED)) != 0) {
+ if (EFX_PCI_FUNCTION_IS_PF(&enp->en_nic_cfg) ||
+ (rc != ENOENT)) {
+ /*
+ * Do not retry alloc for PF, or for other errors on
+ * a VF.
+ */
+ goto fail1;
+ }
+
+ /* VF startup before PF is ready. Retry allocation. */
+ if (retry > 5) {
+ /* Too many attempts */
+ rc = EINVAL;
+ goto fail2;
+ }
+ EFSYS_PROBE1(mcdi_no_evb_port_retry, int, retry);
+ EFSYS_SLEEP(delay_us);
+ retry++;
+ if (delay_us < 500000)
+ delay_us <<= 2;
+ }
+
+ return (0);
+
+fail2:
+ EFSYS_PROBE(fail2);
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+ return (rc);
+}
+
__checkReturn efx_rc_t
ef10_nic_init(
__in efx_nic_t *enp)
uint32_t min_vi_count, max_vi_count;
uint32_t vi_count, vi_base, vi_shift;
uint32_t i;
- uint32_t retry;
- uint32_t delay_us;
uint32_t vi_window_size;
efx_rc_t rc;
+ boolean_t alloc_vadaptor = B_TRUE;
EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
enp->en_family == EFX_FAMILY_MEDFORD ||
}
/*
- * Allocate a vAdaptor attached to our upstream vPort/pPort.
- *
- * On a VF, this may fail with MC_CMD_ERR_NO_EVB_PORT (ENOENT) if the PF
- * driver has yet to bring up the EVB port. See bug 56147. In this case,
- * retry the request several times after waiting a while. The wait time
- * between retries starts small (10ms) and exponentially increases.
- * Total wait time is a little over two seconds. Retry logic in the
- * client driver may mean this whole loop is repeated if it continues to
- * fail.
+ * For SR-IOV use case, vAdaptor is allocated for PF and associated VFs
+ * during NIC initialization when vSwitch is created and vports are
+ * allocated. Hence, skip vAdaptor allocation for EVB and update vport
+ * id in NIC structure with the one allocated for PF.
*/
- retry = 0;
- delay_us = 10000;
- while ((rc = efx_mcdi_vadaptor_alloc(enp, EVB_PORT_ID_ASSIGNED)) != 0) {
- if (EFX_PCI_FUNCTION_IS_PF(&enp->en_nic_cfg) ||
- (rc != ENOENT)) {
- /*
- * Do not retry alloc for PF, or for other errors on
- * a VF.
- */
- goto fail5;
- }
-
- /* VF startup before PF is ready. Retry allocation. */
- if (retry > 5) {
- /* Too many attempts */
- rc = EINVAL;
- goto fail6;
- }
- EFSYS_PROBE1(mcdi_no_evb_port_retry, int, retry);
- EFSYS_SLEEP(delay_us);
- retry++;
- if (delay_us < 500000)
- delay_us <<= 2;
- }
enp->en_vport_id = EVB_PORT_ID_ASSIGNED;
+#if EFSYS_OPT_EVB
+ if ((enp->en_vswitchp != NULL) && (enp->en_vswitchp->ev_evcp != NULL)) {
+ /* For EVB use vport allocated on vswitch */
+ enp->en_vport_id = enp->en_vswitchp->ev_evcp->evc_vport_id;
+ alloc_vadaptor = B_FALSE;
+ }
+#endif
+ if (alloc_vadaptor != B_FALSE) {
+ /* Allocate a vAdaptor attached to our upstream vPort/pPort */
+ if ((rc = ef10_upstream_port_vadaptor_alloc(enp)) != 0)
+ goto fail5;
+ }
enp->en_nic_cfg.enc_mcdi_max_payload_length = MCDI_CTL_SDU_LEN_MAX_V2;
return (0);
-fail6:
- EFSYS_PROBE(fail6);
fail5:
EFSYS_PROBE(fail5);
fail4:
__in efx_nic_t *enp,
__out uint32_t *vi_countp)
{
- EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
- enp->en_family == EFX_FAMILY_MEDFORD ||
- enp->en_family == EFX_FAMILY_MEDFORD2);
+ EFSYS_ASSERT(EFX_FAMILY_IS_EF10(enp));
/*
* Report VIs that the client driver can use.
{
efx_rc_t rc;
- EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
- enp->en_family == EFX_FAMILY_MEDFORD ||
- enp->en_family == EFX_FAMILY_MEDFORD2);
+ EFSYS_ASSERT(EFX_FAMILY_IS_EF10(enp));
/*
* TODO: Specify host memory mapping alignment and granularity
return (rc);
}
+ __checkReturn boolean_t
+ef10_nic_hw_unavailable(
+ __in efx_nic_t *enp)
+{
+ efx_dword_t dword;
+
+ if (enp->en_reset_flags & EFX_RESET_HW_UNAVAIL)
+ return (B_TRUE);
+
+ EFX_BAR_READD(enp, ER_DZ_BIU_MC_SFT_STATUS_REG, &dword, B_FALSE);
+ if (EFX_DWORD_FIELD(dword, EFX_DWORD_0) == 0xffffffff)
+ goto unavail;
+
+ return (B_FALSE);
+
+unavail:
+ ef10_nic_set_hw_unavailable(enp);
+
+ return (B_TRUE);
+}
+
+ void
+ef10_nic_set_hw_unavailable(
+ __in efx_nic_t *enp)
+{
+ EFSYS_PROBE(hw_unavail);
+ enp->en_reset_flags |= EFX_RESET_HW_UNAVAIL;
+}
+
+
void
ef10_nic_fini(
__in efx_nic_t *enp)
{
uint32_t i;
efx_rc_t rc;
+ boolean_t do_vadaptor_free = B_TRUE;
- (void) efx_mcdi_vadaptor_free(enp, enp->en_vport_id);
- enp->en_vport_id = 0;
+#if EFSYS_OPT_EVB
+ if (enp->en_vswitchp != NULL) {
+ /*
+ * For SR-IOV the vAdaptor is freed with the vswitch,
+ * so do not free it here.
+ */
+ do_vadaptor_free = B_FALSE;
+ }
+#endif
+ if (do_vadaptor_free != B_FALSE) {
+ (void) efx_mcdi_vadaptor_free(enp, enp->en_vport_id);
+ enp->en_vport_id = EVB_PORT_ID_NULL;
+ }
/* Unlink piobufs from extra VIs in WC mapping */
if (enp->en_arch.ef10.ena_piobuf_count > 0) {
#endif /* EFSYS_OPT_DIAG */
+#if EFSYS_OPT_FW_SUBVARIANT_AWARE
+
+ __checkReturn efx_rc_t
+efx_mcdi_get_nic_global(
+ __in efx_nic_t *enp,
+ __in uint32_t key,
+ __out uint32_t *valuep)
+{
+ efx_mcdi_req_t req;
+ EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_NIC_GLOBAL_IN_LEN,
+ MC_CMD_GET_NIC_GLOBAL_OUT_LEN);
+ efx_rc_t rc;
+
+ req.emr_cmd = MC_CMD_GET_NIC_GLOBAL;
+ req.emr_in_buf = payload;
+ req.emr_in_length = MC_CMD_GET_NIC_GLOBAL_IN_LEN;
+ req.emr_out_buf = payload;
+ req.emr_out_length = MC_CMD_GET_NIC_GLOBAL_OUT_LEN;
+
+ MCDI_IN_SET_DWORD(req, GET_NIC_GLOBAL_IN_KEY, key);
+
+ efx_mcdi_execute(enp, &req);
+
+ if (req.emr_rc != 0) {
+ rc = req.emr_rc;
+ goto fail1;
+ }
+
+ if (req.emr_out_length_used != MC_CMD_GET_NIC_GLOBAL_OUT_LEN) {
+ rc = EMSGSIZE;
+ goto fail2;
+ }
+
+ *valuep = MCDI_OUT_DWORD(req, GET_NIC_GLOBAL_OUT_VALUE);
+
+ return (0);
+
+fail2:
+ EFSYS_PROBE(fail2);
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+ return (rc);
+}
+
+ __checkReturn efx_rc_t
+efx_mcdi_set_nic_global(
+ __in efx_nic_t *enp,
+ __in uint32_t key,
+ __in uint32_t value)
+{
+ efx_mcdi_req_t req;
+ EFX_MCDI_DECLARE_BUF(payload, MC_CMD_SET_NIC_GLOBAL_IN_LEN, 0);
+ efx_rc_t rc;
+
+ req.emr_cmd = MC_CMD_SET_NIC_GLOBAL;
+ req.emr_in_buf = payload;
+ req.emr_in_length = MC_CMD_SET_NIC_GLOBAL_IN_LEN;
+ req.emr_out_buf = NULL;
+ req.emr_out_length = 0;
+
+ MCDI_IN_SET_DWORD(req, SET_NIC_GLOBAL_IN_KEY, key);
+ MCDI_IN_SET_DWORD(req, SET_NIC_GLOBAL_IN_VALUE, value);
+
+ efx_mcdi_execute(enp, &req);
+
+ if (req.emr_rc != 0) {
+ rc = req.emr_rc;
+ goto fail1;
+ }
+
+ return (0);
+
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+ return (rc);
+}
+
+#endif /* EFSYS_OPT_FW_SUBVARIANT_AWARE */
-#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
+#endif /* EFX_OPTS_EF10() */