@@ -1216,6 +1216,11 @@
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
*/
@@ -2177,6 +2177,10 @@ static uint32_t checksum_tlv_partition(
return (rc);
}
+#define EF10_NVRAM_INITIAL_POLL_DELAY_US 10000
+#define EF10_NVRAM_MAX_POLL_DELAY_US 1000000
+#define EF10_NVRAM_POLL_RETRIES 100
+
__checkReturn efx_rc_t
ef10_nvram_partn_unlock(
__in efx_nic_t *enp,
@@ -2184,17 +2188,58 @@ static uint32_t checksum_tlv_partition(
__out_opt uint32_t *verify_resultp)
{
boolean_t reboot = B_FALSE;
+ uint32_t poll_delay_us = EF10_NVRAM_INITIAL_POLL_DELAY_US;
+ uint32_t poll_retry = 0;
+ uint32_t verify_result = MC_CMD_NVRAM_VERIFY_RC_UNKNOWN;
efx_rc_t rc;
- if (verify_resultp != NULL)
- *verify_resultp = MC_CMD_NVRAM_VERIFY_RC_UNKNOWN;
+ rc = efx_mcdi_nvram_update_finish(enp, partn, reboot,
+ EFX_NVRAM_UPDATE_FLAGS_BACKGROUND, &verify_result);
- rc = efx_mcdi_nvram_update_finish(enp, partn, reboot, verify_resultp);
- if (rc != 0)
- goto fail1;
+ /*
+ * NVRAM updates can take a long time (e.g. up to 1 minute for bundle
+ * images). Polling for NVRAM update completion ensures that other MCDI
+ * commands can be issued before the background NVRAM update completes.
+ *
+ * Without polling, other MCDI commands can only be issued before the
+ * NVRAM update completes if the MCDI transport and the firmware
+ * support the Asynchronous MCDI protocol extensions in SF-116575-PS.
+ *
+ * The initial call either completes the update synchronously, or
+ * returns RC_PENDING to indicate processing is continuing. In the
+ * latter case, we poll for at least 1 minute, at increasing intervals
+ * (10ms, 100ms, 1s).
+ */
+ while (verify_result == MC_CMD_NVRAM_VERIFY_RC_PENDING) {
+
+ if (poll_retry > EF10_NVRAM_POLL_RETRIES) {
+ rc = ETIMEDOUT;
+ goto fail1;
+ }
+ poll_retry++;
+
+ EFSYS_SLEEP(poll_delay_us);
+ if (poll_delay_us < EF10_NVRAM_MAX_POLL_DELAY_US)
+ poll_delay_us *= 10;
+
+ /* Poll for completion of background NVRAM update. */
+ verify_result = MC_CMD_NVRAM_VERIFY_RC_UNKNOWN;
+
+ rc = efx_mcdi_nvram_update_finish(enp, partn, reboot,
+ EFX_NVRAM_UPDATE_FLAGS_POLL, &verify_result);
+ if (rc != 0) {
+ /* Poll failed, so assume NVRAM update failed. */
+ goto fail2;
+ }
+ }
+
+ if (verify_resultp != NULL)
+ *verify_resultp = verify_result;
return (0);
+fail2:
+ EFSYS_PROBE(fail2);
fail1:
EFSYS_PROBE1(fail1, efx_rc_t, rc);
@@ -1395,6 +1395,8 @@ enum {
uint32_t enc_max_pcie_link_gen;
/* Firmware verifies integrity of NVRAM updates */
boolean_t enc_nvram_update_verify_result_supported;
+ /* Firmware supports polled NVRAM updates on select partitions */
+ boolean_t enc_nvram_update_poll_verify_result_supported;
/* Firmware accepts updates via the BUNDLE partition */
boolean_t enc_nvram_bundle_update_supported;
/* Firmware support for extended MAC_STATS buffer */
@@ -594,11 +594,15 @@
__in_bcount(size) caddr_t data,
__in size_t size);
+#define EFX_NVRAM_UPDATE_FLAGS_BACKGROUND 0x00000001
+#define EFX_NVRAM_UPDATE_FLAGS_POLL 0x00000002
+
__checkReturn efx_rc_t
efx_mcdi_nvram_update_finish(
__in efx_nic_t *enp,
__in uint32_t partn,
__in boolean_t reboot,
+ __in uint32_t flags,
__out_opt uint32_t *verify_resultp);
#if EFSYS_OPT_DIAG
@@ -965,6 +965,7 @@
__in efx_nic_t *enp,
__in uint32_t partn,
__in boolean_t reboot,
+ __in uint32_t flags,
__out_opt uint32_t *verify_resultp)
{
const efx_nic_cfg_t *encp = &enp->en_nic_cfg;
@@ -972,7 +973,7 @@
EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN,
MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN);
uint32_t verify_result = MC_CMD_NVRAM_VERIFY_RC_UNKNOWN;
- efx_rc_t rc;
+ efx_rc_t rc = 0;
req.emr_cmd = MC_CMD_NVRAM_UPDATE_FINISH;
req.emr_in_buf = payload;
@@ -983,8 +984,19 @@
MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_V2_IN_TYPE, partn);
MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_V2_IN_REBOOT, reboot);
- MCDI_IN_POPULATE_DWORD_1(req, NVRAM_UPDATE_FINISH_V2_IN_FLAGS,
- NVRAM_UPDATE_FINISH_V2_IN_FLAG_REPORT_VERIFY_RESULT, 1);
+ if (!encp->enc_nvram_update_poll_verify_result_supported) {
+ flags &= ~EFX_NVRAM_UPDATE_FLAGS_BACKGROUND;
+ flags &= ~EFX_NVRAM_UPDATE_FLAGS_POLL;
+ }
+
+ MCDI_IN_POPULATE_DWORD_3(req, NVRAM_UPDATE_FINISH_V2_IN_FLAGS,
+ NVRAM_UPDATE_FINISH_V2_IN_FLAG_REPORT_VERIFY_RESULT,
+ 1,
+ NVRAM_UPDATE_FINISH_V2_IN_FLAG_RUN_IN_BACKGROUND,
+ (flags & EFX_NVRAM_UPDATE_FLAGS_BACKGROUND) ? 1 : 0,
+ NVRAM_UPDATE_FINISH_V2_IN_FLAG_POLL_VERIFY_RESULT,
+ (flags & EFX_NVRAM_UPDATE_FLAGS_POLL) ? 1 : 0
+ );
efx_mcdi_execute(enp, &req);
@@ -1005,11 +1017,13 @@
MCDI_OUT_DWORD(req, NVRAM_UPDATE_FINISH_V2_OUT_RESULT_CODE);
}
- if ((encp->enc_nvram_update_verify_result_supported) &&
- (verify_result != MC_CMD_NVRAM_VERIFY_RC_SUCCESS)) {
- /* Update verification failed */
- rc = EINVAL;
- goto fail3;
+ if (encp->enc_nvram_update_verify_result_supported) {
+ if ((verify_result != MC_CMD_NVRAM_VERIFY_RC_SUCCESS) &&
+ (verify_result != MC_CMD_NVRAM_VERIFY_RC_PENDING)) {
+ /* Update verification failed */
+ rc = EINVAL;
+ goto fail3;
+ }
}
if (verify_resultp != NULL)
@@ -174,6 +174,7 @@
__out_opt uint32_t *verify_resultp)
{
boolean_t reboot;
+ uint32_t flags = 0;
efx_rc_t rc;
/*
@@ -184,7 +185,8 @@
partn == MC_CMD_NVRAM_TYPE_PHY_PORT1 ||
partn == MC_CMD_NVRAM_TYPE_DISABLED_CALLISTO);
- rc = efx_mcdi_nvram_update_finish(enp, partn, reboot, verify_resultp);
+ rc = efx_mcdi_nvram_update_finish(enp, partn, reboot, flags,
+ verify_resultp);
if (rc != 0)
goto fail1;