154912308SNavdeep Parhar /*- 254912308SNavdeep Parhar * Copyright (c) 2011 Chelsio Communications, Inc. 354912308SNavdeep Parhar * All rights reserved. 454912308SNavdeep Parhar * Written by: Navdeep Parhar <np@FreeBSD.org> 554912308SNavdeep Parhar * 654912308SNavdeep Parhar * Redistribution and use in source and binary forms, with or without 754912308SNavdeep Parhar * modification, are permitted provided that the following conditions 854912308SNavdeep Parhar * are met: 954912308SNavdeep Parhar * 1. Redistributions of source code must retain the above copyright 1054912308SNavdeep Parhar * notice, this list of conditions and the following disclaimer. 1154912308SNavdeep Parhar * 2. Redistributions in binary form must reproduce the above copyright 1254912308SNavdeep Parhar * notice, this list of conditions and the following disclaimer in the 1354912308SNavdeep Parhar * documentation and/or other materials provided with the distribution. 1454912308SNavdeep Parhar * 1554912308SNavdeep Parhar * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1654912308SNavdeep Parhar * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1754912308SNavdeep Parhar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1854912308SNavdeep Parhar * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1954912308SNavdeep Parhar * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2054912308SNavdeep Parhar * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2154912308SNavdeep Parhar * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2254912308SNavdeep Parhar * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2354912308SNavdeep Parhar * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2454912308SNavdeep Parhar * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2554912308SNavdeep Parhar * SUCH DAMAGE. 2654912308SNavdeep Parhar */ 2754912308SNavdeep Parhar 2854912308SNavdeep Parhar #include <sys/cdefs.h> 2954912308SNavdeep Parhar __FBSDID("$FreeBSD$"); 3054912308SNavdeep Parhar 3154912308SNavdeep Parhar #include <sys/param.h> 3254912308SNavdeep Parhar #include <sys/ioctl.h> 3354912308SNavdeep Parhar #include <sys/mman.h> 3454912308SNavdeep Parhar #include <sys/socket.h> 3554912308SNavdeep Parhar #include <sys/stat.h> 3654912308SNavdeep Parhar 3754912308SNavdeep Parhar #include <arpa/inet.h> 3854912308SNavdeep Parhar #include <net/ethernet.h> 3954912308SNavdeep Parhar #include <net/sff8472.h> 4054912308SNavdeep Parhar #include <netinet/in.h> 4154912308SNavdeep Parhar 4254912308SNavdeep Parhar #include <ctype.h> 4354912308SNavdeep Parhar #include <err.h> 4454912308SNavdeep Parhar #include <errno.h> 4554912308SNavdeep Parhar #include <fcntl.h> 4654912308SNavdeep Parhar #include <limits.h> 4754912308SNavdeep Parhar #include <stdint.h> 4854912308SNavdeep Parhar #include <stdio.h> 4954912308SNavdeep Parhar #include <stdlib.h> 5054912308SNavdeep Parhar #include <string.h> 5154912308SNavdeep Parhar #include <unistd.h> 521131c927SNavdeep Parhar #include <pcap.h> 5354912308SNavdeep Parhar 5454912308SNavdeep Parhar #include "t4_ioctl.h" 55ae9b4017SNavdeep Parhar #include "tcb_common.h" 5654912308SNavdeep Parhar 5754912308SNavdeep Parhar #define in_range(val, lo, hi) ( val < 0 || (val <= hi && val >= lo)) 5854912308SNavdeep Parhar #define max(x, y) ((x) > (y) ? (x) : (y)) 5954912308SNavdeep Parhar 6054912308SNavdeep Parhar static const char *progname, *nexus; 6154912308SNavdeep Parhar static int chip_id; /* 4 for T4, 5 for T5 */ 6254912308SNavdeep Parhar 6354912308SNavdeep Parhar struct reg_info { 6454912308SNavdeep Parhar const char *name; 6554912308SNavdeep Parhar uint32_t addr; 6654912308SNavdeep Parhar uint32_t len; 6754912308SNavdeep Parhar }; 6854912308SNavdeep Parhar 6954912308SNavdeep Parhar struct mod_regs { 7054912308SNavdeep Parhar const char *name; 7154912308SNavdeep Parhar const struct reg_info *ri; 7254912308SNavdeep Parhar }; 7354912308SNavdeep Parhar 7454912308SNavdeep Parhar struct field_desc { 7554912308SNavdeep Parhar const char *name; /* Field name */ 7654912308SNavdeep Parhar unsigned short start; /* Start bit position */ 7754912308SNavdeep Parhar unsigned short end; /* End bit position */ 7854912308SNavdeep Parhar unsigned char shift; /* # of low order bits omitted and implicitly 0 */ 7954912308SNavdeep Parhar unsigned char hex; /* Print field in hex instead of decimal */ 8054912308SNavdeep Parhar unsigned char islog2; /* Field contains the base-2 log of the value */ 8154912308SNavdeep Parhar }; 8254912308SNavdeep Parhar 8354912308SNavdeep Parhar #include "reg_defs_t4.c" 8454912308SNavdeep Parhar #include "reg_defs_t5.c" 8554912308SNavdeep Parhar #include "reg_defs_t6.c" 8654912308SNavdeep Parhar #include "reg_defs_t4vf.c" 8754912308SNavdeep Parhar 8854912308SNavdeep Parhar static void 8954912308SNavdeep Parhar usage(FILE *fp) 9054912308SNavdeep Parhar { 9154912308SNavdeep Parhar fprintf(fp, "Usage: %s <nexus> [operation]\n", progname); 9254912308SNavdeep Parhar fprintf(fp, 9354912308SNavdeep Parhar "\tclearstats <port> clear port statistics\n" 9454912308SNavdeep Parhar "\tcontext <type> <id> show an SGE context\n" 95f856f099SNavdeep Parhar "\tdumpstate <dump.bin> dump chip state\n" 9654912308SNavdeep Parhar "\tfilter <idx> [<param> <val>] ... set a filter\n" 97*6ba81353SNavdeep Parhar "\tfilter <idx> delete|clear [prio 1] delete a filter\n" 9854912308SNavdeep Parhar "\tfilter list list all filters\n" 9954912308SNavdeep Parhar "\tfilter mode [<match>] ... get/set global filter mode\n" 10036ea2fe3SNavdeep Parhar "\thashfilter [<param> <val>] ... set a hashfilter\n" 10136ea2fe3SNavdeep Parhar "\thashfilter <idx> delete|clear delete a hashfilter\n" 10236ea2fe3SNavdeep Parhar "\thashfilter list list all hashfilters\n" 10336ea2fe3SNavdeep Parhar "\thashfilter mode get global hashfilter mode\n" 10454912308SNavdeep Parhar "\ti2c <port> <devaddr> <addr> [<len>] read from i2c device\n" 1058f82718fSNavdeep Parhar "\tloadboot <bi.bin> [pf|offset <val>] install boot image\n" 1068f82718fSNavdeep Parhar "\tloadboot clear [pf|offset <val>] remove boot image\n" 1078f82718fSNavdeep Parhar "\tloadboot-cfg <bc.bin> install boot config\n" 1088f82718fSNavdeep Parhar "\tloadboot-cfg clear remove boot config\n" 10954912308SNavdeep Parhar "\tloadcfg <fw-config.txt> install configuration file\n" 11054912308SNavdeep Parhar "\tloadcfg clear remove configuration file\n" 11154912308SNavdeep Parhar "\tloadfw <fw-image.bin> install firmware\n" 11254912308SNavdeep Parhar "\tmemdump <addr> <len> dump a memory range\n" 11354912308SNavdeep Parhar "\tmodinfo <port> [raw] optics/cable information\n" 1141131c927SNavdeep Parhar "\tpolicy <policy.txt> install offload policy\n" 1151131c927SNavdeep Parhar "\tpolicy clear remove offload policy\n" 11654912308SNavdeep Parhar "\treg <address>[=<val>] read/write register\n" 11754912308SNavdeep Parhar "\treg64 <address>[=<val>] read/write 64 bit register\n" 11854912308SNavdeep Parhar "\tregdump [<module>] ... dump registers\n" 11954912308SNavdeep Parhar "\tsched-class params <param> <val> .. configure TX scheduler class\n" 12054912308SNavdeep Parhar "\tsched-queue <port> <queue> <class> bind NIC queues to TX Scheduling class\n" 12154912308SNavdeep Parhar "\tstdio interactive mode\n" 12254912308SNavdeep Parhar "\ttcb <tid> read TCB\n" 12354912308SNavdeep Parhar "\ttracer <idx> tx<n>|rx<n> set and enable a tracer\n" 12454912308SNavdeep Parhar "\ttracer <idx> disable|enable disable or enable a tracer\n" 12554912308SNavdeep Parhar "\ttracer list list all tracers\n" 12654912308SNavdeep Parhar ); 12754912308SNavdeep Parhar } 12854912308SNavdeep Parhar 12954912308SNavdeep Parhar static inline unsigned int 13054912308SNavdeep Parhar get_card_vers(unsigned int version) 13154912308SNavdeep Parhar { 13254912308SNavdeep Parhar return (version & 0x3ff); 13354912308SNavdeep Parhar } 13454912308SNavdeep Parhar 13554912308SNavdeep Parhar static int 13654912308SNavdeep Parhar real_doit(unsigned long cmd, void *data, const char *cmdstr) 13754912308SNavdeep Parhar { 13854912308SNavdeep Parhar static int fd = -1; 13954912308SNavdeep Parhar int rc = 0; 14054912308SNavdeep Parhar 14154912308SNavdeep Parhar if (fd == -1) { 14254912308SNavdeep Parhar char buf[64]; 14354912308SNavdeep Parhar 14454912308SNavdeep Parhar snprintf(buf, sizeof(buf), "/dev/%s", nexus); 14554912308SNavdeep Parhar if ((fd = open(buf, O_RDWR)) < 0) { 14654912308SNavdeep Parhar warn("open(%s)", nexus); 14754912308SNavdeep Parhar rc = errno; 14854912308SNavdeep Parhar return (rc); 14954912308SNavdeep Parhar } 15054912308SNavdeep Parhar } 15154912308SNavdeep Parhar 15254912308SNavdeep Parhar rc = ioctl(fd, cmd, data); 15354912308SNavdeep Parhar if (rc < 0) { 15454912308SNavdeep Parhar warn("%s", cmdstr); 15554912308SNavdeep Parhar rc = errno; 15654912308SNavdeep Parhar } 15754912308SNavdeep Parhar 15854912308SNavdeep Parhar return (rc); 15954912308SNavdeep Parhar } 16054912308SNavdeep Parhar #define doit(x, y) real_doit(x, y, #x) 16154912308SNavdeep Parhar 16254912308SNavdeep Parhar static char * 16354912308SNavdeep Parhar str_to_number(const char *s, long *val, long long *vall) 16454912308SNavdeep Parhar { 16554912308SNavdeep Parhar char *p; 16654912308SNavdeep Parhar 16754912308SNavdeep Parhar if (vall) 16854912308SNavdeep Parhar *vall = strtoll(s, &p, 0); 16954912308SNavdeep Parhar else if (val) 17054912308SNavdeep Parhar *val = strtol(s, &p, 0); 17154912308SNavdeep Parhar else 17254912308SNavdeep Parhar p = NULL; 17354912308SNavdeep Parhar 17454912308SNavdeep Parhar return (p); 17554912308SNavdeep Parhar } 17654912308SNavdeep Parhar 17754912308SNavdeep Parhar static int 17854912308SNavdeep Parhar read_reg(long addr, int size, long long *val) 17954912308SNavdeep Parhar { 18054912308SNavdeep Parhar struct t4_reg reg; 18154912308SNavdeep Parhar int rc; 18254912308SNavdeep Parhar 18354912308SNavdeep Parhar reg.addr = (uint32_t) addr; 18454912308SNavdeep Parhar reg.size = (uint32_t) size; 18554912308SNavdeep Parhar reg.val = 0; 18654912308SNavdeep Parhar 18754912308SNavdeep Parhar rc = doit(CHELSIO_T4_GETREG, ®); 18854912308SNavdeep Parhar 18954912308SNavdeep Parhar *val = reg.val; 19054912308SNavdeep Parhar 19154912308SNavdeep Parhar return (rc); 19254912308SNavdeep Parhar } 19354912308SNavdeep Parhar 19454912308SNavdeep Parhar static int 19554912308SNavdeep Parhar write_reg(long addr, int size, long long val) 19654912308SNavdeep Parhar { 19754912308SNavdeep Parhar struct t4_reg reg; 19854912308SNavdeep Parhar 19954912308SNavdeep Parhar reg.addr = (uint32_t) addr; 20054912308SNavdeep Parhar reg.size = (uint32_t) size; 20154912308SNavdeep Parhar reg.val = (uint64_t) val; 20254912308SNavdeep Parhar 20354912308SNavdeep Parhar return doit(CHELSIO_T4_SETREG, ®); 20454912308SNavdeep Parhar } 20554912308SNavdeep Parhar 20654912308SNavdeep Parhar static int 20754912308SNavdeep Parhar register_io(int argc, const char *argv[], int size) 20854912308SNavdeep Parhar { 20954912308SNavdeep Parhar char *p, *v; 21054912308SNavdeep Parhar long addr; 21154912308SNavdeep Parhar long long val; 21254912308SNavdeep Parhar int w = 0, rc; 21354912308SNavdeep Parhar 21454912308SNavdeep Parhar if (argc == 1) { 21554912308SNavdeep Parhar /* <reg> OR <reg>=<value> */ 21654912308SNavdeep Parhar 21754912308SNavdeep Parhar p = str_to_number(argv[0], &addr, NULL); 21854912308SNavdeep Parhar if (*p) { 21954912308SNavdeep Parhar if (*p != '=') { 22054912308SNavdeep Parhar warnx("invalid register \"%s\"", argv[0]); 22154912308SNavdeep Parhar return (EINVAL); 22254912308SNavdeep Parhar } 22354912308SNavdeep Parhar 22454912308SNavdeep Parhar w = 1; 22554912308SNavdeep Parhar v = p + 1; 22654912308SNavdeep Parhar p = str_to_number(v, NULL, &val); 22754912308SNavdeep Parhar 22854912308SNavdeep Parhar if (*p) { 22954912308SNavdeep Parhar warnx("invalid value \"%s\"", v); 23054912308SNavdeep Parhar return (EINVAL); 23154912308SNavdeep Parhar } 23254912308SNavdeep Parhar } 23354912308SNavdeep Parhar 23454912308SNavdeep Parhar } else if (argc == 2) { 23554912308SNavdeep Parhar /* <reg> <value> */ 23654912308SNavdeep Parhar 23754912308SNavdeep Parhar w = 1; 23854912308SNavdeep Parhar 23954912308SNavdeep Parhar p = str_to_number(argv[0], &addr, NULL); 24054912308SNavdeep Parhar if (*p) { 24154912308SNavdeep Parhar warnx("invalid register \"%s\"", argv[0]); 24254912308SNavdeep Parhar return (EINVAL); 24354912308SNavdeep Parhar } 24454912308SNavdeep Parhar 24554912308SNavdeep Parhar p = str_to_number(argv[1], NULL, &val); 24654912308SNavdeep Parhar if (*p) { 24754912308SNavdeep Parhar warnx("invalid value \"%s\"", argv[1]); 24854912308SNavdeep Parhar return (EINVAL); 24954912308SNavdeep Parhar } 25054912308SNavdeep Parhar } else { 25154912308SNavdeep Parhar warnx("reg: invalid number of arguments (%d)", argc); 25254912308SNavdeep Parhar return (EINVAL); 25354912308SNavdeep Parhar } 25454912308SNavdeep Parhar 25554912308SNavdeep Parhar if (w) 25654912308SNavdeep Parhar rc = write_reg(addr, size, val); 25754912308SNavdeep Parhar else { 25854912308SNavdeep Parhar rc = read_reg(addr, size, &val); 25954912308SNavdeep Parhar if (rc == 0) 26054912308SNavdeep Parhar printf("0x%llx [%llu]\n", val, val); 26154912308SNavdeep Parhar } 26254912308SNavdeep Parhar 26354912308SNavdeep Parhar return (rc); 26454912308SNavdeep Parhar } 26554912308SNavdeep Parhar 26654912308SNavdeep Parhar static inline uint32_t 26754912308SNavdeep Parhar xtract(uint32_t val, int shift, int len) 26854912308SNavdeep Parhar { 26954912308SNavdeep Parhar return (val >> shift) & ((1 << len) - 1); 27054912308SNavdeep Parhar } 27154912308SNavdeep Parhar 27254912308SNavdeep Parhar static int 27354912308SNavdeep Parhar dump_block_regs(const struct reg_info *reg_array, const uint32_t *regs) 27454912308SNavdeep Parhar { 27554912308SNavdeep Parhar uint32_t reg_val = 0; 27654912308SNavdeep Parhar 27754912308SNavdeep Parhar for ( ; reg_array->name; ++reg_array) 27854912308SNavdeep Parhar if (!reg_array->len) { 27954912308SNavdeep Parhar reg_val = regs[reg_array->addr / 4]; 28054912308SNavdeep Parhar printf("[%#7x] %-47s %#-10x %u\n", reg_array->addr, 28154912308SNavdeep Parhar reg_array->name, reg_val, reg_val); 28254912308SNavdeep Parhar } else { 28354912308SNavdeep Parhar uint32_t v = xtract(reg_val, reg_array->addr, 28454912308SNavdeep Parhar reg_array->len); 28554912308SNavdeep Parhar 28654912308SNavdeep Parhar printf(" %*u:%u %-47s %#-10x %u\n", 28754912308SNavdeep Parhar reg_array->addr < 10 ? 3 : 2, 28854912308SNavdeep Parhar reg_array->addr + reg_array->len - 1, 28954912308SNavdeep Parhar reg_array->addr, reg_array->name, v, v); 29054912308SNavdeep Parhar } 29154912308SNavdeep Parhar 29254912308SNavdeep Parhar return (1); 29354912308SNavdeep Parhar } 29454912308SNavdeep Parhar 29554912308SNavdeep Parhar static int 29654912308SNavdeep Parhar dump_regs_table(int argc, const char *argv[], const uint32_t *regs, 29754912308SNavdeep Parhar const struct mod_regs *modtab, int nmodules) 29854912308SNavdeep Parhar { 29954912308SNavdeep Parhar int i, j, match; 30054912308SNavdeep Parhar 30154912308SNavdeep Parhar for (i = 0; i < argc; i++) { 30254912308SNavdeep Parhar for (j = 0; j < nmodules; j++) { 30354912308SNavdeep Parhar if (!strcmp(argv[i], modtab[j].name)) 30454912308SNavdeep Parhar break; 30554912308SNavdeep Parhar } 30654912308SNavdeep Parhar 30754912308SNavdeep Parhar if (j == nmodules) { 30854912308SNavdeep Parhar warnx("invalid register block \"%s\"", argv[i]); 30954912308SNavdeep Parhar fprintf(stderr, "\nAvailable blocks:"); 31054912308SNavdeep Parhar for ( ; nmodules; nmodules--, modtab++) 31154912308SNavdeep Parhar fprintf(stderr, " %s", modtab->name); 31254912308SNavdeep Parhar fprintf(stderr, "\n"); 31354912308SNavdeep Parhar return (EINVAL); 31454912308SNavdeep Parhar } 31554912308SNavdeep Parhar } 31654912308SNavdeep Parhar 31754912308SNavdeep Parhar for ( ; nmodules; nmodules--, modtab++) { 31854912308SNavdeep Parhar 31954912308SNavdeep Parhar match = argc == 0 ? 1 : 0; 32054912308SNavdeep Parhar for (i = 0; !match && i < argc; i++) { 32154912308SNavdeep Parhar if (!strcmp(argv[i], modtab->name)) 32254912308SNavdeep Parhar match = 1; 32354912308SNavdeep Parhar } 32454912308SNavdeep Parhar 32554912308SNavdeep Parhar if (match) 32654912308SNavdeep Parhar dump_block_regs(modtab->ri, regs); 32754912308SNavdeep Parhar } 32854912308SNavdeep Parhar 32954912308SNavdeep Parhar return (0); 33054912308SNavdeep Parhar } 33154912308SNavdeep Parhar 33254912308SNavdeep Parhar #define T4_MODREGS(name) { #name, t4_##name##_regs } 33354912308SNavdeep Parhar static int 33454912308SNavdeep Parhar dump_regs_t4(int argc, const char *argv[], const uint32_t *regs) 33554912308SNavdeep Parhar { 33654912308SNavdeep Parhar static struct mod_regs t4_mod[] = { 33754912308SNavdeep Parhar T4_MODREGS(sge), 33854912308SNavdeep Parhar { "pci", t4_pcie_regs }, 33954912308SNavdeep Parhar T4_MODREGS(dbg), 34054912308SNavdeep Parhar T4_MODREGS(mc), 34154912308SNavdeep Parhar T4_MODREGS(ma), 34254912308SNavdeep Parhar { "edc0", t4_edc_0_regs }, 34354912308SNavdeep Parhar { "edc1", t4_edc_1_regs }, 34454912308SNavdeep Parhar T4_MODREGS(cim), 34554912308SNavdeep Parhar T4_MODREGS(tp), 34654912308SNavdeep Parhar T4_MODREGS(ulp_rx), 34754912308SNavdeep Parhar T4_MODREGS(ulp_tx), 34854912308SNavdeep Parhar { "pmrx", t4_pm_rx_regs }, 34954912308SNavdeep Parhar { "pmtx", t4_pm_tx_regs }, 35054912308SNavdeep Parhar T4_MODREGS(mps), 35154912308SNavdeep Parhar { "cplsw", t4_cpl_switch_regs }, 35254912308SNavdeep Parhar T4_MODREGS(smb), 35354912308SNavdeep Parhar { "i2c", t4_i2cm_regs }, 35454912308SNavdeep Parhar T4_MODREGS(mi), 35554912308SNavdeep Parhar T4_MODREGS(uart), 35654912308SNavdeep Parhar T4_MODREGS(pmu), 35754912308SNavdeep Parhar T4_MODREGS(sf), 35854912308SNavdeep Parhar T4_MODREGS(pl), 35954912308SNavdeep Parhar T4_MODREGS(le), 36054912308SNavdeep Parhar T4_MODREGS(ncsi), 36154912308SNavdeep Parhar T4_MODREGS(xgmac) 36254912308SNavdeep Parhar }; 36354912308SNavdeep Parhar 36454912308SNavdeep Parhar return dump_regs_table(argc, argv, regs, t4_mod, nitems(t4_mod)); 36554912308SNavdeep Parhar } 36654912308SNavdeep Parhar #undef T4_MODREGS 36754912308SNavdeep Parhar 36854912308SNavdeep Parhar #define T5_MODREGS(name) { #name, t5_##name##_regs } 36954912308SNavdeep Parhar static int 37054912308SNavdeep Parhar dump_regs_t5(int argc, const char *argv[], const uint32_t *regs) 37154912308SNavdeep Parhar { 37254912308SNavdeep Parhar static struct mod_regs t5_mod[] = { 37354912308SNavdeep Parhar T5_MODREGS(sge), 37454912308SNavdeep Parhar { "pci", t5_pcie_regs }, 37554912308SNavdeep Parhar T5_MODREGS(dbg), 37654912308SNavdeep Parhar { "mc0", t5_mc_0_regs }, 37754912308SNavdeep Parhar { "mc1", t5_mc_1_regs }, 37854912308SNavdeep Parhar T5_MODREGS(ma), 37954912308SNavdeep Parhar { "edc0", t5_edc_t50_regs }, 38054912308SNavdeep Parhar { "edc1", t5_edc_t51_regs }, 38154912308SNavdeep Parhar T5_MODREGS(cim), 38254912308SNavdeep Parhar T5_MODREGS(tp), 38354912308SNavdeep Parhar { "ulprx", t5_ulp_rx_regs }, 38454912308SNavdeep Parhar { "ulptx", t5_ulp_tx_regs }, 38554912308SNavdeep Parhar { "pmrx", t5_pm_rx_regs }, 38654912308SNavdeep Parhar { "pmtx", t5_pm_tx_regs }, 38754912308SNavdeep Parhar T5_MODREGS(mps), 38854912308SNavdeep Parhar { "cplsw", t5_cpl_switch_regs }, 38954912308SNavdeep Parhar T5_MODREGS(smb), 39054912308SNavdeep Parhar { "i2c", t5_i2cm_regs }, 39154912308SNavdeep Parhar T5_MODREGS(mi), 39254912308SNavdeep Parhar T5_MODREGS(uart), 39354912308SNavdeep Parhar T5_MODREGS(pmu), 39454912308SNavdeep Parhar T5_MODREGS(sf), 39554912308SNavdeep Parhar T5_MODREGS(pl), 39654912308SNavdeep Parhar T5_MODREGS(le), 39754912308SNavdeep Parhar T5_MODREGS(ncsi), 39854912308SNavdeep Parhar T5_MODREGS(mac), 39954912308SNavdeep Parhar { "hma", t5_hma_t5_regs } 40054912308SNavdeep Parhar }; 40154912308SNavdeep Parhar 40254912308SNavdeep Parhar return dump_regs_table(argc, argv, regs, t5_mod, nitems(t5_mod)); 40354912308SNavdeep Parhar } 40454912308SNavdeep Parhar #undef T5_MODREGS 40554912308SNavdeep Parhar 40654912308SNavdeep Parhar #define T6_MODREGS(name) { #name, t6_##name##_regs } 40754912308SNavdeep Parhar static int 40854912308SNavdeep Parhar dump_regs_t6(int argc, const char *argv[], const uint32_t *regs) 40954912308SNavdeep Parhar { 41054912308SNavdeep Parhar static struct mod_regs t6_mod[] = { 41154912308SNavdeep Parhar T6_MODREGS(sge), 41254912308SNavdeep Parhar { "pci", t6_pcie_regs }, 41354912308SNavdeep Parhar T6_MODREGS(dbg), 41454912308SNavdeep Parhar { "mc0", t6_mc_0_regs }, 41554912308SNavdeep Parhar T6_MODREGS(ma), 41654912308SNavdeep Parhar { "edc0", t6_edc_t60_regs }, 41754912308SNavdeep Parhar { "edc1", t6_edc_t61_regs }, 41854912308SNavdeep Parhar T6_MODREGS(cim), 41954912308SNavdeep Parhar T6_MODREGS(tp), 42054912308SNavdeep Parhar { "ulprx", t6_ulp_rx_regs }, 42154912308SNavdeep Parhar { "ulptx", t6_ulp_tx_regs }, 42254912308SNavdeep Parhar { "pmrx", t6_pm_rx_regs }, 42354912308SNavdeep Parhar { "pmtx", t6_pm_tx_regs }, 42454912308SNavdeep Parhar T6_MODREGS(mps), 42554912308SNavdeep Parhar { "cplsw", t6_cpl_switch_regs }, 42654912308SNavdeep Parhar T6_MODREGS(smb), 42754912308SNavdeep Parhar { "i2c", t6_i2cm_regs }, 42854912308SNavdeep Parhar T6_MODREGS(mi), 42954912308SNavdeep Parhar T6_MODREGS(uart), 43054912308SNavdeep Parhar T6_MODREGS(pmu), 43154912308SNavdeep Parhar T6_MODREGS(sf), 43254912308SNavdeep Parhar T6_MODREGS(pl), 43354912308SNavdeep Parhar T6_MODREGS(le), 43454912308SNavdeep Parhar T6_MODREGS(ncsi), 43554912308SNavdeep Parhar T6_MODREGS(mac), 43654912308SNavdeep Parhar { "hma", t6_hma_t6_regs } 43754912308SNavdeep Parhar }; 43854912308SNavdeep Parhar 43954912308SNavdeep Parhar return dump_regs_table(argc, argv, regs, t6_mod, nitems(t6_mod)); 44054912308SNavdeep Parhar } 44154912308SNavdeep Parhar #undef T6_MODREGS 44254912308SNavdeep Parhar 44354912308SNavdeep Parhar static int 44454912308SNavdeep Parhar dump_regs_t4vf(int argc, const char *argv[], const uint32_t *regs) 44554912308SNavdeep Parhar { 44654912308SNavdeep Parhar static struct mod_regs t4vf_mod[] = { 44754912308SNavdeep Parhar { "sge", t4vf_sge_regs }, 44854912308SNavdeep Parhar { "mps", t4vf_mps_regs }, 44954912308SNavdeep Parhar { "pl", t4vf_pl_regs }, 45054912308SNavdeep Parhar { "mbdata", t4vf_mbdata_regs }, 45154912308SNavdeep Parhar { "cim", t4vf_cim_regs }, 45254912308SNavdeep Parhar }; 45354912308SNavdeep Parhar 45454912308SNavdeep Parhar return dump_regs_table(argc, argv, regs, t4vf_mod, nitems(t4vf_mod)); 45554912308SNavdeep Parhar } 45654912308SNavdeep Parhar 45754912308SNavdeep Parhar static int 45854912308SNavdeep Parhar dump_regs_t5vf(int argc, const char *argv[], const uint32_t *regs) 45954912308SNavdeep Parhar { 46054912308SNavdeep Parhar static struct mod_regs t5vf_mod[] = { 46154912308SNavdeep Parhar { "sge", t5vf_sge_regs }, 46254912308SNavdeep Parhar { "mps", t4vf_mps_regs }, 46354912308SNavdeep Parhar { "pl", t5vf_pl_regs }, 46454912308SNavdeep Parhar { "mbdata", t4vf_mbdata_regs }, 46554912308SNavdeep Parhar { "cim", t4vf_cim_regs }, 46654912308SNavdeep Parhar }; 46754912308SNavdeep Parhar 46854912308SNavdeep Parhar return dump_regs_table(argc, argv, regs, t5vf_mod, nitems(t5vf_mod)); 46954912308SNavdeep Parhar } 47054912308SNavdeep Parhar 47154912308SNavdeep Parhar static int 47254912308SNavdeep Parhar dump_regs_t6vf(int argc, const char *argv[], const uint32_t *regs) 47354912308SNavdeep Parhar { 47454912308SNavdeep Parhar static struct mod_regs t6vf_mod[] = { 47554912308SNavdeep Parhar { "sge", t5vf_sge_regs }, 47654912308SNavdeep Parhar { "mps", t4vf_mps_regs }, 47754912308SNavdeep Parhar { "pl", t6vf_pl_regs }, 47854912308SNavdeep Parhar { "mbdata", t4vf_mbdata_regs }, 47954912308SNavdeep Parhar { "cim", t4vf_cim_regs }, 48054912308SNavdeep Parhar }; 48154912308SNavdeep Parhar 48254912308SNavdeep Parhar return dump_regs_table(argc, argv, regs, t6vf_mod, nitems(t6vf_mod)); 48354912308SNavdeep Parhar } 48454912308SNavdeep Parhar 48554912308SNavdeep Parhar static int 48654912308SNavdeep Parhar dump_regs(int argc, const char *argv[]) 48754912308SNavdeep Parhar { 48854912308SNavdeep Parhar int vers, revision, rc; 48954912308SNavdeep Parhar struct t4_regdump regs; 49054912308SNavdeep Parhar uint32_t len; 49154912308SNavdeep Parhar 49254912308SNavdeep Parhar len = max(T4_REGDUMP_SIZE, T5_REGDUMP_SIZE); 49354912308SNavdeep Parhar regs.data = calloc(1, len); 49454912308SNavdeep Parhar if (regs.data == NULL) { 49554912308SNavdeep Parhar warnc(ENOMEM, "regdump"); 49654912308SNavdeep Parhar return (ENOMEM); 49754912308SNavdeep Parhar } 49854912308SNavdeep Parhar 49954912308SNavdeep Parhar regs.len = len; 50054912308SNavdeep Parhar rc = doit(CHELSIO_T4_REGDUMP, ®s); 50154912308SNavdeep Parhar if (rc != 0) 50254912308SNavdeep Parhar return (rc); 50354912308SNavdeep Parhar 50454912308SNavdeep Parhar vers = get_card_vers(regs.version); 50554912308SNavdeep Parhar revision = (regs.version >> 10) & 0x3f; 50654912308SNavdeep Parhar 50754912308SNavdeep Parhar if (vers == 4) { 50854912308SNavdeep Parhar if (revision == 0x3f) 50954912308SNavdeep Parhar rc = dump_regs_t4vf(argc, argv, regs.data); 51054912308SNavdeep Parhar else 51154912308SNavdeep Parhar rc = dump_regs_t4(argc, argv, regs.data); 51254912308SNavdeep Parhar } else if (vers == 5) { 51354912308SNavdeep Parhar if (revision == 0x3f) 51454912308SNavdeep Parhar rc = dump_regs_t5vf(argc, argv, regs.data); 51554912308SNavdeep Parhar else 51654912308SNavdeep Parhar rc = dump_regs_t5(argc, argv, regs.data); 51754912308SNavdeep Parhar } else if (vers == 6) { 51854912308SNavdeep Parhar if (revision == 0x3f) 51954912308SNavdeep Parhar rc = dump_regs_t6vf(argc, argv, regs.data); 52054912308SNavdeep Parhar else 52154912308SNavdeep Parhar rc = dump_regs_t6(argc, argv, regs.data); 52254912308SNavdeep Parhar } else { 52354912308SNavdeep Parhar warnx("%s (type %d, rev %d) is not a known card.", 52454912308SNavdeep Parhar nexus, vers, revision); 52554912308SNavdeep Parhar return (ENOTSUP); 52654912308SNavdeep Parhar } 52754912308SNavdeep Parhar 52854912308SNavdeep Parhar free(regs.data); 52954912308SNavdeep Parhar return (rc); 53054912308SNavdeep Parhar } 53154912308SNavdeep Parhar 53254912308SNavdeep Parhar static void 53354912308SNavdeep Parhar do_show_info_header(uint32_t mode) 53454912308SNavdeep Parhar { 53554912308SNavdeep Parhar uint32_t i; 53654912308SNavdeep Parhar 53754912308SNavdeep Parhar printf("%4s %8s", "Idx", "Hits"); 53854912308SNavdeep Parhar for (i = T4_FILTER_FCoE; i <= T4_FILTER_IP_FRAGMENT; i <<= 1) { 53954912308SNavdeep Parhar switch (mode & i) { 54054912308SNavdeep Parhar case T4_FILTER_FCoE: 54154912308SNavdeep Parhar printf(" FCoE"); 54254912308SNavdeep Parhar break; 54354912308SNavdeep Parhar 54454912308SNavdeep Parhar case T4_FILTER_PORT: 54554912308SNavdeep Parhar printf(" Port"); 54654912308SNavdeep Parhar break; 54754912308SNavdeep Parhar 54854912308SNavdeep Parhar case T4_FILTER_VNIC: 54954912308SNavdeep Parhar if (mode & T4_FILTER_IC_VNIC) 55054912308SNavdeep Parhar printf(" VFvld:PF:VF"); 55154912308SNavdeep Parhar else 55254912308SNavdeep Parhar printf(" vld:oVLAN"); 55354912308SNavdeep Parhar break; 55454912308SNavdeep Parhar 55554912308SNavdeep Parhar case T4_FILTER_VLAN: 55654912308SNavdeep Parhar printf(" vld:VLAN"); 55754912308SNavdeep Parhar break; 55854912308SNavdeep Parhar 55954912308SNavdeep Parhar case T4_FILTER_IP_TOS: 56054912308SNavdeep Parhar printf(" TOS"); 56154912308SNavdeep Parhar break; 56254912308SNavdeep Parhar 56354912308SNavdeep Parhar case T4_FILTER_IP_PROTO: 56454912308SNavdeep Parhar printf(" Prot"); 56554912308SNavdeep Parhar break; 56654912308SNavdeep Parhar 56754912308SNavdeep Parhar case T4_FILTER_ETH_TYPE: 56854912308SNavdeep Parhar printf(" EthType"); 56954912308SNavdeep Parhar break; 57054912308SNavdeep Parhar 57154912308SNavdeep Parhar case T4_FILTER_MAC_IDX: 57254912308SNavdeep Parhar printf(" MACIdx"); 57354912308SNavdeep Parhar break; 57454912308SNavdeep Parhar 57554912308SNavdeep Parhar case T4_FILTER_MPS_HIT_TYPE: 57654912308SNavdeep Parhar printf(" MPS"); 57754912308SNavdeep Parhar break; 57854912308SNavdeep Parhar 57954912308SNavdeep Parhar case T4_FILTER_IP_FRAGMENT: 58054912308SNavdeep Parhar printf(" Frag"); 58154912308SNavdeep Parhar break; 58254912308SNavdeep Parhar 58354912308SNavdeep Parhar default: 58454912308SNavdeep Parhar /* compressed filter field not enabled */ 58554912308SNavdeep Parhar break; 58654912308SNavdeep Parhar } 58754912308SNavdeep Parhar } 58854912308SNavdeep Parhar printf(" %20s %20s %9s %9s %s\n", 58954912308SNavdeep Parhar "DIP", "SIP", "DPORT", "SPORT", "Action"); 59054912308SNavdeep Parhar } 59154912308SNavdeep Parhar 59254912308SNavdeep Parhar /* 59354912308SNavdeep Parhar * Parse an argument sub-vector as a { <parameter name> <value>[:<mask>] } 59454912308SNavdeep Parhar * ordered tuple. If the parameter name in the argument sub-vector does not 59554912308SNavdeep Parhar * match the passed in parameter name, then a zero is returned for the 59654912308SNavdeep Parhar * function and no parsing is performed. If there is a match, then the value 59754912308SNavdeep Parhar * and optional mask are parsed and returned in the provided return value 59854912308SNavdeep Parhar * pointers. If no optional mask is specified, then a default mask of all 1s 59954912308SNavdeep Parhar * will be returned. 60054912308SNavdeep Parhar * 60154912308SNavdeep Parhar * An error in parsing the value[:mask] will result in an error message and 60254912308SNavdeep Parhar * program termination. 60354912308SNavdeep Parhar */ 60454912308SNavdeep Parhar static int 60554912308SNavdeep Parhar parse_val_mask(const char *param, const char *args[], uint32_t *val, 60636ea2fe3SNavdeep Parhar uint32_t *mask, int hashfilter) 60754912308SNavdeep Parhar { 608a12a06faSNavdeep Parhar long l; 60954912308SNavdeep Parhar char *p; 61054912308SNavdeep Parhar 61154912308SNavdeep Parhar if (strcmp(param, args[0]) != 0) 61254912308SNavdeep Parhar return (EINVAL); 61354912308SNavdeep Parhar 614a12a06faSNavdeep Parhar p = str_to_number(args[1], &l, NULL); 615a12a06faSNavdeep Parhar if (l >= 0 && l <= UINT32_MAX) { 616a12a06faSNavdeep Parhar *val = (uint32_t)l; 61754912308SNavdeep Parhar if (p > args[1]) { 61854912308SNavdeep Parhar if (p[0] == 0) { 61954912308SNavdeep Parhar *mask = ~0; 62054912308SNavdeep Parhar return (0); 62154912308SNavdeep Parhar } 62254912308SNavdeep Parhar 62354912308SNavdeep Parhar if (p[0] == ':' && p[1] != 0) { 62436ea2fe3SNavdeep Parhar if (hashfilter) { 62536ea2fe3SNavdeep Parhar warnx("param %s: mask not allowed for " 62636ea2fe3SNavdeep Parhar "hashfilter or nat params", param); 62736ea2fe3SNavdeep Parhar return (EINVAL); 62836ea2fe3SNavdeep Parhar } 629a12a06faSNavdeep Parhar p = str_to_number(p + 1, &l, NULL); 630a12a06faSNavdeep Parhar if (l >= 0 && l <= UINT32_MAX && p[0] == 0) { 631a12a06faSNavdeep Parhar *mask = (uint32_t)l; 63254912308SNavdeep Parhar return (0); 633a12a06faSNavdeep Parhar } 634a12a06faSNavdeep Parhar } 63554912308SNavdeep Parhar } 63654912308SNavdeep Parhar } 63754912308SNavdeep Parhar 63854912308SNavdeep Parhar warnx("parameter \"%s\" has bad \"value[:mask]\" %s", 63954912308SNavdeep Parhar args[0], args[1]); 64054912308SNavdeep Parhar 64154912308SNavdeep Parhar return (EINVAL); 64254912308SNavdeep Parhar } 64354912308SNavdeep Parhar 64454912308SNavdeep Parhar /* 64554912308SNavdeep Parhar * Parse an argument sub-vector as a { <parameter name> <addr>[/<mask>] } 64654912308SNavdeep Parhar * ordered tuple. If the parameter name in the argument sub-vector does not 64754912308SNavdeep Parhar * match the passed in parameter name, then a zero is returned for the 64854912308SNavdeep Parhar * function and no parsing is performed. If there is a match, then the value 64954912308SNavdeep Parhar * and optional mask are parsed and returned in the provided return value 65054912308SNavdeep Parhar * pointers. If no optional mask is specified, then a default mask of all 1s 65154912308SNavdeep Parhar * will be returned. 65254912308SNavdeep Parhar * 65354912308SNavdeep Parhar * The value return parameter "afp" is used to specify the expected address 65454912308SNavdeep Parhar * family -- IPv4 or IPv6 -- of the address[/mask] and return its actual 65554912308SNavdeep Parhar * format. A passed in value of AF_UNSPEC indicates that either IPv4 or IPv6 65654912308SNavdeep Parhar * is acceptable; AF_INET means that only IPv4 addresses are acceptable; and 65754912308SNavdeep Parhar * AF_INET6 means that only IPv6 are acceptable. AF_INET is returned for IPv4 65854912308SNavdeep Parhar * and AF_INET6 for IPv6 addresses, respectively. IPv4 address/mask pairs are 65954912308SNavdeep Parhar * returned in the first four bytes of the address and mask return values with 66054912308SNavdeep Parhar * the address A.B.C.D returned with { A, B, C, D } returned in addresses { 0, 66154912308SNavdeep Parhar * 1, 2, 3}, respectively. 66254912308SNavdeep Parhar * 66354912308SNavdeep Parhar * An error in parsing the value[:mask] will result in an error message and 66454912308SNavdeep Parhar * program termination. 66554912308SNavdeep Parhar */ 66654912308SNavdeep Parhar static int 66754912308SNavdeep Parhar parse_ipaddr(const char *param, const char *args[], int *afp, uint8_t addr[], 66836ea2fe3SNavdeep Parhar uint8_t mask[], int maskless) 66954912308SNavdeep Parhar { 67054912308SNavdeep Parhar const char *colon, *afn; 67154912308SNavdeep Parhar char *slash; 67254912308SNavdeep Parhar uint8_t *m; 67354912308SNavdeep Parhar int af, ret; 67454912308SNavdeep Parhar unsigned int masksize; 67554912308SNavdeep Parhar 67654912308SNavdeep Parhar /* 67754912308SNavdeep Parhar * Is this our parameter? 67854912308SNavdeep Parhar */ 67954912308SNavdeep Parhar if (strcmp(param, args[0]) != 0) 68054912308SNavdeep Parhar return (EINVAL); 68154912308SNavdeep Parhar 68254912308SNavdeep Parhar /* 68354912308SNavdeep Parhar * Fundamental IPv4 versus IPv6 selection. 68454912308SNavdeep Parhar */ 68554912308SNavdeep Parhar colon = strchr(args[1], ':'); 68654912308SNavdeep Parhar if (!colon) { 68754912308SNavdeep Parhar afn = "IPv4"; 68854912308SNavdeep Parhar af = AF_INET; 68954912308SNavdeep Parhar masksize = 32; 69054912308SNavdeep Parhar } else { 69154912308SNavdeep Parhar afn = "IPv6"; 69254912308SNavdeep Parhar af = AF_INET6; 69354912308SNavdeep Parhar masksize = 128; 69454912308SNavdeep Parhar } 69554912308SNavdeep Parhar if (*afp == AF_UNSPEC) 69654912308SNavdeep Parhar *afp = af; 69754912308SNavdeep Parhar else if (*afp != af) { 69854912308SNavdeep Parhar warnx("address %s is not of expected family %s", 69954912308SNavdeep Parhar args[1], *afp == AF_INET ? "IP" : "IPv6"); 70054912308SNavdeep Parhar return (EINVAL); 70154912308SNavdeep Parhar } 70254912308SNavdeep Parhar 70354912308SNavdeep Parhar /* 70454912308SNavdeep Parhar * Parse address (temporarily stripping off any "/mask" 70554912308SNavdeep Parhar * specification). 70654912308SNavdeep Parhar */ 70754912308SNavdeep Parhar slash = strchr(args[1], '/'); 70854912308SNavdeep Parhar if (slash) 70954912308SNavdeep Parhar *slash = 0; 71054912308SNavdeep Parhar ret = inet_pton(af, args[1], addr); 71154912308SNavdeep Parhar if (slash) 71254912308SNavdeep Parhar *slash = '/'; 71354912308SNavdeep Parhar if (ret <= 0) { 71454912308SNavdeep Parhar warnx("Cannot parse %s %s address %s", param, afn, args[1]); 71554912308SNavdeep Parhar return (EINVAL); 71654912308SNavdeep Parhar } 71754912308SNavdeep Parhar 71854912308SNavdeep Parhar /* 71954912308SNavdeep Parhar * Parse optional mask specification. 72054912308SNavdeep Parhar */ 72154912308SNavdeep Parhar if (slash) { 72254912308SNavdeep Parhar char *p; 72354912308SNavdeep Parhar unsigned int prefix = strtoul(slash + 1, &p, 10); 72454912308SNavdeep Parhar 72536ea2fe3SNavdeep Parhar if (maskless) { 72636ea2fe3SNavdeep Parhar warnx("mask cannot be provided for maskless specification"); 72736ea2fe3SNavdeep Parhar return (EINVAL); 72836ea2fe3SNavdeep Parhar } 72936ea2fe3SNavdeep Parhar 73054912308SNavdeep Parhar if (p == slash + 1) { 73154912308SNavdeep Parhar warnx("missing address prefix for %s", param); 73254912308SNavdeep Parhar return (EINVAL); 73354912308SNavdeep Parhar } 73454912308SNavdeep Parhar if (*p) { 73554912308SNavdeep Parhar warnx("%s is not a valid address prefix", slash + 1); 73654912308SNavdeep Parhar return (EINVAL); 73754912308SNavdeep Parhar } 73854912308SNavdeep Parhar if (prefix > masksize) { 73954912308SNavdeep Parhar warnx("prefix %u is too long for an %s address", 74054912308SNavdeep Parhar prefix, afn); 74154912308SNavdeep Parhar return (EINVAL); 74254912308SNavdeep Parhar } 74354912308SNavdeep Parhar memset(mask, 0, masksize / 8); 74454912308SNavdeep Parhar masksize = prefix; 74554912308SNavdeep Parhar } 74654912308SNavdeep Parhar 74736ea2fe3SNavdeep Parhar if (mask != NULL) { 74854912308SNavdeep Parhar /* 74954912308SNavdeep Parhar * Fill in mask. 75054912308SNavdeep Parhar */ 75154912308SNavdeep Parhar for (m = mask; masksize >= 8; m++, masksize -= 8) 75254912308SNavdeep Parhar *m = ~0; 75354912308SNavdeep Parhar if (masksize) 75454912308SNavdeep Parhar *m = ~0 << (8 - masksize); 75536ea2fe3SNavdeep Parhar } 75654912308SNavdeep Parhar 75754912308SNavdeep Parhar return (0); 75854912308SNavdeep Parhar } 75954912308SNavdeep Parhar 76054912308SNavdeep Parhar /* 76154912308SNavdeep Parhar * Parse an argument sub-vector as a { <parameter name> <value> } ordered 76254912308SNavdeep Parhar * tuple. If the parameter name in the argument sub-vector does not match the 76354912308SNavdeep Parhar * passed in parameter name, then a zero is returned for the function and no 76454912308SNavdeep Parhar * parsing is performed. If there is a match, then the value is parsed and 76554912308SNavdeep Parhar * returned in the provided return value pointer. 76654912308SNavdeep Parhar */ 76754912308SNavdeep Parhar static int 76854912308SNavdeep Parhar parse_val(const char *param, const char *args[], uint32_t *val) 76954912308SNavdeep Parhar { 77054912308SNavdeep Parhar char *p; 771a12a06faSNavdeep Parhar long l; 77254912308SNavdeep Parhar 77354912308SNavdeep Parhar if (strcmp(param, args[0]) != 0) 77454912308SNavdeep Parhar return (EINVAL); 77554912308SNavdeep Parhar 776a12a06faSNavdeep Parhar p = str_to_number(args[1], &l, NULL); 777a12a06faSNavdeep Parhar if (*p || l < 0 || l > UINT32_MAX) { 77854912308SNavdeep Parhar warnx("parameter \"%s\" has bad \"value\" %s", args[0], args[1]); 77954912308SNavdeep Parhar return (EINVAL); 78054912308SNavdeep Parhar } 78154912308SNavdeep Parhar 782a12a06faSNavdeep Parhar *val = (uint32_t)l; 783a12a06faSNavdeep Parhar return (0); 784a12a06faSNavdeep Parhar } 785a12a06faSNavdeep Parhar 78654912308SNavdeep Parhar static void 78754912308SNavdeep Parhar filters_show_ipaddr(int type, uint8_t *addr, uint8_t *addrm) 78854912308SNavdeep Parhar { 78954912308SNavdeep Parhar int noctets, octet; 79054912308SNavdeep Parhar 79154912308SNavdeep Parhar printf(" "); 79254912308SNavdeep Parhar if (type == 0) { 79354912308SNavdeep Parhar noctets = 4; 79454912308SNavdeep Parhar printf("%3s", " "); 79554912308SNavdeep Parhar } else 79654912308SNavdeep Parhar noctets = 16; 79754912308SNavdeep Parhar 79854912308SNavdeep Parhar for (octet = 0; octet < noctets; octet++) 79954912308SNavdeep Parhar printf("%02x", addr[octet]); 80054912308SNavdeep Parhar printf("/"); 80154912308SNavdeep Parhar for (octet = 0; octet < noctets; octet++) 80254912308SNavdeep Parhar printf("%02x", addrm[octet]); 80354912308SNavdeep Parhar } 80454912308SNavdeep Parhar 80554912308SNavdeep Parhar static void 80654912308SNavdeep Parhar do_show_one_filter_info(struct t4_filter *t, uint32_t mode) 80754912308SNavdeep Parhar { 80854912308SNavdeep Parhar uint32_t i; 80954912308SNavdeep Parhar 81054912308SNavdeep Parhar printf("%4d", t->idx); 81154912308SNavdeep Parhar if (t->hits == UINT64_MAX) 81254912308SNavdeep Parhar printf(" %8s", "-"); 81354912308SNavdeep Parhar else 81454912308SNavdeep Parhar printf(" %8ju", t->hits); 81554912308SNavdeep Parhar 81654912308SNavdeep Parhar /* 81754912308SNavdeep Parhar * Compressed header portion of filter. 81854912308SNavdeep Parhar */ 81954912308SNavdeep Parhar for (i = T4_FILTER_FCoE; i <= T4_FILTER_IP_FRAGMENT; i <<= 1) { 82054912308SNavdeep Parhar switch (mode & i) { 82154912308SNavdeep Parhar case T4_FILTER_FCoE: 82254912308SNavdeep Parhar printf(" %1d/%1d", t->fs.val.fcoe, t->fs.mask.fcoe); 82354912308SNavdeep Parhar break; 82454912308SNavdeep Parhar 82554912308SNavdeep Parhar case T4_FILTER_PORT: 82654912308SNavdeep Parhar printf(" %1d/%1d", t->fs.val.iport, t->fs.mask.iport); 82754912308SNavdeep Parhar break; 82854912308SNavdeep Parhar 82954912308SNavdeep Parhar case T4_FILTER_VNIC: 83054912308SNavdeep Parhar if (mode & T4_FILTER_IC_VNIC) { 83154912308SNavdeep Parhar printf(" %1d:%1x:%02x/%1d:%1x:%02x", 83254912308SNavdeep Parhar t->fs.val.pfvf_vld, 83354912308SNavdeep Parhar (t->fs.val.vnic >> 13) & 0x7, 83454912308SNavdeep Parhar t->fs.val.vnic & 0x1fff, 83554912308SNavdeep Parhar t->fs.mask.pfvf_vld, 83654912308SNavdeep Parhar (t->fs.mask.vnic >> 13) & 0x7, 83754912308SNavdeep Parhar t->fs.mask.vnic & 0x1fff); 83854912308SNavdeep Parhar } else { 83954912308SNavdeep Parhar printf(" %1d:%04x/%1d:%04x", 84054912308SNavdeep Parhar t->fs.val.ovlan_vld, t->fs.val.vnic, 84154912308SNavdeep Parhar t->fs.mask.ovlan_vld, t->fs.mask.vnic); 84254912308SNavdeep Parhar } 84354912308SNavdeep Parhar break; 84454912308SNavdeep Parhar 84554912308SNavdeep Parhar case T4_FILTER_VLAN: 84654912308SNavdeep Parhar printf(" %1d:%04x/%1d:%04x", 84754912308SNavdeep Parhar t->fs.val.vlan_vld, t->fs.val.vlan, 84854912308SNavdeep Parhar t->fs.mask.vlan_vld, t->fs.mask.vlan); 84954912308SNavdeep Parhar break; 85054912308SNavdeep Parhar 85154912308SNavdeep Parhar case T4_FILTER_IP_TOS: 85254912308SNavdeep Parhar printf(" %02x/%02x", t->fs.val.tos, t->fs.mask.tos); 85354912308SNavdeep Parhar break; 85454912308SNavdeep Parhar 85554912308SNavdeep Parhar case T4_FILTER_IP_PROTO: 85654912308SNavdeep Parhar printf(" %02x/%02x", t->fs.val.proto, t->fs.mask.proto); 85754912308SNavdeep Parhar break; 85854912308SNavdeep Parhar 85954912308SNavdeep Parhar case T4_FILTER_ETH_TYPE: 86054912308SNavdeep Parhar printf(" %04x/%04x", t->fs.val.ethtype, 86154912308SNavdeep Parhar t->fs.mask.ethtype); 86254912308SNavdeep Parhar break; 86354912308SNavdeep Parhar 86454912308SNavdeep Parhar case T4_FILTER_MAC_IDX: 86554912308SNavdeep Parhar printf(" %03x/%03x", t->fs.val.macidx, 86654912308SNavdeep Parhar t->fs.mask.macidx); 86754912308SNavdeep Parhar break; 86854912308SNavdeep Parhar 86954912308SNavdeep Parhar case T4_FILTER_MPS_HIT_TYPE: 87054912308SNavdeep Parhar printf(" %1x/%1x", t->fs.val.matchtype, 87154912308SNavdeep Parhar t->fs.mask.matchtype); 87254912308SNavdeep Parhar break; 87354912308SNavdeep Parhar 87454912308SNavdeep Parhar case T4_FILTER_IP_FRAGMENT: 87554912308SNavdeep Parhar printf(" %1d/%1d", t->fs.val.frag, t->fs.mask.frag); 87654912308SNavdeep Parhar break; 87754912308SNavdeep Parhar 87854912308SNavdeep Parhar default: 87954912308SNavdeep Parhar /* compressed filter field not enabled */ 88054912308SNavdeep Parhar break; 88154912308SNavdeep Parhar } 88254912308SNavdeep Parhar } 88354912308SNavdeep Parhar 88454912308SNavdeep Parhar /* 88554912308SNavdeep Parhar * Fixed portion of filter. 88654912308SNavdeep Parhar */ 88754912308SNavdeep Parhar filters_show_ipaddr(t->fs.type, t->fs.val.dip, t->fs.mask.dip); 88854912308SNavdeep Parhar filters_show_ipaddr(t->fs.type, t->fs.val.sip, t->fs.mask.sip); 88954912308SNavdeep Parhar printf(" %04x/%04x %04x/%04x", 89054912308SNavdeep Parhar t->fs.val.dport, t->fs.mask.dport, 89154912308SNavdeep Parhar t->fs.val.sport, t->fs.mask.sport); 89254912308SNavdeep Parhar 89354912308SNavdeep Parhar /* 89454912308SNavdeep Parhar * Variable length filter action. 89554912308SNavdeep Parhar */ 89654912308SNavdeep Parhar if (t->fs.action == FILTER_DROP) 89754912308SNavdeep Parhar printf(" Drop"); 89854912308SNavdeep Parhar else if (t->fs.action == FILTER_SWITCH) { 89954912308SNavdeep Parhar printf(" Switch: port=%d", t->fs.eport); 90054912308SNavdeep Parhar if (t->fs.newdmac) 90154912308SNavdeep Parhar printf( 90254912308SNavdeep Parhar ", dmac=%02x:%02x:%02x:%02x:%02x:%02x " 90354912308SNavdeep Parhar ", l2tidx=%d", 90454912308SNavdeep Parhar t->fs.dmac[0], t->fs.dmac[1], 90554912308SNavdeep Parhar t->fs.dmac[2], t->fs.dmac[3], 90654912308SNavdeep Parhar t->fs.dmac[4], t->fs.dmac[5], 90754912308SNavdeep Parhar t->l2tidx); 90854912308SNavdeep Parhar if (t->fs.newsmac) 90954912308SNavdeep Parhar printf( 91054912308SNavdeep Parhar ", smac=%02x:%02x:%02x:%02x:%02x:%02x " 91154912308SNavdeep Parhar ", smtidx=%d", 91254912308SNavdeep Parhar t->fs.smac[0], t->fs.smac[1], 91354912308SNavdeep Parhar t->fs.smac[2], t->fs.smac[3], 91454912308SNavdeep Parhar t->fs.smac[4], t->fs.smac[5], 91554912308SNavdeep Parhar t->smtidx); 91654912308SNavdeep Parhar if (t->fs.newvlan == VLAN_REMOVE) 91754912308SNavdeep Parhar printf(", vlan=none"); 91854912308SNavdeep Parhar else if (t->fs.newvlan == VLAN_INSERT) 91954912308SNavdeep Parhar printf(", vlan=insert(%x)", t->fs.vlan); 92054912308SNavdeep Parhar else if (t->fs.newvlan == VLAN_REWRITE) 92154912308SNavdeep Parhar printf(", vlan=rewrite(%x)", t->fs.vlan); 92254912308SNavdeep Parhar } else { 92354912308SNavdeep Parhar printf(" Pass: Q="); 92454912308SNavdeep Parhar if (t->fs.dirsteer == 0) { 92554912308SNavdeep Parhar printf("RSS"); 92654912308SNavdeep Parhar if (t->fs.maskhash) 92754912308SNavdeep Parhar printf("(TCB=hash)"); 92854912308SNavdeep Parhar } else { 92954912308SNavdeep Parhar printf("%d", t->fs.iq); 93054912308SNavdeep Parhar if (t->fs.dirsteerhash == 0) 93154912308SNavdeep Parhar printf("(QID)"); 93254912308SNavdeep Parhar else 93354912308SNavdeep Parhar printf("(hash)"); 93454912308SNavdeep Parhar } 93554912308SNavdeep Parhar } 936*6ba81353SNavdeep Parhar if (chip_id <= 5 && t->fs.prio) 93754912308SNavdeep Parhar printf(" Prio"); 93854912308SNavdeep Parhar if (t->fs.rpttid) 93954912308SNavdeep Parhar printf(" RptTID"); 94054912308SNavdeep Parhar printf("\n"); 94154912308SNavdeep Parhar } 94254912308SNavdeep Parhar 94354912308SNavdeep Parhar static int 94436ea2fe3SNavdeep Parhar show_filters(int hash) 94554912308SNavdeep Parhar { 946*6ba81353SNavdeep Parhar uint32_t mode = 0, header, hpfilter = 0; 94754912308SNavdeep Parhar struct t4_filter t; 94854912308SNavdeep Parhar int rc; 94954912308SNavdeep Parhar 95054912308SNavdeep Parhar /* Get the global filter mode first */ 95154912308SNavdeep Parhar rc = doit(CHELSIO_T4_GET_FILTER_MODE, &mode); 95254912308SNavdeep Parhar if (rc != 0) 95354912308SNavdeep Parhar return (rc); 95454912308SNavdeep Parhar 955*6ba81353SNavdeep Parhar if (!hash && chip_id >= 6) { 956*6ba81353SNavdeep Parhar header = 0; 957*6ba81353SNavdeep Parhar bzero(&t, sizeof (t)); 958*6ba81353SNavdeep Parhar t.idx = 0; 959*6ba81353SNavdeep Parhar t.fs.hash = 0; 960*6ba81353SNavdeep Parhar t.fs.prio = 1; 961*6ba81353SNavdeep Parhar for (t.idx = 0; ; t.idx++) { 962*6ba81353SNavdeep Parhar rc = doit(CHELSIO_T4_GET_FILTER, &t); 963*6ba81353SNavdeep Parhar if (rc != 0 || t.idx == 0xffffffff) 964*6ba81353SNavdeep Parhar break; 965*6ba81353SNavdeep Parhar 966*6ba81353SNavdeep Parhar if (!header) { 967*6ba81353SNavdeep Parhar printf("High Priority TCAM Region:\n"); 968*6ba81353SNavdeep Parhar do_show_info_header(mode); 969*6ba81353SNavdeep Parhar header = 1; 970*6ba81353SNavdeep Parhar hpfilter = 1; 971*6ba81353SNavdeep Parhar } 972*6ba81353SNavdeep Parhar do_show_one_filter_info(&t, mode); 973*6ba81353SNavdeep Parhar } 974*6ba81353SNavdeep Parhar } 975*6ba81353SNavdeep Parhar 976*6ba81353SNavdeep Parhar header = 0; 977*6ba81353SNavdeep Parhar bzero(&t, sizeof (t)); 97854912308SNavdeep Parhar t.idx = 0; 97936ea2fe3SNavdeep Parhar t.fs.hash = hash; 98054912308SNavdeep Parhar for (t.idx = 0; ; t.idx++) { 98154912308SNavdeep Parhar rc = doit(CHELSIO_T4_GET_FILTER, &t); 98254912308SNavdeep Parhar if (rc != 0 || t.idx == 0xffffffff) 98354912308SNavdeep Parhar break; 98454912308SNavdeep Parhar 98554912308SNavdeep Parhar if (!header) { 986*6ba81353SNavdeep Parhar if (hpfilter) 987*6ba81353SNavdeep Parhar printf("\nNormal Priority TCAM Region:\n"); 98854912308SNavdeep Parhar do_show_info_header(mode); 98954912308SNavdeep Parhar header = 1; 99054912308SNavdeep Parhar } 99154912308SNavdeep Parhar do_show_one_filter_info(&t, mode); 992*6ba81353SNavdeep Parhar } 99354912308SNavdeep Parhar 99454912308SNavdeep Parhar return (rc); 99554912308SNavdeep Parhar } 99654912308SNavdeep Parhar 99754912308SNavdeep Parhar static int 99836ea2fe3SNavdeep Parhar get_filter_mode(int hashfilter) 99954912308SNavdeep Parhar { 100036ea2fe3SNavdeep Parhar uint32_t mode = hashfilter; 100154912308SNavdeep Parhar int rc; 100254912308SNavdeep Parhar 100354912308SNavdeep Parhar rc = doit(CHELSIO_T4_GET_FILTER_MODE, &mode); 100454912308SNavdeep Parhar if (rc != 0) 100554912308SNavdeep Parhar return (rc); 100654912308SNavdeep Parhar 100754912308SNavdeep Parhar if (mode & T4_FILTER_IPv4) 100854912308SNavdeep Parhar printf("ipv4 "); 100954912308SNavdeep Parhar 101054912308SNavdeep Parhar if (mode & T4_FILTER_IPv6) 101154912308SNavdeep Parhar printf("ipv6 "); 101254912308SNavdeep Parhar 101354912308SNavdeep Parhar if (mode & T4_FILTER_IP_SADDR) 101454912308SNavdeep Parhar printf("sip "); 101554912308SNavdeep Parhar 101654912308SNavdeep Parhar if (mode & T4_FILTER_IP_DADDR) 101754912308SNavdeep Parhar printf("dip "); 101854912308SNavdeep Parhar 101954912308SNavdeep Parhar if (mode & T4_FILTER_IP_SPORT) 102054912308SNavdeep Parhar printf("sport "); 102154912308SNavdeep Parhar 102254912308SNavdeep Parhar if (mode & T4_FILTER_IP_DPORT) 102354912308SNavdeep Parhar printf("dport "); 102454912308SNavdeep Parhar 102554912308SNavdeep Parhar if (mode & T4_FILTER_IP_FRAGMENT) 102654912308SNavdeep Parhar printf("frag "); 102754912308SNavdeep Parhar 102854912308SNavdeep Parhar if (mode & T4_FILTER_MPS_HIT_TYPE) 102954912308SNavdeep Parhar printf("matchtype "); 103054912308SNavdeep Parhar 103154912308SNavdeep Parhar if (mode & T4_FILTER_MAC_IDX) 103254912308SNavdeep Parhar printf("macidx "); 103354912308SNavdeep Parhar 103454912308SNavdeep Parhar if (mode & T4_FILTER_ETH_TYPE) 103554912308SNavdeep Parhar printf("ethtype "); 103654912308SNavdeep Parhar 103754912308SNavdeep Parhar if (mode & T4_FILTER_IP_PROTO) 103854912308SNavdeep Parhar printf("proto "); 103954912308SNavdeep Parhar 104054912308SNavdeep Parhar if (mode & T4_FILTER_IP_TOS) 104154912308SNavdeep Parhar printf("tos "); 104254912308SNavdeep Parhar 104354912308SNavdeep Parhar if (mode & T4_FILTER_VLAN) 104454912308SNavdeep Parhar printf("vlan "); 104554912308SNavdeep Parhar 104654912308SNavdeep Parhar if (mode & T4_FILTER_VNIC) { 104754912308SNavdeep Parhar if (mode & T4_FILTER_IC_VNIC) 104854912308SNavdeep Parhar printf("vnic_id "); 104954912308SNavdeep Parhar else 105054912308SNavdeep Parhar printf("ovlan "); 105154912308SNavdeep Parhar } 105254912308SNavdeep Parhar 105354912308SNavdeep Parhar if (mode & T4_FILTER_PORT) 105454912308SNavdeep Parhar printf("iport "); 105554912308SNavdeep Parhar 105654912308SNavdeep Parhar if (mode & T4_FILTER_FCoE) 105754912308SNavdeep Parhar printf("fcoe "); 105854912308SNavdeep Parhar 105954912308SNavdeep Parhar printf("\n"); 106054912308SNavdeep Parhar 106154912308SNavdeep Parhar return (0); 106254912308SNavdeep Parhar } 106354912308SNavdeep Parhar 106454912308SNavdeep Parhar static int 106554912308SNavdeep Parhar set_filter_mode(int argc, const char *argv[]) 106654912308SNavdeep Parhar { 106754912308SNavdeep Parhar uint32_t mode = 0; 106854912308SNavdeep Parhar int vnic = 0, ovlan = 0; 106954912308SNavdeep Parhar 107054912308SNavdeep Parhar for (; argc; argc--, argv++) { 107154912308SNavdeep Parhar if (!strcmp(argv[0], "frag")) 107254912308SNavdeep Parhar mode |= T4_FILTER_IP_FRAGMENT; 107354912308SNavdeep Parhar 107454912308SNavdeep Parhar if (!strcmp(argv[0], "matchtype")) 107554912308SNavdeep Parhar mode |= T4_FILTER_MPS_HIT_TYPE; 107654912308SNavdeep Parhar 107754912308SNavdeep Parhar if (!strcmp(argv[0], "macidx")) 107854912308SNavdeep Parhar mode |= T4_FILTER_MAC_IDX; 107954912308SNavdeep Parhar 108054912308SNavdeep Parhar if (!strcmp(argv[0], "ethtype")) 108154912308SNavdeep Parhar mode |= T4_FILTER_ETH_TYPE; 108254912308SNavdeep Parhar 108354912308SNavdeep Parhar if (!strcmp(argv[0], "proto")) 108454912308SNavdeep Parhar mode |= T4_FILTER_IP_PROTO; 108554912308SNavdeep Parhar 108654912308SNavdeep Parhar if (!strcmp(argv[0], "tos")) 108754912308SNavdeep Parhar mode |= T4_FILTER_IP_TOS; 108854912308SNavdeep Parhar 108954912308SNavdeep Parhar if (!strcmp(argv[0], "vlan")) 109054912308SNavdeep Parhar mode |= T4_FILTER_VLAN; 109154912308SNavdeep Parhar 109254912308SNavdeep Parhar if (!strcmp(argv[0], "ovlan")) { 109354912308SNavdeep Parhar mode |= T4_FILTER_VNIC; 109454912308SNavdeep Parhar ovlan++; 109554912308SNavdeep Parhar } 109654912308SNavdeep Parhar 109754912308SNavdeep Parhar if (!strcmp(argv[0], "vnic_id")) { 109854912308SNavdeep Parhar mode |= T4_FILTER_VNIC; 109954912308SNavdeep Parhar mode |= T4_FILTER_IC_VNIC; 110054912308SNavdeep Parhar vnic++; 110154912308SNavdeep Parhar } 110254912308SNavdeep Parhar 110354912308SNavdeep Parhar if (!strcmp(argv[0], "iport")) 110454912308SNavdeep Parhar mode |= T4_FILTER_PORT; 110554912308SNavdeep Parhar 110654912308SNavdeep Parhar if (!strcmp(argv[0], "fcoe")) 110754912308SNavdeep Parhar mode |= T4_FILTER_FCoE; 110854912308SNavdeep Parhar } 110954912308SNavdeep Parhar 111054912308SNavdeep Parhar if (vnic > 0 && ovlan > 0) { 111154912308SNavdeep Parhar warnx("\"vnic_id\" and \"ovlan\" are mutually exclusive."); 111254912308SNavdeep Parhar return (EINVAL); 111354912308SNavdeep Parhar } 111454912308SNavdeep Parhar 111554912308SNavdeep Parhar return doit(CHELSIO_T4_SET_FILTER_MODE, &mode); 111654912308SNavdeep Parhar } 111754912308SNavdeep Parhar 111854912308SNavdeep Parhar static int 1119*6ba81353SNavdeep Parhar del_filter(uint32_t idx, int prio, int hashfilter) 112054912308SNavdeep Parhar { 112154912308SNavdeep Parhar struct t4_filter t; 112254912308SNavdeep Parhar 1123*6ba81353SNavdeep Parhar t.fs.prio = prio; 112436ea2fe3SNavdeep Parhar t.fs.hash = hashfilter; 112554912308SNavdeep Parhar t.idx = idx; 112654912308SNavdeep Parhar 112754912308SNavdeep Parhar return doit(CHELSIO_T4_DEL_FILTER, &t); 112854912308SNavdeep Parhar } 112954912308SNavdeep Parhar 11302293e221SNavdeep Parhar #define MAX_VLANID (4095) 11312293e221SNavdeep Parhar 113254912308SNavdeep Parhar static int 113336ea2fe3SNavdeep Parhar set_filter(uint32_t idx, int argc, const char *argv[], int hash) 113454912308SNavdeep Parhar { 113536ea2fe3SNavdeep Parhar int rc, af = AF_UNSPEC, start_arg = 0; 113654912308SNavdeep Parhar struct t4_filter t; 113754912308SNavdeep Parhar 113854912308SNavdeep Parhar if (argc < 2) { 113954912308SNavdeep Parhar warnc(EINVAL, "%s", __func__); 114054912308SNavdeep Parhar return (EINVAL); 114154912308SNavdeep Parhar }; 114254912308SNavdeep Parhar bzero(&t, sizeof (t)); 114354912308SNavdeep Parhar t.idx = idx; 114454912308SNavdeep Parhar t.fs.hitcnts = 1; 114536ea2fe3SNavdeep Parhar t.fs.hash = hash; 114654912308SNavdeep Parhar 114754912308SNavdeep Parhar for (start_arg = 0; start_arg + 2 <= argc; start_arg += 2) { 114854912308SNavdeep Parhar const char **args = &argv[start_arg]; 114954912308SNavdeep Parhar uint32_t val, mask; 115054912308SNavdeep Parhar 115154912308SNavdeep Parhar if (!strcmp(argv[start_arg], "type")) { 115254912308SNavdeep Parhar int newaf; 115354912308SNavdeep Parhar if (!strcasecmp(argv[start_arg + 1], "ipv4")) 115454912308SNavdeep Parhar newaf = AF_INET; 115554912308SNavdeep Parhar else if (!strcasecmp(argv[start_arg + 1], "ipv6")) 115654912308SNavdeep Parhar newaf = AF_INET6; 115754912308SNavdeep Parhar else { 115854912308SNavdeep Parhar warnx("invalid type \"%s\"; " 115954912308SNavdeep Parhar "must be one of \"ipv4\" or \"ipv6\"", 116054912308SNavdeep Parhar argv[start_arg + 1]); 116154912308SNavdeep Parhar return (EINVAL); 116254912308SNavdeep Parhar } 116354912308SNavdeep Parhar 116454912308SNavdeep Parhar if (af != AF_UNSPEC && af != newaf) { 116554912308SNavdeep Parhar warnx("conflicting IPv4/IPv6 specifications."); 116654912308SNavdeep Parhar return (EINVAL); 116754912308SNavdeep Parhar } 116854912308SNavdeep Parhar af = newaf; 116936ea2fe3SNavdeep Parhar } else if (!parse_val_mask("fcoe", args, &val, &mask, hash)) { 117054912308SNavdeep Parhar t.fs.val.fcoe = val; 117154912308SNavdeep Parhar t.fs.mask.fcoe = mask; 117236ea2fe3SNavdeep Parhar } else if (!parse_val_mask("iport", args, &val, &mask, hash)) { 117354912308SNavdeep Parhar t.fs.val.iport = val; 117454912308SNavdeep Parhar t.fs.mask.iport = mask; 117536ea2fe3SNavdeep Parhar } else if (!parse_val_mask("ovlan", args, &val, &mask, hash)) { 117654912308SNavdeep Parhar t.fs.val.vnic = val; 117754912308SNavdeep Parhar t.fs.mask.vnic = mask; 117854912308SNavdeep Parhar t.fs.val.ovlan_vld = 1; 117954912308SNavdeep Parhar t.fs.mask.ovlan_vld = 1; 118036ea2fe3SNavdeep Parhar } else if (!parse_val_mask("ivlan", args, &val, &mask, hash)) { 118154912308SNavdeep Parhar t.fs.val.vlan = val; 118254912308SNavdeep Parhar t.fs.mask.vlan = mask; 118354912308SNavdeep Parhar t.fs.val.vlan_vld = 1; 118454912308SNavdeep Parhar t.fs.mask.vlan_vld = 1; 118536ea2fe3SNavdeep Parhar } else if (!parse_val_mask("pf", args, &val, &mask, hash)) { 118654912308SNavdeep Parhar t.fs.val.vnic &= 0x1fff; 118754912308SNavdeep Parhar t.fs.val.vnic |= (val & 0x7) << 13; 118854912308SNavdeep Parhar t.fs.mask.vnic &= 0x1fff; 118954912308SNavdeep Parhar t.fs.mask.vnic |= (mask & 0x7) << 13; 119054912308SNavdeep Parhar t.fs.val.pfvf_vld = 1; 119154912308SNavdeep Parhar t.fs.mask.pfvf_vld = 1; 119236ea2fe3SNavdeep Parhar } else if (!parse_val_mask("vf", args, &val, &mask, hash)) { 119354912308SNavdeep Parhar t.fs.val.vnic &= 0xe000; 119454912308SNavdeep Parhar t.fs.val.vnic |= val & 0x1fff; 119554912308SNavdeep Parhar t.fs.mask.vnic &= 0xe000; 119654912308SNavdeep Parhar t.fs.mask.vnic |= mask & 0x1fff; 119754912308SNavdeep Parhar t.fs.val.pfvf_vld = 1; 119854912308SNavdeep Parhar t.fs.mask.pfvf_vld = 1; 119936ea2fe3SNavdeep Parhar } else if (!parse_val_mask("tos", args, &val, &mask, hash)) { 120054912308SNavdeep Parhar t.fs.val.tos = val; 120154912308SNavdeep Parhar t.fs.mask.tos = mask; 120236ea2fe3SNavdeep Parhar } else if (!parse_val_mask("proto", args, &val, &mask, hash)) { 120354912308SNavdeep Parhar t.fs.val.proto = val; 120454912308SNavdeep Parhar t.fs.mask.proto = mask; 120536ea2fe3SNavdeep Parhar } else if (!parse_val_mask("ethtype", args, &val, &mask, hash)) { 120654912308SNavdeep Parhar t.fs.val.ethtype = val; 120754912308SNavdeep Parhar t.fs.mask.ethtype = mask; 120836ea2fe3SNavdeep Parhar } else if (!parse_val_mask("macidx", args, &val, &mask, hash)) { 120954912308SNavdeep Parhar t.fs.val.macidx = val; 121054912308SNavdeep Parhar t.fs.mask.macidx = mask; 121136ea2fe3SNavdeep Parhar } else if (!parse_val_mask("matchtype", args, &val, &mask, hash)) { 121254912308SNavdeep Parhar t.fs.val.matchtype = val; 121354912308SNavdeep Parhar t.fs.mask.matchtype = mask; 121436ea2fe3SNavdeep Parhar } else if (!parse_val_mask("frag", args, &val, &mask, hash)) { 121554912308SNavdeep Parhar t.fs.val.frag = val; 121654912308SNavdeep Parhar t.fs.mask.frag = mask; 121736ea2fe3SNavdeep Parhar } else if (!parse_val_mask("dport", args, &val, &mask, hash)) { 121854912308SNavdeep Parhar t.fs.val.dport = val; 121954912308SNavdeep Parhar t.fs.mask.dport = mask; 122036ea2fe3SNavdeep Parhar } else if (!parse_val_mask("sport", args, &val, &mask, hash)) { 122154912308SNavdeep Parhar t.fs.val.sport = val; 122254912308SNavdeep Parhar t.fs.mask.sport = mask; 122354912308SNavdeep Parhar } else if (!parse_ipaddr("dip", args, &af, t.fs.val.dip, 122436ea2fe3SNavdeep Parhar t.fs.mask.dip, hash)) { 122554912308SNavdeep Parhar /* nada */; 122654912308SNavdeep Parhar } else if (!parse_ipaddr("sip", args, &af, t.fs.val.sip, 122736ea2fe3SNavdeep Parhar t.fs.mask.sip, hash)) { 122854912308SNavdeep Parhar /* nada */; 122936ea2fe3SNavdeep Parhar } else if (!parse_ipaddr("nat_dip", args, &af, t.fs.nat_dip, NULL, 1)) { 123036ea2fe3SNavdeep Parhar /*nada*/; 123136ea2fe3SNavdeep Parhar } else if (!parse_ipaddr("nat_sip", args, &af, t.fs.nat_sip, NULL, 1)) { 123236ea2fe3SNavdeep Parhar /*nada*/ 123336ea2fe3SNavdeep Parhar } else if (!parse_val_mask("nat_dport", args, &val, &mask, 1)) { 123436ea2fe3SNavdeep Parhar t.fs.nat_dport = val; 123536ea2fe3SNavdeep Parhar } else if (!parse_val_mask("nat_sport", args, &val, &mask, 1)) { 123636ea2fe3SNavdeep Parhar t.fs.nat_sport = val; 123754912308SNavdeep Parhar } else if (!strcmp(argv[start_arg], "action")) { 123854912308SNavdeep Parhar if (!strcmp(argv[start_arg + 1], "pass")) 123954912308SNavdeep Parhar t.fs.action = FILTER_PASS; 124054912308SNavdeep Parhar else if (!strcmp(argv[start_arg + 1], "drop")) 124154912308SNavdeep Parhar t.fs.action = FILTER_DROP; 124254912308SNavdeep Parhar else if (!strcmp(argv[start_arg + 1], "switch")) 124354912308SNavdeep Parhar t.fs.action = FILTER_SWITCH; 124454912308SNavdeep Parhar else { 124554912308SNavdeep Parhar warnx("invalid action \"%s\"; must be one of" 124654912308SNavdeep Parhar " \"pass\", \"drop\" or \"switch\"", 124754912308SNavdeep Parhar argv[start_arg + 1]); 124854912308SNavdeep Parhar return (EINVAL); 124954912308SNavdeep Parhar } 125054912308SNavdeep Parhar } else if (!parse_val("hitcnts", args, &val)) { 125154912308SNavdeep Parhar t.fs.hitcnts = val; 125254912308SNavdeep Parhar } else if (!parse_val("prio", args, &val)) { 1253*6ba81353SNavdeep Parhar if (hash) { 1254*6ba81353SNavdeep Parhar warnx("Hashfilters doesn't support \"prio\"\n"); 1255*6ba81353SNavdeep Parhar return (EINVAL); 1256*6ba81353SNavdeep Parhar } 1257*6ba81353SNavdeep Parhar if (val != 0 && val != 1) { 1258*6ba81353SNavdeep Parhar warnx("invalid priority \"%s\"; must be" 1259*6ba81353SNavdeep Parhar " \"0\" or \"1\"", argv[start_arg + 1]); 1260*6ba81353SNavdeep Parhar return (EINVAL); 1261*6ba81353SNavdeep Parhar } 126254912308SNavdeep Parhar t.fs.prio = val; 126354912308SNavdeep Parhar } else if (!parse_val("rpttid", args, &val)) { 126454912308SNavdeep Parhar t.fs.rpttid = 1; 126554912308SNavdeep Parhar } else if (!parse_val("queue", args, &val)) { 126654912308SNavdeep Parhar t.fs.dirsteer = 1; 126754912308SNavdeep Parhar t.fs.iq = val; 126854912308SNavdeep Parhar } else if (!parse_val("tcbhash", args, &val)) { 126954912308SNavdeep Parhar t.fs.maskhash = 1; 127054912308SNavdeep Parhar t.fs.dirsteerhash = 1; 127154912308SNavdeep Parhar } else if (!parse_val("eport", args, &val)) { 127254912308SNavdeep Parhar t.fs.eport = val; 127336ea2fe3SNavdeep Parhar } else if (!parse_val("swapmac", args, &val)) { 127436ea2fe3SNavdeep Parhar t.fs.swapmac = 1; 127536ea2fe3SNavdeep Parhar } else if (!strcmp(argv[start_arg], "nat")) { 127636ea2fe3SNavdeep Parhar if (!strcmp(argv[start_arg + 1], "dip")) 127736ea2fe3SNavdeep Parhar t.fs.nat_mode = NAT_MODE_DIP; 127836ea2fe3SNavdeep Parhar else if (!strcmp(argv[start_arg + 1], "dip-dp")) 127936ea2fe3SNavdeep Parhar t.fs.nat_mode = NAT_MODE_DIP_DP; 128036ea2fe3SNavdeep Parhar else if (!strcmp(argv[start_arg + 1], "dip-dp-sip")) 128136ea2fe3SNavdeep Parhar t.fs.nat_mode = NAT_MODE_DIP_DP_SIP; 128236ea2fe3SNavdeep Parhar else if (!strcmp(argv[start_arg + 1], "dip-dp-sp")) 128336ea2fe3SNavdeep Parhar t.fs.nat_mode = NAT_MODE_DIP_DP_SP; 128436ea2fe3SNavdeep Parhar else if (!strcmp(argv[start_arg + 1], "sip-sp")) 128536ea2fe3SNavdeep Parhar t.fs.nat_mode = NAT_MODE_SIP_SP; 128636ea2fe3SNavdeep Parhar else if (!strcmp(argv[start_arg + 1], "dip-sip-sp")) 128736ea2fe3SNavdeep Parhar t.fs.nat_mode = NAT_MODE_DIP_SIP_SP; 128836ea2fe3SNavdeep Parhar else if (!strcmp(argv[start_arg + 1], "all")) 128936ea2fe3SNavdeep Parhar t.fs.nat_mode = NAT_MODE_ALL; 129036ea2fe3SNavdeep Parhar else { 129136ea2fe3SNavdeep Parhar warnx("unknown nat type \"%s\"; known types are dip, " 129236ea2fe3SNavdeep Parhar "dip-dp, dip-dp-sip, dip-dp-sp, sip-sp, " 129336ea2fe3SNavdeep Parhar "dip-sip-sp, and all", argv[start_arg + 1]); 129436ea2fe3SNavdeep Parhar return (EINVAL); 129536ea2fe3SNavdeep Parhar } 129636ea2fe3SNavdeep Parhar } else if (!parse_val("natseq", args, &val)) { 129736ea2fe3SNavdeep Parhar t.fs.nat_seq_chk = val; 129836ea2fe3SNavdeep Parhar } else if (!parse_val("natflag", args, &val)) { 129936ea2fe3SNavdeep Parhar t.fs.nat_flag_chk = 1; 130054912308SNavdeep Parhar } else if (!strcmp(argv[start_arg], "dmac")) { 130154912308SNavdeep Parhar struct ether_addr *daddr; 130254912308SNavdeep Parhar 130354912308SNavdeep Parhar daddr = ether_aton(argv[start_arg + 1]); 130454912308SNavdeep Parhar if (daddr == NULL) { 130554912308SNavdeep Parhar warnx("invalid dmac address \"%s\"", 130654912308SNavdeep Parhar argv[start_arg + 1]); 130754912308SNavdeep Parhar return (EINVAL); 130854912308SNavdeep Parhar } 130954912308SNavdeep Parhar memcpy(t.fs.dmac, daddr, ETHER_ADDR_LEN); 131054912308SNavdeep Parhar t.fs.newdmac = 1; 131154912308SNavdeep Parhar } else if (!strcmp(argv[start_arg], "smac")) { 131254912308SNavdeep Parhar struct ether_addr *saddr; 131354912308SNavdeep Parhar 131454912308SNavdeep Parhar saddr = ether_aton(argv[start_arg + 1]); 131554912308SNavdeep Parhar if (saddr == NULL) { 131654912308SNavdeep Parhar warnx("invalid smac address \"%s\"", 131754912308SNavdeep Parhar argv[start_arg + 1]); 131854912308SNavdeep Parhar return (EINVAL); 131954912308SNavdeep Parhar } 132054912308SNavdeep Parhar memcpy(t.fs.smac, saddr, ETHER_ADDR_LEN); 132154912308SNavdeep Parhar t.fs.newsmac = 1; 132254912308SNavdeep Parhar } else if (!strcmp(argv[start_arg], "vlan")) { 132354912308SNavdeep Parhar char *p; 132454912308SNavdeep Parhar if (!strcmp(argv[start_arg + 1], "none")) { 132554912308SNavdeep Parhar t.fs.newvlan = VLAN_REMOVE; 132654912308SNavdeep Parhar } else if (argv[start_arg + 1][0] == '=') { 132754912308SNavdeep Parhar t.fs.newvlan = VLAN_REWRITE; 132854912308SNavdeep Parhar } else if (argv[start_arg + 1][0] == '+') { 132954912308SNavdeep Parhar t.fs.newvlan = VLAN_INSERT; 133054912308SNavdeep Parhar } else if (isdigit(argv[start_arg + 1][0]) && 133136ea2fe3SNavdeep Parhar !parse_val_mask("vlan", args, &val, &mask, hash)) { 133254912308SNavdeep Parhar t.fs.val.vlan = val; 133354912308SNavdeep Parhar t.fs.mask.vlan = mask; 133454912308SNavdeep Parhar t.fs.val.vlan_vld = 1; 133554912308SNavdeep Parhar t.fs.mask.vlan_vld = 1; 133654912308SNavdeep Parhar } else { 133754912308SNavdeep Parhar warnx("unknown vlan parameter \"%s\"; must" 133854912308SNavdeep Parhar " be one of \"none\", \"=<vlan>\", " 133954912308SNavdeep Parhar " \"+<vlan>\", or \"<vlan>\"", 134054912308SNavdeep Parhar argv[start_arg + 1]); 134154912308SNavdeep Parhar return (EINVAL); 134254912308SNavdeep Parhar } 134354912308SNavdeep Parhar if (t.fs.newvlan == VLAN_REWRITE || 134454912308SNavdeep Parhar t.fs.newvlan == VLAN_INSERT) { 134554912308SNavdeep Parhar t.fs.vlan = strtoul(argv[start_arg + 1] + 1, 134654912308SNavdeep Parhar &p, 0); 13472293e221SNavdeep Parhar if (p == argv[start_arg + 1] + 1 || p[0] != 0 || 13482293e221SNavdeep Parhar t.fs.vlan > MAX_VLANID) { 134954912308SNavdeep Parhar warnx("invalid vlan \"%s\"", 135054912308SNavdeep Parhar argv[start_arg + 1]); 135154912308SNavdeep Parhar return (EINVAL); 135254912308SNavdeep Parhar } 135354912308SNavdeep Parhar } 135454912308SNavdeep Parhar } else { 135554912308SNavdeep Parhar warnx("invalid parameter \"%s\"", argv[start_arg]); 135654912308SNavdeep Parhar return (EINVAL); 135754912308SNavdeep Parhar } 135854912308SNavdeep Parhar } 135954912308SNavdeep Parhar if (start_arg != argc) { 136054912308SNavdeep Parhar warnx("no value for \"%s\"", argv[start_arg]); 136154912308SNavdeep Parhar return (EINVAL); 136254912308SNavdeep Parhar } 136354912308SNavdeep Parhar 136454912308SNavdeep Parhar /* 136554912308SNavdeep Parhar * Check basic sanity of option combinations. 136654912308SNavdeep Parhar */ 136754912308SNavdeep Parhar if (t.fs.action != FILTER_SWITCH && 136836ea2fe3SNavdeep Parhar (t.fs.eport || t.fs.newdmac || t.fs.newsmac || t.fs.newvlan || 136936ea2fe3SNavdeep Parhar t.fs.swapmac || t.fs.nat_mode)) { 137036ea2fe3SNavdeep Parhar warnx("port, dmac, smac, vlan, and nat only make sense with" 137154912308SNavdeep Parhar " \"action switch\""); 137254912308SNavdeep Parhar return (EINVAL); 137354912308SNavdeep Parhar } 137436ea2fe3SNavdeep Parhar if (!t.fs.nat_mode && (t.fs.nat_seq_chk || t.fs.nat_flag_chk || 137536ea2fe3SNavdeep Parhar *t.fs.nat_dip || *t.fs.nat_sip || t.fs.nat_dport || t.fs.nat_sport)) { 137636ea2fe3SNavdeep Parhar warnx("nat params only make sense with valid nat mode"); 137736ea2fe3SNavdeep Parhar return (EINVAL); 137836ea2fe3SNavdeep Parhar } 137954912308SNavdeep Parhar if (t.fs.action != FILTER_PASS && 138054912308SNavdeep Parhar (t.fs.rpttid || t.fs.dirsteer || t.fs.maskhash)) { 138154912308SNavdeep Parhar warnx("rpttid, queue and tcbhash don't make sense with" 138254912308SNavdeep Parhar " action \"drop\" or \"switch\""); 138354912308SNavdeep Parhar return (EINVAL); 138454912308SNavdeep Parhar } 138554912308SNavdeep Parhar if (t.fs.val.ovlan_vld && t.fs.val.pfvf_vld) { 138654912308SNavdeep Parhar warnx("ovlan and vnic_id (pf/vf) are mutually exclusive"); 138754912308SNavdeep Parhar return (EINVAL); 138854912308SNavdeep Parhar } 138954912308SNavdeep Parhar 139054912308SNavdeep Parhar t.fs.type = (af == AF_INET6 ? 1 : 0); /* default IPv4 */ 139136ea2fe3SNavdeep Parhar rc = doit(CHELSIO_T4_SET_FILTER, &t); 139236ea2fe3SNavdeep Parhar if (hash && rc == 0) 139336ea2fe3SNavdeep Parhar printf("%d\n", t.idx); 139436ea2fe3SNavdeep Parhar return (rc); 139554912308SNavdeep Parhar } 139654912308SNavdeep Parhar 139754912308SNavdeep Parhar static int 139836ea2fe3SNavdeep Parhar filter_cmd(int argc, const char *argv[], int hashfilter) 139954912308SNavdeep Parhar { 140054912308SNavdeep Parhar long long val; 140154912308SNavdeep Parhar uint32_t idx; 140254912308SNavdeep Parhar char *s; 140354912308SNavdeep Parhar 140454912308SNavdeep Parhar if (argc == 0) { 140536ea2fe3SNavdeep Parhar warnx("%sfilter: no arguments.", hashfilter ? "hash" : ""); 140654912308SNavdeep Parhar return (EINVAL); 140754912308SNavdeep Parhar }; 140854912308SNavdeep Parhar 140954912308SNavdeep Parhar /* list */ 141054912308SNavdeep Parhar if (strcmp(argv[0], "list") == 0) { 141154912308SNavdeep Parhar if (argc != 1) 141254912308SNavdeep Parhar warnx("trailing arguments after \"list\" ignored."); 141354912308SNavdeep Parhar 141436ea2fe3SNavdeep Parhar return show_filters(hashfilter); 141554912308SNavdeep Parhar } 141654912308SNavdeep Parhar 141754912308SNavdeep Parhar /* mode */ 141854912308SNavdeep Parhar if (argc == 1 && strcmp(argv[0], "mode") == 0) 141936ea2fe3SNavdeep Parhar return get_filter_mode(hashfilter); 142054912308SNavdeep Parhar 142154912308SNavdeep Parhar /* mode <mode> */ 142236ea2fe3SNavdeep Parhar if (!hashfilter && strcmp(argv[0], "mode") == 0) 142354912308SNavdeep Parhar return set_filter_mode(argc - 1, argv + 1); 142454912308SNavdeep Parhar 142554912308SNavdeep Parhar /* <idx> ... */ 142654912308SNavdeep Parhar s = str_to_number(argv[0], NULL, &val); 142736ea2fe3SNavdeep Parhar if (*s || val < 0 || val > 0xffffffffU) { 142836ea2fe3SNavdeep Parhar if (hashfilter) { 142936ea2fe3SNavdeep Parhar /* 143036ea2fe3SNavdeep Parhar * No numeric index means this must be a request to 143136ea2fe3SNavdeep Parhar * create a new hashfilter and we are already at the 143236ea2fe3SNavdeep Parhar * paramter/value list. 143336ea2fe3SNavdeep Parhar */ 143436ea2fe3SNavdeep Parhar idx = (uint32_t) -1; 143536ea2fe3SNavdeep Parhar goto setf; 143636ea2fe3SNavdeep Parhar } 143754912308SNavdeep Parhar warnx("\"%s\" is neither an index nor a filter subcommand.", 143854912308SNavdeep Parhar argv[0]); 143954912308SNavdeep Parhar return (EINVAL); 144054912308SNavdeep Parhar } 144154912308SNavdeep Parhar idx = (uint32_t) val; 144254912308SNavdeep Parhar 1443*6ba81353SNavdeep Parhar /* <idx> delete|clear [prio 0|1] */ 1444*6ba81353SNavdeep Parhar if ((argc == 2 || argc == 4) && 144554912308SNavdeep Parhar (strcmp(argv[1], "delete") == 0 || strcmp(argv[1], "clear") == 0)) { 1446*6ba81353SNavdeep Parhar int prio = 0; 1447*6ba81353SNavdeep Parhar 1448*6ba81353SNavdeep Parhar if (argc == 4) { 1449*6ba81353SNavdeep Parhar if (hashfilter) { 1450*6ba81353SNavdeep Parhar warnx("stray arguments after \"%s\".", argv[1]); 1451*6ba81353SNavdeep Parhar return (EINVAL); 1452*6ba81353SNavdeep Parhar } 1453*6ba81353SNavdeep Parhar 1454*6ba81353SNavdeep Parhar if (strcmp(argv[2], "prio") != 0) { 1455*6ba81353SNavdeep Parhar warnx("\"prio\" is the only valid keyword " 1456*6ba81353SNavdeep Parhar "after \"%s\", found \"%s\" instead.", 1457*6ba81353SNavdeep Parhar argv[1], argv[2]); 1458*6ba81353SNavdeep Parhar return (EINVAL); 1459*6ba81353SNavdeep Parhar } 1460*6ba81353SNavdeep Parhar 1461*6ba81353SNavdeep Parhar s = str_to_number(argv[3], NULL, &val); 1462*6ba81353SNavdeep Parhar if (*s || val < 0 || val > 1) { 1463*6ba81353SNavdeep Parhar warnx("%s \"%s\"; must be \"0\" or \"1\".", 1464*6ba81353SNavdeep Parhar argv[2], argv[3]); 1465*6ba81353SNavdeep Parhar return (EINVAL); 1466*6ba81353SNavdeep Parhar } 1467*6ba81353SNavdeep Parhar prio = (int)val; 1468*6ba81353SNavdeep Parhar } 1469*6ba81353SNavdeep Parhar return del_filter(idx, prio, hashfilter); 147054912308SNavdeep Parhar } 147154912308SNavdeep Parhar 147236ea2fe3SNavdeep Parhar /* skip <idx> */ 147336ea2fe3SNavdeep Parhar argc--; 147436ea2fe3SNavdeep Parhar argv++; 147536ea2fe3SNavdeep Parhar 147636ea2fe3SNavdeep Parhar setf: 147736ea2fe3SNavdeep Parhar /* [<param> <val>] ... */ 147836ea2fe3SNavdeep Parhar return set_filter(idx, argc, argv, hashfilter); 147954912308SNavdeep Parhar } 148054912308SNavdeep Parhar 148154912308SNavdeep Parhar /* 148254912308SNavdeep Parhar * Shows the fields of a multi-word structure. The structure is considered to 148354912308SNavdeep Parhar * consist of @nwords 32-bit words (i.e, it's an (@nwords * 32)-bit structure) 148454912308SNavdeep Parhar * whose fields are described by @fd. The 32-bit words are given in @words 148554912308SNavdeep Parhar * starting with the least significant 32-bit word. 148654912308SNavdeep Parhar */ 148754912308SNavdeep Parhar static void 148854912308SNavdeep Parhar show_struct(const uint32_t *words, int nwords, const struct field_desc *fd) 148954912308SNavdeep Parhar { 149054912308SNavdeep Parhar unsigned int w = 0; 149154912308SNavdeep Parhar const struct field_desc *p; 149254912308SNavdeep Parhar 149354912308SNavdeep Parhar for (p = fd; p->name; p++) 149454912308SNavdeep Parhar w = max(w, strlen(p->name)); 149554912308SNavdeep Parhar 149654912308SNavdeep Parhar while (fd->name) { 149754912308SNavdeep Parhar unsigned long long data; 149854912308SNavdeep Parhar int first_word = fd->start / 32; 149954912308SNavdeep Parhar int shift = fd->start % 32; 150054912308SNavdeep Parhar int width = fd->end - fd->start + 1; 150154912308SNavdeep Parhar unsigned long long mask = (1ULL << width) - 1; 150254912308SNavdeep Parhar 150354912308SNavdeep Parhar data = (words[first_word] >> shift) | 150454912308SNavdeep Parhar ((uint64_t)words[first_word + 1] << (32 - shift)); 150554912308SNavdeep Parhar if (shift) 150654912308SNavdeep Parhar data |= ((uint64_t)words[first_word + 2] << (64 - shift)); 150754912308SNavdeep Parhar data &= mask; 150854912308SNavdeep Parhar if (fd->islog2) 150954912308SNavdeep Parhar data = 1 << data; 151054912308SNavdeep Parhar printf("%-*s ", w, fd->name); 151154912308SNavdeep Parhar printf(fd->hex ? "%#llx\n" : "%llu\n", data << fd->shift); 151254912308SNavdeep Parhar fd++; 151354912308SNavdeep Parhar } 151454912308SNavdeep Parhar } 151554912308SNavdeep Parhar 151654912308SNavdeep Parhar #define FIELD(name, start, end) { name, start, end, 0, 0, 0 } 151754912308SNavdeep Parhar #define FIELD1(name, start) FIELD(name, start, start) 151854912308SNavdeep Parhar 151954912308SNavdeep Parhar static void 152054912308SNavdeep Parhar show_t5t6_ctxt(const struct t4_sge_context *p, int vers) 152154912308SNavdeep Parhar { 152254912308SNavdeep Parhar static struct field_desc egress_t5[] = { 152354912308SNavdeep Parhar FIELD("DCA_ST:", 181, 191), 152454912308SNavdeep Parhar FIELD1("StatusPgNS:", 180), 152554912308SNavdeep Parhar FIELD1("StatusPgRO:", 179), 152654912308SNavdeep Parhar FIELD1("FetchNS:", 178), 152754912308SNavdeep Parhar FIELD1("FetchRO:", 177), 152854912308SNavdeep Parhar FIELD1("Valid:", 176), 152954912308SNavdeep Parhar FIELD("PCIeDataChannel:", 174, 175), 153054912308SNavdeep Parhar FIELD1("StatusPgTPHintEn:", 173), 153154912308SNavdeep Parhar FIELD("StatusPgTPHint:", 171, 172), 153254912308SNavdeep Parhar FIELD1("FetchTPHintEn:", 170), 153354912308SNavdeep Parhar FIELD("FetchTPHint:", 168, 169), 153454912308SNavdeep Parhar FIELD1("FCThreshOverride:", 167), 153554912308SNavdeep Parhar { "WRLength:", 162, 166, 9, 0, 1 }, 153654912308SNavdeep Parhar FIELD1("WRLengthKnown:", 161), 153754912308SNavdeep Parhar FIELD1("ReschedulePending:", 160), 153854912308SNavdeep Parhar FIELD1("OnChipQueue:", 159), 153954912308SNavdeep Parhar FIELD1("FetchSizeMode:", 158), 154054912308SNavdeep Parhar { "FetchBurstMin:", 156, 157, 4, 0, 1 }, 154154912308SNavdeep Parhar FIELD1("FLMPacking:", 155), 154254912308SNavdeep Parhar FIELD("FetchBurstMax:", 153, 154), 154354912308SNavdeep Parhar FIELD("uPToken:", 133, 152), 154454912308SNavdeep Parhar FIELD1("uPTokenEn:", 132), 154554912308SNavdeep Parhar FIELD1("UserModeIO:", 131), 154654912308SNavdeep Parhar FIELD("uPFLCredits:", 123, 130), 154754912308SNavdeep Parhar FIELD1("uPFLCreditEn:", 122), 154854912308SNavdeep Parhar FIELD("FID:", 111, 121), 154954912308SNavdeep Parhar FIELD("HostFCMode:", 109, 110), 155054912308SNavdeep Parhar FIELD1("HostFCOwner:", 108), 155154912308SNavdeep Parhar { "CIDXFlushThresh:", 105, 107, 0, 0, 1 }, 155254912308SNavdeep Parhar FIELD("CIDX:", 89, 104), 155354912308SNavdeep Parhar FIELD("PIDX:", 73, 88), 155454912308SNavdeep Parhar { "BaseAddress:", 18, 72, 9, 1 }, 155554912308SNavdeep Parhar FIELD("QueueSize:", 2, 17), 155654912308SNavdeep Parhar FIELD1("QueueType:", 1), 155754912308SNavdeep Parhar FIELD1("CachePriority:", 0), 155854912308SNavdeep Parhar { NULL } 155954912308SNavdeep Parhar }; 156054912308SNavdeep Parhar static struct field_desc egress_t6[] = { 156154912308SNavdeep Parhar FIELD("DCA_ST:", 181, 191), 156254912308SNavdeep Parhar FIELD1("StatusPgNS:", 180), 156354912308SNavdeep Parhar FIELD1("StatusPgRO:", 179), 156454912308SNavdeep Parhar FIELD1("FetchNS:", 178), 156554912308SNavdeep Parhar FIELD1("FetchRO:", 177), 156654912308SNavdeep Parhar FIELD1("Valid:", 176), 156754912308SNavdeep Parhar FIELD1("ReschedulePending_1:", 175), 156854912308SNavdeep Parhar FIELD1("PCIeDataChannel:", 174), 156954912308SNavdeep Parhar FIELD1("StatusPgTPHintEn:", 173), 157054912308SNavdeep Parhar FIELD("StatusPgTPHint:", 171, 172), 157154912308SNavdeep Parhar FIELD1("FetchTPHintEn:", 170), 157254912308SNavdeep Parhar FIELD("FetchTPHint:", 168, 169), 157354912308SNavdeep Parhar FIELD1("FCThreshOverride:", 167), 157454912308SNavdeep Parhar { "WRLength:", 162, 166, 9, 0, 1 }, 157554912308SNavdeep Parhar FIELD1("WRLengthKnown:", 161), 157654912308SNavdeep Parhar FIELD1("ReschedulePending:", 160), 157754912308SNavdeep Parhar FIELD("TimerIx:", 157, 159), 157854912308SNavdeep Parhar FIELD1("FetchBurstMin:", 156), 157954912308SNavdeep Parhar FIELD1("FLMPacking:", 155), 158054912308SNavdeep Parhar FIELD("FetchBurstMax:", 153, 154), 158154912308SNavdeep Parhar FIELD("uPToken:", 133, 152), 158254912308SNavdeep Parhar FIELD1("uPTokenEn:", 132), 158354912308SNavdeep Parhar FIELD1("UserModeIO:", 131), 158454912308SNavdeep Parhar FIELD("uPFLCredits:", 123, 130), 158554912308SNavdeep Parhar FIELD1("uPFLCreditEn:", 122), 158654912308SNavdeep Parhar FIELD("FID:", 111, 121), 158754912308SNavdeep Parhar FIELD("HostFCMode:", 109, 110), 158854912308SNavdeep Parhar FIELD1("HostFCOwner:", 108), 158954912308SNavdeep Parhar { "CIDXFlushThresh:", 105, 107, 0, 0, 1 }, 159054912308SNavdeep Parhar FIELD("CIDX:", 89, 104), 159154912308SNavdeep Parhar FIELD("PIDX:", 73, 88), 159254912308SNavdeep Parhar { "BaseAddress:", 18, 72, 9, 1 }, 159354912308SNavdeep Parhar FIELD("QueueSize:", 2, 17), 159454912308SNavdeep Parhar FIELD1("QueueType:", 1), 159554912308SNavdeep Parhar FIELD1("FetchSizeMode:", 0), 159654912308SNavdeep Parhar { NULL } 159754912308SNavdeep Parhar }; 159854912308SNavdeep Parhar static struct field_desc fl_t5[] = { 159954912308SNavdeep Parhar FIELD("DCA_ST:", 181, 191), 160054912308SNavdeep Parhar FIELD1("StatusPgNS:", 180), 160154912308SNavdeep Parhar FIELD1("StatusPgRO:", 179), 160254912308SNavdeep Parhar FIELD1("FetchNS:", 178), 160354912308SNavdeep Parhar FIELD1("FetchRO:", 177), 160454912308SNavdeep Parhar FIELD1("Valid:", 176), 160554912308SNavdeep Parhar FIELD("PCIeDataChannel:", 174, 175), 160654912308SNavdeep Parhar FIELD1("StatusPgTPHintEn:", 173), 160754912308SNavdeep Parhar FIELD("StatusPgTPHint:", 171, 172), 160854912308SNavdeep Parhar FIELD1("FetchTPHintEn:", 170), 160954912308SNavdeep Parhar FIELD("FetchTPHint:", 168, 169), 161054912308SNavdeep Parhar FIELD1("FCThreshOverride:", 167), 161154912308SNavdeep Parhar FIELD1("ReschedulePending:", 160), 161254912308SNavdeep Parhar FIELD1("OnChipQueue:", 159), 161354912308SNavdeep Parhar FIELD1("FetchSizeMode:", 158), 161454912308SNavdeep Parhar { "FetchBurstMin:", 156, 157, 4, 0, 1 }, 161554912308SNavdeep Parhar FIELD1("FLMPacking:", 155), 161654912308SNavdeep Parhar FIELD("FetchBurstMax:", 153, 154), 161754912308SNavdeep Parhar FIELD1("FLMcongMode:", 152), 161854912308SNavdeep Parhar FIELD("MaxuPFLCredits:", 144, 151), 161954912308SNavdeep Parhar FIELD("FLMcontextID:", 133, 143), 162054912308SNavdeep Parhar FIELD1("uPTokenEn:", 132), 162154912308SNavdeep Parhar FIELD1("UserModeIO:", 131), 162254912308SNavdeep Parhar FIELD("uPFLCredits:", 123, 130), 162354912308SNavdeep Parhar FIELD1("uPFLCreditEn:", 122), 162454912308SNavdeep Parhar FIELD("FID:", 111, 121), 162554912308SNavdeep Parhar FIELD("HostFCMode:", 109, 110), 162654912308SNavdeep Parhar FIELD1("HostFCOwner:", 108), 162754912308SNavdeep Parhar { "CIDXFlushThresh:", 105, 107, 0, 0, 1 }, 162854912308SNavdeep Parhar FIELD("CIDX:", 89, 104), 162954912308SNavdeep Parhar FIELD("PIDX:", 73, 88), 163054912308SNavdeep Parhar { "BaseAddress:", 18, 72, 9, 1 }, 163154912308SNavdeep Parhar FIELD("QueueSize:", 2, 17), 163254912308SNavdeep Parhar FIELD1("QueueType:", 1), 163354912308SNavdeep Parhar FIELD1("CachePriority:", 0), 163454912308SNavdeep Parhar { NULL } 163554912308SNavdeep Parhar }; 163654912308SNavdeep Parhar static struct field_desc ingress_t5[] = { 163754912308SNavdeep Parhar FIELD("DCA_ST:", 143, 153), 163854912308SNavdeep Parhar FIELD1("ISCSICoalescing:", 142), 163954912308SNavdeep Parhar FIELD1("Queue_Valid:", 141), 164054912308SNavdeep Parhar FIELD1("TimerPending:", 140), 164154912308SNavdeep Parhar FIELD1("DropRSS:", 139), 164254912308SNavdeep Parhar FIELD("PCIeChannel:", 137, 138), 164354912308SNavdeep Parhar FIELD1("SEInterruptArmed:", 136), 164454912308SNavdeep Parhar FIELD1("CongestionMgtEnable:", 135), 164554912308SNavdeep Parhar FIELD1("NoSnoop:", 134), 164654912308SNavdeep Parhar FIELD1("RelaxedOrdering:", 133), 164754912308SNavdeep Parhar FIELD1("GTSmode:", 132), 164854912308SNavdeep Parhar FIELD1("TPHintEn:", 131), 164954912308SNavdeep Parhar FIELD("TPHint:", 129, 130), 165054912308SNavdeep Parhar FIELD1("UpdateScheduling:", 128), 165154912308SNavdeep Parhar FIELD("UpdateDelivery:", 126, 127), 165254912308SNavdeep Parhar FIELD1("InterruptSent:", 125), 165354912308SNavdeep Parhar FIELD("InterruptIDX:", 114, 124), 165454912308SNavdeep Parhar FIELD1("InterruptDestination:", 113), 165554912308SNavdeep Parhar FIELD1("InterruptArmed:", 112), 165654912308SNavdeep Parhar FIELD("RxIntCounter:", 106, 111), 165754912308SNavdeep Parhar FIELD("RxIntCounterThreshold:", 104, 105), 165854912308SNavdeep Parhar FIELD1("Generation:", 103), 165954912308SNavdeep Parhar { "BaseAddress:", 48, 102, 9, 1 }, 166054912308SNavdeep Parhar FIELD("PIDX:", 32, 47), 166154912308SNavdeep Parhar FIELD("CIDX:", 16, 31), 166254912308SNavdeep Parhar { "QueueSize:", 4, 15, 4, 0 }, 166354912308SNavdeep Parhar { "QueueEntrySize:", 2, 3, 4, 0, 1 }, 166454912308SNavdeep Parhar FIELD1("QueueEntryOverride:", 1), 166554912308SNavdeep Parhar FIELD1("CachePriority:", 0), 166654912308SNavdeep Parhar { NULL } 166754912308SNavdeep Parhar }; 166854912308SNavdeep Parhar static struct field_desc ingress_t6[] = { 166954912308SNavdeep Parhar FIELD1("SP_NS:", 158), 167054912308SNavdeep Parhar FIELD1("SP_RO:", 157), 167154912308SNavdeep Parhar FIELD1("SP_TPHintEn:", 156), 167254912308SNavdeep Parhar FIELD("SP_TPHint:", 154, 155), 167354912308SNavdeep Parhar FIELD("DCA_ST:", 143, 153), 167454912308SNavdeep Parhar FIELD1("ISCSICoalescing:", 142), 167554912308SNavdeep Parhar FIELD1("Queue_Valid:", 141), 167654912308SNavdeep Parhar FIELD1("TimerPending:", 140), 167754912308SNavdeep Parhar FIELD1("DropRSS:", 139), 167854912308SNavdeep Parhar FIELD("PCIeChannel:", 137, 138), 167954912308SNavdeep Parhar FIELD1("SEInterruptArmed:", 136), 168054912308SNavdeep Parhar FIELD1("CongestionMgtEnable:", 135), 168154912308SNavdeep Parhar FIELD1("NoSnoop:", 134), 168254912308SNavdeep Parhar FIELD1("RelaxedOrdering:", 133), 168354912308SNavdeep Parhar FIELD1("GTSmode:", 132), 168454912308SNavdeep Parhar FIELD1("TPHintEn:", 131), 168554912308SNavdeep Parhar FIELD("TPHint:", 129, 130), 168654912308SNavdeep Parhar FIELD1("UpdateScheduling:", 128), 168754912308SNavdeep Parhar FIELD("UpdateDelivery:", 126, 127), 168854912308SNavdeep Parhar FIELD1("InterruptSent:", 125), 168954912308SNavdeep Parhar FIELD("InterruptIDX:", 114, 124), 169054912308SNavdeep Parhar FIELD1("InterruptDestination:", 113), 169154912308SNavdeep Parhar FIELD1("InterruptArmed:", 112), 169254912308SNavdeep Parhar FIELD("RxIntCounter:", 106, 111), 169354912308SNavdeep Parhar FIELD("RxIntCounterThreshold:", 104, 105), 169454912308SNavdeep Parhar FIELD1("Generation:", 103), 169554912308SNavdeep Parhar { "BaseAddress:", 48, 102, 9, 1 }, 169654912308SNavdeep Parhar FIELD("PIDX:", 32, 47), 169754912308SNavdeep Parhar FIELD("CIDX:", 16, 31), 169854912308SNavdeep Parhar { "QueueSize:", 4, 15, 4, 0 }, 169954912308SNavdeep Parhar { "QueueEntrySize:", 2, 3, 4, 0, 1 }, 170054912308SNavdeep Parhar FIELD1("QueueEntryOverride:", 1), 170154912308SNavdeep Parhar FIELD1("CachePriority:", 0), 170254912308SNavdeep Parhar { NULL } 170354912308SNavdeep Parhar }; 170454912308SNavdeep Parhar static struct field_desc flm_t5[] = { 170554912308SNavdeep Parhar FIELD1("Valid:", 89), 170654912308SNavdeep Parhar FIELD("SplitLenMode:", 87, 88), 170754912308SNavdeep Parhar FIELD1("TPHintEn:", 86), 170854912308SNavdeep Parhar FIELD("TPHint:", 84, 85), 170954912308SNavdeep Parhar FIELD1("NoSnoop:", 83), 171054912308SNavdeep Parhar FIELD1("RelaxedOrdering:", 82), 171154912308SNavdeep Parhar FIELD("DCA_ST:", 71, 81), 171254912308SNavdeep Parhar FIELD("EQid:", 54, 70), 171354912308SNavdeep Parhar FIELD("SplitEn:", 52, 53), 171454912308SNavdeep Parhar FIELD1("PadEn:", 51), 171554912308SNavdeep Parhar FIELD1("PackEn:", 50), 171654912308SNavdeep Parhar FIELD1("Cache_Lock :", 49), 171754912308SNavdeep Parhar FIELD1("CongDrop:", 48), 171854912308SNavdeep Parhar FIELD("PackOffset:", 16, 47), 171954912308SNavdeep Parhar FIELD("CIDX:", 8, 15), 172054912308SNavdeep Parhar FIELD("PIDX:", 0, 7), 172154912308SNavdeep Parhar { NULL } 172254912308SNavdeep Parhar }; 172354912308SNavdeep Parhar static struct field_desc flm_t6[] = { 172454912308SNavdeep Parhar FIELD1("Valid:", 89), 172554912308SNavdeep Parhar FIELD("SplitLenMode:", 87, 88), 172654912308SNavdeep Parhar FIELD1("TPHintEn:", 86), 172754912308SNavdeep Parhar FIELD("TPHint:", 84, 85), 172854912308SNavdeep Parhar FIELD1("NoSnoop:", 83), 172954912308SNavdeep Parhar FIELD1("RelaxedOrdering:", 82), 173054912308SNavdeep Parhar FIELD("DCA_ST:", 71, 81), 173154912308SNavdeep Parhar FIELD("EQid:", 54, 70), 173254912308SNavdeep Parhar FIELD("SplitEn:", 52, 53), 173354912308SNavdeep Parhar FIELD1("PadEn:", 51), 173454912308SNavdeep Parhar FIELD1("PackEn:", 50), 173554912308SNavdeep Parhar FIELD1("Cache_Lock :", 49), 173654912308SNavdeep Parhar FIELD1("CongDrop:", 48), 173754912308SNavdeep Parhar FIELD1("Inflight:", 47), 173854912308SNavdeep Parhar FIELD1("CongEn:", 46), 173954912308SNavdeep Parhar FIELD1("CongMode:", 45), 174054912308SNavdeep Parhar FIELD("PackOffset:", 20, 39), 174154912308SNavdeep Parhar FIELD("CIDX:", 8, 15), 174254912308SNavdeep Parhar FIELD("PIDX:", 0, 7), 174354912308SNavdeep Parhar { NULL } 174454912308SNavdeep Parhar }; 174554912308SNavdeep Parhar static struct field_desc conm_t5[] = { 174654912308SNavdeep Parhar FIELD1("CngMPSEnable:", 21), 174754912308SNavdeep Parhar FIELD("CngTPMode:", 19, 20), 174854912308SNavdeep Parhar FIELD1("CngDBPHdr:", 18), 174954912308SNavdeep Parhar FIELD1("CngDBPData:", 17), 175054912308SNavdeep Parhar FIELD1("CngIMSG:", 16), 175154912308SNavdeep Parhar { "CngChMap:", 0, 15, 0, 1, 0 }, 175254912308SNavdeep Parhar { NULL } 175354912308SNavdeep Parhar }; 175454912308SNavdeep Parhar 175554912308SNavdeep Parhar if (p->mem_id == SGE_CONTEXT_EGRESS) { 175654912308SNavdeep Parhar if (p->data[0] & 2) 175754912308SNavdeep Parhar show_struct(p->data, 6, fl_t5); 175854912308SNavdeep Parhar else if (vers == 5) 175954912308SNavdeep Parhar show_struct(p->data, 6, egress_t5); 176054912308SNavdeep Parhar else 176154912308SNavdeep Parhar show_struct(p->data, 6, egress_t6); 176254912308SNavdeep Parhar } else if (p->mem_id == SGE_CONTEXT_FLM) 176354912308SNavdeep Parhar show_struct(p->data, 3, vers == 5 ? flm_t5 : flm_t6); 176454912308SNavdeep Parhar else if (p->mem_id == SGE_CONTEXT_INGRESS) 176554912308SNavdeep Parhar show_struct(p->data, 5, vers == 5 ? ingress_t5 : ingress_t6); 176654912308SNavdeep Parhar else if (p->mem_id == SGE_CONTEXT_CNM) 176754912308SNavdeep Parhar show_struct(p->data, 1, conm_t5); 176854912308SNavdeep Parhar } 176954912308SNavdeep Parhar 177054912308SNavdeep Parhar static void 177154912308SNavdeep Parhar show_t4_ctxt(const struct t4_sge_context *p) 177254912308SNavdeep Parhar { 177354912308SNavdeep Parhar static struct field_desc egress_t4[] = { 177454912308SNavdeep Parhar FIELD1("StatusPgNS:", 180), 177554912308SNavdeep Parhar FIELD1("StatusPgRO:", 179), 177654912308SNavdeep Parhar FIELD1("FetchNS:", 178), 177754912308SNavdeep Parhar FIELD1("FetchRO:", 177), 177854912308SNavdeep Parhar FIELD1("Valid:", 176), 177954912308SNavdeep Parhar FIELD("PCIeDataChannel:", 174, 175), 178054912308SNavdeep Parhar FIELD1("DCAEgrQEn:", 173), 178154912308SNavdeep Parhar FIELD("DCACPUID:", 168, 172), 178254912308SNavdeep Parhar FIELD1("FCThreshOverride:", 167), 178354912308SNavdeep Parhar FIELD("WRLength:", 162, 166), 178454912308SNavdeep Parhar FIELD1("WRLengthKnown:", 161), 178554912308SNavdeep Parhar FIELD1("ReschedulePending:", 160), 178654912308SNavdeep Parhar FIELD1("OnChipQueue:", 159), 178754912308SNavdeep Parhar FIELD1("FetchSizeMode", 158), 178854912308SNavdeep Parhar { "FetchBurstMin:", 156, 157, 4, 0, 1 }, 178954912308SNavdeep Parhar { "FetchBurstMax:", 153, 154, 6, 0, 1 }, 179054912308SNavdeep Parhar FIELD("uPToken:", 133, 152), 179154912308SNavdeep Parhar FIELD1("uPTokenEn:", 132), 179254912308SNavdeep Parhar FIELD1("UserModeIO:", 131), 179354912308SNavdeep Parhar FIELD("uPFLCredits:", 123, 130), 179454912308SNavdeep Parhar FIELD1("uPFLCreditEn:", 122), 179554912308SNavdeep Parhar FIELD("FID:", 111, 121), 179654912308SNavdeep Parhar FIELD("HostFCMode:", 109, 110), 179754912308SNavdeep Parhar FIELD1("HostFCOwner:", 108), 179854912308SNavdeep Parhar { "CIDXFlushThresh:", 105, 107, 0, 0, 1 }, 179954912308SNavdeep Parhar FIELD("CIDX:", 89, 104), 180054912308SNavdeep Parhar FIELD("PIDX:", 73, 88), 180154912308SNavdeep Parhar { "BaseAddress:", 18, 72, 9, 1 }, 180254912308SNavdeep Parhar FIELD("QueueSize:", 2, 17), 180354912308SNavdeep Parhar FIELD1("QueueType:", 1), 180454912308SNavdeep Parhar FIELD1("CachePriority:", 0), 180554912308SNavdeep Parhar { NULL } 180654912308SNavdeep Parhar }; 180754912308SNavdeep Parhar static struct field_desc fl_t4[] = { 180854912308SNavdeep Parhar FIELD1("StatusPgNS:", 180), 180954912308SNavdeep Parhar FIELD1("StatusPgRO:", 179), 181054912308SNavdeep Parhar FIELD1("FetchNS:", 178), 181154912308SNavdeep Parhar FIELD1("FetchRO:", 177), 181254912308SNavdeep Parhar FIELD1("Valid:", 176), 181354912308SNavdeep Parhar FIELD("PCIeDataChannel:", 174, 175), 181454912308SNavdeep Parhar FIELD1("DCAEgrQEn:", 173), 181554912308SNavdeep Parhar FIELD("DCACPUID:", 168, 172), 181654912308SNavdeep Parhar FIELD1("FCThreshOverride:", 167), 181754912308SNavdeep Parhar FIELD1("ReschedulePending:", 160), 181854912308SNavdeep Parhar FIELD1("OnChipQueue:", 159), 181954912308SNavdeep Parhar FIELD1("FetchSizeMode", 158), 182054912308SNavdeep Parhar { "FetchBurstMin:", 156, 157, 4, 0, 1 }, 182154912308SNavdeep Parhar { "FetchBurstMax:", 153, 154, 6, 0, 1 }, 182254912308SNavdeep Parhar FIELD1("FLMcongMode:", 152), 182354912308SNavdeep Parhar FIELD("MaxuPFLCredits:", 144, 151), 182454912308SNavdeep Parhar FIELD("FLMcontextID:", 133, 143), 182554912308SNavdeep Parhar FIELD1("uPTokenEn:", 132), 182654912308SNavdeep Parhar FIELD1("UserModeIO:", 131), 182754912308SNavdeep Parhar FIELD("uPFLCredits:", 123, 130), 182854912308SNavdeep Parhar FIELD1("uPFLCreditEn:", 122), 182954912308SNavdeep Parhar FIELD("FID:", 111, 121), 183054912308SNavdeep Parhar FIELD("HostFCMode:", 109, 110), 183154912308SNavdeep Parhar FIELD1("HostFCOwner:", 108), 183254912308SNavdeep Parhar { "CIDXFlushThresh:", 105, 107, 0, 0, 1 }, 183354912308SNavdeep Parhar FIELD("CIDX:", 89, 104), 183454912308SNavdeep Parhar FIELD("PIDX:", 73, 88), 183554912308SNavdeep Parhar { "BaseAddress:", 18, 72, 9, 1 }, 183654912308SNavdeep Parhar FIELD("QueueSize:", 2, 17), 183754912308SNavdeep Parhar FIELD1("QueueType:", 1), 183854912308SNavdeep Parhar FIELD1("CachePriority:", 0), 183954912308SNavdeep Parhar { NULL } 184054912308SNavdeep Parhar }; 184154912308SNavdeep Parhar static struct field_desc ingress_t4[] = { 184254912308SNavdeep Parhar FIELD1("NoSnoop:", 145), 184354912308SNavdeep Parhar FIELD1("RelaxedOrdering:", 144), 184454912308SNavdeep Parhar FIELD1("GTSmode:", 143), 184554912308SNavdeep Parhar FIELD1("ISCSICoalescing:", 142), 184654912308SNavdeep Parhar FIELD1("Valid:", 141), 184754912308SNavdeep Parhar FIELD1("TimerPending:", 140), 184854912308SNavdeep Parhar FIELD1("DropRSS:", 139), 184954912308SNavdeep Parhar FIELD("PCIeChannel:", 137, 138), 185054912308SNavdeep Parhar FIELD1("SEInterruptArmed:", 136), 185154912308SNavdeep Parhar FIELD1("CongestionMgtEnable:", 135), 185254912308SNavdeep Parhar FIELD1("DCAIngQEnable:", 134), 185354912308SNavdeep Parhar FIELD("DCACPUID:", 129, 133), 185454912308SNavdeep Parhar FIELD1("UpdateScheduling:", 128), 185554912308SNavdeep Parhar FIELD("UpdateDelivery:", 126, 127), 185654912308SNavdeep Parhar FIELD1("InterruptSent:", 125), 185754912308SNavdeep Parhar FIELD("InterruptIDX:", 114, 124), 185854912308SNavdeep Parhar FIELD1("InterruptDestination:", 113), 185954912308SNavdeep Parhar FIELD1("InterruptArmed:", 112), 186054912308SNavdeep Parhar FIELD("RxIntCounter:", 106, 111), 186154912308SNavdeep Parhar FIELD("RxIntCounterThreshold:", 104, 105), 186254912308SNavdeep Parhar FIELD1("Generation:", 103), 186354912308SNavdeep Parhar { "BaseAddress:", 48, 102, 9, 1 }, 186454912308SNavdeep Parhar FIELD("PIDX:", 32, 47), 186554912308SNavdeep Parhar FIELD("CIDX:", 16, 31), 186654912308SNavdeep Parhar { "QueueSize:", 4, 15, 4, 0 }, 186754912308SNavdeep Parhar { "QueueEntrySize:", 2, 3, 4, 0, 1 }, 186854912308SNavdeep Parhar FIELD1("QueueEntryOverride:", 1), 186954912308SNavdeep Parhar FIELD1("CachePriority:", 0), 187054912308SNavdeep Parhar { NULL } 187154912308SNavdeep Parhar }; 187254912308SNavdeep Parhar static struct field_desc flm_t4[] = { 187354912308SNavdeep Parhar FIELD1("NoSnoop:", 79), 187454912308SNavdeep Parhar FIELD1("RelaxedOrdering:", 78), 187554912308SNavdeep Parhar FIELD1("Valid:", 77), 187654912308SNavdeep Parhar FIELD("DCACPUID:", 72, 76), 187754912308SNavdeep Parhar FIELD1("DCAFLEn:", 71), 187854912308SNavdeep Parhar FIELD("EQid:", 54, 70), 187954912308SNavdeep Parhar FIELD("SplitEn:", 52, 53), 188054912308SNavdeep Parhar FIELD1("PadEn:", 51), 188154912308SNavdeep Parhar FIELD1("PackEn:", 50), 188254912308SNavdeep Parhar FIELD1("DBpriority:", 48), 188354912308SNavdeep Parhar FIELD("PackOffset:", 16, 47), 188454912308SNavdeep Parhar FIELD("CIDX:", 8, 15), 188554912308SNavdeep Parhar FIELD("PIDX:", 0, 7), 188654912308SNavdeep Parhar { NULL } 188754912308SNavdeep Parhar }; 188854912308SNavdeep Parhar static struct field_desc conm_t4[] = { 188954912308SNavdeep Parhar FIELD1("CngDBPHdr:", 6), 189054912308SNavdeep Parhar FIELD1("CngDBPData:", 5), 189154912308SNavdeep Parhar FIELD1("CngIMSG:", 4), 189254912308SNavdeep Parhar { "CngChMap:", 0, 3, 0, 1, 0}, 189354912308SNavdeep Parhar { NULL } 189454912308SNavdeep Parhar }; 189554912308SNavdeep Parhar 189654912308SNavdeep Parhar if (p->mem_id == SGE_CONTEXT_EGRESS) 189754912308SNavdeep Parhar show_struct(p->data, 6, (p->data[0] & 2) ? fl_t4 : egress_t4); 189854912308SNavdeep Parhar else if (p->mem_id == SGE_CONTEXT_FLM) 189954912308SNavdeep Parhar show_struct(p->data, 3, flm_t4); 190054912308SNavdeep Parhar else if (p->mem_id == SGE_CONTEXT_INGRESS) 190154912308SNavdeep Parhar show_struct(p->data, 5, ingress_t4); 190254912308SNavdeep Parhar else if (p->mem_id == SGE_CONTEXT_CNM) 190354912308SNavdeep Parhar show_struct(p->data, 1, conm_t4); 190454912308SNavdeep Parhar } 190554912308SNavdeep Parhar 190654912308SNavdeep Parhar #undef FIELD 190754912308SNavdeep Parhar #undef FIELD1 190854912308SNavdeep Parhar 190954912308SNavdeep Parhar static int 191054912308SNavdeep Parhar get_sge_context(int argc, const char *argv[]) 191154912308SNavdeep Parhar { 191254912308SNavdeep Parhar int rc; 191354912308SNavdeep Parhar char *p; 191454912308SNavdeep Parhar long cid; 191554912308SNavdeep Parhar struct t4_sge_context cntxt = {0}; 191654912308SNavdeep Parhar 191754912308SNavdeep Parhar if (argc != 2) { 191854912308SNavdeep Parhar warnx("sge_context: incorrect number of arguments."); 191954912308SNavdeep Parhar return (EINVAL); 192054912308SNavdeep Parhar } 192154912308SNavdeep Parhar 192254912308SNavdeep Parhar if (!strcmp(argv[0], "egress")) 192354912308SNavdeep Parhar cntxt.mem_id = SGE_CONTEXT_EGRESS; 192454912308SNavdeep Parhar else if (!strcmp(argv[0], "ingress")) 192554912308SNavdeep Parhar cntxt.mem_id = SGE_CONTEXT_INGRESS; 192654912308SNavdeep Parhar else if (!strcmp(argv[0], "fl")) 192754912308SNavdeep Parhar cntxt.mem_id = SGE_CONTEXT_FLM; 192854912308SNavdeep Parhar else if (!strcmp(argv[0], "cong")) 192954912308SNavdeep Parhar cntxt.mem_id = SGE_CONTEXT_CNM; 193054912308SNavdeep Parhar else { 193154912308SNavdeep Parhar warnx("unknown context type \"%s\"; known types are egress, " 193254912308SNavdeep Parhar "ingress, fl, and cong.", argv[0]); 193354912308SNavdeep Parhar return (EINVAL); 193454912308SNavdeep Parhar } 193554912308SNavdeep Parhar 193654912308SNavdeep Parhar p = str_to_number(argv[1], &cid, NULL); 193754912308SNavdeep Parhar if (*p) { 193854912308SNavdeep Parhar warnx("invalid context id \"%s\"", argv[1]); 193954912308SNavdeep Parhar return (EINVAL); 194054912308SNavdeep Parhar } 194154912308SNavdeep Parhar cntxt.cid = cid; 194254912308SNavdeep Parhar 194354912308SNavdeep Parhar rc = doit(CHELSIO_T4_GET_SGE_CONTEXT, &cntxt); 194454912308SNavdeep Parhar if (rc != 0) 194554912308SNavdeep Parhar return (rc); 194654912308SNavdeep Parhar 194754912308SNavdeep Parhar if (chip_id == 4) 194854912308SNavdeep Parhar show_t4_ctxt(&cntxt); 194954912308SNavdeep Parhar else 195054912308SNavdeep Parhar show_t5t6_ctxt(&cntxt, chip_id); 195154912308SNavdeep Parhar 195254912308SNavdeep Parhar return (0); 195354912308SNavdeep Parhar } 195454912308SNavdeep Parhar 195554912308SNavdeep Parhar static int 195654912308SNavdeep Parhar loadfw(int argc, const char *argv[]) 195754912308SNavdeep Parhar { 195854912308SNavdeep Parhar int rc, fd; 195954912308SNavdeep Parhar struct t4_data data = {0}; 196054912308SNavdeep Parhar const char *fname = argv[0]; 196154912308SNavdeep Parhar struct stat st = {0}; 196254912308SNavdeep Parhar 196354912308SNavdeep Parhar if (argc != 1) { 196454912308SNavdeep Parhar warnx("loadfw: incorrect number of arguments."); 196554912308SNavdeep Parhar return (EINVAL); 196654912308SNavdeep Parhar } 196754912308SNavdeep Parhar 196854912308SNavdeep Parhar fd = open(fname, O_RDONLY); 196954912308SNavdeep Parhar if (fd < 0) { 197054912308SNavdeep Parhar warn("open(%s)", fname); 197154912308SNavdeep Parhar return (errno); 197254912308SNavdeep Parhar } 197354912308SNavdeep Parhar 197454912308SNavdeep Parhar if (fstat(fd, &st) < 0) { 197554912308SNavdeep Parhar warn("fstat"); 197654912308SNavdeep Parhar close(fd); 197754912308SNavdeep Parhar return (errno); 197854912308SNavdeep Parhar } 197954912308SNavdeep Parhar 198054912308SNavdeep Parhar data.len = st.st_size; 198154912308SNavdeep Parhar data.data = mmap(0, data.len, PROT_READ, MAP_PRIVATE, fd, 0); 198254912308SNavdeep Parhar if (data.data == MAP_FAILED) { 198354912308SNavdeep Parhar warn("mmap"); 198454912308SNavdeep Parhar close(fd); 198554912308SNavdeep Parhar return (errno); 198654912308SNavdeep Parhar } 198754912308SNavdeep Parhar 198854912308SNavdeep Parhar rc = doit(CHELSIO_T4_LOAD_FW, &data); 198954912308SNavdeep Parhar munmap(data.data, data.len); 199054912308SNavdeep Parhar close(fd); 199154912308SNavdeep Parhar return (rc); 199254912308SNavdeep Parhar } 199354912308SNavdeep Parhar 199454912308SNavdeep Parhar static int 199554912308SNavdeep Parhar loadcfg(int argc, const char *argv[]) 199654912308SNavdeep Parhar { 199754912308SNavdeep Parhar int rc, fd; 199854912308SNavdeep Parhar struct t4_data data = {0}; 199954912308SNavdeep Parhar const char *fname = argv[0]; 200054912308SNavdeep Parhar struct stat st = {0}; 200154912308SNavdeep Parhar 200254912308SNavdeep Parhar if (argc != 1) { 200354912308SNavdeep Parhar warnx("loadcfg: incorrect number of arguments."); 200454912308SNavdeep Parhar return (EINVAL); 200554912308SNavdeep Parhar } 200654912308SNavdeep Parhar 200754912308SNavdeep Parhar if (strcmp(fname, "clear") == 0) 200854912308SNavdeep Parhar return (doit(CHELSIO_T4_LOAD_CFG, &data)); 200954912308SNavdeep Parhar 201054912308SNavdeep Parhar fd = open(fname, O_RDONLY); 201154912308SNavdeep Parhar if (fd < 0) { 201254912308SNavdeep Parhar warn("open(%s)", fname); 201354912308SNavdeep Parhar return (errno); 201454912308SNavdeep Parhar } 201554912308SNavdeep Parhar 201654912308SNavdeep Parhar if (fstat(fd, &st) < 0) { 201754912308SNavdeep Parhar warn("fstat"); 201854912308SNavdeep Parhar close(fd); 201954912308SNavdeep Parhar return (errno); 202054912308SNavdeep Parhar } 202154912308SNavdeep Parhar 202254912308SNavdeep Parhar data.len = st.st_size; 202354912308SNavdeep Parhar data.len &= ~3; /* Clip off to make it a multiple of 4 */ 202454912308SNavdeep Parhar data.data = mmap(0, data.len, PROT_READ, MAP_PRIVATE, fd, 0); 202554912308SNavdeep Parhar if (data.data == MAP_FAILED) { 202654912308SNavdeep Parhar warn("mmap"); 202754912308SNavdeep Parhar close(fd); 202854912308SNavdeep Parhar return (errno); 202954912308SNavdeep Parhar } 203054912308SNavdeep Parhar 203154912308SNavdeep Parhar rc = doit(CHELSIO_T4_LOAD_CFG, &data); 203254912308SNavdeep Parhar munmap(data.data, data.len); 203354912308SNavdeep Parhar close(fd); 203454912308SNavdeep Parhar return (rc); 203554912308SNavdeep Parhar } 203654912308SNavdeep Parhar 203754912308SNavdeep Parhar static int 2038f856f099SNavdeep Parhar dumpstate(int argc, const char *argv[]) 2039f856f099SNavdeep Parhar { 2040f856f099SNavdeep Parhar int rc, fd; 2041f856f099SNavdeep Parhar struct t4_cudbg_dump dump = {0}; 2042f856f099SNavdeep Parhar const char *fname = argv[0]; 2043f856f099SNavdeep Parhar 2044f856f099SNavdeep Parhar if (argc != 1) { 2045f856f099SNavdeep Parhar warnx("dumpstate: incorrect number of arguments."); 2046f856f099SNavdeep Parhar return (EINVAL); 2047f856f099SNavdeep Parhar } 2048f856f099SNavdeep Parhar 2049f856f099SNavdeep Parhar dump.wr_flash = 0; 2050f856f099SNavdeep Parhar memset(&dump.bitmap, 0xff, sizeof(dump.bitmap)); 2051f856f099SNavdeep Parhar dump.len = 8 * 1024 * 1024; 2052f856f099SNavdeep Parhar dump.data = malloc(dump.len); 2053f856f099SNavdeep Parhar if (dump.data == NULL) { 2054f856f099SNavdeep Parhar return (ENOMEM); 2055f856f099SNavdeep Parhar } 2056f856f099SNavdeep Parhar 2057f856f099SNavdeep Parhar rc = doit(CHELSIO_T4_CUDBG_DUMP, &dump); 2058313a6435SNavdeep Parhar if (rc != 0) 2059313a6435SNavdeep Parhar goto done; 2060313a6435SNavdeep Parhar 2061313a6435SNavdeep Parhar fd = open(fname, O_CREAT | O_TRUNC | O_EXCL | O_WRONLY, 2062313a6435SNavdeep Parhar S_IRUSR | S_IRGRP | S_IROTH); 2063313a6435SNavdeep Parhar if (fd < 0) { 2064313a6435SNavdeep Parhar warn("open(%s)", fname); 2065313a6435SNavdeep Parhar rc = errno; 2066313a6435SNavdeep Parhar goto done; 2067313a6435SNavdeep Parhar } 2068f856f099SNavdeep Parhar write(fd, dump.data, dump.len); 2069f856f099SNavdeep Parhar close(fd); 2070313a6435SNavdeep Parhar done: 2071313a6435SNavdeep Parhar free(dump.data); 2072f856f099SNavdeep Parhar return (rc); 2073f856f099SNavdeep Parhar } 2074f856f099SNavdeep Parhar 2075f856f099SNavdeep Parhar static int 207654912308SNavdeep Parhar read_mem(uint32_t addr, uint32_t len, void (*output)(uint32_t *, uint32_t)) 207754912308SNavdeep Parhar { 207854912308SNavdeep Parhar int rc; 207954912308SNavdeep Parhar struct t4_mem_range mr; 208054912308SNavdeep Parhar 208154912308SNavdeep Parhar mr.addr = addr; 208254912308SNavdeep Parhar mr.len = len; 208354912308SNavdeep Parhar mr.data = malloc(mr.len); 208454912308SNavdeep Parhar 208554912308SNavdeep Parhar if (mr.data == 0) { 208654912308SNavdeep Parhar warn("read_mem: malloc"); 208754912308SNavdeep Parhar return (errno); 208854912308SNavdeep Parhar } 208954912308SNavdeep Parhar 209054912308SNavdeep Parhar rc = doit(CHELSIO_T4_GET_MEM, &mr); 209154912308SNavdeep Parhar if (rc != 0) 209254912308SNavdeep Parhar goto done; 209354912308SNavdeep Parhar 209454912308SNavdeep Parhar if (output) 209554912308SNavdeep Parhar (*output)(mr.data, mr.len); 209654912308SNavdeep Parhar done: 209754912308SNavdeep Parhar free(mr.data); 209854912308SNavdeep Parhar return (rc); 209954912308SNavdeep Parhar } 210054912308SNavdeep Parhar 21018f82718fSNavdeep Parhar static int 21028f82718fSNavdeep Parhar loadboot(int argc, const char *argv[]) 21038f82718fSNavdeep Parhar { 21048f82718fSNavdeep Parhar int rc, fd; 21058f82718fSNavdeep Parhar long l; 21068f82718fSNavdeep Parhar char *p; 21078f82718fSNavdeep Parhar struct t4_bootrom br = {0}; 21088f82718fSNavdeep Parhar const char *fname = argv[0]; 21098f82718fSNavdeep Parhar struct stat st = {0}; 21108f82718fSNavdeep Parhar 21118f82718fSNavdeep Parhar if (argc == 1) { 21128f82718fSNavdeep Parhar br.pf_offset = 0; 21138f82718fSNavdeep Parhar br.pfidx_addr = 0; 21148f82718fSNavdeep Parhar } else if (argc == 3) { 21158f82718fSNavdeep Parhar if (!strcmp(argv[1], "pf")) 21168f82718fSNavdeep Parhar br.pf_offset = 0; 21178f82718fSNavdeep Parhar else if (!strcmp(argv[1], "offset")) 21188f82718fSNavdeep Parhar br.pf_offset = 1; 21198f82718fSNavdeep Parhar else 21208f82718fSNavdeep Parhar return (EINVAL); 21218f82718fSNavdeep Parhar 21228f82718fSNavdeep Parhar p = str_to_number(argv[2], &l, NULL); 21238f82718fSNavdeep Parhar if (*p) 21248f82718fSNavdeep Parhar return (EINVAL); 21258f82718fSNavdeep Parhar br.pfidx_addr = l; 21268f82718fSNavdeep Parhar } else { 21278f82718fSNavdeep Parhar warnx("loadboot: incorrect number of arguments."); 21288f82718fSNavdeep Parhar return (EINVAL); 21298f82718fSNavdeep Parhar } 21308f82718fSNavdeep Parhar 21318f82718fSNavdeep Parhar if (strcmp(fname, "clear") == 0) 21328f82718fSNavdeep Parhar return (doit(CHELSIO_T4_LOAD_BOOT, &br)); 21338f82718fSNavdeep Parhar 21348f82718fSNavdeep Parhar fd = open(fname, O_RDONLY); 21358f82718fSNavdeep Parhar if (fd < 0) { 21368f82718fSNavdeep Parhar warn("open(%s)", fname); 21378f82718fSNavdeep Parhar return (errno); 21388f82718fSNavdeep Parhar } 21398f82718fSNavdeep Parhar 21408f82718fSNavdeep Parhar if (fstat(fd, &st) < 0) { 21418f82718fSNavdeep Parhar warn("fstat"); 21428f82718fSNavdeep Parhar close(fd); 21438f82718fSNavdeep Parhar return (errno); 21448f82718fSNavdeep Parhar } 21458f82718fSNavdeep Parhar 21468f82718fSNavdeep Parhar br.len = st.st_size; 21478f82718fSNavdeep Parhar br.data = mmap(0, br.len, PROT_READ, MAP_PRIVATE, fd, 0); 21488f82718fSNavdeep Parhar if (br.data == MAP_FAILED) { 21498f82718fSNavdeep Parhar warn("mmap"); 21508f82718fSNavdeep Parhar close(fd); 21518f82718fSNavdeep Parhar return (errno); 21528f82718fSNavdeep Parhar } 21538f82718fSNavdeep Parhar 21548f82718fSNavdeep Parhar rc = doit(CHELSIO_T4_LOAD_BOOT, &br); 21558f82718fSNavdeep Parhar munmap(br.data, br.len); 21568f82718fSNavdeep Parhar close(fd); 21578f82718fSNavdeep Parhar return (rc); 21588f82718fSNavdeep Parhar } 21598f82718fSNavdeep Parhar 21608f82718fSNavdeep Parhar static int 21618f82718fSNavdeep Parhar loadbootcfg(int argc, const char *argv[]) 21628f82718fSNavdeep Parhar { 21638f82718fSNavdeep Parhar int rc, fd; 21648f82718fSNavdeep Parhar struct t4_data bc = {0}; 21658f82718fSNavdeep Parhar const char *fname = argv[0]; 21668f82718fSNavdeep Parhar struct stat st = {0}; 21678f82718fSNavdeep Parhar 21688f82718fSNavdeep Parhar if (argc != 1) { 21698f82718fSNavdeep Parhar warnx("loadbootcfg: incorrect number of arguments."); 21708f82718fSNavdeep Parhar return (EINVAL); 21718f82718fSNavdeep Parhar } 21728f82718fSNavdeep Parhar 21738f82718fSNavdeep Parhar if (strcmp(fname, "clear") == 0) 21748f82718fSNavdeep Parhar return (doit(CHELSIO_T4_LOAD_BOOTCFG, &bc)); 21758f82718fSNavdeep Parhar 21768f82718fSNavdeep Parhar fd = open(fname, O_RDONLY); 21778f82718fSNavdeep Parhar if (fd < 0) { 21788f82718fSNavdeep Parhar warn("open(%s)", fname); 21798f82718fSNavdeep Parhar return (errno); 21808f82718fSNavdeep Parhar } 21818f82718fSNavdeep Parhar 21828f82718fSNavdeep Parhar if (fstat(fd, &st) < 0) { 21838f82718fSNavdeep Parhar warn("fstat"); 21848f82718fSNavdeep Parhar close(fd); 21858f82718fSNavdeep Parhar return (errno); 21868f82718fSNavdeep Parhar } 21878f82718fSNavdeep Parhar 21888f82718fSNavdeep Parhar bc.len = st.st_size; 21898f82718fSNavdeep Parhar bc.data = mmap(0, bc.len, PROT_READ, MAP_PRIVATE, fd, 0); 21908f82718fSNavdeep Parhar if (bc.data == MAP_FAILED) { 21918f82718fSNavdeep Parhar warn("mmap"); 21928f82718fSNavdeep Parhar close(fd); 21938f82718fSNavdeep Parhar return (errno); 21948f82718fSNavdeep Parhar } 21958f82718fSNavdeep Parhar 21968f82718fSNavdeep Parhar rc = doit(CHELSIO_T4_LOAD_BOOTCFG, &bc); 21978f82718fSNavdeep Parhar munmap(bc.data, bc.len); 21988f82718fSNavdeep Parhar close(fd); 21998f82718fSNavdeep Parhar return (rc); 22008f82718fSNavdeep Parhar } 22018f82718fSNavdeep Parhar 220254912308SNavdeep Parhar /* 220354912308SNavdeep Parhar * Display memory as list of 'n' 4-byte values per line. 220454912308SNavdeep Parhar */ 220554912308SNavdeep Parhar static void 220654912308SNavdeep Parhar show_mem(uint32_t *buf, uint32_t len) 220754912308SNavdeep Parhar { 220854912308SNavdeep Parhar const char *s; 220954912308SNavdeep Parhar int i, n = 8; 221054912308SNavdeep Parhar 221154912308SNavdeep Parhar while (len) { 221254912308SNavdeep Parhar for (i = 0; len && i < n; i++, buf++, len -= 4) { 221354912308SNavdeep Parhar s = i ? " " : ""; 221454912308SNavdeep Parhar printf("%s%08x", s, htonl(*buf)); 221554912308SNavdeep Parhar } 221654912308SNavdeep Parhar printf("\n"); 221754912308SNavdeep Parhar } 221854912308SNavdeep Parhar } 221954912308SNavdeep Parhar 222054912308SNavdeep Parhar static int 222154912308SNavdeep Parhar memdump(int argc, const char *argv[]) 222254912308SNavdeep Parhar { 222354912308SNavdeep Parhar char *p; 222454912308SNavdeep Parhar long l; 222554912308SNavdeep Parhar uint32_t addr, len; 222654912308SNavdeep Parhar 222754912308SNavdeep Parhar if (argc != 2) { 222854912308SNavdeep Parhar warnx("incorrect number of arguments."); 222954912308SNavdeep Parhar return (EINVAL); 223054912308SNavdeep Parhar } 223154912308SNavdeep Parhar 223254912308SNavdeep Parhar p = str_to_number(argv[0], &l, NULL); 223354912308SNavdeep Parhar if (*p) { 223454912308SNavdeep Parhar warnx("invalid address \"%s\"", argv[0]); 223554912308SNavdeep Parhar return (EINVAL); 223654912308SNavdeep Parhar } 223754912308SNavdeep Parhar addr = l; 223854912308SNavdeep Parhar 223954912308SNavdeep Parhar p = str_to_number(argv[1], &l, NULL); 224054912308SNavdeep Parhar if (*p) { 224154912308SNavdeep Parhar warnx("memdump: invalid length \"%s\"", argv[1]); 224254912308SNavdeep Parhar return (EINVAL); 224354912308SNavdeep Parhar } 224454912308SNavdeep Parhar len = l; 224554912308SNavdeep Parhar 224654912308SNavdeep Parhar return (read_mem(addr, len, show_mem)); 224754912308SNavdeep Parhar } 224854912308SNavdeep Parhar 224954912308SNavdeep Parhar /* 225054912308SNavdeep Parhar * Display TCB as list of 'n' 4-byte values per line. 225154912308SNavdeep Parhar */ 225254912308SNavdeep Parhar static void 225354912308SNavdeep Parhar show_tcb(uint32_t *buf, uint32_t len) 225454912308SNavdeep Parhar { 2255ae9b4017SNavdeep Parhar unsigned char *tcb = (unsigned char *)buf; 225654912308SNavdeep Parhar const char *s; 225754912308SNavdeep Parhar int i, n = 8; 225854912308SNavdeep Parhar 225954912308SNavdeep Parhar while (len) { 226054912308SNavdeep Parhar for (i = 0; len && i < n; i++, buf++, len -= 4) { 226154912308SNavdeep Parhar s = i ? " " : ""; 226254912308SNavdeep Parhar printf("%s%08x", s, htonl(*buf)); 226354912308SNavdeep Parhar } 226454912308SNavdeep Parhar printf("\n"); 226554912308SNavdeep Parhar } 2266ae9b4017SNavdeep Parhar set_tcb_info(TIDTYPE_TCB, chip_id); 2267ae9b4017SNavdeep Parhar set_print_style(PRNTSTYL_COMP); 2268ae9b4017SNavdeep Parhar swizzle_tcb(tcb); 2269ae9b4017SNavdeep Parhar parse_n_display_xcb(tcb); 227054912308SNavdeep Parhar } 227154912308SNavdeep Parhar 227254912308SNavdeep Parhar #define A_TP_CMM_TCB_BASE 0x7d10 227354912308SNavdeep Parhar #define TCB_SIZE 128 227454912308SNavdeep Parhar static int 227554912308SNavdeep Parhar read_tcb(int argc, const char *argv[]) 227654912308SNavdeep Parhar { 227754912308SNavdeep Parhar char *p; 227854912308SNavdeep Parhar long l; 227954912308SNavdeep Parhar long long val; 228054912308SNavdeep Parhar unsigned int tid; 228154912308SNavdeep Parhar uint32_t addr; 228254912308SNavdeep Parhar int rc; 228354912308SNavdeep Parhar 228454912308SNavdeep Parhar if (argc != 1) { 228554912308SNavdeep Parhar warnx("incorrect number of arguments."); 228654912308SNavdeep Parhar return (EINVAL); 228754912308SNavdeep Parhar } 228854912308SNavdeep Parhar 228954912308SNavdeep Parhar p = str_to_number(argv[0], &l, NULL); 229054912308SNavdeep Parhar if (*p) { 229154912308SNavdeep Parhar warnx("invalid tid \"%s\"", argv[0]); 229254912308SNavdeep Parhar return (EINVAL); 229354912308SNavdeep Parhar } 229454912308SNavdeep Parhar tid = l; 229554912308SNavdeep Parhar 229654912308SNavdeep Parhar rc = read_reg(A_TP_CMM_TCB_BASE, 4, &val); 229754912308SNavdeep Parhar if (rc != 0) 229854912308SNavdeep Parhar return (rc); 229954912308SNavdeep Parhar 230054912308SNavdeep Parhar addr = val + tid * TCB_SIZE; 230154912308SNavdeep Parhar 230254912308SNavdeep Parhar return (read_mem(addr, TCB_SIZE, show_tcb)); 230354912308SNavdeep Parhar } 230454912308SNavdeep Parhar 230554912308SNavdeep Parhar static int 230654912308SNavdeep Parhar read_i2c(int argc, const char *argv[]) 230754912308SNavdeep Parhar { 230854912308SNavdeep Parhar char *p; 230954912308SNavdeep Parhar long l; 231054912308SNavdeep Parhar struct t4_i2c_data i2cd; 231154912308SNavdeep Parhar int rc, i; 231254912308SNavdeep Parhar 231354912308SNavdeep Parhar if (argc < 3 || argc > 4) { 231454912308SNavdeep Parhar warnx("incorrect number of arguments."); 231554912308SNavdeep Parhar return (EINVAL); 231654912308SNavdeep Parhar } 231754912308SNavdeep Parhar 231854912308SNavdeep Parhar p = str_to_number(argv[0], &l, NULL); 231954912308SNavdeep Parhar if (*p || l > UCHAR_MAX) { 232054912308SNavdeep Parhar warnx("invalid port id \"%s\"", argv[0]); 232154912308SNavdeep Parhar return (EINVAL); 232254912308SNavdeep Parhar } 232354912308SNavdeep Parhar i2cd.port_id = l; 232454912308SNavdeep Parhar 232554912308SNavdeep Parhar p = str_to_number(argv[1], &l, NULL); 232654912308SNavdeep Parhar if (*p || l > UCHAR_MAX) { 232754912308SNavdeep Parhar warnx("invalid i2c device address \"%s\"", argv[1]); 232854912308SNavdeep Parhar return (EINVAL); 232954912308SNavdeep Parhar } 233054912308SNavdeep Parhar i2cd.dev_addr = l; 233154912308SNavdeep Parhar 233254912308SNavdeep Parhar p = str_to_number(argv[2], &l, NULL); 233354912308SNavdeep Parhar if (*p || l > UCHAR_MAX) { 233454912308SNavdeep Parhar warnx("invalid byte offset \"%s\"", argv[2]); 233554912308SNavdeep Parhar return (EINVAL); 233654912308SNavdeep Parhar } 233754912308SNavdeep Parhar i2cd.offset = l; 233854912308SNavdeep Parhar 233954912308SNavdeep Parhar if (argc == 4) { 234054912308SNavdeep Parhar p = str_to_number(argv[3], &l, NULL); 234154912308SNavdeep Parhar if (*p || l > sizeof(i2cd.data)) { 234254912308SNavdeep Parhar warnx("invalid number of bytes \"%s\"", argv[3]); 234354912308SNavdeep Parhar return (EINVAL); 234454912308SNavdeep Parhar } 234554912308SNavdeep Parhar i2cd.len = l; 234654912308SNavdeep Parhar } else 234754912308SNavdeep Parhar i2cd.len = 1; 234854912308SNavdeep Parhar 234954912308SNavdeep Parhar rc = doit(CHELSIO_T4_GET_I2C, &i2cd); 235054912308SNavdeep Parhar if (rc != 0) 235154912308SNavdeep Parhar return (rc); 235254912308SNavdeep Parhar 235354912308SNavdeep Parhar for (i = 0; i < i2cd.len; i++) 235454912308SNavdeep Parhar printf("0x%x [%u]\n", i2cd.data[i], i2cd.data[i]); 235554912308SNavdeep Parhar 235654912308SNavdeep Parhar return (0); 235754912308SNavdeep Parhar } 235854912308SNavdeep Parhar 235954912308SNavdeep Parhar static int 236054912308SNavdeep Parhar clearstats(int argc, const char *argv[]) 236154912308SNavdeep Parhar { 236254912308SNavdeep Parhar char *p; 236354912308SNavdeep Parhar long l; 236454912308SNavdeep Parhar uint32_t port; 236554912308SNavdeep Parhar 236654912308SNavdeep Parhar if (argc != 1) { 236754912308SNavdeep Parhar warnx("incorrect number of arguments."); 236854912308SNavdeep Parhar return (EINVAL); 236954912308SNavdeep Parhar } 237054912308SNavdeep Parhar 237154912308SNavdeep Parhar p = str_to_number(argv[0], &l, NULL); 237254912308SNavdeep Parhar if (*p) { 237354912308SNavdeep Parhar warnx("invalid port id \"%s\"", argv[0]); 237454912308SNavdeep Parhar return (EINVAL); 237554912308SNavdeep Parhar } 237654912308SNavdeep Parhar port = l; 237754912308SNavdeep Parhar 237854912308SNavdeep Parhar return doit(CHELSIO_T4_CLEAR_STATS, &port); 237954912308SNavdeep Parhar } 238054912308SNavdeep Parhar 238154912308SNavdeep Parhar static int 238254912308SNavdeep Parhar show_tracers(void) 238354912308SNavdeep Parhar { 238454912308SNavdeep Parhar struct t4_tracer t; 238554912308SNavdeep Parhar char *s; 238654912308SNavdeep Parhar int rc, port_idx, i; 238754912308SNavdeep Parhar long long val; 238854912308SNavdeep Parhar 238954912308SNavdeep Parhar /* Magic values: MPS_TRC_CFG = 0x9800. MPS_TRC_CFG[1:1] = TrcEn */ 239054912308SNavdeep Parhar rc = read_reg(0x9800, 4, &val); 239154912308SNavdeep Parhar if (rc != 0) 239254912308SNavdeep Parhar return (rc); 239354912308SNavdeep Parhar printf("tracing is %s\n", val & 2 ? "ENABLED" : "DISABLED"); 239454912308SNavdeep Parhar 239554912308SNavdeep Parhar t.idx = 0; 239654912308SNavdeep Parhar for (t.idx = 0; ; t.idx++) { 239754912308SNavdeep Parhar rc = doit(CHELSIO_T4_GET_TRACER, &t); 239854912308SNavdeep Parhar if (rc != 0 || t.idx == 0xff) 239954912308SNavdeep Parhar break; 240054912308SNavdeep Parhar 240154912308SNavdeep Parhar if (t.tp.port < 4) { 240254912308SNavdeep Parhar s = "Rx"; 240354912308SNavdeep Parhar port_idx = t.tp.port; 240454912308SNavdeep Parhar } else if (t.tp.port < 8) { 240554912308SNavdeep Parhar s = "Tx"; 240654912308SNavdeep Parhar port_idx = t.tp.port - 4; 240754912308SNavdeep Parhar } else if (t.tp.port < 12) { 240854912308SNavdeep Parhar s = "loopback"; 240954912308SNavdeep Parhar port_idx = t.tp.port - 8; 241054912308SNavdeep Parhar } else if (t.tp.port < 16) { 241154912308SNavdeep Parhar s = "MPS Rx"; 241254912308SNavdeep Parhar port_idx = t.tp.port - 12; 241354912308SNavdeep Parhar } else if (t.tp.port < 20) { 241454912308SNavdeep Parhar s = "MPS Tx"; 241554912308SNavdeep Parhar port_idx = t.tp.port - 16; 241654912308SNavdeep Parhar } else { 241754912308SNavdeep Parhar s = "unknown"; 241854912308SNavdeep Parhar port_idx = t.tp.port; 241954912308SNavdeep Parhar } 242054912308SNavdeep Parhar 242154912308SNavdeep Parhar printf("\ntracer %u (currently %s) captures ", t.idx, 242254912308SNavdeep Parhar t.enabled ? "ENABLED" : "DISABLED"); 242354912308SNavdeep Parhar if (t.tp.port < 8) 242454912308SNavdeep Parhar printf("port %u %s, ", port_idx, s); 242554912308SNavdeep Parhar else 242654912308SNavdeep Parhar printf("%s %u, ", s, port_idx); 242754912308SNavdeep Parhar printf("snap length: %u, min length: %u\n", t.tp.snap_len, 242854912308SNavdeep Parhar t.tp.min_len); 242954912308SNavdeep Parhar printf("packets captured %smatch filter\n", 243054912308SNavdeep Parhar t.tp.invert ? "do not " : ""); 243154912308SNavdeep Parhar if (t.tp.skip_ofst) { 243254912308SNavdeep Parhar printf("filter pattern: "); 243354912308SNavdeep Parhar for (i = 0; i < t.tp.skip_ofst * 2; i += 2) 243454912308SNavdeep Parhar printf("%08x%08x", t.tp.data[i], 243554912308SNavdeep Parhar t.tp.data[i + 1]); 243654912308SNavdeep Parhar printf("/"); 243754912308SNavdeep Parhar for (i = 0; i < t.tp.skip_ofst * 2; i += 2) 243854912308SNavdeep Parhar printf("%08x%08x", t.tp.mask[i], 243954912308SNavdeep Parhar t.tp.mask[i + 1]); 244054912308SNavdeep Parhar printf("@0\n"); 244154912308SNavdeep Parhar } 244254912308SNavdeep Parhar printf("filter pattern: "); 244354912308SNavdeep Parhar for (i = t.tp.skip_ofst * 2; i < T4_TRACE_LEN / 4; i += 2) 244454912308SNavdeep Parhar printf("%08x%08x", t.tp.data[i], t.tp.data[i + 1]); 244554912308SNavdeep Parhar printf("/"); 244654912308SNavdeep Parhar for (i = t.tp.skip_ofst * 2; i < T4_TRACE_LEN / 4; i += 2) 244754912308SNavdeep Parhar printf("%08x%08x", t.tp.mask[i], t.tp.mask[i + 1]); 244854912308SNavdeep Parhar printf("@%u\n", (t.tp.skip_ofst + t.tp.skip_len) * 8); 244954912308SNavdeep Parhar } 245054912308SNavdeep Parhar 245154912308SNavdeep Parhar return (rc); 245254912308SNavdeep Parhar } 245354912308SNavdeep Parhar 245454912308SNavdeep Parhar static int 245554912308SNavdeep Parhar tracer_onoff(uint8_t idx, int enabled) 245654912308SNavdeep Parhar { 245754912308SNavdeep Parhar struct t4_tracer t; 245854912308SNavdeep Parhar 245954912308SNavdeep Parhar t.idx = idx; 246054912308SNavdeep Parhar t.enabled = enabled; 246154912308SNavdeep Parhar t.valid = 0; 246254912308SNavdeep Parhar 246354912308SNavdeep Parhar return doit(CHELSIO_T4_SET_TRACER, &t); 246454912308SNavdeep Parhar } 246554912308SNavdeep Parhar 246654912308SNavdeep Parhar static void 246754912308SNavdeep Parhar create_tracing_ifnet() 246854912308SNavdeep Parhar { 246954912308SNavdeep Parhar char *cmd[] = { 247054912308SNavdeep Parhar "/sbin/ifconfig", __DECONST(char *, nexus), "create", NULL 247154912308SNavdeep Parhar }; 247254912308SNavdeep Parhar char *env[] = {NULL}; 247354912308SNavdeep Parhar 247454912308SNavdeep Parhar if (vfork() == 0) { 247554912308SNavdeep Parhar close(STDERR_FILENO); 247654912308SNavdeep Parhar execve(cmd[0], cmd, env); 247754912308SNavdeep Parhar _exit(0); 247854912308SNavdeep Parhar } 247954912308SNavdeep Parhar } 248054912308SNavdeep Parhar 248154912308SNavdeep Parhar /* 248254912308SNavdeep Parhar * XXX: Allow user to specify snaplen, minlen, and pattern (including inverted 248354912308SNavdeep Parhar * matching). Right now this is a quick-n-dirty implementation that traces the 248454912308SNavdeep Parhar * first 128B of all tx or rx on a port 248554912308SNavdeep Parhar */ 248654912308SNavdeep Parhar static int 248754912308SNavdeep Parhar set_tracer(uint8_t idx, int argc, const char *argv[]) 248854912308SNavdeep Parhar { 248954912308SNavdeep Parhar struct t4_tracer t; 249054912308SNavdeep Parhar int len, port; 249154912308SNavdeep Parhar 249254912308SNavdeep Parhar bzero(&t, sizeof (t)); 249354912308SNavdeep Parhar t.idx = idx; 249454912308SNavdeep Parhar t.enabled = 1; 249554912308SNavdeep Parhar t.valid = 1; 249654912308SNavdeep Parhar 249754912308SNavdeep Parhar if (argc != 1) { 249854912308SNavdeep Parhar warnx("must specify tx<n> or rx<n>."); 249954912308SNavdeep Parhar return (EINVAL); 250054912308SNavdeep Parhar } 250154912308SNavdeep Parhar 250254912308SNavdeep Parhar len = strlen(argv[0]); 250354912308SNavdeep Parhar if (len != 3) { 250454912308SNavdeep Parhar warnx("argument must be 3 characters (tx<n> or rx<n>)"); 250554912308SNavdeep Parhar return (EINVAL); 250654912308SNavdeep Parhar } 250754912308SNavdeep Parhar 250854912308SNavdeep Parhar if (strncmp(argv[0], "tx", 2) == 0) { 250954912308SNavdeep Parhar port = argv[0][2] - '0'; 251054912308SNavdeep Parhar if (port < 0 || port > 3) { 251154912308SNavdeep Parhar warnx("'%c' in %s is invalid", argv[0][2], argv[0]); 251254912308SNavdeep Parhar return (EINVAL); 251354912308SNavdeep Parhar } 251454912308SNavdeep Parhar port += 4; 251554912308SNavdeep Parhar } else if (strncmp(argv[0], "rx", 2) == 0) { 251654912308SNavdeep Parhar port = argv[0][2] - '0'; 251754912308SNavdeep Parhar if (port < 0 || port > 3) { 251854912308SNavdeep Parhar warnx("'%c' in %s is invalid", argv[0][2], argv[0]); 251954912308SNavdeep Parhar return (EINVAL); 252054912308SNavdeep Parhar } 252154912308SNavdeep Parhar } else { 252254912308SNavdeep Parhar warnx("argument '%s' isn't tx<n> or rx<n>", argv[0]); 252354912308SNavdeep Parhar return (EINVAL); 252454912308SNavdeep Parhar } 252554912308SNavdeep Parhar 252654912308SNavdeep Parhar t.tp.snap_len = 128; 252754912308SNavdeep Parhar t.tp.min_len = 0; 252854912308SNavdeep Parhar t.tp.skip_ofst = 0; 252954912308SNavdeep Parhar t.tp.skip_len = 0; 253054912308SNavdeep Parhar t.tp.invert = 0; 253154912308SNavdeep Parhar t.tp.port = port; 253254912308SNavdeep Parhar 253354912308SNavdeep Parhar create_tracing_ifnet(); 253454912308SNavdeep Parhar return doit(CHELSIO_T4_SET_TRACER, &t); 253554912308SNavdeep Parhar } 253654912308SNavdeep Parhar 253754912308SNavdeep Parhar static int 253854912308SNavdeep Parhar tracer_cmd(int argc, const char *argv[]) 253954912308SNavdeep Parhar { 254054912308SNavdeep Parhar long long val; 254154912308SNavdeep Parhar uint8_t idx; 254254912308SNavdeep Parhar char *s; 254354912308SNavdeep Parhar 254454912308SNavdeep Parhar if (argc == 0) { 254554912308SNavdeep Parhar warnx("tracer: no arguments."); 254654912308SNavdeep Parhar return (EINVAL); 254754912308SNavdeep Parhar }; 254854912308SNavdeep Parhar 254954912308SNavdeep Parhar /* list */ 255054912308SNavdeep Parhar if (strcmp(argv[0], "list") == 0) { 255154912308SNavdeep Parhar if (argc != 1) 255254912308SNavdeep Parhar warnx("trailing arguments after \"list\" ignored."); 255354912308SNavdeep Parhar 255454912308SNavdeep Parhar return show_tracers(); 255554912308SNavdeep Parhar } 255654912308SNavdeep Parhar 255754912308SNavdeep Parhar /* <idx> ... */ 255854912308SNavdeep Parhar s = str_to_number(argv[0], NULL, &val); 255954912308SNavdeep Parhar if (*s || val > 0xff) { 256054912308SNavdeep Parhar warnx("\"%s\" is neither an index nor a tracer subcommand.", 256154912308SNavdeep Parhar argv[0]); 256254912308SNavdeep Parhar return (EINVAL); 256354912308SNavdeep Parhar } 256454912308SNavdeep Parhar idx = (int8_t)val; 256554912308SNavdeep Parhar 256654912308SNavdeep Parhar /* <idx> disable */ 256754912308SNavdeep Parhar if (argc == 2 && strcmp(argv[1], "disable") == 0) 256854912308SNavdeep Parhar return tracer_onoff(idx, 0); 256954912308SNavdeep Parhar 257054912308SNavdeep Parhar /* <idx> enable */ 257154912308SNavdeep Parhar if (argc == 2 && strcmp(argv[1], "enable") == 0) 257254912308SNavdeep Parhar return tracer_onoff(idx, 1); 257354912308SNavdeep Parhar 257454912308SNavdeep Parhar /* <idx> ... */ 257554912308SNavdeep Parhar return set_tracer(idx, argc - 1, argv + 1); 257654912308SNavdeep Parhar } 257754912308SNavdeep Parhar 257854912308SNavdeep Parhar static int 257954912308SNavdeep Parhar modinfo_raw(int port_id) 258054912308SNavdeep Parhar { 258154912308SNavdeep Parhar uint8_t offset; 258254912308SNavdeep Parhar struct t4_i2c_data i2cd; 258354912308SNavdeep Parhar int rc; 258454912308SNavdeep Parhar 258554912308SNavdeep Parhar for (offset = 0; offset < 96; offset += sizeof(i2cd.data)) { 258654912308SNavdeep Parhar bzero(&i2cd, sizeof(i2cd)); 258754912308SNavdeep Parhar i2cd.port_id = port_id; 258854912308SNavdeep Parhar i2cd.dev_addr = 0xa0; 258954912308SNavdeep Parhar i2cd.offset = offset; 259054912308SNavdeep Parhar i2cd.len = sizeof(i2cd.data); 259154912308SNavdeep Parhar rc = doit(CHELSIO_T4_GET_I2C, &i2cd); 259254912308SNavdeep Parhar if (rc != 0) 259354912308SNavdeep Parhar return (rc); 259454912308SNavdeep Parhar printf("%02x: %02x %02x %02x %02x %02x %02x %02x %02x", 259554912308SNavdeep Parhar offset, i2cd.data[0], i2cd.data[1], i2cd.data[2], 259654912308SNavdeep Parhar i2cd.data[3], i2cd.data[4], i2cd.data[5], i2cd.data[6], 259754912308SNavdeep Parhar i2cd.data[7]); 259854912308SNavdeep Parhar 259954912308SNavdeep Parhar printf(" %c%c%c%c %c%c%c%c\n", 260054912308SNavdeep Parhar isprint(i2cd.data[0]) ? i2cd.data[0] : '.', 260154912308SNavdeep Parhar isprint(i2cd.data[1]) ? i2cd.data[1] : '.', 260254912308SNavdeep Parhar isprint(i2cd.data[2]) ? i2cd.data[2] : '.', 260354912308SNavdeep Parhar isprint(i2cd.data[3]) ? i2cd.data[3] : '.', 260454912308SNavdeep Parhar isprint(i2cd.data[4]) ? i2cd.data[4] : '.', 260554912308SNavdeep Parhar isprint(i2cd.data[5]) ? i2cd.data[5] : '.', 260654912308SNavdeep Parhar isprint(i2cd.data[6]) ? i2cd.data[6] : '.', 260754912308SNavdeep Parhar isprint(i2cd.data[7]) ? i2cd.data[7] : '.'); 260854912308SNavdeep Parhar } 260954912308SNavdeep Parhar 261054912308SNavdeep Parhar return (0); 261154912308SNavdeep Parhar } 261254912308SNavdeep Parhar 261354912308SNavdeep Parhar static int 261454912308SNavdeep Parhar modinfo(int argc, const char *argv[]) 261554912308SNavdeep Parhar { 261654912308SNavdeep Parhar long port; 261754912308SNavdeep Parhar char string[16], *p; 261854912308SNavdeep Parhar struct t4_i2c_data i2cd; 261954912308SNavdeep Parhar int rc, i; 262054912308SNavdeep Parhar uint16_t temp, vcc, tx_bias, tx_power, rx_power; 262154912308SNavdeep Parhar 262254912308SNavdeep Parhar if (argc < 1) { 262354912308SNavdeep Parhar warnx("must supply a port"); 262454912308SNavdeep Parhar return (EINVAL); 262554912308SNavdeep Parhar } 262654912308SNavdeep Parhar 262754912308SNavdeep Parhar if (argc > 2) { 262854912308SNavdeep Parhar warnx("too many arguments"); 262954912308SNavdeep Parhar return (EINVAL); 263054912308SNavdeep Parhar } 263154912308SNavdeep Parhar 263254912308SNavdeep Parhar p = str_to_number(argv[0], &port, NULL); 263354912308SNavdeep Parhar if (*p || port > UCHAR_MAX) { 263454912308SNavdeep Parhar warnx("invalid port id \"%s\"", argv[0]); 263554912308SNavdeep Parhar return (EINVAL); 263654912308SNavdeep Parhar } 263754912308SNavdeep Parhar 263854912308SNavdeep Parhar if (argc == 2) { 263954912308SNavdeep Parhar if (!strcmp(argv[1], "raw")) 264054912308SNavdeep Parhar return (modinfo_raw(port)); 264154912308SNavdeep Parhar else { 264254912308SNavdeep Parhar warnx("second argument can only be \"raw\""); 264354912308SNavdeep Parhar return (EINVAL); 264454912308SNavdeep Parhar } 264554912308SNavdeep Parhar } 264654912308SNavdeep Parhar 264754912308SNavdeep Parhar bzero(&i2cd, sizeof(i2cd)); 264854912308SNavdeep Parhar i2cd.len = 1; 264954912308SNavdeep Parhar i2cd.port_id = port; 265054912308SNavdeep Parhar i2cd.dev_addr = SFF_8472_BASE; 265154912308SNavdeep Parhar 265254912308SNavdeep Parhar i2cd.offset = SFF_8472_ID; 265354912308SNavdeep Parhar if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) 265454912308SNavdeep Parhar goto fail; 265554912308SNavdeep Parhar 265654912308SNavdeep Parhar if (i2cd.data[0] > SFF_8472_ID_LAST) 265754912308SNavdeep Parhar printf("Unknown ID\n"); 265854912308SNavdeep Parhar else 265954912308SNavdeep Parhar printf("ID: %s\n", sff_8472_id[i2cd.data[0]]); 266054912308SNavdeep Parhar 266154912308SNavdeep Parhar bzero(&string, sizeof(string)); 266254912308SNavdeep Parhar for (i = SFF_8472_VENDOR_START; i < SFF_8472_VENDOR_END; i++) { 266354912308SNavdeep Parhar i2cd.offset = i; 266454912308SNavdeep Parhar if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) 266554912308SNavdeep Parhar goto fail; 266654912308SNavdeep Parhar string[i - SFF_8472_VENDOR_START] = i2cd.data[0]; 266754912308SNavdeep Parhar } 266854912308SNavdeep Parhar printf("Vendor %s\n", string); 266954912308SNavdeep Parhar 267054912308SNavdeep Parhar bzero(&string, sizeof(string)); 267154912308SNavdeep Parhar for (i = SFF_8472_SN_START; i < SFF_8472_SN_END; i++) { 267254912308SNavdeep Parhar i2cd.offset = i; 267354912308SNavdeep Parhar if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) 267454912308SNavdeep Parhar goto fail; 267554912308SNavdeep Parhar string[i - SFF_8472_SN_START] = i2cd.data[0]; 267654912308SNavdeep Parhar } 267754912308SNavdeep Parhar printf("SN %s\n", string); 267854912308SNavdeep Parhar 267954912308SNavdeep Parhar bzero(&string, sizeof(string)); 268054912308SNavdeep Parhar for (i = SFF_8472_PN_START; i < SFF_8472_PN_END; i++) { 268154912308SNavdeep Parhar i2cd.offset = i; 268254912308SNavdeep Parhar if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) 268354912308SNavdeep Parhar goto fail; 268454912308SNavdeep Parhar string[i - SFF_8472_PN_START] = i2cd.data[0]; 268554912308SNavdeep Parhar } 268654912308SNavdeep Parhar printf("PN %s\n", string); 268754912308SNavdeep Parhar 268854912308SNavdeep Parhar bzero(&string, sizeof(string)); 268954912308SNavdeep Parhar for (i = SFF_8472_REV_START; i < SFF_8472_REV_END; i++) { 269054912308SNavdeep Parhar i2cd.offset = i; 269154912308SNavdeep Parhar if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) 269254912308SNavdeep Parhar goto fail; 269354912308SNavdeep Parhar string[i - SFF_8472_REV_START] = i2cd.data[0]; 269454912308SNavdeep Parhar } 269554912308SNavdeep Parhar printf("Rev %s\n", string); 269654912308SNavdeep Parhar 269754912308SNavdeep Parhar i2cd.offset = SFF_8472_DIAG_TYPE; 269854912308SNavdeep Parhar if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) 269954912308SNavdeep Parhar goto fail; 270054912308SNavdeep Parhar 270154912308SNavdeep Parhar if ((char )i2cd.data[0] & (SFF_8472_DIAG_IMPL | 270254912308SNavdeep Parhar SFF_8472_DIAG_INTERNAL)) { 270354912308SNavdeep Parhar 270454912308SNavdeep Parhar /* Switch to reading from the Diagnostic address. */ 270554912308SNavdeep Parhar i2cd.dev_addr = SFF_8472_DIAG; 270654912308SNavdeep Parhar i2cd.len = 1; 270754912308SNavdeep Parhar 270854912308SNavdeep Parhar i2cd.offset = SFF_8472_TEMP; 270954912308SNavdeep Parhar if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) 271054912308SNavdeep Parhar goto fail; 271154912308SNavdeep Parhar temp = i2cd.data[0] << 8; 271254912308SNavdeep Parhar printf("Temp: "); 271354912308SNavdeep Parhar if ((temp & SFF_8472_TEMP_SIGN) == SFF_8472_TEMP_SIGN) 271454912308SNavdeep Parhar printf("-"); 271554912308SNavdeep Parhar else 271654912308SNavdeep Parhar printf("+"); 271754912308SNavdeep Parhar printf("%dC\n", (temp & SFF_8472_TEMP_MSK) >> 271854912308SNavdeep Parhar SFF_8472_TEMP_SHIFT); 271954912308SNavdeep Parhar 272054912308SNavdeep Parhar i2cd.offset = SFF_8472_VCC; 272154912308SNavdeep Parhar if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) 272254912308SNavdeep Parhar goto fail; 272354912308SNavdeep Parhar vcc = i2cd.data[0] << 8; 272454912308SNavdeep Parhar printf("Vcc %fV\n", vcc / SFF_8472_VCC_FACTOR); 272554912308SNavdeep Parhar 272654912308SNavdeep Parhar i2cd.offset = SFF_8472_TX_BIAS; 272754912308SNavdeep Parhar if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) 272854912308SNavdeep Parhar goto fail; 272954912308SNavdeep Parhar tx_bias = i2cd.data[0] << 8; 273054912308SNavdeep Parhar printf("TX Bias %fuA\n", tx_bias / SFF_8472_BIAS_FACTOR); 273154912308SNavdeep Parhar 273254912308SNavdeep Parhar i2cd.offset = SFF_8472_TX_POWER; 273354912308SNavdeep Parhar if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) 273454912308SNavdeep Parhar goto fail; 273554912308SNavdeep Parhar tx_power = i2cd.data[0] << 8; 273654912308SNavdeep Parhar printf("TX Power %fmW\n", tx_power / SFF_8472_POWER_FACTOR); 273754912308SNavdeep Parhar 273854912308SNavdeep Parhar i2cd.offset = SFF_8472_RX_POWER; 273954912308SNavdeep Parhar if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) 274054912308SNavdeep Parhar goto fail; 274154912308SNavdeep Parhar rx_power = i2cd.data[0] << 8; 274254912308SNavdeep Parhar printf("RX Power %fmW\n", rx_power / SFF_8472_POWER_FACTOR); 274354912308SNavdeep Parhar 274454912308SNavdeep Parhar } else 274554912308SNavdeep Parhar printf("Diagnostics not supported.\n"); 274654912308SNavdeep Parhar 274754912308SNavdeep Parhar return(0); 274854912308SNavdeep Parhar 274954912308SNavdeep Parhar fail: 275054912308SNavdeep Parhar if (rc == EPERM) 275154912308SNavdeep Parhar warnx("No module/cable in port %ld", port); 275254912308SNavdeep Parhar return (rc); 275354912308SNavdeep Parhar 275454912308SNavdeep Parhar } 275554912308SNavdeep Parhar 275654912308SNavdeep Parhar /* XXX: pass in a low/high and do range checks as well */ 275754912308SNavdeep Parhar static int 275854912308SNavdeep Parhar get_sched_param(const char *param, const char *args[], long *val) 275954912308SNavdeep Parhar { 276054912308SNavdeep Parhar char *p; 276154912308SNavdeep Parhar 276254912308SNavdeep Parhar if (strcmp(param, args[0]) != 0) 276354912308SNavdeep Parhar return (EINVAL); 276454912308SNavdeep Parhar 276554912308SNavdeep Parhar p = str_to_number(args[1], val, NULL); 276654912308SNavdeep Parhar if (*p) { 276754912308SNavdeep Parhar warnx("parameter \"%s\" has bad value \"%s\"", args[0], 276854912308SNavdeep Parhar args[1]); 276954912308SNavdeep Parhar return (EINVAL); 277054912308SNavdeep Parhar } 277154912308SNavdeep Parhar 277254912308SNavdeep Parhar return (0); 277354912308SNavdeep Parhar } 277454912308SNavdeep Parhar 277554912308SNavdeep Parhar static int 277654912308SNavdeep Parhar sched_class(int argc, const char *argv[]) 277754912308SNavdeep Parhar { 277854912308SNavdeep Parhar struct t4_sched_params op; 277954912308SNavdeep Parhar int errs, i; 278054912308SNavdeep Parhar 278154912308SNavdeep Parhar memset(&op, 0xff, sizeof(op)); 278254912308SNavdeep Parhar op.subcmd = -1; 278354912308SNavdeep Parhar op.type = -1; 278454912308SNavdeep Parhar if (argc == 0) { 278554912308SNavdeep Parhar warnx("missing scheduling sub-command"); 278654912308SNavdeep Parhar return (EINVAL); 278754912308SNavdeep Parhar } 278854912308SNavdeep Parhar if (!strcmp(argv[0], "config")) { 278954912308SNavdeep Parhar op.subcmd = SCHED_CLASS_SUBCMD_CONFIG; 279054912308SNavdeep Parhar op.u.config.minmax = -1; 279154912308SNavdeep Parhar } else if (!strcmp(argv[0], "params")) { 279254912308SNavdeep Parhar op.subcmd = SCHED_CLASS_SUBCMD_PARAMS; 279354912308SNavdeep Parhar op.u.params.level = op.u.params.mode = op.u.params.rateunit = 279454912308SNavdeep Parhar op.u.params.ratemode = op.u.params.channel = 279554912308SNavdeep Parhar op.u.params.cl = op.u.params.minrate = op.u.params.maxrate = 279654912308SNavdeep Parhar op.u.params.weight = op.u.params.pktsize = -1; 279754912308SNavdeep Parhar } else { 279854912308SNavdeep Parhar warnx("invalid scheduling sub-command \"%s\"", argv[0]); 279954912308SNavdeep Parhar return (EINVAL); 280054912308SNavdeep Parhar } 280154912308SNavdeep Parhar 280254912308SNavdeep Parhar /* Decode remaining arguments ... */ 280354912308SNavdeep Parhar errs = 0; 280454912308SNavdeep Parhar for (i = 1; i < argc; i += 2) { 280554912308SNavdeep Parhar const char **args = &argv[i]; 280654912308SNavdeep Parhar long l; 280754912308SNavdeep Parhar 280854912308SNavdeep Parhar if (i + 1 == argc) { 280954912308SNavdeep Parhar warnx("missing argument for \"%s\"", args[0]); 281054912308SNavdeep Parhar errs++; 281154912308SNavdeep Parhar break; 281254912308SNavdeep Parhar } 281354912308SNavdeep Parhar 281454912308SNavdeep Parhar if (!strcmp(args[0], "type")) { 281554912308SNavdeep Parhar if (!strcmp(args[1], "packet")) 281654912308SNavdeep Parhar op.type = SCHED_CLASS_TYPE_PACKET; 281754912308SNavdeep Parhar else { 281854912308SNavdeep Parhar warnx("invalid type parameter \"%s\"", args[1]); 281954912308SNavdeep Parhar errs++; 282054912308SNavdeep Parhar } 282154912308SNavdeep Parhar 282254912308SNavdeep Parhar continue; 282354912308SNavdeep Parhar } 282454912308SNavdeep Parhar 282554912308SNavdeep Parhar if (op.subcmd == SCHED_CLASS_SUBCMD_CONFIG) { 282654912308SNavdeep Parhar if(!get_sched_param("minmax", args, &l)) 282754912308SNavdeep Parhar op.u.config.minmax = (int8_t)l; 282854912308SNavdeep Parhar else { 282954912308SNavdeep Parhar warnx("unknown scheduler config parameter " 283054912308SNavdeep Parhar "\"%s\"", args[0]); 283154912308SNavdeep Parhar errs++; 283254912308SNavdeep Parhar } 283354912308SNavdeep Parhar 283454912308SNavdeep Parhar continue; 283554912308SNavdeep Parhar } 283654912308SNavdeep Parhar 283754912308SNavdeep Parhar /* Rest applies only to SUBCMD_PARAMS */ 283854912308SNavdeep Parhar if (op.subcmd != SCHED_CLASS_SUBCMD_PARAMS) 283954912308SNavdeep Parhar continue; 284054912308SNavdeep Parhar 284154912308SNavdeep Parhar if (!strcmp(args[0], "level")) { 284254912308SNavdeep Parhar if (!strcmp(args[1], "cl-rl")) 284354912308SNavdeep Parhar op.u.params.level = SCHED_CLASS_LEVEL_CL_RL; 284454912308SNavdeep Parhar else if (!strcmp(args[1], "cl-wrr")) 284554912308SNavdeep Parhar op.u.params.level = SCHED_CLASS_LEVEL_CL_WRR; 284654912308SNavdeep Parhar else if (!strcmp(args[1], "ch-rl")) 284754912308SNavdeep Parhar op.u.params.level = SCHED_CLASS_LEVEL_CH_RL; 284854912308SNavdeep Parhar else { 284954912308SNavdeep Parhar warnx("invalid level parameter \"%s\"", 285054912308SNavdeep Parhar args[1]); 285154912308SNavdeep Parhar errs++; 285254912308SNavdeep Parhar } 285354912308SNavdeep Parhar } else if (!strcmp(args[0], "mode")) { 285454912308SNavdeep Parhar if (!strcmp(args[1], "class")) 285554912308SNavdeep Parhar op.u.params.mode = SCHED_CLASS_MODE_CLASS; 285654912308SNavdeep Parhar else if (!strcmp(args[1], "flow")) 285754912308SNavdeep Parhar op.u.params.mode = SCHED_CLASS_MODE_FLOW; 285854912308SNavdeep Parhar else { 285954912308SNavdeep Parhar warnx("invalid mode parameter \"%s\"", args[1]); 286054912308SNavdeep Parhar errs++; 286154912308SNavdeep Parhar } 286254912308SNavdeep Parhar } else if (!strcmp(args[0], "rate-unit")) { 286354912308SNavdeep Parhar if (!strcmp(args[1], "bits")) 286454912308SNavdeep Parhar op.u.params.rateunit = SCHED_CLASS_RATEUNIT_BITS; 286554912308SNavdeep Parhar else if (!strcmp(args[1], "pkts")) 286654912308SNavdeep Parhar op.u.params.rateunit = SCHED_CLASS_RATEUNIT_PKTS; 286754912308SNavdeep Parhar else { 286854912308SNavdeep Parhar warnx("invalid rate-unit parameter \"%s\"", 286954912308SNavdeep Parhar args[1]); 287054912308SNavdeep Parhar errs++; 287154912308SNavdeep Parhar } 287254912308SNavdeep Parhar } else if (!strcmp(args[0], "rate-mode")) { 287354912308SNavdeep Parhar if (!strcmp(args[1], "relative")) 287454912308SNavdeep Parhar op.u.params.ratemode = SCHED_CLASS_RATEMODE_REL; 287554912308SNavdeep Parhar else if (!strcmp(args[1], "absolute")) 287654912308SNavdeep Parhar op.u.params.ratemode = SCHED_CLASS_RATEMODE_ABS; 287754912308SNavdeep Parhar else { 287854912308SNavdeep Parhar warnx("invalid rate-mode parameter \"%s\"", 287954912308SNavdeep Parhar args[1]); 288054912308SNavdeep Parhar errs++; 288154912308SNavdeep Parhar } 288254912308SNavdeep Parhar } else if (!get_sched_param("channel", args, &l)) 288354912308SNavdeep Parhar op.u.params.channel = (int8_t)l; 288454912308SNavdeep Parhar else if (!get_sched_param("class", args, &l)) 288554912308SNavdeep Parhar op.u.params.cl = (int8_t)l; 288654912308SNavdeep Parhar else if (!get_sched_param("min-rate", args, &l)) 288754912308SNavdeep Parhar op.u.params.minrate = (int32_t)l; 288854912308SNavdeep Parhar else if (!get_sched_param("max-rate", args, &l)) 288954912308SNavdeep Parhar op.u.params.maxrate = (int32_t)l; 289054912308SNavdeep Parhar else if (!get_sched_param("weight", args, &l)) 289154912308SNavdeep Parhar op.u.params.weight = (int16_t)l; 289254912308SNavdeep Parhar else if (!get_sched_param("pkt-size", args, &l)) 289354912308SNavdeep Parhar op.u.params.pktsize = (int16_t)l; 289454912308SNavdeep Parhar else { 289554912308SNavdeep Parhar warnx("unknown scheduler parameter \"%s\"", args[0]); 289654912308SNavdeep Parhar errs++; 289754912308SNavdeep Parhar } 289854912308SNavdeep Parhar } 289954912308SNavdeep Parhar 290054912308SNavdeep Parhar /* 290154912308SNavdeep Parhar * Catch some logical fallacies in terms of argument combinations here 290254912308SNavdeep Parhar * so we can offer more than just the EINVAL return from the driver. 290354912308SNavdeep Parhar * The driver will be able to catch a lot more issues since it knows 290454912308SNavdeep Parhar * the specifics of the device hardware capabilities like how many 290554912308SNavdeep Parhar * channels, classes, etc. the device supports. 290654912308SNavdeep Parhar */ 290754912308SNavdeep Parhar if (op.type < 0) { 290854912308SNavdeep Parhar warnx("sched \"type\" parameter missing"); 290954912308SNavdeep Parhar errs++; 291054912308SNavdeep Parhar } 291154912308SNavdeep Parhar if (op.subcmd == SCHED_CLASS_SUBCMD_CONFIG) { 291254912308SNavdeep Parhar if (op.u.config.minmax < 0) { 291354912308SNavdeep Parhar warnx("sched config \"minmax\" parameter missing"); 291454912308SNavdeep Parhar errs++; 291554912308SNavdeep Parhar } 291654912308SNavdeep Parhar } 291754912308SNavdeep Parhar if (op.subcmd == SCHED_CLASS_SUBCMD_PARAMS) { 291854912308SNavdeep Parhar if (op.u.params.level < 0) { 291954912308SNavdeep Parhar warnx("sched params \"level\" parameter missing"); 292054912308SNavdeep Parhar errs++; 292154912308SNavdeep Parhar } 2922ffcf81c9SNavdeep Parhar if (op.u.params.mode < 0 && 2923ffcf81c9SNavdeep Parhar op.u.params.level == SCHED_CLASS_LEVEL_CL_RL) { 292454912308SNavdeep Parhar warnx("sched params \"mode\" parameter missing"); 292554912308SNavdeep Parhar errs++; 292654912308SNavdeep Parhar } 2927ffcf81c9SNavdeep Parhar if (op.u.params.rateunit < 0 && 2928ffcf81c9SNavdeep Parhar (op.u.params.level == SCHED_CLASS_LEVEL_CL_RL || 2929ffcf81c9SNavdeep Parhar op.u.params.level == SCHED_CLASS_LEVEL_CH_RL)) { 293054912308SNavdeep Parhar warnx("sched params \"rate-unit\" parameter missing"); 293154912308SNavdeep Parhar errs++; 293254912308SNavdeep Parhar } 2933ffcf81c9SNavdeep Parhar if (op.u.params.ratemode < 0 && 2934ffcf81c9SNavdeep Parhar (op.u.params.level == SCHED_CLASS_LEVEL_CL_RL || 2935ffcf81c9SNavdeep Parhar op.u.params.level == SCHED_CLASS_LEVEL_CH_RL)) { 293654912308SNavdeep Parhar warnx("sched params \"rate-mode\" parameter missing"); 293754912308SNavdeep Parhar errs++; 293854912308SNavdeep Parhar } 293954912308SNavdeep Parhar if (op.u.params.channel < 0) { 294054912308SNavdeep Parhar warnx("sched params \"channel\" missing"); 294154912308SNavdeep Parhar errs++; 294254912308SNavdeep Parhar } 2943ffcf81c9SNavdeep Parhar if (op.u.params.cl < 0 && 2944ffcf81c9SNavdeep Parhar (op.u.params.level == SCHED_CLASS_LEVEL_CL_RL || 2945ffcf81c9SNavdeep Parhar op.u.params.level == SCHED_CLASS_LEVEL_CL_WRR)) { 294654912308SNavdeep Parhar warnx("sched params \"class\" missing"); 294754912308SNavdeep Parhar errs++; 294854912308SNavdeep Parhar } 294954912308SNavdeep Parhar if (op.u.params.maxrate < 0 && 295054912308SNavdeep Parhar (op.u.params.level == SCHED_CLASS_LEVEL_CL_RL || 295154912308SNavdeep Parhar op.u.params.level == SCHED_CLASS_LEVEL_CH_RL)) { 295254912308SNavdeep Parhar warnx("sched params \"max-rate\" missing for " 295354912308SNavdeep Parhar "rate-limit level"); 295454912308SNavdeep Parhar errs++; 295554912308SNavdeep Parhar } 2956ffcf81c9SNavdeep Parhar if (op.u.params.level == SCHED_CLASS_LEVEL_CL_WRR && 2957ffcf81c9SNavdeep Parhar (op.u.params.weight < 1 || op.u.params.weight > 99)) { 2958ffcf81c9SNavdeep Parhar warnx("sched params \"weight\" missing or invalid " 2959ffcf81c9SNavdeep Parhar "(not 1-99) for weighted-round-robin level"); 296054912308SNavdeep Parhar errs++; 296154912308SNavdeep Parhar } 296254912308SNavdeep Parhar if (op.u.params.pktsize < 0 && 2963ffcf81c9SNavdeep Parhar op.u.params.level == SCHED_CLASS_LEVEL_CL_RL) { 296454912308SNavdeep Parhar warnx("sched params \"pkt-size\" missing for " 296554912308SNavdeep Parhar "rate-limit level"); 296654912308SNavdeep Parhar errs++; 296754912308SNavdeep Parhar } 296854912308SNavdeep Parhar if (op.u.params.mode == SCHED_CLASS_MODE_FLOW && 296954912308SNavdeep Parhar op.u.params.ratemode != SCHED_CLASS_RATEMODE_ABS) { 297054912308SNavdeep Parhar warnx("sched params mode flow needs rate-mode absolute"); 297154912308SNavdeep Parhar errs++; 297254912308SNavdeep Parhar } 297354912308SNavdeep Parhar if (op.u.params.ratemode == SCHED_CLASS_RATEMODE_REL && 297454912308SNavdeep Parhar !in_range(op.u.params.maxrate, 1, 100)) { 297554912308SNavdeep Parhar warnx("sched params \"max-rate\" takes " 297654912308SNavdeep Parhar "percentage value(1-100) for rate-mode relative"); 297754912308SNavdeep Parhar errs++; 297854912308SNavdeep Parhar } 297954912308SNavdeep Parhar if (op.u.params.ratemode == SCHED_CLASS_RATEMODE_ABS && 298054912308SNavdeep Parhar !in_range(op.u.params.maxrate, 1, 100000000)) { 298154912308SNavdeep Parhar warnx("sched params \"max-rate\" takes " 298254912308SNavdeep Parhar "value(1-100000000) for rate-mode absolute"); 298354912308SNavdeep Parhar errs++; 298454912308SNavdeep Parhar } 298554912308SNavdeep Parhar if (op.u.params.maxrate > 0 && 298654912308SNavdeep Parhar op.u.params.maxrate < op.u.params.minrate) { 298754912308SNavdeep Parhar warnx("sched params \"max-rate\" is less than " 298854912308SNavdeep Parhar "\"min-rate\""); 298954912308SNavdeep Parhar errs++; 299054912308SNavdeep Parhar } 299154912308SNavdeep Parhar } 299254912308SNavdeep Parhar 299354912308SNavdeep Parhar if (errs > 0) { 299454912308SNavdeep Parhar warnx("%d error%s in sched-class command", errs, 299554912308SNavdeep Parhar errs == 1 ? "" : "s"); 299654912308SNavdeep Parhar return (EINVAL); 299754912308SNavdeep Parhar } 299854912308SNavdeep Parhar 299954912308SNavdeep Parhar return doit(CHELSIO_T4_SCHED_CLASS, &op); 300054912308SNavdeep Parhar } 300154912308SNavdeep Parhar 300254912308SNavdeep Parhar static int 300354912308SNavdeep Parhar sched_queue(int argc, const char *argv[]) 300454912308SNavdeep Parhar { 300554912308SNavdeep Parhar struct t4_sched_queue op = {0}; 300654912308SNavdeep Parhar char *p; 300754912308SNavdeep Parhar long val; 300854912308SNavdeep Parhar 300954912308SNavdeep Parhar if (argc != 3) { 301054912308SNavdeep Parhar /* need "<port> <queue> <class> */ 301154912308SNavdeep Parhar warnx("incorrect number of arguments."); 301254912308SNavdeep Parhar return (EINVAL); 301354912308SNavdeep Parhar } 301454912308SNavdeep Parhar 301554912308SNavdeep Parhar p = str_to_number(argv[0], &val, NULL); 301654912308SNavdeep Parhar if (*p || val > UCHAR_MAX) { 301754912308SNavdeep Parhar warnx("invalid port id \"%s\"", argv[0]); 301854912308SNavdeep Parhar return (EINVAL); 301954912308SNavdeep Parhar } 302054912308SNavdeep Parhar op.port = (uint8_t)val; 302154912308SNavdeep Parhar 302254912308SNavdeep Parhar if (!strcmp(argv[1], "all") || !strcmp(argv[1], "*")) 302354912308SNavdeep Parhar op.queue = -1; 302454912308SNavdeep Parhar else { 302554912308SNavdeep Parhar p = str_to_number(argv[1], &val, NULL); 302654912308SNavdeep Parhar if (*p || val < -1) { 302754912308SNavdeep Parhar warnx("invalid queue \"%s\"", argv[1]); 302854912308SNavdeep Parhar return (EINVAL); 302954912308SNavdeep Parhar } 303054912308SNavdeep Parhar op.queue = (int8_t)val; 303154912308SNavdeep Parhar } 303254912308SNavdeep Parhar 303354912308SNavdeep Parhar if (!strcmp(argv[2], "unbind") || !strcmp(argv[2], "clear")) 303454912308SNavdeep Parhar op.cl = -1; 303554912308SNavdeep Parhar else { 303654912308SNavdeep Parhar p = str_to_number(argv[2], &val, NULL); 303754912308SNavdeep Parhar if (*p || val < -1) { 303854912308SNavdeep Parhar warnx("invalid class \"%s\"", argv[2]); 303954912308SNavdeep Parhar return (EINVAL); 304054912308SNavdeep Parhar } 304154912308SNavdeep Parhar op.cl = (int8_t)val; 304254912308SNavdeep Parhar } 304354912308SNavdeep Parhar 304454912308SNavdeep Parhar return doit(CHELSIO_T4_SCHED_QUEUE, &op); 304554912308SNavdeep Parhar } 304654912308SNavdeep Parhar 304754912308SNavdeep Parhar static int 30481131c927SNavdeep Parhar parse_offload_settings_word(const char *s, char **pnext, const char *ws, 30491131c927SNavdeep Parhar int *pneg, struct offload_settings *os) 30501131c927SNavdeep Parhar { 30511131c927SNavdeep Parhar 30521131c927SNavdeep Parhar while (*s == '!') { 30531131c927SNavdeep Parhar (*pneg)++; 30541131c927SNavdeep Parhar s++; 30551131c927SNavdeep Parhar } 30561131c927SNavdeep Parhar 30571131c927SNavdeep Parhar if (!strcmp(s, "not")) { 30581131c927SNavdeep Parhar (*pneg)++; 30591131c927SNavdeep Parhar return (0); 30601131c927SNavdeep Parhar } 30611131c927SNavdeep Parhar 30621131c927SNavdeep Parhar if (!strcmp(s, "offload")) { 30631131c927SNavdeep Parhar os->offload = (*pneg + 1) & 1; 30641131c927SNavdeep Parhar *pneg = 0; 30651131c927SNavdeep Parhar } else if (!strcmp(s , "coalesce")) { 30661131c927SNavdeep Parhar os->rx_coalesce = (*pneg + 1) & 1; 30671131c927SNavdeep Parhar *pneg = 0; 30681131c927SNavdeep Parhar } else if (!strcmp(s, "timestamp") || !strcmp(s, "tstamp")) { 30691131c927SNavdeep Parhar os->tstamp = (*pneg + 1) & 1; 30701131c927SNavdeep Parhar *pneg = 0; 30711131c927SNavdeep Parhar } else if (!strcmp(s, "sack")) { 30721131c927SNavdeep Parhar os->sack = (*pneg + 1) & 1; 30731131c927SNavdeep Parhar *pneg = 0; 30741131c927SNavdeep Parhar } else if (!strcmp(s, "nagle")) { 30751131c927SNavdeep Parhar os->nagle = (*pneg + 1) & 1; 30761131c927SNavdeep Parhar *pneg = 0; 30771131c927SNavdeep Parhar } else if (!strcmp(s, "ecn")) { 30781131c927SNavdeep Parhar os->ecn = (*pneg + 1) & 1; 30791131c927SNavdeep Parhar *pneg = 0; 30801131c927SNavdeep Parhar } else if (!strcmp(s, "ddp")) { 30811131c927SNavdeep Parhar os->ddp = (*pneg + 1) & 1; 30821131c927SNavdeep Parhar *pneg = 0; 30831131c927SNavdeep Parhar } else if (!strcmp(s, "tls")) { 30841131c927SNavdeep Parhar os->tls = (*pneg + 1) & 1; 30851131c927SNavdeep Parhar *pneg = 0; 30861131c927SNavdeep Parhar } else { 30871131c927SNavdeep Parhar char *param, *p; 30881131c927SNavdeep Parhar long val; 30891131c927SNavdeep Parhar 30901131c927SNavdeep Parhar /* Settings with additional parameter handled here. */ 30911131c927SNavdeep Parhar 30921131c927SNavdeep Parhar if (*pneg) { 30931131c927SNavdeep Parhar warnx("\"%s\" is not a valid keyword, or it does not " 30941131c927SNavdeep Parhar "support negation.", s); 30951131c927SNavdeep Parhar return (EINVAL); 30961131c927SNavdeep Parhar } 30971131c927SNavdeep Parhar 30981131c927SNavdeep Parhar while ((param = strsep(pnext, ws)) != NULL) { 30991131c927SNavdeep Parhar if (*param != '\0') 31001131c927SNavdeep Parhar break; 31011131c927SNavdeep Parhar } 31021131c927SNavdeep Parhar if (param == NULL) { 31031131c927SNavdeep Parhar warnx("\"%s\" is not a valid keyword, or it requires a " 31041131c927SNavdeep Parhar "parameter that has not been provided.", s); 31051131c927SNavdeep Parhar return (EINVAL); 31061131c927SNavdeep Parhar } 31071131c927SNavdeep Parhar 31081131c927SNavdeep Parhar if (!strcmp(s, "cong")) { 31091131c927SNavdeep Parhar if (!strcmp(param, "reno")) 31101131c927SNavdeep Parhar os->cong_algo = 0; 31111131c927SNavdeep Parhar else if (!strcmp(param, "tahoe")) 31121131c927SNavdeep Parhar os->cong_algo = 1; 31131131c927SNavdeep Parhar else if (!strcmp(param, "newreno")) 31141131c927SNavdeep Parhar os->cong_algo = 2; 31151131c927SNavdeep Parhar else if (!strcmp(param, "highspeed")) 31161131c927SNavdeep Parhar os->cong_algo = 3; 31171131c927SNavdeep Parhar else { 31181131c927SNavdeep Parhar warnx("unknown congestion algorithm \"%s\".", s); 31191131c927SNavdeep Parhar return (EINVAL); 31201131c927SNavdeep Parhar } 31211131c927SNavdeep Parhar } else if (!strcmp(s, "class")) { 31221131c927SNavdeep Parhar val = -1; 31231131c927SNavdeep Parhar p = str_to_number(param, &val, NULL); 31241131c927SNavdeep Parhar /* (nsched_cls - 1) is spelled 15 here. */ 31251131c927SNavdeep Parhar if (*p || val < 0 || val > 15) { 31261131c927SNavdeep Parhar warnx("invalid scheduling class \"%s\". " 31271131c927SNavdeep Parhar "\"class\" needs an integer value where " 31281131c927SNavdeep Parhar "0 <= value <= 15", param); 31291131c927SNavdeep Parhar return (EINVAL); 31301131c927SNavdeep Parhar } 31311131c927SNavdeep Parhar os->sched_class = val; 31321131c927SNavdeep Parhar } else if (!strcmp(s, "bind") || !strcmp(s, "txq") || 31331131c927SNavdeep Parhar !strcmp(s, "rxq")) { 31341131c927SNavdeep Parhar val = -1; 31351131c927SNavdeep Parhar if (strcmp(param, "random")) { 31361131c927SNavdeep Parhar p = str_to_number(param, &val, NULL); 31371131c927SNavdeep Parhar if (*p || val < 0 || val > 0xffff) { 31381131c927SNavdeep Parhar warnx("invalid queue specification " 31391131c927SNavdeep Parhar "\"%s\". \"%s\" needs an integer" 31401131c927SNavdeep Parhar " value, or \"random\".", 31411131c927SNavdeep Parhar param, s); 31421131c927SNavdeep Parhar return (EINVAL); 31431131c927SNavdeep Parhar } 31441131c927SNavdeep Parhar } 31451131c927SNavdeep Parhar if (!strcmp(s, "bind")) { 31461131c927SNavdeep Parhar os->txq = val; 31471131c927SNavdeep Parhar os->rxq = val; 31481131c927SNavdeep Parhar } else if (!strcmp(s, "txq")) { 31491131c927SNavdeep Parhar os->txq = val; 31501131c927SNavdeep Parhar } else if (!strcmp(s, "rxq")) { 31511131c927SNavdeep Parhar os->rxq = val; 31521131c927SNavdeep Parhar } else { 31531131c927SNavdeep Parhar return (EDOOFUS); 31541131c927SNavdeep Parhar } 31551131c927SNavdeep Parhar } else if (!strcmp(s, "mss")) { 31561131c927SNavdeep Parhar val = -1; 31571131c927SNavdeep Parhar p = str_to_number(param, &val, NULL); 31581131c927SNavdeep Parhar if (*p || val <= 0) { 31591131c927SNavdeep Parhar warnx("invalid MSS specification \"%s\". " 31601131c927SNavdeep Parhar "\"mss\" needs a positive integer value", 31611131c927SNavdeep Parhar param); 31621131c927SNavdeep Parhar return (EINVAL); 31631131c927SNavdeep Parhar } 31641131c927SNavdeep Parhar os->mss = val; 31651131c927SNavdeep Parhar } else { 31661131c927SNavdeep Parhar warnx("unknown settings keyword: \"%s\"", s); 31671131c927SNavdeep Parhar return (EINVAL); 31681131c927SNavdeep Parhar } 31691131c927SNavdeep Parhar } 31701131c927SNavdeep Parhar 31711131c927SNavdeep Parhar return (0); 31721131c927SNavdeep Parhar } 31731131c927SNavdeep Parhar 31741131c927SNavdeep Parhar static int 31751131c927SNavdeep Parhar parse_offload_settings(const char *settings_ro, struct offload_settings *os) 31761131c927SNavdeep Parhar { 31771131c927SNavdeep Parhar const char *ws = " \f\n\r\v\t"; 31781131c927SNavdeep Parhar char *settings, *s, *next; 31791131c927SNavdeep Parhar int rc, nsettings, neg; 31801131c927SNavdeep Parhar static const struct offload_settings default_settings = { 31811131c927SNavdeep Parhar .offload = 0, /* No settings imply !offload */ 31821131c927SNavdeep Parhar .rx_coalesce = -1, 31831131c927SNavdeep Parhar .cong_algo = -1, 31841131c927SNavdeep Parhar .sched_class = -1, 31851131c927SNavdeep Parhar .tstamp = -1, 31861131c927SNavdeep Parhar .sack = -1, 31871131c927SNavdeep Parhar .nagle = -1, 31881131c927SNavdeep Parhar .ecn = -1, 31891131c927SNavdeep Parhar .ddp = -1, 31901131c927SNavdeep Parhar .tls = -1, 31911131c927SNavdeep Parhar .txq = -1, 31921131c927SNavdeep Parhar .rxq = -1, 31931131c927SNavdeep Parhar .mss = -1, 31941131c927SNavdeep Parhar }; 31951131c927SNavdeep Parhar 31961131c927SNavdeep Parhar *os = default_settings; 31971131c927SNavdeep Parhar 31981131c927SNavdeep Parhar next = settings = strdup(settings_ro); 31991131c927SNavdeep Parhar if (settings == NULL) { 32001131c927SNavdeep Parhar warn (NULL); 32011131c927SNavdeep Parhar return (errno); 32021131c927SNavdeep Parhar } 32031131c927SNavdeep Parhar 32041131c927SNavdeep Parhar nsettings = 0; 32051131c927SNavdeep Parhar rc = 0; 32061131c927SNavdeep Parhar neg = 0; 32071131c927SNavdeep Parhar while ((s = strsep(&next, ws)) != NULL) { 32081131c927SNavdeep Parhar if (*s == '\0') 32091131c927SNavdeep Parhar continue; 32101131c927SNavdeep Parhar nsettings++; 32111131c927SNavdeep Parhar rc = parse_offload_settings_word(s, &next, ws, &neg, os); 32121131c927SNavdeep Parhar if (rc != 0) 32131131c927SNavdeep Parhar goto done; 32141131c927SNavdeep Parhar } 32151131c927SNavdeep Parhar if (nsettings == 0) { 32161131c927SNavdeep Parhar warnx("no settings provided"); 32171131c927SNavdeep Parhar rc = EINVAL; 32181131c927SNavdeep Parhar goto done; 32191131c927SNavdeep Parhar } 32201131c927SNavdeep Parhar if (neg > 0) { 32211131c927SNavdeep Parhar warnx("%d stray negation(s) at end of offload settings", neg); 32221131c927SNavdeep Parhar rc = EINVAL; 32231131c927SNavdeep Parhar goto done; 32241131c927SNavdeep Parhar } 32251131c927SNavdeep Parhar done: 32261131c927SNavdeep Parhar free(settings); 32271131c927SNavdeep Parhar return (rc); 32281131c927SNavdeep Parhar } 32291131c927SNavdeep Parhar 32301131c927SNavdeep Parhar static int 32311131c927SNavdeep Parhar isempty_line(char *line, size_t llen) 32321131c927SNavdeep Parhar { 32331131c927SNavdeep Parhar 32341131c927SNavdeep Parhar /* skip leading whitespace */ 32351131c927SNavdeep Parhar while (isspace(*line)) { 32361131c927SNavdeep Parhar line++; 32371131c927SNavdeep Parhar llen--; 32381131c927SNavdeep Parhar } 32391131c927SNavdeep Parhar if (llen == 0 || *line == '#' || *line == '\n') 32401131c927SNavdeep Parhar return (1); 32411131c927SNavdeep Parhar 32421131c927SNavdeep Parhar return (0); 32431131c927SNavdeep Parhar } 32441131c927SNavdeep Parhar 32451131c927SNavdeep Parhar static int 32461131c927SNavdeep Parhar special_offload_rule(char *str) 32471131c927SNavdeep Parhar { 32481131c927SNavdeep Parhar 32491131c927SNavdeep Parhar /* skip leading whitespaces */ 32501131c927SNavdeep Parhar while (isspace(*str)) 32511131c927SNavdeep Parhar str++; 32521131c927SNavdeep Parhar 32531131c927SNavdeep Parhar /* check for special strings: "-", "all", "any" */ 32541131c927SNavdeep Parhar if (*str == '-') { 32551131c927SNavdeep Parhar str++; 32561131c927SNavdeep Parhar } else if (!strncmp(str, "all", 3) || !strncmp(str, "any", 3)) { 32571131c927SNavdeep Parhar str += 3; 32581131c927SNavdeep Parhar } else { 32591131c927SNavdeep Parhar return (0); 32601131c927SNavdeep Parhar } 32611131c927SNavdeep Parhar 32621131c927SNavdeep Parhar /* skip trailing whitespaces */ 32631131c927SNavdeep Parhar while (isspace(*str)) 32641131c927SNavdeep Parhar str++; 32651131c927SNavdeep Parhar 32661131c927SNavdeep Parhar return (*str == '\0'); 32671131c927SNavdeep Parhar } 32681131c927SNavdeep Parhar 32691131c927SNavdeep Parhar /* 32701131c927SNavdeep Parhar * A rule has 3 parts: an open-type, a match expression, and offload settings. 32711131c927SNavdeep Parhar * 32721131c927SNavdeep Parhar * [<open-type>] <expr> => <settings> 32731131c927SNavdeep Parhar */ 32741131c927SNavdeep Parhar static int 32751131c927SNavdeep Parhar parse_offload_policy_line(size_t lno, char *line, size_t llen, pcap_t *pd, 32761131c927SNavdeep Parhar struct offload_rule *r) 32771131c927SNavdeep Parhar { 32781131c927SNavdeep Parhar char *expr, *settings, *s; 32791131c927SNavdeep Parhar 32801131c927SNavdeep Parhar bzero(r, sizeof(*r)); 32811131c927SNavdeep Parhar 32821131c927SNavdeep Parhar /* Skip leading whitespace. */ 32831131c927SNavdeep Parhar while (isspace(*line)) 32841131c927SNavdeep Parhar line++; 32851131c927SNavdeep Parhar /* Trim trailing whitespace */ 32861131c927SNavdeep Parhar s = &line[llen - 1]; 32871131c927SNavdeep Parhar while (isspace(*s)) { 32881131c927SNavdeep Parhar *s-- = '\0'; 32891131c927SNavdeep Parhar llen--; 32901131c927SNavdeep Parhar } 32911131c927SNavdeep Parhar 32921131c927SNavdeep Parhar /* 32931131c927SNavdeep Parhar * First part of the rule: '[X]' where X = A/D/L/P 32941131c927SNavdeep Parhar */ 32951131c927SNavdeep Parhar if (*line++ != '[') { 32961131c927SNavdeep Parhar warnx("missing \"[\" on line %zd", lno); 32971131c927SNavdeep Parhar return (EINVAL); 32981131c927SNavdeep Parhar } 32991131c927SNavdeep Parhar switch (*line) { 33001131c927SNavdeep Parhar case 'A': 33011131c927SNavdeep Parhar case 'D': 33021131c927SNavdeep Parhar case 'L': 33031131c927SNavdeep Parhar case 'P': 33041131c927SNavdeep Parhar r->open_type = *line; 33051131c927SNavdeep Parhar break; 33061131c927SNavdeep Parhar default: 33071131c927SNavdeep Parhar warnx("invalid socket-type \"%c\" on line %zd.", *line, lno); 33081131c927SNavdeep Parhar return (EINVAL); 33091131c927SNavdeep Parhar } 33101131c927SNavdeep Parhar line++; 33111131c927SNavdeep Parhar if (*line++ != ']') { 33121131c927SNavdeep Parhar warnx("missing \"]\" after \"[%c\" on line %zd", 33131131c927SNavdeep Parhar r->open_type, lno); 33141131c927SNavdeep Parhar return (EINVAL); 33151131c927SNavdeep Parhar } 33161131c927SNavdeep Parhar 33171131c927SNavdeep Parhar /* Skip whitespace. */ 33181131c927SNavdeep Parhar while (isspace(*line)) 33191131c927SNavdeep Parhar line++; 33201131c927SNavdeep Parhar 33211131c927SNavdeep Parhar /* 33221131c927SNavdeep Parhar * Rest of the rule: <expr> => <settings> 33231131c927SNavdeep Parhar */ 33241131c927SNavdeep Parhar expr = line; 33251131c927SNavdeep Parhar s = strstr(line, "=>"); 33261131c927SNavdeep Parhar if (s == NULL) 33271131c927SNavdeep Parhar return (EINVAL); 33281131c927SNavdeep Parhar settings = s + 2; 33291131c927SNavdeep Parhar while (isspace(*settings)) 33301131c927SNavdeep Parhar settings++; 33311131c927SNavdeep Parhar *s = '\0'; 33321131c927SNavdeep Parhar 33331131c927SNavdeep Parhar /* 33341131c927SNavdeep Parhar * <expr> is either a special name (all, any) or a pcap-filter(7). 33351131c927SNavdeep Parhar * In case of a special name the bpf_prog stays all-zero. 33361131c927SNavdeep Parhar */ 33371131c927SNavdeep Parhar if (!special_offload_rule(expr)) { 33381131c927SNavdeep Parhar if (pcap_compile(pd, &r->bpf_prog, expr, 1, 33391131c927SNavdeep Parhar PCAP_NETMASK_UNKNOWN) < 0) { 33401131c927SNavdeep Parhar warnx("failed to compile \"%s\" on line %zd: %s", expr, 33411131c927SNavdeep Parhar lno, pcap_geterr(pd)); 33421131c927SNavdeep Parhar return (EINVAL); 33431131c927SNavdeep Parhar } 33441131c927SNavdeep Parhar } 33451131c927SNavdeep Parhar 33461131c927SNavdeep Parhar /* settings to apply on a match. */ 33471131c927SNavdeep Parhar if (parse_offload_settings(settings, &r->settings) != 0) { 33481131c927SNavdeep Parhar warnx("failed to parse offload settings \"%s\" on line %zd", 33491131c927SNavdeep Parhar settings, lno); 33501131c927SNavdeep Parhar pcap_freecode(&r->bpf_prog); 33511131c927SNavdeep Parhar return (EINVAL); 33521131c927SNavdeep Parhar } 33531131c927SNavdeep Parhar 33541131c927SNavdeep Parhar return (0); 33551131c927SNavdeep Parhar 33561131c927SNavdeep Parhar } 33571131c927SNavdeep Parhar 33581131c927SNavdeep Parhar /* 33591131c927SNavdeep Parhar * Note that op itself is not dynamically allocated. 33601131c927SNavdeep Parhar */ 33611131c927SNavdeep Parhar static void 33621131c927SNavdeep Parhar free_offload_policy(struct t4_offload_policy *op) 33631131c927SNavdeep Parhar { 33641131c927SNavdeep Parhar int i; 33651131c927SNavdeep Parhar 33661131c927SNavdeep Parhar for (i = 0; i < op->nrules; i++) { 33671131c927SNavdeep Parhar /* 33681131c927SNavdeep Parhar * pcap_freecode can cope with empty bpf_prog, which is the case 33691131c927SNavdeep Parhar * for an rule that matches on 'any/all/-'. 33701131c927SNavdeep Parhar */ 33711131c927SNavdeep Parhar pcap_freecode(&op->rule[i].bpf_prog); 33721131c927SNavdeep Parhar } 33731131c927SNavdeep Parhar free(op->rule); 33741131c927SNavdeep Parhar op->nrules = 0; 33751131c927SNavdeep Parhar op->rule = NULL; 33761131c927SNavdeep Parhar } 33771131c927SNavdeep Parhar 33781131c927SNavdeep Parhar #define REALLOC_STRIDE 32 33791131c927SNavdeep Parhar 33801131c927SNavdeep Parhar /* 33811131c927SNavdeep Parhar * Fills up op->nrules and op->rule. 33821131c927SNavdeep Parhar */ 33831131c927SNavdeep Parhar static int 33841131c927SNavdeep Parhar parse_offload_policy(const char *fname, struct t4_offload_policy *op) 33851131c927SNavdeep Parhar { 33861131c927SNavdeep Parhar FILE *fp; 33871131c927SNavdeep Parhar char *line; 33881131c927SNavdeep Parhar int lno, maxrules, rc; 33891131c927SNavdeep Parhar size_t lcap, llen; 33901131c927SNavdeep Parhar struct offload_rule *r; 33911131c927SNavdeep Parhar pcap_t *pd; 33921131c927SNavdeep Parhar 33931131c927SNavdeep Parhar fp = fopen(fname, "r"); 33941131c927SNavdeep Parhar if (fp == NULL) { 33951131c927SNavdeep Parhar warn("Unable to open file \"%s\"", fname); 33961131c927SNavdeep Parhar return (errno); 33971131c927SNavdeep Parhar } 33981131c927SNavdeep Parhar pd = pcap_open_dead(DLT_EN10MB, 128); 33991131c927SNavdeep Parhar if (pd == NULL) { 34001131c927SNavdeep Parhar warnx("Failed to open pcap device"); 34011131c927SNavdeep Parhar fclose(fp); 34021131c927SNavdeep Parhar return (EIO); 34031131c927SNavdeep Parhar } 34041131c927SNavdeep Parhar 34051131c927SNavdeep Parhar rc = 0; 34061131c927SNavdeep Parhar lno = 0; 34071131c927SNavdeep Parhar lcap = 0; 34081131c927SNavdeep Parhar maxrules = 0; 34091131c927SNavdeep Parhar op->nrules = 0; 34101131c927SNavdeep Parhar op->rule = NULL; 34111131c927SNavdeep Parhar line = NULL; 34121131c927SNavdeep Parhar 34131131c927SNavdeep Parhar while ((llen = getline(&line, &lcap, fp)) != -1) { 34141131c927SNavdeep Parhar lno++; 34151131c927SNavdeep Parhar 34161131c927SNavdeep Parhar /* Skip empty lines. */ 34171131c927SNavdeep Parhar if (isempty_line(line, llen)) 34181131c927SNavdeep Parhar continue; 34191131c927SNavdeep Parhar 34201131c927SNavdeep Parhar if (op->nrules == maxrules) { 34211131c927SNavdeep Parhar maxrules += REALLOC_STRIDE; 34221131c927SNavdeep Parhar r = realloc(op->rule, 34231131c927SNavdeep Parhar maxrules * sizeof(struct offload_rule)); 34241131c927SNavdeep Parhar if (r == NULL) { 34251131c927SNavdeep Parhar warnx("failed to allocate memory for %d rules", 34261131c927SNavdeep Parhar maxrules); 34271131c927SNavdeep Parhar rc = ENOMEM; 34281131c927SNavdeep Parhar goto done; 34291131c927SNavdeep Parhar } 34301131c927SNavdeep Parhar op->rule = r; 34311131c927SNavdeep Parhar } 34321131c927SNavdeep Parhar 34331131c927SNavdeep Parhar r = &op->rule[op->nrules]; 34341131c927SNavdeep Parhar rc = parse_offload_policy_line(lno, line, llen, pd, r); 34351131c927SNavdeep Parhar if (rc != 0) { 34361131c927SNavdeep Parhar warnx("Error parsing line %d of \"%s\"", lno, fname); 34371131c927SNavdeep Parhar goto done; 34381131c927SNavdeep Parhar } 34391131c927SNavdeep Parhar 34401131c927SNavdeep Parhar op->nrules++; 34411131c927SNavdeep Parhar } 34421131c927SNavdeep Parhar free(line); 34431131c927SNavdeep Parhar 34441131c927SNavdeep Parhar if (!feof(fp)) { 34451131c927SNavdeep Parhar warn("Error while reading from file \"%s\" at line %d", 34461131c927SNavdeep Parhar fname, lno); 34471131c927SNavdeep Parhar rc = errno; 34481131c927SNavdeep Parhar goto done; 34491131c927SNavdeep Parhar } 34501131c927SNavdeep Parhar 34511131c927SNavdeep Parhar if (op->nrules == 0) { 34521131c927SNavdeep Parhar warnx("No valid rules found in \"%s\"", fname); 34531131c927SNavdeep Parhar rc = EINVAL; 34541131c927SNavdeep Parhar } 34551131c927SNavdeep Parhar done: 34561131c927SNavdeep Parhar pcap_close(pd); 34571131c927SNavdeep Parhar fclose(fp); 34581131c927SNavdeep Parhar if (rc != 0) { 34591131c927SNavdeep Parhar free_offload_policy(op); 34601131c927SNavdeep Parhar } 34611131c927SNavdeep Parhar 34621131c927SNavdeep Parhar return (rc); 34631131c927SNavdeep Parhar } 34641131c927SNavdeep Parhar 34651131c927SNavdeep Parhar static int 34661131c927SNavdeep Parhar load_offload_policy(int argc, const char *argv[]) 34671131c927SNavdeep Parhar { 34681131c927SNavdeep Parhar int rc = 0; 34691131c927SNavdeep Parhar const char *fname = argv[0]; 34701131c927SNavdeep Parhar struct t4_offload_policy op = {0}; 34711131c927SNavdeep Parhar 34721131c927SNavdeep Parhar if (argc != 1) { 34731131c927SNavdeep Parhar warnx("incorrect number of arguments."); 34741131c927SNavdeep Parhar return (EINVAL); 34751131c927SNavdeep Parhar } 34761131c927SNavdeep Parhar 34771131c927SNavdeep Parhar if (!strcmp(fname, "clear") || !strcmp(fname, "none")) { 34781131c927SNavdeep Parhar /* op.nrules is 0 and that means clear policy */ 34791131c927SNavdeep Parhar return (doit(CHELSIO_T4_SET_OFLD_POLICY, &op)); 34801131c927SNavdeep Parhar } 34811131c927SNavdeep Parhar 34821131c927SNavdeep Parhar rc = parse_offload_policy(fname, &op); 34831131c927SNavdeep Parhar if (rc != 0) { 34841131c927SNavdeep Parhar /* Error message displayed already */ 34851131c927SNavdeep Parhar return (EINVAL); 34861131c927SNavdeep Parhar } 34871131c927SNavdeep Parhar 34881131c927SNavdeep Parhar rc = doit(CHELSIO_T4_SET_OFLD_POLICY, &op); 34891131c927SNavdeep Parhar free_offload_policy(&op); 34901131c927SNavdeep Parhar 34911131c927SNavdeep Parhar return (rc); 34921131c927SNavdeep Parhar } 34931131c927SNavdeep Parhar 34941131c927SNavdeep Parhar static int 349554912308SNavdeep Parhar run_cmd(int argc, const char *argv[]) 349654912308SNavdeep Parhar { 349754912308SNavdeep Parhar int rc = -1; 349854912308SNavdeep Parhar const char *cmd = argv[0]; 349954912308SNavdeep Parhar 350054912308SNavdeep Parhar /* command */ 350154912308SNavdeep Parhar argc--; 350254912308SNavdeep Parhar argv++; 350354912308SNavdeep Parhar 350454912308SNavdeep Parhar if (!strcmp(cmd, "reg") || !strcmp(cmd, "reg32")) 350554912308SNavdeep Parhar rc = register_io(argc, argv, 4); 350654912308SNavdeep Parhar else if (!strcmp(cmd, "reg64")) 350754912308SNavdeep Parhar rc = register_io(argc, argv, 8); 350854912308SNavdeep Parhar else if (!strcmp(cmd, "regdump")) 350954912308SNavdeep Parhar rc = dump_regs(argc, argv); 351054912308SNavdeep Parhar else if (!strcmp(cmd, "filter")) 351136ea2fe3SNavdeep Parhar rc = filter_cmd(argc, argv, 0); 351254912308SNavdeep Parhar else if (!strcmp(cmd, "context")) 351354912308SNavdeep Parhar rc = get_sge_context(argc, argv); 351454912308SNavdeep Parhar else if (!strcmp(cmd, "loadfw")) 351554912308SNavdeep Parhar rc = loadfw(argc, argv); 351654912308SNavdeep Parhar else if (!strcmp(cmd, "memdump")) 351754912308SNavdeep Parhar rc = memdump(argc, argv); 351854912308SNavdeep Parhar else if (!strcmp(cmd, "tcb")) 351954912308SNavdeep Parhar rc = read_tcb(argc, argv); 352054912308SNavdeep Parhar else if (!strcmp(cmd, "i2c")) 352154912308SNavdeep Parhar rc = read_i2c(argc, argv); 352254912308SNavdeep Parhar else if (!strcmp(cmd, "clearstats")) 352354912308SNavdeep Parhar rc = clearstats(argc, argv); 352454912308SNavdeep Parhar else if (!strcmp(cmd, "tracer")) 352554912308SNavdeep Parhar rc = tracer_cmd(argc, argv); 352654912308SNavdeep Parhar else if (!strcmp(cmd, "modinfo")) 352754912308SNavdeep Parhar rc = modinfo(argc, argv); 352854912308SNavdeep Parhar else if (!strcmp(cmd, "sched-class")) 352954912308SNavdeep Parhar rc = sched_class(argc, argv); 353054912308SNavdeep Parhar else if (!strcmp(cmd, "sched-queue")) 353154912308SNavdeep Parhar rc = sched_queue(argc, argv); 353254912308SNavdeep Parhar else if (!strcmp(cmd, "loadcfg")) 353354912308SNavdeep Parhar rc = loadcfg(argc, argv); 35348f82718fSNavdeep Parhar else if (!strcmp(cmd, "loadboot")) 35358f82718fSNavdeep Parhar rc = loadboot(argc, argv); 35368f82718fSNavdeep Parhar else if (!strcmp(cmd, "loadboot-cfg")) 35378f82718fSNavdeep Parhar rc = loadbootcfg(argc, argv); 3538f856f099SNavdeep Parhar else if (!strcmp(cmd, "dumpstate")) 3539f856f099SNavdeep Parhar rc = dumpstate(argc, argv); 35401131c927SNavdeep Parhar else if (!strcmp(cmd, "policy")) 35411131c927SNavdeep Parhar rc = load_offload_policy(argc, argv); 354236ea2fe3SNavdeep Parhar else if (!strcmp(cmd, "hashfilter")) 354336ea2fe3SNavdeep Parhar rc = filter_cmd(argc, argv, 1); 354454912308SNavdeep Parhar else { 354554912308SNavdeep Parhar rc = EINVAL; 354654912308SNavdeep Parhar warnx("invalid command \"%s\"", cmd); 354754912308SNavdeep Parhar } 354854912308SNavdeep Parhar 354954912308SNavdeep Parhar return (rc); 355054912308SNavdeep Parhar } 355154912308SNavdeep Parhar 355254912308SNavdeep Parhar #define MAX_ARGS 15 355354912308SNavdeep Parhar static int 355454912308SNavdeep Parhar run_cmd_loop(void) 355554912308SNavdeep Parhar { 355654912308SNavdeep Parhar int i, rc = 0; 355754912308SNavdeep Parhar char buffer[128], *buf; 355854912308SNavdeep Parhar const char *args[MAX_ARGS + 1]; 355954912308SNavdeep Parhar 356054912308SNavdeep Parhar /* 356154912308SNavdeep Parhar * Simple loop: displays a "> " prompt and processes any input as a 356254912308SNavdeep Parhar * cxgbetool command. You're supposed to enter only the part after 356354912308SNavdeep Parhar * "cxgbetool t4nexX". Use "quit" or "exit" to exit. 356454912308SNavdeep Parhar */ 356554912308SNavdeep Parhar for (;;) { 356654912308SNavdeep Parhar fprintf(stdout, "> "); 356754912308SNavdeep Parhar fflush(stdout); 356854912308SNavdeep Parhar buf = fgets(buffer, sizeof(buffer), stdin); 356954912308SNavdeep Parhar if (buf == NULL) { 357054912308SNavdeep Parhar if (ferror(stdin)) { 357154912308SNavdeep Parhar warn("stdin error"); 357254912308SNavdeep Parhar rc = errno; /* errno from fgets */ 357354912308SNavdeep Parhar } 357454912308SNavdeep Parhar break; 357554912308SNavdeep Parhar } 357654912308SNavdeep Parhar 357754912308SNavdeep Parhar i = 0; 357854912308SNavdeep Parhar while ((args[i] = strsep(&buf, " \t\n")) != NULL) { 357954912308SNavdeep Parhar if (args[i][0] != 0 && ++i == MAX_ARGS) 358054912308SNavdeep Parhar break; 358154912308SNavdeep Parhar } 358254912308SNavdeep Parhar args[i] = 0; 358354912308SNavdeep Parhar 358454912308SNavdeep Parhar if (i == 0) 358554912308SNavdeep Parhar continue; /* skip empty line */ 358654912308SNavdeep Parhar 358754912308SNavdeep Parhar if (!strcmp(args[0], "quit") || !strcmp(args[0], "exit")) 358854912308SNavdeep Parhar break; 358954912308SNavdeep Parhar 359054912308SNavdeep Parhar rc = run_cmd(i, args); 359154912308SNavdeep Parhar } 359254912308SNavdeep Parhar 359354912308SNavdeep Parhar /* rc normally comes from the last command (not including quit/exit) */ 359454912308SNavdeep Parhar return (rc); 359554912308SNavdeep Parhar } 359654912308SNavdeep Parhar 359754912308SNavdeep Parhar int 359854912308SNavdeep Parhar main(int argc, const char *argv[]) 359954912308SNavdeep Parhar { 360054912308SNavdeep Parhar int rc = -1; 360154912308SNavdeep Parhar 360254912308SNavdeep Parhar progname = argv[0]; 360354912308SNavdeep Parhar 360454912308SNavdeep Parhar if (argc == 2) { 360554912308SNavdeep Parhar if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) { 360654912308SNavdeep Parhar usage(stdout); 360754912308SNavdeep Parhar exit(0); 360854912308SNavdeep Parhar } 360954912308SNavdeep Parhar } 361054912308SNavdeep Parhar 361154912308SNavdeep Parhar if (argc < 3) { 361254912308SNavdeep Parhar usage(stderr); 361354912308SNavdeep Parhar exit(EINVAL); 361454912308SNavdeep Parhar } 361554912308SNavdeep Parhar 361654912308SNavdeep Parhar nexus = argv[1]; 3617*6ba81353SNavdeep Parhar chip_id = nexus[1] - '0'; 361854912308SNavdeep Parhar 361954912308SNavdeep Parhar /* progname and nexus */ 362054912308SNavdeep Parhar argc -= 2; 362154912308SNavdeep Parhar argv += 2; 362254912308SNavdeep Parhar 362354912308SNavdeep Parhar if (argc == 1 && !strcmp(argv[0], "stdio")) 362454912308SNavdeep Parhar rc = run_cmd_loop(); 362554912308SNavdeep Parhar else 362654912308SNavdeep Parhar rc = run_cmd(argc, argv); 362754912308SNavdeep Parhar 362854912308SNavdeep Parhar return (rc); 362954912308SNavdeep Parhar } 3630