#include "mcdi_mon.h"
#endif
-#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
+#if EFX_OPTS_EF10()
#include "ef10_tlv_layout.h"
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));
req.emr_cmd = MC_CMD_GET_PORT_ASSIGNMENT;
req.emr_in_buf = payload;
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));
req.emr_cmd = MC_CMD_GET_PORT_MODES;
req.emr_in_buf = payload;
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)
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)
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));
req.emr_cmd = MC_CMD_GET_MAC_ADDRESSES;
req.emr_in_buf = payload;
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));
req.emr_cmd = MC_CMD_VPORT_GET_MAC_ADDRESSES;
req.emr_in_buf = payload;
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));
req.emr_cmd = MC_CMD_GET_CLOCK;
req.emr_in_buf = payload;
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);
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.
}
+#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_1x1_NA) | /* mode 0 */
+ (1U << TLV_PORT_MODE_1x4_NA) | /* mode 1 */
(1U << TLV_PORT_MODE_1x1_1x1), /* mode 2 */
- 1, /* ports per cage */
- 1 /* first cage */
+ { 0, 1, 2, 3 }
},
/*
* Modes that on Medford allocate 2 adjacent port numbers to each
*/
{
EFX_FAMILY_MEDFORD,
- (1U << TLV_PORT_MODE_1x4_NA) | /* mode 1 */
(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_2x1_2x1) | /* mode 5 */
/* Do not use 10G_10G_10G_10G_Q1 (see bug63270) */
(1U << TLV_PORT_MODE_4x1_NA), /* mode 4 */
- 4, /* ports per cage */
- 1 /* first cage */
+ { 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_NA_4x1), /* mode 8 */
- 4, /* ports per cage */
- 2 /* first cage */
+ { EFX_EXT_PORT_NA, 0, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA }
},
/*
* Modes that on Medford2 allocate each port number to a separate
(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 */
- 1, /* ports per cage */
- 1 /* first cage */
+ { 0, 1, 2, 3 }
},
/*
- * FIXME: Some port modes are not representable in this mapping:
- * - TLV_PORT_MODE_1x2_2x1 (mode 17):
+ * 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 each
- * cage, starting on cage 1.
+ * 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
*/
{
EFX_FAMILY_MEDFORD2,
- (1U << TLV_PORT_MODE_1x4_1x4) | /* mode 3 */
(1U << TLV_PORT_MODE_2x1_2x1) | /* mode 4 */
- (1U << TLV_PORT_MODE_1x4_2x1) | /* mode 6 */
(1U << TLV_PORT_MODE_2x1_1x4) | /* mode 7 */
(1U << TLV_PORT_MODE_2x2_NA) | /* mode 13 */
(1U << TLV_PORT_MODE_2x1_1x2), /* mode 18 */
- 2, /* ports per cage */
- 1 /* first cage */
- },
- /*
- * Modes that on Medford2 allocate 2 adjacent port numbers to each
- * cage, starting on cage 2.
- * port 0 -> cage 2
- * port 1 -> cage 2
- */
- {
- EFX_FAMILY_MEDFORD2,
- (1U << TLV_PORT_MODE_NA_2x2), /* mode 14 */
- 2, /* ports per cage */
- 2 /* first cage */
+ { 0, 2, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA }
},
/*
- * Modes that on Medford2 allocate 4 adjacent port numbers to each
- * connector, starting on cage 1.
+ * 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
{
EFX_FAMILY_MEDFORD2,
(1U << TLV_PORT_MODE_4x1_NA), /* mode 5 */
- 4, /* ports per cage */
- 1 /* first cage */
+ { 0, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA }
},
/*
- * Modes that on Medford2 allocate 4 adjacent port numbers to each
- * connector, starting on cage 2.
+ * 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
{
EFX_FAMILY_MEDFORD2,
(1U << TLV_PORT_MODE_NA_4x1) | /* mode 8 */
- (1U << TLV_PORT_MODE_NA_1x2), /* mode 11 */
- 4, /* ports per cage */
- 2 /* first cage */
+ (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,
NULL)) != 0) {
* 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;
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)
uint32_t vi_window_size;
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));
/* Enable reporting of some events (e.g. link change) */
if ((rc = efx_mcdi_log_ctrl(enp)) != 0)
__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
#endif /* EFSYS_OPT_FW_SUBVARIANT_AWARE */
-#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
+#endif /* EFX_OPTS_EF10() */