/************************************************************************** Copyright (c) 2007, Chelsio Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Chelsio Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define NMTUS 16 #define TCB_SIZE 128 #define TCB_WORDS (TCB_SIZE / 4) #define PROTO_SRAM_LINES 128 #define PROTO_SRAM_LINE_BITS 132 #define PROTO_SRAM_LINE_NIBBLES (132 / 4) #define PROTO_SRAM_SIZE (PROTO_SRAM_LINE_NIBBLES * PROTO_SRAM_LINES / 2) #define PROTO_SRAM_EEPROM_ADDR 4096 #include #include #include "version.h" struct reg_info { const char *name; uint16_t addr; uint16_t len; }; #include "reg_defs.c" #if defined(CONFIG_T3_REGS) # include "reg_defs_t3.c" # include "reg_defs_t3b.c" #endif static const char *progname; static void __attribute__((noreturn)) usage(FILE *fp) { fprintf(fp, "Usage: %s [operation]\n", progname); fprintf(fp, #ifdef CHELSIO_INTERNAL "\treg
[=] read/write register\n" "\ttpi
[=] read/write TPI register\n" "\tmdio \n" "\t [] read/write MDIO register\n" #endif "\tmtus [...] read/write MTU table\n" #ifdef CHELSIO_INTERNAL "\tpm [ ] read/write PM config\n" "\ttcam [<#serv> <#routes> <#filters>] read/write TCAM config\n" "\ttcb read TCB\n" #endif "\tregdump [] dump registers\n" #ifdef CHELSIO_INTERNAL "\ttcamdump
show TCAM contents\n" "\tcontext show an SGE context\n" "\tdesc [] dump SGE descriptors\n" "\tmemdump cm|tx|rx dump a mem range\n" "\tmeminfo show memory info\n" #endif "\tup activate TOE\n" "\tproto [] read/write proto SRAM\n" "\tloadfw download firmware\n" "\tqset [ [ ] ...] read/write qset parameters\n" "\tqsets [<# of qsets>] read/write # of qsets\n" "\ttrace tx|rx|all on|off [not]\n" "\t [ [:]] ... write trace parameters\n" "\tt1powersave [on|off] enable/disable T1xx powersave mode\n" "\tpktsched port set TX port scheduler params\n" "\tpktsched tunnelq \n" "\t set TX tunnelq scheduler params\n" ); exit(fp == stderr ? 1 : 0); } /* * Make a TOETOOL ioctl call. */ static int doit(const char *iff_name, unsigned long cmd, void *data) { static int fd = 0; if (fd == 0) { char buf[64]; snprintf(buf, 64, "/dev/%s", iff_name); if ((fd = open(buf, O_RDWR)) < 0) return (EINVAL); } return ioctl(fd, cmd, data) < 0 ? -1 : 0; } static int get_int_arg(const char *s, uint32_t *valp) { char *p; *valp = strtoul(s, &p, 0); if (*p) { warnx("bad parameter \"%s\"", s); return -1; } return 0; } static uint32_t read_reg(const char *iff_name, uint32_t addr) { struct ch_reg reg; reg.addr = addr; if (doit(iff_name, CHELSIO_GETREG, ®) < 0) err(1, "register read"); return reg.val; } static void write_reg(const char *iff_name, uint32_t addr, uint32_t val) { struct ch_reg ch_reg; ch_reg.addr = addr; ch_reg.val = val; if (doit(iff_name, CHELSIO_SETREG, &ch_reg) < 0) err(1, "register write"); } static int register_io(int argc, char *argv[], int start_arg, const char *iff_name) { char *p; uint32_t addr, val = 0, write = 0; if (argc != start_arg + 1) return -1; addr = strtoul(argv[start_arg], &p, 0); if (p == argv[start_arg]) return -1; if (*p == '=' && p[1]) { val = strtoul(p + 1, &p, 0); write = 1; } if (*p) { warnx("bad parameter \"%s\"", argv[start_arg]); return -1; } if (write) write_reg(iff_name, addr, val); else { val = read_reg(iff_name, addr); printf("%#x [%u]\n", val, val); } return 0; } static int mdio_io(int argc, char *argv[], int start_arg, const char *iff_name) { struct ifreq ifr; struct mii_data p; unsigned int cmd, phy_addr, reg, mmd, val; if (argc == start_arg + 3) cmd = SIOCGMIIREG; else if (argc == start_arg + 4) cmd = SIOCSMIIREG; else return -1; if (get_int_arg(argv[start_arg], &phy_addr) || get_int_arg(argv[start_arg + 1], &mmd) || get_int_arg(argv[start_arg + 2], ®) || (cmd == SIOCSMIIREG && get_int_arg(argv[start_arg + 3], &val))) return -1; p.phy_id = phy_addr | (mmd << 8); p.reg_num = reg; p.val_in = val; if (doit(iff_name, cmd, &p) < 0) err(1, "MDIO %s", cmd == SIOCGMIIREG ? "read" : "write"); if (cmd == SIOCGMIIREG) printf("%#x [%u]\n", p.val_out, p.val_out); return 0; } static inline uint32_t xtract(uint32_t val, int shift, int len) { return (val >> shift) & ((1 << len) - 1); } static int dump_block_regs(const struct reg_info *reg_array, uint32_t *regs) { uint32_t reg_val = 0; // silence compiler warning for ( ; reg_array->name; ++reg_array) if (!reg_array->len) { reg_val = regs[reg_array->addr / 4]; printf("[%#5x] %-40s %#-10x [%u]\n", reg_array->addr, reg_array->name, reg_val, reg_val); } else { uint32_t v = xtract(reg_val, reg_array->addr, reg_array->len); printf(" %-40s %#-10x [%u]\n", reg_array->name, v, v); } return 1; } static int dump_regs_t2(int argc, char *argv[], int start_arg, uint32_t *regs) { int match = 0; char *block_name = NULL; if (argc == start_arg + 1) block_name = argv[start_arg]; else if (argc != start_arg) return -1; if (!block_name || !strcmp(block_name, "sge")) match += dump_block_regs(sge_regs, regs); if (!block_name || !strcmp(block_name, "mc3")) match += dump_block_regs(mc3_regs, regs); if (!block_name || !strcmp(block_name, "mc4")) match += dump_block_regs(mc4_regs, regs); if (!block_name || !strcmp(block_name, "tpi")) match += dump_block_regs(tpi_regs, regs); if (!block_name || !strcmp(block_name, "tp")) match += dump_block_regs(tp_regs, regs); if (!block_name || !strcmp(block_name, "rat")) match += dump_block_regs(rat_regs, regs); if (!block_name || !strcmp(block_name, "cspi")) match += dump_block_regs(cspi_regs, regs); if (!block_name || !strcmp(block_name, "espi")) match += dump_block_regs(espi_regs, regs); if (!block_name || !strcmp(block_name, "ulp")) match += dump_block_regs(ulp_regs, regs); if (!block_name || !strcmp(block_name, "pl")) match += dump_block_regs(pl_regs, regs); if (!block_name || !strcmp(block_name, "mc5")) match += dump_block_regs(mc5_regs, regs); if (!match) errx(1, "unknown block \"%s\"", block_name); return 0; } #if defined(CONFIG_T3_REGS) static int dump_regs_t3(int argc, char *argv[], int start_arg, uint32_t *regs, int is_pcie) { int match = 0; char *block_name = NULL; if (argc == start_arg + 1) block_name = argv[start_arg]; else if (argc != start_arg) return -1; if (!block_name || !strcmp(block_name, "sge")) match += dump_block_regs(sge3_regs, regs); if (!block_name || !strcmp(block_name, "pci")) match += dump_block_regs(is_pcie ? pcie0_regs : pcix1_regs, regs); if (!block_name || !strcmp(block_name, "t3dbg")) match += dump_block_regs(t3dbg_regs, regs); if (!block_name || !strcmp(block_name, "pmrx")) match += dump_block_regs(mc7_pmrx_regs, regs); if (!block_name || !strcmp(block_name, "pmtx")) match += dump_block_regs(mc7_pmtx_regs, regs); if (!block_name || !strcmp(block_name, "cm")) match += dump_block_regs(mc7_cm_regs, regs); if (!block_name || !strcmp(block_name, "cim")) match += dump_block_regs(cim_regs, regs); if (!block_name || !strcmp(block_name, "tp")) match += dump_block_regs(tp1_regs, regs); if (!block_name || !strcmp(block_name, "ulp_rx")) match += dump_block_regs(ulp2_rx_regs, regs); if (!block_name || !strcmp(block_name, "ulp_tx")) match += dump_block_regs(ulp2_tx_regs, regs); if (!block_name || !strcmp(block_name, "pmrx")) match += dump_block_regs(pm1_rx_regs, regs); if (!block_name || !strcmp(block_name, "pmtx")) match += dump_block_regs(pm1_tx_regs, regs); if (!block_name || !strcmp(block_name, "mps")) match += dump_block_regs(mps0_regs, regs); if (!block_name || !strcmp(block_name, "cplsw")) match += dump_block_regs(cpl_switch_regs, regs); if (!block_name || !strcmp(block_name, "smb")) match += dump_block_regs(smb0_regs, regs); if (!block_name || !strcmp(block_name, "i2c")) match += dump_block_regs(i2cm0_regs, regs); if (!block_name || !strcmp(block_name, "mi1")) match += dump_block_regs(mi1_regs, regs); if (!block_name || !strcmp(block_name, "sf")) match += dump_block_regs(sf1_regs, regs); if (!block_name || !strcmp(block_name, "pl")) match += dump_block_regs(pl3_regs, regs); if (!block_name || !strcmp(block_name, "mc5")) match += dump_block_regs(mc5a_regs, regs); if (!block_name || !strcmp(block_name, "xgmac0")) match += dump_block_regs(xgmac0_0_regs, regs); if (!block_name || !strcmp(block_name, "xgmac1")) match += dump_block_regs(xgmac0_1_regs, regs); if (!match) errx(1, "unknown block \"%s\"", block_name); return 0; } static int dump_regs_t3b(int argc, char *argv[], int start_arg, uint32_t *regs, int is_pcie) { int match = 0; char *block_name = NULL; if (argc == start_arg + 1) block_name = argv[start_arg]; else if (argc != start_arg) return -1; if (!block_name || !strcmp(block_name, "sge")) match += dump_block_regs(t3b_sge3_regs, regs); if (!block_name || !strcmp(block_name, "pci")) match += dump_block_regs(is_pcie ? t3b_pcie0_regs : t3b_pcix1_regs, regs); if (!block_name || !strcmp(block_name, "t3dbg")) match += dump_block_regs(t3b_t3dbg_regs, regs); if (!block_name || !strcmp(block_name, "pmrx")) match += dump_block_regs(t3b_mc7_pmrx_regs, regs); if (!block_name || !strcmp(block_name, "pmtx")) match += dump_block_regs(t3b_mc7_pmtx_regs, regs); if (!block_name || !strcmp(block_name, "cm")) match += dump_block_regs(t3b_mc7_cm_regs, regs); if (!block_name || !strcmp(block_name, "cim")) match += dump_block_regs(t3b_cim_regs, regs); if (!block_name || !strcmp(block_name, "tp")) match += dump_block_regs(t3b_tp1_regs, regs); if (!block_name || !strcmp(block_name, "ulp_rx")) match += dump_block_regs(t3b_ulp2_rx_regs, regs); if (!block_name || !strcmp(block_name, "ulp_tx")) match += dump_block_regs(t3b_ulp2_tx_regs, regs); if (!block_name || !strcmp(block_name, "pmrx")) match += dump_block_regs(t3b_pm1_rx_regs, regs); if (!block_name || !strcmp(block_name, "pmtx")) match += dump_block_regs(t3b_pm1_tx_regs, regs); if (!block_name || !strcmp(block_name, "mps")) match += dump_block_regs(t3b_mps0_regs, regs); if (!block_name || !strcmp(block_name, "cplsw")) match += dump_block_regs(t3b_cpl_switch_regs, regs); if (!block_name || !strcmp(block_name, "smb")) match += dump_block_regs(t3b_smb0_regs, regs); if (!block_name || !strcmp(block_name, "i2c")) match += dump_block_regs(t3b_i2cm0_regs, regs); if (!block_name || !strcmp(block_name, "mi1")) match += dump_block_regs(t3b_mi1_regs, regs); if (!block_name || !strcmp(block_name, "sf")) match += dump_block_regs(t3b_sf1_regs, regs); if (!block_name || !strcmp(block_name, "pl")) match += dump_block_regs(t3b_pl3_regs, regs); if (!block_name || !strcmp(block_name, "mc5")) match += dump_block_regs(t3b_mc5a_regs, regs); if (!block_name || !strcmp(block_name, "xgmac0")) match += dump_block_regs(t3b_xgmac0_0_regs, regs); if (!block_name || !strcmp(block_name, "xgmac1")) match += dump_block_regs(t3b_xgmac0_1_regs, regs); if (!match) errx(1, "unknown block \"%s\"", block_name); return 0; } #endif static int dump_regs(int argc, char *argv[], int start_arg, const char *iff_name) { int i, vers, revision, is_pcie; struct ifconf_regs regs; regs.len = REGDUMP_SIZE; if ((regs.data = malloc(REGDUMP_SIZE)) == NULL) err(1, "can't malloc"); if (doit(iff_name, CHELSIO_IFCONF_GETREGS, ®s)) err(1, "can't read registers"); vers = regs.version & 0x3ff; revision = (regs.version >> 10) & 0x3f; is_pcie = (regs.version & 0x80000000) != 0; if (vers <= 2) return dump_regs_t2(argc, argv, start_arg, (uint32_t *)regs.data); #if defined(CONFIG_T3_REGS) if (vers == 3) { if (revision == 0) return dump_regs_t3(argc, argv, start_arg, (uint32_t *)regs.data, is_pcie); if (revision == 2) return dump_regs_t3b(argc, argv, start_arg, (uint32_t *)regs.data, is_pcie); } #endif errx(1, "unknown card type %d", vers); return 0; } static int t3_meminfo(const uint32_t *regs) { enum { SG_EGR_CNTX_BADDR = 0x58, SG_CQ_CONTEXT_BADDR = 0x6c, CIM_SDRAM_BASE_ADDR = 0x28c, CIM_SDRAM_ADDR_SIZE = 0x290, TP_CMM_MM_BASE = 0x314, TP_CMM_TIMER_BASE = 0x318, TP_CMM_MM_RX_FLST_BASE = 0x460, TP_CMM_MM_TX_FLST_BASE = 0x464, TP_CMM_MM_PS_FLST_BASE = 0x468, ULPRX_ISCSI_LLIMIT = 0x50c, ULPRX_ISCSI_ULIMIT = 0x510, ULPRX_TDDP_LLIMIT = 0x51c, ULPRX_TDDP_ULIMIT = 0x520, ULPRX_STAG_LLIMIT = 0x52c, ULPRX_STAG_ULIMIT = 0x530, ULPRX_RQ_LLIMIT = 0x534, ULPRX_RQ_ULIMIT = 0x538, ULPRX_PBL_LLIMIT = 0x53c, ULPRX_PBL_ULIMIT = 0x540, }; unsigned int egr_cntxt = regs[SG_EGR_CNTX_BADDR / 4], cq_cntxt = regs[SG_CQ_CONTEXT_BADDR / 4], timers = regs[TP_CMM_TIMER_BASE / 4] & 0xfffffff, pstructs = regs[TP_CMM_MM_BASE / 4], pstruct_fl = regs[TP_CMM_MM_PS_FLST_BASE / 4], rx_fl = regs[TP_CMM_MM_RX_FLST_BASE / 4], tx_fl = regs[TP_CMM_MM_TX_FLST_BASE / 4], cim_base = regs[CIM_SDRAM_BASE_ADDR / 4], cim_size = regs[CIM_SDRAM_ADDR_SIZE / 4]; unsigned int iscsi_ll = regs[ULPRX_ISCSI_LLIMIT / 4], iscsi_ul = regs[ULPRX_ISCSI_ULIMIT / 4], tddp_ll = regs[ULPRX_TDDP_LLIMIT / 4], tddp_ul = regs[ULPRX_TDDP_ULIMIT / 4], stag_ll = regs[ULPRX_STAG_LLIMIT / 4], stag_ul = regs[ULPRX_STAG_ULIMIT / 4], rq_ll = regs[ULPRX_RQ_LLIMIT / 4], rq_ul = regs[ULPRX_RQ_ULIMIT / 4], pbl_ll = regs[ULPRX_PBL_LLIMIT / 4], pbl_ul = regs[ULPRX_PBL_ULIMIT / 4]; printf("CM memory map:\n"); printf(" TCB region: 0x%08x - 0x%08x [%u]\n", 0, egr_cntxt - 1, egr_cntxt); printf(" Egress contexts: 0x%08x - 0x%08x [%u]\n", egr_cntxt, cq_cntxt - 1, cq_cntxt - egr_cntxt); printf(" CQ contexts: 0x%08x - 0x%08x [%u]\n", cq_cntxt, timers - 1, timers - cq_cntxt); printf(" Timers: 0x%08x - 0x%08x [%u]\n", timers, pstructs - 1, pstructs - timers); printf(" Pstructs: 0x%08x - 0x%08x [%u]\n", pstructs, pstruct_fl - 1, pstruct_fl - pstructs); printf(" Pstruct FL: 0x%08x - 0x%08x [%u]\n", pstruct_fl, rx_fl - 1, rx_fl - pstruct_fl); printf(" Rx FL: 0x%08x - 0x%08x [%u]\n", rx_fl, tx_fl - 1, tx_fl - rx_fl); printf(" Tx FL: 0x%08x - 0x%08x [%u]\n", tx_fl, cim_base - 1, cim_base - tx_fl); printf(" uP RAM: 0x%08x - 0x%08x [%u]\n", cim_base, cim_base + cim_size - 1, cim_size); printf("\nPMRX memory map:\n"); printf(" iSCSI region: 0x%08x - 0x%08x [%u]\n", iscsi_ll, iscsi_ul, iscsi_ul - iscsi_ll + 1); printf(" TCP DDP region: 0x%08x - 0x%08x [%u]\n", tddp_ll, tddp_ul, tddp_ul - tddp_ll + 1); printf(" TPT region: 0x%08x - 0x%08x [%u]\n", stag_ll, stag_ul, stag_ul - stag_ll + 1); printf(" RQ region: 0x%08x - 0x%08x [%u]\n", rq_ll, rq_ul, rq_ul - rq_ll + 1); printf(" PBL region: 0x%08x - 0x%08x [%u]\n", pbl_ll, pbl_ul, pbl_ul - pbl_ll + 1); return 0; } static int meminfo(int argc, char *argv[], int start_arg, const char *iff_name) { int vers; struct ifconf_regs regs; if ((regs.data = malloc(REGDUMP_SIZE)) == NULL) err(1, "can't malloc"); if (doit(iff_name, CHELSIO_IFCONF_GETREGS, ®s)) err(1, "can't read registers"); vers = regs.version & 0x3ff; if (vers == 3) return t3_meminfo((uint32_t *)regs.data); errx(1, "unknown card type %d", vers); return 0; } #ifdef notyet static int mtu_tab_op(int argc, char *argv[], int start_arg, const char *iff_name) { struct toetool_mtus op; int i; if (argc == start_arg) { op.cmd = TOETOOL_GETMTUTAB; op.nmtus = MAX_NMTUS; if (doit(iff_name, &op) < 0) err(1, "get MTU table"); for (i = 0; i < op.nmtus; ++i) printf("%u ", op.mtus[i]); printf("\n"); } else if (argc <= start_arg + MAX_NMTUS) { op.cmd = TOETOOL_SETMTUTAB; op.nmtus = argc - start_arg; for (i = 0; i < op.nmtus; ++i) { char *p; unsigned long m = strtoul(argv[start_arg + i], &p, 0); if (*p || m > 9600) { warnx("bad parameter \"%s\"", argv[start_arg + i]); return -1; } if (i && m < op.mtus[i - 1]) errx(1, "MTUs must be in ascending order"); op.mtus[i] = m; } if (doit(iff_name, &op) < 0) err(1, "set MTU table"); } else return -1; return 0; } #endif #ifdef CHELSIO_INTERNAL static void show_egress_cntxt(uint32_t data[]) { printf("credits: %u\n", data[0] & 0x7fff); printf("GTS: %u\n", (data[0] >> 15) & 1); printf("index: %u\n", data[0] >> 16); printf("queue size: %u\n", data[1] & 0xffff); printf("base address: 0x%llx\n", ((data[1] >> 16) | ((uint64_t)data[2] << 16) | (((uint64_t)data[3] & 0xf) << 48)) << 12); printf("rsp queue #: %u\n", (data[3] >> 4) & 7); printf("cmd queue #: %u\n", (data[3] >> 7) & 1); printf("TUN: %u\n", (data[3] >> 8) & 1); printf("TOE: %u\n", (data[3] >> 9) & 1); printf("generation: %u\n", (data[3] >> 10) & 1); printf("uP token: %u\n", (data[3] >> 11) & 0xfffff); printf("valid: %u\n", (data[3] >> 31) & 1); } static void show_fl_cntxt(uint32_t data[]) { printf("base address: 0x%llx\n", ((uint64_t)data[0] | ((uint64_t)data[1] & 0xfffff) << 32) << 12); printf("index: %u\n", (data[1] >> 20) | ((data[2] & 0xf) << 12)); printf("queue size: %u\n", (data[2] >> 4) & 0xffff); printf("generation: %u\n", (data[2] >> 20) & 1); printf("entry size: %u\n", ((data[2] >> 21) & 0x7ff) | (data[3] & 0x1fffff)); printf("congest thr: %u\n", (data[3] >> 21) & 0x3ff); printf("GTS: %u\n", (data[3] >> 31) & 1); } static void show_response_cntxt(uint32_t data[]) { printf("index: %u\n", data[0] & 0xffff); printf("size: %u\n", data[0] >> 16); printf("base address: 0x%llx\n", ((uint64_t)data[1] | ((uint64_t)data[2] & 0xfffff) << 32) << 12); printf("MSI-X/RspQ: %u\n", (data[2] >> 20) & 0x3f); printf("intr enable: %u\n", (data[2] >> 26) & 1); printf("intr armed: %u\n", (data[2] >> 27) & 1); printf("generation: %u\n", (data[2] >> 28) & 1); printf("CQ mode: %u\n", (data[2] >> 31) & 1); printf("FL threshold: %u\n", data[3]); } static void show_cq_cntxt(uint32_t data[]) { printf("index: %u\n", data[0] & 0xffff); printf("size: %u\n", data[0] >> 16); printf("base address: 0x%llx\n", ((uint64_t)data[1] | ((uint64_t)data[2] & 0xfffff) << 32) << 12); printf("rsp queue #: %u\n", (data[2] >> 20) & 0x3f); printf("AN: %u\n", (data[2] >> 26) & 1); printf("armed: %u\n", (data[2] >> 27) & 1); printf("ANS: %u\n", (data[2] >> 28) & 1); printf("generation: %u\n", (data[2] >> 29) & 1); printf("overflow mode: %u\n", (data[2] >> 31) & 1); printf("credits: %u\n", data[3] & 0xffff); printf("credit threshold: %u\n", data[3] >> 16); } static int get_sge_context(int argc, char *argv[], int start_arg, const char *iff_name) { struct ch_cntxt ctx; if (argc != start_arg + 2) return -1; if (!strcmp(argv[start_arg], "egress")) ctx.cntxt_type = CNTXT_TYPE_EGRESS; else if (!strcmp(argv[start_arg], "fl")) ctx.cntxt_type = CNTXT_TYPE_FL; else if (!strcmp(argv[start_arg], "response")) ctx.cntxt_type = CNTXT_TYPE_RSP; else if (!strcmp(argv[start_arg], "cq")) ctx.cntxt_type = CNTXT_TYPE_CQ; else { warnx("unknown context type \"%s\"; known types are egress, " "fl, cq, and response", argv[start_arg]); return -1; } if (get_int_arg(argv[start_arg + 1], &ctx.cntxt_id)) return -1; if (doit(iff_name, CHELSIO_GET_SGE_CONTEXT, &ctx) < 0) err(1, "get SGE context"); if (!strcmp(argv[start_arg], "egress")) show_egress_cntxt(ctx.data); else if (!strcmp(argv[start_arg], "fl")) show_fl_cntxt(ctx.data); else if (!strcmp(argv[start_arg], "response")) show_response_cntxt(ctx.data); else if (!strcmp(argv[start_arg], "cq")) show_cq_cntxt(ctx.data); return 0; } #if __BYTE_ORDER == __BIG_ENDIAN # define ntohll(n) (n) #else # define ntohll(n) bswap_64(n) #endif static int get_sge_desc(int argc, char *argv[], int start_arg, const char *iff_name) { uint64_t *p, wr_hdr; unsigned int n = 1, qset, qnum; struct ch_desc desc; if (argc != start_arg + 3 && argc != start_arg + 4) return -1; if (get_int_arg(argv[start_arg], &qset) || get_int_arg(argv[start_arg + 1], &qnum) || get_int_arg(argv[start_arg + 2], &desc.idx)) return -1; if (argc == start_arg + 4 && get_int_arg(argv[start_arg + 3], &n)) return -1; if (qnum > 5) errx(1, "invalid queue number %d, range is 0..5", qnum); desc.queue_num = qset * 6 + qnum; for (; n--; desc.idx++) { if (doit(iff_name, CHELSIO_GET_SGE_DESC, &desc) < 0) err(1, "get SGE descriptor"); p = (uint64_t *)desc.data; wr_hdr = ntohll(*p); printf("Descriptor %u: cmd %u, TID %u, %s%s%s%s%u flits\n", desc.idx, (unsigned int)(wr_hdr >> 56), ((unsigned int)wr_hdr >> 8) & 0xfffff, ((wr_hdr >> 55) & 1) ? "SOP, " : "", ((wr_hdr >> 54) & 1) ? "EOP, " : "", ((wr_hdr >> 53) & 1) ? "COMPL, " : "", ((wr_hdr >> 52) & 1) ? "SGL, " : "", (unsigned int)wr_hdr & 0xff); for (; desc.size; p++, desc.size -= sizeof(uint64_t)) printf("%016" PRIx64 "%c", ntohll(*p), desc.size % 32 == 8 ? '\n' : ' '); } return 0; } #endif #ifdef notyet static int get_tcb2(unsigned int tcb_idx, const char *iff_name) { uint64_t *d; unsigned int i; struct toetool_mem_range *op; op = malloc(sizeof(*op) + TCB_SIZE); if (!op) err(1, "get TCB"); op->cmd = TOETOOL_GET_MEM; op->mem_id = MEM_CM; op->addr = tcb_idx * TCB_SIZE; op->len = TCB_SIZE; if (doit(iff_name, op) < 0) err(1, "get TCB"); for (d = (uint64_t *)op->buf, i = 0; i < TCB_SIZE / 32; i++) { printf("%2u:", i); printf(" %08x %08x %08x %08x", (uint32_t)d[1], (uint32_t)(d[1] >> 32), (uint32_t)d[0], (uint32_t)(d[0] >> 32)); d += 2; printf(" %08x %08x %08x %08x\n", (uint32_t)d[1], (uint32_t)(d[1] >> 32), (uint32_t)d[0], (uint32_t)(d[0] >> 32)); d += 2; } free(op); return 0; } static int get_tcb(int argc, char *argv[], int start_arg, const char *iff_name) { int i; uint32_t *d; struct toetool_tcb op; if (argc != start_arg + 1) return -1; op.cmd = TOETOOL_GET_TCB; if (get_int_arg(argv[start_arg], &op.tcb_index)) return -1; /* * If this operation isn't directly supported by the driver we may * still be able to read TCBs using the generic memory dump operation. */ if (doit(iff_name, &op) < 0) { if (errno != EOPNOTSUPP) err(1, "get TCB"); return get_tcb2(op.tcb_index, iff_name); } for (d = op.tcb_data, i = 0; i < TCB_WORDS; i += 8) { int j; printf("%2u:", 4 * i); for (j = 0; j < 8; ++j) printf(" %08x", *d++); printf("\n"); } return 0; } #endif #ifdef WRC /* * The following defines, typedefs and structures are defined in the FW and * should be exported instead of being redefined here (and kept up in sync). * We'll fix this in the next round of FW cleanup. */ #define CM_WRCONTEXT_BASE 0x20300000 #define CM_WRCONTEXT_OFFSET 0x300000 #define WRC_SIZE (FW_WR_SIZE * (2 + FW_WR_NUM) + 32 + 4 * 128) #define FW_WR_SIZE 128 #define FW_WR_NUM 16 #define FBUF_SIZE (FW_WR_SIZE * FW_WR_NUM) #define FBUF_WRAP_SIZE 128 #define FBUF_WRAP_FSZ (FBUF_WRAP_SZ >> 3) #define MEM_CM_WRC_SIZE WRC_SIZE typedef char int8_t; typedef short int16_t; typedef int int32_t; typedef long long _s64; typedef unsigned char _u8; typedef unsigned short _u16; typedef unsigned int _uint32_t; typedef unsigned long long uint64_t; enum fw_ri_mpa_attrs { FW_RI_MPA_RX_MARKER_ENABLE = 0x1, FW_RI_MPA_TX_MARKER_ENABLE = 0x2, FW_RI_MPA_CRC_ENABLE = 0x4, FW_RI_MPA_IETF_ENABLE = 0x8 } __attribute__ ((packed)); enum fw_ri_qp_caps { FW_RI_QP_RDMA_READ_ENABLE = 0x01, FW_RI_QP_RDMA_WRITE_ENABLE = 0x02, FW_RI_QP_BIND_ENABLE = 0x04, FW_RI_QP_FAST_REGISTER_ENABLE = 0x08, FW_RI_QP_STAG0_ENABLE = 0x10 } __attribute__ ((packed)); enum wrc_state { WRC_STATE_CLOSED, WRC_STATE_ABORTED, WRC_STATE_HALFCLOSED, WRC_STATE_TOE_ESTABLISHED, WRC_STATE_RDMA_TX_DATA_PEND, WRC_STATE_RDMA_PEND, WRC_STATE_RDMA_ESTABLISHED, }; struct _wr { uint32_t a; uint32_t b; }; struct fbuf { uint32_t pp; /* fifo producer pointer */ uint32_t cp; /* fifo consumer pointer */ int32_t num_bytes; /* num bytes stored in the fbuf */ char bufferb[FBUF_SIZE]; /* buffer space in bytes */ char _wrap[FBUF_WRAP_SIZE]; /* wrap buffer size*/ }; struct wrc { uint32_t wrc_tid; _u16 wrc_flags; _u8 wrc_state; _u8 wrc_credits; /* IO */ _u16 wrc_sge_ec; _u8 wrc_sge_respQ; _u8 wrc_port; _u8 wrc_ulp; _u8 wrc_coherency_counter; /* REASSEMBLY */ _u8 wrc_frag_len; _u8 wrc_frag_credits; uint32_t wrc_frag; union { struct { /* TOE */ _u8 aborted; _u8 wrc_num_tx_pages; _u8 wrc_max_tx_pages; _u8 wrc_trace_idx; uint32_t wrc_snd_nxt; uint32_t wrc_snd_max; uint32_t wrc_snd_una; uint32_t wrc_snd_iss; /* RI */ uint32_t wrc_pdid; uint32_t wrc_scqid; uint32_t wrc_rcqid; uint32_t wrc_rq_addr_32a; _u16 wrc_rq_size; _u16 wrc_rq_wr_idx; enum fw_ri_mpa_attrs wrc_mpaattrs; enum fw_ri_qp_caps wrc_qpcaps; _u16 wrc_mulpdu_tagged; _u16 wrc_mulpdu_untagged; _u16 wrc_ord_max; _u16 wrc_ird_max; _u16 wrc_ord; _u16 wrc_ird; _u16 wrc_markeroffset; uint32_t wrc_msn_send; uint32_t wrc_msn_rdma_read; uint32_t wrc_msn_rdma_read_req; _u16 wrc_rdma_read_req_err; _u8 wrc_ack_mode; _u8 wrc_sge_ec_credits; _u16 wrc_maxiolen_tagged; _u16 wrc_maxiolen_untagged; uint32_t wrc_mo; } toe_ri; struct { } ipmi; struct { uint32_t wrc_pad2[24]; } pad; } u __attribute__ ((packed)); /* BUFFERING */ struct fbuf wrc_fbuf __attribute__ ((packed)); }; #define wrc_aborted u.toe_ri.aborted #define wrc_num_tx_pages u.toe_ri.wrc_num_tx_pages #define wrc_max_tx_pages u.toe_ri.wrc_max_tx_pages #define wrc_trace_idx u.toe_ri.wrc_trace_idx #define wrc_snd_nxt u.toe_ri.wrc_snd_nxt #define wrc_snd_max u.toe_ri.wrc_snd_max #define wrc_snd_una u.toe_ri.wrc_snd_una #define wrc_snd_iss u.toe_ri.wrc_snd_iss #define wrc_pdid u.toe_ri.wrc_pdid #define wrc_scqid u.toe_ri.wrc_scqid #define wrc_rcqid u.toe_ri.wrc_rcqid #define wrc_rq_addr_32a u.toe_ri.wrc_rq_addr_32a #define wrc_rq_size u.toe_ri.wrc_rq_size #define wrc_rq_wr_idx u.toe_ri.wrc_rq_wr_idx #define wrc_mpaattrs u.toe_ri.wrc_mpaattrs #define wrc_qpcaps u.toe_ri.wrc_qpcaps #define wrc_mulpdu_tagged u.toe_ri.wrc_mulpdu_tagged #define wrc_mulpdu_untagged u.toe_ri.wrc_mulpdu_untagged #define wrc_ord_max u.toe_ri.wrc_ord_max #define wrc_ird_max u.toe_ri.wrc_ird_max #define wrc_ord u.toe_ri.wrc_ord #define wrc_ird u.toe_ri.wrc_ird #define wrc_markeroffset u.toe_ri.wrc_markeroffset #define wrc_msn_send u.toe_ri.wrc_msn_send #define wrc_msn_rdma_read u.toe_ri.wrc_msn_rdma_read #define wrc_msn_rdma_read_req u.toe_ri.wrc_msn_rdma_read_req #define wrc_rdma_read_req_err u.toe_ri.wrc_rdma_read_req_err #define wrc_ack_mode u.toe_ri.wrc_ack_mode #define wrc_sge_ec_credits u.toe_ri.wrc_sge_ec_credits #define wrc_maxiolen_tagged u.toe_ri.wrc_maxiolen_tagged #define wrc_maxiolen_untagged u.toe_ri.wrc_maxiolen_untagged #define wrc_mo u.toe_ri.wrc_mo static void print_wrc_field(char *field, unsigned int value, unsigned int size) { switch(size) { case 1: printf(" 1 %s: 0x%02x (%u)\n", field, value, value); break; case 2: { unsigned short host_value = ntohs(value); printf(" 2 %s: 0x%04x (%u)\n", field, host_value, host_value); break; } case 4: { unsigned int host_value = ntohl(value); printf(" 4 %s: 0x%08x (%u)\n", field, host_value, host_value); break; } default: printf(" unknown size %u for field %s\n", size, field); } } #define P(field) print_wrc_field(#field, p->wrc_ ## field, sizeof (p->wrc_ ## field)) static void print_wrc(unsigned int wrc_idx, struct wrc *p) { u32 *buf = (u32 *)p; unsigned int i, j; printf("WRC STATE (raw)\n"); for (i = 0; i < 32;) { printf("[%08x]:", 0x20300000 + wrc_idx * MEM_CM_WRC_SIZE + i * 4); for (j = 0; j < 8; j++) { printf(" %08x ", htonl(buf[i++])); } printf("\n"); } printf("WRC BASIC\n"); P(tid); P(flags); P(state); P(credits); printf("WRC IO\n"); P(sge_ec); P(sge_respQ); P(port); P(ulp); P(coherency_counter); printf("WRC REASSEMBLY\n"); P(frag_len); P(frag_credits); P(frag); printf("WRC TOE\n"); P(aborted); P(num_tx_pages); P(max_tx_pages); P(trace_idx); P(snd_nxt); P(snd_max); P(snd_una); P(snd_iss); printf("WRC RI\n"); P(pdid); P(scqid); P(rcqid); P(rq_addr_32a); P(rq_size); P(rq_wr_idx); P(mpaattrs); P(qpcaps); P(mulpdu_tagged); P(mulpdu_untagged); P(ord_max); P(ird_max); P(ord); P(ird); P(markeroffset); P(msn_send); P(msn_rdma_read); P(msn_rdma_read_req); P(rdma_read_req_err); P(ack_mode); P(sge_ec_credits); P(maxiolen_tagged); P(maxiolen_untagged); P(mo); printf("WRC BUFFERING\n"); printf(" 4 fbuf.pp: 0x%08x (%u)\n", htonl(p->wrc_fbuf.pp), htonl(p->wrc_fbuf.pp)); printf(" 4 fbuf.cp: 0x%08x (%u)\n", htonl(p->wrc_fbuf.cp), htonl(p->wrc_fbuf.cp)); printf(" 4 fbuf.num_bytes: 0x%08x (%d)\n", htonl(p->wrc_fbuf.num_bytes), htonl(p->wrc_fbuf.num_bytes)); printf("WRC BUFFER (raw)\n"); for (i = 32; i < (FBUF_SIZE + FBUF_WRAP_SIZE) / 4;) { printf("[%08x]:", 0x20300000 + wrc_idx * MEM_CM_WRC_SIZE + i * 4); for (j = 0; j < 4; j++) { printf(" %08x%08x", htonl(buf[i++]), htonl(buf[i++])); } printf("\n"); } } #undef P #define P(field) print_sizeof(#field, ##field, sizeof (p->##field)) struct history_e { uint32_t wr_addr; uint32_t debug; uint64_t wr_flit0; uint64_t wr_flit1; uint64_t wr_flit2; }; static void print_wrc_zero(unsigned int wrc_idx, struct wrc *p) { uint32_t *buf = (uint32_t *)((unsigned long)p + FW_WR_SIZE * (2 + FW_WR_NUM)); unsigned int i; printf("WRC ZERO\n"); printf("[%08x]:", CM_WRCONTEXT_BASE + wrc_idx * MEM_CM_WRC_SIZE + FW_WR_SIZE * (2 + FW_WR_NUM)); for (i = 0; i < 4;) printf(" %08x%08x", htonl(buf[i]), htonl(buf[i++])); printf("\n"); } static void print_wrc_history(struct wrc *p) { unsigned int i, idx; struct history_e *e = (struct history_e *)((unsigned long)p + FW_WR_SIZE * (2 + FW_WR_NUM) + 32); printf("WRC WR HISTORY, idx %u\n", p->wrc_trace_idx); idx = p->wrc_trace_idx; for (i = 0; i < 16; i++) { printf("%02u: %08x %08x %08x%08x %08x%08x %08x%08x\n", idx, htonl(e[idx].wr_addr), htonl(e[idx].debug), htonl(e[idx].wr_flit0 & 0xFFFFFFFF), htonl(e[idx].wr_flit0 >> 32), htonl(e[idx].wr_flit1 & 0xFFFFFFFF), htonl(e[idx].wr_flit1 >> 32), htonl(e[idx].wr_flit2 & 0xFFFFFFFF), htonl(e[idx].wr_flit2 >> 32)); idx = (idx - 1) & 0xF; } } static int get_wrc(int argc, char *argv[], int start_arg, const char *iff_name) { struct toetool_mem_range *op; uint64_t *p; uint32_t *buf; unsigned int idx, i = 0; if (argc != start_arg + 1) return -1; if (get_int_arg(argv[start_arg], &idx)) return -1; op = malloc(sizeof(*op) + MEM_CM_WRC_SIZE); if (!op) err(1, "get_wrc: malloc failed"); op->cmd = TOETOOL_GET_MEM; op->mem_id = MEM_CM; op->addr = read_reg(iff_name, 0x28c) + CM_WRCONTEXT_OFFSET + idx * MEM_CM_WRC_SIZE; op->len = MEM_CM_WRC_SIZE; buf = (uint32_t *)op->buf; if (doit(iff_name, op) < 0) err(1, "get_wrc"); /* driver manges with the data... put it back into the the FW's view */ for (p = (uint64_t *)op->buf; p < (uint64_t *)(op->buf + MEM_CM_WRC_SIZE); p++) { uint64_t flit = *p; buf[i++] = htonl((uint32_t)(flit >> 32)); buf[i++] = htonl((uint32_t)flit); } print_wrc(idx, (struct wrc *)op->buf); print_wrc_zero(idx, (struct wrc *)op->buf); print_wrc_history((struct wrc *)op->buf); free(op); return 0; } #endif #ifdef notyet static int get_pm_page_spec(const char *s, unsigned int *page_size, unsigned int *num_pages) { char *p; unsigned long val; val = strtoul(s, &p, 0); if (p == s) return -1; if (*p == 'x' && p[1]) { *num_pages = val; *page_size = strtoul(p + 1, &p, 0); } else { *num_pages = -1; *page_size = val; } *page_size <<= 10; // KB -> bytes return *p; } static int conf_pm(int argc, char *argv[], int start_arg, const char *iff_name) { struct toetool_pm op; if (argc == start_arg) { op.cmd = TOETOOL_GET_PM; if (doit(iff_name, &op) < 0) err(1, "read pm config"); printf("%ux%uKB TX pages, %ux%uKB RX pages, %uKB total memory\n", op.tx_num_pg, op.tx_pg_sz >> 10, op.rx_num_pg, op.rx_pg_sz >> 10, op.pm_total >> 10); return 0; } if (argc != start_arg + 2) return -1; if (get_pm_page_spec(argv[start_arg], &op.tx_pg_sz, &op.tx_num_pg)) { warnx("bad parameter \"%s\"", argv[start_arg]); return -1; } if (get_pm_page_spec(argv[start_arg + 1], &op.rx_pg_sz, &op.rx_num_pg)) { warnx("bad parameter \"%s\"", argv[start_arg + 1]); return -1; } op.cmd = TOETOOL_SET_PM; if (doit(iff_name, &op) < 0) err(1, "pm config"); return 0; } static int conf_tcam(int argc, char *argv[], int start_arg, const char *iff_name) { struct toetool_tcam op; if (argc == start_arg) { op.cmd = TOETOOL_GET_TCAM; op.nfilters = 0; if (doit(iff_name, &op) < 0) err(1, "read tcam config"); printf("%u total entries, %u servers, %u filters, %u routes\n", op.tcam_size, op.nservers, op.nfilters, op.nroutes); return 0; } if (argc != start_arg + 3) return -1; if (get_int_arg(argv[start_arg], &op.nservers) || get_int_arg(argv[start_arg + 1], &op.nroutes) || get_int_arg(argv[start_arg + 2], &op.nfilters)) return -1; op.cmd = TOETOOL_SET_TCAM; if (doit(iff_name, &op) < 0) err(1, "tcam config"); return 0; } #endif #ifdef CHELSIO_INTERNAL #ifdef notyet static int dump_tcam(int argc, char *argv[], int start_arg, const char *iff_name) { unsigned int nwords; struct toetool_tcam_word op; if (argc != start_arg + 2) return -1; if (get_int_arg(argv[start_arg], &op.addr) || get_int_arg(argv[start_arg + 1], &nwords)) return -1; op.cmd = TOETOOL_READ_TCAM_WORD; while (nwords--) { if (doit(iff_name, &op) < 0) err(1, "tcam dump"); printf("0x%08x: 0x%02x 0x%08x 0x%08x\n", op.addr, op.buf[0] & 0xff, op.buf[1], op.buf[2]); op.addr++; } return 0; } #endif static void hexdump_8b(unsigned int start, uint64_t *data, unsigned int len) { int i; while (len) { printf("0x%08x:", start); for (i = 0; i < 4 && len; ++i, --len) printf(" %016llx", (unsigned long long)*data++); printf("\n"); start += 32; } } static int dump_mc7(int argc, char *argv[], int start_arg, const char *iff_name) { struct ch_mem_range mem; unsigned int mem_id, addr, len; if (argc != start_arg + 3) return -1; if (!strcmp(argv[start_arg], "cm")) mem_id = MEM_CM; else if (!strcmp(argv[start_arg], "rx")) mem_id = MEM_PMRX; else if (!strcmp(argv[start_arg], "tx")) mem_id = MEM_PMTX; else errx(1, "unknown memory \"%s\"; must be one of \"cm\", \"tx\"," " or \"rx\"", argv[start_arg]); if (get_int_arg(argv[start_arg + 1], &addr) || get_int_arg(argv[start_arg + 2], &len)) return -1; mem.buf = malloc(len); if (!mem.buf) err(1, "memory dump"); mem.mem_id = mem_id; mem.addr = addr; mem.len = len; if (doit(iff_name, CHELSIO_GET_MEM, &mem) < 0) err(1, "memory dump"); hexdump_8b(mem.addr, (uint64_t *)mem.buf, mem.len >> 3); free(mem.buf); return 0; } #endif #ifdef notyet /* Max FW size is 32K including version, +4 bytes for the checksum. */ #define MAX_FW_IMAGE_SIZE (32768 + 4) static int load_fw(int argc, char *argv[], int start_arg, const char *iff_name) { int fd, len; struct toetool_mem_range *op; const char *fname = argv[start_arg]; if (argc != start_arg + 1) return -1; fd = open(fname, O_RDONLY); if (fd < 0) err(1, "load firmware"); op = malloc(sizeof(*op) + MAX_FW_IMAGE_SIZE + 1); if (!op) err(1, "load firmware"); len = read(fd, op->buf, MAX_FW_IMAGE_SIZE + 1); if (len < 0) err(1, "load firmware"); if (len > MAX_FW_IMAGE_SIZE) errx(1, "FW image too large"); op->cmd = TOETOOL_LOAD_FW; op->len = len; if (doit(iff_name, op) < 0) err(1, "load firmware"); return 0; } static int write_proto_sram(const char *fname, const char *iff_name) { int i; char c; struct toetool_proto op = { .cmd = TOETOOL_SET_PROTO }; uint32_t *p = op.data; FILE *fp = fopen(fname, "r"); if (!fp) err(1, "load protocol sram"); for (i = 0; i < 128; i++, p += 5) { int n = fscanf(fp, "%1x%8x%8x%8x%8x", &p[0], &p[1], &p[2], &p[3], &p[4]); if (n != 5) errx(1, "%s: bad line %d", fname, i); } if (fscanf(fp, "%1s", &c) != EOF) errx(1, "%s: protocol sram image has too many lines", fname); fclose(fp); if (doit(iff_name, &op) < 0) err(1, "load protocol sram"); return 0; } static int dump_proto_sram(const char *iff_name) { int i, j; u8 buf[sizeof(struct ethtool_eeprom) + PROTO_SRAM_SIZE]; struct ethtool_eeprom *ee = (struct ethtool_eeprom *)buf; u8 *p = buf + sizeof(struct ethtool_eeprom); ee->cmd = ETHTOOL_GEEPROM; ee->len = PROTO_SRAM_SIZE; ee->offset = PROTO_SRAM_EEPROM_ADDR; if (ethtool_call(iff_name, ee)) err(1, "show protocol sram"); for (i = 0; i < PROTO_SRAM_LINES; i++) { for (j = PROTO_SRAM_LINE_NIBBLES - 1; j >= 0; j--) { int nibble_idx = i * PROTO_SRAM_LINE_NIBBLES + j; u8 nibble = p[nibble_idx / 2]; if (nibble_idx & 1) nibble >>= 4; else nibble &= 0xf; printf("%x", nibble); } putchar('\n'); } return 0; } static int proto_sram_op(int argc, char *argv[], int start_arg, const char *iff_name) { if (argc == start_arg + 1) return write_proto_sram(argv[start_arg], iff_name); if (argc == start_arg) return dump_proto_sram(iff_name); return -1; } #endif static int dump_qset_params(const char *iff_name) { struct ch_qset_params qp; qp.qset_idx = 0; while (doit(iff_name, CHELSIO_GET_QSET_PARAMS, &qp) == 0) { if (!qp.qset_idx) printf("Qnum TxQ0 TxQ1 TxQ2 RspQ RxQ0 RxQ1" " Cong Intr Lat Rx Mode\n"); printf("%4u %6u %6u %6u %6u %6u %6u %5u %9u %s \n", qp.qset_idx, qp.txq_size[0], qp.txq_size[1], qp.txq_size[2], qp.rspq_size, qp.fl_size[0], qp.fl_size[1], qp.cong_thres, qp.intr_lat, qp.polling ? "Polling" : "Interrupt"); qp.qset_idx++; } if (!qp.qset_idx || (errno && errno != EINVAL)) err(1, "get qset parameters"); return 0; } static int qset_config(int argc, char *argv[], int start_arg, const char *iff_name) { struct ch_qset_params qp; if (argc == start_arg) return dump_qset_params(iff_name); if (get_int_arg(argv[start_arg++], &qp.qset_idx)) return -1; qp.txq_size[0] = qp.txq_size[1] = qp.txq_size[2] = -1; qp.fl_size[0] = qp.fl_size[1] = qp.rspq_size = -1; qp.polling = qp.intr_lat = qp.cong_thres = -1; while (start_arg + 2 <= argc) { int32_t *param = NULL; if (!strcmp(argv[start_arg], "txq0")) param = &qp.txq_size[0]; else if (!strcmp(argv[start_arg], "txq1")) param = &qp.txq_size[1]; else if (!strcmp(argv[start_arg], "txq2")) param = &qp.txq_size[2]; else if (!strcmp(argv[start_arg], "rspq")) param = &qp.rspq_size; else if (!strcmp(argv[start_arg], "fl0")) param = &qp.fl_size[0]; else if (!strcmp(argv[start_arg], "fl1")) param = &qp.fl_size[1]; else if (!strcmp(argv[start_arg], "lat")) param = &qp.intr_lat; else if (!strcmp(argv[start_arg], "cong")) param = &qp.cong_thres; else if (!strcmp(argv[start_arg], "mode")) param = &qp.polling; else errx(1, "unknown qset parameter \"%s\"\n" "allowed parameters are \"txq0\", \"txq1\", " "\"txq2\", \"rspq\", \"fl0\", \"fl1\", \"lat\", " "\"cong\", \"mode\' and \"lro\"", argv[start_arg]); start_arg++; if (param == &qp.polling) { if (!strcmp(argv[start_arg], "irq")) qp.polling = 0; else if (!strcmp(argv[start_arg], "polling")) qp.polling = 1; else errx(1, "illegal qset mode \"%s\"\n" "known modes are \"irq\" and \"polling\"", argv[start_arg]); } else if (get_int_arg(argv[start_arg], (uint32_t *)param)) return -1; start_arg++; } if (start_arg != argc) errx(1, "unknown parameter %s", argv[start_arg]); #if 0 printf("%4u %6d %6d %6d %6d %6d %6d %5d %9d %d\n", op.qset_idx, op.txq_size[0], op.txq_size[1], op.txq_size[2], op.rspq_size, op.fl_size[0], op.fl_size[1], op.cong_thres, op.intr_lat, op.polling); #endif if (doit(iff_name, CHELSIO_SET_QSET_PARAMS, &qp) < 0) err(1, "set qset parameters"); return 0; } static int qset_num_config(int argc, char *argv[], int start_arg, const char *iff_name) { struct ch_reg reg; if (argc == start_arg) { if (doit(iff_name, CHELSIO_GET_QSET_NUM, ®) < 0) err(1, "get qsets"); printf("%u\n", reg.val); return 0; } if (argc != start_arg + 1) return -1; if (get_int_arg(argv[start_arg], ®.val)) return -1; if (doit(iff_name, CHELSIO_SET_QSET_NUM, ®) < 0) err(1, "set qsets"); return 0; } /* * Parse a string containing an IP address with an optional network prefix. */ static int parse_ipaddr(const char *s, uint32_t *addr, uint32_t *mask) { char *p, *slash; struct in_addr ia; *mask = 0xffffffffU; slash = strchr(s, '/'); if (slash) *slash = 0; if (!inet_aton(s, &ia)) { if (slash) *slash = '/'; *addr = 0; return -1; } *addr = ntohl(ia.s_addr); if (slash) { unsigned int prefix = strtoul(slash + 1, &p, 10); *slash = '/'; if (p == slash + 1 || *p || prefix > 32) return -1; *mask <<= (32 - prefix); } return 0; } /* * Parse a string containing a value and an optional colon separated mask. */ static int parse_val_mask_param(const char *s, uint32_t *val, uint32_t *mask) { char *p; *mask = 0xffffffffU; *val = strtoul(s, &p, 0); if (p == s) return -1; if (*p == ':' && p[1]) *mask = strtoul(p + 1, &p, 0); return *p ? -1 : 0; } static int parse_trace_param(const char *s, uint32_t *val, uint32_t *mask) { return strchr(s, '.') ? parse_ipaddr(s, val, mask) : parse_val_mask_param(s, val, mask); } static int trace_config(int argc, char *argv[], int start_arg, const char *iff_name) { uint32_t val, mask; struct ch_trace trace; if (argc == start_arg) return -1; memset(&trace, 0, sizeof(trace)); if (!strcmp(argv[start_arg], "tx")) trace.config_tx = 1; else if (!strcmp(argv[start_arg], "rx")) trace.config_rx = 1; else if (!strcmp(argv[start_arg], "all")) trace.config_tx = trace.config_rx = 1; else errx(1, "bad trace filter \"%s\"; must be one of \"rx\", " "\"tx\" or \"all\"", argv[start_arg]); if (argc == ++start_arg) return -1; if (!strcmp(argv[start_arg], "on")) { trace.trace_tx = trace.config_tx; trace.trace_rx = trace.config_rx; } else if (strcmp(argv[start_arg], "off")) errx(1, "bad argument \"%s\"; must be \"on\" or \"off\"", argv[start_arg]); start_arg++; if (start_arg < argc && !strcmp(argv[start_arg], "not")) { trace.invert_match = 1; start_arg++; } while (start_arg + 2 <= argc) { int ret = parse_trace_param(argv[start_arg + 1], &val, &mask); if (!strcmp(argv[start_arg], "interface")) { trace.intf = val; trace.intf_mask = mask; } else if (!strcmp(argv[start_arg], "sip")) { trace.sip = val; trace.sip_mask = mask; } else if (!strcmp(argv[start_arg], "dip")) { trace.dip = val; trace.dip_mask = mask; } else if (!strcmp(argv[start_arg], "sport")) { trace.sport = val; trace.sport_mask = mask; } else if (!strcmp(argv[start_arg], "dport")) { trace.dport = val; trace.dport_mask = mask; } else if (!strcmp(argv[start_arg], "vlan")) { trace.vlan = val; trace.vlan_mask = mask; } else if (!strcmp(argv[start_arg], "proto")) { trace.proto = val; trace.proto_mask = mask; } else errx(1, "unknown trace parameter \"%s\"\n" "known parameters are \"interface\", \"sip\", " "\"dip\", \"sport\", \"dport\", \"vlan\", " "\"proto\"", argv[start_arg]); if (ret < 0) errx(1, "bad parameter \"%s\"", argv[start_arg + 1]); start_arg += 2; } if (start_arg != argc) errx(1, "unknown parameter \"%s\"", argv[start_arg]); #if 0 printf("sip: %x:%x, dip: %x:%x, sport: %x:%x, dport: %x:%x, " "interface: %x:%x, vlan: %x:%x, tx_config: %u, rx_config: %u, " "invert: %u, tx_enable: %u, rx_enable: %u\n", op.sip, op.sip_mask, op.dip, op.dip_mask, op.sport, op.sport_mask, op.dport, op.dport_mask, op.intf, op.intf_mask, op.vlan, op.vlan_mask, op.config_tx, op.config_rx, op.invert_match, op.trace_tx, op.trace_rx); #endif if (doit(iff_name, CHELSIO_SET_TRACE_FILTER, &trace) < 0) err(1, "trace"); return 0; } #ifdef notyet static int t1_powersave(int argc, char *argv[], int start_arg, const char *iff_name) { struct toetool_t1powersave op = { .cmd = TOETOOL_T1POWERSAVE, .mode = 0 }; if (argc == start_arg) op.mode = 2; /* Check powersave mode */ else if (argc == start_arg + 1) { if (strcmp(argv[start_arg], "on") == 0) op.mode = 1; else if (strcmp(argv[start_arg], "off") == 0) op.mode = 0; else { warnx("bad parameter \"%s\"", argv[start_arg]); return -1; } } else { errx(1, "too many arguments"); return -1; } if (doit(iff_name, &op) < 0) err(1, "t1powersave"); if (op.mode & 2) printf("t1powersave is %s\n", (op.mode & 1) ? "on" : "off"); return 0; } #endif static int pktsched(int argc, char *argv[], int start_arg, const char *iff_name) { struct ch_pktsched_params pktsched; unsigned int idx, min = -1, max, binding = -1; if (!strcmp(argv[start_arg], "port")) { if (argc != start_arg + 4) return -1; if (get_int_arg(argv[start_arg + 1], &idx) || get_int_arg(argv[start_arg + 2], &min) || get_int_arg(argv[start_arg + 3], &max)) return -1; pktsched.sched = 0; } else if (!strcmp(argv[start_arg], "tunnelq")) { if (argc != start_arg + 4) return -1; if (get_int_arg(argv[start_arg + 1], &idx) || get_int_arg(argv[start_arg + 2], &max) || get_int_arg(argv[start_arg + 3], &binding)) return -1; pktsched.sched = 1; } else errx(1, "unknown scheduler \"%s\"; must be one of \"port\"" " or \"tunnelq\"", argv[start_arg]); pktsched.idx = idx; pktsched.min = min; pktsched.max = max; pktsched.binding = binding; if (doit(iff_name, CHELSIO_SET_PKTSCHED, &pktsched) < 0) err(1, "pktsched"); return 0; } int main(int argc, char *argv[]) { int r = -1; const char *iff_name; progname = argv[0]; if (argc == 2) { if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) usage(stdout); if (!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version")) { printf("%s version %s\n", PROGNAME, VERSION); printf("%s\n", COPYRIGHT); exit(0); } } if (argc < 3) usage(stderr); iff_name = argv[1]; if (!strcmp(argv[2], "reg")) r = register_io(argc, argv, 3, iff_name); else if (!strcmp(argv[2], "mdio")) r = mdio_io(argc, argv, 3, iff_name); #ifdef notyet else if (!strcmp(argv[2], "tpi")) r = tpi_io(argc, argv, 3, iff_name); else if (!strcmp(argv[2], "up")) r = device_up(argc, argv, 3, iff_name); else if (!strcmp(argv[2], "mtus")) r = mtu_tab_op(argc, argv, 3, iff_name); else if (!strcmp(argv[2], "pm")) r = conf_pm(argc, argv, 3, iff_name); else if (!strcmp(argv[2], "tcam")) r = conf_tcam(argc, argv, 3, iff_name); else if (!strcmp(argv[2], "tcb")) r = get_tcb(argc, argv, 3, iff_name); #ifdef WRC else if (!strcmp(argv[2], "wrc")) r = get_wrc(argc, argv, 3, iff_name); #endif #endif else if (!strcmp(argv[2], "regdump")) r = dump_regs(argc, argv, 3, iff_name); #ifdef CHELSIO_INTERNAL else if (!strcmp(argv[2], "memdump")) r = dump_mc7(argc, argv, 3, iff_name); else if (!strcmp(argv[2], "meminfo")) r = meminfo(argc, argv, 3, iff_name); else if (!strcmp(argv[2], "context")) r = get_sge_context(argc, argv, 3, iff_name); else if (!strcmp(argv[2], "desc")) r = get_sge_desc(argc, argv, 3, iff_name); #endif else if (!strcmp(argv[2], "qset")) r = qset_config(argc, argv, 3, iff_name); else if (!strcmp(argv[2], "qsets")) r = qset_num_config(argc, argv, 3, iff_name); else if (!strcmp(argv[2], "trace")) r = trace_config(argc, argv, 3, iff_name); #ifdef notyet else if (!strcmp(argv[2], "tcamdump")) r = dump_tcam(argc, argv, 3, iff_name); else if (!strcmp(argv[2], "loadfw")) r = load_fw(argc, argv, 3, iff_name); else if (!strcmp(argv[2], "proto")) r = proto_sram_op(argc, argv, 3, iff_name); else if (!strcmp(argv[2], "t1powersave")) r = t1_powersave(argc, argv, 3, iff_name); #endif else if (!strcmp(argv[2], "pktsched")) r = pktsched(argc, argv, 3, iff_name); if (r == -1) usage(stderr); return 0; }