diff options
author | Rob Johnston <rob.johnston@joyent.com> | 2018-07-24 23:17:57 +0000 |
---|---|---|
committer | Rob Johnston <rob.johnston@joyent.com> | 2018-08-07 17:42:32 +0000 |
commit | 757454db6669c1186f60bc625510c1b67217aae6 (patch) | |
tree | f5c0d1a218cfcba61bb192c75c463fdbea617998 | |
parent | 6ce17ef1e269338b564b10ef91271385757dfc3f (diff) | |
download | illumos-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/Makefile | 3 | ||||
-rw-r--r-- | usr/src/cmd/mdb/intel/modules/i40e/i40e.c | 175 | ||||
-rw-r--r-- | usr/src/uts/common/io/i40e/i40e_stats.c | 3 | ||||
-rw-r--r-- | usr/src/uts/common/io/i40e/i40e_sw.h | 1 | ||||
-rw-r--r-- | usr/src/uts/common/io/i40e/i40e_transceiver.c | 12 |
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; |