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> 36ac02945fSNavdeep Parhar #include <sys/sysctl.h> 3754912308SNavdeep Parhar 3854912308SNavdeep Parhar #include <arpa/inet.h> 3954912308SNavdeep Parhar #include <net/ethernet.h> 4054912308SNavdeep Parhar #include <net/sff8472.h> 4154912308SNavdeep Parhar #include <netinet/in.h> 4254912308SNavdeep Parhar 4354912308SNavdeep Parhar #include <ctype.h> 4454912308SNavdeep Parhar #include <err.h> 4554912308SNavdeep Parhar #include <errno.h> 4654912308SNavdeep Parhar #include <fcntl.h> 4754912308SNavdeep Parhar #include <limits.h> 4854912308SNavdeep Parhar #include <stdint.h> 4954912308SNavdeep Parhar #include <stdio.h> 5054912308SNavdeep Parhar #include <stdlib.h> 5154912308SNavdeep Parhar #include <string.h> 5254912308SNavdeep Parhar #include <unistd.h> 531131c927SNavdeep Parhar #include <pcap.h> 5454912308SNavdeep Parhar 5554912308SNavdeep Parhar #include "t4_ioctl.h" 56ae9b4017SNavdeep Parhar #include "tcb_common.h" 5754912308SNavdeep Parhar 5854912308SNavdeep Parhar #define in_range(val, lo, hi) ( val < 0 || (val <= hi && val >= lo)) 5954912308SNavdeep Parhar #define max(x, y) ((x) > (y) ? (x) : (y)) 6054912308SNavdeep Parhar 6154912308SNavdeep Parhar static const char *progname, *nexus; 62ac02945fSNavdeep Parhar static int chip_id; /* 4 for T4, 5 for T5, and so on. */ 63ac02945fSNavdeep Parhar static int inst; /* instance of nexus device */ 6454912308SNavdeep Parhar 6554912308SNavdeep Parhar struct reg_info { 6654912308SNavdeep Parhar const char *name; 6754912308SNavdeep Parhar uint32_t addr; 6854912308SNavdeep Parhar uint32_t len; 6954912308SNavdeep Parhar }; 7054912308SNavdeep Parhar 7154912308SNavdeep Parhar struct mod_regs { 7254912308SNavdeep Parhar const char *name; 7354912308SNavdeep Parhar const struct reg_info *ri; 7454912308SNavdeep Parhar }; 7554912308SNavdeep Parhar 7654912308SNavdeep Parhar struct field_desc { 7754912308SNavdeep Parhar const char *name; /* Field name */ 7854912308SNavdeep Parhar unsigned short start; /* Start bit position */ 7954912308SNavdeep Parhar unsigned short end; /* End bit position */ 8054912308SNavdeep Parhar unsigned char shift; /* # of low order bits omitted and implicitly 0 */ 8154912308SNavdeep Parhar unsigned char hex; /* Print field in hex instead of decimal */ 8254912308SNavdeep Parhar unsigned char islog2; /* Field contains the base-2 log of the value */ 8354912308SNavdeep Parhar }; 8454912308SNavdeep Parhar 8554912308SNavdeep Parhar #include "reg_defs_t4.c" 8654912308SNavdeep Parhar #include "reg_defs_t5.c" 8754912308SNavdeep Parhar #include "reg_defs_t6.c" 8854912308SNavdeep Parhar #include "reg_defs_t4vf.c" 8954912308SNavdeep Parhar 9054912308SNavdeep Parhar static void 9154912308SNavdeep Parhar usage(FILE *fp) 9254912308SNavdeep Parhar { 9354912308SNavdeep Parhar fprintf(fp, "Usage: %s <nexus> [operation]\n", progname); 9454912308SNavdeep Parhar fprintf(fp, 9554912308SNavdeep Parhar "\tclearstats <port> clear port statistics\n" 96ac02945fSNavdeep Parhar "\tclip hold|release <ip6> hold/release an address\n" 97ac02945fSNavdeep Parhar "\tclip list list the CLIP table\n" 9854912308SNavdeep Parhar "\tcontext <type> <id> show an SGE context\n" 99f856f099SNavdeep Parhar "\tdumpstate <dump.bin> dump chip state\n" 10054912308SNavdeep Parhar "\tfilter <idx> [<param> <val>] ... set a filter\n" 1016ba81353SNavdeep Parhar "\tfilter <idx> delete|clear [prio 1] delete a filter\n" 10254912308SNavdeep Parhar "\tfilter list list all filters\n" 10354912308SNavdeep Parhar "\tfilter mode [<match>] ... get/set global filter mode\n" 10436ea2fe3SNavdeep Parhar "\thashfilter [<param> <val>] ... set a hashfilter\n" 10536ea2fe3SNavdeep Parhar "\thashfilter <idx> delete|clear delete a hashfilter\n" 10636ea2fe3SNavdeep Parhar "\thashfilter list list all hashfilters\n" 107038148c1SNavdeep Parhar "\thashfilter mode [<match>] ... get/set global hashfilter mode\n" 10854912308SNavdeep Parhar "\ti2c <port> <devaddr> <addr> [<len>] read from i2c device\n" 1098f82718fSNavdeep Parhar "\tloadboot <bi.bin> [pf|offset <val>] install boot image\n" 1108f82718fSNavdeep Parhar "\tloadboot clear [pf|offset <val>] remove boot image\n" 1118f82718fSNavdeep Parhar "\tloadboot-cfg <bc.bin> install boot config\n" 1128f82718fSNavdeep Parhar "\tloadboot-cfg clear remove boot config\n" 11354912308SNavdeep Parhar "\tloadcfg <fw-config.txt> install configuration file\n" 11454912308SNavdeep Parhar "\tloadcfg clear remove configuration file\n" 11554912308SNavdeep Parhar "\tloadfw <fw-image.bin> install firmware\n" 11654912308SNavdeep Parhar "\tmemdump <addr> <len> dump a memory range\n" 11754912308SNavdeep Parhar "\tmodinfo <port> [raw] optics/cable information\n" 1181131c927SNavdeep Parhar "\tpolicy <policy.txt> install offload policy\n" 1191131c927SNavdeep Parhar "\tpolicy clear remove offload policy\n" 12054912308SNavdeep Parhar "\treg <address>[=<val>] read/write register\n" 12154912308SNavdeep Parhar "\treg64 <address>[=<val>] read/write 64 bit register\n" 12254912308SNavdeep Parhar "\tregdump [<module>] ... dump registers\n" 12354912308SNavdeep Parhar "\tsched-class params <param> <val> .. configure TX scheduler class\n" 12454912308SNavdeep Parhar "\tsched-queue <port> <queue> <class> bind NIC queues to TX Scheduling class\n" 12554912308SNavdeep Parhar "\tstdio interactive mode\n" 12654912308SNavdeep Parhar "\ttcb <tid> read TCB\n" 12754912308SNavdeep Parhar "\ttracer <idx> tx<n>|rx<n> set and enable a tracer\n" 12854912308SNavdeep Parhar "\ttracer <idx> disable|enable disable or enable a tracer\n" 12954912308SNavdeep Parhar "\ttracer list list all tracers\n" 13054912308SNavdeep Parhar ); 13154912308SNavdeep Parhar } 13254912308SNavdeep Parhar 13354912308SNavdeep Parhar static inline unsigned int 13454912308SNavdeep Parhar get_card_vers(unsigned int version) 13554912308SNavdeep Parhar { 13654912308SNavdeep Parhar return (version & 0x3ff); 13754912308SNavdeep Parhar } 13854912308SNavdeep Parhar 13954912308SNavdeep Parhar static int 14054912308SNavdeep Parhar real_doit(unsigned long cmd, void *data, const char *cmdstr) 14154912308SNavdeep Parhar { 14254912308SNavdeep Parhar static int fd = -1; 14354912308SNavdeep Parhar int rc = 0; 14454912308SNavdeep Parhar 14554912308SNavdeep Parhar if (fd == -1) { 14654912308SNavdeep Parhar char buf[64]; 14754912308SNavdeep Parhar 14854912308SNavdeep Parhar snprintf(buf, sizeof(buf), "/dev/%s", nexus); 14954912308SNavdeep Parhar if ((fd = open(buf, O_RDWR)) < 0) { 15054912308SNavdeep Parhar warn("open(%s)", nexus); 15154912308SNavdeep Parhar rc = errno; 15254912308SNavdeep Parhar return (rc); 15354912308SNavdeep Parhar } 15454912308SNavdeep Parhar } 15554912308SNavdeep Parhar 15654912308SNavdeep Parhar rc = ioctl(fd, cmd, data); 15754912308SNavdeep Parhar if (rc < 0) { 15854912308SNavdeep Parhar warn("%s", cmdstr); 15954912308SNavdeep Parhar rc = errno; 16054912308SNavdeep Parhar } 16154912308SNavdeep Parhar 16254912308SNavdeep Parhar return (rc); 16354912308SNavdeep Parhar } 16454912308SNavdeep Parhar #define doit(x, y) real_doit(x, y, #x) 16554912308SNavdeep Parhar 16654912308SNavdeep Parhar static char * 16754912308SNavdeep Parhar str_to_number(const char *s, long *val, long long *vall) 16854912308SNavdeep Parhar { 16954912308SNavdeep Parhar char *p; 17054912308SNavdeep Parhar 17154912308SNavdeep Parhar if (vall) 17254912308SNavdeep Parhar *vall = strtoll(s, &p, 0); 17354912308SNavdeep Parhar else if (val) 17454912308SNavdeep Parhar *val = strtol(s, &p, 0); 17554912308SNavdeep Parhar else 17654912308SNavdeep Parhar p = NULL; 17754912308SNavdeep Parhar 17854912308SNavdeep Parhar return (p); 17954912308SNavdeep Parhar } 18054912308SNavdeep Parhar 18154912308SNavdeep Parhar static int 18254912308SNavdeep Parhar read_reg(long addr, int size, long long *val) 18354912308SNavdeep Parhar { 18454912308SNavdeep Parhar struct t4_reg reg; 18554912308SNavdeep Parhar int rc; 18654912308SNavdeep Parhar 18754912308SNavdeep Parhar reg.addr = (uint32_t) addr; 18854912308SNavdeep Parhar reg.size = (uint32_t) size; 18954912308SNavdeep Parhar reg.val = 0; 19054912308SNavdeep Parhar 19154912308SNavdeep Parhar rc = doit(CHELSIO_T4_GETREG, ®); 19254912308SNavdeep Parhar 19354912308SNavdeep Parhar *val = reg.val; 19454912308SNavdeep Parhar 19554912308SNavdeep Parhar return (rc); 19654912308SNavdeep Parhar } 19754912308SNavdeep Parhar 19854912308SNavdeep Parhar static int 19954912308SNavdeep Parhar write_reg(long addr, int size, long long val) 20054912308SNavdeep Parhar { 20154912308SNavdeep Parhar struct t4_reg reg; 20254912308SNavdeep Parhar 20354912308SNavdeep Parhar reg.addr = (uint32_t) addr; 20454912308SNavdeep Parhar reg.size = (uint32_t) size; 20554912308SNavdeep Parhar reg.val = (uint64_t) val; 20654912308SNavdeep Parhar 20754912308SNavdeep Parhar return doit(CHELSIO_T4_SETREG, ®); 20854912308SNavdeep Parhar } 20954912308SNavdeep Parhar 21054912308SNavdeep Parhar static int 21154912308SNavdeep Parhar register_io(int argc, const char *argv[], int size) 21254912308SNavdeep Parhar { 21354912308SNavdeep Parhar char *p, *v; 21454912308SNavdeep Parhar long addr; 21554912308SNavdeep Parhar long long val; 21654912308SNavdeep Parhar int w = 0, rc; 21754912308SNavdeep Parhar 21854912308SNavdeep Parhar if (argc == 1) { 21954912308SNavdeep Parhar /* <reg> OR <reg>=<value> */ 22054912308SNavdeep Parhar 22154912308SNavdeep Parhar p = str_to_number(argv[0], &addr, NULL); 22254912308SNavdeep Parhar if (*p) { 22354912308SNavdeep Parhar if (*p != '=') { 22454912308SNavdeep Parhar warnx("invalid register \"%s\"", argv[0]); 22554912308SNavdeep Parhar return (EINVAL); 22654912308SNavdeep Parhar } 22754912308SNavdeep Parhar 22854912308SNavdeep Parhar w = 1; 22954912308SNavdeep Parhar v = p + 1; 23054912308SNavdeep Parhar p = str_to_number(v, NULL, &val); 23154912308SNavdeep Parhar 23254912308SNavdeep Parhar if (*p) { 23354912308SNavdeep Parhar warnx("invalid value \"%s\"", v); 23454912308SNavdeep Parhar return (EINVAL); 23554912308SNavdeep Parhar } 23654912308SNavdeep Parhar } 23754912308SNavdeep Parhar 23854912308SNavdeep Parhar } else if (argc == 2) { 23954912308SNavdeep Parhar /* <reg> <value> */ 24054912308SNavdeep Parhar 24154912308SNavdeep Parhar w = 1; 24254912308SNavdeep Parhar 24354912308SNavdeep Parhar p = str_to_number(argv[0], &addr, NULL); 24454912308SNavdeep Parhar if (*p) { 24554912308SNavdeep Parhar warnx("invalid register \"%s\"", argv[0]); 24654912308SNavdeep Parhar return (EINVAL); 24754912308SNavdeep Parhar } 24854912308SNavdeep Parhar 24954912308SNavdeep Parhar p = str_to_number(argv[1], NULL, &val); 25054912308SNavdeep Parhar if (*p) { 25154912308SNavdeep Parhar warnx("invalid value \"%s\"", argv[1]); 25254912308SNavdeep Parhar return (EINVAL); 25354912308SNavdeep Parhar } 25454912308SNavdeep Parhar } else { 25554912308SNavdeep Parhar warnx("reg: invalid number of arguments (%d)", argc); 25654912308SNavdeep Parhar return (EINVAL); 25754912308SNavdeep Parhar } 25854912308SNavdeep Parhar 25954912308SNavdeep Parhar if (w) 26054912308SNavdeep Parhar rc = write_reg(addr, size, val); 26154912308SNavdeep Parhar else { 26254912308SNavdeep Parhar rc = read_reg(addr, size, &val); 26354912308SNavdeep Parhar if (rc == 0) 26454912308SNavdeep Parhar printf("0x%llx [%llu]\n", val, val); 26554912308SNavdeep Parhar } 26654912308SNavdeep Parhar 26754912308SNavdeep Parhar return (rc); 26854912308SNavdeep Parhar } 26954912308SNavdeep Parhar 27054912308SNavdeep Parhar static inline uint32_t 27154912308SNavdeep Parhar xtract(uint32_t val, int shift, int len) 27254912308SNavdeep Parhar { 27354912308SNavdeep Parhar return (val >> shift) & ((1 << len) - 1); 27454912308SNavdeep Parhar } 27554912308SNavdeep Parhar 27654912308SNavdeep Parhar static int 27754912308SNavdeep Parhar dump_block_regs(const struct reg_info *reg_array, const uint32_t *regs) 27854912308SNavdeep Parhar { 27954912308SNavdeep Parhar uint32_t reg_val = 0; 28054912308SNavdeep Parhar 28154912308SNavdeep Parhar for ( ; reg_array->name; ++reg_array) 28254912308SNavdeep Parhar if (!reg_array->len) { 28354912308SNavdeep Parhar reg_val = regs[reg_array->addr / 4]; 28454912308SNavdeep Parhar printf("[%#7x] %-47s %#-10x %u\n", reg_array->addr, 28554912308SNavdeep Parhar reg_array->name, reg_val, reg_val); 28654912308SNavdeep Parhar } else { 28754912308SNavdeep Parhar uint32_t v = xtract(reg_val, reg_array->addr, 28854912308SNavdeep Parhar reg_array->len); 28954912308SNavdeep Parhar 29054912308SNavdeep Parhar printf(" %*u:%u %-47s %#-10x %u\n", 29154912308SNavdeep Parhar reg_array->addr < 10 ? 3 : 2, 29254912308SNavdeep Parhar reg_array->addr + reg_array->len - 1, 29354912308SNavdeep Parhar reg_array->addr, reg_array->name, v, v); 29454912308SNavdeep Parhar } 29554912308SNavdeep Parhar 29654912308SNavdeep Parhar return (1); 29754912308SNavdeep Parhar } 29854912308SNavdeep Parhar 29954912308SNavdeep Parhar static int 30054912308SNavdeep Parhar dump_regs_table(int argc, const char *argv[], const uint32_t *regs, 30154912308SNavdeep Parhar const struct mod_regs *modtab, int nmodules) 30254912308SNavdeep Parhar { 30354912308SNavdeep Parhar int i, j, match; 30454912308SNavdeep Parhar 30554912308SNavdeep Parhar for (i = 0; i < argc; i++) { 30654912308SNavdeep Parhar for (j = 0; j < nmodules; j++) { 30754912308SNavdeep Parhar if (!strcmp(argv[i], modtab[j].name)) 30854912308SNavdeep Parhar break; 30954912308SNavdeep Parhar } 31054912308SNavdeep Parhar 31154912308SNavdeep Parhar if (j == nmodules) { 31254912308SNavdeep Parhar warnx("invalid register block \"%s\"", argv[i]); 31354912308SNavdeep Parhar fprintf(stderr, "\nAvailable blocks:"); 31454912308SNavdeep Parhar for ( ; nmodules; nmodules--, modtab++) 31554912308SNavdeep Parhar fprintf(stderr, " %s", modtab->name); 31654912308SNavdeep Parhar fprintf(stderr, "\n"); 31754912308SNavdeep Parhar return (EINVAL); 31854912308SNavdeep Parhar } 31954912308SNavdeep Parhar } 32054912308SNavdeep Parhar 32154912308SNavdeep Parhar for ( ; nmodules; nmodules--, modtab++) { 32254912308SNavdeep Parhar 32354912308SNavdeep Parhar match = argc == 0 ? 1 : 0; 32454912308SNavdeep Parhar for (i = 0; !match && i < argc; i++) { 32554912308SNavdeep Parhar if (!strcmp(argv[i], modtab->name)) 32654912308SNavdeep Parhar match = 1; 32754912308SNavdeep Parhar } 32854912308SNavdeep Parhar 32954912308SNavdeep Parhar if (match) 33054912308SNavdeep Parhar dump_block_regs(modtab->ri, regs); 33154912308SNavdeep Parhar } 33254912308SNavdeep Parhar 33354912308SNavdeep Parhar return (0); 33454912308SNavdeep Parhar } 33554912308SNavdeep Parhar 33654912308SNavdeep Parhar #define T4_MODREGS(name) { #name, t4_##name##_regs } 33754912308SNavdeep Parhar static int 33854912308SNavdeep Parhar dump_regs_t4(int argc, const char *argv[], const uint32_t *regs) 33954912308SNavdeep Parhar { 34054912308SNavdeep Parhar static struct mod_regs t4_mod[] = { 34154912308SNavdeep Parhar T4_MODREGS(sge), 34254912308SNavdeep Parhar { "pci", t4_pcie_regs }, 34354912308SNavdeep Parhar T4_MODREGS(dbg), 34454912308SNavdeep Parhar T4_MODREGS(mc), 34554912308SNavdeep Parhar T4_MODREGS(ma), 34654912308SNavdeep Parhar { "edc0", t4_edc_0_regs }, 34754912308SNavdeep Parhar { "edc1", t4_edc_1_regs }, 34854912308SNavdeep Parhar T4_MODREGS(cim), 34954912308SNavdeep Parhar T4_MODREGS(tp), 35054912308SNavdeep Parhar T4_MODREGS(ulp_rx), 35154912308SNavdeep Parhar T4_MODREGS(ulp_tx), 35254912308SNavdeep Parhar { "pmrx", t4_pm_rx_regs }, 35354912308SNavdeep Parhar { "pmtx", t4_pm_tx_regs }, 35454912308SNavdeep Parhar T4_MODREGS(mps), 35554912308SNavdeep Parhar { "cplsw", t4_cpl_switch_regs }, 35654912308SNavdeep Parhar T4_MODREGS(smb), 35754912308SNavdeep Parhar { "i2c", t4_i2cm_regs }, 35854912308SNavdeep Parhar T4_MODREGS(mi), 35954912308SNavdeep Parhar T4_MODREGS(uart), 36054912308SNavdeep Parhar T4_MODREGS(pmu), 36154912308SNavdeep Parhar T4_MODREGS(sf), 36254912308SNavdeep Parhar T4_MODREGS(pl), 36354912308SNavdeep Parhar T4_MODREGS(le), 36454912308SNavdeep Parhar T4_MODREGS(ncsi), 36554912308SNavdeep Parhar T4_MODREGS(xgmac) 36654912308SNavdeep Parhar }; 36754912308SNavdeep Parhar 36854912308SNavdeep Parhar return dump_regs_table(argc, argv, regs, t4_mod, nitems(t4_mod)); 36954912308SNavdeep Parhar } 37054912308SNavdeep Parhar #undef T4_MODREGS 37154912308SNavdeep Parhar 37254912308SNavdeep Parhar #define T5_MODREGS(name) { #name, t5_##name##_regs } 37354912308SNavdeep Parhar static int 37454912308SNavdeep Parhar dump_regs_t5(int argc, const char *argv[], const uint32_t *regs) 37554912308SNavdeep Parhar { 37654912308SNavdeep Parhar static struct mod_regs t5_mod[] = { 37754912308SNavdeep Parhar T5_MODREGS(sge), 37854912308SNavdeep Parhar { "pci", t5_pcie_regs }, 37954912308SNavdeep Parhar T5_MODREGS(dbg), 38054912308SNavdeep Parhar { "mc0", t5_mc_0_regs }, 38154912308SNavdeep Parhar { "mc1", t5_mc_1_regs }, 38254912308SNavdeep Parhar T5_MODREGS(ma), 38354912308SNavdeep Parhar { "edc0", t5_edc_t50_regs }, 38454912308SNavdeep Parhar { "edc1", t5_edc_t51_regs }, 38554912308SNavdeep Parhar T5_MODREGS(cim), 38654912308SNavdeep Parhar T5_MODREGS(tp), 38754912308SNavdeep Parhar { "ulprx", t5_ulp_rx_regs }, 38854912308SNavdeep Parhar { "ulptx", t5_ulp_tx_regs }, 38954912308SNavdeep Parhar { "pmrx", t5_pm_rx_regs }, 39054912308SNavdeep Parhar { "pmtx", t5_pm_tx_regs }, 39154912308SNavdeep Parhar T5_MODREGS(mps), 39254912308SNavdeep Parhar { "cplsw", t5_cpl_switch_regs }, 39354912308SNavdeep Parhar T5_MODREGS(smb), 39454912308SNavdeep Parhar { "i2c", t5_i2cm_regs }, 39554912308SNavdeep Parhar T5_MODREGS(mi), 39654912308SNavdeep Parhar T5_MODREGS(uart), 39754912308SNavdeep Parhar T5_MODREGS(pmu), 39854912308SNavdeep Parhar T5_MODREGS(sf), 39954912308SNavdeep Parhar T5_MODREGS(pl), 40054912308SNavdeep Parhar T5_MODREGS(le), 40154912308SNavdeep Parhar T5_MODREGS(ncsi), 40254912308SNavdeep Parhar T5_MODREGS(mac), 40354912308SNavdeep Parhar { "hma", t5_hma_t5_regs } 40454912308SNavdeep Parhar }; 40554912308SNavdeep Parhar 40654912308SNavdeep Parhar return dump_regs_table(argc, argv, regs, t5_mod, nitems(t5_mod)); 40754912308SNavdeep Parhar } 40854912308SNavdeep Parhar #undef T5_MODREGS 40954912308SNavdeep Parhar 41054912308SNavdeep Parhar #define T6_MODREGS(name) { #name, t6_##name##_regs } 41154912308SNavdeep Parhar static int 41254912308SNavdeep Parhar dump_regs_t6(int argc, const char *argv[], const uint32_t *regs) 41354912308SNavdeep Parhar { 41454912308SNavdeep Parhar static struct mod_regs t6_mod[] = { 41554912308SNavdeep Parhar T6_MODREGS(sge), 41654912308SNavdeep Parhar { "pci", t6_pcie_regs }, 41754912308SNavdeep Parhar T6_MODREGS(dbg), 41854912308SNavdeep Parhar { "mc0", t6_mc_0_regs }, 41954912308SNavdeep Parhar T6_MODREGS(ma), 42054912308SNavdeep Parhar { "edc0", t6_edc_t60_regs }, 42154912308SNavdeep Parhar { "edc1", t6_edc_t61_regs }, 42254912308SNavdeep Parhar T6_MODREGS(cim), 42354912308SNavdeep Parhar T6_MODREGS(tp), 42454912308SNavdeep Parhar { "ulprx", t6_ulp_rx_regs }, 42554912308SNavdeep Parhar { "ulptx", t6_ulp_tx_regs }, 42654912308SNavdeep Parhar { "pmrx", t6_pm_rx_regs }, 42754912308SNavdeep Parhar { "pmtx", t6_pm_tx_regs }, 42854912308SNavdeep Parhar T6_MODREGS(mps), 42954912308SNavdeep Parhar { "cplsw", t6_cpl_switch_regs }, 43054912308SNavdeep Parhar T6_MODREGS(smb), 43154912308SNavdeep Parhar { "i2c", t6_i2cm_regs }, 43254912308SNavdeep Parhar T6_MODREGS(mi), 43354912308SNavdeep Parhar T6_MODREGS(uart), 43454912308SNavdeep Parhar T6_MODREGS(pmu), 43554912308SNavdeep Parhar T6_MODREGS(sf), 43654912308SNavdeep Parhar T6_MODREGS(pl), 43754912308SNavdeep Parhar T6_MODREGS(le), 43854912308SNavdeep Parhar T6_MODREGS(ncsi), 43954912308SNavdeep Parhar T6_MODREGS(mac), 44054912308SNavdeep Parhar { "hma", t6_hma_t6_regs } 44154912308SNavdeep Parhar }; 44254912308SNavdeep Parhar 44354912308SNavdeep Parhar return dump_regs_table(argc, argv, regs, t6_mod, nitems(t6_mod)); 44454912308SNavdeep Parhar } 44554912308SNavdeep Parhar #undef T6_MODREGS 44654912308SNavdeep Parhar 44754912308SNavdeep Parhar static int 44854912308SNavdeep Parhar dump_regs_t4vf(int argc, const char *argv[], const uint32_t *regs) 44954912308SNavdeep Parhar { 45054912308SNavdeep Parhar static struct mod_regs t4vf_mod[] = { 45154912308SNavdeep Parhar { "sge", t4vf_sge_regs }, 45254912308SNavdeep Parhar { "mps", t4vf_mps_regs }, 45354912308SNavdeep Parhar { "pl", t4vf_pl_regs }, 45454912308SNavdeep Parhar { "mbdata", t4vf_mbdata_regs }, 45554912308SNavdeep Parhar { "cim", t4vf_cim_regs }, 45654912308SNavdeep Parhar }; 45754912308SNavdeep Parhar 45854912308SNavdeep Parhar return dump_regs_table(argc, argv, regs, t4vf_mod, nitems(t4vf_mod)); 45954912308SNavdeep Parhar } 46054912308SNavdeep Parhar 46154912308SNavdeep Parhar static int 46254912308SNavdeep Parhar dump_regs_t5vf(int argc, const char *argv[], const uint32_t *regs) 46354912308SNavdeep Parhar { 46454912308SNavdeep Parhar static struct mod_regs t5vf_mod[] = { 46554912308SNavdeep Parhar { "sge", t5vf_sge_regs }, 46654912308SNavdeep Parhar { "mps", t4vf_mps_regs }, 46754912308SNavdeep Parhar { "pl", t5vf_pl_regs }, 46854912308SNavdeep Parhar { "mbdata", t4vf_mbdata_regs }, 46954912308SNavdeep Parhar { "cim", t4vf_cim_regs }, 47054912308SNavdeep Parhar }; 47154912308SNavdeep Parhar 47254912308SNavdeep Parhar return dump_regs_table(argc, argv, regs, t5vf_mod, nitems(t5vf_mod)); 47354912308SNavdeep Parhar } 47454912308SNavdeep Parhar 47554912308SNavdeep Parhar static int 47654912308SNavdeep Parhar dump_regs_t6vf(int argc, const char *argv[], const uint32_t *regs) 47754912308SNavdeep Parhar { 47854912308SNavdeep Parhar static struct mod_regs t6vf_mod[] = { 47954912308SNavdeep Parhar { "sge", t5vf_sge_regs }, 48054912308SNavdeep Parhar { "mps", t4vf_mps_regs }, 48154912308SNavdeep Parhar { "pl", t6vf_pl_regs }, 48254912308SNavdeep Parhar { "mbdata", t4vf_mbdata_regs }, 48354912308SNavdeep Parhar { "cim", t4vf_cim_regs }, 48454912308SNavdeep Parhar }; 48554912308SNavdeep Parhar 48654912308SNavdeep Parhar return dump_regs_table(argc, argv, regs, t6vf_mod, nitems(t6vf_mod)); 48754912308SNavdeep Parhar } 48854912308SNavdeep Parhar 48954912308SNavdeep Parhar static int 49054912308SNavdeep Parhar dump_regs(int argc, const char *argv[]) 49154912308SNavdeep Parhar { 49254912308SNavdeep Parhar int vers, revision, rc; 49354912308SNavdeep Parhar struct t4_regdump regs; 49454912308SNavdeep Parhar uint32_t len; 49554912308SNavdeep Parhar 49654912308SNavdeep Parhar len = max(T4_REGDUMP_SIZE, T5_REGDUMP_SIZE); 49754912308SNavdeep Parhar regs.data = calloc(1, len); 49854912308SNavdeep Parhar if (regs.data == NULL) { 49954912308SNavdeep Parhar warnc(ENOMEM, "regdump"); 50054912308SNavdeep Parhar return (ENOMEM); 50154912308SNavdeep Parhar } 50254912308SNavdeep Parhar 50354912308SNavdeep Parhar regs.len = len; 50454912308SNavdeep Parhar rc = doit(CHELSIO_T4_REGDUMP, ®s); 50554912308SNavdeep Parhar if (rc != 0) 50654912308SNavdeep Parhar return (rc); 50754912308SNavdeep Parhar 50854912308SNavdeep Parhar vers = get_card_vers(regs.version); 50954912308SNavdeep Parhar revision = (regs.version >> 10) & 0x3f; 51054912308SNavdeep Parhar 51154912308SNavdeep Parhar if (vers == 4) { 51254912308SNavdeep Parhar if (revision == 0x3f) 51354912308SNavdeep Parhar rc = dump_regs_t4vf(argc, argv, regs.data); 51454912308SNavdeep Parhar else 51554912308SNavdeep Parhar rc = dump_regs_t4(argc, argv, regs.data); 51654912308SNavdeep Parhar } else if (vers == 5) { 51754912308SNavdeep Parhar if (revision == 0x3f) 51854912308SNavdeep Parhar rc = dump_regs_t5vf(argc, argv, regs.data); 51954912308SNavdeep Parhar else 52054912308SNavdeep Parhar rc = dump_regs_t5(argc, argv, regs.data); 52154912308SNavdeep Parhar } else if (vers == 6) { 52254912308SNavdeep Parhar if (revision == 0x3f) 52354912308SNavdeep Parhar rc = dump_regs_t6vf(argc, argv, regs.data); 52454912308SNavdeep Parhar else 52554912308SNavdeep Parhar rc = dump_regs_t6(argc, argv, regs.data); 52654912308SNavdeep Parhar } else { 52754912308SNavdeep Parhar warnx("%s (type %d, rev %d) is not a known card.", 52854912308SNavdeep Parhar nexus, vers, revision); 52954912308SNavdeep Parhar return (ENOTSUP); 53054912308SNavdeep Parhar } 53154912308SNavdeep Parhar 53254912308SNavdeep Parhar free(regs.data); 53354912308SNavdeep Parhar return (rc); 53454912308SNavdeep Parhar } 53554912308SNavdeep Parhar 53654912308SNavdeep Parhar static void 53754912308SNavdeep Parhar do_show_info_header(uint32_t mode) 53854912308SNavdeep Parhar { 53954912308SNavdeep Parhar uint32_t i; 54054912308SNavdeep Parhar 54154912308SNavdeep Parhar printf("%4s %8s", "Idx", "Hits"); 54254912308SNavdeep Parhar for (i = T4_FILTER_FCoE; i <= T4_FILTER_IP_FRAGMENT; i <<= 1) { 54354912308SNavdeep Parhar switch (mode & i) { 54454912308SNavdeep Parhar case T4_FILTER_FCoE: 54554912308SNavdeep Parhar printf(" FCoE"); 54654912308SNavdeep Parhar break; 54754912308SNavdeep Parhar 54854912308SNavdeep Parhar case T4_FILTER_PORT: 54954912308SNavdeep Parhar printf(" Port"); 55054912308SNavdeep Parhar break; 55154912308SNavdeep Parhar 55254912308SNavdeep Parhar case T4_FILTER_VNIC: 55354912308SNavdeep Parhar if (mode & T4_FILTER_IC_VNIC) 55454912308SNavdeep Parhar printf(" VFvld:PF:VF"); 55554912308SNavdeep Parhar else 55654912308SNavdeep Parhar printf(" vld:oVLAN"); 55754912308SNavdeep Parhar break; 55854912308SNavdeep Parhar 55954912308SNavdeep Parhar case T4_FILTER_VLAN: 56054912308SNavdeep Parhar printf(" vld:VLAN"); 56154912308SNavdeep Parhar break; 56254912308SNavdeep Parhar 56354912308SNavdeep Parhar case T4_FILTER_IP_TOS: 56454912308SNavdeep Parhar printf(" TOS"); 56554912308SNavdeep Parhar break; 56654912308SNavdeep Parhar 56754912308SNavdeep Parhar case T4_FILTER_IP_PROTO: 56854912308SNavdeep Parhar printf(" Prot"); 56954912308SNavdeep Parhar break; 57054912308SNavdeep Parhar 57154912308SNavdeep Parhar case T4_FILTER_ETH_TYPE: 57254912308SNavdeep Parhar printf(" EthType"); 57354912308SNavdeep Parhar break; 57454912308SNavdeep Parhar 57554912308SNavdeep Parhar case T4_FILTER_MAC_IDX: 57654912308SNavdeep Parhar printf(" MACIdx"); 57754912308SNavdeep Parhar break; 57854912308SNavdeep Parhar 57954912308SNavdeep Parhar case T4_FILTER_MPS_HIT_TYPE: 58054912308SNavdeep Parhar printf(" MPS"); 58154912308SNavdeep Parhar break; 58254912308SNavdeep Parhar 58354912308SNavdeep Parhar case T4_FILTER_IP_FRAGMENT: 58454912308SNavdeep Parhar printf(" Frag"); 58554912308SNavdeep Parhar break; 58654912308SNavdeep Parhar 58754912308SNavdeep Parhar default: 58854912308SNavdeep Parhar /* compressed filter field not enabled */ 58954912308SNavdeep Parhar break; 59054912308SNavdeep Parhar } 59154912308SNavdeep Parhar } 59254912308SNavdeep Parhar printf(" %20s %20s %9s %9s %s\n", 59354912308SNavdeep Parhar "DIP", "SIP", "DPORT", "SPORT", "Action"); 59454912308SNavdeep Parhar } 59554912308SNavdeep Parhar 59654912308SNavdeep Parhar /* 59754912308SNavdeep Parhar * Parse an argument sub-vector as a { <parameter name> <value>[:<mask>] } 59854912308SNavdeep Parhar * ordered tuple. If the parameter name in the argument sub-vector does not 59954912308SNavdeep Parhar * match the passed in parameter name, then a zero is returned for the 60054912308SNavdeep Parhar * function and no parsing is performed. If there is a match, then the value 60154912308SNavdeep Parhar * and optional mask are parsed and returned in the provided return value 60254912308SNavdeep Parhar * pointers. If no optional mask is specified, then a default mask of all 1s 60354912308SNavdeep Parhar * will be returned. 60454912308SNavdeep Parhar * 60554912308SNavdeep Parhar * An error in parsing the value[:mask] will result in an error message and 60654912308SNavdeep Parhar * program termination. 60754912308SNavdeep Parhar */ 60854912308SNavdeep Parhar static int 60954912308SNavdeep Parhar parse_val_mask(const char *param, const char *args[], uint32_t *val, 61036ea2fe3SNavdeep Parhar uint32_t *mask, int hashfilter) 61154912308SNavdeep Parhar { 612a12a06faSNavdeep Parhar long l; 61354912308SNavdeep Parhar char *p; 61454912308SNavdeep Parhar 61554912308SNavdeep Parhar if (strcmp(param, args[0]) != 0) 61654912308SNavdeep Parhar return (EINVAL); 61754912308SNavdeep Parhar 618a12a06faSNavdeep Parhar p = str_to_number(args[1], &l, NULL); 619a12a06faSNavdeep Parhar if (l >= 0 && l <= UINT32_MAX) { 620a12a06faSNavdeep Parhar *val = (uint32_t)l; 62154912308SNavdeep Parhar if (p > args[1]) { 62254912308SNavdeep Parhar if (p[0] == 0) { 62354912308SNavdeep Parhar *mask = ~0; 62454912308SNavdeep Parhar return (0); 62554912308SNavdeep Parhar } 62654912308SNavdeep Parhar 62754912308SNavdeep Parhar if (p[0] == ':' && p[1] != 0) { 62836ea2fe3SNavdeep Parhar if (hashfilter) { 62936ea2fe3SNavdeep Parhar warnx("param %s: mask not allowed for " 63036ea2fe3SNavdeep Parhar "hashfilter or nat params", param); 63136ea2fe3SNavdeep Parhar return (EINVAL); 63236ea2fe3SNavdeep Parhar } 633a12a06faSNavdeep Parhar p = str_to_number(p + 1, &l, NULL); 634a12a06faSNavdeep Parhar if (l >= 0 && l <= UINT32_MAX && p[0] == 0) { 635a12a06faSNavdeep Parhar *mask = (uint32_t)l; 63654912308SNavdeep Parhar return (0); 637a12a06faSNavdeep Parhar } 638a12a06faSNavdeep Parhar } 63954912308SNavdeep Parhar } 64054912308SNavdeep Parhar } 64154912308SNavdeep Parhar 64254912308SNavdeep Parhar warnx("parameter \"%s\" has bad \"value[:mask]\" %s", 64354912308SNavdeep Parhar args[0], args[1]); 64454912308SNavdeep Parhar 64554912308SNavdeep Parhar return (EINVAL); 64654912308SNavdeep Parhar } 64754912308SNavdeep Parhar 64854912308SNavdeep Parhar /* 64954912308SNavdeep Parhar * Parse an argument sub-vector as a { <parameter name> <addr>[/<mask>] } 65054912308SNavdeep Parhar * ordered tuple. If the parameter name in the argument sub-vector does not 65154912308SNavdeep Parhar * match the passed in parameter name, then a zero is returned for the 65254912308SNavdeep Parhar * function and no parsing is performed. If there is a match, then the value 65354912308SNavdeep Parhar * and optional mask are parsed and returned in the provided return value 65454912308SNavdeep Parhar * pointers. If no optional mask is specified, then a default mask of all 1s 65554912308SNavdeep Parhar * will be returned. 65654912308SNavdeep Parhar * 65754912308SNavdeep Parhar * The value return parameter "afp" is used to specify the expected address 65854912308SNavdeep Parhar * family -- IPv4 or IPv6 -- of the address[/mask] and return its actual 65954912308SNavdeep Parhar * format. A passed in value of AF_UNSPEC indicates that either IPv4 or IPv6 66054912308SNavdeep Parhar * is acceptable; AF_INET means that only IPv4 addresses are acceptable; and 66154912308SNavdeep Parhar * AF_INET6 means that only IPv6 are acceptable. AF_INET is returned for IPv4 66254912308SNavdeep Parhar * and AF_INET6 for IPv6 addresses, respectively. IPv4 address/mask pairs are 66354912308SNavdeep Parhar * returned in the first four bytes of the address and mask return values with 66454912308SNavdeep Parhar * the address A.B.C.D returned with { A, B, C, D } returned in addresses { 0, 66554912308SNavdeep Parhar * 1, 2, 3}, respectively. 66654912308SNavdeep Parhar * 66754912308SNavdeep Parhar * An error in parsing the value[:mask] will result in an error message and 66854912308SNavdeep Parhar * program termination. 66954912308SNavdeep Parhar */ 67054912308SNavdeep Parhar static int 67154912308SNavdeep Parhar parse_ipaddr(const char *param, const char *args[], int *afp, uint8_t addr[], 67236ea2fe3SNavdeep Parhar uint8_t mask[], int maskless) 67354912308SNavdeep Parhar { 67454912308SNavdeep Parhar const char *colon, *afn; 67554912308SNavdeep Parhar char *slash; 67654912308SNavdeep Parhar uint8_t *m; 67754912308SNavdeep Parhar int af, ret; 67854912308SNavdeep Parhar unsigned int masksize; 67954912308SNavdeep Parhar 68054912308SNavdeep Parhar /* 68154912308SNavdeep Parhar * Is this our parameter? 68254912308SNavdeep Parhar */ 68354912308SNavdeep Parhar if (strcmp(param, args[0]) != 0) 68454912308SNavdeep Parhar return (EINVAL); 68554912308SNavdeep Parhar 68654912308SNavdeep Parhar /* 68754912308SNavdeep Parhar * Fundamental IPv4 versus IPv6 selection. 68854912308SNavdeep Parhar */ 68954912308SNavdeep Parhar colon = strchr(args[1], ':'); 69054912308SNavdeep Parhar if (!colon) { 69154912308SNavdeep Parhar afn = "IPv4"; 69254912308SNavdeep Parhar af = AF_INET; 69354912308SNavdeep Parhar masksize = 32; 69454912308SNavdeep Parhar } else { 69554912308SNavdeep Parhar afn = "IPv6"; 69654912308SNavdeep Parhar af = AF_INET6; 69754912308SNavdeep Parhar masksize = 128; 69854912308SNavdeep Parhar } 69954912308SNavdeep Parhar if (*afp == AF_UNSPEC) 70054912308SNavdeep Parhar *afp = af; 70154912308SNavdeep Parhar else if (*afp != af) { 70254912308SNavdeep Parhar warnx("address %s is not of expected family %s", 70354912308SNavdeep Parhar args[1], *afp == AF_INET ? "IP" : "IPv6"); 70454912308SNavdeep Parhar return (EINVAL); 70554912308SNavdeep Parhar } 70654912308SNavdeep Parhar 70754912308SNavdeep Parhar /* 70854912308SNavdeep Parhar * Parse address (temporarily stripping off any "/mask" 70954912308SNavdeep Parhar * specification). 71054912308SNavdeep Parhar */ 71154912308SNavdeep Parhar slash = strchr(args[1], '/'); 71254912308SNavdeep Parhar if (slash) 71354912308SNavdeep Parhar *slash = 0; 71454912308SNavdeep Parhar ret = inet_pton(af, args[1], addr); 71554912308SNavdeep Parhar if (slash) 71654912308SNavdeep Parhar *slash = '/'; 71754912308SNavdeep Parhar if (ret <= 0) { 71854912308SNavdeep Parhar warnx("Cannot parse %s %s address %s", param, afn, args[1]); 71954912308SNavdeep Parhar return (EINVAL); 72054912308SNavdeep Parhar } 72154912308SNavdeep Parhar 72254912308SNavdeep Parhar /* 72354912308SNavdeep Parhar * Parse optional mask specification. 72454912308SNavdeep Parhar */ 72554912308SNavdeep Parhar if (slash) { 72654912308SNavdeep Parhar char *p; 72754912308SNavdeep Parhar unsigned int prefix = strtoul(slash + 1, &p, 10); 72854912308SNavdeep Parhar 72936ea2fe3SNavdeep Parhar if (maskless) { 73036ea2fe3SNavdeep Parhar warnx("mask cannot be provided for maskless specification"); 73136ea2fe3SNavdeep Parhar return (EINVAL); 73236ea2fe3SNavdeep Parhar } 73336ea2fe3SNavdeep Parhar 73454912308SNavdeep Parhar if (p == slash + 1) { 73554912308SNavdeep Parhar warnx("missing address prefix for %s", param); 73654912308SNavdeep Parhar return (EINVAL); 73754912308SNavdeep Parhar } 73854912308SNavdeep Parhar if (*p) { 73954912308SNavdeep Parhar warnx("%s is not a valid address prefix", slash + 1); 74054912308SNavdeep Parhar return (EINVAL); 74154912308SNavdeep Parhar } 74254912308SNavdeep Parhar if (prefix > masksize) { 74354912308SNavdeep Parhar warnx("prefix %u is too long for an %s address", 74454912308SNavdeep Parhar prefix, afn); 74554912308SNavdeep Parhar return (EINVAL); 74654912308SNavdeep Parhar } 74754912308SNavdeep Parhar memset(mask, 0, masksize / 8); 74854912308SNavdeep Parhar masksize = prefix; 74954912308SNavdeep Parhar } 75054912308SNavdeep Parhar 75136ea2fe3SNavdeep Parhar if (mask != NULL) { 75254912308SNavdeep Parhar /* 75354912308SNavdeep Parhar * Fill in mask. 75454912308SNavdeep Parhar */ 75554912308SNavdeep Parhar for (m = mask; masksize >= 8; m++, masksize -= 8) 75654912308SNavdeep Parhar *m = ~0; 75754912308SNavdeep Parhar if (masksize) 75854912308SNavdeep Parhar *m = ~0 << (8 - masksize); 75936ea2fe3SNavdeep Parhar } 76054912308SNavdeep Parhar 76154912308SNavdeep Parhar return (0); 76254912308SNavdeep Parhar } 76354912308SNavdeep Parhar 76454912308SNavdeep Parhar /* 76554912308SNavdeep Parhar * Parse an argument sub-vector as a { <parameter name> <value> } ordered 76654912308SNavdeep Parhar * tuple. If the parameter name in the argument sub-vector does not match the 76754912308SNavdeep Parhar * passed in parameter name, then a zero is returned for the function and no 76854912308SNavdeep Parhar * parsing is performed. If there is a match, then the value is parsed and 76954912308SNavdeep Parhar * returned in the provided return value pointer. 77054912308SNavdeep Parhar */ 77154912308SNavdeep Parhar static int 77254912308SNavdeep Parhar parse_val(const char *param, const char *args[], uint32_t *val) 77354912308SNavdeep Parhar { 77454912308SNavdeep Parhar char *p; 775a12a06faSNavdeep Parhar long l; 77654912308SNavdeep Parhar 77754912308SNavdeep Parhar if (strcmp(param, args[0]) != 0) 77854912308SNavdeep Parhar return (EINVAL); 77954912308SNavdeep Parhar 780a12a06faSNavdeep Parhar p = str_to_number(args[1], &l, NULL); 781a12a06faSNavdeep Parhar if (*p || l < 0 || l > UINT32_MAX) { 78254912308SNavdeep Parhar warnx("parameter \"%s\" has bad \"value\" %s", args[0], args[1]); 78354912308SNavdeep Parhar return (EINVAL); 78454912308SNavdeep Parhar } 78554912308SNavdeep Parhar 786a12a06faSNavdeep Parhar *val = (uint32_t)l; 787a12a06faSNavdeep Parhar return (0); 788a12a06faSNavdeep Parhar } 789a12a06faSNavdeep Parhar 79054912308SNavdeep Parhar static void 79154912308SNavdeep Parhar filters_show_ipaddr(int type, uint8_t *addr, uint8_t *addrm) 79254912308SNavdeep Parhar { 79354912308SNavdeep Parhar int noctets, octet; 79454912308SNavdeep Parhar 79554912308SNavdeep Parhar printf(" "); 79654912308SNavdeep Parhar if (type == 0) { 79754912308SNavdeep Parhar noctets = 4; 79854912308SNavdeep Parhar printf("%3s", " "); 79954912308SNavdeep Parhar } else 80054912308SNavdeep Parhar noctets = 16; 80154912308SNavdeep Parhar 80254912308SNavdeep Parhar for (octet = 0; octet < noctets; octet++) 80354912308SNavdeep Parhar printf("%02x", addr[octet]); 80454912308SNavdeep Parhar printf("/"); 80554912308SNavdeep Parhar for (octet = 0; octet < noctets; octet++) 80654912308SNavdeep Parhar printf("%02x", addrm[octet]); 80754912308SNavdeep Parhar } 80854912308SNavdeep Parhar 80954912308SNavdeep Parhar static void 81054912308SNavdeep Parhar do_show_one_filter_info(struct t4_filter *t, uint32_t mode) 81154912308SNavdeep Parhar { 81254912308SNavdeep Parhar uint32_t i; 81354912308SNavdeep Parhar 81454912308SNavdeep Parhar printf("%4d", t->idx); 81554912308SNavdeep Parhar if (t->hits == UINT64_MAX) 81654912308SNavdeep Parhar printf(" %8s", "-"); 81754912308SNavdeep Parhar else 81854912308SNavdeep Parhar printf(" %8ju", t->hits); 81954912308SNavdeep Parhar 82054912308SNavdeep Parhar /* 82154912308SNavdeep Parhar * Compressed header portion of filter. 82254912308SNavdeep Parhar */ 82354912308SNavdeep Parhar for (i = T4_FILTER_FCoE; i <= T4_FILTER_IP_FRAGMENT; i <<= 1) { 82454912308SNavdeep Parhar switch (mode & i) { 82554912308SNavdeep Parhar case T4_FILTER_FCoE: 82654912308SNavdeep Parhar printf(" %1d/%1d", t->fs.val.fcoe, t->fs.mask.fcoe); 82754912308SNavdeep Parhar break; 82854912308SNavdeep Parhar 82954912308SNavdeep Parhar case T4_FILTER_PORT: 83054912308SNavdeep Parhar printf(" %1d/%1d", t->fs.val.iport, t->fs.mask.iport); 83154912308SNavdeep Parhar break; 83254912308SNavdeep Parhar 83354912308SNavdeep Parhar case T4_FILTER_VNIC: 83454912308SNavdeep Parhar if (mode & T4_FILTER_IC_VNIC) { 83554912308SNavdeep Parhar printf(" %1d:%1x:%02x/%1d:%1x:%02x", 83654912308SNavdeep Parhar t->fs.val.pfvf_vld, 83754912308SNavdeep Parhar (t->fs.val.vnic >> 13) & 0x7, 83854912308SNavdeep Parhar t->fs.val.vnic & 0x1fff, 83954912308SNavdeep Parhar t->fs.mask.pfvf_vld, 84054912308SNavdeep Parhar (t->fs.mask.vnic >> 13) & 0x7, 84154912308SNavdeep Parhar t->fs.mask.vnic & 0x1fff); 84254912308SNavdeep Parhar } else { 84354912308SNavdeep Parhar printf(" %1d:%04x/%1d:%04x", 84454912308SNavdeep Parhar t->fs.val.ovlan_vld, t->fs.val.vnic, 84554912308SNavdeep Parhar t->fs.mask.ovlan_vld, t->fs.mask.vnic); 84654912308SNavdeep Parhar } 84754912308SNavdeep Parhar break; 84854912308SNavdeep Parhar 84954912308SNavdeep Parhar case T4_FILTER_VLAN: 85054912308SNavdeep Parhar printf(" %1d:%04x/%1d:%04x", 85154912308SNavdeep Parhar t->fs.val.vlan_vld, t->fs.val.vlan, 85254912308SNavdeep Parhar t->fs.mask.vlan_vld, t->fs.mask.vlan); 85354912308SNavdeep Parhar break; 85454912308SNavdeep Parhar 85554912308SNavdeep Parhar case T4_FILTER_IP_TOS: 85654912308SNavdeep Parhar printf(" %02x/%02x", t->fs.val.tos, t->fs.mask.tos); 85754912308SNavdeep Parhar break; 85854912308SNavdeep Parhar 85954912308SNavdeep Parhar case T4_FILTER_IP_PROTO: 86054912308SNavdeep Parhar printf(" %02x/%02x", t->fs.val.proto, t->fs.mask.proto); 86154912308SNavdeep Parhar break; 86254912308SNavdeep Parhar 86354912308SNavdeep Parhar case T4_FILTER_ETH_TYPE: 86454912308SNavdeep Parhar printf(" %04x/%04x", t->fs.val.ethtype, 86554912308SNavdeep Parhar t->fs.mask.ethtype); 86654912308SNavdeep Parhar break; 86754912308SNavdeep Parhar 86854912308SNavdeep Parhar case T4_FILTER_MAC_IDX: 86954912308SNavdeep Parhar printf(" %03x/%03x", t->fs.val.macidx, 87054912308SNavdeep Parhar t->fs.mask.macidx); 87154912308SNavdeep Parhar break; 87254912308SNavdeep Parhar 87354912308SNavdeep Parhar case T4_FILTER_MPS_HIT_TYPE: 87454912308SNavdeep Parhar printf(" %1x/%1x", t->fs.val.matchtype, 87554912308SNavdeep Parhar t->fs.mask.matchtype); 87654912308SNavdeep Parhar break; 87754912308SNavdeep Parhar 87854912308SNavdeep Parhar case T4_FILTER_IP_FRAGMENT: 87954912308SNavdeep Parhar printf(" %1d/%1d", t->fs.val.frag, t->fs.mask.frag); 88054912308SNavdeep Parhar break; 88154912308SNavdeep Parhar 88254912308SNavdeep Parhar default: 88354912308SNavdeep Parhar /* compressed filter field not enabled */ 88454912308SNavdeep Parhar break; 88554912308SNavdeep Parhar } 88654912308SNavdeep Parhar } 88754912308SNavdeep Parhar 88854912308SNavdeep Parhar /* 88954912308SNavdeep Parhar * Fixed portion of filter. 89054912308SNavdeep Parhar */ 89154912308SNavdeep Parhar filters_show_ipaddr(t->fs.type, t->fs.val.dip, t->fs.mask.dip); 89254912308SNavdeep Parhar filters_show_ipaddr(t->fs.type, t->fs.val.sip, t->fs.mask.sip); 89354912308SNavdeep Parhar printf(" %04x/%04x %04x/%04x", 89454912308SNavdeep Parhar t->fs.val.dport, t->fs.mask.dport, 89554912308SNavdeep Parhar t->fs.val.sport, t->fs.mask.sport); 89654912308SNavdeep Parhar 89754912308SNavdeep Parhar /* 89854912308SNavdeep Parhar * Variable length filter action. 89954912308SNavdeep Parhar */ 90054912308SNavdeep Parhar if (t->fs.action == FILTER_DROP) 90154912308SNavdeep Parhar printf(" Drop"); 90254912308SNavdeep Parhar else if (t->fs.action == FILTER_SWITCH) { 90354912308SNavdeep Parhar printf(" Switch: port=%d", t->fs.eport); 90454912308SNavdeep Parhar if (t->fs.newdmac) 90554912308SNavdeep Parhar printf( 90654912308SNavdeep Parhar ", dmac=%02x:%02x:%02x:%02x:%02x:%02x " 90754912308SNavdeep Parhar ", l2tidx=%d", 90854912308SNavdeep Parhar t->fs.dmac[0], t->fs.dmac[1], 90954912308SNavdeep Parhar t->fs.dmac[2], t->fs.dmac[3], 91054912308SNavdeep Parhar t->fs.dmac[4], t->fs.dmac[5], 91154912308SNavdeep Parhar t->l2tidx); 91254912308SNavdeep Parhar if (t->fs.newsmac) 91354912308SNavdeep Parhar printf( 91454912308SNavdeep Parhar ", smac=%02x:%02x:%02x:%02x:%02x:%02x " 91554912308SNavdeep Parhar ", smtidx=%d", 91654912308SNavdeep Parhar t->fs.smac[0], t->fs.smac[1], 91754912308SNavdeep Parhar t->fs.smac[2], t->fs.smac[3], 91854912308SNavdeep Parhar t->fs.smac[4], t->fs.smac[5], 91954912308SNavdeep Parhar t->smtidx); 92054912308SNavdeep Parhar if (t->fs.newvlan == VLAN_REMOVE) 92154912308SNavdeep Parhar printf(", vlan=none"); 92254912308SNavdeep Parhar else if (t->fs.newvlan == VLAN_INSERT) 92354912308SNavdeep Parhar printf(", vlan=insert(%x)", t->fs.vlan); 92454912308SNavdeep Parhar else if (t->fs.newvlan == VLAN_REWRITE) 92554912308SNavdeep Parhar printf(", vlan=rewrite(%x)", t->fs.vlan); 92654912308SNavdeep Parhar } else { 92754912308SNavdeep Parhar printf(" Pass: Q="); 92854912308SNavdeep Parhar if (t->fs.dirsteer == 0) { 92954912308SNavdeep Parhar printf("RSS"); 93054912308SNavdeep Parhar if (t->fs.maskhash) 9319edef078SNavdeep Parhar printf("(region %d)", t->fs.iq << 1); 93254912308SNavdeep Parhar } else { 93354912308SNavdeep Parhar printf("%d", t->fs.iq); 93454912308SNavdeep Parhar if (t->fs.dirsteerhash == 0) 93554912308SNavdeep Parhar printf("(QID)"); 93654912308SNavdeep Parhar else 93754912308SNavdeep Parhar printf("(hash)"); 93854912308SNavdeep Parhar } 93954912308SNavdeep Parhar } 9406ba81353SNavdeep Parhar if (chip_id <= 5 && t->fs.prio) 94154912308SNavdeep Parhar printf(" Prio"); 94254912308SNavdeep Parhar if (t->fs.rpttid) 94354912308SNavdeep Parhar printf(" RptTID"); 94454912308SNavdeep Parhar printf("\n"); 94554912308SNavdeep Parhar } 94654912308SNavdeep Parhar 94754912308SNavdeep Parhar static int 94836ea2fe3SNavdeep Parhar show_filters(int hash) 94954912308SNavdeep Parhar { 9506ba81353SNavdeep Parhar uint32_t mode = 0, header, hpfilter = 0; 95154912308SNavdeep Parhar struct t4_filter t; 95254912308SNavdeep Parhar int rc; 95354912308SNavdeep Parhar 95454912308SNavdeep Parhar /* Get the global filter mode first */ 95554912308SNavdeep Parhar rc = doit(CHELSIO_T4_GET_FILTER_MODE, &mode); 95654912308SNavdeep Parhar if (rc != 0) 95754912308SNavdeep Parhar return (rc); 95854912308SNavdeep Parhar 9596ba81353SNavdeep Parhar if (!hash && chip_id >= 6) { 9606ba81353SNavdeep Parhar header = 0; 9616ba81353SNavdeep Parhar bzero(&t, sizeof (t)); 9626ba81353SNavdeep Parhar t.idx = 0; 9636ba81353SNavdeep Parhar t.fs.hash = 0; 9646ba81353SNavdeep Parhar t.fs.prio = 1; 9656ba81353SNavdeep Parhar for (t.idx = 0; ; t.idx++) { 9666ba81353SNavdeep Parhar rc = doit(CHELSIO_T4_GET_FILTER, &t); 9676ba81353SNavdeep Parhar if (rc != 0 || t.idx == 0xffffffff) 9686ba81353SNavdeep Parhar break; 9696ba81353SNavdeep Parhar 9706ba81353SNavdeep Parhar if (!header) { 9716ba81353SNavdeep Parhar printf("High Priority TCAM Region:\n"); 9726ba81353SNavdeep Parhar do_show_info_header(mode); 9736ba81353SNavdeep Parhar header = 1; 9746ba81353SNavdeep Parhar hpfilter = 1; 9756ba81353SNavdeep Parhar } 9766ba81353SNavdeep Parhar do_show_one_filter_info(&t, mode); 9776ba81353SNavdeep Parhar } 9786ba81353SNavdeep Parhar } 9796ba81353SNavdeep Parhar 9806ba81353SNavdeep Parhar header = 0; 9816ba81353SNavdeep Parhar bzero(&t, sizeof (t)); 98254912308SNavdeep Parhar t.idx = 0; 98336ea2fe3SNavdeep Parhar t.fs.hash = hash; 98454912308SNavdeep Parhar for (t.idx = 0; ; t.idx++) { 98554912308SNavdeep Parhar rc = doit(CHELSIO_T4_GET_FILTER, &t); 98654912308SNavdeep Parhar if (rc != 0 || t.idx == 0xffffffff) 98754912308SNavdeep Parhar break; 98854912308SNavdeep Parhar 98954912308SNavdeep Parhar if (!header) { 9906ba81353SNavdeep Parhar if (hpfilter) 9916ba81353SNavdeep Parhar printf("\nNormal Priority TCAM Region:\n"); 99254912308SNavdeep Parhar do_show_info_header(mode); 99354912308SNavdeep Parhar header = 1; 99454912308SNavdeep Parhar } 99554912308SNavdeep Parhar do_show_one_filter_info(&t, mode); 9966ba81353SNavdeep Parhar } 99754912308SNavdeep Parhar 99854912308SNavdeep Parhar return (rc); 99954912308SNavdeep Parhar } 100054912308SNavdeep Parhar 100154912308SNavdeep Parhar static int 100236ea2fe3SNavdeep Parhar get_filter_mode(int hashfilter) 100354912308SNavdeep Parhar { 100436ea2fe3SNavdeep Parhar uint32_t mode = hashfilter; 100554912308SNavdeep Parhar int rc; 100654912308SNavdeep Parhar 100754912308SNavdeep Parhar rc = doit(CHELSIO_T4_GET_FILTER_MODE, &mode); 100854912308SNavdeep Parhar if (rc != 0) 100954912308SNavdeep Parhar return (rc); 101054912308SNavdeep Parhar 101154912308SNavdeep Parhar if (mode & T4_FILTER_IPv4) 101254912308SNavdeep Parhar printf("ipv4 "); 101354912308SNavdeep Parhar 101454912308SNavdeep Parhar if (mode & T4_FILTER_IPv6) 101554912308SNavdeep Parhar printf("ipv6 "); 101654912308SNavdeep Parhar 101754912308SNavdeep Parhar if (mode & T4_FILTER_IP_SADDR) 101854912308SNavdeep Parhar printf("sip "); 101954912308SNavdeep Parhar 102054912308SNavdeep Parhar if (mode & T4_FILTER_IP_DADDR) 102154912308SNavdeep Parhar printf("dip "); 102254912308SNavdeep Parhar 102354912308SNavdeep Parhar if (mode & T4_FILTER_IP_SPORT) 102454912308SNavdeep Parhar printf("sport "); 102554912308SNavdeep Parhar 102654912308SNavdeep Parhar if (mode & T4_FILTER_IP_DPORT) 102754912308SNavdeep Parhar printf("dport "); 102854912308SNavdeep Parhar 102954912308SNavdeep Parhar if (mode & T4_FILTER_IP_FRAGMENT) 103054912308SNavdeep Parhar printf("frag "); 103154912308SNavdeep Parhar 103254912308SNavdeep Parhar if (mode & T4_FILTER_MPS_HIT_TYPE) 103354912308SNavdeep Parhar printf("matchtype "); 103454912308SNavdeep Parhar 103554912308SNavdeep Parhar if (mode & T4_FILTER_MAC_IDX) 103654912308SNavdeep Parhar printf("macidx "); 103754912308SNavdeep Parhar 103854912308SNavdeep Parhar if (mode & T4_FILTER_ETH_TYPE) 103954912308SNavdeep Parhar printf("ethtype "); 104054912308SNavdeep Parhar 104154912308SNavdeep Parhar if (mode & T4_FILTER_IP_PROTO) 104254912308SNavdeep Parhar printf("proto "); 104354912308SNavdeep Parhar 104454912308SNavdeep Parhar if (mode & T4_FILTER_IP_TOS) 104554912308SNavdeep Parhar printf("tos "); 104654912308SNavdeep Parhar 104754912308SNavdeep Parhar if (mode & T4_FILTER_VLAN) 104854912308SNavdeep Parhar printf("vlan "); 104954912308SNavdeep Parhar 105054912308SNavdeep Parhar if (mode & T4_FILTER_VNIC) { 105154912308SNavdeep Parhar if (mode & T4_FILTER_IC_VNIC) 105254912308SNavdeep Parhar printf("vnic_id "); 1053038148c1SNavdeep Parhar else if (mode & T4_FILTER_IC_ENCAP) 1054038148c1SNavdeep Parhar printf("encap "); 105554912308SNavdeep Parhar else 105654912308SNavdeep Parhar printf("ovlan "); 105754912308SNavdeep Parhar } 105854912308SNavdeep Parhar 105954912308SNavdeep Parhar if (mode & T4_FILTER_PORT) 106054912308SNavdeep Parhar printf("iport "); 106154912308SNavdeep Parhar 106254912308SNavdeep Parhar if (mode & T4_FILTER_FCoE) 106354912308SNavdeep Parhar printf("fcoe "); 106454912308SNavdeep Parhar 106554912308SNavdeep Parhar printf("\n"); 106654912308SNavdeep Parhar 106754912308SNavdeep Parhar return (0); 106854912308SNavdeep Parhar } 106954912308SNavdeep Parhar 107054912308SNavdeep Parhar static int 1071038148c1SNavdeep Parhar set_filter_mode(int argc, const char *argv[], int hashfilter) 107254912308SNavdeep Parhar { 107354912308SNavdeep Parhar uint32_t mode = 0; 1074038148c1SNavdeep Parhar int vnic = 0, ovlan = 0, invalid = 0; 107554912308SNavdeep Parhar 107654912308SNavdeep Parhar for (; argc; argc--, argv++) { 1077038148c1SNavdeep Parhar if (!strcmp(argv[0], "ipv4") || !strcmp(argv[0], "ipv6") || 1078038148c1SNavdeep Parhar !strcmp(argv[0], "sip") || !strcmp(argv[0], "dip") || 1079038148c1SNavdeep Parhar !strcmp(argv[0], "sport") || !strcmp(argv[0], "dport")) { 1080038148c1SNavdeep Parhar /* These are always available and enabled. */ 1081038148c1SNavdeep Parhar continue; 1082038148c1SNavdeep Parhar } else if (!strcmp(argv[0], "frag")) 108354912308SNavdeep Parhar mode |= T4_FILTER_IP_FRAGMENT; 1084038148c1SNavdeep Parhar else if (!strcmp(argv[0], "matchtype")) 108554912308SNavdeep Parhar mode |= T4_FILTER_MPS_HIT_TYPE; 1086038148c1SNavdeep Parhar else if (!strcmp(argv[0], "macidx")) 108754912308SNavdeep Parhar mode |= T4_FILTER_MAC_IDX; 1088038148c1SNavdeep Parhar else if (!strcmp(argv[0], "ethtype")) 108954912308SNavdeep Parhar mode |= T4_FILTER_ETH_TYPE; 1090038148c1SNavdeep Parhar else if (!strcmp(argv[0], "proto")) 109154912308SNavdeep Parhar mode |= T4_FILTER_IP_PROTO; 1092038148c1SNavdeep Parhar else if (!strcmp(argv[0], "tos")) 109354912308SNavdeep Parhar mode |= T4_FILTER_IP_TOS; 1094038148c1SNavdeep Parhar else if (!strcmp(argv[0], "vlan")) 109554912308SNavdeep Parhar mode |= T4_FILTER_VLAN; 1096038148c1SNavdeep Parhar else if (!strcmp(argv[0], "ovlan")) { 109754912308SNavdeep Parhar mode |= T4_FILTER_VNIC; 1098038148c1SNavdeep Parhar ovlan = 1; 1099038148c1SNavdeep Parhar } else if (!strcmp(argv[0], "vnic_id")) { 110054912308SNavdeep Parhar mode |= T4_FILTER_VNIC; 110154912308SNavdeep Parhar mode |= T4_FILTER_IC_VNIC; 1102038148c1SNavdeep Parhar vnic = 1; 110354912308SNavdeep Parhar } 1104038148c1SNavdeep Parhar #ifdef notyet 1105038148c1SNavdeep Parhar else if (!strcmp(argv[0], "encap")) { 1106038148c1SNavdeep Parhar mode |= T4_FILTER_VNIC; 1107038148c1SNavdeep Parhar mode |= T4_FILTER_IC_ENCAP; 1108038148c1SNavdeep Parhar encap = 1; 1109038148c1SNavdeep Parhar } 1110038148c1SNavdeep Parhar #endif 1111038148c1SNavdeep Parhar else if (!strcmp(argv[0], "iport")) 111254912308SNavdeep Parhar mode |= T4_FILTER_PORT; 1113038148c1SNavdeep Parhar else if (!strcmp(argv[0], "fcoe")) 111454912308SNavdeep Parhar mode |= T4_FILTER_FCoE; 1115038148c1SNavdeep Parhar else { 1116038148c1SNavdeep Parhar warnx("\"%s\" is not valid while setting filter mode.", 1117038148c1SNavdeep Parhar argv[0]); 1118038148c1SNavdeep Parhar invalid++; 1119038148c1SNavdeep Parhar } 112054912308SNavdeep Parhar } 112154912308SNavdeep Parhar 1122038148c1SNavdeep Parhar if (vnic + ovlan > 1) { 112354912308SNavdeep Parhar warnx("\"vnic_id\" and \"ovlan\" are mutually exclusive."); 1124038148c1SNavdeep Parhar invalid++; 112554912308SNavdeep Parhar } 112654912308SNavdeep Parhar 1127038148c1SNavdeep Parhar if (invalid > 0) 1128038148c1SNavdeep Parhar return (EINVAL); 1129038148c1SNavdeep Parhar 1130038148c1SNavdeep Parhar if (hashfilter) 1131038148c1SNavdeep Parhar return doit(CHELSIO_T4_SET_FILTER_MASK, &mode); 1132038148c1SNavdeep Parhar else 113354912308SNavdeep Parhar return doit(CHELSIO_T4_SET_FILTER_MODE, &mode); 113454912308SNavdeep Parhar } 113554912308SNavdeep Parhar 113654912308SNavdeep Parhar static int 11376ba81353SNavdeep Parhar del_filter(uint32_t idx, int prio, int hashfilter) 113854912308SNavdeep Parhar { 113954912308SNavdeep Parhar struct t4_filter t; 114054912308SNavdeep Parhar 11416ba81353SNavdeep Parhar t.fs.prio = prio; 114236ea2fe3SNavdeep Parhar t.fs.hash = hashfilter; 114354912308SNavdeep Parhar t.idx = idx; 114454912308SNavdeep Parhar 114554912308SNavdeep Parhar return doit(CHELSIO_T4_DEL_FILTER, &t); 114654912308SNavdeep Parhar } 114754912308SNavdeep Parhar 11482293e221SNavdeep Parhar #define MAX_VLANID (4095) 11492293e221SNavdeep Parhar 115054912308SNavdeep Parhar static int 115136ea2fe3SNavdeep Parhar set_filter(uint32_t idx, int argc, const char *argv[], int hash) 115254912308SNavdeep Parhar { 115336ea2fe3SNavdeep Parhar int rc, af = AF_UNSPEC, start_arg = 0; 115454912308SNavdeep Parhar struct t4_filter t; 115554912308SNavdeep Parhar 115654912308SNavdeep Parhar if (argc < 2) { 115754912308SNavdeep Parhar warnc(EINVAL, "%s", __func__); 115854912308SNavdeep Parhar return (EINVAL); 115954912308SNavdeep Parhar }; 116054912308SNavdeep Parhar bzero(&t, sizeof (t)); 116154912308SNavdeep Parhar t.idx = idx; 116254912308SNavdeep Parhar t.fs.hitcnts = 1; 116336ea2fe3SNavdeep Parhar t.fs.hash = hash; 116454912308SNavdeep Parhar 116554912308SNavdeep Parhar for (start_arg = 0; start_arg + 2 <= argc; start_arg += 2) { 116654912308SNavdeep Parhar const char **args = &argv[start_arg]; 116754912308SNavdeep Parhar uint32_t val, mask; 116854912308SNavdeep Parhar 116954912308SNavdeep Parhar if (!strcmp(argv[start_arg], "type")) { 117054912308SNavdeep Parhar int newaf; 117154912308SNavdeep Parhar if (!strcasecmp(argv[start_arg + 1], "ipv4")) 117254912308SNavdeep Parhar newaf = AF_INET; 117354912308SNavdeep Parhar else if (!strcasecmp(argv[start_arg + 1], "ipv6")) 117454912308SNavdeep Parhar newaf = AF_INET6; 117554912308SNavdeep Parhar else { 117654912308SNavdeep Parhar warnx("invalid type \"%s\"; " 117754912308SNavdeep Parhar "must be one of \"ipv4\" or \"ipv6\"", 117854912308SNavdeep Parhar argv[start_arg + 1]); 117954912308SNavdeep Parhar return (EINVAL); 118054912308SNavdeep Parhar } 118154912308SNavdeep Parhar 118254912308SNavdeep Parhar if (af != AF_UNSPEC && af != newaf) { 118354912308SNavdeep Parhar warnx("conflicting IPv4/IPv6 specifications."); 118454912308SNavdeep Parhar return (EINVAL); 118554912308SNavdeep Parhar } 118654912308SNavdeep Parhar af = newaf; 118736ea2fe3SNavdeep Parhar } else if (!parse_val_mask("fcoe", args, &val, &mask, hash)) { 118854912308SNavdeep Parhar t.fs.val.fcoe = val; 118954912308SNavdeep Parhar t.fs.mask.fcoe = mask; 119036ea2fe3SNavdeep Parhar } else if (!parse_val_mask("iport", args, &val, &mask, hash)) { 119154912308SNavdeep Parhar t.fs.val.iport = val; 119254912308SNavdeep Parhar t.fs.mask.iport = mask; 119336ea2fe3SNavdeep Parhar } else if (!parse_val_mask("ovlan", args, &val, &mask, hash)) { 119454912308SNavdeep Parhar t.fs.val.vnic = val; 119554912308SNavdeep Parhar t.fs.mask.vnic = mask; 119654912308SNavdeep Parhar t.fs.val.ovlan_vld = 1; 119754912308SNavdeep Parhar t.fs.mask.ovlan_vld = 1; 119836ea2fe3SNavdeep Parhar } else if (!parse_val_mask("ivlan", args, &val, &mask, hash)) { 119954912308SNavdeep Parhar t.fs.val.vlan = val; 120054912308SNavdeep Parhar t.fs.mask.vlan = mask; 120154912308SNavdeep Parhar t.fs.val.vlan_vld = 1; 120254912308SNavdeep Parhar t.fs.mask.vlan_vld = 1; 120336ea2fe3SNavdeep Parhar } else if (!parse_val_mask("pf", args, &val, &mask, hash)) { 120454912308SNavdeep Parhar t.fs.val.vnic &= 0x1fff; 120554912308SNavdeep Parhar t.fs.val.vnic |= (val & 0x7) << 13; 120654912308SNavdeep Parhar t.fs.mask.vnic &= 0x1fff; 120754912308SNavdeep Parhar t.fs.mask.vnic |= (mask & 0x7) << 13; 120854912308SNavdeep Parhar t.fs.val.pfvf_vld = 1; 120954912308SNavdeep Parhar t.fs.mask.pfvf_vld = 1; 121036ea2fe3SNavdeep Parhar } else if (!parse_val_mask("vf", args, &val, &mask, hash)) { 121154912308SNavdeep Parhar t.fs.val.vnic &= 0xe000; 121254912308SNavdeep Parhar t.fs.val.vnic |= val & 0x1fff; 121354912308SNavdeep Parhar t.fs.mask.vnic &= 0xe000; 121454912308SNavdeep Parhar t.fs.mask.vnic |= mask & 0x1fff; 121554912308SNavdeep Parhar t.fs.val.pfvf_vld = 1; 121654912308SNavdeep Parhar t.fs.mask.pfvf_vld = 1; 121736ea2fe3SNavdeep Parhar } else if (!parse_val_mask("tos", args, &val, &mask, hash)) { 121854912308SNavdeep Parhar t.fs.val.tos = val; 121954912308SNavdeep Parhar t.fs.mask.tos = mask; 122036ea2fe3SNavdeep Parhar } else if (!parse_val_mask("proto", args, &val, &mask, hash)) { 122154912308SNavdeep Parhar t.fs.val.proto = val; 122254912308SNavdeep Parhar t.fs.mask.proto = mask; 122336ea2fe3SNavdeep Parhar } else if (!parse_val_mask("ethtype", args, &val, &mask, hash)) { 122454912308SNavdeep Parhar t.fs.val.ethtype = val; 122554912308SNavdeep Parhar t.fs.mask.ethtype = mask; 122636ea2fe3SNavdeep Parhar } else if (!parse_val_mask("macidx", args, &val, &mask, hash)) { 122754912308SNavdeep Parhar t.fs.val.macidx = val; 122854912308SNavdeep Parhar t.fs.mask.macidx = mask; 122936ea2fe3SNavdeep Parhar } else if (!parse_val_mask("matchtype", args, &val, &mask, hash)) { 123054912308SNavdeep Parhar t.fs.val.matchtype = val; 123154912308SNavdeep Parhar t.fs.mask.matchtype = mask; 123236ea2fe3SNavdeep Parhar } else if (!parse_val_mask("frag", args, &val, &mask, hash)) { 123354912308SNavdeep Parhar t.fs.val.frag = val; 123454912308SNavdeep Parhar t.fs.mask.frag = mask; 123536ea2fe3SNavdeep Parhar } else if (!parse_val_mask("dport", args, &val, &mask, hash)) { 123654912308SNavdeep Parhar t.fs.val.dport = val; 123754912308SNavdeep Parhar t.fs.mask.dport = mask; 123836ea2fe3SNavdeep Parhar } else if (!parse_val_mask("sport", args, &val, &mask, hash)) { 123954912308SNavdeep Parhar t.fs.val.sport = val; 124054912308SNavdeep Parhar t.fs.mask.sport = mask; 124154912308SNavdeep Parhar } else if (!parse_ipaddr("dip", args, &af, t.fs.val.dip, 124236ea2fe3SNavdeep Parhar t.fs.mask.dip, hash)) { 124354912308SNavdeep Parhar /* nada */; 124454912308SNavdeep Parhar } else if (!parse_ipaddr("sip", args, &af, t.fs.val.sip, 124536ea2fe3SNavdeep Parhar t.fs.mask.sip, hash)) { 124654912308SNavdeep Parhar /* nada */; 124736ea2fe3SNavdeep Parhar } else if (!parse_ipaddr("nat_dip", args, &af, t.fs.nat_dip, NULL, 1)) { 124836ea2fe3SNavdeep Parhar /*nada*/; 124936ea2fe3SNavdeep Parhar } else if (!parse_ipaddr("nat_sip", args, &af, t.fs.nat_sip, NULL, 1)) { 125036ea2fe3SNavdeep Parhar /*nada*/ 125136ea2fe3SNavdeep Parhar } else if (!parse_val_mask("nat_dport", args, &val, &mask, 1)) { 125236ea2fe3SNavdeep Parhar t.fs.nat_dport = val; 125336ea2fe3SNavdeep Parhar } else if (!parse_val_mask("nat_sport", args, &val, &mask, 1)) { 125436ea2fe3SNavdeep Parhar t.fs.nat_sport = val; 125554912308SNavdeep Parhar } else if (!strcmp(argv[start_arg], "action")) { 125654912308SNavdeep Parhar if (!strcmp(argv[start_arg + 1], "pass")) 125754912308SNavdeep Parhar t.fs.action = FILTER_PASS; 125854912308SNavdeep Parhar else if (!strcmp(argv[start_arg + 1], "drop")) 125954912308SNavdeep Parhar t.fs.action = FILTER_DROP; 126054912308SNavdeep Parhar else if (!strcmp(argv[start_arg + 1], "switch")) 126154912308SNavdeep Parhar t.fs.action = FILTER_SWITCH; 126254912308SNavdeep Parhar else { 126354912308SNavdeep Parhar warnx("invalid action \"%s\"; must be one of" 126454912308SNavdeep Parhar " \"pass\", \"drop\" or \"switch\"", 126554912308SNavdeep Parhar argv[start_arg + 1]); 126654912308SNavdeep Parhar return (EINVAL); 126754912308SNavdeep Parhar } 126854912308SNavdeep Parhar } else if (!parse_val("hitcnts", args, &val)) { 126954912308SNavdeep Parhar t.fs.hitcnts = val; 127054912308SNavdeep Parhar } else if (!parse_val("prio", args, &val)) { 12716ba81353SNavdeep Parhar if (hash) { 12726ba81353SNavdeep Parhar warnx("Hashfilters doesn't support \"prio\"\n"); 12736ba81353SNavdeep Parhar return (EINVAL); 12746ba81353SNavdeep Parhar } 12756ba81353SNavdeep Parhar if (val != 0 && val != 1) { 12766ba81353SNavdeep Parhar warnx("invalid priority \"%s\"; must be" 12776ba81353SNavdeep Parhar " \"0\" or \"1\"", argv[start_arg + 1]); 12786ba81353SNavdeep Parhar return (EINVAL); 12796ba81353SNavdeep Parhar } 128054912308SNavdeep Parhar t.fs.prio = val; 128154912308SNavdeep Parhar } else if (!parse_val("rpttid", args, &val)) { 128254912308SNavdeep Parhar t.fs.rpttid = 1; 128354912308SNavdeep Parhar } else if (!parse_val("queue", args, &val)) { 12849edef078SNavdeep Parhar t.fs.dirsteer = 1; /* direct steer */ 12859edef078SNavdeep Parhar t.fs.iq = val; /* to the iq with this cntxt_id */ 128654912308SNavdeep Parhar } else if (!parse_val("tcbhash", args, &val)) { 12879edef078SNavdeep Parhar t.fs.dirsteerhash = 1; /* direct steer */ 12889edef078SNavdeep Parhar /* XXX: use (val << 1) as the rss_hash? */ 12899edef078SNavdeep Parhar t.fs.iq = val; 12909edef078SNavdeep Parhar } else if (!parse_val("tcbrss", args, &val)) { 12919edef078SNavdeep Parhar t.fs.maskhash = 1; /* steer to RSS region */ 12929edef078SNavdeep Parhar /* 12939edef078SNavdeep Parhar * val = start idx of the region but the internal TCB 12949edef078SNavdeep Parhar * field is 10b only and is left shifted by 1 before use. 12959edef078SNavdeep Parhar */ 12969edef078SNavdeep Parhar t.fs.iq = val >> 1; 129754912308SNavdeep Parhar } else if (!parse_val("eport", args, &val)) { 129854912308SNavdeep Parhar t.fs.eport = val; 129936ea2fe3SNavdeep Parhar } else if (!parse_val("swapmac", args, &val)) { 130036ea2fe3SNavdeep Parhar t.fs.swapmac = 1; 130136ea2fe3SNavdeep Parhar } else if (!strcmp(argv[start_arg], "nat")) { 130236ea2fe3SNavdeep Parhar if (!strcmp(argv[start_arg + 1], "dip")) 130336ea2fe3SNavdeep Parhar t.fs.nat_mode = NAT_MODE_DIP; 130436ea2fe3SNavdeep Parhar else if (!strcmp(argv[start_arg + 1], "dip-dp")) 130536ea2fe3SNavdeep Parhar t.fs.nat_mode = NAT_MODE_DIP_DP; 130636ea2fe3SNavdeep Parhar else if (!strcmp(argv[start_arg + 1], "dip-dp-sip")) 130736ea2fe3SNavdeep Parhar t.fs.nat_mode = NAT_MODE_DIP_DP_SIP; 130836ea2fe3SNavdeep Parhar else if (!strcmp(argv[start_arg + 1], "dip-dp-sp")) 130936ea2fe3SNavdeep Parhar t.fs.nat_mode = NAT_MODE_DIP_DP_SP; 131036ea2fe3SNavdeep Parhar else if (!strcmp(argv[start_arg + 1], "sip-sp")) 131136ea2fe3SNavdeep Parhar t.fs.nat_mode = NAT_MODE_SIP_SP; 131236ea2fe3SNavdeep Parhar else if (!strcmp(argv[start_arg + 1], "dip-sip-sp")) 131336ea2fe3SNavdeep Parhar t.fs.nat_mode = NAT_MODE_DIP_SIP_SP; 131436ea2fe3SNavdeep Parhar else if (!strcmp(argv[start_arg + 1], "all")) 131536ea2fe3SNavdeep Parhar t.fs.nat_mode = NAT_MODE_ALL; 131636ea2fe3SNavdeep Parhar else { 131736ea2fe3SNavdeep Parhar warnx("unknown nat type \"%s\"; known types are dip, " 131836ea2fe3SNavdeep Parhar "dip-dp, dip-dp-sip, dip-dp-sp, sip-sp, " 131936ea2fe3SNavdeep Parhar "dip-sip-sp, and all", argv[start_arg + 1]); 132036ea2fe3SNavdeep Parhar return (EINVAL); 132136ea2fe3SNavdeep Parhar } 132236ea2fe3SNavdeep Parhar } else if (!parse_val("natseq", args, &val)) { 132336ea2fe3SNavdeep Parhar t.fs.nat_seq_chk = val; 132436ea2fe3SNavdeep Parhar } else if (!parse_val("natflag", args, &val)) { 132536ea2fe3SNavdeep Parhar t.fs.nat_flag_chk = 1; 132654912308SNavdeep Parhar } else if (!strcmp(argv[start_arg], "dmac")) { 132754912308SNavdeep Parhar struct ether_addr *daddr; 132854912308SNavdeep Parhar 132954912308SNavdeep Parhar daddr = ether_aton(argv[start_arg + 1]); 133054912308SNavdeep Parhar if (daddr == NULL) { 133154912308SNavdeep Parhar warnx("invalid dmac address \"%s\"", 133254912308SNavdeep Parhar argv[start_arg + 1]); 133354912308SNavdeep Parhar return (EINVAL); 133454912308SNavdeep Parhar } 133554912308SNavdeep Parhar memcpy(t.fs.dmac, daddr, ETHER_ADDR_LEN); 133654912308SNavdeep Parhar t.fs.newdmac = 1; 133754912308SNavdeep Parhar } else if (!strcmp(argv[start_arg], "smac")) { 133854912308SNavdeep Parhar struct ether_addr *saddr; 133954912308SNavdeep Parhar 134054912308SNavdeep Parhar saddr = ether_aton(argv[start_arg + 1]); 134154912308SNavdeep Parhar if (saddr == NULL) { 134254912308SNavdeep Parhar warnx("invalid smac address \"%s\"", 134354912308SNavdeep Parhar argv[start_arg + 1]); 134454912308SNavdeep Parhar return (EINVAL); 134554912308SNavdeep Parhar } 134654912308SNavdeep Parhar memcpy(t.fs.smac, saddr, ETHER_ADDR_LEN); 134754912308SNavdeep Parhar t.fs.newsmac = 1; 134854912308SNavdeep Parhar } else if (!strcmp(argv[start_arg], "vlan")) { 134954912308SNavdeep Parhar char *p; 135054912308SNavdeep Parhar if (!strcmp(argv[start_arg + 1], "none")) { 135154912308SNavdeep Parhar t.fs.newvlan = VLAN_REMOVE; 135254912308SNavdeep Parhar } else if (argv[start_arg + 1][0] == '=') { 135354912308SNavdeep Parhar t.fs.newvlan = VLAN_REWRITE; 135454912308SNavdeep Parhar } else if (argv[start_arg + 1][0] == '+') { 135554912308SNavdeep Parhar t.fs.newvlan = VLAN_INSERT; 135654912308SNavdeep Parhar } else { 135754912308SNavdeep Parhar warnx("unknown vlan parameter \"%s\"; must" 135854912308SNavdeep Parhar " be one of \"none\", \"=<vlan>\", " 13591e168376SNavdeep Parhar " \"+<vlan>\"", argv[start_arg + 1]); 136054912308SNavdeep Parhar return (EINVAL); 136154912308SNavdeep Parhar } 136254912308SNavdeep Parhar if (t.fs.newvlan == VLAN_REWRITE || 136354912308SNavdeep Parhar t.fs.newvlan == VLAN_INSERT) { 136454912308SNavdeep Parhar t.fs.vlan = strtoul(argv[start_arg + 1] + 1, 136554912308SNavdeep Parhar &p, 0); 13662293e221SNavdeep Parhar if (p == argv[start_arg + 1] + 1 || p[0] != 0 || 13672293e221SNavdeep Parhar t.fs.vlan > MAX_VLANID) { 136854912308SNavdeep Parhar warnx("invalid vlan \"%s\"", 136954912308SNavdeep Parhar argv[start_arg + 1]); 137054912308SNavdeep Parhar return (EINVAL); 137154912308SNavdeep Parhar } 137254912308SNavdeep Parhar } 137354912308SNavdeep Parhar } else { 137454912308SNavdeep Parhar warnx("invalid parameter \"%s\"", argv[start_arg]); 137554912308SNavdeep Parhar return (EINVAL); 137654912308SNavdeep Parhar } 137754912308SNavdeep Parhar } 137854912308SNavdeep Parhar if (start_arg != argc) { 137954912308SNavdeep Parhar warnx("no value for \"%s\"", argv[start_arg]); 138054912308SNavdeep Parhar return (EINVAL); 138154912308SNavdeep Parhar } 138254912308SNavdeep Parhar 138354912308SNavdeep Parhar /* 138454912308SNavdeep Parhar * Check basic sanity of option combinations. 138554912308SNavdeep Parhar */ 138654912308SNavdeep Parhar if (t.fs.action != FILTER_SWITCH && 138736ea2fe3SNavdeep Parhar (t.fs.eport || t.fs.newdmac || t.fs.newsmac || t.fs.newvlan || 138836ea2fe3SNavdeep Parhar t.fs.swapmac || t.fs.nat_mode)) { 138936ea2fe3SNavdeep Parhar warnx("port, dmac, smac, vlan, and nat only make sense with" 139054912308SNavdeep Parhar " \"action switch\""); 139154912308SNavdeep Parhar return (EINVAL); 139254912308SNavdeep Parhar } 139336ea2fe3SNavdeep Parhar if (!t.fs.nat_mode && (t.fs.nat_seq_chk || t.fs.nat_flag_chk || 139436ea2fe3SNavdeep Parhar *t.fs.nat_dip || *t.fs.nat_sip || t.fs.nat_dport || t.fs.nat_sport)) { 139536ea2fe3SNavdeep Parhar warnx("nat params only make sense with valid nat mode"); 139636ea2fe3SNavdeep Parhar return (EINVAL); 139736ea2fe3SNavdeep Parhar } 139854912308SNavdeep Parhar if (t.fs.action != FILTER_PASS && 139954912308SNavdeep Parhar (t.fs.rpttid || t.fs.dirsteer || t.fs.maskhash)) { 140054912308SNavdeep Parhar warnx("rpttid, queue and tcbhash don't make sense with" 140154912308SNavdeep Parhar " action \"drop\" or \"switch\""); 140254912308SNavdeep Parhar return (EINVAL); 140354912308SNavdeep Parhar } 140454912308SNavdeep Parhar if (t.fs.val.ovlan_vld && t.fs.val.pfvf_vld) { 140554912308SNavdeep Parhar warnx("ovlan and vnic_id (pf/vf) are mutually exclusive"); 140654912308SNavdeep Parhar return (EINVAL); 140754912308SNavdeep Parhar } 140854912308SNavdeep Parhar 140954912308SNavdeep Parhar t.fs.type = (af == AF_INET6 ? 1 : 0); /* default IPv4 */ 141036ea2fe3SNavdeep Parhar rc = doit(CHELSIO_T4_SET_FILTER, &t); 141136ea2fe3SNavdeep Parhar if (hash && rc == 0) 141236ea2fe3SNavdeep Parhar printf("%d\n", t.idx); 141336ea2fe3SNavdeep Parhar return (rc); 141454912308SNavdeep Parhar } 141554912308SNavdeep Parhar 141654912308SNavdeep Parhar static int 141736ea2fe3SNavdeep Parhar filter_cmd(int argc, const char *argv[], int hashfilter) 141854912308SNavdeep Parhar { 141954912308SNavdeep Parhar long long val; 142054912308SNavdeep Parhar uint32_t idx; 142154912308SNavdeep Parhar char *s; 142254912308SNavdeep Parhar 142354912308SNavdeep Parhar if (argc == 0) { 142436ea2fe3SNavdeep Parhar warnx("%sfilter: no arguments.", hashfilter ? "hash" : ""); 142554912308SNavdeep Parhar return (EINVAL); 142654912308SNavdeep Parhar }; 142754912308SNavdeep Parhar 142854912308SNavdeep Parhar /* list */ 142954912308SNavdeep Parhar if (strcmp(argv[0], "list") == 0) { 143054912308SNavdeep Parhar if (argc != 1) 143154912308SNavdeep Parhar warnx("trailing arguments after \"list\" ignored."); 143254912308SNavdeep Parhar 143336ea2fe3SNavdeep Parhar return show_filters(hashfilter); 143454912308SNavdeep Parhar } 143554912308SNavdeep Parhar 143654912308SNavdeep Parhar /* mode */ 143754912308SNavdeep Parhar if (argc == 1 && strcmp(argv[0], "mode") == 0) 143836ea2fe3SNavdeep Parhar return get_filter_mode(hashfilter); 143954912308SNavdeep Parhar 144054912308SNavdeep Parhar /* mode <mode> */ 1441038148c1SNavdeep Parhar if (strcmp(argv[0], "mode") == 0) 1442038148c1SNavdeep Parhar return set_filter_mode(argc - 1, argv + 1, hashfilter); 144354912308SNavdeep Parhar 144454912308SNavdeep Parhar /* <idx> ... */ 144554912308SNavdeep Parhar s = str_to_number(argv[0], NULL, &val); 144636ea2fe3SNavdeep Parhar if (*s || val < 0 || val > 0xffffffffU) { 144736ea2fe3SNavdeep Parhar if (hashfilter) { 144836ea2fe3SNavdeep Parhar /* 144936ea2fe3SNavdeep Parhar * No numeric index means this must be a request to 145036ea2fe3SNavdeep Parhar * create a new hashfilter and we are already at the 145136ea2fe3SNavdeep Parhar * paramter/value list. 145236ea2fe3SNavdeep Parhar */ 145336ea2fe3SNavdeep Parhar idx = (uint32_t) -1; 145436ea2fe3SNavdeep Parhar goto setf; 145536ea2fe3SNavdeep Parhar } 145654912308SNavdeep Parhar warnx("\"%s\" is neither an index nor a filter subcommand.", 145754912308SNavdeep Parhar argv[0]); 145854912308SNavdeep Parhar return (EINVAL); 145954912308SNavdeep Parhar } 146054912308SNavdeep Parhar idx = (uint32_t) val; 146154912308SNavdeep Parhar 14626ba81353SNavdeep Parhar /* <idx> delete|clear [prio 0|1] */ 14636ba81353SNavdeep Parhar if ((argc == 2 || argc == 4) && 146454912308SNavdeep Parhar (strcmp(argv[1], "delete") == 0 || strcmp(argv[1], "clear") == 0)) { 14656ba81353SNavdeep Parhar int prio = 0; 14666ba81353SNavdeep Parhar 14676ba81353SNavdeep Parhar if (argc == 4) { 14686ba81353SNavdeep Parhar if (hashfilter) { 14696ba81353SNavdeep Parhar warnx("stray arguments after \"%s\".", argv[1]); 14706ba81353SNavdeep Parhar return (EINVAL); 14716ba81353SNavdeep Parhar } 14726ba81353SNavdeep Parhar 14736ba81353SNavdeep Parhar if (strcmp(argv[2], "prio") != 0) { 14746ba81353SNavdeep Parhar warnx("\"prio\" is the only valid keyword " 14756ba81353SNavdeep Parhar "after \"%s\", found \"%s\" instead.", 14766ba81353SNavdeep Parhar argv[1], argv[2]); 14776ba81353SNavdeep Parhar return (EINVAL); 14786ba81353SNavdeep Parhar } 14796ba81353SNavdeep Parhar 14806ba81353SNavdeep Parhar s = str_to_number(argv[3], NULL, &val); 14816ba81353SNavdeep Parhar if (*s || val < 0 || val > 1) { 14826ba81353SNavdeep Parhar warnx("%s \"%s\"; must be \"0\" or \"1\".", 14836ba81353SNavdeep Parhar argv[2], argv[3]); 14846ba81353SNavdeep Parhar return (EINVAL); 14856ba81353SNavdeep Parhar } 14866ba81353SNavdeep Parhar prio = (int)val; 14876ba81353SNavdeep Parhar } 14886ba81353SNavdeep Parhar return del_filter(idx, prio, hashfilter); 148954912308SNavdeep Parhar } 149054912308SNavdeep Parhar 149136ea2fe3SNavdeep Parhar /* skip <idx> */ 149236ea2fe3SNavdeep Parhar argc--; 149336ea2fe3SNavdeep Parhar argv++; 149436ea2fe3SNavdeep Parhar 149536ea2fe3SNavdeep Parhar setf: 149636ea2fe3SNavdeep Parhar /* [<param> <val>] ... */ 149736ea2fe3SNavdeep Parhar return set_filter(idx, argc, argv, hashfilter); 149854912308SNavdeep Parhar } 149954912308SNavdeep Parhar 150054912308SNavdeep Parhar /* 150154912308SNavdeep Parhar * Shows the fields of a multi-word structure. The structure is considered to 150254912308SNavdeep Parhar * consist of @nwords 32-bit words (i.e, it's an (@nwords * 32)-bit structure) 150354912308SNavdeep Parhar * whose fields are described by @fd. The 32-bit words are given in @words 150454912308SNavdeep Parhar * starting with the least significant 32-bit word. 150554912308SNavdeep Parhar */ 150654912308SNavdeep Parhar static void 150754912308SNavdeep Parhar show_struct(const uint32_t *words, int nwords, const struct field_desc *fd) 150854912308SNavdeep Parhar { 150954912308SNavdeep Parhar unsigned int w = 0; 151054912308SNavdeep Parhar const struct field_desc *p; 151154912308SNavdeep Parhar 151254912308SNavdeep Parhar for (p = fd; p->name; p++) 151354912308SNavdeep Parhar w = max(w, strlen(p->name)); 151454912308SNavdeep Parhar 151554912308SNavdeep Parhar while (fd->name) { 151654912308SNavdeep Parhar unsigned long long data; 151754912308SNavdeep Parhar int first_word = fd->start / 32; 151854912308SNavdeep Parhar int shift = fd->start % 32; 151954912308SNavdeep Parhar int width = fd->end - fd->start + 1; 152054912308SNavdeep Parhar unsigned long long mask = (1ULL << width) - 1; 152154912308SNavdeep Parhar 152254912308SNavdeep Parhar data = (words[first_word] >> shift) | 152354912308SNavdeep Parhar ((uint64_t)words[first_word + 1] << (32 - shift)); 152454912308SNavdeep Parhar if (shift) 152554912308SNavdeep Parhar data |= ((uint64_t)words[first_word + 2] << (64 - shift)); 152654912308SNavdeep Parhar data &= mask; 152754912308SNavdeep Parhar if (fd->islog2) 152854912308SNavdeep Parhar data = 1 << data; 152954912308SNavdeep Parhar printf("%-*s ", w, fd->name); 153054912308SNavdeep Parhar printf(fd->hex ? "%#llx\n" : "%llu\n", data << fd->shift); 153154912308SNavdeep Parhar fd++; 153254912308SNavdeep Parhar } 153354912308SNavdeep Parhar } 153454912308SNavdeep Parhar 153554912308SNavdeep Parhar #define FIELD(name, start, end) { name, start, end, 0, 0, 0 } 153654912308SNavdeep Parhar #define FIELD1(name, start) FIELD(name, start, start) 153754912308SNavdeep Parhar 153854912308SNavdeep Parhar static void 153954912308SNavdeep Parhar show_t5t6_ctxt(const struct t4_sge_context *p, int vers) 154054912308SNavdeep Parhar { 154154912308SNavdeep Parhar static struct field_desc egress_t5[] = { 154254912308SNavdeep Parhar FIELD("DCA_ST:", 181, 191), 154354912308SNavdeep Parhar FIELD1("StatusPgNS:", 180), 154454912308SNavdeep Parhar FIELD1("StatusPgRO:", 179), 154554912308SNavdeep Parhar FIELD1("FetchNS:", 178), 154654912308SNavdeep Parhar FIELD1("FetchRO:", 177), 154754912308SNavdeep Parhar FIELD1("Valid:", 176), 154854912308SNavdeep Parhar FIELD("PCIeDataChannel:", 174, 175), 154954912308SNavdeep Parhar FIELD1("StatusPgTPHintEn:", 173), 155054912308SNavdeep Parhar FIELD("StatusPgTPHint:", 171, 172), 155154912308SNavdeep Parhar FIELD1("FetchTPHintEn:", 170), 155254912308SNavdeep Parhar FIELD("FetchTPHint:", 168, 169), 155354912308SNavdeep Parhar FIELD1("FCThreshOverride:", 167), 155454912308SNavdeep Parhar { "WRLength:", 162, 166, 9, 0, 1 }, 155554912308SNavdeep Parhar FIELD1("WRLengthKnown:", 161), 155654912308SNavdeep Parhar FIELD1("ReschedulePending:", 160), 155754912308SNavdeep Parhar FIELD1("OnChipQueue:", 159), 155854912308SNavdeep Parhar FIELD1("FetchSizeMode:", 158), 155954912308SNavdeep Parhar { "FetchBurstMin:", 156, 157, 4, 0, 1 }, 156054912308SNavdeep Parhar FIELD1("FLMPacking:", 155), 156154912308SNavdeep Parhar FIELD("FetchBurstMax:", 153, 154), 156254912308SNavdeep Parhar FIELD("uPToken:", 133, 152), 156354912308SNavdeep Parhar FIELD1("uPTokenEn:", 132), 156454912308SNavdeep Parhar FIELD1("UserModeIO:", 131), 156554912308SNavdeep Parhar FIELD("uPFLCredits:", 123, 130), 156654912308SNavdeep Parhar FIELD1("uPFLCreditEn:", 122), 156754912308SNavdeep Parhar FIELD("FID:", 111, 121), 156854912308SNavdeep Parhar FIELD("HostFCMode:", 109, 110), 156954912308SNavdeep Parhar FIELD1("HostFCOwner:", 108), 157054912308SNavdeep Parhar { "CIDXFlushThresh:", 105, 107, 0, 0, 1 }, 157154912308SNavdeep Parhar FIELD("CIDX:", 89, 104), 157254912308SNavdeep Parhar FIELD("PIDX:", 73, 88), 157354912308SNavdeep Parhar { "BaseAddress:", 18, 72, 9, 1 }, 157454912308SNavdeep Parhar FIELD("QueueSize:", 2, 17), 157554912308SNavdeep Parhar FIELD1("QueueType:", 1), 157654912308SNavdeep Parhar FIELD1("CachePriority:", 0), 157754912308SNavdeep Parhar { NULL } 157854912308SNavdeep Parhar }; 157954912308SNavdeep Parhar static struct field_desc egress_t6[] = { 158054912308SNavdeep Parhar FIELD("DCA_ST:", 181, 191), 158154912308SNavdeep Parhar FIELD1("StatusPgNS:", 180), 158254912308SNavdeep Parhar FIELD1("StatusPgRO:", 179), 158354912308SNavdeep Parhar FIELD1("FetchNS:", 178), 158454912308SNavdeep Parhar FIELD1("FetchRO:", 177), 158554912308SNavdeep Parhar FIELD1("Valid:", 176), 158654912308SNavdeep Parhar FIELD1("ReschedulePending_1:", 175), 158754912308SNavdeep Parhar FIELD1("PCIeDataChannel:", 174), 158854912308SNavdeep Parhar FIELD1("StatusPgTPHintEn:", 173), 158954912308SNavdeep Parhar FIELD("StatusPgTPHint:", 171, 172), 159054912308SNavdeep Parhar FIELD1("FetchTPHintEn:", 170), 159154912308SNavdeep Parhar FIELD("FetchTPHint:", 168, 169), 159254912308SNavdeep Parhar FIELD1("FCThreshOverride:", 167), 159354912308SNavdeep Parhar { "WRLength:", 162, 166, 9, 0, 1 }, 159454912308SNavdeep Parhar FIELD1("WRLengthKnown:", 161), 159554912308SNavdeep Parhar FIELD1("ReschedulePending:", 160), 159654912308SNavdeep Parhar FIELD("TimerIx:", 157, 159), 159754912308SNavdeep Parhar FIELD1("FetchBurstMin:", 156), 159854912308SNavdeep Parhar FIELD1("FLMPacking:", 155), 159954912308SNavdeep Parhar FIELD("FetchBurstMax:", 153, 154), 160054912308SNavdeep Parhar FIELD("uPToken:", 133, 152), 160154912308SNavdeep Parhar FIELD1("uPTokenEn:", 132), 160254912308SNavdeep Parhar FIELD1("UserModeIO:", 131), 160354912308SNavdeep Parhar FIELD("uPFLCredits:", 123, 130), 160454912308SNavdeep Parhar FIELD1("uPFLCreditEn:", 122), 160554912308SNavdeep Parhar FIELD("FID:", 111, 121), 160654912308SNavdeep Parhar FIELD("HostFCMode:", 109, 110), 160754912308SNavdeep Parhar FIELD1("HostFCOwner:", 108), 160854912308SNavdeep Parhar { "CIDXFlushThresh:", 105, 107, 0, 0, 1 }, 160954912308SNavdeep Parhar FIELD("CIDX:", 89, 104), 161054912308SNavdeep Parhar FIELD("PIDX:", 73, 88), 161154912308SNavdeep Parhar { "BaseAddress:", 18, 72, 9, 1 }, 161254912308SNavdeep Parhar FIELD("QueueSize:", 2, 17), 161354912308SNavdeep Parhar FIELD1("QueueType:", 1), 161454912308SNavdeep Parhar FIELD1("FetchSizeMode:", 0), 161554912308SNavdeep Parhar { NULL } 161654912308SNavdeep Parhar }; 161754912308SNavdeep Parhar static struct field_desc fl_t5[] = { 161854912308SNavdeep Parhar FIELD("DCA_ST:", 181, 191), 161954912308SNavdeep Parhar FIELD1("StatusPgNS:", 180), 162054912308SNavdeep Parhar FIELD1("StatusPgRO:", 179), 162154912308SNavdeep Parhar FIELD1("FetchNS:", 178), 162254912308SNavdeep Parhar FIELD1("FetchRO:", 177), 162354912308SNavdeep Parhar FIELD1("Valid:", 176), 162454912308SNavdeep Parhar FIELD("PCIeDataChannel:", 174, 175), 162554912308SNavdeep Parhar FIELD1("StatusPgTPHintEn:", 173), 162654912308SNavdeep Parhar FIELD("StatusPgTPHint:", 171, 172), 162754912308SNavdeep Parhar FIELD1("FetchTPHintEn:", 170), 162854912308SNavdeep Parhar FIELD("FetchTPHint:", 168, 169), 162954912308SNavdeep Parhar FIELD1("FCThreshOverride:", 167), 163054912308SNavdeep Parhar FIELD1("ReschedulePending:", 160), 163154912308SNavdeep Parhar FIELD1("OnChipQueue:", 159), 163254912308SNavdeep Parhar FIELD1("FetchSizeMode:", 158), 163354912308SNavdeep Parhar { "FetchBurstMin:", 156, 157, 4, 0, 1 }, 163454912308SNavdeep Parhar FIELD1("FLMPacking:", 155), 163554912308SNavdeep Parhar FIELD("FetchBurstMax:", 153, 154), 163654912308SNavdeep Parhar FIELD1("FLMcongMode:", 152), 163754912308SNavdeep Parhar FIELD("MaxuPFLCredits:", 144, 151), 163854912308SNavdeep Parhar FIELD("FLMcontextID:", 133, 143), 163954912308SNavdeep Parhar FIELD1("uPTokenEn:", 132), 164054912308SNavdeep Parhar FIELD1("UserModeIO:", 131), 164154912308SNavdeep Parhar FIELD("uPFLCredits:", 123, 130), 164254912308SNavdeep Parhar FIELD1("uPFLCreditEn:", 122), 164354912308SNavdeep Parhar FIELD("FID:", 111, 121), 164454912308SNavdeep Parhar FIELD("HostFCMode:", 109, 110), 164554912308SNavdeep Parhar FIELD1("HostFCOwner:", 108), 164654912308SNavdeep Parhar { "CIDXFlushThresh:", 105, 107, 0, 0, 1 }, 164754912308SNavdeep Parhar FIELD("CIDX:", 89, 104), 164854912308SNavdeep Parhar FIELD("PIDX:", 73, 88), 164954912308SNavdeep Parhar { "BaseAddress:", 18, 72, 9, 1 }, 165054912308SNavdeep Parhar FIELD("QueueSize:", 2, 17), 165154912308SNavdeep Parhar FIELD1("QueueType:", 1), 165254912308SNavdeep Parhar FIELD1("CachePriority:", 0), 165354912308SNavdeep Parhar { NULL } 165454912308SNavdeep Parhar }; 165554912308SNavdeep Parhar static struct field_desc ingress_t5[] = { 165654912308SNavdeep Parhar FIELD("DCA_ST:", 143, 153), 165754912308SNavdeep Parhar FIELD1("ISCSICoalescing:", 142), 165854912308SNavdeep Parhar FIELD1("Queue_Valid:", 141), 165954912308SNavdeep Parhar FIELD1("TimerPending:", 140), 166054912308SNavdeep Parhar FIELD1("DropRSS:", 139), 166154912308SNavdeep Parhar FIELD("PCIeChannel:", 137, 138), 166254912308SNavdeep Parhar FIELD1("SEInterruptArmed:", 136), 166354912308SNavdeep Parhar FIELD1("CongestionMgtEnable:", 135), 166454912308SNavdeep Parhar FIELD1("NoSnoop:", 134), 166554912308SNavdeep Parhar FIELD1("RelaxedOrdering:", 133), 166654912308SNavdeep Parhar FIELD1("GTSmode:", 132), 166754912308SNavdeep Parhar FIELD1("TPHintEn:", 131), 166854912308SNavdeep Parhar FIELD("TPHint:", 129, 130), 166954912308SNavdeep Parhar FIELD1("UpdateScheduling:", 128), 167054912308SNavdeep Parhar FIELD("UpdateDelivery:", 126, 127), 167154912308SNavdeep Parhar FIELD1("InterruptSent:", 125), 167254912308SNavdeep Parhar FIELD("InterruptIDX:", 114, 124), 167354912308SNavdeep Parhar FIELD1("InterruptDestination:", 113), 167454912308SNavdeep Parhar FIELD1("InterruptArmed:", 112), 167554912308SNavdeep Parhar FIELD("RxIntCounter:", 106, 111), 167654912308SNavdeep Parhar FIELD("RxIntCounterThreshold:", 104, 105), 167754912308SNavdeep Parhar FIELD1("Generation:", 103), 167854912308SNavdeep Parhar { "BaseAddress:", 48, 102, 9, 1 }, 167954912308SNavdeep Parhar FIELD("PIDX:", 32, 47), 168054912308SNavdeep Parhar FIELD("CIDX:", 16, 31), 168154912308SNavdeep Parhar { "QueueSize:", 4, 15, 4, 0 }, 168254912308SNavdeep Parhar { "QueueEntrySize:", 2, 3, 4, 0, 1 }, 168354912308SNavdeep Parhar FIELD1("QueueEntryOverride:", 1), 168454912308SNavdeep Parhar FIELD1("CachePriority:", 0), 168554912308SNavdeep Parhar { NULL } 168654912308SNavdeep Parhar }; 168754912308SNavdeep Parhar static struct field_desc ingress_t6[] = { 168854912308SNavdeep Parhar FIELD1("SP_NS:", 158), 168954912308SNavdeep Parhar FIELD1("SP_RO:", 157), 169054912308SNavdeep Parhar FIELD1("SP_TPHintEn:", 156), 169154912308SNavdeep Parhar FIELD("SP_TPHint:", 154, 155), 169254912308SNavdeep Parhar FIELD("DCA_ST:", 143, 153), 169354912308SNavdeep Parhar FIELD1("ISCSICoalescing:", 142), 169454912308SNavdeep Parhar FIELD1("Queue_Valid:", 141), 169554912308SNavdeep Parhar FIELD1("TimerPending:", 140), 169654912308SNavdeep Parhar FIELD1("DropRSS:", 139), 169754912308SNavdeep Parhar FIELD("PCIeChannel:", 137, 138), 169854912308SNavdeep Parhar FIELD1("SEInterruptArmed:", 136), 169954912308SNavdeep Parhar FIELD1("CongestionMgtEnable:", 135), 170054912308SNavdeep Parhar FIELD1("NoSnoop:", 134), 170154912308SNavdeep Parhar FIELD1("RelaxedOrdering:", 133), 170254912308SNavdeep Parhar FIELD1("GTSmode:", 132), 170354912308SNavdeep Parhar FIELD1("TPHintEn:", 131), 170454912308SNavdeep Parhar FIELD("TPHint:", 129, 130), 170554912308SNavdeep Parhar FIELD1("UpdateScheduling:", 128), 170654912308SNavdeep Parhar FIELD("UpdateDelivery:", 126, 127), 170754912308SNavdeep Parhar FIELD1("InterruptSent:", 125), 170854912308SNavdeep Parhar FIELD("InterruptIDX:", 114, 124), 170954912308SNavdeep Parhar FIELD1("InterruptDestination:", 113), 171054912308SNavdeep Parhar FIELD1("InterruptArmed:", 112), 171154912308SNavdeep Parhar FIELD("RxIntCounter:", 106, 111), 171254912308SNavdeep Parhar FIELD("RxIntCounterThreshold:", 104, 105), 171354912308SNavdeep Parhar FIELD1("Generation:", 103), 171454912308SNavdeep Parhar { "BaseAddress:", 48, 102, 9, 1 }, 171554912308SNavdeep Parhar FIELD("PIDX:", 32, 47), 171654912308SNavdeep Parhar FIELD("CIDX:", 16, 31), 171754912308SNavdeep Parhar { "QueueSize:", 4, 15, 4, 0 }, 171854912308SNavdeep Parhar { "QueueEntrySize:", 2, 3, 4, 0, 1 }, 171954912308SNavdeep Parhar FIELD1("QueueEntryOverride:", 1), 172054912308SNavdeep Parhar FIELD1("CachePriority:", 0), 172154912308SNavdeep Parhar { NULL } 172254912308SNavdeep Parhar }; 172354912308SNavdeep Parhar static struct field_desc flm_t5[] = { 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 FIELD("PackOffset:", 16, 47), 173854912308SNavdeep Parhar FIELD("CIDX:", 8, 15), 173954912308SNavdeep Parhar FIELD("PIDX:", 0, 7), 174054912308SNavdeep Parhar { NULL } 174154912308SNavdeep Parhar }; 174254912308SNavdeep Parhar static struct field_desc flm_t6[] = { 174354912308SNavdeep Parhar FIELD1("Valid:", 89), 174454912308SNavdeep Parhar FIELD("SplitLenMode:", 87, 88), 174554912308SNavdeep Parhar FIELD1("TPHintEn:", 86), 174654912308SNavdeep Parhar FIELD("TPHint:", 84, 85), 174754912308SNavdeep Parhar FIELD1("NoSnoop:", 83), 174854912308SNavdeep Parhar FIELD1("RelaxedOrdering:", 82), 174954912308SNavdeep Parhar FIELD("DCA_ST:", 71, 81), 175054912308SNavdeep Parhar FIELD("EQid:", 54, 70), 175154912308SNavdeep Parhar FIELD("SplitEn:", 52, 53), 175254912308SNavdeep Parhar FIELD1("PadEn:", 51), 175354912308SNavdeep Parhar FIELD1("PackEn:", 50), 175454912308SNavdeep Parhar FIELD1("Cache_Lock :", 49), 175554912308SNavdeep Parhar FIELD1("CongDrop:", 48), 175654912308SNavdeep Parhar FIELD1("Inflight:", 47), 175754912308SNavdeep Parhar FIELD1("CongEn:", 46), 175854912308SNavdeep Parhar FIELD1("CongMode:", 45), 175954912308SNavdeep Parhar FIELD("PackOffset:", 20, 39), 176054912308SNavdeep Parhar FIELD("CIDX:", 8, 15), 176154912308SNavdeep Parhar FIELD("PIDX:", 0, 7), 176254912308SNavdeep Parhar { NULL } 176354912308SNavdeep Parhar }; 176454912308SNavdeep Parhar static struct field_desc conm_t5[] = { 176554912308SNavdeep Parhar FIELD1("CngMPSEnable:", 21), 176654912308SNavdeep Parhar FIELD("CngTPMode:", 19, 20), 176754912308SNavdeep Parhar FIELD1("CngDBPHdr:", 18), 176854912308SNavdeep Parhar FIELD1("CngDBPData:", 17), 176954912308SNavdeep Parhar FIELD1("CngIMSG:", 16), 177054912308SNavdeep Parhar { "CngChMap:", 0, 15, 0, 1, 0 }, 177154912308SNavdeep Parhar { NULL } 177254912308SNavdeep Parhar }; 177354912308SNavdeep Parhar 177454912308SNavdeep Parhar if (p->mem_id == SGE_CONTEXT_EGRESS) { 177554912308SNavdeep Parhar if (p->data[0] & 2) 177654912308SNavdeep Parhar show_struct(p->data, 6, fl_t5); 177754912308SNavdeep Parhar else if (vers == 5) 177854912308SNavdeep Parhar show_struct(p->data, 6, egress_t5); 177954912308SNavdeep Parhar else 178054912308SNavdeep Parhar show_struct(p->data, 6, egress_t6); 178154912308SNavdeep Parhar } else if (p->mem_id == SGE_CONTEXT_FLM) 178254912308SNavdeep Parhar show_struct(p->data, 3, vers == 5 ? flm_t5 : flm_t6); 178354912308SNavdeep Parhar else if (p->mem_id == SGE_CONTEXT_INGRESS) 178454912308SNavdeep Parhar show_struct(p->data, 5, vers == 5 ? ingress_t5 : ingress_t6); 178554912308SNavdeep Parhar else if (p->mem_id == SGE_CONTEXT_CNM) 178654912308SNavdeep Parhar show_struct(p->data, 1, conm_t5); 178754912308SNavdeep Parhar } 178854912308SNavdeep Parhar 178954912308SNavdeep Parhar static void 179054912308SNavdeep Parhar show_t4_ctxt(const struct t4_sge_context *p) 179154912308SNavdeep Parhar { 179254912308SNavdeep Parhar static struct field_desc egress_t4[] = { 179354912308SNavdeep Parhar FIELD1("StatusPgNS:", 180), 179454912308SNavdeep Parhar FIELD1("StatusPgRO:", 179), 179554912308SNavdeep Parhar FIELD1("FetchNS:", 178), 179654912308SNavdeep Parhar FIELD1("FetchRO:", 177), 179754912308SNavdeep Parhar FIELD1("Valid:", 176), 179854912308SNavdeep Parhar FIELD("PCIeDataChannel:", 174, 175), 179954912308SNavdeep Parhar FIELD1("DCAEgrQEn:", 173), 180054912308SNavdeep Parhar FIELD("DCACPUID:", 168, 172), 180154912308SNavdeep Parhar FIELD1("FCThreshOverride:", 167), 180254912308SNavdeep Parhar FIELD("WRLength:", 162, 166), 180354912308SNavdeep Parhar FIELD1("WRLengthKnown:", 161), 180454912308SNavdeep Parhar FIELD1("ReschedulePending:", 160), 180554912308SNavdeep Parhar FIELD1("OnChipQueue:", 159), 180654912308SNavdeep Parhar FIELD1("FetchSizeMode", 158), 180754912308SNavdeep Parhar { "FetchBurstMin:", 156, 157, 4, 0, 1 }, 180854912308SNavdeep Parhar { "FetchBurstMax:", 153, 154, 6, 0, 1 }, 180954912308SNavdeep Parhar FIELD("uPToken:", 133, 152), 181054912308SNavdeep Parhar FIELD1("uPTokenEn:", 132), 181154912308SNavdeep Parhar FIELD1("UserModeIO:", 131), 181254912308SNavdeep Parhar FIELD("uPFLCredits:", 123, 130), 181354912308SNavdeep Parhar FIELD1("uPFLCreditEn:", 122), 181454912308SNavdeep Parhar FIELD("FID:", 111, 121), 181554912308SNavdeep Parhar FIELD("HostFCMode:", 109, 110), 181654912308SNavdeep Parhar FIELD1("HostFCOwner:", 108), 181754912308SNavdeep Parhar { "CIDXFlushThresh:", 105, 107, 0, 0, 1 }, 181854912308SNavdeep Parhar FIELD("CIDX:", 89, 104), 181954912308SNavdeep Parhar FIELD("PIDX:", 73, 88), 182054912308SNavdeep Parhar { "BaseAddress:", 18, 72, 9, 1 }, 182154912308SNavdeep Parhar FIELD("QueueSize:", 2, 17), 182254912308SNavdeep Parhar FIELD1("QueueType:", 1), 182354912308SNavdeep Parhar FIELD1("CachePriority:", 0), 182454912308SNavdeep Parhar { NULL } 182554912308SNavdeep Parhar }; 182654912308SNavdeep Parhar static struct field_desc fl_t4[] = { 182754912308SNavdeep Parhar FIELD1("StatusPgNS:", 180), 182854912308SNavdeep Parhar FIELD1("StatusPgRO:", 179), 182954912308SNavdeep Parhar FIELD1("FetchNS:", 178), 183054912308SNavdeep Parhar FIELD1("FetchRO:", 177), 183154912308SNavdeep Parhar FIELD1("Valid:", 176), 183254912308SNavdeep Parhar FIELD("PCIeDataChannel:", 174, 175), 183354912308SNavdeep Parhar FIELD1("DCAEgrQEn:", 173), 183454912308SNavdeep Parhar FIELD("DCACPUID:", 168, 172), 183554912308SNavdeep Parhar FIELD1("FCThreshOverride:", 167), 183654912308SNavdeep Parhar FIELD1("ReschedulePending:", 160), 183754912308SNavdeep Parhar FIELD1("OnChipQueue:", 159), 183854912308SNavdeep Parhar FIELD1("FetchSizeMode", 158), 183954912308SNavdeep Parhar { "FetchBurstMin:", 156, 157, 4, 0, 1 }, 184054912308SNavdeep Parhar { "FetchBurstMax:", 153, 154, 6, 0, 1 }, 184154912308SNavdeep Parhar FIELD1("FLMcongMode:", 152), 184254912308SNavdeep Parhar FIELD("MaxuPFLCredits:", 144, 151), 184354912308SNavdeep Parhar FIELD("FLMcontextID:", 133, 143), 184454912308SNavdeep Parhar FIELD1("uPTokenEn:", 132), 184554912308SNavdeep Parhar FIELD1("UserModeIO:", 131), 184654912308SNavdeep Parhar FIELD("uPFLCredits:", 123, 130), 184754912308SNavdeep Parhar FIELD1("uPFLCreditEn:", 122), 184854912308SNavdeep Parhar FIELD("FID:", 111, 121), 184954912308SNavdeep Parhar FIELD("HostFCMode:", 109, 110), 185054912308SNavdeep Parhar FIELD1("HostFCOwner:", 108), 185154912308SNavdeep Parhar { "CIDXFlushThresh:", 105, 107, 0, 0, 1 }, 185254912308SNavdeep Parhar FIELD("CIDX:", 89, 104), 185354912308SNavdeep Parhar FIELD("PIDX:", 73, 88), 185454912308SNavdeep Parhar { "BaseAddress:", 18, 72, 9, 1 }, 185554912308SNavdeep Parhar FIELD("QueueSize:", 2, 17), 185654912308SNavdeep Parhar FIELD1("QueueType:", 1), 185754912308SNavdeep Parhar FIELD1("CachePriority:", 0), 185854912308SNavdeep Parhar { NULL } 185954912308SNavdeep Parhar }; 186054912308SNavdeep Parhar static struct field_desc ingress_t4[] = { 186154912308SNavdeep Parhar FIELD1("NoSnoop:", 145), 186254912308SNavdeep Parhar FIELD1("RelaxedOrdering:", 144), 186354912308SNavdeep Parhar FIELD1("GTSmode:", 143), 186454912308SNavdeep Parhar FIELD1("ISCSICoalescing:", 142), 186554912308SNavdeep Parhar FIELD1("Valid:", 141), 186654912308SNavdeep Parhar FIELD1("TimerPending:", 140), 186754912308SNavdeep Parhar FIELD1("DropRSS:", 139), 186854912308SNavdeep Parhar FIELD("PCIeChannel:", 137, 138), 186954912308SNavdeep Parhar FIELD1("SEInterruptArmed:", 136), 187054912308SNavdeep Parhar FIELD1("CongestionMgtEnable:", 135), 187154912308SNavdeep Parhar FIELD1("DCAIngQEnable:", 134), 187254912308SNavdeep Parhar FIELD("DCACPUID:", 129, 133), 187354912308SNavdeep Parhar FIELD1("UpdateScheduling:", 128), 187454912308SNavdeep Parhar FIELD("UpdateDelivery:", 126, 127), 187554912308SNavdeep Parhar FIELD1("InterruptSent:", 125), 187654912308SNavdeep Parhar FIELD("InterruptIDX:", 114, 124), 187754912308SNavdeep Parhar FIELD1("InterruptDestination:", 113), 187854912308SNavdeep Parhar FIELD1("InterruptArmed:", 112), 187954912308SNavdeep Parhar FIELD("RxIntCounter:", 106, 111), 188054912308SNavdeep Parhar FIELD("RxIntCounterThreshold:", 104, 105), 188154912308SNavdeep Parhar FIELD1("Generation:", 103), 188254912308SNavdeep Parhar { "BaseAddress:", 48, 102, 9, 1 }, 188354912308SNavdeep Parhar FIELD("PIDX:", 32, 47), 188454912308SNavdeep Parhar FIELD("CIDX:", 16, 31), 188554912308SNavdeep Parhar { "QueueSize:", 4, 15, 4, 0 }, 188654912308SNavdeep Parhar { "QueueEntrySize:", 2, 3, 4, 0, 1 }, 188754912308SNavdeep Parhar FIELD1("QueueEntryOverride:", 1), 188854912308SNavdeep Parhar FIELD1("CachePriority:", 0), 188954912308SNavdeep Parhar { NULL } 189054912308SNavdeep Parhar }; 189154912308SNavdeep Parhar static struct field_desc flm_t4[] = { 189254912308SNavdeep Parhar FIELD1("NoSnoop:", 79), 189354912308SNavdeep Parhar FIELD1("RelaxedOrdering:", 78), 189454912308SNavdeep Parhar FIELD1("Valid:", 77), 189554912308SNavdeep Parhar FIELD("DCACPUID:", 72, 76), 189654912308SNavdeep Parhar FIELD1("DCAFLEn:", 71), 189754912308SNavdeep Parhar FIELD("EQid:", 54, 70), 189854912308SNavdeep Parhar FIELD("SplitEn:", 52, 53), 189954912308SNavdeep Parhar FIELD1("PadEn:", 51), 190054912308SNavdeep Parhar FIELD1("PackEn:", 50), 190154912308SNavdeep Parhar FIELD1("DBpriority:", 48), 190254912308SNavdeep Parhar FIELD("PackOffset:", 16, 47), 190354912308SNavdeep Parhar FIELD("CIDX:", 8, 15), 190454912308SNavdeep Parhar FIELD("PIDX:", 0, 7), 190554912308SNavdeep Parhar { NULL } 190654912308SNavdeep Parhar }; 190754912308SNavdeep Parhar static struct field_desc conm_t4[] = { 190854912308SNavdeep Parhar FIELD1("CngDBPHdr:", 6), 190954912308SNavdeep Parhar FIELD1("CngDBPData:", 5), 191054912308SNavdeep Parhar FIELD1("CngIMSG:", 4), 191154912308SNavdeep Parhar { "CngChMap:", 0, 3, 0, 1, 0}, 191254912308SNavdeep Parhar { NULL } 191354912308SNavdeep Parhar }; 191454912308SNavdeep Parhar 191554912308SNavdeep Parhar if (p->mem_id == SGE_CONTEXT_EGRESS) 191654912308SNavdeep Parhar show_struct(p->data, 6, (p->data[0] & 2) ? fl_t4 : egress_t4); 191754912308SNavdeep Parhar else if (p->mem_id == SGE_CONTEXT_FLM) 191854912308SNavdeep Parhar show_struct(p->data, 3, flm_t4); 191954912308SNavdeep Parhar else if (p->mem_id == SGE_CONTEXT_INGRESS) 192054912308SNavdeep Parhar show_struct(p->data, 5, ingress_t4); 192154912308SNavdeep Parhar else if (p->mem_id == SGE_CONTEXT_CNM) 192254912308SNavdeep Parhar show_struct(p->data, 1, conm_t4); 192354912308SNavdeep Parhar } 192454912308SNavdeep Parhar 192554912308SNavdeep Parhar #undef FIELD 192654912308SNavdeep Parhar #undef FIELD1 192754912308SNavdeep Parhar 192854912308SNavdeep Parhar static int 192954912308SNavdeep Parhar get_sge_context(int argc, const char *argv[]) 193054912308SNavdeep Parhar { 193154912308SNavdeep Parhar int rc; 193254912308SNavdeep Parhar char *p; 193354912308SNavdeep Parhar long cid; 193454912308SNavdeep Parhar struct t4_sge_context cntxt = {0}; 193554912308SNavdeep Parhar 193654912308SNavdeep Parhar if (argc != 2) { 193754912308SNavdeep Parhar warnx("sge_context: incorrect number of arguments."); 193854912308SNavdeep Parhar return (EINVAL); 193954912308SNavdeep Parhar } 194054912308SNavdeep Parhar 194154912308SNavdeep Parhar if (!strcmp(argv[0], "egress")) 194254912308SNavdeep Parhar cntxt.mem_id = SGE_CONTEXT_EGRESS; 194354912308SNavdeep Parhar else if (!strcmp(argv[0], "ingress")) 194454912308SNavdeep Parhar cntxt.mem_id = SGE_CONTEXT_INGRESS; 194554912308SNavdeep Parhar else if (!strcmp(argv[0], "fl")) 194654912308SNavdeep Parhar cntxt.mem_id = SGE_CONTEXT_FLM; 194754912308SNavdeep Parhar else if (!strcmp(argv[0], "cong")) 194854912308SNavdeep Parhar cntxt.mem_id = SGE_CONTEXT_CNM; 194954912308SNavdeep Parhar else { 195054912308SNavdeep Parhar warnx("unknown context type \"%s\"; known types are egress, " 195154912308SNavdeep Parhar "ingress, fl, and cong.", argv[0]); 195254912308SNavdeep Parhar return (EINVAL); 195354912308SNavdeep Parhar } 195454912308SNavdeep Parhar 195554912308SNavdeep Parhar p = str_to_number(argv[1], &cid, NULL); 195654912308SNavdeep Parhar if (*p) { 195754912308SNavdeep Parhar warnx("invalid context id \"%s\"", argv[1]); 195854912308SNavdeep Parhar return (EINVAL); 195954912308SNavdeep Parhar } 196054912308SNavdeep Parhar cntxt.cid = cid; 196154912308SNavdeep Parhar 196254912308SNavdeep Parhar rc = doit(CHELSIO_T4_GET_SGE_CONTEXT, &cntxt); 196354912308SNavdeep Parhar if (rc != 0) 196454912308SNavdeep Parhar return (rc); 196554912308SNavdeep Parhar 196654912308SNavdeep Parhar if (chip_id == 4) 196754912308SNavdeep Parhar show_t4_ctxt(&cntxt); 196854912308SNavdeep Parhar else 196954912308SNavdeep Parhar show_t5t6_ctxt(&cntxt, chip_id); 197054912308SNavdeep Parhar 197154912308SNavdeep Parhar return (0); 197254912308SNavdeep Parhar } 197354912308SNavdeep Parhar 197454912308SNavdeep Parhar static int 197554912308SNavdeep Parhar loadfw(int argc, const char *argv[]) 197654912308SNavdeep Parhar { 197754912308SNavdeep Parhar int rc, fd; 197854912308SNavdeep Parhar struct t4_data data = {0}; 197954912308SNavdeep Parhar const char *fname = argv[0]; 198054912308SNavdeep Parhar struct stat st = {0}; 198154912308SNavdeep Parhar 198254912308SNavdeep Parhar if (argc != 1) { 198354912308SNavdeep Parhar warnx("loadfw: incorrect number of arguments."); 198454912308SNavdeep Parhar return (EINVAL); 198554912308SNavdeep Parhar } 198654912308SNavdeep Parhar 198754912308SNavdeep Parhar fd = open(fname, O_RDONLY); 198854912308SNavdeep Parhar if (fd < 0) { 198954912308SNavdeep Parhar warn("open(%s)", fname); 199054912308SNavdeep Parhar return (errno); 199154912308SNavdeep Parhar } 199254912308SNavdeep Parhar 199354912308SNavdeep Parhar if (fstat(fd, &st) < 0) { 199454912308SNavdeep Parhar warn("fstat"); 199554912308SNavdeep Parhar close(fd); 199654912308SNavdeep Parhar return (errno); 199754912308SNavdeep Parhar } 199854912308SNavdeep Parhar 199954912308SNavdeep Parhar data.len = st.st_size; 200054912308SNavdeep Parhar data.data = mmap(0, data.len, PROT_READ, MAP_PRIVATE, fd, 0); 200154912308SNavdeep Parhar if (data.data == MAP_FAILED) { 200254912308SNavdeep Parhar warn("mmap"); 200354912308SNavdeep Parhar close(fd); 200454912308SNavdeep Parhar return (errno); 200554912308SNavdeep Parhar } 200654912308SNavdeep Parhar 200754912308SNavdeep Parhar rc = doit(CHELSIO_T4_LOAD_FW, &data); 200854912308SNavdeep Parhar munmap(data.data, data.len); 200954912308SNavdeep Parhar close(fd); 201054912308SNavdeep Parhar return (rc); 201154912308SNavdeep Parhar } 201254912308SNavdeep Parhar 201354912308SNavdeep Parhar static int 201454912308SNavdeep Parhar loadcfg(int argc, const char *argv[]) 201554912308SNavdeep Parhar { 201654912308SNavdeep Parhar int rc, fd; 201754912308SNavdeep Parhar struct t4_data data = {0}; 201854912308SNavdeep Parhar const char *fname = argv[0]; 201954912308SNavdeep Parhar struct stat st = {0}; 202054912308SNavdeep Parhar 202154912308SNavdeep Parhar if (argc != 1) { 202254912308SNavdeep Parhar warnx("loadcfg: incorrect number of arguments."); 202354912308SNavdeep Parhar return (EINVAL); 202454912308SNavdeep Parhar } 202554912308SNavdeep Parhar 202654912308SNavdeep Parhar if (strcmp(fname, "clear") == 0) 202754912308SNavdeep Parhar return (doit(CHELSIO_T4_LOAD_CFG, &data)); 202854912308SNavdeep Parhar 202954912308SNavdeep Parhar fd = open(fname, O_RDONLY); 203054912308SNavdeep Parhar if (fd < 0) { 203154912308SNavdeep Parhar warn("open(%s)", fname); 203254912308SNavdeep Parhar return (errno); 203354912308SNavdeep Parhar } 203454912308SNavdeep Parhar 203554912308SNavdeep Parhar if (fstat(fd, &st) < 0) { 203654912308SNavdeep Parhar warn("fstat"); 203754912308SNavdeep Parhar close(fd); 203854912308SNavdeep Parhar return (errno); 203954912308SNavdeep Parhar } 204054912308SNavdeep Parhar 204154912308SNavdeep Parhar data.len = st.st_size; 204254912308SNavdeep Parhar data.len &= ~3; /* Clip off to make it a multiple of 4 */ 204354912308SNavdeep Parhar data.data = mmap(0, data.len, PROT_READ, MAP_PRIVATE, fd, 0); 204454912308SNavdeep Parhar if (data.data == MAP_FAILED) { 204554912308SNavdeep Parhar warn("mmap"); 204654912308SNavdeep Parhar close(fd); 204754912308SNavdeep Parhar return (errno); 204854912308SNavdeep Parhar } 204954912308SNavdeep Parhar 205054912308SNavdeep Parhar rc = doit(CHELSIO_T4_LOAD_CFG, &data); 205154912308SNavdeep Parhar munmap(data.data, data.len); 205254912308SNavdeep Parhar close(fd); 205354912308SNavdeep Parhar return (rc); 205454912308SNavdeep Parhar } 205554912308SNavdeep Parhar 205654912308SNavdeep Parhar static int 2057f856f099SNavdeep Parhar dumpstate(int argc, const char *argv[]) 2058f856f099SNavdeep Parhar { 2059f856f099SNavdeep Parhar int rc, fd; 2060f856f099SNavdeep Parhar struct t4_cudbg_dump dump = {0}; 2061f856f099SNavdeep Parhar const char *fname = argv[0]; 2062f856f099SNavdeep Parhar 2063f856f099SNavdeep Parhar if (argc != 1) { 2064f856f099SNavdeep Parhar warnx("dumpstate: incorrect number of arguments."); 2065f856f099SNavdeep Parhar return (EINVAL); 2066f856f099SNavdeep Parhar } 2067f856f099SNavdeep Parhar 2068f856f099SNavdeep Parhar dump.wr_flash = 0; 2069f856f099SNavdeep Parhar memset(&dump.bitmap, 0xff, sizeof(dump.bitmap)); 2070f856f099SNavdeep Parhar dump.len = 8 * 1024 * 1024; 2071f856f099SNavdeep Parhar dump.data = malloc(dump.len); 2072f856f099SNavdeep Parhar if (dump.data == NULL) { 2073f856f099SNavdeep Parhar return (ENOMEM); 2074f856f099SNavdeep Parhar } 2075f856f099SNavdeep Parhar 2076f856f099SNavdeep Parhar rc = doit(CHELSIO_T4_CUDBG_DUMP, &dump); 2077313a6435SNavdeep Parhar if (rc != 0) 2078313a6435SNavdeep Parhar goto done; 2079313a6435SNavdeep Parhar 2080313a6435SNavdeep Parhar fd = open(fname, O_CREAT | O_TRUNC | O_EXCL | O_WRONLY, 2081313a6435SNavdeep Parhar S_IRUSR | S_IRGRP | S_IROTH); 2082313a6435SNavdeep Parhar if (fd < 0) { 2083313a6435SNavdeep Parhar warn("open(%s)", fname); 2084313a6435SNavdeep Parhar rc = errno; 2085313a6435SNavdeep Parhar goto done; 2086313a6435SNavdeep Parhar } 2087f856f099SNavdeep Parhar write(fd, dump.data, dump.len); 2088f856f099SNavdeep Parhar close(fd); 2089313a6435SNavdeep Parhar done: 2090313a6435SNavdeep Parhar free(dump.data); 2091f856f099SNavdeep Parhar return (rc); 2092f856f099SNavdeep Parhar } 2093f856f099SNavdeep Parhar 2094f856f099SNavdeep Parhar static int 209554912308SNavdeep Parhar read_mem(uint32_t addr, uint32_t len, void (*output)(uint32_t *, uint32_t)) 209654912308SNavdeep Parhar { 209754912308SNavdeep Parhar int rc; 209854912308SNavdeep Parhar struct t4_mem_range mr; 209954912308SNavdeep Parhar 210054912308SNavdeep Parhar mr.addr = addr; 210154912308SNavdeep Parhar mr.len = len; 210254912308SNavdeep Parhar mr.data = malloc(mr.len); 210354912308SNavdeep Parhar 210454912308SNavdeep Parhar if (mr.data == 0) { 210554912308SNavdeep Parhar warn("read_mem: malloc"); 210654912308SNavdeep Parhar return (errno); 210754912308SNavdeep Parhar } 210854912308SNavdeep Parhar 210954912308SNavdeep Parhar rc = doit(CHELSIO_T4_GET_MEM, &mr); 211054912308SNavdeep Parhar if (rc != 0) 211154912308SNavdeep Parhar goto done; 211254912308SNavdeep Parhar 211354912308SNavdeep Parhar if (output) 211454912308SNavdeep Parhar (*output)(mr.data, mr.len); 211554912308SNavdeep Parhar done: 211654912308SNavdeep Parhar free(mr.data); 211754912308SNavdeep Parhar return (rc); 211854912308SNavdeep Parhar } 211954912308SNavdeep Parhar 21208f82718fSNavdeep Parhar static int 21218f82718fSNavdeep Parhar loadboot(int argc, const char *argv[]) 21228f82718fSNavdeep Parhar { 21238f82718fSNavdeep Parhar int rc, fd; 21248f82718fSNavdeep Parhar long l; 21258f82718fSNavdeep Parhar char *p; 21268f82718fSNavdeep Parhar struct t4_bootrom br = {0}; 21278f82718fSNavdeep Parhar const char *fname = argv[0]; 21288f82718fSNavdeep Parhar struct stat st = {0}; 21298f82718fSNavdeep Parhar 21308f82718fSNavdeep Parhar if (argc == 1) { 21318f82718fSNavdeep Parhar br.pf_offset = 0; 21328f82718fSNavdeep Parhar br.pfidx_addr = 0; 21338f82718fSNavdeep Parhar } else if (argc == 3) { 21348f82718fSNavdeep Parhar if (!strcmp(argv[1], "pf")) 21358f82718fSNavdeep Parhar br.pf_offset = 0; 21368f82718fSNavdeep Parhar else if (!strcmp(argv[1], "offset")) 21378f82718fSNavdeep Parhar br.pf_offset = 1; 21388f82718fSNavdeep Parhar else 21398f82718fSNavdeep Parhar return (EINVAL); 21408f82718fSNavdeep Parhar 21418f82718fSNavdeep Parhar p = str_to_number(argv[2], &l, NULL); 21428f82718fSNavdeep Parhar if (*p) 21438f82718fSNavdeep Parhar return (EINVAL); 21448f82718fSNavdeep Parhar br.pfidx_addr = l; 21458f82718fSNavdeep Parhar } else { 21468f82718fSNavdeep Parhar warnx("loadboot: incorrect number of arguments."); 21478f82718fSNavdeep Parhar return (EINVAL); 21488f82718fSNavdeep Parhar } 21498f82718fSNavdeep Parhar 21508f82718fSNavdeep Parhar if (strcmp(fname, "clear") == 0) 21518f82718fSNavdeep Parhar return (doit(CHELSIO_T4_LOAD_BOOT, &br)); 21528f82718fSNavdeep Parhar 21538f82718fSNavdeep Parhar fd = open(fname, O_RDONLY); 21548f82718fSNavdeep Parhar if (fd < 0) { 21558f82718fSNavdeep Parhar warn("open(%s)", fname); 21568f82718fSNavdeep Parhar return (errno); 21578f82718fSNavdeep Parhar } 21588f82718fSNavdeep Parhar 21598f82718fSNavdeep Parhar if (fstat(fd, &st) < 0) { 21608f82718fSNavdeep Parhar warn("fstat"); 21618f82718fSNavdeep Parhar close(fd); 21628f82718fSNavdeep Parhar return (errno); 21638f82718fSNavdeep Parhar } 21648f82718fSNavdeep Parhar 21658f82718fSNavdeep Parhar br.len = st.st_size; 21668f82718fSNavdeep Parhar br.data = mmap(0, br.len, PROT_READ, MAP_PRIVATE, fd, 0); 21678f82718fSNavdeep Parhar if (br.data == MAP_FAILED) { 21688f82718fSNavdeep Parhar warn("mmap"); 21698f82718fSNavdeep Parhar close(fd); 21708f82718fSNavdeep Parhar return (errno); 21718f82718fSNavdeep Parhar } 21728f82718fSNavdeep Parhar 21738f82718fSNavdeep Parhar rc = doit(CHELSIO_T4_LOAD_BOOT, &br); 21748f82718fSNavdeep Parhar munmap(br.data, br.len); 21758f82718fSNavdeep Parhar close(fd); 21768f82718fSNavdeep Parhar return (rc); 21778f82718fSNavdeep Parhar } 21788f82718fSNavdeep Parhar 21798f82718fSNavdeep Parhar static int 21808f82718fSNavdeep Parhar loadbootcfg(int argc, const char *argv[]) 21818f82718fSNavdeep Parhar { 21828f82718fSNavdeep Parhar int rc, fd; 21838f82718fSNavdeep Parhar struct t4_data bc = {0}; 21848f82718fSNavdeep Parhar const char *fname = argv[0]; 21858f82718fSNavdeep Parhar struct stat st = {0}; 21868f82718fSNavdeep Parhar 21878f82718fSNavdeep Parhar if (argc != 1) { 21888f82718fSNavdeep Parhar warnx("loadbootcfg: incorrect number of arguments."); 21898f82718fSNavdeep Parhar return (EINVAL); 21908f82718fSNavdeep Parhar } 21918f82718fSNavdeep Parhar 21928f82718fSNavdeep Parhar if (strcmp(fname, "clear") == 0) 21938f82718fSNavdeep Parhar return (doit(CHELSIO_T4_LOAD_BOOTCFG, &bc)); 21948f82718fSNavdeep Parhar 21958f82718fSNavdeep Parhar fd = open(fname, O_RDONLY); 21968f82718fSNavdeep Parhar if (fd < 0) { 21978f82718fSNavdeep Parhar warn("open(%s)", fname); 21988f82718fSNavdeep Parhar return (errno); 21998f82718fSNavdeep Parhar } 22008f82718fSNavdeep Parhar 22018f82718fSNavdeep Parhar if (fstat(fd, &st) < 0) { 22028f82718fSNavdeep Parhar warn("fstat"); 22038f82718fSNavdeep Parhar close(fd); 22048f82718fSNavdeep Parhar return (errno); 22058f82718fSNavdeep Parhar } 22068f82718fSNavdeep Parhar 22078f82718fSNavdeep Parhar bc.len = st.st_size; 22088f82718fSNavdeep Parhar bc.data = mmap(0, bc.len, PROT_READ, MAP_PRIVATE, fd, 0); 22098f82718fSNavdeep Parhar if (bc.data == MAP_FAILED) { 22108f82718fSNavdeep Parhar warn("mmap"); 22118f82718fSNavdeep Parhar close(fd); 22128f82718fSNavdeep Parhar return (errno); 22138f82718fSNavdeep Parhar } 22148f82718fSNavdeep Parhar 22158f82718fSNavdeep Parhar rc = doit(CHELSIO_T4_LOAD_BOOTCFG, &bc); 22168f82718fSNavdeep Parhar munmap(bc.data, bc.len); 22178f82718fSNavdeep Parhar close(fd); 22188f82718fSNavdeep Parhar return (rc); 22198f82718fSNavdeep Parhar } 22208f82718fSNavdeep Parhar 222154912308SNavdeep Parhar /* 222254912308SNavdeep Parhar * Display memory as list of 'n' 4-byte values per line. 222354912308SNavdeep Parhar */ 222454912308SNavdeep Parhar static void 222554912308SNavdeep Parhar show_mem(uint32_t *buf, uint32_t len) 222654912308SNavdeep Parhar { 222754912308SNavdeep Parhar const char *s; 222854912308SNavdeep Parhar int i, n = 8; 222954912308SNavdeep Parhar 223054912308SNavdeep Parhar while (len) { 223154912308SNavdeep Parhar for (i = 0; len && i < n; i++, buf++, len -= 4) { 223254912308SNavdeep Parhar s = i ? " " : ""; 223354912308SNavdeep Parhar printf("%s%08x", s, htonl(*buf)); 223454912308SNavdeep Parhar } 223554912308SNavdeep Parhar printf("\n"); 223654912308SNavdeep Parhar } 223754912308SNavdeep Parhar } 223854912308SNavdeep Parhar 223954912308SNavdeep Parhar static int 224054912308SNavdeep Parhar memdump(int argc, const char *argv[]) 224154912308SNavdeep Parhar { 224254912308SNavdeep Parhar char *p; 224354912308SNavdeep Parhar long l; 224454912308SNavdeep Parhar uint32_t addr, len; 224554912308SNavdeep Parhar 224654912308SNavdeep Parhar if (argc != 2) { 224754912308SNavdeep Parhar warnx("incorrect number of arguments."); 224854912308SNavdeep Parhar return (EINVAL); 224954912308SNavdeep Parhar } 225054912308SNavdeep Parhar 225154912308SNavdeep Parhar p = str_to_number(argv[0], &l, NULL); 225254912308SNavdeep Parhar if (*p) { 225354912308SNavdeep Parhar warnx("invalid address \"%s\"", argv[0]); 225454912308SNavdeep Parhar return (EINVAL); 225554912308SNavdeep Parhar } 225654912308SNavdeep Parhar addr = l; 225754912308SNavdeep Parhar 225854912308SNavdeep Parhar p = str_to_number(argv[1], &l, NULL); 225954912308SNavdeep Parhar if (*p) { 226054912308SNavdeep Parhar warnx("memdump: invalid length \"%s\"", argv[1]); 226154912308SNavdeep Parhar return (EINVAL); 226254912308SNavdeep Parhar } 226354912308SNavdeep Parhar len = l; 226454912308SNavdeep Parhar 226554912308SNavdeep Parhar return (read_mem(addr, len, show_mem)); 226654912308SNavdeep Parhar } 226754912308SNavdeep Parhar 226854912308SNavdeep Parhar /* 226954912308SNavdeep Parhar * Display TCB as list of 'n' 4-byte values per line. 227054912308SNavdeep Parhar */ 227154912308SNavdeep Parhar static void 227254912308SNavdeep Parhar show_tcb(uint32_t *buf, uint32_t len) 227354912308SNavdeep Parhar { 2274ae9b4017SNavdeep Parhar unsigned char *tcb = (unsigned char *)buf; 227554912308SNavdeep Parhar const char *s; 227654912308SNavdeep Parhar int i, n = 8; 227754912308SNavdeep Parhar 227854912308SNavdeep Parhar while (len) { 227954912308SNavdeep Parhar for (i = 0; len && i < n; i++, buf++, len -= 4) { 228054912308SNavdeep Parhar s = i ? " " : ""; 228154912308SNavdeep Parhar printf("%s%08x", s, htonl(*buf)); 228254912308SNavdeep Parhar } 228354912308SNavdeep Parhar printf("\n"); 228454912308SNavdeep Parhar } 2285ae9b4017SNavdeep Parhar set_tcb_info(TIDTYPE_TCB, chip_id); 2286ae9b4017SNavdeep Parhar set_print_style(PRNTSTYL_COMP); 2287ae9b4017SNavdeep Parhar swizzle_tcb(tcb); 2288ae9b4017SNavdeep Parhar parse_n_display_xcb(tcb); 228954912308SNavdeep Parhar } 229054912308SNavdeep Parhar 229154912308SNavdeep Parhar #define A_TP_CMM_TCB_BASE 0x7d10 229254912308SNavdeep Parhar #define TCB_SIZE 128 229354912308SNavdeep Parhar static int 229454912308SNavdeep Parhar read_tcb(int argc, const char *argv[]) 229554912308SNavdeep Parhar { 229654912308SNavdeep Parhar char *p; 229754912308SNavdeep Parhar long l; 229854912308SNavdeep Parhar long long val; 229954912308SNavdeep Parhar unsigned int tid; 230054912308SNavdeep Parhar uint32_t addr; 230154912308SNavdeep Parhar int rc; 230254912308SNavdeep Parhar 230354912308SNavdeep Parhar if (argc != 1) { 230454912308SNavdeep Parhar warnx("incorrect number of arguments."); 230554912308SNavdeep Parhar return (EINVAL); 230654912308SNavdeep Parhar } 230754912308SNavdeep Parhar 230854912308SNavdeep Parhar p = str_to_number(argv[0], &l, NULL); 230954912308SNavdeep Parhar if (*p) { 231054912308SNavdeep Parhar warnx("invalid tid \"%s\"", argv[0]); 231154912308SNavdeep Parhar return (EINVAL); 231254912308SNavdeep Parhar } 231354912308SNavdeep Parhar tid = l; 231454912308SNavdeep Parhar 231554912308SNavdeep Parhar rc = read_reg(A_TP_CMM_TCB_BASE, 4, &val); 231654912308SNavdeep Parhar if (rc != 0) 231754912308SNavdeep Parhar return (rc); 231854912308SNavdeep Parhar 231954912308SNavdeep Parhar addr = val + tid * TCB_SIZE; 232054912308SNavdeep Parhar 232154912308SNavdeep Parhar return (read_mem(addr, TCB_SIZE, show_tcb)); 232254912308SNavdeep Parhar } 232354912308SNavdeep Parhar 232454912308SNavdeep Parhar static int 232554912308SNavdeep Parhar read_i2c(int argc, const char *argv[]) 232654912308SNavdeep Parhar { 232754912308SNavdeep Parhar char *p; 232854912308SNavdeep Parhar long l; 232954912308SNavdeep Parhar struct t4_i2c_data i2cd; 233054912308SNavdeep Parhar int rc, i; 233154912308SNavdeep Parhar 233254912308SNavdeep Parhar if (argc < 3 || argc > 4) { 233354912308SNavdeep Parhar warnx("incorrect number of arguments."); 233454912308SNavdeep Parhar return (EINVAL); 233554912308SNavdeep Parhar } 233654912308SNavdeep Parhar 233754912308SNavdeep Parhar p = str_to_number(argv[0], &l, NULL); 233854912308SNavdeep Parhar if (*p || l > UCHAR_MAX) { 233954912308SNavdeep Parhar warnx("invalid port id \"%s\"", argv[0]); 234054912308SNavdeep Parhar return (EINVAL); 234154912308SNavdeep Parhar } 234254912308SNavdeep Parhar i2cd.port_id = l; 234354912308SNavdeep Parhar 234454912308SNavdeep Parhar p = str_to_number(argv[1], &l, NULL); 234554912308SNavdeep Parhar if (*p || l > UCHAR_MAX) { 234654912308SNavdeep Parhar warnx("invalid i2c device address \"%s\"", argv[1]); 234754912308SNavdeep Parhar return (EINVAL); 234854912308SNavdeep Parhar } 234954912308SNavdeep Parhar i2cd.dev_addr = l; 235054912308SNavdeep Parhar 235154912308SNavdeep Parhar p = str_to_number(argv[2], &l, NULL); 235254912308SNavdeep Parhar if (*p || l > UCHAR_MAX) { 235354912308SNavdeep Parhar warnx("invalid byte offset \"%s\"", argv[2]); 235454912308SNavdeep Parhar return (EINVAL); 235554912308SNavdeep Parhar } 235654912308SNavdeep Parhar i2cd.offset = l; 235754912308SNavdeep Parhar 235854912308SNavdeep Parhar if (argc == 4) { 235954912308SNavdeep Parhar p = str_to_number(argv[3], &l, NULL); 236054912308SNavdeep Parhar if (*p || l > sizeof(i2cd.data)) { 236154912308SNavdeep Parhar warnx("invalid number of bytes \"%s\"", argv[3]); 236254912308SNavdeep Parhar return (EINVAL); 236354912308SNavdeep Parhar } 236454912308SNavdeep Parhar i2cd.len = l; 236554912308SNavdeep Parhar } else 236654912308SNavdeep Parhar i2cd.len = 1; 236754912308SNavdeep Parhar 236854912308SNavdeep Parhar rc = doit(CHELSIO_T4_GET_I2C, &i2cd); 236954912308SNavdeep Parhar if (rc != 0) 237054912308SNavdeep Parhar return (rc); 237154912308SNavdeep Parhar 237254912308SNavdeep Parhar for (i = 0; i < i2cd.len; i++) 237354912308SNavdeep Parhar printf("0x%x [%u]\n", i2cd.data[i], i2cd.data[i]); 237454912308SNavdeep Parhar 237554912308SNavdeep Parhar return (0); 237654912308SNavdeep Parhar } 237754912308SNavdeep Parhar 237854912308SNavdeep Parhar static int 237954912308SNavdeep Parhar clearstats(int argc, const char *argv[]) 238054912308SNavdeep Parhar { 238154912308SNavdeep Parhar char *p; 238254912308SNavdeep Parhar long l; 238354912308SNavdeep Parhar uint32_t port; 238454912308SNavdeep Parhar 238554912308SNavdeep Parhar if (argc != 1) { 238654912308SNavdeep Parhar warnx("incorrect number of arguments."); 238754912308SNavdeep Parhar return (EINVAL); 238854912308SNavdeep Parhar } 238954912308SNavdeep Parhar 239054912308SNavdeep Parhar p = str_to_number(argv[0], &l, NULL); 239154912308SNavdeep Parhar if (*p) { 239254912308SNavdeep Parhar warnx("invalid port id \"%s\"", argv[0]); 239354912308SNavdeep Parhar return (EINVAL); 239454912308SNavdeep Parhar } 239554912308SNavdeep Parhar port = l; 239654912308SNavdeep Parhar 239754912308SNavdeep Parhar return doit(CHELSIO_T4_CLEAR_STATS, &port); 239854912308SNavdeep Parhar } 239954912308SNavdeep Parhar 240054912308SNavdeep Parhar static int 240154912308SNavdeep Parhar show_tracers(void) 240254912308SNavdeep Parhar { 240354912308SNavdeep Parhar struct t4_tracer t; 240454912308SNavdeep Parhar char *s; 240554912308SNavdeep Parhar int rc, port_idx, i; 240654912308SNavdeep Parhar long long val; 240754912308SNavdeep Parhar 240854912308SNavdeep Parhar /* Magic values: MPS_TRC_CFG = 0x9800. MPS_TRC_CFG[1:1] = TrcEn */ 240954912308SNavdeep Parhar rc = read_reg(0x9800, 4, &val); 241054912308SNavdeep Parhar if (rc != 0) 241154912308SNavdeep Parhar return (rc); 241254912308SNavdeep Parhar printf("tracing is %s\n", val & 2 ? "ENABLED" : "DISABLED"); 241354912308SNavdeep Parhar 241454912308SNavdeep Parhar t.idx = 0; 241554912308SNavdeep Parhar for (t.idx = 0; ; t.idx++) { 241654912308SNavdeep Parhar rc = doit(CHELSIO_T4_GET_TRACER, &t); 241754912308SNavdeep Parhar if (rc != 0 || t.idx == 0xff) 241854912308SNavdeep Parhar break; 241954912308SNavdeep Parhar 242054912308SNavdeep Parhar if (t.tp.port < 4) { 242154912308SNavdeep Parhar s = "Rx"; 242254912308SNavdeep Parhar port_idx = t.tp.port; 242354912308SNavdeep Parhar } else if (t.tp.port < 8) { 242454912308SNavdeep Parhar s = "Tx"; 242554912308SNavdeep Parhar port_idx = t.tp.port - 4; 242654912308SNavdeep Parhar } else if (t.tp.port < 12) { 242754912308SNavdeep Parhar s = "loopback"; 242854912308SNavdeep Parhar port_idx = t.tp.port - 8; 242954912308SNavdeep Parhar } else if (t.tp.port < 16) { 243054912308SNavdeep Parhar s = "MPS Rx"; 243154912308SNavdeep Parhar port_idx = t.tp.port - 12; 243254912308SNavdeep Parhar } else if (t.tp.port < 20) { 243354912308SNavdeep Parhar s = "MPS Tx"; 243454912308SNavdeep Parhar port_idx = t.tp.port - 16; 243554912308SNavdeep Parhar } else { 243654912308SNavdeep Parhar s = "unknown"; 243754912308SNavdeep Parhar port_idx = t.tp.port; 243854912308SNavdeep Parhar } 243954912308SNavdeep Parhar 244054912308SNavdeep Parhar printf("\ntracer %u (currently %s) captures ", t.idx, 244154912308SNavdeep Parhar t.enabled ? "ENABLED" : "DISABLED"); 244254912308SNavdeep Parhar if (t.tp.port < 8) 244354912308SNavdeep Parhar printf("port %u %s, ", port_idx, s); 244454912308SNavdeep Parhar else 244554912308SNavdeep Parhar printf("%s %u, ", s, port_idx); 244654912308SNavdeep Parhar printf("snap length: %u, min length: %u\n", t.tp.snap_len, 244754912308SNavdeep Parhar t.tp.min_len); 244854912308SNavdeep Parhar printf("packets captured %smatch filter\n", 244954912308SNavdeep Parhar t.tp.invert ? "do not " : ""); 245054912308SNavdeep Parhar if (t.tp.skip_ofst) { 245154912308SNavdeep Parhar printf("filter pattern: "); 245254912308SNavdeep Parhar for (i = 0; i < t.tp.skip_ofst * 2; i += 2) 245354912308SNavdeep Parhar printf("%08x%08x", t.tp.data[i], 245454912308SNavdeep Parhar t.tp.data[i + 1]); 245554912308SNavdeep Parhar printf("/"); 245654912308SNavdeep Parhar for (i = 0; i < t.tp.skip_ofst * 2; i += 2) 245754912308SNavdeep Parhar printf("%08x%08x", t.tp.mask[i], 245854912308SNavdeep Parhar t.tp.mask[i + 1]); 245954912308SNavdeep Parhar printf("@0\n"); 246054912308SNavdeep Parhar } 246154912308SNavdeep Parhar printf("filter pattern: "); 246254912308SNavdeep Parhar for (i = t.tp.skip_ofst * 2; i < T4_TRACE_LEN / 4; i += 2) 246354912308SNavdeep Parhar printf("%08x%08x", t.tp.data[i], t.tp.data[i + 1]); 246454912308SNavdeep Parhar printf("/"); 246554912308SNavdeep Parhar for (i = t.tp.skip_ofst * 2; i < T4_TRACE_LEN / 4; i += 2) 246654912308SNavdeep Parhar printf("%08x%08x", t.tp.mask[i], t.tp.mask[i + 1]); 246754912308SNavdeep Parhar printf("@%u\n", (t.tp.skip_ofst + t.tp.skip_len) * 8); 246854912308SNavdeep Parhar } 246954912308SNavdeep Parhar 247054912308SNavdeep Parhar return (rc); 247154912308SNavdeep Parhar } 247254912308SNavdeep Parhar 247354912308SNavdeep Parhar static int 247454912308SNavdeep Parhar tracer_onoff(uint8_t idx, int enabled) 247554912308SNavdeep Parhar { 247654912308SNavdeep Parhar struct t4_tracer t; 247754912308SNavdeep Parhar 247854912308SNavdeep Parhar t.idx = idx; 247954912308SNavdeep Parhar t.enabled = enabled; 248054912308SNavdeep Parhar t.valid = 0; 248154912308SNavdeep Parhar 248254912308SNavdeep Parhar return doit(CHELSIO_T4_SET_TRACER, &t); 248354912308SNavdeep Parhar } 248454912308SNavdeep Parhar 248554912308SNavdeep Parhar static void 248654912308SNavdeep Parhar create_tracing_ifnet() 248754912308SNavdeep Parhar { 248854912308SNavdeep Parhar char *cmd[] = { 248954912308SNavdeep Parhar "/sbin/ifconfig", __DECONST(char *, nexus), "create", NULL 249054912308SNavdeep Parhar }; 249154912308SNavdeep Parhar char *env[] = {NULL}; 249254912308SNavdeep Parhar 249354912308SNavdeep Parhar if (vfork() == 0) { 249454912308SNavdeep Parhar close(STDERR_FILENO); 249554912308SNavdeep Parhar execve(cmd[0], cmd, env); 249654912308SNavdeep Parhar _exit(0); 249754912308SNavdeep Parhar } 249854912308SNavdeep Parhar } 249954912308SNavdeep Parhar 250054912308SNavdeep Parhar /* 250154912308SNavdeep Parhar * XXX: Allow user to specify snaplen, minlen, and pattern (including inverted 250254912308SNavdeep Parhar * matching). Right now this is a quick-n-dirty implementation that traces the 250354912308SNavdeep Parhar * first 128B of all tx or rx on a port 250454912308SNavdeep Parhar */ 250554912308SNavdeep Parhar static int 250654912308SNavdeep Parhar set_tracer(uint8_t idx, int argc, const char *argv[]) 250754912308SNavdeep Parhar { 250854912308SNavdeep Parhar struct t4_tracer t; 250954912308SNavdeep Parhar int len, port; 251054912308SNavdeep Parhar 251154912308SNavdeep Parhar bzero(&t, sizeof (t)); 251254912308SNavdeep Parhar t.idx = idx; 251354912308SNavdeep Parhar t.enabled = 1; 251454912308SNavdeep Parhar t.valid = 1; 251554912308SNavdeep Parhar 251654912308SNavdeep Parhar if (argc != 1) { 251754912308SNavdeep Parhar warnx("must specify tx<n> or rx<n>."); 251854912308SNavdeep Parhar return (EINVAL); 251954912308SNavdeep Parhar } 252054912308SNavdeep Parhar 252154912308SNavdeep Parhar len = strlen(argv[0]); 252254912308SNavdeep Parhar if (len != 3) { 252354912308SNavdeep Parhar warnx("argument must be 3 characters (tx<n> or rx<n>)"); 252454912308SNavdeep Parhar return (EINVAL); 252554912308SNavdeep Parhar } 252654912308SNavdeep Parhar 252754912308SNavdeep Parhar if (strncmp(argv[0], "tx", 2) == 0) { 252854912308SNavdeep Parhar port = argv[0][2] - '0'; 252954912308SNavdeep Parhar if (port < 0 || port > 3) { 253054912308SNavdeep Parhar warnx("'%c' in %s is invalid", argv[0][2], argv[0]); 253154912308SNavdeep Parhar return (EINVAL); 253254912308SNavdeep Parhar } 253354912308SNavdeep Parhar port += 4; 253454912308SNavdeep Parhar } else if (strncmp(argv[0], "rx", 2) == 0) { 253554912308SNavdeep Parhar port = argv[0][2] - '0'; 253654912308SNavdeep Parhar if (port < 0 || port > 3) { 253754912308SNavdeep Parhar warnx("'%c' in %s is invalid", argv[0][2], argv[0]); 253854912308SNavdeep Parhar return (EINVAL); 253954912308SNavdeep Parhar } 254054912308SNavdeep Parhar } else { 254154912308SNavdeep Parhar warnx("argument '%s' isn't tx<n> or rx<n>", argv[0]); 254254912308SNavdeep Parhar return (EINVAL); 254354912308SNavdeep Parhar } 254454912308SNavdeep Parhar 254554912308SNavdeep Parhar t.tp.snap_len = 128; 254654912308SNavdeep Parhar t.tp.min_len = 0; 254754912308SNavdeep Parhar t.tp.skip_ofst = 0; 254854912308SNavdeep Parhar t.tp.skip_len = 0; 254954912308SNavdeep Parhar t.tp.invert = 0; 255054912308SNavdeep Parhar t.tp.port = port; 255154912308SNavdeep Parhar 255254912308SNavdeep Parhar create_tracing_ifnet(); 255354912308SNavdeep Parhar return doit(CHELSIO_T4_SET_TRACER, &t); 255454912308SNavdeep Parhar } 255554912308SNavdeep Parhar 255654912308SNavdeep Parhar static int 255754912308SNavdeep Parhar tracer_cmd(int argc, const char *argv[]) 255854912308SNavdeep Parhar { 255954912308SNavdeep Parhar long long val; 256054912308SNavdeep Parhar uint8_t idx; 256154912308SNavdeep Parhar char *s; 256254912308SNavdeep Parhar 256354912308SNavdeep Parhar if (argc == 0) { 256454912308SNavdeep Parhar warnx("tracer: no arguments."); 256554912308SNavdeep Parhar return (EINVAL); 256654912308SNavdeep Parhar }; 256754912308SNavdeep Parhar 256854912308SNavdeep Parhar /* list */ 256954912308SNavdeep Parhar if (strcmp(argv[0], "list") == 0) { 257054912308SNavdeep Parhar if (argc != 1) 257154912308SNavdeep Parhar warnx("trailing arguments after \"list\" ignored."); 257254912308SNavdeep Parhar 257354912308SNavdeep Parhar return show_tracers(); 257454912308SNavdeep Parhar } 257554912308SNavdeep Parhar 257654912308SNavdeep Parhar /* <idx> ... */ 257754912308SNavdeep Parhar s = str_to_number(argv[0], NULL, &val); 257854912308SNavdeep Parhar if (*s || val > 0xff) { 257954912308SNavdeep Parhar warnx("\"%s\" is neither an index nor a tracer subcommand.", 258054912308SNavdeep Parhar argv[0]); 258154912308SNavdeep Parhar return (EINVAL); 258254912308SNavdeep Parhar } 258354912308SNavdeep Parhar idx = (int8_t)val; 258454912308SNavdeep Parhar 258554912308SNavdeep Parhar /* <idx> disable */ 258654912308SNavdeep Parhar if (argc == 2 && strcmp(argv[1], "disable") == 0) 258754912308SNavdeep Parhar return tracer_onoff(idx, 0); 258854912308SNavdeep Parhar 258954912308SNavdeep Parhar /* <idx> enable */ 259054912308SNavdeep Parhar if (argc == 2 && strcmp(argv[1], "enable") == 0) 259154912308SNavdeep Parhar return tracer_onoff(idx, 1); 259254912308SNavdeep Parhar 259354912308SNavdeep Parhar /* <idx> ... */ 259454912308SNavdeep Parhar return set_tracer(idx, argc - 1, argv + 1); 259554912308SNavdeep Parhar } 259654912308SNavdeep Parhar 259754912308SNavdeep Parhar static int 259854912308SNavdeep Parhar modinfo_raw(int port_id) 259954912308SNavdeep Parhar { 260054912308SNavdeep Parhar uint8_t offset; 260154912308SNavdeep Parhar struct t4_i2c_data i2cd; 260254912308SNavdeep Parhar int rc; 260354912308SNavdeep Parhar 260454912308SNavdeep Parhar for (offset = 0; offset < 96; offset += sizeof(i2cd.data)) { 260554912308SNavdeep Parhar bzero(&i2cd, sizeof(i2cd)); 260654912308SNavdeep Parhar i2cd.port_id = port_id; 260754912308SNavdeep Parhar i2cd.dev_addr = 0xa0; 260854912308SNavdeep Parhar i2cd.offset = offset; 260954912308SNavdeep Parhar i2cd.len = sizeof(i2cd.data); 261054912308SNavdeep Parhar rc = doit(CHELSIO_T4_GET_I2C, &i2cd); 261154912308SNavdeep Parhar if (rc != 0) 261254912308SNavdeep Parhar return (rc); 261354912308SNavdeep Parhar printf("%02x: %02x %02x %02x %02x %02x %02x %02x %02x", 261454912308SNavdeep Parhar offset, i2cd.data[0], i2cd.data[1], i2cd.data[2], 261554912308SNavdeep Parhar i2cd.data[3], i2cd.data[4], i2cd.data[5], i2cd.data[6], 261654912308SNavdeep Parhar i2cd.data[7]); 261754912308SNavdeep Parhar 261854912308SNavdeep Parhar printf(" %c%c%c%c %c%c%c%c\n", 261954912308SNavdeep Parhar isprint(i2cd.data[0]) ? i2cd.data[0] : '.', 262054912308SNavdeep Parhar isprint(i2cd.data[1]) ? i2cd.data[1] : '.', 262154912308SNavdeep Parhar isprint(i2cd.data[2]) ? i2cd.data[2] : '.', 262254912308SNavdeep Parhar isprint(i2cd.data[3]) ? i2cd.data[3] : '.', 262354912308SNavdeep Parhar isprint(i2cd.data[4]) ? i2cd.data[4] : '.', 262454912308SNavdeep Parhar isprint(i2cd.data[5]) ? i2cd.data[5] : '.', 262554912308SNavdeep Parhar isprint(i2cd.data[6]) ? i2cd.data[6] : '.', 262654912308SNavdeep Parhar isprint(i2cd.data[7]) ? i2cd.data[7] : '.'); 262754912308SNavdeep Parhar } 262854912308SNavdeep Parhar 262954912308SNavdeep Parhar return (0); 263054912308SNavdeep Parhar } 263154912308SNavdeep Parhar 263254912308SNavdeep Parhar static int 263354912308SNavdeep Parhar modinfo(int argc, const char *argv[]) 263454912308SNavdeep Parhar { 263554912308SNavdeep Parhar long port; 263654912308SNavdeep Parhar char string[16], *p; 263754912308SNavdeep Parhar struct t4_i2c_data i2cd; 263854912308SNavdeep Parhar int rc, i; 263954912308SNavdeep Parhar uint16_t temp, vcc, tx_bias, tx_power, rx_power; 264054912308SNavdeep Parhar 264154912308SNavdeep Parhar if (argc < 1) { 264254912308SNavdeep Parhar warnx("must supply a port"); 264354912308SNavdeep Parhar return (EINVAL); 264454912308SNavdeep Parhar } 264554912308SNavdeep Parhar 264654912308SNavdeep Parhar if (argc > 2) { 264754912308SNavdeep Parhar warnx("too many arguments"); 264854912308SNavdeep Parhar return (EINVAL); 264954912308SNavdeep Parhar } 265054912308SNavdeep Parhar 265154912308SNavdeep Parhar p = str_to_number(argv[0], &port, NULL); 265254912308SNavdeep Parhar if (*p || port > UCHAR_MAX) { 265354912308SNavdeep Parhar warnx("invalid port id \"%s\"", argv[0]); 265454912308SNavdeep Parhar return (EINVAL); 265554912308SNavdeep Parhar } 265654912308SNavdeep Parhar 265754912308SNavdeep Parhar if (argc == 2) { 265854912308SNavdeep Parhar if (!strcmp(argv[1], "raw")) 265954912308SNavdeep Parhar return (modinfo_raw(port)); 266054912308SNavdeep Parhar else { 266154912308SNavdeep Parhar warnx("second argument can only be \"raw\""); 266254912308SNavdeep Parhar return (EINVAL); 266354912308SNavdeep Parhar } 266454912308SNavdeep Parhar } 266554912308SNavdeep Parhar 266654912308SNavdeep Parhar bzero(&i2cd, sizeof(i2cd)); 266754912308SNavdeep Parhar i2cd.len = 1; 266854912308SNavdeep Parhar i2cd.port_id = port; 266954912308SNavdeep Parhar i2cd.dev_addr = SFF_8472_BASE; 267054912308SNavdeep Parhar 267154912308SNavdeep Parhar i2cd.offset = SFF_8472_ID; 267254912308SNavdeep Parhar if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) 267354912308SNavdeep Parhar goto fail; 267454912308SNavdeep Parhar 267554912308SNavdeep Parhar if (i2cd.data[0] > SFF_8472_ID_LAST) 267654912308SNavdeep Parhar printf("Unknown ID\n"); 267754912308SNavdeep Parhar else 267854912308SNavdeep Parhar printf("ID: %s\n", sff_8472_id[i2cd.data[0]]); 267954912308SNavdeep Parhar 268054912308SNavdeep Parhar bzero(&string, sizeof(string)); 268154912308SNavdeep Parhar for (i = SFF_8472_VENDOR_START; i < SFF_8472_VENDOR_END; i++) { 268254912308SNavdeep Parhar i2cd.offset = i; 268354912308SNavdeep Parhar if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) 268454912308SNavdeep Parhar goto fail; 268554912308SNavdeep Parhar string[i - SFF_8472_VENDOR_START] = i2cd.data[0]; 268654912308SNavdeep Parhar } 268754912308SNavdeep Parhar printf("Vendor %s\n", string); 268854912308SNavdeep Parhar 268954912308SNavdeep Parhar bzero(&string, sizeof(string)); 269054912308SNavdeep Parhar for (i = SFF_8472_SN_START; i < SFF_8472_SN_END; i++) { 269154912308SNavdeep Parhar i2cd.offset = i; 269254912308SNavdeep Parhar if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) 269354912308SNavdeep Parhar goto fail; 269454912308SNavdeep Parhar string[i - SFF_8472_SN_START] = i2cd.data[0]; 269554912308SNavdeep Parhar } 269654912308SNavdeep Parhar printf("SN %s\n", string); 269754912308SNavdeep Parhar 269854912308SNavdeep Parhar bzero(&string, sizeof(string)); 269954912308SNavdeep Parhar for (i = SFF_8472_PN_START; i < SFF_8472_PN_END; i++) { 270054912308SNavdeep Parhar i2cd.offset = i; 270154912308SNavdeep Parhar if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) 270254912308SNavdeep Parhar goto fail; 270354912308SNavdeep Parhar string[i - SFF_8472_PN_START] = i2cd.data[0]; 270454912308SNavdeep Parhar } 270554912308SNavdeep Parhar printf("PN %s\n", string); 270654912308SNavdeep Parhar 270754912308SNavdeep Parhar bzero(&string, sizeof(string)); 270854912308SNavdeep Parhar for (i = SFF_8472_REV_START; i < SFF_8472_REV_END; i++) { 270954912308SNavdeep Parhar i2cd.offset = i; 271054912308SNavdeep Parhar if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) 271154912308SNavdeep Parhar goto fail; 271254912308SNavdeep Parhar string[i - SFF_8472_REV_START] = i2cd.data[0]; 271354912308SNavdeep Parhar } 271454912308SNavdeep Parhar printf("Rev %s\n", string); 271554912308SNavdeep Parhar 271654912308SNavdeep Parhar i2cd.offset = SFF_8472_DIAG_TYPE; 271754912308SNavdeep Parhar if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) 271854912308SNavdeep Parhar goto fail; 271954912308SNavdeep Parhar 272054912308SNavdeep Parhar if ((char )i2cd.data[0] & (SFF_8472_DIAG_IMPL | 272154912308SNavdeep Parhar SFF_8472_DIAG_INTERNAL)) { 272254912308SNavdeep Parhar 272354912308SNavdeep Parhar /* Switch to reading from the Diagnostic address. */ 272454912308SNavdeep Parhar i2cd.dev_addr = SFF_8472_DIAG; 272554912308SNavdeep Parhar i2cd.len = 1; 272654912308SNavdeep Parhar 272754912308SNavdeep Parhar i2cd.offset = SFF_8472_TEMP; 272854912308SNavdeep Parhar if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) 272954912308SNavdeep Parhar goto fail; 273054912308SNavdeep Parhar temp = i2cd.data[0] << 8; 273154912308SNavdeep Parhar printf("Temp: "); 273254912308SNavdeep Parhar if ((temp & SFF_8472_TEMP_SIGN) == SFF_8472_TEMP_SIGN) 273354912308SNavdeep Parhar printf("-"); 273454912308SNavdeep Parhar else 273554912308SNavdeep Parhar printf("+"); 273654912308SNavdeep Parhar printf("%dC\n", (temp & SFF_8472_TEMP_MSK) >> 273754912308SNavdeep Parhar SFF_8472_TEMP_SHIFT); 273854912308SNavdeep Parhar 273954912308SNavdeep Parhar i2cd.offset = SFF_8472_VCC; 274054912308SNavdeep Parhar if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) 274154912308SNavdeep Parhar goto fail; 274254912308SNavdeep Parhar vcc = i2cd.data[0] << 8; 274354912308SNavdeep Parhar printf("Vcc %fV\n", vcc / SFF_8472_VCC_FACTOR); 274454912308SNavdeep Parhar 274554912308SNavdeep Parhar i2cd.offset = SFF_8472_TX_BIAS; 274654912308SNavdeep Parhar if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) 274754912308SNavdeep Parhar goto fail; 274854912308SNavdeep Parhar tx_bias = i2cd.data[0] << 8; 274954912308SNavdeep Parhar printf("TX Bias %fuA\n", tx_bias / SFF_8472_BIAS_FACTOR); 275054912308SNavdeep Parhar 275154912308SNavdeep Parhar i2cd.offset = SFF_8472_TX_POWER; 275254912308SNavdeep Parhar if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) 275354912308SNavdeep Parhar goto fail; 275454912308SNavdeep Parhar tx_power = i2cd.data[0] << 8; 275554912308SNavdeep Parhar printf("TX Power %fmW\n", tx_power / SFF_8472_POWER_FACTOR); 275654912308SNavdeep Parhar 275754912308SNavdeep Parhar i2cd.offset = SFF_8472_RX_POWER; 275854912308SNavdeep Parhar if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) 275954912308SNavdeep Parhar goto fail; 276054912308SNavdeep Parhar rx_power = i2cd.data[0] << 8; 276154912308SNavdeep Parhar printf("RX Power %fmW\n", rx_power / SFF_8472_POWER_FACTOR); 276254912308SNavdeep Parhar 276354912308SNavdeep Parhar } else 276454912308SNavdeep Parhar printf("Diagnostics not supported.\n"); 276554912308SNavdeep Parhar 276654912308SNavdeep Parhar return(0); 276754912308SNavdeep Parhar 276854912308SNavdeep Parhar fail: 276954912308SNavdeep Parhar if (rc == EPERM) 277054912308SNavdeep Parhar warnx("No module/cable in port %ld", port); 277154912308SNavdeep Parhar return (rc); 277254912308SNavdeep Parhar 277354912308SNavdeep Parhar } 277454912308SNavdeep Parhar 277554912308SNavdeep Parhar /* XXX: pass in a low/high and do range checks as well */ 277654912308SNavdeep Parhar static int 277754912308SNavdeep Parhar get_sched_param(const char *param, const char *args[], long *val) 277854912308SNavdeep Parhar { 277954912308SNavdeep Parhar char *p; 278054912308SNavdeep Parhar 278154912308SNavdeep Parhar if (strcmp(param, args[0]) != 0) 278254912308SNavdeep Parhar return (EINVAL); 278354912308SNavdeep Parhar 278454912308SNavdeep Parhar p = str_to_number(args[1], val, NULL); 278554912308SNavdeep Parhar if (*p) { 278654912308SNavdeep Parhar warnx("parameter \"%s\" has bad value \"%s\"", args[0], 278754912308SNavdeep Parhar args[1]); 278854912308SNavdeep Parhar return (EINVAL); 278954912308SNavdeep Parhar } 279054912308SNavdeep Parhar 279154912308SNavdeep Parhar return (0); 279254912308SNavdeep Parhar } 279354912308SNavdeep Parhar 279454912308SNavdeep Parhar static int 279554912308SNavdeep Parhar sched_class(int argc, const char *argv[]) 279654912308SNavdeep Parhar { 279754912308SNavdeep Parhar struct t4_sched_params op; 279854912308SNavdeep Parhar int errs, i; 279954912308SNavdeep Parhar 280054912308SNavdeep Parhar memset(&op, 0xff, sizeof(op)); 280154912308SNavdeep Parhar op.subcmd = -1; 280254912308SNavdeep Parhar op.type = -1; 280354912308SNavdeep Parhar if (argc == 0) { 280454912308SNavdeep Parhar warnx("missing scheduling sub-command"); 280554912308SNavdeep Parhar return (EINVAL); 280654912308SNavdeep Parhar } 280754912308SNavdeep Parhar if (!strcmp(argv[0], "config")) { 280854912308SNavdeep Parhar op.subcmd = SCHED_CLASS_SUBCMD_CONFIG; 280954912308SNavdeep Parhar op.u.config.minmax = -1; 281054912308SNavdeep Parhar } else if (!strcmp(argv[0], "params")) { 281154912308SNavdeep Parhar op.subcmd = SCHED_CLASS_SUBCMD_PARAMS; 281254912308SNavdeep Parhar op.u.params.level = op.u.params.mode = op.u.params.rateunit = 281354912308SNavdeep Parhar op.u.params.ratemode = op.u.params.channel = 281454912308SNavdeep Parhar op.u.params.cl = op.u.params.minrate = op.u.params.maxrate = 281554912308SNavdeep Parhar op.u.params.weight = op.u.params.pktsize = -1; 281654912308SNavdeep Parhar } else { 281754912308SNavdeep Parhar warnx("invalid scheduling sub-command \"%s\"", argv[0]); 281854912308SNavdeep Parhar return (EINVAL); 281954912308SNavdeep Parhar } 282054912308SNavdeep Parhar 282154912308SNavdeep Parhar /* Decode remaining arguments ... */ 282254912308SNavdeep Parhar errs = 0; 282354912308SNavdeep Parhar for (i = 1; i < argc; i += 2) { 282454912308SNavdeep Parhar const char **args = &argv[i]; 282554912308SNavdeep Parhar long l; 282654912308SNavdeep Parhar 282754912308SNavdeep Parhar if (i + 1 == argc) { 282854912308SNavdeep Parhar warnx("missing argument for \"%s\"", args[0]); 282954912308SNavdeep Parhar errs++; 283054912308SNavdeep Parhar break; 283154912308SNavdeep Parhar } 283254912308SNavdeep Parhar 283354912308SNavdeep Parhar if (!strcmp(args[0], "type")) { 283454912308SNavdeep Parhar if (!strcmp(args[1], "packet")) 283554912308SNavdeep Parhar op.type = SCHED_CLASS_TYPE_PACKET; 283654912308SNavdeep Parhar else { 283754912308SNavdeep Parhar warnx("invalid type parameter \"%s\"", args[1]); 283854912308SNavdeep Parhar errs++; 283954912308SNavdeep Parhar } 284054912308SNavdeep Parhar 284154912308SNavdeep Parhar continue; 284254912308SNavdeep Parhar } 284354912308SNavdeep Parhar 284454912308SNavdeep Parhar if (op.subcmd == SCHED_CLASS_SUBCMD_CONFIG) { 284554912308SNavdeep Parhar if(!get_sched_param("minmax", args, &l)) 284654912308SNavdeep Parhar op.u.config.minmax = (int8_t)l; 284754912308SNavdeep Parhar else { 284854912308SNavdeep Parhar warnx("unknown scheduler config parameter " 284954912308SNavdeep Parhar "\"%s\"", args[0]); 285054912308SNavdeep Parhar errs++; 285154912308SNavdeep Parhar } 285254912308SNavdeep Parhar 285354912308SNavdeep Parhar continue; 285454912308SNavdeep Parhar } 285554912308SNavdeep Parhar 285654912308SNavdeep Parhar /* Rest applies only to SUBCMD_PARAMS */ 285754912308SNavdeep Parhar if (op.subcmd != SCHED_CLASS_SUBCMD_PARAMS) 285854912308SNavdeep Parhar continue; 285954912308SNavdeep Parhar 286054912308SNavdeep Parhar if (!strcmp(args[0], "level")) { 286154912308SNavdeep Parhar if (!strcmp(args[1], "cl-rl")) 286254912308SNavdeep Parhar op.u.params.level = SCHED_CLASS_LEVEL_CL_RL; 286354912308SNavdeep Parhar else if (!strcmp(args[1], "cl-wrr")) 286454912308SNavdeep Parhar op.u.params.level = SCHED_CLASS_LEVEL_CL_WRR; 286554912308SNavdeep Parhar else if (!strcmp(args[1], "ch-rl")) 286654912308SNavdeep Parhar op.u.params.level = SCHED_CLASS_LEVEL_CH_RL; 286754912308SNavdeep Parhar else { 286854912308SNavdeep Parhar warnx("invalid level parameter \"%s\"", 286954912308SNavdeep Parhar args[1]); 287054912308SNavdeep Parhar errs++; 287154912308SNavdeep Parhar } 287254912308SNavdeep Parhar } else if (!strcmp(args[0], "mode")) { 287354912308SNavdeep Parhar if (!strcmp(args[1], "class")) 287454912308SNavdeep Parhar op.u.params.mode = SCHED_CLASS_MODE_CLASS; 287554912308SNavdeep Parhar else if (!strcmp(args[1], "flow")) 287654912308SNavdeep Parhar op.u.params.mode = SCHED_CLASS_MODE_FLOW; 287754912308SNavdeep Parhar else { 287854912308SNavdeep Parhar warnx("invalid mode parameter \"%s\"", args[1]); 287954912308SNavdeep Parhar errs++; 288054912308SNavdeep Parhar } 288154912308SNavdeep Parhar } else if (!strcmp(args[0], "rate-unit")) { 288254912308SNavdeep Parhar if (!strcmp(args[1], "bits")) 288354912308SNavdeep Parhar op.u.params.rateunit = SCHED_CLASS_RATEUNIT_BITS; 288454912308SNavdeep Parhar else if (!strcmp(args[1], "pkts")) 288554912308SNavdeep Parhar op.u.params.rateunit = SCHED_CLASS_RATEUNIT_PKTS; 288654912308SNavdeep Parhar else { 288754912308SNavdeep Parhar warnx("invalid rate-unit parameter \"%s\"", 288854912308SNavdeep Parhar args[1]); 288954912308SNavdeep Parhar errs++; 289054912308SNavdeep Parhar } 289154912308SNavdeep Parhar } else if (!strcmp(args[0], "rate-mode")) { 289254912308SNavdeep Parhar if (!strcmp(args[1], "relative")) 289354912308SNavdeep Parhar op.u.params.ratemode = SCHED_CLASS_RATEMODE_REL; 289454912308SNavdeep Parhar else if (!strcmp(args[1], "absolute")) 289554912308SNavdeep Parhar op.u.params.ratemode = SCHED_CLASS_RATEMODE_ABS; 289654912308SNavdeep Parhar else { 289754912308SNavdeep Parhar warnx("invalid rate-mode parameter \"%s\"", 289854912308SNavdeep Parhar args[1]); 289954912308SNavdeep Parhar errs++; 290054912308SNavdeep Parhar } 290154912308SNavdeep Parhar } else if (!get_sched_param("channel", args, &l)) 290254912308SNavdeep Parhar op.u.params.channel = (int8_t)l; 290354912308SNavdeep Parhar else if (!get_sched_param("class", args, &l)) 290454912308SNavdeep Parhar op.u.params.cl = (int8_t)l; 290554912308SNavdeep Parhar else if (!get_sched_param("min-rate", args, &l)) 290654912308SNavdeep Parhar op.u.params.minrate = (int32_t)l; 290754912308SNavdeep Parhar else if (!get_sched_param("max-rate", args, &l)) 290854912308SNavdeep Parhar op.u.params.maxrate = (int32_t)l; 290954912308SNavdeep Parhar else if (!get_sched_param("weight", args, &l)) 291054912308SNavdeep Parhar op.u.params.weight = (int16_t)l; 291154912308SNavdeep Parhar else if (!get_sched_param("pkt-size", args, &l)) 291254912308SNavdeep Parhar op.u.params.pktsize = (int16_t)l; 291354912308SNavdeep Parhar else { 291454912308SNavdeep Parhar warnx("unknown scheduler parameter \"%s\"", args[0]); 291554912308SNavdeep Parhar errs++; 291654912308SNavdeep Parhar } 291754912308SNavdeep Parhar } 291854912308SNavdeep Parhar 291954912308SNavdeep Parhar /* 292054912308SNavdeep Parhar * Catch some logical fallacies in terms of argument combinations here 292154912308SNavdeep Parhar * so we can offer more than just the EINVAL return from the driver. 292254912308SNavdeep Parhar * The driver will be able to catch a lot more issues since it knows 292354912308SNavdeep Parhar * the specifics of the device hardware capabilities like how many 292454912308SNavdeep Parhar * channels, classes, etc. the device supports. 292554912308SNavdeep Parhar */ 292654912308SNavdeep Parhar if (op.type < 0) { 292754912308SNavdeep Parhar warnx("sched \"type\" parameter missing"); 292854912308SNavdeep Parhar errs++; 292954912308SNavdeep Parhar } 293054912308SNavdeep Parhar if (op.subcmd == SCHED_CLASS_SUBCMD_CONFIG) { 293154912308SNavdeep Parhar if (op.u.config.minmax < 0) { 293254912308SNavdeep Parhar warnx("sched config \"minmax\" parameter missing"); 293354912308SNavdeep Parhar errs++; 293454912308SNavdeep Parhar } 293554912308SNavdeep Parhar } 293654912308SNavdeep Parhar if (op.subcmd == SCHED_CLASS_SUBCMD_PARAMS) { 293754912308SNavdeep Parhar if (op.u.params.level < 0) { 293854912308SNavdeep Parhar warnx("sched params \"level\" parameter missing"); 293954912308SNavdeep Parhar errs++; 294054912308SNavdeep Parhar } 2941ffcf81c9SNavdeep Parhar if (op.u.params.mode < 0 && 2942ffcf81c9SNavdeep Parhar op.u.params.level == SCHED_CLASS_LEVEL_CL_RL) { 294354912308SNavdeep Parhar warnx("sched params \"mode\" parameter missing"); 294454912308SNavdeep Parhar errs++; 294554912308SNavdeep Parhar } 2946ffcf81c9SNavdeep Parhar if (op.u.params.rateunit < 0 && 2947ffcf81c9SNavdeep Parhar (op.u.params.level == SCHED_CLASS_LEVEL_CL_RL || 2948ffcf81c9SNavdeep Parhar op.u.params.level == SCHED_CLASS_LEVEL_CH_RL)) { 294954912308SNavdeep Parhar warnx("sched params \"rate-unit\" parameter missing"); 295054912308SNavdeep Parhar errs++; 295154912308SNavdeep Parhar } 2952ffcf81c9SNavdeep Parhar if (op.u.params.ratemode < 0 && 2953ffcf81c9SNavdeep Parhar (op.u.params.level == SCHED_CLASS_LEVEL_CL_RL || 2954ffcf81c9SNavdeep Parhar op.u.params.level == SCHED_CLASS_LEVEL_CH_RL)) { 295554912308SNavdeep Parhar warnx("sched params \"rate-mode\" parameter missing"); 295654912308SNavdeep Parhar errs++; 295754912308SNavdeep Parhar } 295854912308SNavdeep Parhar if (op.u.params.channel < 0) { 295954912308SNavdeep Parhar warnx("sched params \"channel\" missing"); 296054912308SNavdeep Parhar errs++; 296154912308SNavdeep Parhar } 2962ffcf81c9SNavdeep Parhar if (op.u.params.cl < 0 && 2963ffcf81c9SNavdeep Parhar (op.u.params.level == SCHED_CLASS_LEVEL_CL_RL || 2964ffcf81c9SNavdeep Parhar op.u.params.level == SCHED_CLASS_LEVEL_CL_WRR)) { 296554912308SNavdeep Parhar warnx("sched params \"class\" missing"); 296654912308SNavdeep Parhar errs++; 296754912308SNavdeep Parhar } 296854912308SNavdeep Parhar if (op.u.params.maxrate < 0 && 296954912308SNavdeep Parhar (op.u.params.level == SCHED_CLASS_LEVEL_CL_RL || 297054912308SNavdeep Parhar op.u.params.level == SCHED_CLASS_LEVEL_CH_RL)) { 297154912308SNavdeep Parhar warnx("sched params \"max-rate\" missing for " 297254912308SNavdeep Parhar "rate-limit level"); 297354912308SNavdeep Parhar errs++; 297454912308SNavdeep Parhar } 2975ffcf81c9SNavdeep Parhar if (op.u.params.level == SCHED_CLASS_LEVEL_CL_WRR && 2976ffcf81c9SNavdeep Parhar (op.u.params.weight < 1 || op.u.params.weight > 99)) { 2977ffcf81c9SNavdeep Parhar warnx("sched params \"weight\" missing or invalid " 2978ffcf81c9SNavdeep Parhar "(not 1-99) for weighted-round-robin level"); 297954912308SNavdeep Parhar errs++; 298054912308SNavdeep Parhar } 298154912308SNavdeep Parhar if (op.u.params.pktsize < 0 && 2982ffcf81c9SNavdeep Parhar op.u.params.level == SCHED_CLASS_LEVEL_CL_RL) { 298354912308SNavdeep Parhar warnx("sched params \"pkt-size\" missing for " 298454912308SNavdeep Parhar "rate-limit level"); 298554912308SNavdeep Parhar errs++; 298654912308SNavdeep Parhar } 298754912308SNavdeep Parhar if (op.u.params.mode == SCHED_CLASS_MODE_FLOW && 298854912308SNavdeep Parhar op.u.params.ratemode != SCHED_CLASS_RATEMODE_ABS) { 298954912308SNavdeep Parhar warnx("sched params mode flow needs rate-mode absolute"); 299054912308SNavdeep Parhar errs++; 299154912308SNavdeep Parhar } 299254912308SNavdeep Parhar if (op.u.params.ratemode == SCHED_CLASS_RATEMODE_REL && 299354912308SNavdeep Parhar !in_range(op.u.params.maxrate, 1, 100)) { 299454912308SNavdeep Parhar warnx("sched params \"max-rate\" takes " 299554912308SNavdeep Parhar "percentage value(1-100) for rate-mode relative"); 299654912308SNavdeep Parhar errs++; 299754912308SNavdeep Parhar } 299854912308SNavdeep Parhar if (op.u.params.ratemode == SCHED_CLASS_RATEMODE_ABS && 299954912308SNavdeep Parhar !in_range(op.u.params.maxrate, 1, 100000000)) { 300054912308SNavdeep Parhar warnx("sched params \"max-rate\" takes " 300154912308SNavdeep Parhar "value(1-100000000) for rate-mode absolute"); 300254912308SNavdeep Parhar errs++; 300354912308SNavdeep Parhar } 300454912308SNavdeep Parhar if (op.u.params.maxrate > 0 && 300554912308SNavdeep Parhar op.u.params.maxrate < op.u.params.minrate) { 300654912308SNavdeep Parhar warnx("sched params \"max-rate\" is less than " 300754912308SNavdeep Parhar "\"min-rate\""); 300854912308SNavdeep Parhar errs++; 300954912308SNavdeep Parhar } 301054912308SNavdeep Parhar } 301154912308SNavdeep Parhar 301254912308SNavdeep Parhar if (errs > 0) { 301354912308SNavdeep Parhar warnx("%d error%s in sched-class command", errs, 301454912308SNavdeep Parhar errs == 1 ? "" : "s"); 301554912308SNavdeep Parhar return (EINVAL); 301654912308SNavdeep Parhar } 301754912308SNavdeep Parhar 301854912308SNavdeep Parhar return doit(CHELSIO_T4_SCHED_CLASS, &op); 301954912308SNavdeep Parhar } 302054912308SNavdeep Parhar 302154912308SNavdeep Parhar static int 302254912308SNavdeep Parhar sched_queue(int argc, const char *argv[]) 302354912308SNavdeep Parhar { 302454912308SNavdeep Parhar struct t4_sched_queue op = {0}; 302554912308SNavdeep Parhar char *p; 302654912308SNavdeep Parhar long val; 302754912308SNavdeep Parhar 302854912308SNavdeep Parhar if (argc != 3) { 302954912308SNavdeep Parhar /* need "<port> <queue> <class> */ 303054912308SNavdeep Parhar warnx("incorrect number of arguments."); 303154912308SNavdeep Parhar return (EINVAL); 303254912308SNavdeep Parhar } 303354912308SNavdeep Parhar 303454912308SNavdeep Parhar p = str_to_number(argv[0], &val, NULL); 303554912308SNavdeep Parhar if (*p || val > UCHAR_MAX) { 303654912308SNavdeep Parhar warnx("invalid port id \"%s\"", argv[0]); 303754912308SNavdeep Parhar return (EINVAL); 303854912308SNavdeep Parhar } 303954912308SNavdeep Parhar op.port = (uint8_t)val; 304054912308SNavdeep Parhar 304154912308SNavdeep Parhar if (!strcmp(argv[1], "all") || !strcmp(argv[1], "*")) 304254912308SNavdeep Parhar op.queue = -1; 304354912308SNavdeep Parhar else { 304454912308SNavdeep Parhar p = str_to_number(argv[1], &val, NULL); 304554912308SNavdeep Parhar if (*p || val < -1) { 304654912308SNavdeep Parhar warnx("invalid queue \"%s\"", argv[1]); 304754912308SNavdeep Parhar return (EINVAL); 304854912308SNavdeep Parhar } 304954912308SNavdeep Parhar op.queue = (int8_t)val; 305054912308SNavdeep Parhar } 305154912308SNavdeep Parhar 305254912308SNavdeep Parhar if (!strcmp(argv[2], "unbind") || !strcmp(argv[2], "clear")) 305354912308SNavdeep Parhar op.cl = -1; 305454912308SNavdeep Parhar else { 305554912308SNavdeep Parhar p = str_to_number(argv[2], &val, NULL); 305654912308SNavdeep Parhar if (*p || val < -1) { 305754912308SNavdeep Parhar warnx("invalid class \"%s\"", argv[2]); 305854912308SNavdeep Parhar return (EINVAL); 305954912308SNavdeep Parhar } 306054912308SNavdeep Parhar op.cl = (int8_t)val; 306154912308SNavdeep Parhar } 306254912308SNavdeep Parhar 306354912308SNavdeep Parhar return doit(CHELSIO_T4_SCHED_QUEUE, &op); 306454912308SNavdeep Parhar } 306554912308SNavdeep Parhar 306654912308SNavdeep Parhar static int 30671131c927SNavdeep Parhar parse_offload_settings_word(const char *s, char **pnext, const char *ws, 30681131c927SNavdeep Parhar int *pneg, struct offload_settings *os) 30691131c927SNavdeep Parhar { 30701131c927SNavdeep Parhar 30711131c927SNavdeep Parhar while (*s == '!') { 30721131c927SNavdeep Parhar (*pneg)++; 30731131c927SNavdeep Parhar s++; 30741131c927SNavdeep Parhar } 30751131c927SNavdeep Parhar 30761131c927SNavdeep Parhar if (!strcmp(s, "not")) { 30771131c927SNavdeep Parhar (*pneg)++; 30781131c927SNavdeep Parhar return (0); 30791131c927SNavdeep Parhar } 30801131c927SNavdeep Parhar 30811131c927SNavdeep Parhar if (!strcmp(s, "offload")) { 30821131c927SNavdeep Parhar os->offload = (*pneg + 1) & 1; 30831131c927SNavdeep Parhar *pneg = 0; 30841131c927SNavdeep Parhar } else if (!strcmp(s , "coalesce")) { 30851131c927SNavdeep Parhar os->rx_coalesce = (*pneg + 1) & 1; 30861131c927SNavdeep Parhar *pneg = 0; 30871131c927SNavdeep Parhar } else if (!strcmp(s, "timestamp") || !strcmp(s, "tstamp")) { 30881131c927SNavdeep Parhar os->tstamp = (*pneg + 1) & 1; 30891131c927SNavdeep Parhar *pneg = 0; 30901131c927SNavdeep Parhar } else if (!strcmp(s, "sack")) { 30911131c927SNavdeep Parhar os->sack = (*pneg + 1) & 1; 30921131c927SNavdeep Parhar *pneg = 0; 30931131c927SNavdeep Parhar } else if (!strcmp(s, "nagle")) { 30941131c927SNavdeep Parhar os->nagle = (*pneg + 1) & 1; 30951131c927SNavdeep Parhar *pneg = 0; 30961131c927SNavdeep Parhar } else if (!strcmp(s, "ecn")) { 30971131c927SNavdeep Parhar os->ecn = (*pneg + 1) & 1; 30981131c927SNavdeep Parhar *pneg = 0; 30991131c927SNavdeep Parhar } else if (!strcmp(s, "ddp")) { 31001131c927SNavdeep Parhar os->ddp = (*pneg + 1) & 1; 31011131c927SNavdeep Parhar *pneg = 0; 31021131c927SNavdeep Parhar } else if (!strcmp(s, "tls")) { 31031131c927SNavdeep Parhar os->tls = (*pneg + 1) & 1; 31041131c927SNavdeep Parhar *pneg = 0; 31051131c927SNavdeep Parhar } else { 31061131c927SNavdeep Parhar char *param, *p; 31071131c927SNavdeep Parhar long val; 31081131c927SNavdeep Parhar 31091131c927SNavdeep Parhar /* Settings with additional parameter handled here. */ 31101131c927SNavdeep Parhar 31111131c927SNavdeep Parhar if (*pneg) { 31121131c927SNavdeep Parhar warnx("\"%s\" is not a valid keyword, or it does not " 31131131c927SNavdeep Parhar "support negation.", s); 31141131c927SNavdeep Parhar return (EINVAL); 31151131c927SNavdeep Parhar } 31161131c927SNavdeep Parhar 31171131c927SNavdeep Parhar while ((param = strsep(pnext, ws)) != NULL) { 31181131c927SNavdeep Parhar if (*param != '\0') 31191131c927SNavdeep Parhar break; 31201131c927SNavdeep Parhar } 31211131c927SNavdeep Parhar if (param == NULL) { 31221131c927SNavdeep Parhar warnx("\"%s\" is not a valid keyword, or it requires a " 31231131c927SNavdeep Parhar "parameter that has not been provided.", s); 31241131c927SNavdeep Parhar return (EINVAL); 31251131c927SNavdeep Parhar } 31261131c927SNavdeep Parhar 31271131c927SNavdeep Parhar if (!strcmp(s, "cong")) { 31281131c927SNavdeep Parhar if (!strcmp(param, "reno")) 31291131c927SNavdeep Parhar os->cong_algo = 0; 31301131c927SNavdeep Parhar else if (!strcmp(param, "tahoe")) 31311131c927SNavdeep Parhar os->cong_algo = 1; 31321131c927SNavdeep Parhar else if (!strcmp(param, "newreno")) 31331131c927SNavdeep Parhar os->cong_algo = 2; 31341131c927SNavdeep Parhar else if (!strcmp(param, "highspeed")) 31351131c927SNavdeep Parhar os->cong_algo = 3; 31361131c927SNavdeep Parhar else { 31371131c927SNavdeep Parhar warnx("unknown congestion algorithm \"%s\".", s); 31381131c927SNavdeep Parhar return (EINVAL); 31391131c927SNavdeep Parhar } 31401131c927SNavdeep Parhar } else if (!strcmp(s, "class")) { 31411131c927SNavdeep Parhar val = -1; 31421131c927SNavdeep Parhar p = str_to_number(param, &val, NULL); 31431131c927SNavdeep Parhar /* (nsched_cls - 1) is spelled 15 here. */ 31441131c927SNavdeep Parhar if (*p || val < 0 || val > 15) { 31451131c927SNavdeep Parhar warnx("invalid scheduling class \"%s\". " 31461131c927SNavdeep Parhar "\"class\" needs an integer value where " 31471131c927SNavdeep Parhar "0 <= value <= 15", param); 31481131c927SNavdeep Parhar return (EINVAL); 31491131c927SNavdeep Parhar } 31501131c927SNavdeep Parhar os->sched_class = val; 31511131c927SNavdeep Parhar } else if (!strcmp(s, "bind") || !strcmp(s, "txq") || 31521131c927SNavdeep Parhar !strcmp(s, "rxq")) { 3153*811a82d5SNavdeep Parhar if (!strcmp(param, "random")) { 3154*811a82d5SNavdeep Parhar val = QUEUE_RANDOM; 3155*811a82d5SNavdeep Parhar } else if (!strcmp(param, "roundrobin")) { 3156*811a82d5SNavdeep Parhar val = QUEUE_ROUNDROBIN; 3157*811a82d5SNavdeep Parhar } else { 31581131c927SNavdeep Parhar p = str_to_number(param, &val, NULL); 31591131c927SNavdeep Parhar if (*p || val < 0 || val > 0xffff) { 31601131c927SNavdeep Parhar warnx("invalid queue specification " 31611131c927SNavdeep Parhar "\"%s\". \"%s\" needs an integer" 3162*811a82d5SNavdeep Parhar " value, \"random\", or " 3163*811a82d5SNavdeep Parhar "\"roundrobin\".", param, s); 31641131c927SNavdeep Parhar return (EINVAL); 31651131c927SNavdeep Parhar } 31661131c927SNavdeep Parhar } 31671131c927SNavdeep Parhar if (!strcmp(s, "bind")) { 31681131c927SNavdeep Parhar os->txq = val; 31691131c927SNavdeep Parhar os->rxq = val; 31701131c927SNavdeep Parhar } else if (!strcmp(s, "txq")) { 31711131c927SNavdeep Parhar os->txq = val; 31721131c927SNavdeep Parhar } else if (!strcmp(s, "rxq")) { 31731131c927SNavdeep Parhar os->rxq = val; 31741131c927SNavdeep Parhar } else { 31751131c927SNavdeep Parhar return (EDOOFUS); 31761131c927SNavdeep Parhar } 31771131c927SNavdeep Parhar } else if (!strcmp(s, "mss")) { 31781131c927SNavdeep Parhar val = -1; 31791131c927SNavdeep Parhar p = str_to_number(param, &val, NULL); 31801131c927SNavdeep Parhar if (*p || val <= 0) { 31811131c927SNavdeep Parhar warnx("invalid MSS specification \"%s\". " 31821131c927SNavdeep Parhar "\"mss\" needs a positive integer value", 31831131c927SNavdeep Parhar param); 31841131c927SNavdeep Parhar return (EINVAL); 31851131c927SNavdeep Parhar } 31861131c927SNavdeep Parhar os->mss = val; 31871131c927SNavdeep Parhar } else { 31881131c927SNavdeep Parhar warnx("unknown settings keyword: \"%s\"", s); 31891131c927SNavdeep Parhar return (EINVAL); 31901131c927SNavdeep Parhar } 31911131c927SNavdeep Parhar } 31921131c927SNavdeep Parhar 31931131c927SNavdeep Parhar return (0); 31941131c927SNavdeep Parhar } 31951131c927SNavdeep Parhar 31961131c927SNavdeep Parhar static int 31971131c927SNavdeep Parhar parse_offload_settings(const char *settings_ro, struct offload_settings *os) 31981131c927SNavdeep Parhar { 31991131c927SNavdeep Parhar const char *ws = " \f\n\r\v\t"; 32001131c927SNavdeep Parhar char *settings, *s, *next; 32011131c927SNavdeep Parhar int rc, nsettings, neg; 32021131c927SNavdeep Parhar static const struct offload_settings default_settings = { 32031131c927SNavdeep Parhar .offload = 0, /* No settings imply !offload */ 32041131c927SNavdeep Parhar .rx_coalesce = -1, 32051131c927SNavdeep Parhar .cong_algo = -1, 32061131c927SNavdeep Parhar .sched_class = -1, 32071131c927SNavdeep Parhar .tstamp = -1, 32081131c927SNavdeep Parhar .sack = -1, 32091131c927SNavdeep Parhar .nagle = -1, 32101131c927SNavdeep Parhar .ecn = -1, 32111131c927SNavdeep Parhar .ddp = -1, 32121131c927SNavdeep Parhar .tls = -1, 3213*811a82d5SNavdeep Parhar .txq = QUEUE_RANDOM, 3214*811a82d5SNavdeep Parhar .rxq = QUEUE_RANDOM, 32151131c927SNavdeep Parhar .mss = -1, 32161131c927SNavdeep Parhar }; 32171131c927SNavdeep Parhar 32181131c927SNavdeep Parhar *os = default_settings; 32191131c927SNavdeep Parhar 32201131c927SNavdeep Parhar next = settings = strdup(settings_ro); 32211131c927SNavdeep Parhar if (settings == NULL) { 32221131c927SNavdeep Parhar warn (NULL); 32231131c927SNavdeep Parhar return (errno); 32241131c927SNavdeep Parhar } 32251131c927SNavdeep Parhar 32261131c927SNavdeep Parhar nsettings = 0; 32271131c927SNavdeep Parhar rc = 0; 32281131c927SNavdeep Parhar neg = 0; 32291131c927SNavdeep Parhar while ((s = strsep(&next, ws)) != NULL) { 32301131c927SNavdeep Parhar if (*s == '\0') 32311131c927SNavdeep Parhar continue; 32321131c927SNavdeep Parhar nsettings++; 32331131c927SNavdeep Parhar rc = parse_offload_settings_word(s, &next, ws, &neg, os); 32341131c927SNavdeep Parhar if (rc != 0) 32351131c927SNavdeep Parhar goto done; 32361131c927SNavdeep Parhar } 32371131c927SNavdeep Parhar if (nsettings == 0) { 32381131c927SNavdeep Parhar warnx("no settings provided"); 32391131c927SNavdeep Parhar rc = EINVAL; 32401131c927SNavdeep Parhar goto done; 32411131c927SNavdeep Parhar } 32421131c927SNavdeep Parhar if (neg > 0) { 32431131c927SNavdeep Parhar warnx("%d stray negation(s) at end of offload settings", neg); 32441131c927SNavdeep Parhar rc = EINVAL; 32451131c927SNavdeep Parhar goto done; 32461131c927SNavdeep Parhar } 32471131c927SNavdeep Parhar done: 32481131c927SNavdeep Parhar free(settings); 32491131c927SNavdeep Parhar return (rc); 32501131c927SNavdeep Parhar } 32511131c927SNavdeep Parhar 32521131c927SNavdeep Parhar static int 32531131c927SNavdeep Parhar isempty_line(char *line, size_t llen) 32541131c927SNavdeep Parhar { 32551131c927SNavdeep Parhar 32561131c927SNavdeep Parhar /* skip leading whitespace */ 32571131c927SNavdeep Parhar while (isspace(*line)) { 32581131c927SNavdeep Parhar line++; 32591131c927SNavdeep Parhar llen--; 32601131c927SNavdeep Parhar } 32611131c927SNavdeep Parhar if (llen == 0 || *line == '#' || *line == '\n') 32621131c927SNavdeep Parhar return (1); 32631131c927SNavdeep Parhar 32641131c927SNavdeep Parhar return (0); 32651131c927SNavdeep Parhar } 32661131c927SNavdeep Parhar 32671131c927SNavdeep Parhar static int 32681131c927SNavdeep Parhar special_offload_rule(char *str) 32691131c927SNavdeep Parhar { 32701131c927SNavdeep Parhar 32711131c927SNavdeep Parhar /* skip leading whitespaces */ 32721131c927SNavdeep Parhar while (isspace(*str)) 32731131c927SNavdeep Parhar str++; 32741131c927SNavdeep Parhar 32751131c927SNavdeep Parhar /* check for special strings: "-", "all", "any" */ 32761131c927SNavdeep Parhar if (*str == '-') { 32771131c927SNavdeep Parhar str++; 32781131c927SNavdeep Parhar } else if (!strncmp(str, "all", 3) || !strncmp(str, "any", 3)) { 32791131c927SNavdeep Parhar str += 3; 32801131c927SNavdeep Parhar } else { 32811131c927SNavdeep Parhar return (0); 32821131c927SNavdeep Parhar } 32831131c927SNavdeep Parhar 32841131c927SNavdeep Parhar /* skip trailing whitespaces */ 32851131c927SNavdeep Parhar while (isspace(*str)) 32861131c927SNavdeep Parhar str++; 32871131c927SNavdeep Parhar 32881131c927SNavdeep Parhar return (*str == '\0'); 32891131c927SNavdeep Parhar } 32901131c927SNavdeep Parhar 32911131c927SNavdeep Parhar /* 32921131c927SNavdeep Parhar * A rule has 3 parts: an open-type, a match expression, and offload settings. 32931131c927SNavdeep Parhar * 32941131c927SNavdeep Parhar * [<open-type>] <expr> => <settings> 32951131c927SNavdeep Parhar */ 32961131c927SNavdeep Parhar static int 32971131c927SNavdeep Parhar parse_offload_policy_line(size_t lno, char *line, size_t llen, pcap_t *pd, 32981131c927SNavdeep Parhar struct offload_rule *r) 32991131c927SNavdeep Parhar { 33001131c927SNavdeep Parhar char *expr, *settings, *s; 33011131c927SNavdeep Parhar 33021131c927SNavdeep Parhar bzero(r, sizeof(*r)); 33031131c927SNavdeep Parhar 33041131c927SNavdeep Parhar /* Skip leading whitespace. */ 33051131c927SNavdeep Parhar while (isspace(*line)) 33061131c927SNavdeep Parhar line++; 33071131c927SNavdeep Parhar /* Trim trailing whitespace */ 33081131c927SNavdeep Parhar s = &line[llen - 1]; 33091131c927SNavdeep Parhar while (isspace(*s)) { 33101131c927SNavdeep Parhar *s-- = '\0'; 33111131c927SNavdeep Parhar llen--; 33121131c927SNavdeep Parhar } 33131131c927SNavdeep Parhar 33141131c927SNavdeep Parhar /* 33151131c927SNavdeep Parhar * First part of the rule: '[X]' where X = A/D/L/P 33161131c927SNavdeep Parhar */ 33171131c927SNavdeep Parhar if (*line++ != '[') { 33181131c927SNavdeep Parhar warnx("missing \"[\" on line %zd", lno); 33191131c927SNavdeep Parhar return (EINVAL); 33201131c927SNavdeep Parhar } 33211131c927SNavdeep Parhar switch (*line) { 33221131c927SNavdeep Parhar case 'A': 33231131c927SNavdeep Parhar case 'D': 33241131c927SNavdeep Parhar case 'L': 33251131c927SNavdeep Parhar case 'P': 33261131c927SNavdeep Parhar r->open_type = *line; 33271131c927SNavdeep Parhar break; 33281131c927SNavdeep Parhar default: 33291131c927SNavdeep Parhar warnx("invalid socket-type \"%c\" on line %zd.", *line, lno); 33301131c927SNavdeep Parhar return (EINVAL); 33311131c927SNavdeep Parhar } 33321131c927SNavdeep Parhar line++; 33331131c927SNavdeep Parhar if (*line++ != ']') { 33341131c927SNavdeep Parhar warnx("missing \"]\" after \"[%c\" on line %zd", 33351131c927SNavdeep Parhar r->open_type, lno); 33361131c927SNavdeep Parhar return (EINVAL); 33371131c927SNavdeep Parhar } 33381131c927SNavdeep Parhar 33391131c927SNavdeep Parhar /* Skip whitespace. */ 33401131c927SNavdeep Parhar while (isspace(*line)) 33411131c927SNavdeep Parhar line++; 33421131c927SNavdeep Parhar 33431131c927SNavdeep Parhar /* 33441131c927SNavdeep Parhar * Rest of the rule: <expr> => <settings> 33451131c927SNavdeep Parhar */ 33461131c927SNavdeep Parhar expr = line; 33471131c927SNavdeep Parhar s = strstr(line, "=>"); 33481131c927SNavdeep Parhar if (s == NULL) 33491131c927SNavdeep Parhar return (EINVAL); 33501131c927SNavdeep Parhar settings = s + 2; 33511131c927SNavdeep Parhar while (isspace(*settings)) 33521131c927SNavdeep Parhar settings++; 33531131c927SNavdeep Parhar *s = '\0'; 33541131c927SNavdeep Parhar 33551131c927SNavdeep Parhar /* 33561131c927SNavdeep Parhar * <expr> is either a special name (all, any) or a pcap-filter(7). 33571131c927SNavdeep Parhar * In case of a special name the bpf_prog stays all-zero. 33581131c927SNavdeep Parhar */ 33591131c927SNavdeep Parhar if (!special_offload_rule(expr)) { 33601131c927SNavdeep Parhar if (pcap_compile(pd, &r->bpf_prog, expr, 1, 33611131c927SNavdeep Parhar PCAP_NETMASK_UNKNOWN) < 0) { 33621131c927SNavdeep Parhar warnx("failed to compile \"%s\" on line %zd: %s", expr, 33631131c927SNavdeep Parhar lno, pcap_geterr(pd)); 33641131c927SNavdeep Parhar return (EINVAL); 33651131c927SNavdeep Parhar } 33661131c927SNavdeep Parhar } 33671131c927SNavdeep Parhar 33681131c927SNavdeep Parhar /* settings to apply on a match. */ 33691131c927SNavdeep Parhar if (parse_offload_settings(settings, &r->settings) != 0) { 33701131c927SNavdeep Parhar warnx("failed to parse offload settings \"%s\" on line %zd", 33711131c927SNavdeep Parhar settings, lno); 33721131c927SNavdeep Parhar pcap_freecode(&r->bpf_prog); 33731131c927SNavdeep Parhar return (EINVAL); 33741131c927SNavdeep Parhar } 33751131c927SNavdeep Parhar 33761131c927SNavdeep Parhar return (0); 33771131c927SNavdeep Parhar 33781131c927SNavdeep Parhar } 33791131c927SNavdeep Parhar 33801131c927SNavdeep Parhar /* 33811131c927SNavdeep Parhar * Note that op itself is not dynamically allocated. 33821131c927SNavdeep Parhar */ 33831131c927SNavdeep Parhar static void 33841131c927SNavdeep Parhar free_offload_policy(struct t4_offload_policy *op) 33851131c927SNavdeep Parhar { 33861131c927SNavdeep Parhar int i; 33871131c927SNavdeep Parhar 33881131c927SNavdeep Parhar for (i = 0; i < op->nrules; i++) { 33891131c927SNavdeep Parhar /* 33901131c927SNavdeep Parhar * pcap_freecode can cope with empty bpf_prog, which is the case 33911131c927SNavdeep Parhar * for an rule that matches on 'any/all/-'. 33921131c927SNavdeep Parhar */ 33931131c927SNavdeep Parhar pcap_freecode(&op->rule[i].bpf_prog); 33941131c927SNavdeep Parhar } 33951131c927SNavdeep Parhar free(op->rule); 33961131c927SNavdeep Parhar op->nrules = 0; 33971131c927SNavdeep Parhar op->rule = NULL; 33981131c927SNavdeep Parhar } 33991131c927SNavdeep Parhar 34001131c927SNavdeep Parhar #define REALLOC_STRIDE 32 34011131c927SNavdeep Parhar 34021131c927SNavdeep Parhar /* 34031131c927SNavdeep Parhar * Fills up op->nrules and op->rule. 34041131c927SNavdeep Parhar */ 34051131c927SNavdeep Parhar static int 34061131c927SNavdeep Parhar parse_offload_policy(const char *fname, struct t4_offload_policy *op) 34071131c927SNavdeep Parhar { 34081131c927SNavdeep Parhar FILE *fp; 34091131c927SNavdeep Parhar char *line; 34101131c927SNavdeep Parhar int lno, maxrules, rc; 34111131c927SNavdeep Parhar size_t lcap, llen; 34121131c927SNavdeep Parhar struct offload_rule *r; 34131131c927SNavdeep Parhar pcap_t *pd; 34141131c927SNavdeep Parhar 34151131c927SNavdeep Parhar fp = fopen(fname, "r"); 34161131c927SNavdeep Parhar if (fp == NULL) { 34171131c927SNavdeep Parhar warn("Unable to open file \"%s\"", fname); 34181131c927SNavdeep Parhar return (errno); 34191131c927SNavdeep Parhar } 34201131c927SNavdeep Parhar pd = pcap_open_dead(DLT_EN10MB, 128); 34211131c927SNavdeep Parhar if (pd == NULL) { 34221131c927SNavdeep Parhar warnx("Failed to open pcap device"); 34231131c927SNavdeep Parhar fclose(fp); 34241131c927SNavdeep Parhar return (EIO); 34251131c927SNavdeep Parhar } 34261131c927SNavdeep Parhar 34271131c927SNavdeep Parhar rc = 0; 34281131c927SNavdeep Parhar lno = 0; 34291131c927SNavdeep Parhar lcap = 0; 34301131c927SNavdeep Parhar maxrules = 0; 34311131c927SNavdeep Parhar op->nrules = 0; 34321131c927SNavdeep Parhar op->rule = NULL; 34331131c927SNavdeep Parhar line = NULL; 34341131c927SNavdeep Parhar 34351131c927SNavdeep Parhar while ((llen = getline(&line, &lcap, fp)) != -1) { 34361131c927SNavdeep Parhar lno++; 34371131c927SNavdeep Parhar 34381131c927SNavdeep Parhar /* Skip empty lines. */ 34391131c927SNavdeep Parhar if (isempty_line(line, llen)) 34401131c927SNavdeep Parhar continue; 34411131c927SNavdeep Parhar 34421131c927SNavdeep Parhar if (op->nrules == maxrules) { 34431131c927SNavdeep Parhar maxrules += REALLOC_STRIDE; 34441131c927SNavdeep Parhar r = realloc(op->rule, 34451131c927SNavdeep Parhar maxrules * sizeof(struct offload_rule)); 34461131c927SNavdeep Parhar if (r == NULL) { 34471131c927SNavdeep Parhar warnx("failed to allocate memory for %d rules", 34481131c927SNavdeep Parhar maxrules); 34491131c927SNavdeep Parhar rc = ENOMEM; 34501131c927SNavdeep Parhar goto done; 34511131c927SNavdeep Parhar } 34521131c927SNavdeep Parhar op->rule = r; 34531131c927SNavdeep Parhar } 34541131c927SNavdeep Parhar 34551131c927SNavdeep Parhar r = &op->rule[op->nrules]; 34561131c927SNavdeep Parhar rc = parse_offload_policy_line(lno, line, llen, pd, r); 34571131c927SNavdeep Parhar if (rc != 0) { 34581131c927SNavdeep Parhar warnx("Error parsing line %d of \"%s\"", lno, fname); 34591131c927SNavdeep Parhar goto done; 34601131c927SNavdeep Parhar } 34611131c927SNavdeep Parhar 34621131c927SNavdeep Parhar op->nrules++; 34631131c927SNavdeep Parhar } 34641131c927SNavdeep Parhar free(line); 34651131c927SNavdeep Parhar 34661131c927SNavdeep Parhar if (!feof(fp)) { 34671131c927SNavdeep Parhar warn("Error while reading from file \"%s\" at line %d", 34681131c927SNavdeep Parhar fname, lno); 34691131c927SNavdeep Parhar rc = errno; 34701131c927SNavdeep Parhar goto done; 34711131c927SNavdeep Parhar } 34721131c927SNavdeep Parhar 34731131c927SNavdeep Parhar if (op->nrules == 0) { 34741131c927SNavdeep Parhar warnx("No valid rules found in \"%s\"", fname); 34751131c927SNavdeep Parhar rc = EINVAL; 34761131c927SNavdeep Parhar } 34771131c927SNavdeep Parhar done: 34781131c927SNavdeep Parhar pcap_close(pd); 34791131c927SNavdeep Parhar fclose(fp); 34801131c927SNavdeep Parhar if (rc != 0) { 34811131c927SNavdeep Parhar free_offload_policy(op); 34821131c927SNavdeep Parhar } 34831131c927SNavdeep Parhar 34841131c927SNavdeep Parhar return (rc); 34851131c927SNavdeep Parhar } 34861131c927SNavdeep Parhar 34871131c927SNavdeep Parhar static int 34881131c927SNavdeep Parhar load_offload_policy(int argc, const char *argv[]) 34891131c927SNavdeep Parhar { 34901131c927SNavdeep Parhar int rc = 0; 34911131c927SNavdeep Parhar const char *fname = argv[0]; 34921131c927SNavdeep Parhar struct t4_offload_policy op = {0}; 34931131c927SNavdeep Parhar 34941131c927SNavdeep Parhar if (argc != 1) { 34951131c927SNavdeep Parhar warnx("incorrect number of arguments."); 34961131c927SNavdeep Parhar return (EINVAL); 34971131c927SNavdeep Parhar } 34981131c927SNavdeep Parhar 34991131c927SNavdeep Parhar if (!strcmp(fname, "clear") || !strcmp(fname, "none")) { 35001131c927SNavdeep Parhar /* op.nrules is 0 and that means clear policy */ 35011131c927SNavdeep Parhar return (doit(CHELSIO_T4_SET_OFLD_POLICY, &op)); 35021131c927SNavdeep Parhar } 35031131c927SNavdeep Parhar 35041131c927SNavdeep Parhar rc = parse_offload_policy(fname, &op); 35051131c927SNavdeep Parhar if (rc != 0) { 35061131c927SNavdeep Parhar /* Error message displayed already */ 35071131c927SNavdeep Parhar return (EINVAL); 35081131c927SNavdeep Parhar } 35091131c927SNavdeep Parhar 35101131c927SNavdeep Parhar rc = doit(CHELSIO_T4_SET_OFLD_POLICY, &op); 35111131c927SNavdeep Parhar free_offload_policy(&op); 35121131c927SNavdeep Parhar 35131131c927SNavdeep Parhar return (rc); 35141131c927SNavdeep Parhar } 35151131c927SNavdeep Parhar 35161131c927SNavdeep Parhar static int 3517ac02945fSNavdeep Parhar display_clip(void) 3518ac02945fSNavdeep Parhar { 3519ac02945fSNavdeep Parhar size_t clip_buf_size = 4096; 3520ac02945fSNavdeep Parhar char *buf, name[32]; 3521ac02945fSNavdeep Parhar int rc; 3522ac02945fSNavdeep Parhar 3523ac02945fSNavdeep Parhar buf = malloc(clip_buf_size); 3524ac02945fSNavdeep Parhar if (buf == NULL) { 3525ac02945fSNavdeep Parhar warn("%s", __func__); 3526ac02945fSNavdeep Parhar return (errno); 3527ac02945fSNavdeep Parhar } 3528ac02945fSNavdeep Parhar 3529ac02945fSNavdeep Parhar snprintf(name, sizeof(name), "dev.t%unex.%u.misc.clip", chip_id, inst); 3530ac02945fSNavdeep Parhar rc = sysctlbyname(name, buf, &clip_buf_size, NULL, 0); 3531ac02945fSNavdeep Parhar if (rc != 0) { 3532ac02945fSNavdeep Parhar warn("sysctl %s", name); 3533ac02945fSNavdeep Parhar free(buf); 3534ac02945fSNavdeep Parhar return (errno); 3535ac02945fSNavdeep Parhar } 3536ac02945fSNavdeep Parhar 3537ac02945fSNavdeep Parhar printf("%s\n", buf); 3538ac02945fSNavdeep Parhar free(buf); 3539ac02945fSNavdeep Parhar return (0); 3540ac02945fSNavdeep Parhar } 3541ac02945fSNavdeep Parhar 3542ac02945fSNavdeep Parhar static int 3543ac02945fSNavdeep Parhar clip_cmd(int argc, const char *argv[]) 3544ac02945fSNavdeep Parhar { 3545ac02945fSNavdeep Parhar int rc, af = AF_INET6, add; 3546ac02945fSNavdeep Parhar struct t4_clip_addr ca = {0}; 3547ac02945fSNavdeep Parhar 3548ac02945fSNavdeep Parhar if (argc == 1 && !strcmp(argv[0], "list")) { 3549ac02945fSNavdeep Parhar rc = display_clip(); 3550ac02945fSNavdeep Parhar return (rc); 3551ac02945fSNavdeep Parhar } 3552ac02945fSNavdeep Parhar 3553ac02945fSNavdeep Parhar if (argc != 2) { 3554ac02945fSNavdeep Parhar warnx("incorrect number of arguments."); 3555ac02945fSNavdeep Parhar return (EINVAL); 3556ac02945fSNavdeep Parhar } 3557ac02945fSNavdeep Parhar 3558ac02945fSNavdeep Parhar if (!strcmp(argv[0], "hold")) { 3559ac02945fSNavdeep Parhar add = 1; 3560ac02945fSNavdeep Parhar } else if (!strcmp(argv[0], "rel") || !strcmp(argv[0], "release")) { 3561ac02945fSNavdeep Parhar add = 0; 3562ac02945fSNavdeep Parhar } else { 3563ac02945fSNavdeep Parhar warnx("first argument must be \"hold\" or \"release\""); 3564ac02945fSNavdeep Parhar return (EINVAL); 3565ac02945fSNavdeep Parhar } 3566ac02945fSNavdeep Parhar 3567ac02945fSNavdeep Parhar rc = parse_ipaddr(argv[0], argv, &af, &ca.addr[0], &ca.mask[0], 1); 3568ac02945fSNavdeep Parhar if (rc != 0) 3569ac02945fSNavdeep Parhar return (rc); 3570ac02945fSNavdeep Parhar 3571ac02945fSNavdeep Parhar if (add) 3572ac02945fSNavdeep Parhar rc = doit(CHELSIO_T4_HOLD_CLIP_ADDR, &ca); 3573ac02945fSNavdeep Parhar else 3574ac02945fSNavdeep Parhar rc = doit(CHELSIO_T4_RELEASE_CLIP_ADDR, &ca); 3575ac02945fSNavdeep Parhar 3576ac02945fSNavdeep Parhar return (rc); 3577ac02945fSNavdeep Parhar } 3578ac02945fSNavdeep Parhar 3579ac02945fSNavdeep Parhar static int 358054912308SNavdeep Parhar run_cmd(int argc, const char *argv[]) 358154912308SNavdeep Parhar { 358254912308SNavdeep Parhar int rc = -1; 358354912308SNavdeep Parhar const char *cmd = argv[0]; 358454912308SNavdeep Parhar 358554912308SNavdeep Parhar /* command */ 358654912308SNavdeep Parhar argc--; 358754912308SNavdeep Parhar argv++; 358854912308SNavdeep Parhar 358954912308SNavdeep Parhar if (!strcmp(cmd, "reg") || !strcmp(cmd, "reg32")) 359054912308SNavdeep Parhar rc = register_io(argc, argv, 4); 359154912308SNavdeep Parhar else if (!strcmp(cmd, "reg64")) 359254912308SNavdeep Parhar rc = register_io(argc, argv, 8); 359354912308SNavdeep Parhar else if (!strcmp(cmd, "regdump")) 359454912308SNavdeep Parhar rc = dump_regs(argc, argv); 359554912308SNavdeep Parhar else if (!strcmp(cmd, "filter")) 359636ea2fe3SNavdeep Parhar rc = filter_cmd(argc, argv, 0); 359754912308SNavdeep Parhar else if (!strcmp(cmd, "context")) 359854912308SNavdeep Parhar rc = get_sge_context(argc, argv); 359954912308SNavdeep Parhar else if (!strcmp(cmd, "loadfw")) 360054912308SNavdeep Parhar rc = loadfw(argc, argv); 360154912308SNavdeep Parhar else if (!strcmp(cmd, "memdump")) 360254912308SNavdeep Parhar rc = memdump(argc, argv); 360354912308SNavdeep Parhar else if (!strcmp(cmd, "tcb")) 360454912308SNavdeep Parhar rc = read_tcb(argc, argv); 360554912308SNavdeep Parhar else if (!strcmp(cmd, "i2c")) 360654912308SNavdeep Parhar rc = read_i2c(argc, argv); 360754912308SNavdeep Parhar else if (!strcmp(cmd, "clearstats")) 360854912308SNavdeep Parhar rc = clearstats(argc, argv); 360954912308SNavdeep Parhar else if (!strcmp(cmd, "tracer")) 361054912308SNavdeep Parhar rc = tracer_cmd(argc, argv); 361154912308SNavdeep Parhar else if (!strcmp(cmd, "modinfo")) 361254912308SNavdeep Parhar rc = modinfo(argc, argv); 361354912308SNavdeep Parhar else if (!strcmp(cmd, "sched-class")) 361454912308SNavdeep Parhar rc = sched_class(argc, argv); 361554912308SNavdeep Parhar else if (!strcmp(cmd, "sched-queue")) 361654912308SNavdeep Parhar rc = sched_queue(argc, argv); 361754912308SNavdeep Parhar else if (!strcmp(cmd, "loadcfg")) 361854912308SNavdeep Parhar rc = loadcfg(argc, argv); 36198f82718fSNavdeep Parhar else if (!strcmp(cmd, "loadboot")) 36208f82718fSNavdeep Parhar rc = loadboot(argc, argv); 36218f82718fSNavdeep Parhar else if (!strcmp(cmd, "loadboot-cfg")) 36228f82718fSNavdeep Parhar rc = loadbootcfg(argc, argv); 3623f856f099SNavdeep Parhar else if (!strcmp(cmd, "dumpstate")) 3624f856f099SNavdeep Parhar rc = dumpstate(argc, argv); 36251131c927SNavdeep Parhar else if (!strcmp(cmd, "policy")) 36261131c927SNavdeep Parhar rc = load_offload_policy(argc, argv); 362736ea2fe3SNavdeep Parhar else if (!strcmp(cmd, "hashfilter")) 362836ea2fe3SNavdeep Parhar rc = filter_cmd(argc, argv, 1); 3629ac02945fSNavdeep Parhar else if (!strcmp(cmd, "clip")) 3630ac02945fSNavdeep Parhar rc = clip_cmd(argc, argv); 363154912308SNavdeep Parhar else { 363254912308SNavdeep Parhar rc = EINVAL; 363354912308SNavdeep Parhar warnx("invalid command \"%s\"", cmd); 363454912308SNavdeep Parhar } 363554912308SNavdeep Parhar 363654912308SNavdeep Parhar return (rc); 363754912308SNavdeep Parhar } 363854912308SNavdeep Parhar 363954912308SNavdeep Parhar #define MAX_ARGS 15 364054912308SNavdeep Parhar static int 364154912308SNavdeep Parhar run_cmd_loop(void) 364254912308SNavdeep Parhar { 364354912308SNavdeep Parhar int i, rc = 0; 364454912308SNavdeep Parhar char buffer[128], *buf; 364554912308SNavdeep Parhar const char *args[MAX_ARGS + 1]; 364654912308SNavdeep Parhar 364754912308SNavdeep Parhar /* 364854912308SNavdeep Parhar * Simple loop: displays a "> " prompt and processes any input as a 364954912308SNavdeep Parhar * cxgbetool command. You're supposed to enter only the part after 365054912308SNavdeep Parhar * "cxgbetool t4nexX". Use "quit" or "exit" to exit. 365154912308SNavdeep Parhar */ 365254912308SNavdeep Parhar for (;;) { 365354912308SNavdeep Parhar fprintf(stdout, "> "); 365454912308SNavdeep Parhar fflush(stdout); 365554912308SNavdeep Parhar buf = fgets(buffer, sizeof(buffer), stdin); 365654912308SNavdeep Parhar if (buf == NULL) { 365754912308SNavdeep Parhar if (ferror(stdin)) { 365854912308SNavdeep Parhar warn("stdin error"); 365954912308SNavdeep Parhar rc = errno; /* errno from fgets */ 366054912308SNavdeep Parhar } 366154912308SNavdeep Parhar break; 366254912308SNavdeep Parhar } 366354912308SNavdeep Parhar 366454912308SNavdeep Parhar i = 0; 366554912308SNavdeep Parhar while ((args[i] = strsep(&buf, " \t\n")) != NULL) { 366654912308SNavdeep Parhar if (args[i][0] != 0 && ++i == MAX_ARGS) 366754912308SNavdeep Parhar break; 366854912308SNavdeep Parhar } 366954912308SNavdeep Parhar args[i] = 0; 367054912308SNavdeep Parhar 367154912308SNavdeep Parhar if (i == 0) 367254912308SNavdeep Parhar continue; /* skip empty line */ 367354912308SNavdeep Parhar 367454912308SNavdeep Parhar if (!strcmp(args[0], "quit") || !strcmp(args[0], "exit")) 367554912308SNavdeep Parhar break; 367654912308SNavdeep Parhar 367754912308SNavdeep Parhar rc = run_cmd(i, args); 367854912308SNavdeep Parhar } 367954912308SNavdeep Parhar 368054912308SNavdeep Parhar /* rc normally comes from the last command (not including quit/exit) */ 368154912308SNavdeep Parhar return (rc); 368254912308SNavdeep Parhar } 368354912308SNavdeep Parhar 3684ac02945fSNavdeep Parhar static void 3685ac02945fSNavdeep Parhar parse_nexus_name(const char *s) 3686ac02945fSNavdeep Parhar { 3687ac02945fSNavdeep Parhar char junk; 3688ac02945fSNavdeep Parhar 3689ac02945fSNavdeep Parhar if (sscanf(s, "t%unex%u%c", &chip_id, &inst, &junk) != 2) 3690ac02945fSNavdeep Parhar errx(EINVAL, "invalid nexus \"%s\"", s); 3691ac02945fSNavdeep Parhar nexus = s; 3692ac02945fSNavdeep Parhar } 3693ac02945fSNavdeep Parhar 369454912308SNavdeep Parhar int 369554912308SNavdeep Parhar main(int argc, const char *argv[]) 369654912308SNavdeep Parhar { 369754912308SNavdeep Parhar int rc = -1; 369854912308SNavdeep Parhar 369954912308SNavdeep Parhar progname = argv[0]; 370054912308SNavdeep Parhar 370154912308SNavdeep Parhar if (argc == 2) { 370254912308SNavdeep Parhar if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) { 370354912308SNavdeep Parhar usage(stdout); 370454912308SNavdeep Parhar exit(0); 370554912308SNavdeep Parhar } 370654912308SNavdeep Parhar } 370754912308SNavdeep Parhar 370854912308SNavdeep Parhar if (argc < 3) { 370954912308SNavdeep Parhar usage(stderr); 371054912308SNavdeep Parhar exit(EINVAL); 371154912308SNavdeep Parhar } 371254912308SNavdeep Parhar 3713ac02945fSNavdeep Parhar parse_nexus_name(argv[1]); 371454912308SNavdeep Parhar 371554912308SNavdeep Parhar /* progname and nexus */ 371654912308SNavdeep Parhar argc -= 2; 371754912308SNavdeep Parhar argv += 2; 371854912308SNavdeep Parhar 371954912308SNavdeep Parhar if (argc == 1 && !strcmp(argv[0], "stdio")) 372054912308SNavdeep Parhar rc = run_cmd_loop(); 372154912308SNavdeep Parhar else 372254912308SNavdeep Parhar rc = run_cmd(argc, argv); 372354912308SNavdeep Parhar 372454912308SNavdeep Parhar return (rc); 372554912308SNavdeep Parhar } 3726