1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2018 Joyent, Inc. 14 */ 15 16 #include <mdb/mdb_ctf.h> 17 #include <sys/mdb_modapi.h> 18 #include "i40e_sw.h" 19 20 #define RSRC_MAX 0x13 21 static const char *i40e_switch_rsrc_names[] = { 22 "VEBs", 23 "VSIs", 24 "Perfect Match MAC Addresses", 25 "S-Tags", 26 "Reserved", 27 "Multicast Hash Entries", 28 "Reserved", 29 "VLANs", 30 "VSI Lists", 31 "Reserved", 32 "VLAN Stat pools", 33 "Mirror rules", 34 "Queue sets", 35 "Inner VLAN Forwarding", 36 "Reserved", 37 "Inner MACs", 38 "IPs", 39 "GRE/VN1 Keys", 40 "VN2 Keys", 41 "Tunnelling Ports" 42 }; 43 44 /* 45 * i40e mdb dcmds 46 */ 47 /* ARGSUSED */ 48 static int 49 i40e_switch_rsrcs_dcmd(uintptr_t addr, uint_t flags, int argc, 50 const mdb_arg_t *argv) 51 { 52 i40e_t i40e; 53 int i; 54 55 if (!(flags & DCMD_ADDRSPEC)) { 56 mdb_warn("::i40e_switch_rsrcs does not operate globally\n"); 57 return (DCMD_USAGE); 58 } 59 60 if (mdb_vread(&i40e, sizeof (i40e_t), addr) != sizeof (i40e_t)) { 61 mdb_warn("failed to read i40e_t at %p", addr); 62 return (DCMD_ERR); 63 } 64 65 mdb_printf("%-28s %-12s %-8s %-8s %s\n", "TYPE", "GUARANTEE", 66 "TOTAL", "USED", "UNALLOCED"); 67 68 for (i = 0; i < i40e.i40e_switch_rsrc_actual; i++) { 69 i40e_switch_rsrc_t rsrc; 70 uintptr_t raddr = (uintptr_t)i40e.i40e_switch_rsrcs + 71 i * sizeof (i40e_switch_rsrc_t); 72 const char *name; 73 74 if (mdb_vread(&rsrc, sizeof (i40e_switch_rsrc_t), raddr) != 75 sizeof (i40e_switch_rsrc_t)) { 76 mdb_warn("failed to read i40e_switch_rsrc_t %d at %p", 77 i, raddr); 78 return (DCMD_ERR); 79 } 80 81 if (rsrc.resource_type <= RSRC_MAX) { 82 name = i40e_switch_rsrc_names[rsrc.resource_type]; 83 } else { 84 char *buf; 85 size_t s = mdb_snprintf(NULL, 0, "Unknown type (%d)", 86 rsrc.resource_type); 87 buf = mdb_alloc(s + 1, UM_GC | UM_SLEEP); 88 (void) mdb_snprintf(buf, s + 1, "Unknown type (%d)", 89 rsrc.resource_type); 90 name = buf; 91 } 92 93 mdb_printf("%-28s %-12d %-8d %-8d %d\n", name, 94 LE_16(rsrc.guaranteed), LE_16(rsrc.total), LE_16(rsrc.used), 95 LE_16(rsrc.total_unalloced)); 96 } 97 98 return (DCMD_OK); 99 } 100 101 typedef struct mdb_i40e_trqpair { 102 uint32_t itrq_tx_ring_size; 103 uint32_t itrq_desc_free; 104 uint32_t *itrq_desc_wbhead; 105 uint32_t itrq_desc_head; 106 uint32_t itrq_desc_tail; 107 i40e_tx_desc_t *itrq_desc_ring; 108 i40e_tx_control_block_t **itrq_tcb_work_list; 109 } mdb_i40e_trqpair_t; 110 111 static void 112 i40e_tx_ring_help() 113 { 114 mdb_printf( 115 "\t -a dump all ring entries\n" 116 "\t or\n" 117 "\t combine -b [start index] with -e [end index] to specify a \n" 118 "\t range of ring entries to print\n"); 119 } 120 121 static int 122 i40e_tx_ring_dcmd(uintptr_t addr, uint_t flags, int argc, 123 const mdb_arg_t *argv) 124 { 125 mdb_i40e_trqpair_t trq; 126 i40e_tx_desc_t *descring; 127 i40e_tx_control_block_t **wklist; 128 uint32_t wbhead; 129 size_t ringsz, wklistsz; 130 boolean_t opt_a = B_FALSE; 131 char *opt_b = NULL, *opt_e = NULL; 132 uint64_t begin = UINT64_MAX, end = UINT64_MAX; 133 134 if (!(flags & DCMD_ADDRSPEC)) { 135 mdb_warn("::i40e_tx_ring does not operate globally\n"); 136 return (DCMD_USAGE); 137 } 138 139 if (mdb_getopts(argc, argv, 140 'a', MDB_OPT_SETBITS, B_TRUE, &opt_a, 141 'b', MDB_OPT_STR, &opt_b, 142 'e', MDB_OPT_STR, &opt_e, NULL) != argc) 143 return (DCMD_USAGE); 144 145 /* 146 * Verify that a legal combination of -a/-b/-e were used. 147 */ 148 if (opt_a && (opt_b != NULL || opt_e != NULL)) { 149 mdb_warn("-a and -b/-e are mutually exclusive\n"); 150 return (DCMD_USAGE); 151 } 152 if (argc > 0 && ! opt_a && (opt_b == NULL || opt_e == NULL)) { 153 mdb_warn("-b/-e must both be specified\n"); 154 return (DCMD_USAGE); 155 } 156 157 if (mdb_ctf_vread(&trq, "i40e_trqpair_t", "mdb_i40e_trqpair_t", addr, 158 0) == -1) { 159 mdb_warn("failed to read i40e_trqpair_t at %p", addr); 160 return (DCMD_ERR); 161 } 162 163 if (opt_b != NULL) 164 begin = mdb_strtoull(opt_b); 165 if (opt_e != NULL) 166 end = mdb_strtoull(opt_e); 167 if (opt_a) { 168 begin = 0; 169 end = trq.itrq_tx_ring_size - 1; 170 } 171 172 /* 173 * Verify that the requested range of ring entries makes sense. 174 */ 175 if (argc > 0 && (end < begin || begin >= trq.itrq_tx_ring_size || 176 end >= trq.itrq_tx_ring_size)) { 177 mdb_warn("invalid range specified\n"); 178 return (DCMD_USAGE); 179 } 180 181 if (mdb_vread(&wbhead, sizeof (uint32_t), 182 (uintptr_t)trq.itrq_desc_wbhead) != sizeof (uint32_t)) { 183 mdb_warn("failed to read trq.itrq_desc_wbhead"); 184 return (DCMD_ERR); 185 } 186 mdb_printf("%-20s%d\n", "Ring Size:", trq.itrq_tx_ring_size); 187 mdb_printf("%-20s%d\n", "Free Descriptors:", trq.itrq_desc_free); 188 mdb_printf("%-20s%d\n", "Writeback Head:", wbhead); 189 mdb_printf("%-20s%d\n", "Head:", trq.itrq_desc_head); 190 mdb_printf("%-20s%d\n", "Tail:", trq.itrq_desc_tail); 191 192 /* 193 * No arguments were specified, so we're done. 194 */ 195 if (argc == 0) 196 return (DCMD_OK); 197 198 /* 199 * Allocate memory and read in the entire TX descriptor ring and 200 * TCB work list. 201 */ 202 ringsz = sizeof (i40e_tx_desc_t) * trq.itrq_tx_ring_size; 203 descring = mdb_alloc(ringsz, UM_SLEEP); 204 if (mdb_vread(descring, ringsz, (uintptr_t)trq.itrq_desc_ring) != 205 ringsz) { 206 mdb_warn("Failed to read in TX decriptor ring\n"); 207 mdb_free(descring, ringsz); 208 return (DCMD_ERR); 209 } 210 wklistsz = sizeof (i40e_tx_control_block_t *) * trq.itrq_tx_ring_size; 211 wklist = mdb_alloc(wklistsz, UM_SLEEP); 212 if (mdb_vread(wklist, wklistsz, (uintptr_t)trq.itrq_tcb_work_list) != 213 wklistsz) { 214 mdb_warn("Failed to read in TX TCB work list\n"); 215 mdb_free(descring, ringsz); 216 mdb_free(wklist, wklistsz); 217 return (DCMD_ERR); 218 } 219 220 mdb_printf("\n%-10s %-10s %-16s %-16s %-10s\n", "Index", "Desc Type", 221 "Desc Ptr", "TCB Ptr", "Other"); 222 for (uint64_t i = begin; i <= end; i++) { 223 const char *dtype; 224 char dother[17]; 225 i40e_tx_desc_t *dptr; 226 i40e_tx_control_block_t *tcbptr; 227 uint64_t ctob; 228 229 dptr = &descring[i]; 230 tcbptr = wklist[i]; 231 ctob = LE_64(dptr->cmd_type_offset_bsz); 232 if (ctob == 0) { 233 dtype = "FREE"; 234 } else { 235 switch (ctob & I40E_TXD_QW1_DTYPE_MASK) { 236 case (I40E_TX_DESC_DTYPE_CONTEXT): 237 dtype = "CONTEXT"; 238 break; 239 case (I40E_TX_DESC_DTYPE_DATA): 240 dtype = "DATA"; 241 break; 242 case (I40E_TX_DESC_DTYPE_FILTER_PROG): 243 dtype = "FILTER"; 244 break; 245 default: 246 dtype = "UNKNOWN"; 247 } 248 } 249 dother[0] = '\0'; 250 if (i == wbhead) 251 (void) strcat(dother, "WBHEAD"); 252 253 if (i == trq.itrq_desc_head) 254 (void) strcat(dother, 255 strlen(dother) > 0 ? " HEAD" : "HEAD"); 256 257 if (i == trq.itrq_desc_tail) 258 (void) strcat(dother, 259 strlen(dother) > 0 ? " TAIL" : "TAIL"); 260 261 mdb_printf("%-10d %-10s %-16p %-16p %-10s\n", i, dtype, dptr, 262 tcbptr, dother); 263 } 264 265 mdb_free(descring, ringsz); 266 mdb_free(wklist, wklistsz); 267 return (DCMD_OK); 268 } 269 270 static const mdb_dcmd_t i40e_dcmds[] = { 271 { "i40e_switch_rsrcs", NULL, "print switch resources", 272 i40e_switch_rsrcs_dcmd, NULL }, 273 { "i40e_tx_ring", "[-a] -b [start index] -e [end index]\n", 274 "dump TX descriptor ring state", i40e_tx_ring_dcmd, 275 i40e_tx_ring_help }, 276 { NULL } 277 }; 278 279 static const mdb_modinfo_t i40e_modinfo = { 280 MDB_API_VERSION, i40e_dcmds, NULL 281 }; 282 283 const mdb_modinfo_t * 284 _mdb_init(void) 285 { 286 return (&i40e_modinfo); 287 } 288