summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornp <np@FreeBSD.org>2012-08-16 18:31:50 +0000
committernp <np@FreeBSD.org>2012-08-16 18:31:50 +0000
commitc7341dcaf2fa694c9d87bebc6ca147bd08145dd4 (patch)
treec9303f00f31090d659e2981c310593863697bd6a
parent05949946d9fee4725e201f8b2d233420c2c74983 (diff)
downloadFreeBSD-src-c7341dcaf2fa694c9d87bebc6ca147bd08145dd4.zip
FreeBSD-src-c7341dcaf2fa694c9d87bebc6ca147bd08145dd4.tar.gz
Allow for a different handler for each type of firmware message.
MFC after: 2 weeks
-rw-r--r--sys/dev/cxgbe/adapter.h5
-rw-r--r--sys/dev/cxgbe/common/t4_msg.h2
-rw-r--r--sys/dev/cxgbe/t4_main.c40
-rw-r--r--sys/dev/cxgbe/t4_sge.c16
4 files changed, 52 insertions, 11 deletions
diff --git a/sys/dev/cxgbe/adapter.h b/sys/dev/cxgbe/adapter.h
index 5b0efa1..b6bffda 100644
--- a/sys/dev/cxgbe/adapter.h
+++ b/sys/dev/cxgbe/adapter.h
@@ -510,6 +510,7 @@ struct rss_header;
typedef int (*cpl_handler_t)(struct sge_iq *, const struct rss_header *,
struct mbuf *);
typedef int (*an_handler_t)(struct sge_iq *, const struct rsp_ctrl *);
+typedef int (*fw_msg_handler_t)(struct adapter *, const __be64 *);
struct adapter {
SLIST_ENTRY(adapter) link;
@@ -582,7 +583,8 @@ struct adapter {
struct callout sfl_callout;
an_handler_t an_handler __aligned(CACHE_LINE_SIZE);
- cpl_handler_t cpl_handler[256];
+ fw_msg_handler_t fw_msg_handler[4]; /* NUM_FW6_TYPES */
+ cpl_handler_t cpl_handler[0xef]; /* NUM_CPL_CMDS */
};
#define ADAPTER_LOCK(sc) mtx_lock(&(sc)->sc_lock)
@@ -741,6 +743,7 @@ void t4_os_link_changed(struct adapter *, int, int);
void t4_iterate(void (*)(struct adapter *, void *), void *);
int t4_register_cpl_handler(struct adapter *, int, cpl_handler_t);
int t4_register_an_handler(struct adapter *, an_handler_t);
+int t4_register_fw_msg_handler(struct adapter *, int, fw_msg_handler_t);
/* t4_sge.c */
void t4_sge_modload(void);
diff --git a/sys/dev/cxgbe/common/t4_msg.h b/sys/dev/cxgbe/common/t4_msg.h
index f1d86b2..d6c01e2 100644
--- a/sys/dev/cxgbe/common/t4_msg.h
+++ b/sys/dev/cxgbe/common/t4_msg.h
@@ -2281,6 +2281,8 @@ enum {
FW6_TYPE_WR_RPL = 1,
FW6_TYPE_CQE = 2,
FW6_TYPE_OFLD_CONNECTION_WR_RPL = 3,
+
+ NUM_FW6_TYPES
};
struct cpl_fw6_msg_ofld_connection_wr_rpl {
diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c
index 61cb849..c09dc46 100644
--- a/sys/dev/cxgbe/t4_main.c
+++ b/sys/dev/cxgbe/t4_main.c
@@ -306,6 +306,7 @@ static void cxgbe_vlan_config(void *, struct ifnet *, uint16_t);
static int cpl_not_handled(struct sge_iq *, const struct rss_header *,
struct mbuf *);
static int an_not_handled(struct sge_iq *, const struct rsp_ctrl *);
+static int fw_msg_not_handled(struct adapter *, const __be64 *);
static int t4_sysctls(struct adapter *);
static int cxgbe_sysctls(struct port_info *);
static int sysctl_int_array(SYSCTL_HANDLER_ARGS);
@@ -381,6 +382,10 @@ CTASSERT(offsetof(struct sge_ofld_rxq, iq) == offsetof(struct sge_rxq, iq));
CTASSERT(offsetof(struct sge_ofld_rxq, fl) == offsetof(struct sge_rxq, fl));
#endif
+/* No easy way to include t4_msg.h before adapter.h so we check this way */
+CTASSERT(ARRAY_SIZE(((struct adapter *)0)->cpl_handler) == NUM_CPL_CMDS);
+CTASSERT(ARRAY_SIZE(((struct adapter *)0)->fw_msg_handler) == NUM_FW6_TYPES);
+
static int
t4_probe(device_t dev)
{
@@ -458,6 +463,8 @@ t4_attach(device_t dev)
sc->an_handler = an_not_handled;
for (i = 0; i < ARRAY_SIZE(sc->cpl_handler); i++)
sc->cpl_handler[i] = cpl_not_handled;
+ for (i = 0; i < ARRAY_SIZE(sc->fw_msg_handler); i++)
+ sc->fw_msg_handler[i] = fw_msg_not_handled;
t4_register_cpl_handler(sc, CPL_SET_TCB_RPL, filter_rpl);
/* Prepare the adapter for operation */
@@ -2980,7 +2987,7 @@ cpl_not_handled(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
panic("%s: opcode 0x%02x on iq %p with payload %p",
__func__, rss->opcode, iq, m);
#else
- log(LOG_ERR, "%s: opcode 0x%02x on iq %p with payload %p",
+ log(LOG_ERR, "%s: opcode 0x%02x on iq %p with payload %p\n",
__func__, rss->opcode, iq, m);
m_freem(m);
#endif
@@ -3009,7 +3016,7 @@ an_not_handled(struct sge_iq *iq, const struct rsp_ctrl *ctrl)
#ifdef INVARIANTS
panic("%s: async notification on iq %p (ctrl %p)", __func__, iq, ctrl);
#else
- log(LOG_ERR, "%s: async notification on iq %p (ctrl %p)",
+ log(LOG_ERR, "%s: async notification on iq %p (ctrl %p)\n",
__func__, iq, ctrl);
#endif
return (EDOOFUS);
@@ -3028,6 +3035,35 @@ t4_register_an_handler(struct adapter *sc, an_handler_t h)
}
static int
+fw_msg_not_handled(struct adapter *sc, const __be64 *rpl)
+{
+ __be64 *r = __DECONST(__be64 *, rpl);
+ struct cpl_fw6_msg *cpl = member2struct(cpl_fw6_msg, data, r);
+
+#ifdef INVARIANTS
+ panic("%s: fw_msg type %d", __func__, cpl->type);
+#else
+ log(LOG_ERR, "%s: fw_msg type %d\n", __func__, cpl->type);
+#endif
+ return (EDOOFUS);
+}
+
+int
+t4_register_fw_msg_handler(struct adapter *sc, int type, fw_msg_handler_t h)
+{
+ uintptr_t *loc, new;
+
+ if (type >= ARRAY_SIZE(sc->fw_msg_handler))
+ return (EINVAL);
+
+ new = h ? (uintptr_t)h : (uintptr_t)fw_msg_not_handled;
+ loc = (uintptr_t *) &sc->fw_msg_handler[type];
+ atomic_store_rel_ptr(loc, new);
+
+ return (0);
+}
+
+static int
t4_sysctls(struct adapter *sc)
{
struct sysctl_ctx_list *ctx;
diff --git a/sys/dev/cxgbe/t4_sge.c b/sys/dev/cxgbe/t4_sge.c
index 09e5518..8e0daac 100644
--- a/sys/dev/cxgbe/t4_sge.c
+++ b/sys/dev/cxgbe/t4_sge.c
@@ -185,7 +185,7 @@ static void write_eqflush_wr(struct sge_eq *);
static __be64 get_flit(bus_dma_segment_t *, int, int);
static int handle_sge_egr_update(struct sge_iq *, const struct rss_header *,
struct mbuf *);
-static int handle_fw_rpl(struct sge_iq *, const struct rss_header *,
+static int handle_fw_msg(struct sge_iq *, const struct rss_header *,
struct mbuf *);
static int sysctl_uint16(SYSCTL_HANDLER_ARGS);
@@ -361,11 +361,13 @@ t4_sge_init(struct adapter *sc)
sc->sge.timer_val[4] = G_TIMERVALUE4(v) / core_ticks_per_usec(sc);
sc->sge.timer_val[5] = G_TIMERVALUE5(v) / core_ticks_per_usec(sc);
- t4_register_cpl_handler(sc, CPL_FW4_MSG, handle_fw_rpl);
- t4_register_cpl_handler(sc, CPL_FW6_MSG, handle_fw_rpl);
+ t4_register_cpl_handler(sc, CPL_FW4_MSG, handle_fw_msg);
+ t4_register_cpl_handler(sc, CPL_FW6_MSG, handle_fw_msg);
t4_register_cpl_handler(sc, CPL_SGE_EGR_UPDATE, handle_sge_egr_update);
t4_register_cpl_handler(sc, CPL_RX_PKT, t4_eth_rx);
+ t4_register_fw_msg_handler(sc, FW6_TYPE_CMD_RPL, t4_handle_fw_rpl);
+
return (rc);
}
@@ -3520,17 +3522,15 @@ handle_sge_egr_update(struct sge_iq *iq, const struct rss_header *rss,
}
static int
-handle_fw_rpl(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
+handle_fw_msg(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
{
+ struct adapter *sc = iq->adapter;
const struct cpl_fw6_msg *cpl = (const void *)(rss + 1);
KASSERT(m == NULL, ("%s: payload with opcode %02x", __func__,
rss->opcode));
- if (cpl->type == FW6_TYPE_CMD_RPL)
- t4_handle_fw_rpl(iq->adapter, cpl->data);
-
- return (0);
+ return (sc->fw_msg_handler[cpl->type](sc, &cpl->data[0]));
}
static int
OpenPOWER on IntegriCloud