Index: head/sys/dev/sfxge/common/efx_mcdi.h =================================================================== --- head/sys/dev/sfxge/common/efx_mcdi.h +++ head/sys/dev/sfxge/common/efx_mcdi.h @@ -59,6 +59,9 @@ uint8_t *emr_out_buf; size_t emr_out_length; size_t emr_out_length_used; + /* Internals: low level transport details */ + unsigned int emr_err_code; + unsigned int emr_err_arg; }; typedef struct efx_mcdi_iface_s { @@ -82,6 +85,11 @@ __in efx_nic_t *enp, __inout efx_mcdi_req_t *emrp); + extern void +efx_mcdi_read_response_header( + __in efx_nic_t *enp, + __inout efx_mcdi_req_t *emrp); + extern void efx_mcdi_ev_cpl( __in efx_nic_t *enp, Index: head/sys/dev/sfxge/common/efx_mcdi.c =================================================================== --- head/sys/dev/sfxge/common/efx_mcdi.c +++ head/sys/dev/sfxge/common/efx_mcdi.c @@ -228,6 +228,114 @@ emcop->emco_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_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop; + 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); + + emcop->emco_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 { + emcop->emco_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); + emcop->emco_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) */ + emcop->emco_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_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; + 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) Index: head/sys/dev/sfxge/common/hunt_mcdi.c =================================================================== --- head/sys/dev/sfxge/common/hunt_mcdi.c +++ head/sys/dev/sfxge/common/hunt_mcdi.c @@ -308,11 +308,6 @@ #endif /* EFSYS_OPT_MCDI_LOGGING */ efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); efx_mcdi_req_t *emrp; - efx_dword_t hdr[2]; - unsigned int hdr_len; - unsigned int data_len; - unsigned int seq; - unsigned int cmd; int state; efx_rc_t rc; @@ -332,101 +327,26 @@ } /* Read the response header */ - hdr_len = sizeof (hdr[0]); - hunt_mcdi_read_response(enp, &hdr[0], 0, hdr_len); - - if (EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_CODE) == MC_CMD_V2_EXTN) { - hunt_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); - } else { - cmd = EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_CODE); - data_len = EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_DATALEN); - } + efx_mcdi_read_response_header(enp, emrp); /* Request complete */ emip->emi_pending_req = NULL; - seq = (emip->emi_seq - 1) & EFX_MASK32(MCDI_HEADER_SEQ); - - /* Check for synchronous reboot */ - if (EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_ERROR) != 0 && data_len == 0) { - /* The MC has rebooted since the request was sent. */ - EFSYS_SPIN(EFX_MCDI_STATUS_SLEEP_US); - hunt_mcdi_poll_reboot(enp); - - EFSYS_UNLOCK(enp->en_eslp, state); - rc = EIO; - goto fail1; - } /* Ensure stale MCDI requests fail after an MC reboot. */ emip->emi_new_epoch = B_FALSE; EFSYS_UNLOCK(enp->en_eslp, state); - /* Check that the returned data is consistent */ - if (cmd != emrp->emr_cmd || - EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_SEQ) != seq) { - /* Response is for a different request */ - rc = EIO; - goto fail2; - } - if (EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_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) */ - hunt_mcdi_read_response(enp, &err[0], 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); - - if (err_len >= MC_CMD_ERR_ARG_OFST + sizeof (efx_dword_t)) - err_arg = EFX_DWORD_FIELD(err[1], EFX_DWORD_0); - -#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 */ - - rc = efx_mcdi_request_errcode(err_code); - if (!emrp->emr_quiet) { - EFSYS_PROBE3(mcdi_err_arg, int, emrp->emr_cmd, - int, err_code, int, err_arg); - } - goto fail3; - - } else { - emrp->emr_out_length_used = data_len; - emrp->emr_rc = 0; - hunt_mcdi_request_copyout(enp, emrp); - } + if ((rc = emrp->emr_rc) != 0) + goto fail1; + hunt_mcdi_request_copyout(enp, emrp); goto out; -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); - /* Fill out error state */ - emrp->emr_rc = rc; - emrp->emr_out_length_used = 0; - /* Reboot/Assertion */ if (rc == EIO || rc == EINTR) efx_mcdi_raise_exception(enp, emrp, rc); Index: head/sys/dev/sfxge/common/siena_mcdi.c =================================================================== --- head/sys/dev/sfxge/common/siena_mcdi.c +++ head/sys/dev/sfxge/common/siena_mcdi.c @@ -222,15 +222,8 @@ siena_mcdi_request_poll( __in efx_nic_t *enp) { -#if EFSYS_OPT_MCDI_LOGGING - const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp; -#endif efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); efx_mcdi_req_t *emrp; - efx_dword_t hdr; - unsigned int hdr_len; - unsigned int data_len; - unsigned int seq; int state; efx_rc_t rc; @@ -260,76 +253,19 @@ } /* Read the response header */ - hdr_len = sizeof (hdr); - siena_mcdi_read_response(enp, &hdr, 0, hdr_len); + efx_mcdi_read_response_header(enp, emrp); /* Request complete */ emip->emi_pending_req = NULL; - seq = (emip->emi_seq - 1) & EFX_MASK32(MCDI_HEADER_SEQ); - - /* Check for synchronous reboot */ - if (EFX_DWORD_FIELD(hdr, MCDI_HEADER_ERROR) != 0 && - EFX_DWORD_FIELD(hdr, MCDI_HEADER_DATALEN) == 0) { - /* Consume status word */ - EFSYS_SPIN(EFX_MCDI_STATUS_SLEEP_US); - siena_mcdi_poll_reboot(enp); - EFSYS_UNLOCK(enp->en_eslp, state); - rc = EIO; - goto fail2; - } EFSYS_UNLOCK(enp->en_eslp, state); - /* Check that the returned data is consistent */ - if (EFX_DWORD_FIELD(hdr, MCDI_HEADER_CODE) != emrp->emr_cmd || - EFX_DWORD_FIELD(hdr, MCDI_HEADER_SEQ) != seq) { - /* Response is for a different request */ - rc = EIO; - goto fail3; - } - - data_len = EFX_DWORD_FIELD(hdr, MCDI_HEADER_DATALEN); - if (EFX_DWORD_FIELD(hdr, MCDI_HEADER_ERROR)) { - efx_dword_t err; - int err_code = MC_CMD_ERR_EPROTO; - unsigned int err_len = MIN(data_len, sizeof (err)); - - /* Read error code */ - siena_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, EFX_DWORD_0); - -#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 */ - - rc = efx_mcdi_request_errcode(err_code); - if (!emrp->emr_quiet) { - EFSYS_PROBE2(mcdi_err, int, emrp->emr_cmd, - int, err_code); - } - goto fail4; - - } else { - emrp->emr_out_length_used = data_len; - emrp->emr_rc = 0; - siena_mcdi_request_copyout(enp, emrp); - } + if ((rc = emrp->emr_rc) != 0) + goto fail2; + siena_mcdi_request_copyout(enp, emrp); goto out; -fail4: - if (!emrp->emr_quiet) - EFSYS_PROBE(fail4); -fail3: - if (!emrp->emr_quiet) - EFSYS_PROBE(fail3); fail2: if (!emrp->emr_quiet) EFSYS_PROBE(fail2); @@ -337,10 +273,6 @@ if (!emrp->emr_quiet) EFSYS_PROBE1(fail1, efx_rc_t, rc); - /* Fill out error state */ - emrp->emr_rc = rc; - emrp->emr_out_length_used = 0; - /* Reboot/Assertion */ if (rc == EIO || rc == EINTR) efx_mcdi_raise_exception(enp, emrp, rc);