summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Johnston <rob.johnston@joyent.com>2018-07-24 23:17:57 +0000
committerRob Johnston <rob.johnston@joyent.com>2018-08-07 17:42:32 +0000
commit757454db6669c1186f60bc625510c1b67217aae6 (patch)
treef5c0d1a218cfcba61bb192c75c463fdbea617998
parent6ce17ef1e269338b564b10ef91271385757dfc3f (diff)
downloadillumos-joyent-757454db6669c1186f60bc625510c1b67217aae6.tar.gz
OS-7082 i40e: blown assert in i40e_tx_cleanup_ring()
OS-7086 i40e: add mdb dcmd to dump info on tx descriptor rings OS-7101 i40e: add kstat to track TX DMA bind failures Reviewed by: Ryan Zezeski <rpz@joyent.com> Reviewed by: Robert Mustacchi <rm@joyent.com> Approved by: Patrick Mooney <patrick.mooney@joyent.com>
-rw-r--r--usr/src/cmd/mdb/intel/modules/i40e/amd64/Makefile3
-rw-r--r--usr/src/cmd/mdb/intel/modules/i40e/i40e.c175
-rw-r--r--usr/src/uts/common/io/i40e/i40e_stats.c3
-rw-r--r--usr/src/uts/common/io/i40e/i40e_sw.h1
-rw-r--r--usr/src/uts/common/io/i40e/i40e_transceiver.c12
5 files changed, 187 insertions, 7 deletions
diff --git a/usr/src/cmd/mdb/intel/modules/i40e/amd64/Makefile b/usr/src/cmd/mdb/intel/modules/i40e/amd64/Makefile
index 66f97451b6..f1632172f5 100644
--- a/usr/src/cmd/mdb/intel/modules/i40e/amd64/Makefile
+++ b/usr/src/cmd/mdb/intel/modules/i40e/amd64/Makefile
@@ -10,7 +10,7 @@
#
#
-# Copyright 2017 Joyent, Inc.
+# Copyright 2018 Joyent, Inc.
#
MODULE = i40e.so
@@ -23,6 +23,7 @@ include ../../../../../Makefile.cmd.64
include ../../../Makefile.amd64
include ../../../../Makefile.module
+CPPFLAGS += -I$(SRC)/cmd/mdb/common
CPPFLAGS += -I$(SRC)/uts/common/io/i40e
CPPFLAGS += -I$(SRC)/uts/common/io/i40e/core
CPPFLAGS += -I$(SRC)/uts/common
diff --git a/usr/src/cmd/mdb/intel/modules/i40e/i40e.c b/usr/src/cmd/mdb/intel/modules/i40e/i40e.c
index 6d1f900b43..3f42d24d1f 100644
--- a/usr/src/cmd/mdb/intel/modules/i40e/i40e.c
+++ b/usr/src/cmd/mdb/intel/modules/i40e/i40e.c
@@ -10,9 +10,10 @@
*/
/*
- * Copyright 2016 Joyent, Inc.
+ * Copyright 2018 Joyent, Inc.
*/
+#include <mdb/mdb_ctf.h>
#include <sys/mdb_modapi.h>
#include "i40e_sw.h"
@@ -97,9 +98,181 @@ i40e_switch_rsrcs_dcmd(uintptr_t addr, uint_t flags, int argc,
return (DCMD_OK);
}
+typedef struct mdb_i40e_trqpair {
+ uint32_t itrq_tx_ring_size;
+ uint32_t itrq_desc_free;
+ uint32_t *itrq_desc_wbhead;
+ uint32_t itrq_desc_head;
+ uint32_t itrq_desc_tail;
+ i40e_tx_desc_t *itrq_desc_ring;
+ i40e_tx_control_block_t **itrq_tcb_work_list;
+} mdb_i40e_trqpair_t;
+
+static void
+i40e_tx_ring_help()
+{
+ mdb_printf(
+ "\t -a dump all ring entries\n"
+ "\t or\n"
+ "\t combine -b [start index] with -e [end index] to specify a \n"
+ "\t range of ring entries to print\n");
+}
+
+static int
+i40e_tx_ring_dcmd(uintptr_t addr, uint_t flags, int argc,
+ const mdb_arg_t *argv)
+{
+ mdb_i40e_trqpair_t trq;
+ i40e_tx_desc_t *descring;
+ i40e_tx_control_block_t **wklist;
+ uint32_t wbhead;
+ size_t ringsz, wklistsz;
+ boolean_t opt_a = B_FALSE;
+ char *opt_b = NULL, *opt_e = NULL;
+ uint64_t begin = UINT64_MAX, end = UINT64_MAX;
+
+ if (!(flags & DCMD_ADDRSPEC)) {
+ mdb_warn("::i40e_tx_ring does not operate globally\n");
+ return (DCMD_USAGE);
+ }
+
+ if (mdb_getopts(argc, argv,
+ 'a', MDB_OPT_SETBITS, B_TRUE, &opt_a,
+ 'b', MDB_OPT_STR, &opt_b,
+ 'e', MDB_OPT_STR, &opt_e, NULL) != argc)
+ return (DCMD_USAGE);
+
+ /*
+ * Verify that a legal combination of -a/-b/-e were used.
+ */
+ if (opt_a && (opt_b != NULL || opt_e != NULL)) {
+ mdb_warn("-a and -b/-e are mutually exclusive\n");
+ return (DCMD_USAGE);
+ }
+ if (argc > 0 && ! opt_a && (opt_b == NULL || opt_e == NULL)) {
+ mdb_warn("-b/-e must both be specified\n");
+ return (DCMD_USAGE);
+ }
+
+ if (mdb_ctf_vread(&trq, "i40e_trqpair_t", "mdb_i40e_trqpair_t", addr,
+ 0) == -1) {
+ mdb_warn("failed to read i40e_trqpair_t at %p", addr);
+ return (DCMD_ERR);
+ }
+
+ if (opt_b != NULL)
+ begin = mdb_strtoull(opt_b);
+ if (opt_e != NULL)
+ end = mdb_strtoull(opt_e);
+ if (opt_a) {
+ begin = 0;
+ end = trq.itrq_tx_ring_size - 1;
+ }
+
+ /*
+ * Verify that the requested range of ring entries makes sense.
+ */
+ if (argc > 0 && (end < begin || begin >= trq.itrq_tx_ring_size ||
+ end >= trq.itrq_tx_ring_size)) {
+ mdb_warn("invalid range specified\n");
+ return (DCMD_USAGE);
+ }
+
+ if (mdb_vread(&wbhead, sizeof (uint32_t),
+ (uintptr_t)trq.itrq_desc_wbhead) != sizeof (uint32_t)) {
+ mdb_warn("failed to read trq.itrq_desc_wbhead");
+ return (DCMD_ERR);
+ }
+ mdb_printf("%-20s%d\n", "Ring Size:", trq.itrq_tx_ring_size);
+ mdb_printf("%-20s%d\n", "Free Descriptors:", trq.itrq_desc_free);
+ mdb_printf("%-20s%d\n", "Writeback Head:", wbhead);
+ mdb_printf("%-20s%d\n", "Head:", trq.itrq_desc_head);
+ mdb_printf("%-20s%d\n", "Tail:", trq.itrq_desc_tail);
+
+ /*
+ * No arguments were specified, so we're done.
+ */
+ if (argc == 0)
+ return (DCMD_OK);
+
+ /*
+ * Allocate memory and read in the entire TX descriptor ring and
+ * TCB work list.
+ */
+ ringsz = sizeof (i40e_tx_desc_t) * trq.itrq_tx_ring_size;
+ descring = mdb_alloc(ringsz, UM_SLEEP);
+ if (mdb_vread(descring, ringsz, (uintptr_t)trq.itrq_desc_ring) !=
+ ringsz) {
+ mdb_warn("Failed to read in TX decriptor ring\n");
+ mdb_free(descring, ringsz);
+ return (DCMD_ERR);
+ }
+ wklistsz = sizeof (i40e_tx_control_block_t *) * trq.itrq_tx_ring_size;
+ wklist = mdb_alloc(wklistsz, UM_SLEEP);
+ if (mdb_vread(wklist, wklistsz, (uintptr_t)trq.itrq_tcb_work_list) !=
+ wklistsz) {
+ mdb_warn("Failed to read in TX TCB work list\n");
+ mdb_free(descring, ringsz);
+ mdb_free(wklist, wklistsz);
+ return (DCMD_ERR);
+ }
+
+ mdb_printf("\n%-10s %-10s %-16s %-16s %-10s\n", "Index", "Desc Type",
+ "Desc Ptr", "TCB Ptr", "Other");
+ for (uint64_t i = begin; i <= end; i++) {
+ const char *dtype;
+ char dother[17];
+ i40e_tx_desc_t *dptr;
+ i40e_tx_control_block_t *tcbptr;
+ uint64_t ctob;
+
+ dptr = &descring[i];
+ tcbptr = wklist[i];
+ ctob = LE_64(dptr->cmd_type_offset_bsz);
+ if (ctob == 0) {
+ dtype = "FREE";
+ } else {
+ switch (ctob & I40E_TXD_QW1_DTYPE_MASK) {
+ case (I40E_TX_DESC_DTYPE_CONTEXT):
+ dtype = "CONTEXT";
+ break;
+ case (I40E_TX_DESC_DTYPE_DATA):
+ dtype = "DATA";
+ break;
+ case (I40E_TX_DESC_DTYPE_FILTER_PROG):
+ dtype = "FILTER";
+ break;
+ default:
+ dtype = "UNKNOWN";
+ }
+ }
+ dother[0] = '\0';
+ if (i == wbhead)
+ (void) strcat(dother, "WBHEAD");
+
+ if (i == trq.itrq_desc_head)
+ (void) strcat(dother,
+ strlen(dother) > 0 ? " HEAD" : "HEAD");
+
+ if (i == trq.itrq_desc_tail)
+ (void) strcat(dother,
+ strlen(dother) > 0 ? " TAIL" : "TAIL");
+
+ mdb_printf("%-10d %-10s %-16p %-16p %-10s\n", i, dtype, dptr,
+ tcbptr, dother);
+ }
+
+ mdb_free(descring, ringsz);
+ mdb_free(wklist, wklistsz);
+ return (DCMD_OK);
+}
+
static const mdb_dcmd_t i40e_dcmds[] = {
{ "i40e_switch_rsrcs", NULL, "print switch resources",
i40e_switch_rsrcs_dcmd, NULL },
+ { "i40e_tx_ring", "[-a] -b [start index] -e [end index]\n",
+ "dump TX descriptor ring state", i40e_tx_ring_dcmd,
+ i40e_tx_ring_help },
{ NULL }
};
diff --git a/usr/src/uts/common/io/i40e/i40e_stats.c b/usr/src/uts/common/io/i40e/i40e_stats.c
index 810ccedd8f..e5f6de9f9f 100644
--- a/usr/src/uts/common/io/i40e/i40e_stats.c
+++ b/usr/src/uts/common/io/i40e/i40e_stats.c
@@ -1252,6 +1252,9 @@ i40e_stats_trqpair_init(i40e_trqpair_t *itrq)
kstat_named_init(&tsp->itxs_lso_nohck, "tx_lso_nohck",
KSTAT_DATA_UINT64);
tsp->itxs_lso_nohck.value.ui64 = 0;
+ kstat_named_init(&tsp->itxs_bind_fails, "tx_bind_fails",
+ KSTAT_DATA_UINT64);
+ tsp->itxs_bind_fails.value.ui64 = 0;
kstat_named_init(&tsp->itxs_err_notcb, "tx_err_notcb",
KSTAT_DATA_UINT64);
tsp->itxs_err_notcb.value.ui64 = 0;
diff --git a/usr/src/uts/common/io/i40e/i40e_sw.h b/usr/src/uts/common/io/i40e/i40e_sw.h
index 5411be3d83..8e1d72a09e 100644
--- a/usr/src/uts/common/io/i40e/i40e_sw.h
+++ b/usr/src/uts/common/io/i40e/i40e_sw.h
@@ -554,6 +554,7 @@ typedef struct i40e_txq_stat {
kstat_named_t itxs_hck_badl3; /* Not IPv4/IPv6 */
kstat_named_t itxs_hck_badl4; /* Bad L4 Paylaod */
kstat_named_t itxs_lso_nohck; /* Missing offloads for LSO */
+ kstat_named_t itxs_bind_fails; /* DMA bind failures */
kstat_named_t itxs_err_notcb; /* No tcb's available */
kstat_named_t itxs_err_nodescs; /* No tcb's available */
diff --git a/usr/src/uts/common/io/i40e/i40e_transceiver.c b/usr/src/uts/common/io/i40e/i40e_transceiver.c
index cb150545ea..f91c2237b7 100644
--- a/usr/src/uts/common/io/i40e/i40e_transceiver.c
+++ b/usr/src/uts/common/io/i40e/i40e_transceiver.c
@@ -2071,10 +2071,11 @@ i40e_tx_cleanup_ring(i40e_trqpair_t *itrq)
i40e_tx_control_block_t *tcb;
tcb = itrq->itrq_tcb_work_list[index];
- VERIFY(tcb != NULL);
- itrq->itrq_tcb_work_list[index] = NULL;
- i40e_tcb_reset(tcb);
- i40e_tcb_free(itrq, tcb);
+ if (tcb != NULL) {
+ itrq->itrq_tcb_work_list[index] = NULL;
+ i40e_tcb_reset(tcb);
+ i40e_tcb_free(itrq, tcb);
+ }
bzero(&itrq->itrq_desc_ring[index], sizeof (i40e_tx_desc_t));
index = i40e_next_desc(index, 1, itrq->itrq_tx_ring_size);
@@ -2218,10 +2219,11 @@ i40e_tx_bind_fragment(i40e_trqpair_t *itrq, const mblk_t *mp,
else
dma_handle = tcb->tcb_dma_handle;
- dmaflags = DDI_DMA_RDWR | DDI_DMA_STREAMING;
+ dmaflags = DDI_DMA_WRITE | DDI_DMA_STREAMING;
if (ddi_dma_addr_bind_handle(dma_handle, NULL,
(caddr_t)mp->b_rptr, MBLKL(mp), dmaflags, DDI_DMA_DONTWAIT, NULL,
&dma_cookie, &ncookies) != DDI_DMA_MAPPED) {
+ txs->itxs_bind_fails.value.ui64++;
goto bffail;
}
tcb->tcb_bind_ncookies = ncookies;