From e827b61cacddd4bc9a2f1657ad8c6d2bcd70d52e Mon Sep 17 00:00:00 2001 From: Navdeep Parhar Date: Thu, 13 Jun 2024 13:17:55 -0700 Subject: [PATCH] cxgbetool(8): Be flexible about the nexus name. Use the name as-is but perform cxgbe specific ioctls on the device to make sure that it is a Terminator device nexus. Determine the chip type, pf/vf, etc. from the device registers rather than the nexus name. This allows cxgbetool to work with the VF driver. MFC after: 1 week Sponsored by: Chelsio Communications --- usr.sbin/cxgbetool/cxgbetool.c | 118 +++++++++++++++++++++------------ 1 file changed, 77 insertions(+), 41 deletions(-) diff --git a/usr.sbin/cxgbetool/cxgbetool.c b/usr.sbin/cxgbetool/cxgbetool.c index bef99ff0f3da..8f58fe8107dc 100644 --- a/usr.sbin/cxgbetool/cxgbetool.c +++ b/usr.sbin/cxgbetool/cxgbetool.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -55,9 +56,16 @@ #define in_range(val, lo, hi) ( val < 0 || (val <= hi && val >= lo)) #define max(x, y) ((x) > (y) ? (x) : (y)) -static const char *progname, *nexus; -static int chip_id; /* 4 for T4, 5 for T5, and so on. */ -static int inst; /* instance of nexus device */ +static struct { + const char *progname, *nexus; + int chip_id; /* 4 for T4, 5 for T5, and so on. */ + int inst; /* instance of nexus device */ + int pf; /* PF# of the nexus (if not VF). */ + bool vf; /* Nexus is a VF. */ + + int fd; + bool warn_on_ioctl_err; +} g; struct reg_info { const char *name; @@ -87,7 +95,7 @@ struct field_desc { static void usage(FILE *fp) { - fprintf(fp, "Usage: %s [operation]\n", progname); + fprintf(fp, "Usage: %s [operation]\n", g.progname); fprintf(fp, "\tclearstats clear port statistics\n" "\tclip hold|release hold/release an address\n" @@ -136,27 +144,12 @@ get_card_vers(unsigned int version) static int real_doit(unsigned long cmd, void *data, const char *cmdstr) { - static int fd = -1; - int rc = 0; - - if (fd == -1) { - char buf[64]; - - snprintf(buf, sizeof(buf), "/dev/%s", nexus); - if ((fd = open(buf, O_RDWR)) < 0) { - warn("open(%s)", nexus); - rc = errno; - return (rc); - } + if (ioctl(g.fd, cmd, data) < 0) { + if (g.warn_on_ioctl_err) + warn("%s", cmdstr); + return (errno); } - - rc = ioctl(fd, cmd, data); - if (rc < 0) { - warn("%s", cmdstr); - rc = errno; - } - - return (rc); + return (0); } #define doit(x, y) real_doit(x, y, #x) @@ -522,7 +515,7 @@ dump_regs(int argc, const char *argv[]) rc = dump_regs_t6(argc, argv, regs.data); } else { warnx("%s (type %d, rev %d) is not a known card.", - nexus, vers, revision); + g.nexus, vers, revision); return (ENOTSUP); } @@ -914,7 +907,7 @@ do_show_one_filter_info(struct t4_filter *t, uint32_t mode) printf("(hash)"); } } - if (chip_id <= 5 && t->fs.prio) + if (g.chip_id <= 5 && t->fs.prio) printf(" Prio"); if (t->fs.rpttid) printf(" RptTID"); @@ -933,7 +926,7 @@ show_filters(int hash) if (rc != 0) return (rc); - if (!hash && chip_id >= 6) { + if (!hash && g.chip_id >= 6) { header = 0; bzero(&t, sizeof (t)); t.idx = 0; @@ -1924,10 +1917,10 @@ get_sge_context(int argc, const char *argv[]) if (rc != 0) return (rc); - if (chip_id == 4) + if (g.chip_id == 4) show_t4_ctxt(&cntxt); else - show_t5t6_ctxt(&cntxt, chip_id); + show_t5t6_ctxt(&cntxt, g.chip_id); return (0); } @@ -2243,7 +2236,7 @@ show_tcb(uint32_t *buf, uint32_t len) } printf("\n"); } - set_tcb_info(TIDTYPE_TCB, chip_id); + set_tcb_info(TIDTYPE_TCB, g.chip_id); set_print_style(PRNTSTYL_COMP); swizzle_tcb(tcb); parse_n_display_xcb(tcb); @@ -2447,7 +2440,7 @@ static void create_tracing_ifnet() { char *cmd[] = { - "/sbin/ifconfig", __DECONST(char *, nexus), "create", NULL + "/sbin/ifconfig", __DECONST(char *, g.nexus), "create", NULL }; char *env[] = {NULL}; @@ -3494,7 +3487,7 @@ display_clip(void) return (errno); } - snprintf(name, sizeof(name), "dev.t%unex.%u.misc.clip", chip_id, inst); + snprintf(name, sizeof(name), "dev.t%unex.%u.misc.clip", g.chip_id, g.inst); rc = sysctlbyname(name, buf, &clip_buf_size, NULL, 0); if (rc != 0) { warn("sysctl %s", name); @@ -3649,14 +3642,57 @@ run_cmd_loop(void) return (rc); } -static void -parse_nexus_name(const char *s) -{ - char junk; +#define A_PL_WHOAMI 0x19400 +#define A_PL_REV 0x1943c +#define A_PL_VF_WHOAMI 0x200 +#define A_PL_VF_REV 0x204 - if (sscanf(s, "t%unex%u%c", &chip_id, &inst, &junk) != 2) - errx(EINVAL, "invalid nexus \"%s\"", s); - nexus = s; +static void +open_nexus_device(const char *s) +{ + const int len = strlen(s); + long long val; + const char *num; + int rc; + u_int chip_id, whoami; + char buf[128]; + + if (len < 2 || isdigit(s[0]) || !isdigit(s[len - 1])) + errx(1, "invalid nexus name \"%s\"", s); + for (num = s + len - 1; isdigit(*num); num--) + continue; + g.inst = strtoll(num, NULL, 0); + g.nexus = s; + snprintf(buf, sizeof(buf), "/dev/%s", g.nexus); + if ((g.fd = open(buf, O_RDWR)) < 0) + err(1, "open(%s)", buf); + + g.warn_on_ioctl_err = false; + rc = read_reg(A_PL_REV, 4, &val); + if (rc == 0) { + /* PF */ + g.vf = false; + whoami = A_PL_WHOAMI; + } else { + rc = read_reg(A_PL_VF_REV, 4, &val); + if (rc != 0) + errx(1, "%s is not a Terminator device.", s); + /* VF */ + g.vf = true; + whoami = A_PL_VF_WHOAMI; + } + chip_id = (val >> 4) & 0xf; + if (chip_id == 0) + chip_id = 4; + if (chip_id < 4 || chip_id > 7) + warnx("%s reports chip_id %d.", s, chip_id); + g.chip_id = chip_id; + + rc = read_reg(whoami, 4, &val); + if (rc != 0) + errx(rc, "failed to read whoami(0x%x): %d", whoami, rc); + g.pf = g.chip_id > 5 ? (val >> 9) & 7 : (val >> 8) & 7; + g.warn_on_ioctl_err = true; } int @@ -3664,7 +3700,7 @@ main(int argc, const char *argv[]) { int rc = -1; - progname = argv[0]; + g.progname = argv[0]; if (argc == 2) { if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) { @@ -3678,7 +3714,7 @@ main(int argc, const char *argv[]) exit(EINVAL); } - parse_nexus_name(argv[1]); + open_nexus_device(argv[1]); /* progname and nexus */ argc -= 2;