19d26e4fcSRobert Mustacchi /*
29d26e4fcSRobert Mustacchi  * This file and its contents are supplied under the terms of the
39d26e4fcSRobert Mustacchi  * Common Development and Distribution License ("CDDL"), version 1.0.
49d26e4fcSRobert Mustacchi  * You may only use this file in accordance with the terms of version
59d26e4fcSRobert Mustacchi  * 1.0 of the CDDL.
69d26e4fcSRobert Mustacchi  *
79d26e4fcSRobert Mustacchi  * A full copy of the text of the CDDL should have accompanied this
89d26e4fcSRobert Mustacchi  * source.  A copy of the CDDL is also available via the Internet at
99d26e4fcSRobert Mustacchi  * http://www.illumos.org/license/CDDL.
109d26e4fcSRobert Mustacchi  */
119d26e4fcSRobert Mustacchi 
129d26e4fcSRobert Mustacchi /*
13*09aee612SRyan Zezeski  * Copyright 2018 Joyent, Inc.
149d26e4fcSRobert Mustacchi  */
159d26e4fcSRobert Mustacchi 
16*09aee612SRyan Zezeski #include <mdb/mdb_ctf.h>
179d26e4fcSRobert Mustacchi #include <sys/mdb_modapi.h>
189d26e4fcSRobert Mustacchi #include "i40e_sw.h"
199d26e4fcSRobert Mustacchi 
209d26e4fcSRobert Mustacchi #define	RSRC_MAX	0x13
219d26e4fcSRobert Mustacchi static const char *i40e_switch_rsrc_names[] = {
229d26e4fcSRobert Mustacchi 	"VEBs",
239d26e4fcSRobert Mustacchi 	"VSIs",
249d26e4fcSRobert Mustacchi 	"Perfect Match MAC Addresses",
259d26e4fcSRobert Mustacchi 	"S-Tags",
269d26e4fcSRobert Mustacchi 	"Reserved",
279d26e4fcSRobert Mustacchi 	"Multicast Hash Entries",
289d26e4fcSRobert Mustacchi 	"Reserved",
299d26e4fcSRobert Mustacchi 	"VLANs",
309d26e4fcSRobert Mustacchi 	"VSI Lists",
319d26e4fcSRobert Mustacchi 	"Reserved",
329d26e4fcSRobert Mustacchi 	"VLAN Stat pools",
339d26e4fcSRobert Mustacchi 	"Mirror rules",
349d26e4fcSRobert Mustacchi 	"Queue sets",
359d26e4fcSRobert Mustacchi 	"Inner VLAN Forwarding",
369d26e4fcSRobert Mustacchi 	"Reserved",
379d26e4fcSRobert Mustacchi 	"Inner MACs",
389d26e4fcSRobert Mustacchi 	"IPs",
399d26e4fcSRobert Mustacchi 	"GRE/VN1 Keys",
409d26e4fcSRobert Mustacchi 	"VN2 Keys",
419d26e4fcSRobert Mustacchi 	"Tunnelling Ports"
429d26e4fcSRobert Mustacchi };
439d26e4fcSRobert Mustacchi 
449d26e4fcSRobert Mustacchi /*
459d26e4fcSRobert Mustacchi  * i40e mdb dcmds
469d26e4fcSRobert Mustacchi  */
479d26e4fcSRobert Mustacchi /* ARGSUSED */
489d26e4fcSRobert Mustacchi static int
i40e_switch_rsrcs_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)499d26e4fcSRobert Mustacchi i40e_switch_rsrcs_dcmd(uintptr_t addr, uint_t flags, int argc,
509d26e4fcSRobert Mustacchi     const mdb_arg_t *argv)
519d26e4fcSRobert Mustacchi {
529d26e4fcSRobert Mustacchi 	i40e_t i40e;
539d26e4fcSRobert Mustacchi 	int i;
549d26e4fcSRobert Mustacchi 
559d26e4fcSRobert Mustacchi 	if (!(flags & DCMD_ADDRSPEC)) {
569d26e4fcSRobert Mustacchi 		mdb_warn("::i40e_switch_rsrcs does not operate globally\n");
579d26e4fcSRobert Mustacchi 		return (DCMD_USAGE);
589d26e4fcSRobert Mustacchi 	}
599d26e4fcSRobert Mustacchi 
609d26e4fcSRobert Mustacchi 	if (mdb_vread(&i40e, sizeof (i40e_t), addr) != sizeof (i40e_t)) {
619d26e4fcSRobert Mustacchi 		mdb_warn("failed to read i40e_t at %p", addr);
629d26e4fcSRobert Mustacchi 		return (DCMD_ERR);
639d26e4fcSRobert Mustacchi 	}
649d26e4fcSRobert Mustacchi 
659d26e4fcSRobert Mustacchi 	mdb_printf("%-28s %-12s %-8s %-8s %s\n", "TYPE", "GUARANTEE",
669d26e4fcSRobert Mustacchi 	    "TOTAL", "USED", "UNALLOCED");
679d26e4fcSRobert Mustacchi 
689d26e4fcSRobert Mustacchi 	for (i = 0; i < i40e.i40e_switch_rsrc_actual; i++) {
699d26e4fcSRobert Mustacchi 		i40e_switch_rsrc_t rsrc;
709d26e4fcSRobert Mustacchi 		uintptr_t raddr = (uintptr_t)i40e.i40e_switch_rsrcs +
719d26e4fcSRobert Mustacchi 		    i * sizeof (i40e_switch_rsrc_t);
729d26e4fcSRobert Mustacchi 		const char *name;
739d26e4fcSRobert Mustacchi 
749d26e4fcSRobert Mustacchi 		if (mdb_vread(&rsrc, sizeof (i40e_switch_rsrc_t), raddr) !=
759d26e4fcSRobert Mustacchi 		    sizeof (i40e_switch_rsrc_t)) {
769d26e4fcSRobert Mustacchi 			mdb_warn("failed to read i40e_switch_rsrc_t %d at %p",
779d26e4fcSRobert Mustacchi 			    i, raddr);
789d26e4fcSRobert Mustacchi 			return (DCMD_ERR);
799d26e4fcSRobert Mustacchi 		}
809d26e4fcSRobert Mustacchi 
819d26e4fcSRobert Mustacchi 		if (rsrc.resource_type <= RSRC_MAX) {
829d26e4fcSRobert Mustacchi 			name = i40e_switch_rsrc_names[rsrc.resource_type];
839d26e4fcSRobert Mustacchi 		} else {
849d26e4fcSRobert Mustacchi 			char *buf;
859d26e4fcSRobert Mustacchi 			size_t s = mdb_snprintf(NULL, 0, "Unknown type (%d)",
869d26e4fcSRobert Mustacchi 			    rsrc.resource_type);
879d26e4fcSRobert Mustacchi 			buf = mdb_alloc(s + 1, UM_GC | UM_SLEEP);
889d26e4fcSRobert Mustacchi 			(void) mdb_snprintf(buf, s + 1, "Unknown type (%d)",
899d26e4fcSRobert Mustacchi 			    rsrc.resource_type);
909d26e4fcSRobert Mustacchi 			name = buf;
919d26e4fcSRobert Mustacchi 		}
929d26e4fcSRobert Mustacchi 
939d26e4fcSRobert Mustacchi 		mdb_printf("%-28s %-12d %-8d %-8d %d\n", name,
949d26e4fcSRobert Mustacchi 		    LE_16(rsrc.guaranteed), LE_16(rsrc.total), LE_16(rsrc.used),
959d26e4fcSRobert Mustacchi 		    LE_16(rsrc.total_unalloced));
969d26e4fcSRobert Mustacchi 	}
979d26e4fcSRobert Mustacchi 
989d26e4fcSRobert Mustacchi 	return (DCMD_OK);
999d26e4fcSRobert Mustacchi }
1009d26e4fcSRobert Mustacchi 
101*09aee612SRyan Zezeski typedef struct mdb_i40e_trqpair {
102*09aee612SRyan Zezeski 	uint32_t		itrq_tx_ring_size;
103*09aee612SRyan Zezeski 	uint32_t		itrq_desc_free;
104*09aee612SRyan Zezeski 	uint32_t 		*itrq_desc_wbhead;
105*09aee612SRyan Zezeski 	uint32_t		itrq_desc_head;
106*09aee612SRyan Zezeski 	uint32_t		itrq_desc_tail;
107*09aee612SRyan Zezeski 	i40e_tx_desc_t		*itrq_desc_ring;
108*09aee612SRyan Zezeski 	i40e_tx_control_block_t	**itrq_tcb_work_list;
109*09aee612SRyan Zezeski } mdb_i40e_trqpair_t;
110*09aee612SRyan Zezeski 
111*09aee612SRyan Zezeski static void
i40e_tx_ring_help()112*09aee612SRyan Zezeski i40e_tx_ring_help()
113*09aee612SRyan Zezeski {
114*09aee612SRyan Zezeski 	mdb_printf(
115*09aee612SRyan Zezeski 	    "\t -a dump all ring entries\n"
116*09aee612SRyan Zezeski 	    "\t or\n"
117*09aee612SRyan Zezeski 	    "\t combine -b [start index] with -e [end index] to specify a \n"
118*09aee612SRyan Zezeski 	    "\t range of ring entries to print\n");
119*09aee612SRyan Zezeski }
120*09aee612SRyan Zezeski 
121*09aee612SRyan Zezeski static int
i40e_tx_ring_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)122*09aee612SRyan Zezeski i40e_tx_ring_dcmd(uintptr_t addr, uint_t flags, int argc,
123*09aee612SRyan Zezeski     const mdb_arg_t *argv)
124*09aee612SRyan Zezeski {
125*09aee612SRyan Zezeski 	mdb_i40e_trqpair_t trq;
126*09aee612SRyan Zezeski 	i40e_tx_desc_t *descring;
127*09aee612SRyan Zezeski 	i40e_tx_control_block_t **wklist;
128*09aee612SRyan Zezeski 	uint32_t wbhead;
129*09aee612SRyan Zezeski 	size_t ringsz, wklistsz;
130*09aee612SRyan Zezeski 	boolean_t opt_a = B_FALSE;
131*09aee612SRyan Zezeski 	char *opt_b = NULL, *opt_e = NULL;
132*09aee612SRyan Zezeski 	uint64_t begin = UINT64_MAX, end = UINT64_MAX;
133*09aee612SRyan Zezeski 
134*09aee612SRyan Zezeski 	if (!(flags & DCMD_ADDRSPEC)) {
135*09aee612SRyan Zezeski 		mdb_warn("::i40e_tx_ring does not operate globally\n");
136*09aee612SRyan Zezeski 		return (DCMD_USAGE);
137*09aee612SRyan Zezeski 	}
138*09aee612SRyan Zezeski 
139*09aee612SRyan Zezeski 	if (mdb_getopts(argc, argv,
140*09aee612SRyan Zezeski 	    'a', MDB_OPT_SETBITS, B_TRUE, &opt_a,
141*09aee612SRyan Zezeski 	    'b', MDB_OPT_STR, &opt_b,
142*09aee612SRyan Zezeski 	    'e', MDB_OPT_STR, &opt_e, NULL) != argc)
143*09aee612SRyan Zezeski 		return (DCMD_USAGE);
144*09aee612SRyan Zezeski 
145*09aee612SRyan Zezeski 	/*
146*09aee612SRyan Zezeski 	 * Verify that a legal combination of -a/-b/-e were used.
147*09aee612SRyan Zezeski 	 */
148*09aee612SRyan Zezeski 	if (opt_a && (opt_b != NULL || opt_e != NULL)) {
149*09aee612SRyan Zezeski 		mdb_warn("-a and -b/-e are mutually exclusive\n");
150*09aee612SRyan Zezeski 		return (DCMD_USAGE);
151*09aee612SRyan Zezeski 	}
152*09aee612SRyan Zezeski 	if (argc > 0 && ! opt_a && (opt_b == NULL || opt_e == NULL)) {
153*09aee612SRyan Zezeski 		mdb_warn("-b/-e must both be specified\n");
154*09aee612SRyan Zezeski 		return (DCMD_USAGE);
155*09aee612SRyan Zezeski 	}
156*09aee612SRyan Zezeski 
157*09aee612SRyan Zezeski 	if (mdb_ctf_vread(&trq, "i40e_trqpair_t", "mdb_i40e_trqpair_t", addr,
158*09aee612SRyan Zezeski 	    0) == -1) {
159*09aee612SRyan Zezeski 		mdb_warn("failed to read i40e_trqpair_t at %p", addr);
160*09aee612SRyan Zezeski 		return (DCMD_ERR);
161*09aee612SRyan Zezeski 	}
162*09aee612SRyan Zezeski 
163*09aee612SRyan Zezeski 	if (opt_b != NULL)
164*09aee612SRyan Zezeski 		begin = mdb_strtoull(opt_b);
165*09aee612SRyan Zezeski 	if (opt_e != NULL)
166*09aee612SRyan Zezeski 		end = mdb_strtoull(opt_e);
167*09aee612SRyan Zezeski 	if (opt_a) {
168*09aee612SRyan Zezeski 		begin = 0;
169*09aee612SRyan Zezeski 		end = trq.itrq_tx_ring_size - 1;
170*09aee612SRyan Zezeski 	}
171*09aee612SRyan Zezeski 
172*09aee612SRyan Zezeski 	/*
173*09aee612SRyan Zezeski 	 * Verify that the requested range of ring entries makes sense.
174*09aee612SRyan Zezeski 	 */
175*09aee612SRyan Zezeski 	if (argc > 0 && (end < begin || begin >= trq.itrq_tx_ring_size ||
176*09aee612SRyan Zezeski 	    end >= trq.itrq_tx_ring_size)) {
177*09aee612SRyan Zezeski 		mdb_warn("invalid range specified\n");
178*09aee612SRyan Zezeski 		return (DCMD_USAGE);
179*09aee612SRyan Zezeski 	}
180*09aee612SRyan Zezeski 
181*09aee612SRyan Zezeski 	if (mdb_vread(&wbhead, sizeof (uint32_t),
182*09aee612SRyan Zezeski 	    (uintptr_t)trq.itrq_desc_wbhead) != sizeof (uint32_t)) {
183*09aee612SRyan Zezeski 		mdb_warn("failed to read trq.itrq_desc_wbhead");
184*09aee612SRyan Zezeski 		return (DCMD_ERR);
185*09aee612SRyan Zezeski 	}
186*09aee612SRyan Zezeski 	mdb_printf("%-20s%d\n", "Ring Size:", trq.itrq_tx_ring_size);
187*09aee612SRyan Zezeski 	mdb_printf("%-20s%d\n", "Free Descriptors:", trq.itrq_desc_free);
188*09aee612SRyan Zezeski 	mdb_printf("%-20s%d\n", "Writeback Head:", wbhead);
189*09aee612SRyan Zezeski 	mdb_printf("%-20s%d\n", "Head:", trq.itrq_desc_head);
190*09aee612SRyan Zezeski 	mdb_printf("%-20s%d\n", "Tail:", trq.itrq_desc_tail);
191*09aee612SRyan Zezeski 
192*09aee612SRyan Zezeski 	/*
193*09aee612SRyan Zezeski 	 * No arguments were specified, so we're done.
194*09aee612SRyan Zezeski 	 */
195*09aee612SRyan Zezeski 	if (argc == 0)
196*09aee612SRyan Zezeski 		return (DCMD_OK);
197*09aee612SRyan Zezeski 
198*09aee612SRyan Zezeski 	/*
199*09aee612SRyan Zezeski 	 * Allocate memory and read in the entire TX descriptor ring and
200*09aee612SRyan Zezeski 	 * TCB work list.
201*09aee612SRyan Zezeski 	 */
202*09aee612SRyan Zezeski 	ringsz = sizeof (i40e_tx_desc_t) * trq.itrq_tx_ring_size;
203*09aee612SRyan Zezeski 	descring = mdb_alloc(ringsz, UM_SLEEP);
204*09aee612SRyan Zezeski 	if (mdb_vread(descring, ringsz, (uintptr_t)trq.itrq_desc_ring) !=
205*09aee612SRyan Zezeski 	    ringsz) {
206*09aee612SRyan Zezeski 		mdb_warn("Failed to read in TX decriptor ring\n");
207*09aee612SRyan Zezeski 		mdb_free(descring, ringsz);
208*09aee612SRyan Zezeski 		return (DCMD_ERR);
209*09aee612SRyan Zezeski 	}
210*09aee612SRyan Zezeski 	wklistsz = sizeof (i40e_tx_control_block_t *) * trq.itrq_tx_ring_size;
211*09aee612SRyan Zezeski 	wklist = mdb_alloc(wklistsz, UM_SLEEP);
212*09aee612SRyan Zezeski 	if (mdb_vread(wklist, wklistsz, (uintptr_t)trq.itrq_tcb_work_list) !=
213*09aee612SRyan Zezeski 	    wklistsz) {
214*09aee612SRyan Zezeski 		mdb_warn("Failed to read in TX TCB work list\n");
215*09aee612SRyan Zezeski 		mdb_free(descring, ringsz);
216*09aee612SRyan Zezeski 		mdb_free(wklist, wklistsz);
217*09aee612SRyan Zezeski 		return (DCMD_ERR);
218*09aee612SRyan Zezeski 	}
219*09aee612SRyan Zezeski 
220*09aee612SRyan Zezeski 	mdb_printf("\n%-10s %-10s %-16s %-16s %-10s\n", "Index", "Desc Type",
221*09aee612SRyan Zezeski 	    "Desc Ptr", "TCB Ptr", "Other");
222*09aee612SRyan Zezeski 	for (uint64_t i = begin; i <= end; i++) {
223*09aee612SRyan Zezeski 		const char *dtype;
224*09aee612SRyan Zezeski 		char dother[17];
225*09aee612SRyan Zezeski 		i40e_tx_desc_t *dptr;
226*09aee612SRyan Zezeski 		i40e_tx_control_block_t *tcbptr;
227*09aee612SRyan Zezeski 		uint64_t ctob;
228*09aee612SRyan Zezeski 
229*09aee612SRyan Zezeski 		dptr = &descring[i];
230*09aee612SRyan Zezeski 		tcbptr = wklist[i];
231*09aee612SRyan Zezeski 		ctob = LE_64(dptr->cmd_type_offset_bsz);
232*09aee612SRyan Zezeski 		if (ctob == 0) {
233*09aee612SRyan Zezeski 			dtype = "FREE";
234*09aee612SRyan Zezeski 		} else {
235*09aee612SRyan Zezeski 			switch (ctob & I40E_TXD_QW1_DTYPE_MASK) {
236*09aee612SRyan Zezeski 			case (I40E_TX_DESC_DTYPE_CONTEXT):
237*09aee612SRyan Zezeski 				dtype = "CONTEXT";
238*09aee612SRyan Zezeski 				break;
239*09aee612SRyan Zezeski 			case (I40E_TX_DESC_DTYPE_DATA):
240*09aee612SRyan Zezeski 				dtype = "DATA";
241*09aee612SRyan Zezeski 				break;
242*09aee612SRyan Zezeski 			case (I40E_TX_DESC_DTYPE_FILTER_PROG):
243*09aee612SRyan Zezeski 				dtype = "FILTER";
244*09aee612SRyan Zezeski 				break;
245*09aee612SRyan Zezeski 			default:
246*09aee612SRyan Zezeski 				dtype = "UNKNOWN";
247*09aee612SRyan Zezeski 			}
248*09aee612SRyan Zezeski 		}
249*09aee612SRyan Zezeski 		dother[0] = '\0';
250*09aee612SRyan Zezeski 		if (i == wbhead)
251*09aee612SRyan Zezeski 			(void) strcat(dother, "WBHEAD");
252*09aee612SRyan Zezeski 
253*09aee612SRyan Zezeski 		if (i == trq.itrq_desc_head)
254*09aee612SRyan Zezeski 			(void) strcat(dother,
255*09aee612SRyan Zezeski 			    strlen(dother) > 0 ? " HEAD" : "HEAD");
256*09aee612SRyan Zezeski 
257*09aee612SRyan Zezeski 		if (i == trq.itrq_desc_tail)
258*09aee612SRyan Zezeski 			(void) strcat(dother,
259*09aee612SRyan Zezeski 			    strlen(dother) > 0 ? " TAIL" : "TAIL");
260*09aee612SRyan Zezeski 
261*09aee612SRyan Zezeski 		mdb_printf("%-10d %-10s %-16p %-16p %-10s\n", i, dtype, dptr,
262*09aee612SRyan Zezeski 		    tcbptr, dother);
263*09aee612SRyan Zezeski 	}
264*09aee612SRyan Zezeski 
265*09aee612SRyan Zezeski 	mdb_free(descring, ringsz);
266*09aee612SRyan Zezeski 	mdb_free(wklist, wklistsz);
267*09aee612SRyan Zezeski 	return (DCMD_OK);
268*09aee612SRyan Zezeski }
269*09aee612SRyan Zezeski 
2709d26e4fcSRobert Mustacchi static const mdb_dcmd_t i40e_dcmds[] = {
2719d26e4fcSRobert Mustacchi 	{ "i40e_switch_rsrcs", NULL, "print switch resources",
2729d26e4fcSRobert Mustacchi 	    i40e_switch_rsrcs_dcmd, NULL },
273*09aee612SRyan Zezeski 	{ "i40e_tx_ring", "[-a] -b [start index] -e [end index]\n",
274*09aee612SRyan Zezeski 	    "dump TX descriptor ring state", i40e_tx_ring_dcmd,
275*09aee612SRyan Zezeski 	    i40e_tx_ring_help },
2769d26e4fcSRobert Mustacchi 	{ NULL }
2779d26e4fcSRobert Mustacchi };
2789d26e4fcSRobert Mustacchi 
2799d26e4fcSRobert Mustacchi static const mdb_modinfo_t i40e_modinfo = {
2809d26e4fcSRobert Mustacchi 	MDB_API_VERSION, i40e_dcmds, NULL
2819d26e4fcSRobert Mustacchi };
2829d26e4fcSRobert Mustacchi 
2839d26e4fcSRobert Mustacchi const mdb_modinfo_t *
_mdb_init(void)2849d26e4fcSRobert Mustacchi _mdb_init(void)
2859d26e4fcSRobert Mustacchi {
2869d26e4fcSRobert Mustacchi 	return (&i40e_modinfo);
2879d26e4fcSRobert Mustacchi }
288