Install a handler for firmware work request error messages.
If a driver sends an malformed or disallowed work request, the firmware responds with a work request error. Previously the driver treated this is as an unexpected message and panicked. Now it decodes the error message to aid in debugging. Reviewed by: np (older version) MFC after: 1 month Sponsored by: Chelsio Communications Differential Revision: https://reviews.freebsd.org/D6950
This commit is contained in:
parent
879e0b3e70
commit
069af0eb14
@ -244,6 +244,7 @@ static int handle_sge_egr_update(struct sge_iq *, const struct rss_header *,
|
||||
struct mbuf *);
|
||||
static int handle_fw_msg(struct sge_iq *, const struct rss_header *,
|
||||
struct mbuf *);
|
||||
static int t4_handle_wrerr_rpl(struct adapter *, const __be64 *);
|
||||
static void wrq_tx_drain(void *, int);
|
||||
static void drain_wrq_wr_list(struct adapter *, struct sge_wrq *);
|
||||
|
||||
@ -402,6 +403,7 @@ t4_sge_modload(void)
|
||||
t4_register_cpl_handler(CPL_SGE_EGR_UPDATE, handle_sge_egr_update);
|
||||
t4_register_cpl_handler(CPL_RX_PKT, t4_eth_rx);
|
||||
t4_register_fw_msg_handler(FW6_TYPE_CMD_RPL, t4_handle_fw_rpl);
|
||||
t4_register_fw_msg_handler(FW6_TYPE_WRERR_RPL, t4_handle_wrerr_rpl);
|
||||
}
|
||||
|
||||
void
|
||||
@ -4782,6 +4784,71 @@ handle_fw_msg(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
|
||||
return (t4_fw_msg_handler[cpl->type](sc, &cpl->data[0]));
|
||||
}
|
||||
|
||||
/**
|
||||
* t4_handle_wrerr_rpl - process a FW work request error message
|
||||
* @adap: the adapter
|
||||
* @rpl: start of the FW message
|
||||
*/
|
||||
static int
|
||||
t4_handle_wrerr_rpl(struct adapter *adap, const __be64 *rpl)
|
||||
{
|
||||
u8 opcode = *(const u8 *)rpl;
|
||||
const struct fw_error_cmd *e = (const void *)rpl;
|
||||
unsigned int i;
|
||||
|
||||
if (opcode != FW_ERROR_CMD) {
|
||||
log(LOG_ERR,
|
||||
"%s: Received WRERR_RPL message with opcode %#x\n",
|
||||
device_get_nameunit(adap->dev), opcode);
|
||||
return (EINVAL);
|
||||
}
|
||||
log(LOG_ERR, "%s: FW_ERROR (%s) ", device_get_nameunit(adap->dev),
|
||||
G_FW_ERROR_CMD_FATAL(be32toh(e->op_to_type)) ? "fatal" :
|
||||
"non-fatal");
|
||||
switch (G_FW_ERROR_CMD_TYPE(be32toh(e->op_to_type))) {
|
||||
case FW_ERROR_TYPE_EXCEPTION:
|
||||
log(LOG_ERR, "exception info:\n");
|
||||
for (i = 0; i < nitems(e->u.exception.info); i++)
|
||||
log(LOG_ERR, "%s%08x", i == 0 ? "\t" : " ",
|
||||
be32toh(e->u.exception.info[i]));
|
||||
log(LOG_ERR, "\n");
|
||||
break;
|
||||
case FW_ERROR_TYPE_HWMODULE:
|
||||
log(LOG_ERR, "HW module regaddr %08x regval %08x\n",
|
||||
be32toh(e->u.hwmodule.regaddr),
|
||||
be32toh(e->u.hwmodule.regval));
|
||||
break;
|
||||
case FW_ERROR_TYPE_WR:
|
||||
log(LOG_ERR, "WR cidx %d PF %d VF %d eqid %d hdr:\n",
|
||||
be16toh(e->u.wr.cidx),
|
||||
G_FW_ERROR_CMD_PFN(be16toh(e->u.wr.pfn_vfn)),
|
||||
G_FW_ERROR_CMD_VFN(be16toh(e->u.wr.pfn_vfn)),
|
||||
be32toh(e->u.wr.eqid));
|
||||
for (i = 0; i < nitems(e->u.wr.wrhdr); i++)
|
||||
log(LOG_ERR, "%s%02x", i == 0 ? "\t" : " ",
|
||||
e->u.wr.wrhdr[i]);
|
||||
log(LOG_ERR, "\n");
|
||||
break;
|
||||
case FW_ERROR_TYPE_ACL:
|
||||
log(LOG_ERR, "ACL cidx %d PF %d VF %d eqid %d %s",
|
||||
be16toh(e->u.acl.cidx),
|
||||
G_FW_ERROR_CMD_PFN(be16toh(e->u.acl.pfn_vfn)),
|
||||
G_FW_ERROR_CMD_VFN(be16toh(e->u.acl.pfn_vfn)),
|
||||
be32toh(e->u.acl.eqid),
|
||||
G_FW_ERROR_CMD_MV(be16toh(e->u.acl.mv_pkd)) ? "vlanid" :
|
||||
"MAC");
|
||||
for (i = 0; i < nitems(e->u.acl.val); i++)
|
||||
log(LOG_ERR, " %02x", e->u.acl.val[i]);
|
||||
log(LOG_ERR, "\n");
|
||||
break;
|
||||
default:
|
||||
log(LOG_ERR, "type %#x\n",
|
||||
G_FW_ERROR_CMD_TYPE(be32toh(e->op_to_type)));
|
||||
return (EINVAL);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
sysctl_uint16(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user