Index: head/sys/dev/sfxge/common/efx_impl.h =================================================================== --- head/sys/dev/sfxge/common/efx_impl.h +++ head/sys/dev/sfxge/common/efx_impl.h @@ -463,6 +463,7 @@ efx_rc_t (*emco_fw_update_supported)(efx_nic_t *, boolean_t *); efx_rc_t (*emco_macaddr_change_supported)(efx_nic_t *, boolean_t *); efx_rc_t (*emco_link_control_supported)(efx_nic_t *, boolean_t *); + void (*emco_read_response)(efx_nic_t *, void *, size_t, size_t); } efx_mcdi_ops_t; typedef struct efx_mcdi_s { 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 @@ -55,6 +55,7 @@ /* emco_macaddr_change_supported */ siena_mcdi_link_control_supported, /* emco_link_control_supported */ + siena_mcdi_read_response, /* emco_read_response */ }; #endif /* EFSYS_OPT_SIENA */ @@ -73,6 +74,7 @@ /* emco_macaddr_change_supported */ hunt_mcdi_link_control_supported, /* emco_link_control_supported */ + hunt_mcdi_read_response, /* emco_read_response */ }; #endif /* EFSYS_OPT_HUNTINGTON */ Index: head/sys/dev/sfxge/common/hunt_impl.h =================================================================== --- head/sys/dev/sfxge/common/hunt_impl.h +++ head/sys/dev/sfxge/common/hunt_impl.h @@ -263,6 +263,13 @@ __in boolean_t ev_cpl, __in boolean_t new_epoch); +extern void +hunt_mcdi_read_response( + __in efx_nic_t *enp, + __out void *bufferp, + __in size_t offset, + __in size_t length); + extern __checkReturn boolean_t hunt_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 @@ -229,47 +229,41 @@ __in efx_nic_t *enp, __in efx_mcdi_req_t *emrp) { +#if EFSYS_OPT_MCDI_LOGGING const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp; - efsys_mem_t *esmp = emtp->emt_dma_mem; - unsigned int pos; - unsigned int offset; +#endif /* EFSYS_OPT_MCDI_LOGGING */ efx_dword_t hdr[2]; - efx_dword_t data; + unsigned int hdr_len; size_t bytes; if (emrp->emr_out_buf == NULL) return; /* Read the command header to detect MCDI response format */ - EFSYS_MEM_READD(esmp, 0, &hdr[0]); + 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) { - offset = 2 * sizeof (efx_dword_t); - /* * Read the actual payload length. The length given in the event * is only correct for responses with the V1 format. */ - EFSYS_MEM_READD(esmp, sizeof (efx_dword_t), &hdr[1]); + hunt_mcdi_read_response(enp, &hdr[1], hdr_len, sizeof (hdr[1])); + hdr_len += sizeof (hdr[1]); + emrp->emr_out_length_used = EFX_DWORD_FIELD(hdr[1], MC_CMD_V2_EXTN_IN_ACTUAL_LEN); - } else { - offset = sizeof (efx_dword_t); } /* Copy payload out into caller supplied buffer */ bytes = MIN(emrp->emr_out_length_used, emrp->emr_out_length); - for (pos = 0; pos < bytes; pos += sizeof (efx_dword_t)) { - EFSYS_MEM_READD(esmp, offset + pos, &data); - memcpy(MCDI_OUT(*emrp, efx_dword_t, pos), &data, - MIN(sizeof (data), bytes - pos)); - } + hunt_mcdi_read_response(enp, emrp->emr_out_buf, hdr_len, bytes); #if EFSYS_OPT_MCDI_LOGGING if (emtp->emt_logger != NULL) { emtp->emt_logger(emtp->emt_context, EFX_LOG_MCDI_RESPONSE, - &hdr, offset, - emrp->emr_out_buf, emrp->emr_out_length_used); + &hdr, hdr_len, + emrp->emr_out_buf, bytes); } #endif /* EFSYS_OPT_MCDI_LOGGING */ } @@ -286,19 +280,39 @@ return (EFX_DWORD_FIELD(hdr, MCDI_HEADER_RESPONSE) ? B_TRUE : B_FALSE); } + void +hunt_mcdi_read_response( + __in efx_nic_t *enp, + __out void *bufferp, + __in size_t offset, + __in size_t length) +{ + const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp; + efsys_mem_t *esmp = emtp->emt_dma_mem; + unsigned int pos; + efx_dword_t data; + + for (pos = 0; pos < length; pos += sizeof (efx_dword_t)) { + EFSYS_MEM_READD(esmp, offset + pos, &data); + memcpy((uint8_t *)bufferp + pos, &data, + MIN(sizeof (data), length - pos)); + } +} + __checkReturn boolean_t hunt_mcdi_request_poll( __in efx_nic_t *enp) { - efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); +#if EFSYS_OPT_MCDI_LOGGING const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp; - efsys_mem_t *esmp = emtp->emt_dma_mem; +#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; - unsigned int length; - size_t offset; int state; efx_rc_t rc; @@ -311,8 +325,6 @@ EFSYS_ASSERT(!emip->emi_ev_cpl); emrp = emip->emi_pending_req; - offset = 0; - /* Check if a response is available */ if (hunt_mcdi_poll_response(enp) == B_FALSE) { EFSYS_UNLOCK(enp->en_eslp, state); @@ -320,17 +332,19 @@ } /* Read the response header */ - EFSYS_MEM_READD(esmp, offset, &hdr[0]); - offset += sizeof (efx_dword_t); + 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) { - EFSYS_MEM_READD(esmp, offset, &hdr[1]); - offset += sizeof (efx_dword_t); + 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); - length = EFX_DWORD_FIELD(hdr[1], MC_CMD_V2_EXTN_IN_ACTUAL_LEN); + data_len = + EFX_DWORD_FIELD(hdr[1], MC_CMD_V2_EXTN_IN_ACTUAL_LEN); } else { cmd = EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_CODE); - length = EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_DATALEN); + data_len = EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_DATALEN); } /* Request complete */ @@ -338,7 +352,7 @@ seq = (emip->emi_seq - 1) & EFX_MASK32(MCDI_HEADER_SEQ); /* Check for synchronous reboot */ - if (EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_ERROR) != 0 && length == 0) { + 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); @@ -362,34 +376,37 @@ } if (EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_ERROR)) { efx_dword_t err[2]; - int errcode; - int argnum; + 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) */ - EFSYS_MEM_READD(esmp, offset + MC_CMD_ERR_CODE_OFST, &err[0]); - errcode = EFX_DWORD_FIELD(err[0], EFX_DWORD_0); + 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); - EFSYS_MEM_READD(esmp, offset + MC_CMD_ERR_ARG_OFST, &err[1]); - argnum = EFX_DWORD_FIELD(err[1], 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, offset, - &err, sizeof (err)); + &hdr, hdr_len, + &err, err_len); } #endif /* EFSYS_OPT_MCDI_LOGGING */ - rc = efx_mcdi_request_errcode(errcode); + rc = efx_mcdi_request_errcode(err_code); if (!emrp->emr_quiet) { EFSYS_PROBE3(mcdi_err_arg, int, emrp->emr_cmd, - int, errcode, int, argnum); + int, err_code, int, err_arg); } goto fail3; } else { - emrp->emr_out_length_used = length; + emrp->emr_out_length_used = data_len; emrp->emr_rc = 0; hunt_mcdi_request_copyout(enp, emrp); } Index: head/sys/dev/sfxge/common/siena_impl.h =================================================================== --- head/sys/dev/sfxge/common/siena_impl.h +++ head/sys/dev/sfxge/common/siena_impl.h @@ -121,6 +121,13 @@ __in boolean_t ev_cpl, __in boolean_t new_epoch); +extern void +siena_mcdi_read_response( + __in efx_nic_t *enp, + __out void *bufferp, + __in size_t offset, + __in size_t length); + extern __checkReturn boolean_t siena_mcdi_request_poll( __in efx_nic_t *enp); 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 @@ -123,33 +123,22 @@ const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp; efx_dword_t hdr; #endif - efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); - unsigned int pos; - unsigned int pdur; - efx_dword_t data; - - pdur = SIENA_MCDI_PDU(emip); + size_t bytes = MIN(emrp->emr_out_length_used, emrp->emr_out_length); /* Copy payload out if caller supplied buffer */ if (emrp->emr_out_buf != NULL) { - size_t bytes = MIN(emrp->emr_out_length_used, - emrp->emr_out_length); - for (pos = 0; pos < bytes; pos += sizeof (efx_dword_t)) { - EFX_BAR_TBL_READD(enp, FR_CZ_MC_TREG_SMEM, - pdur + 1 + (pos >> 2), &data, B_FALSE); - memcpy(MCDI_OUT(*emrp, efx_dword_t, pos), &data, - MIN(sizeof (data), bytes - pos)); - } + siena_mcdi_read_response(enp, emrp->emr_out_buf, + sizeof (efx_dword_t), bytes); } #if EFSYS_OPT_MCDI_LOGGING if (emtp->emt_logger != NULL) { - EFX_BAR_TBL_READD(enp, FR_CZ_MC_TREG_SMEM, pdur, &hdr, B_FALSE); + siena_mcdi_read_response(enp, &hdr, 0, sizeof (hdr)); emtp->emt_logger(emtp->emt_context, EFX_LOG_MCDI_RESPONSE, &hdr, sizeof (hdr), - emrp->emr_out_buf, emrp->emr_out_length_used); + emrp->emr_out_buf, bytes); } #endif /* EFSYS_OPT_MCDI_LOGGING */ } @@ -206,6 +195,29 @@ return (EFX_DWORD_FIELD(hdr, MCDI_HEADER_RESPONSE) ? B_TRUE : B_FALSE); } + void +siena_mcdi_read_response( + __in efx_nic_t *enp, + __out void *bufferp, + __in size_t offset, + __in size_t length) +{ + efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); + unsigned int pdur; + unsigned int pos; + efx_dword_t data; + + EFSYS_ASSERT(emip->emi_port == 1 || emip->emi_port == 2); + pdur = SIENA_MCDI_PDU(emip); + + for (pos = 0; pos < length; pos += sizeof (efx_dword_t)) { + EFX_BAR_TBL_READD(enp, FR_CZ_MC_TREG_SMEM, + pdur + ((offset + pos) >> 2), &data, B_FALSE); + memcpy((uint8_t *)bufferp + pos, &data, + MIN(sizeof (data), length - pos)); + } +} + __checkReturn boolean_t siena_mcdi_request_poll( __in efx_nic_t *enp) @@ -216,9 +228,9 @@ efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); efx_mcdi_req_t *emrp; efx_dword_t hdr; - unsigned int pdur; + unsigned int hdr_len; + unsigned int data_len; unsigned int seq; - unsigned int length; int state; efx_rc_t rc; @@ -241,9 +253,6 @@ } } - EFSYS_ASSERT(emip->emi_port == 1 || emip->emi_port == 2); - pdur = SIENA_MCDI_PDU(emip); - /* Check if a response is available */ if (siena_mcdi_poll_response(enp) == B_FALSE) { EFSYS_UNLOCK(enp->en_eslp, state); @@ -251,7 +260,8 @@ } /* Read the response header */ - EFX_BAR_TBL_READD(enp, FR_CZ_MC_TREG_SMEM, pdur, &hdr, B_FALSE); + hdr_len = sizeof (hdr); + siena_mcdi_read_response(enp, &hdr, 0, hdr_len); /* Request complete */ emip->emi_pending_req = NULL; @@ -278,35 +288,36 @@ goto fail3; } - length = EFX_DWORD_FIELD(hdr, MCDI_HEADER_DATALEN); + data_len = EFX_DWORD_FIELD(hdr, MCDI_HEADER_DATALEN); if (EFX_DWORD_FIELD(hdr, MCDI_HEADER_ERROR)) { - efx_dword_t errdword; - int errcode; + efx_dword_t err; + int err_code = MC_CMD_ERR_EPROTO; + unsigned int err_len = MIN(data_len, sizeof (err)); - EFSYS_ASSERT3U(length, ==, 4); - EFX_BAR_TBL_READD(enp, FR_CZ_MC_TREG_SMEM, - pdur + 1 + (MC_CMD_ERR_CODE_OFST >> 2), - &errdword, B_FALSE); - errcode = EFX_DWORD_FIELD(errdword, EFX_DWORD_0); + /* 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, sizeof (hdr), - &errdword, sizeof (errdword)); + &hdr, hdr_len, + &err, err_len); } #endif /* EFSYS_OPT_MCDI_LOGGING */ - rc = efx_mcdi_request_errcode(errcode); + rc = efx_mcdi_request_errcode(err_code); if (!emrp->emr_quiet) { EFSYS_PROBE2(mcdi_err, int, emrp->emr_cmd, - int, errcode); + int, err_code); } goto fail4; } else { - emrp->emr_out_length_used = length; + emrp->emr_out_length_used = data_len; emrp->emr_rc = 0; siena_mcdi_request_copyout(enp, emrp); }