sfxge: add MCDI logging support to common code

Submitted by:   Andy Moreton <amoreton at solarflare.com>
Sponsored by:   Solarflare Communications, Inc.
MFC after:      2 days
Differential Revision: https://reviews.freebsd.org/D4331
This commit is contained in:
arybchik 2015-12-03 07:13:13 +00:00
parent 1f49e276c3
commit 3314a1ba8f
6 changed files with 132 additions and 47 deletions

View File

@ -245,6 +245,7 @@ sfxge_map_mbuf_fast(bus_dma_tag_t tag, bus_dmamap_t map,
#endif
#define EFSYS_OPT_MCDI 1
#define EFSYS_OPT_MCDI_LOGGING 0
#define EFSYS_OPT_MAC_FALCON_GMAC 0
#define EFSYS_OPT_MAC_FALCON_XMAC 0

View File

@ -201,12 +201,25 @@ typedef enum efx_mcdi_exception_e {
EFX_MCDI_EXCEPTION_MC_BADASSERT,
} efx_mcdi_exception_t;
#if EFSYS_OPT_MCDI_LOGGING
typedef enum efx_log_msg_e
{
EFX_LOG_INVALID,
EFX_LOG_MCDI_REQUEST,
EFX_LOG_MCDI_RESPONSE,
} efx_log_msg_t;
#endif /* EFSYS_OPT_MCDI_LOGGING */
typedef struct efx_mcdi_transport_s {
void *emt_context;
efsys_mem_t *emt_dma_mem;
void (*emt_execute)(void *, efx_mcdi_req_t *);
void (*emt_ev_cpl)(void *);
void (*emt_exception)(void *, efx_mcdi_exception_t);
#if EFSYS_OPT_MCDI_LOGGING
void (*emt_logger)(void *, efx_log_msg_t,
void *, size_t, void *, size_t);
#endif /* EFSYS_OPT_MCDI_LOGGING */
} efx_mcdi_transport_t;
extern __checkReturn efx_rc_t

View File

@ -146,6 +146,13 @@
# error "HUNTINGTON requires MCDI"
#endif
/* Support MCDI logging */
#if EFSYS_OPT_MCDI_LOGGING
# if !EFSYS_OPT_MCDI
# error "MCDI_LOGGING requires MCDI"
# endif
#endif /* EFSYS_OPT_MCDI_LOGGING */
/* Support LM87 monitor */
#if EFSYS_OPT_MON_LM87
# if !EFSYS_OPT_FALCON

View File

@ -468,9 +468,8 @@ efx_mcdi_ev_cpl(
} else {
emrp->emr_out_length_used = outlen;
emrp->emr_rc = 0;
emcop->emco_request_copyout(enp, emrp);
}
emcop->emco_request_copyout(enp, emrp);
emtp->emt_ev_cpl(emtp->emt_context);
}

View File

