git: e827b61cacdd - main - cxgbetool(8): Be flexible about the nexus name.

From: Navdeep Parhar <np_at_FreeBSD.org>
Date: Mon, 17 Jun 2024 02:11:34 UTC
The branch main has been updated by np:

URL: https://cgit.FreeBSD.org/src/commit/?id=e827b61cacddd4bc9a2f1657ad8c6d2bcd70d52e

commit e827b61cacddd4bc9a2f1657ad8c6d2bcd70d52e
Author:     Navdeep Parhar <np@FreeBSD.org>
AuthorDate: 2024-06-13 20:17:55 +0000
Commit:     Navdeep Parhar <np@FreeBSD.org>
CommitDate: 2024-06-17 01:54:02 +0000

    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 | 116 +++++++++++++++++++++++++++--------------
 1 file changed, 76 insertions(+), 40 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 <errno.h>
 #include <fcntl.h>
 #include <limits.h>
+#include <stdbool.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -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 <nexus> [operation]\n", progname);
+	fprintf(fp, "Usage: %s <nexus> [operation]\n", g.progname);
 	fprintf(fp,
 	    "\tclearstats <port>                   clear port statistics\n"
 	    "\tclip hold|release <ip6>             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);
-		}
-	}
-
-	rc = ioctl(fd, cmd, data);
-	if (rc < 0) {
-		warn("%s", cmdstr);
-		rc = errno;
+	if (ioctl(g.fd, cmd, data) < 0) {
+		if (g.warn_on_ioctl_err)
+			warn("%s", cmdstr);
+		return (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);
 }
 
+#define A_PL_WHOAMI 0x19400
+#define A_PL_REV 0x1943c
+#define A_PL_VF_WHOAMI 0x200
+#define A_PL_VF_REV 0x204
+
 static void
-parse_nexus_name(const char *s)
+open_nexus_device(const char *s)
 {
-	char junk;
-
-	if (sscanf(s, "t%unex%u%c", &chip_id, &inst, &junk) != 2)
-		errx(EINVAL, "invalid nexus \"%s\"", s);
-	nexus = 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;