mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-24 11:29:10 +00:00
1799 lines
51 KiB
C
1799 lines
51 KiB
C
/**************************************************************************
|
|
|
|
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 <sys/cdefs.h>
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <err.h>
|
|
#include <errno.h>
|
|
#include <inttypes.h>
|
|
#include <sys/param.h>
|
|
#include <sys/time.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/socket.h>
|
|
|
|
#include <netinet/in.h>
|
|
#include <arpa/inet.h>
|
|
|
|
#include <net/if.h>
|
|
#include <net/if_var.h>
|
|
#include <net/if_types.h>
|
|
|
|
#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 <cxgb_ioctl.h>
|
|
#include <common/cxgb_regs.h>
|
|
#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 <interface> [operation]\n", progname);
|
|
fprintf(fp,
|
|
#ifdef CHELSIO_INTERNAL
|
|
"\treg <address>[=<val>] read/write register\n"
|
|
"\ttpi <address>[=<val>] read/write TPI register\n"
|
|
"\tmdio <phy_addr> <mmd_addr>\n"
|
|
"\t <reg_addr> [<val>] read/write MDIO register\n"
|
|
#endif
|
|
"\tmtus [<mtu0>...<mtuN>] read/write MTU table\n"
|
|
#ifdef CHELSIO_INTERNAL
|
|
"\tpm [<TX page spec> <RX page spec>] read/write PM config\n"
|
|
"\ttcam [<#serv> <#routes> <#filters>] read/write TCAM config\n"
|
|
"\ttcb <index> read TCB\n"
|
|
#endif
|
|
"\tregdump [<module>] dump registers\n"
|
|
#ifdef CHELSIO_INTERNAL
|
|
"\ttcamdump <address> <count> show TCAM contents\n"
|
|
"\tcontext <type> <id> show an SGE context\n"
|
|
"\tdesc <qset> <queue> <idx> [<cnt>] dump SGE descriptors\n"
|
|
"\tmemdump cm|tx|rx <addr> <len> dump a mem range\n"
|
|
"\tmeminfo show memory info\n"
|
|
#endif
|
|
"\tup activate TOE\n"
|
|
"\tproto [<protocol image>] read/write proto SRAM\n"
|
|
"\tloadfw <FW image> download firmware\n"
|
|
"\tqset [<index> [<param> <val>] ...] read/write qset parameters\n"
|
|
"\tqsets [<# of qsets>] read/write # of qsets\n"
|
|
"\ttrace tx|rx|all on|off [not]\n"
|
|
"\t [<param> <val>[:<mask>]] ... write trace parameters\n"
|
|
"\tt1powersave [on|off] enable/disable T1xx powersave mode\n"
|
|
"\tpktsched port <idx> <min> <max> set TX port scheduler params\n"
|
|
"\tpktsched tunnelq <idx> <max>\n"
|
|
"\t <binding> 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;
|
|
}
|