@ -143,6 +143,7 @@ hunt_mcdi_request_copyin(
efsys_mem_t *esmp = emtp->emt_dma_mem;
efx_mcdi_header_type_t hdr_type;
efx_dword_t dword;
efx_dword_t hdr[2];
unsigned int xflags;
unsigned int pos;
size_t offset;
@ -160,7 +161,7 @@ hunt_mcdi_request_copyin(
if (hdr_type == EFX_MCDI_HEADER_TYPE_V2) {
/* Construct MCDI v2 header */
EFX_POPULATE_DWORD_8(dword,
EFX_POPULATE_DWORD_8(hdr[0],
MCDI_HEADER_CODE, MC_CMD_V2_EXTN,
MCDI_HEADER_RESYNC, 1,
MCDI_HEADER_DATALEN, 0,
@ -169,17 +170,17 @@ hunt_mcdi_request_copyin(
MCDI_HEADER_ERROR, 0,
MCDI_HEADER_RESPONSE, 0,
MCDI_HEADER_XFLAGS, xflags);
EFSYS_MEM_WRITED(esmp, offset, &dword);
offset += sizeof (dword);
EFSYS_MEM_WRITED(esmp, offset, &hdr[0]);
offset += sizeof (efx_dword_t);
EFX_POPULATE_DWORD_2(dword,
EFX_POPULATE_DWORD_2(hdr[1],
MC_CMD_V2_EXTN_IN_EXTENDED_CMD, emrp->emr_cmd,
MC_CMD_V2_EXTN_IN_ACTUAL_LEN, emrp->emr_in_length);
EFSYS_MEM_WRITED(esmp, offset, &dword);
offset += sizeof (dword);
EFSYS_MEM_WRITED(esmp, offset, &hdr[1]);
offset += sizeof (efx_dword_t);
} else {
/* Construct MCDI v1 header */
EFX_POPULATE_DWORD_8(dword,
EFX_POPULATE_DWORD_8(hdr[0],
MCDI_HEADER_CODE, emrp->emr_cmd,
MCDI_HEADER_RESYNC, 1,
MCDI_HEADER_DATALEN, emrp->emr_in_length,
@ -188,10 +189,18 @@ hunt_mcdi_request_copyin(
MCDI_HEADER_ERROR, 0,
MCDI_HEADER_RESPONSE, 0,
MCDI_HEADER_XFLAGS, xflags);
EFSYS_MEM_WRITED(esmp, offset, &dword);
offset += sizeof (dword);
EFSYS_MEM_WRITED(esmp, 0, &hdr[0]);
offset += sizeof (efx_dword_t);
}
#if EFSYS_OPT_MCDI_LOGGING
if (emtp->emt_logger != NULL) {
emtp->emt_logger(emtp->emt_context, EFX_LOG_MCDI_REQUEST,
&hdr, offset,
emrp->emr_in_buf, emrp->emr_in_length);
}
#endif /* EFSYS_OPT_MCDI_LOGGING */
/* Construct the payload */
for (pos = 0; pos < emrp->emr_in_length; pos += sizeof (efx_dword_t)) {
memcpy(&dword, MCDI_IN(*emrp, efx_dword_t, pos),
@ -224,8 +233,7 @@ hunt_mcdi_request_copyout(
efsys_mem_t *esmp = emtp->emt_dma_mem;
unsigned int pos;
unsigned int offset;
efx_dword_t hdr;
efx_dword_t hdr2;
efx_dword_t hdr[2];
efx_dword_t data;
size_t bytes;
@ -233,16 +241,16 @@ hunt_mcdi_request_copyout(
return;
/* Read the command header to detect MCDI response format */
EFSYS_MEM_READD(esmp, 0, &hdr);
if (EFX_DWORD_FIELD(hdr, MCDI_HEADER_CODE) == MC_CMD_V2_EXTN) {
EFSYS_MEM_READD(esmp, 0, &hdr[0]);
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), &hdr2);
emrp->emr_out_length_used = EFX_DWORD_FIELD(hdr2,
EFSYS_MEM_READD(esmp, sizeof (efx_dword_t), &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);
@ -255,6 +263,15 @@ hunt_mcdi_request_copyout(
memcpy(MCDI_OUT(*emrp, efx_dword_t, pos), &data,
MIN(sizeof (data), bytes - pos));
}
#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);
}
#endif /* EFSYS_OPT_MCDI_LOGGING */
}
__checkReturn boolean_t
@ -265,7 +282,7 @@ hunt_mcdi_request_poll(
const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp;
efsys_mem_t *esmp = emtp->emt_dma_mem;
efx_mcdi_req_t *emrp;
efx_dword_t dword;
efx_dword_t hdr[2];
unsigned int seq;
unsigned int cmd;
unsigned int length;
@ -285,23 +302,21 @@ hunt_mcdi_request_poll(
offset = 0;
/* Read the command header */
EFSYS_MEM_READD(esmp, offset, &dword);
EFSYS_MEM_READD(esmp, offset, &hdr[0]);
offset += sizeof (efx_dword_t);
if (EFX_DWORD_FIELD(dword, MCDI_HEADER_RESPONSE) == 0) {
if (EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_RESPONSE) == 0) {
EFSYS_UNLOCK(enp->en_eslp, state);
return (B_FALSE);
}
if (EFX_DWORD_FIELD(dword, MCDI_HEADER_CODE) == MC_CMD_V2_EXTN) {
efx_dword_t dword2;
EFSYS_MEM_READD(esmp, offset, &dword2);
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);
cmd = EFX_DWORD_FIELD(dword2, MC_CMD_V2_EXTN_IN_EXTENDED_CMD);
length = EFX_DWORD_FIELD(dword2, MC_CMD_V2_EXTN_IN_ACTUAL_LEN);
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);
} else {
cmd = EFX_DWORD_FIELD(dword, MCDI_HEADER_CODE);
length = EFX_DWORD_FIELD(dword, MCDI_HEADER_DATALEN);
cmd = EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_CODE);
length = EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_DATALEN);
}
/* Request complete */
@ -309,7 +324,7 @@ hunt_mcdi_request_poll(
seq = (emip->emi_seq - 1) & EFX_MASK32(MCDI_HEADER_SEQ);
/* Check for synchronous reboot */
if (EFX_DWORD_FIELD(dword, MCDI_HEADER_ERROR) != 0 && length == 0) {
if (EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_ERROR) != 0 && length == 0) {
/* The MC has rebooted since the request was sent. */
EFSYS_SPIN(EFX_MCDI_STATUS_SLEEP_US);
hunt_mcdi_poll_reboot(enp);
@ -326,22 +341,31 @@ hunt_mcdi_request_poll(
/* Check that the returned data is consistent */
if (cmd != emrp->emr_cmd ||
EFX_DWORD_FIELD(dword, MCDI_HEADER_SEQ) != seq) {
EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_SEQ) != seq) {
/* Response is for a different request */
rc = EIO;
goto fail2;
}
if (EFX_DWORD_FIELD(dword, MCDI_HEADER_ERROR)) {
efx_dword_t errdword;
if (EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_ERROR)) {
efx_dword_t err[2];
int errcode;
int argnum;
/* Read error code (and arg num for MCDI v2 commands) */
EFSYS_MEM_READD(esmp, offset + MC_CMD_ERR_CODE_OFST, &errdword);
errcode = EFX_DWORD_FIELD(errdword, EFX_DWORD_0);
EFSYS_MEM_READD(esmp, offset + MC_CMD_ERR_CODE_OFST, &err[0]);
errcode = EFX_DWORD_FIELD(err[0], EFX_DWORD_0);
EFSYS_MEM_READD(esmp, offset + MC_CMD_ERR_ARG_OFST, &errdword);
argnum = EFX_DWORD_FIELD(errdword, 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 EFSYS_OPT_MCDI_LOGGING
if (emtp->emt_logger != NULL) {
emtp->emt_logger(emtp->emt_context,
EFX_LOG_MCDI_RESPONSE,
&hdr, offset,
&err, sizeof (err));
}
#endif /* EFSYS_OPT_MCDI_LOGGING */
rc = efx_mcdi_request_errcode(errcode);
if (!emrp->emr_quiet) {

View File

@ -61,7 +61,11 @@ siena_mcdi_request_copyin(
__in boolean_t ev_cpl,
__in boolean_t new_epoch)
{
#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_dword_t hdr;
efx_dword_t dword;
unsigned int xflags;
unsigned int pdur;
@ -80,15 +84,24 @@ siena_mcdi_request_copyin(
xflags |= MCDI_HEADER_XFLAGS_EVREQ;
/* Construct the header in shared memory */
EFX_POPULATE_DWORD_6(dword,
EFX_POPULATE_DWORD_6(hdr,
MCDI_HEADER_CODE, emrp->emr_cmd,
MCDI_HEADER_RESYNC, 1,
MCDI_HEADER_DATALEN, emrp->emr_in_length,
MCDI_HEADER_SEQ, seq,
MCDI_HEADER_RESPONSE, 0,
MCDI_HEADER_XFLAGS, xflags);
EFX_BAR_TBL_WRITED(enp, FR_CZ_MC_TREG_SMEM, pdur, &dword, B_TRUE);
EFX_BAR_TBL_WRITED(enp, FR_CZ_MC_TREG_SMEM, pdur, &hdr, B_TRUE);
#if EFSYS_OPT_MCDI_LOGGING
if (emtp->emt_logger != NULL) {
emtp->emt_logger(emtp->emt_context, EFX_LOG_MCDI_REQUEST,
&hdr, sizeof (hdr),
emrp->emr_in_buf, emrp->emr_in_length);
}
#endif /* EFSYS_OPT_MCDI_LOGGING */
/* Construct the payload */
for (pos = 0; pos < emrp->emr_in_length; pos += sizeof (efx_dword_t)) {
memcpy(&dword, MCDI_IN(*emrp, efx_dword_t, pos),
MIN(sizeof (dword), emrp->emr_in_length - pos));
@ -106,6 +119,10 @@ siena_mcdi_request_copyout(
__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;
efx_dword_t hdr;
#endif
efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
unsigned int pos;
unsigned int pdur;
@ -124,6 +141,17 @@ siena_mcdi_request_copyout(
MIN(sizeof (data), bytes - pos));
}
}
#if EFSYS_OPT_MCDI_LOGGING
if (emtp->emt_logger != NULL) {
EFX_BAR_TBL_READD(enp, FR_CZ_MC_TREG_SMEM, pdur, &hdr, B_FALSE);
emtp->emt_logger(emtp->emt_context,
EFX_LOG_MCDI_RESPONSE,
&hdr, sizeof (hdr),
emrp->emr_out_buf, emrp->emr_out_length_used);
}
#endif /* EFSYS_OPT_MCDI_LOGGING */
}
efx_rc_t
@ -167,9 +195,12 @@ siena_mcdi_poll_reboot(
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 dword;
efx_dword_t hdr;
unsigned int pdur;
unsigned int seq;
unsigned int length;
@ -199,8 +230,8 @@ siena_mcdi_request_poll(
pdur = SIENA_MCDI_PDU(emip);
/* Read the command header */
EFX_BAR_TBL_READD(enp, FR_CZ_MC_TREG_SMEM, pdur, &dword, B_FALSE);
if (EFX_DWORD_FIELD(dword, MCDI_HEADER_RESPONSE) == 0) {
EFX_BAR_TBL_READD(enp, FR_CZ_MC_TREG_SMEM, pdur, &hdr, B_FALSE);
if (EFX_DWORD_FIELD(hdr, MCDI_HEADER_RESPONSE) == 0) {
EFSYS_UNLOCK(enp->en_eslp, state);
return (B_FALSE);
}
@ -210,8 +241,8 @@ siena_mcdi_request_poll(
seq = (emip->emi_seq - 1) & EFX_MASK32(MCDI_HEADER_SEQ);
/* Check for synchronous reboot */
if (EFX_DWORD_FIELD(dword, MCDI_HEADER_ERROR) != 0 &&
EFX_DWORD_FIELD(dword, MCDI_HEADER_DATALEN) == 0) {
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);
@ -223,15 +254,15 @@ siena_mcdi_request_poll(
EFSYS_UNLOCK(enp->en_eslp, state);
/* Check that the returned data is consistent */
if (EFX_DWORD_FIELD(dword, MCDI_HEADER_CODE) != emrp->emr_cmd ||
EFX_DWORD_FIELD(dword, MCDI_HEADER_SEQ) != seq) {
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;
}
length = EFX_DWORD_FIELD(dword, MCDI_HEADER_DATALEN);
if (EFX_DWORD_FIELD(dword, MCDI_HEADER_ERROR)) {
length = EFX_DWORD_FIELD(hdr, MCDI_HEADER_DATALEN);
if (EFX_DWORD_FIELD(hdr, MCDI_HEADER_ERROR)) {
efx_dword_t errdword;
int errcode;
@ -240,6 +271,16 @@ siena_mcdi_request_poll(
pdur + 1 + (MC_CMD_ERR_CODE_OFST >> 2),
&errdword, B_FALSE);
errcode = EFX_DWORD_FIELD(errdword, 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));
}
#endif /* EFSYS_OPT_MCDI_LOGGING */
rc = efx_mcdi_request_errcode(errcode);
if (!emrp->emr_quiet) {
EFSYS_PROBE2(mcdi_err, int, emrp->emr_cmd,