diff options
author | jhb <jhb@FreeBSD.org> | 2016-11-04 21:43:10 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2016-11-04 21:43:10 +0000 |
commit | 5d45cb0e371564824664c32f312376d51ded5a8e (patch) | |
tree | 3be4f626b101cfa8ba44ffa1b5d7e828c3b7c805 | |
parent | fcd0752232f1d6e2f643cb33ced40ed7901f1934 (diff) | |
download | FreeBSD-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.c | 178 | ||||
-rw-r--r-- | sys/dev/cxgbe/tom/t4_ddp.c | 25 | ||||
-rw-r--r-- | sys/kern/subr_bus.c | 22 | ||||
-rw-r--r-- | sys/modules/cxgbe/if_cxgbe/Makefile | 1 | ||||
-rw-r--r-- | sys/sys/bus.h | 1 |
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); |