diff options
Diffstat (limited to 'sys/dev/sfxge/common/efx_mcdi.c')
-rw-r--r-- | sys/dev/sfxge/common/efx_mcdi.c | 589 |
1 files changed, 455 insertions, 134 deletions
diff --git a/sys/dev/sfxge/common/efx_mcdi.c b/sys/dev/sfxge/common/efx_mcdi.c index e1c4b45..07224c7 100644 --- a/sys/dev/sfxge/common/efx_mcdi.c +++ b/sys/dev/sfxge/common/efx_mcdi.c @@ -31,11 +31,7 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); -#include "efsys.h" #include "efx.h" -#include "efx_types.h" -#include "efx_regs.h" -#include "efx_regs_mcdi.h" #include "efx_impl.h" #if EFSYS_OPT_MCDI @@ -46,42 +42,40 @@ __FBSDID("$FreeBSD$"); static efx_mcdi_ops_t __efx_mcdi_siena_ops = { siena_mcdi_init, /* emco_init */ siena_mcdi_request_copyin, /* emco_request_copyin */ - siena_mcdi_request_poll, /* emco_request_poll */ siena_mcdi_request_copyout, /* emco_request_copyout */ siena_mcdi_poll_reboot, /* emco_poll_reboot */ + siena_mcdi_poll_response, /* emco_poll_response */ + siena_mcdi_read_response, /* emco_read_response */ siena_mcdi_fini, /* emco_fini */ - siena_mcdi_fw_update_supported, /* emco_fw_update_supported */ - siena_mcdi_macaddr_change_supported, - /* emco_macaddr_change_supported */ + siena_mcdi_feature_supported, /* emco_feature_supported */ }; #endif /* EFSYS_OPT_SIENA */ -#if EFSYS_OPT_HUNTINGTON - -static efx_mcdi_ops_t __efx_mcdi_hunt_ops = { - hunt_mcdi_init, /* emco_init */ - hunt_mcdi_request_copyin, /* emco_request_copyin */ - hunt_mcdi_request_poll, /* emco_request_poll */ - hunt_mcdi_request_copyout, /* emco_request_copyout */ - hunt_mcdi_poll_reboot, /* emco_poll_reboot */ - hunt_mcdi_fini, /* emco_fini */ - hunt_mcdi_fw_update_supported, /* emco_fw_update_supported */ - hunt_mcdi_macaddr_change_supported, - /* emco_macaddr_change_supported */ +#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD + +static efx_mcdi_ops_t __efx_mcdi_ef10_ops = { + ef10_mcdi_init, /* emco_init */ + ef10_mcdi_request_copyin, /* emco_request_copyin */ + ef10_mcdi_request_copyout, /* emco_request_copyout */ + ef10_mcdi_poll_reboot, /* emco_poll_reboot */ + ef10_mcdi_poll_response, /* emco_poll_response */ + ef10_mcdi_read_response, /* emco_read_response */ + ef10_mcdi_fini, /* emco_fini */ + ef10_mcdi_feature_supported, /* emco_feature_supported */ }; -#endif /* EFSYS_OPT_HUNTINGTON */ +#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */ - __checkReturn int + __checkReturn efx_rc_t efx_mcdi_init( __in efx_nic_t *enp, __in const efx_mcdi_transport_t *emtp) { efx_mcdi_ops_t *emcop; - int rc; + efx_rc_t rc; EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); EFSYS_ASSERT3U(enp->en_mod_flags, ==, 0); @@ -102,10 +96,16 @@ efx_mcdi_init( #if EFSYS_OPT_HUNTINGTON case EFX_FAMILY_HUNTINGTON: - emcop = (efx_mcdi_ops_t *)&__efx_mcdi_hunt_ops; + emcop = (efx_mcdi_ops_t *)&__efx_mcdi_ef10_ops; break; #endif /* EFSYS_OPT_HUNTINGTON */ +#if EFSYS_OPT_MEDFORD + case EFX_FAMILY_MEDFORD: + emcop = (efx_mcdi_ops_t *)&__efx_mcdi_ef10_ops; + break; +#endif /* EFSYS_OPT_MEDFORD */ + default: EFSYS_ASSERT(0); rc = ENOTSUP; @@ -136,7 +136,7 @@ fail3: fail2: EFSYS_PROBE(fail2); fail1: - EFSYS_PROBE1(fail1, int, rc); + EFSYS_PROBE1(fail1, efx_rc_t, rc); enp->en_mcdi.em_emcop = NULL; enp->en_mcdi.em_emtp = NULL; @@ -178,6 +178,62 @@ efx_mcdi_new_epoch( EFSYS_UNLOCK(enp->en_eslp, state); } +static void +efx_mcdi_request_copyin( + __in efx_nic_t *enp, + __in efx_mcdi_req_t *emrp, + __in unsigned int seq, + __in boolean_t ev_cpl, + __in boolean_t new_epoch) +{ + efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop; + + emcop->emco_request_copyin(enp, emrp, seq, ev_cpl, new_epoch); +} + +static void +efx_mcdi_request_copyout( + __in efx_nic_t *enp, + __in efx_mcdi_req_t *emrp) +{ + efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop; + + emcop->emco_request_copyout(enp, emrp); +} + +static efx_rc_t +efx_mcdi_poll_reboot( + __in efx_nic_t *enp) +{ + efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop; + efx_rc_t rc; + + rc = emcop->emco_poll_reboot(enp); + return (rc); +} + +static boolean_t +efx_mcdi_poll_response( + __in efx_nic_t *enp) +{ + efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop; + boolean_t available; + + available = emcop->emco_poll_response(enp); + return (available); +} + +static void +efx_mcdi_read_response( + __in efx_nic_t *enp, + __out void *bufferp, + __in size_t offset, + __in size_t length) +{ + efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop; + + emcop->emco_read_response(enp, bufferp, offset, length); +} void efx_mcdi_request_start( @@ -186,7 +242,6 @@ efx_mcdi_request_start( __in boolean_t ev_cpl) { efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); - efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop; unsigned int seq; boolean_t new_epoch; int state; @@ -195,9 +250,6 @@ efx_mcdi_request_start( EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI); EFSYS_ASSERT3U(enp->en_features, &, EFX_FEATURE_MCDI); - if (emcop == NULL || emcop->emco_request_copyin == NULL) - return; - /* * efx_mcdi_request_start() is naturally serialised against both * efx_mcdi_request_poll() and efx_mcdi_ev_cpl()/efx_mcdi_ev_death(), @@ -219,26 +271,194 @@ efx_mcdi_request_start( new_epoch = emip->emi_new_epoch; EFSYS_UNLOCK(enp->en_eslp, state); - emcop->emco_request_copyin(enp, emrp, seq, ev_cpl, new_epoch); + efx_mcdi_request_copyin(enp, emrp, seq, ev_cpl, new_epoch); +} + + + void +efx_mcdi_read_response_header( + __in efx_nic_t *enp, + __inout efx_mcdi_req_t *emrp) +{ +#if EFSYS_OPT_MCDI_LOGGING + const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp; +#endif /* EFSYS_OPT_MCDI_LOGGING */ + efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); + efx_dword_t hdr[2]; + unsigned int hdr_len; + unsigned int data_len; + unsigned int seq; + unsigned int cmd; + unsigned int error; + efx_rc_t rc; + + EFSYS_ASSERT(emrp != NULL); + + efx_mcdi_read_response(enp, &hdr[0], 0, sizeof (hdr[0])); + hdr_len = sizeof (hdr[0]); + + cmd = EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_CODE); + seq = EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_SEQ); + error = EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_ERROR); + + if (cmd != MC_CMD_V2_EXTN) { + data_len = EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_DATALEN); + } else { + efx_mcdi_read_response(enp, &hdr[1], hdr_len, sizeof (hdr[1])); + hdr_len += sizeof (hdr[1]); + + cmd = EFX_DWORD_FIELD(hdr[1], MC_CMD_V2_EXTN_IN_EXTENDED_CMD); + data_len = + EFX_DWORD_FIELD(hdr[1], MC_CMD_V2_EXTN_IN_ACTUAL_LEN); + } + + if (error && (data_len == 0)) { + /* The MC has rebooted since the request was sent. */ + EFSYS_SPIN(EFX_MCDI_STATUS_SLEEP_US); + efx_mcdi_poll_reboot(enp); + rc = EIO; + goto fail1; + } + if ((cmd != emrp->emr_cmd) || + (seq != ((emip->emi_seq - 1) & EFX_MASK32(MCDI_HEADER_SEQ)))) { + /* Response is for a different request */ + rc = EIO; + goto fail2; + } + if (error) { + efx_dword_t err[2]; + unsigned int err_len = MIN(data_len, sizeof (err)); + int err_code = MC_CMD_ERR_EPROTO; + int err_arg = 0; + + /* Read error code (and arg num for MCDI v2 commands) */ + efx_mcdi_read_response(enp, &err, hdr_len, err_len); + + if (err_len >= (MC_CMD_ERR_CODE_OFST + sizeof (efx_dword_t))) + err_code = EFX_DWORD_FIELD(err[0], EFX_DWORD_0); +#ifdef WITH_MCDI_V2 + if (err_len >= (MC_CMD_ERR_ARG_OFST + sizeof (efx_dword_t))) + err_arg = EFX_DWORD_FIELD(err[1], EFX_DWORD_0); +#endif + emrp->emr_err_code = err_code; + emrp->emr_err_arg = err_arg; + +#if EFSYS_OPT_MCDI_PROXY_AUTH + if ((err_code == MC_CMD_ERR_PROXY_PENDING) && + (err_len == sizeof (err))) { + /* + * The MCDI request would normally fail with EPERM, but + * firmware has forwarded it to an authorization agent + * attached to a privileged PF. + * + * Save the authorization request handle. The client + * must wait for a PROXY_RESPONSE event, or timeout. + */ + emrp->emr_proxy_handle = err_arg; + } +#endif /* EFSYS_OPT_MCDI_PROXY_AUTH */ + +#if EFSYS_OPT_MCDI_LOGGING + if (emtp->emt_logger != NULL) { + emtp->emt_logger(emtp->emt_context, + EFX_LOG_MCDI_RESPONSE, + &hdr, hdr_len, + &err, err_len); + } +#endif /* EFSYS_OPT_MCDI_LOGGING */ + + if (!emrp->emr_quiet) { + EFSYS_PROBE3(mcdi_err_arg, int, emrp->emr_cmd, + int, err_code, int, err_arg); + } + + rc = efx_mcdi_request_errcode(err_code); + goto fail3; + } + + emrp->emr_rc = 0; + emrp->emr_out_length_used = data_len; +#if EFSYS_OPT_MCDI_PROXY_AUTH + emrp->emr_proxy_handle = 0; +#endif /* EFSYS_OPT_MCDI_PROXY_AUTH */ + return; + +fail3: + if (!emrp->emr_quiet) + EFSYS_PROBE(fail3); +fail2: + if (!emrp->emr_quiet) + EFSYS_PROBE(fail2); +fail1: + if (!emrp->emr_quiet) + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + emrp->emr_rc = rc; + emrp->emr_out_length_used = 0; } + __checkReturn boolean_t efx_mcdi_request_poll( __in efx_nic_t *enp) { - efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop; - boolean_t completed; + efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); + efx_mcdi_req_t *emrp; + int state; + efx_rc_t rc; EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI); EFSYS_ASSERT3U(enp->en_features, &, EFX_FEATURE_MCDI); - completed = B_FALSE; + /* Serialise against post-watchdog efx_mcdi_ev* */ + EFSYS_LOCK(enp->en_eslp, state); + + EFSYS_ASSERT(emip->emi_pending_req != NULL); + EFSYS_ASSERT(!emip->emi_ev_cpl); + emrp = emip->emi_pending_req; + + /* Check for reboot atomically w.r.t efx_mcdi_request_start */ + if (emip->emi_poll_cnt++ == 0) { + if ((rc = efx_mcdi_poll_reboot(enp)) != 0) { + emip->emi_pending_req = NULL; + EFSYS_UNLOCK(enp->en_eslp, state); + goto fail1; + } + } + + /* Check if a response is available */ + if (efx_mcdi_poll_response(enp) == B_FALSE) { + EFSYS_UNLOCK(enp->en_eslp, state); + return (B_FALSE); + } + + /* Read the response header */ + efx_mcdi_read_response_header(enp, emrp); + + /* Request complete */ + emip->emi_pending_req = NULL; + + EFSYS_UNLOCK(enp->en_eslp, state); + + if ((rc = emrp->emr_rc) != 0) + goto fail2; + + efx_mcdi_request_copyout(enp, emrp); + return (B_TRUE); + +fail2: + if (!emrp->emr_quiet) + EFSYS_PROBE(fail2); +fail1: + if (!emrp->emr_quiet) + EFSYS_PROBE1(fail1, efx_rc_t, rc); - if (emcop != NULL && emcop->emco_request_poll != NULL) - completed = emcop->emco_request_poll(enp); + /* Reboot/Assertion */ + if (rc == EIO || rc == EINTR) + efx_mcdi_raise_exception(enp, emrp, rc); - return (completed); + return (B_TRUE); } __checkReturn boolean_t @@ -285,7 +505,7 @@ efx_mcdi_request_abort( return (aborted); } - __checkReturn int + __checkReturn efx_rc_t efx_mcdi_request_errcode( __in unsigned int err) { @@ -346,6 +566,9 @@ efx_mcdi_request_errcode( case MC_CMD_ERR_MAC_EXIST: return (EEXIST); + case MC_CMD_ERR_PROXY_PENDING: + return (EAGAIN); + default: EFSYS_PROBE1(mc_pcol_error, int, err); return (EIO); @@ -378,16 +601,6 @@ efx_mcdi_raise_exception( emtp->emt_exception(emtp->emt_context, exception); } -static int -efx_mcdi_poll_reboot( - __in efx_nic_t *enp) -{ - efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop; - - return (emcop->emco_poll_reboot(enp)); -} - - void efx_mcdi_execute( __in efx_nic_t *enp, @@ -450,27 +663,86 @@ efx_mcdi_ev_cpl( emip->emi_pending_req = NULL; EFSYS_UNLOCK(enp->en_eslp, state); - /* - * Fill out the remaining hdr fields, and copyout the payload - * if the user supplied an output buffer. - */ - if (errcode != 0) { - if (!emrp->emr_quiet) { - EFSYS_PROBE2(mcdi_err, int, emrp->emr_cmd, - int, errcode); - } - emrp->emr_out_length_used = 0; - emrp->emr_rc = efx_mcdi_request_errcode(errcode); + if (emip->emi_max_version >= 2) { + /* MCDIv2 response details do not fit into an event. */ + efx_mcdi_read_response_header(enp, emrp); } else { - emrp->emr_out_length_used = outlen; - emrp->emr_rc = 0; - + if (errcode != 0) { + if (!emrp->emr_quiet) { + EFSYS_PROBE2(mcdi_err, int, emrp->emr_cmd, + int, errcode); + } + emrp->emr_out_length_used = 0; + emrp->emr_rc = efx_mcdi_request_errcode(errcode); + } else { + emrp->emr_out_length_used = outlen; + emrp->emr_rc = 0; + } + } + if (errcode == 0) { emcop->emco_request_copyout(enp, emrp); } emtp->emt_ev_cpl(emtp->emt_context); } +#if EFSYS_OPT_MCDI_PROXY_AUTH + + __checkReturn efx_rc_t +efx_mcdi_get_proxy_handle( + __in efx_nic_t *enp, + __in efx_mcdi_req_t *emrp, + __out uint32_t *handlep) +{ + efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); + efx_rc_t rc; + + /* + * Return proxy handle from MCDI request that returned with error + * MC_MCD_ERR_PROXY_PENDING. This handle is used to wait for a matching + * PROXY_RESPONSE event. + */ + if ((emrp == NULL) || (handlep == NULL)) { + rc = EINVAL; + goto fail1; + } + if ((emrp->emr_rc != 0) && + (emrp->emr_err_code == MC_CMD_ERR_PROXY_PENDING)) { + *handlep = emrp->emr_proxy_handle; + rc = 0; + } else { + *handlep = 0; + rc = ENOENT; + } + return (rc); + +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + return (rc); +} + + void +efx_mcdi_ev_proxy_response( + __in efx_nic_t *enp, + __in unsigned int handle, + __in unsigned int status) +{ + const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp; + efx_rc_t rc; + + /* + * Handle results of an authorization request for a privileged MCDI + * command. If authorization was granted then we must re-issue the + * original MCDI request. If authorization failed or timed out, + * then the original MCDI request should be completed with the + * result code from this event. + */ + rc = (status == 0) ? 0 : efx_mcdi_request_errcode(status); + + emtp->emt_ev_proxy_response(emtp->emt_context, handle, rc); +} +#endif /* EFSYS_OPT_MCDI_PROXY_AUTH */ + void efx_mcdi_ev_death( __in efx_nic_t *enp, @@ -524,7 +796,7 @@ efx_mcdi_ev_death( emtp->emt_ev_cpl(emtp->emt_context); } - __checkReturn int + __checkReturn efx_rc_t efx_mcdi_version( __in efx_nic_t *enp, __out_ecount_opt(4) uint16_t versionp[4], @@ -540,7 +812,7 @@ efx_mcdi_version( uint16_t version[4]; uint32_t build; efx_mcdi_boot_t status; - int rc; + efx_rc_t rc; EFSYS_ASSERT3U(enp->en_features, &, EFX_FEATURE_MCDI); @@ -635,19 +907,19 @@ fail3: fail2: EFSYS_PROBE(fail2); fail1: - EFSYS_PROBE1(fail1, int, rc); + EFSYS_PROBE1(fail1, efx_rc_t, rc); return (rc); } -static __checkReturn int +static __checkReturn efx_rc_t efx_mcdi_do_reboot( __in efx_nic_t *enp, __in boolean_t after_assertion) { uint8_t payload[MAX(MC_CMD_REBOOT_IN_LEN, MC_CMD_REBOOT_OUT_LEN)]; efx_mcdi_req_t req; - int rc; + efx_rc_t rc; /* * We could require the caller to have caused en_mod_flags=0 to @@ -685,26 +957,26 @@ out: return (0); fail1: - EFSYS_PROBE1(fail1, int, rc); + EFSYS_PROBE1(fail1, efx_rc_t, rc); return (rc); } - __checkReturn int + __checkReturn efx_rc_t efx_mcdi_reboot( __in efx_nic_t *enp) { return (efx_mcdi_do_reboot(enp, B_FALSE)); } - __checkReturn int + __checkReturn efx_rc_t efx_mcdi_exit_assertion_handler( __in efx_nic_t *enp) { return (efx_mcdi_do_reboot(enp, B_TRUE)); } - __checkReturn int + __checkReturn efx_rc_t efx_mcdi_read_assertion( __in efx_nic_t *enp) { @@ -716,7 +988,7 @@ efx_mcdi_read_assertion( unsigned int index; unsigned int ofst; int retry; - int rc; + efx_rc_t rc; /* * Before we attempt to chat to the MC, we should verify that the MC @@ -795,7 +1067,7 @@ out: fail2: EFSYS_PROBE(fail2); fail1: - EFSYS_PROBE1(fail1, int, rc); + EFSYS_PROBE1(fail1, efx_rc_t, rc); return (rc); } @@ -805,7 +1077,7 @@ fail1: * Internal routines for for specific MCDI requests. */ - __checkReturn int + __checkReturn efx_rc_t efx_mcdi_drv_attach( __in efx_nic_t *enp, __in boolean_t attach) @@ -815,7 +1087,7 @@ efx_mcdi_drv_attach( uint8_t payload[MAX(MC_CMD_DRV_ATTACH_IN_LEN, MC_CMD_DRV_ATTACH_EXT_OUT_LEN)]; uint32_t flags; - int rc; + efx_rc_t rc; (void) memset(payload, 0, sizeof (payload)); req.emr_cmd = MC_CMD_DRV_ATTACH; @@ -878,12 +1150,12 @@ fail3: fail2: EFSYS_PROBE(fail2); fail1: - EFSYS_PROBE1(fail1, int, rc); + EFSYS_PROBE1(fail1, efx_rc_t, rc); return (rc); } - __checkReturn int + __checkReturn efx_rc_t efx_mcdi_get_board_cfg( __in efx_nic_t *enp, __out_opt uint32_t *board_typep, @@ -894,7 +1166,7 @@ efx_mcdi_get_board_cfg( efx_mcdi_req_t req; uint8_t payload[MAX(MC_CMD_GET_BOARD_CFG_IN_LEN, MC_CMD_GET_BOARD_CFG_OUT_LENMIN)]; - int rc; + efx_rc_t rc; (void) memset(payload, 0, sizeof (payload)); req.emr_cmd = MC_CMD_GET_BOARD_CFG; @@ -959,12 +1231,12 @@ fail3: fail2: EFSYS_PROBE(fail2); fail1: - EFSYS_PROBE1(fail1, int, rc); + EFSYS_PROBE1(fail1, efx_rc_t, rc); return (rc); } - __checkReturn int + __checkReturn efx_rc_t efx_mcdi_get_resource_limits( __in efx_nic_t *enp, __out_opt uint32_t *nevqp, @@ -974,7 +1246,7 @@ efx_mcdi_get_resource_limits( efx_mcdi_req_t req; uint8_t payload[MAX(MC_CMD_GET_RESOURCE_LIMITS_IN_LEN, MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN)]; - int rc; + efx_rc_t rc; (void) memset(payload, 0, sizeof (payload)); req.emr_cmd = MC_CMD_GET_RESOURCE_LIMITS; @@ -1007,12 +1279,12 @@ efx_mcdi_get_resource_limits( fail2: EFSYS_PROBE(fail2); fail1: - EFSYS_PROBE1(fail1, int, rc); + EFSYS_PROBE1(fail1, efx_rc_t, rc); return (rc); } - __checkReturn int + __checkReturn efx_rc_t efx_mcdi_get_phy_cfg( __in efx_nic_t *enp) { @@ -1021,7 +1293,7 @@ efx_mcdi_get_phy_cfg( efx_mcdi_req_t req; uint8_t payload[MAX(MC_CMD_GET_PHY_CFG_IN_LEN, MC_CMD_GET_PHY_CFG_OUT_LEN)]; - int rc; + efx_rc_t rc; (void) memset(payload, 0, sizeof (payload)); req.emr_cmd = MC_CMD_GET_PHY_CFG; @@ -1113,23 +1385,22 @@ efx_mcdi_get_phy_cfg( fail2: EFSYS_PROBE(fail2); fail1: - EFSYS_PROBE1(fail1, int, rc); + EFSYS_PROBE1(fail1, efx_rc_t, rc); return (rc); } - - __checkReturn int + __checkReturn efx_rc_t efx_mcdi_firmware_update_supported( __in efx_nic_t *enp, __out boolean_t *supportedp) { efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop; - int rc; + efx_rc_t rc; - if (emcop != NULL && emcop->emco_fw_update_supported != NULL) { - if ((rc = emcop->emco_fw_update_supported(enp, supportedp)) - != 0) + if (emcop != NULL) { + if ((rc = emcop->emco_feature_supported(enp, + EFX_MCDI_FEATURE_FW_UPDATE, supportedp)) != 0) goto fail1; } else { /* Earlier devices always supported updates */ @@ -1139,22 +1410,22 @@ efx_mcdi_firmware_update_supported( return (0); fail1: - EFSYS_PROBE1(fail1, int, rc); + EFSYS_PROBE1(fail1, efx_rc_t, rc); return (rc); } - __checkReturn int + __checkReturn efx_rc_t efx_mcdi_macaddr_change_supported( __in efx_nic_t *enp, __out boolean_t *supportedp) { efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop; - int rc; + efx_rc_t rc; - if (emcop != NULL && emcop->emco_macaddr_change_supported != NULL) { - if ((rc = emcop->emco_macaddr_change_supported(enp, supportedp)) - != 0) + if (emcop != NULL) { + if ((rc = emcop->emco_feature_supported(enp, + EFX_MCDI_FEATURE_MACADDR_CHANGE, supportedp)) != 0) goto fail1; } else { /* Earlier devices always supported MAC changes */ @@ -1164,25 +1435,75 @@ efx_mcdi_macaddr_change_supported( return (0); fail1: - EFSYS_PROBE1(fail1, int, rc); + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} + + __checkReturn efx_rc_t +efx_mcdi_link_control_supported( + __in efx_nic_t *enp, + __out boolean_t *supportedp) +{ + efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop; + efx_rc_t rc; + + if (emcop != NULL) { + if ((rc = emcop->emco_feature_supported(enp, + EFX_MCDI_FEATURE_LINK_CONTROL, supportedp)) != 0) + goto fail1; + } else { + /* Earlier devices always supported link control */ + *supportedp = B_TRUE; + } + + return (0); + +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} + + __checkReturn efx_rc_t +efx_mcdi_mac_spoofing_supported( + __in efx_nic_t *enp, + __out boolean_t *supportedp) +{ + efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop; + efx_rc_t rc; + + if (emcop != NULL) { + if ((rc = emcop->emco_feature_supported(enp, + EFX_MCDI_FEATURE_MAC_SPOOFING, supportedp)) != 0) + goto fail1; + } else { + /* Earlier devices always supported MAC spoofing */ + *supportedp = B_TRUE; + } + + return (0); + +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); return (rc); } #if EFSYS_OPT_BIST -#if EFSYS_OPT_HUNTINGTON +#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD /* * Enter bist offline mode. This is a fw mode which puts the NIC into a state * where memory BIST tests can be run and not much else can interfere or happen. * A reboot is required to exit this mode. */ - __checkReturn int + __checkReturn efx_rc_t efx_mcdi_bist_enable_offline( __in efx_nic_t *enp) { efx_mcdi_req_t req; - int rc; + efx_rc_t rc; EFX_STATIC_ASSERT(MC_CMD_ENABLE_OFFLINE_BIST_IN_LEN == 0); EFX_STATIC_ASSERT(MC_CMD_ENABLE_OFFLINE_BIST_OUT_LEN == 0); @@ -1203,13 +1524,13 @@ efx_mcdi_bist_enable_offline( return (0); fail1: - EFSYS_PROBE1(fail1, int, rc); + EFSYS_PROBE1(fail1, efx_rc_t, rc); return (rc); } -#endif /* EFSYS_OPT_HUNTINGTON */ +#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */ - __checkReturn int + __checkReturn efx_rc_t efx_mcdi_bist_start( __in efx_nic_t *enp, __in efx_bist_type_t type) @@ -1217,7 +1538,7 @@ efx_mcdi_bist_start( efx_mcdi_req_t req; uint8_t payload[MAX(MC_CMD_START_BIST_IN_LEN, MC_CMD_START_BIST_OUT_LEN)]; - int rc; + efx_rc_t rc; (void) memset(payload, 0, sizeof (payload)); req.emr_cmd = MC_CMD_START_BIST; @@ -1264,7 +1585,7 @@ efx_mcdi_bist_start( return (0); fail1: - EFSYS_PROBE1(fail1, int, rc); + EFSYS_PROBE1(fail1, efx_rc_t, rc); return (rc); } @@ -1273,14 +1594,14 @@ fail1: /* Enable logging of some events (e.g. link state changes) */ - __checkReturn int + __checkReturn efx_rc_t efx_mcdi_log_ctrl( __in efx_nic_t *enp) { efx_mcdi_req_t req; uint8_t payload[MAX(MC_CMD_LOG_CTRL_IN_LEN, MC_CMD_LOG_CTRL_OUT_LEN)]; - int rc; + efx_rc_t rc; (void) memset(payload, 0, sizeof (payload)); req.emr_cmd = MC_CMD_LOG_CTRL; @@ -1303,7 +1624,7 @@ efx_mcdi_log_ctrl( return (0); fail1: - EFSYS_PROBE1(fail1, int, rc); + EFSYS_PROBE1(fail1, efx_rc_t, rc); return (rc); } @@ -1320,7 +1641,7 @@ typedef enum efx_stats_action_e EFX_STATS_DISABLE, } efx_stats_action_t; -static __checkReturn int +static __checkReturn efx_rc_t efx_mcdi_mac_stats( __in efx_nic_t *enp, __in_opt efsys_mem_t *esmp, @@ -1334,7 +1655,7 @@ efx_mcdi_mac_stats( int enable = (action == EFX_STATS_ENABLE_NOEVENTS); int events = (action == EFX_STATS_ENABLE_EVENTS); int disable = (action == EFX_STATS_DISABLE); - int rc; + efx_rc_t rc; (void) memset(payload, 0, sizeof (payload)); req.emr_cmd = MC_CMD_MAC_STATS; @@ -1388,16 +1709,16 @@ efx_mcdi_mac_stats( return (0); fail1: - EFSYS_PROBE1(fail1, int, rc); + EFSYS_PROBE1(fail1, efx_rc_t, rc); return (rc); } - __checkReturn int + __checkReturn efx_rc_t efx_mcdi_mac_stats_clear( __in efx_nic_t *enp) { - int rc; + efx_rc_t rc; if ((rc = efx_mcdi_mac_stats(enp, NULL, EFX_STATS_CLEAR)) != 0) goto fail1; @@ -1405,17 +1726,17 @@ efx_mcdi_mac_stats_clear( return (0); fail1: - EFSYS_PROBE1(fail1, int, rc); + EFSYS_PROBE1(fail1, efx_rc_t, rc); return (rc); } - __checkReturn int + __checkReturn efx_rc_t efx_mcdi_mac_stats_upload( __in efx_nic_t *enp, __in efsys_mem_t *esmp) { - int rc; + efx_rc_t rc; /* * The MC DMAs aggregate statistics for our convenience, so we can @@ -1428,19 +1749,19 @@ efx_mcdi_mac_stats_upload( return (0); fail1: - EFSYS_PROBE1(fail1, int, rc); + EFSYS_PROBE1(fail1, efx_rc_t, rc); return (rc); } - __checkReturn int + __checkReturn efx_rc_t efx_mcdi_mac_stats_periodic( __in efx_nic_t *enp, __in efsys_mem_t *esmp, __in uint16_t period, __in boolean_t events) { - int rc; + efx_rc_t rc; /* * The MC DMAs aggregate statistics for our convenience, so we can @@ -1461,14 +1782,14 @@ efx_mcdi_mac_stats_periodic( return (0); fail1: - EFSYS_PROBE1(fail1, int, rc); + EFSYS_PROBE1(fail1, efx_rc_t, rc); return (rc); } #endif /* EFSYS_OPT_MAC_STATS */ -#if EFSYS_OPT_HUNTINGTON +#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD /* * This function returns the pf and vf number of a function. If it is a pf the @@ -1476,7 +1797,7 @@ fail1: * function. So if you have 3 vfs on pf 0 the 3 vfs will return (pf=0,vf=0), * (pf=0,vf=1), (pf=0,vf=2) aand the pf will return (pf=0, vf=0xffff). */ - __checkReturn int + __checkReturn efx_rc_t efx_mcdi_get_function_info( __in efx_nic_t *enp, __out uint32_t *pfp, @@ -1485,7 +1806,7 @@ efx_mcdi_get_function_info( efx_mcdi_req_t req; uint8_t payload[MAX(MC_CMD_GET_FUNCTION_INFO_IN_LEN, MC_CMD_GET_FUNCTION_INFO_OUT_LEN)]; - int rc; + efx_rc_t rc; (void) memset(payload, 0, sizeof (payload)); req.emr_cmd = MC_CMD_GET_FUNCTION_INFO; @@ -1515,12 +1836,12 @@ efx_mcdi_get_function_info( fail2: EFSYS_PROBE(fail2); fail1: - EFSYS_PROBE1(fail1, int, rc); + EFSYS_PROBE1(fail1, efx_rc_t, rc); return (rc); } - __checkReturn int + __checkReturn efx_rc_t efx_mcdi_privilege_mask( __in efx_nic_t *enp, __in uint32_t pf, @@ -1530,7 +1851,7 @@ efx_mcdi_privilege_mask( efx_mcdi_req_t req; uint8_t payload[MAX(MC_CMD_PRIVILEGE_MASK_IN_LEN, MC_CMD_PRIVILEGE_MASK_OUT_LEN)]; - int rc; + efx_rc_t rc; (void) memset(payload, 0, sizeof (payload)); req.emr_cmd = MC_CMD_PRIVILEGE_MASK; @@ -1562,14 +1883,14 @@ efx_mcdi_privilege_mask( fail2: EFSYS_PROBE(fail2); fail1: - EFSYS_PROBE1(fail1, int, rc); + EFSYS_PROBE1(fail1, efx_rc_t, rc); return (rc); } -#endif /* EFSYS_OPT_HUNTINGTON */ +#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */ - __checkReturn int + __checkReturn efx_rc_t efx_mcdi_set_workaround( __in efx_nic_t *enp, __in uint32_t type, @@ -1579,7 +1900,7 @@ efx_mcdi_set_workaround( efx_mcdi_req_t req; uint8_t payload[MAX(MC_CMD_WORKAROUND_IN_LEN, MC_CMD_WORKAROUND_EXT_OUT_LEN)]; - int rc; + efx_rc_t rc; (void) memset(payload, 0, sizeof (payload)); req.emr_cmd = MC_CMD_WORKAROUND; @@ -1608,13 +1929,13 @@ efx_mcdi_set_workaround( return (0); fail1: - EFSYS_PROBE1(fail1, int, rc); + EFSYS_PROBE1(fail1, efx_rc_t, rc); return (rc); } - __checkReturn int + __checkReturn efx_rc_t efx_mcdi_get_workarounds( __in efx_nic_t *enp, __out_opt uint32_t *implementedp, @@ -1622,7 +1943,7 @@ efx_mcdi_get_workarounds( { efx_mcdi_req_t req; uint8_t payload[MC_CMD_GET_WORKAROUNDS_OUT_LEN]; - int rc; + efx_rc_t rc; (void) memset(payload, 0, sizeof (payload)); req.emr_cmd = MC_CMD_GET_WORKAROUNDS; @@ -1650,7 +1971,7 @@ efx_mcdi_get_workarounds( return (0); fail1: - EFSYS_PROBE1(fail1, int, rc); + EFSYS_PROBE1(fail1, efx_rc_t, rc); return (rc); } |