summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2016-11-04 21:43:10 +0000
committerjhb <jhb@FreeBSD.org>2016-11-04 21:43:10 +0000
commit5d45cb0e371564824664c32f312376d51ded5a8e (patch)
tree3be4f626b101cfa8ba44ffa1b5d7e828c3b7c805
parentfcd0752232f1d6e2f643cb33ced40ed7901f1934 (diff)
downloadFreeBSD-src-5d45cb0e371564824664c32f312376d51ded5a8e.zip
FreeBSD-src-5d45cb0e371564824664c32f312376d51ded5a8e.tar.gz
MFC 297776,297777,297779: Add DDB commands to cxgbe(4).
297776: Add a function to lookup a device_t object by name. This just walks the global list of devices looking for one with the requested name. The one use case outside of devctl2's implementation is for DDB commands that wish to lookup devices by name. 297777: Add a 'show t4 tcb <nexus> <tid>' command to dump a TCB from DDB. This allows the contents of a TCB to be extracted from a T4/T5 card in DDB after a panic. 297779: Add a 'show t4 devlog <nexus>' DDB command. This command displays the adapter's firmware device log similar to the dev.<nexus>.misc.devlog sysctl. Sponsored by: Chelsio Communications
-rw-r--r--sys/dev/cxgbe/t4_main.c178
-rw-r--r--sys/dev/cxgbe/tom/t4_ddp.c25
-rw-r--r--sys/kern/subr_bus.c22
-rw-r--r--sys/modules/cxgbe/if_cxgbe/Makefile1
-rw-r--r--sys/sys/bus.h1
5 files changed, 196 insertions, 31 deletions
diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c
index f64ce21..90c4dfa 100644
--- a/sys/dev/cxgbe/t4_main.c
+++ b/sys/dev/cxgbe/t4_main.c
@@ -28,6 +28,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_ddb.h"
#include "opt_inet.h"
#include "opt_inet6.h"
@@ -64,6 +65,10 @@ __FBSDID("$FreeBSD$");
#include <vm/vm.h>
#include <vm/pmap.h>
#endif
+#ifdef DDB
+#include <ddb/ddb.h>
+#include <ddb/db_lex.h>
+#endif
#include "common/common.h"
#include "common/t4_msg.h"
@@ -9095,6 +9100,179 @@ tweak_tunables(void)
t4_intr_types &= INTR_MSIX | INTR_MSI | INTR_INTX;
}
+#ifdef DDB
+static void
+t4_dump_tcb(struct adapter *sc, int tid)
+{
+ uint32_t base, i, j, off, pf, reg, save, tcb_addr, win_pos;
+
+ reg = PCIE_MEM_ACCESS_REG(A_PCIE_MEM_ACCESS_OFFSET, 2);
+ save = t4_read_reg(sc, reg);
+ base = sc->memwin[2].mw_base;
+
+ /* Dump TCB for the tid */
+ tcb_addr = t4_read_reg(sc, A_TP_CMM_TCB_BASE);
+ tcb_addr += tid * TCB_SIZE;
+
+ if (is_t4(sc)) {
+ pf = 0;
+ win_pos = tcb_addr & ~0xf; /* start must be 16B aligned */
+ } else {
+ pf = V_PFNUM(sc->pf);
+ win_pos = tcb_addr & ~0x7f; /* start must be 128B aligned */
+ }
+ t4_write_reg(sc, reg, win_pos | pf);
+ t4_read_reg(sc, reg);
+
+ off = tcb_addr - win_pos;
+ for (i = 0; i < 4; i++) {
+ uint32_t buf[8];
+ for (j = 0; j < 8; j++, off += 4)
+ buf[j] = htonl(t4_read_reg(sc, base + off));
+
+ db_printf("%08x %08x %08x %08x %08x %08x %08x %08x\n",
+ buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6],
+ buf[7]);
+ }
+
+ t4_write_reg(sc, reg, save);
+ t4_read_reg(sc, reg);
+}
+
+static void
+t4_dump_devlog(struct adapter *sc)
+{
+ struct devlog_params *dparams = &sc->params.devlog;
+ struct fw_devlog_e e;
+ int i, first, j, m, nentries, rc;
+ uint64_t ftstamp = UINT64_MAX;
+
+ if (dparams->start == 0) {
+ db_printf("devlog params not valid\n");
+ return;
+ }
+
+ nentries = dparams->size / sizeof(struct fw_devlog_e);
+ m = fwmtype_to_hwmtype(dparams->memtype);
+
+ /* Find the first entry. */
+ first = -1;
+ for (i = 0; i < nentries && !db_pager_quit; i++) {
+ rc = -t4_mem_read(sc, m, dparams->start + i * sizeof(e),
+ sizeof(e), (void *)&e);
+ if (rc != 0)
+ break;
+
+ if (e.timestamp == 0)
+ break;
+
+ e.timestamp = be64toh(e.timestamp);
+ if (e.timestamp < ftstamp) {
+ ftstamp = e.timestamp;
+ first = i;
+ }
+ }
+
+ if (first == -1)
+ return;
+
+ i = first;
+ do {
+ rc = -t4_mem_read(sc, m, dparams->start + i * sizeof(e),
+ sizeof(e), (void *)&e);
+ if (rc != 0)
+ return;
+
+ if (e.timestamp == 0)
+ return;
+
+ e.timestamp = be64toh(e.timestamp);
+ e.seqno = be32toh(e.seqno);
+ for (j = 0; j < 8; j++)
+ e.params[j] = be32toh(e.params[j]);
+
+ db_printf("%10d %15ju %8s %8s ",
+ e.seqno, e.timestamp,
+ (e.level < nitems(devlog_level_strings) ?
+ devlog_level_strings[e.level] : "UNKNOWN"),
+ (e.facility < nitems(devlog_facility_strings) ?
+ devlog_facility_strings[e.facility] : "UNKNOWN"));
+ db_printf(e.fmt, e.params[0], e.params[1], e.params[2],
+ e.params[3], e.params[4], e.params[5], e.params[6],
+ e.params[7]);
+
+ if (++i == nentries)
+ i = 0;
+ } while (i != first && !db_pager_quit);
+}
+
+static struct command_table db_t4_table = LIST_HEAD_INITIALIZER(db_t4_table);
+_DB_SET(_show, t4, NULL, db_show_table, 0, &db_t4_table);
+
+DB_FUNC(devlog, db_show_devlog, db_t4_table, CS_OWN, NULL)
+{
+ device_t dev;
+ int t;
+ bool valid;
+
+ valid = false;
+ t = db_read_token();
+ if (t == tIDENT) {
+ dev = device_lookup_by_name(db_tok_string);
+ valid = true;
+ }
+ db_skip_to_eol();
+ if (!valid) {
+ db_printf("usage: show t4 devlog <nexus>\n");
+ return;
+ }
+
+ if (dev == NULL) {
+ db_printf("device not found\n");
+ return;
+ }
+
+ t4_dump_devlog(device_get_softc(dev));
+}
+
+DB_FUNC(tcb, db_show_t4tcb, db_t4_table, CS_OWN, NULL)
+{
+ device_t dev;
+ int radix, tid, t;
+ bool valid;
+
+ valid = false;
+ radix = db_radix;
+ db_radix = 10;
+ t = db_read_token();
+ if (t == tIDENT) {
+ dev = device_lookup_by_name(db_tok_string);
+ t = db_read_token();
+ if (t == tNUMBER) {
+ tid = db_tok_number;
+ valid = true;
+ }
+ }
+ db_radix = radix;
+ db_skip_to_eol();
+ if (!valid) {
+ db_printf("usage: show t4 tcb <nexus> <tid>\n");
+ return;
+ }
+
+ if (dev == NULL) {
+ db_printf("device not found\n");
+ return;
+ }
+ if (tid < 0) {
+ db_printf("invalid tid\n");
+ return;
+ }
+
+ t4_dump_tcb(device_get_softc(dev), tid);
+}
+#endif
+
static struct sx mlu; /* mod load unload */
SX_SYSINIT(cxgbe_mlu, &mlu, "cxgbe mod load/unload");
diff --git a/sys/dev/cxgbe/tom/t4_ddp.c b/sys/dev/cxgbe/tom/t4_ddp.c
index 90d646a..777eb46 100644
--- a/sys/dev/cxgbe/tom/t4_ddp.c
+++ b/sys/dev/cxgbe/tom/t4_ddp.c
@@ -80,31 +80,6 @@ static struct mbuf *get_ddp_mbuf(int len);
/* XXX: must match A_ULP_RX_TDDP_PSZ */
static int t4_ddp_pgsz[] = {4096, 4096 << 2, 4096 << 4, 4096 << 6};
-#if 0
-static void
-t4_dump_tcb(struct adapter *sc, int tid)
-{
- uint32_t tcb_base, off, i, j;
-
- /* Dump TCB for the tid */
- tcb_base = t4_read_reg(sc, A_TP_CMM_TCB_BASE);
- t4_write_reg(sc, PCIE_MEM_ACCESS_REG(A_PCIE_MEM_ACCESS_OFFSET, 2),
- tcb_base + tid * TCB_SIZE);
- t4_read_reg(sc, PCIE_MEM_ACCESS_REG(A_PCIE_MEM_ACCESS_OFFSET, 2));
- off = 0;
- printf("\n");
- for (i = 0; i < 4; i++) {
- uint32_t buf[8];
- for (j = 0; j < 8; j++, off += 4)
- buf[j] = htonl(t4_read_reg(sc, MEMWIN2_BASE + off));
-
- printf("%08x %08x %08x %08x %08x %08x %08x %08x\n",
- buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6],
- buf[7]);
- }
-}
-#endif
-
#define MAX_DDP_BUFFER_SIZE (M_TCB_RX_DDP_BUF0_LEN)
static int
alloc_ppods(struct tom_data *td, int n, u_int *ppod_addr)
diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c
index 6ccda55..1a22efe 100644
--- a/sys/kern/subr_bus.c
+++ b/sys/kern/subr_bus.c
@@ -5003,6 +5003,18 @@ bus_free_resource(device_t dev, int type, struct resource *r)
return (bus_release_resource(dev, type, rman_get_rid(r), r));
}
+device_t
+device_lookup_by_name(const char *name)
+{
+ device_t dev;
+
+ TAILQ_FOREACH(dev, &bus_data_devices, devlink) {
+ if (dev->nameunit != NULL && strcmp(dev->nameunit, name) == 0)
+ return (dev);
+ }
+ return (NULL);
+}
+
/*
* /dev/devctl2 implementation. The existing /dev/devctl device has
* implicit semantics on open, so it could not be reused for this.
@@ -5023,12 +5035,10 @@ find_device(struct devreq *req, device_t *devp)
* Second, try to find an attached device whose name matches
* 'name'.
*/
- TAILQ_FOREACH(dev, &bus_data_devices, devlink) {
- if (dev->nameunit != NULL &&
- strcmp(dev->nameunit, req->dr_name) == 0) {
- *devp = dev;
- return (0);
- }
+ dev = device_lookup_by_name(req->dr_name);
+ if (dev != NULL) {
+ *devp = dev;
+ return (0);
}
/* Finally, give device enumerators a chance. */
diff --git a/sys/modules/cxgbe/if_cxgbe/Makefile b/sys/modules/cxgbe/if_cxgbe/Makefile
index 301dd76..73c773b 100644
--- a/sys/modules/cxgbe/if_cxgbe/Makefile
+++ b/sys/modules/cxgbe/if_cxgbe/Makefile
@@ -10,6 +10,7 @@ CXGBE= ${.CURDIR}/../../../dev/cxgbe
KMOD= if_cxgbe
SRCS= bus_if.h
SRCS+= device_if.h
+SRCS+= opt_ddb.h
SRCS+= opt_inet.h
SRCS+= opt_inet6.h
SRCS+= opt_ofed.h
diff --git a/sys/sys/bus.h b/sys/sys/bus.h
index 6c65449..32bb317 100644
--- a/sys/sys/bus.h
+++ b/sys/sys/bus.h
@@ -503,6 +503,7 @@ int device_is_attached(device_t dev); /* did attach succeed? */
int device_is_enabled(device_t dev);
int device_is_suspended(device_t dev);
int device_is_quiet(device_t dev);
+device_t device_lookup_by_name(const char *name);
int device_print_prettyname(device_t dev);
int device_printf(device_t dev, const char *, ...) __printflike(2, 3);
int device_probe(device_t dev);
OpenPOWER on IntegriCloud