diff options
| author | Vishal Kulkarni <vishal@chelsio.com> | 2018-04-13 23:33:08 +0000 |
|---|---|---|
| committer | Robert Mustacchi <rm@joyent.com> | 2018-05-23 23:50:04 +0000 |
| commit | 5a9113e79c46be778552f0a0fd02087e13e41bff (patch) | |
| tree | b917fcc65529b742be84af13ee88c30fd3ade4d2 /usr | |
| parent | aafbdf3fa8f988ec989a8143b47d3158161d2143 (diff) | |
| download | illumos-joyent-5a9113e79c46be778552f0a0fd02087e13e41bff.tar.gz | |
9482 Want cxgbetool
Reviewed by: Toomas Soome <tsoome@me.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Approved by: Dan McDonald <danmcd@joyent.com>
Diffstat (limited to 'usr')
| -rw-r--r-- | usr/src/cmd/Makefile | 1 | ||||
| -rw-r--r-- | usr/src/cmd/cxgbetool/Makefile | 29 | ||||
| -rw-r--r-- | usr/src/cmd/cxgbetool/cxgbetool.c | 293 | ||||
| -rw-r--r-- | usr/src/pkg/manifests/driver-network-cxgbe.mf | 3 | ||||
| -rw-r--r-- | usr/src/uts/common/io/cxgbe/t4nex/t4_ioctl.c | 44 | ||||
| -rw-r--r-- | usr/src/uts/common/io/cxgbe/t4nex/t4nex.h | 8 |
6 files changed, 375 insertions, 3 deletions
diff --git a/usr/src/cmd/Makefile b/usr/src/cmd/Makefile index 7249f43cb1..3d5e3f3e5b 100644 --- a/usr/src/cmd/Makefile +++ b/usr/src/cmd/Makefile @@ -108,6 +108,7 @@ COMMON_SUBDIRS= \ ctrun \ ctstat \ ctwatch \ + cxgbetool \ datadm \ date \ dc \ diff --git a/usr/src/cmd/cxgbetool/Makefile b/usr/src/cmd/cxgbetool/Makefile new file mode 100644 index 0000000000..4a39c9e80f --- /dev/null +++ b/usr/src/cmd/cxgbetool/Makefile @@ -0,0 +1,29 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2018 by Chelsio Communications, Inc. +# +PROG = cxgbetool + +include ../Makefile.cmd + +CFLAGS += $(CCVERBOSE) -I$(SRC)/uts/common/io/cxgbe/t4nex -I$(SRC)/uts/common/io/cxgbe/firmware + +all: $(PROG) + +install: all $(ROOTUSRSBINPROG) + +clean: + +lint: lint_PROG + +include ../Makefile.targ diff --git a/usr/src/cmd/cxgbetool/cxgbetool.c b/usr/src/cmd/cxgbetool/cxgbetool.c new file mode 100644 index 0000000000..d45e843202 --- /dev/null +++ b/usr/src/cmd/cxgbetool/cxgbetool.c @@ -0,0 +1,293 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2018 by Chelsio Communications, Inc. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <stropts.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <sys/socket.h> +#include <strings.h> +#include <sys/varargs.h> +#include <errno.h> +#include <sys/byteorder.h> +#include <inttypes.h> +#include <sys/sysmacros.h> + +#include "t4nex.h" +#include "version.h" +#include "osdep.h" +#include "t4fw_interface.h" + +/* + * Firmware Device Log Dumping + */ + +static const char * const devlog_level_strings[] = { + [FW_DEVLOG_LEVEL_EMERG] = "EMERG", + [FW_DEVLOG_LEVEL_CRIT] = "CRIT", + [FW_DEVLOG_LEVEL_ERR] = "ERR", + [FW_DEVLOG_LEVEL_NOTICE] = "NOTICE", + [FW_DEVLOG_LEVEL_INFO] = "INFO", + [FW_DEVLOG_LEVEL_DEBUG] = "DEBUG" +}; + +static const char * const devlog_facility_strings[] = { + [FW_DEVLOG_FACILITY_CORE] = "CORE", + [FW_DEVLOG_FACILITY_CF] = "CF", + [FW_DEVLOG_FACILITY_SCHED] = "SCHED", + [FW_DEVLOG_FACILITY_TIMER] = "TIMER", + [FW_DEVLOG_FACILITY_RES] = "RES", + [FW_DEVLOG_FACILITY_HW] = "HW", + [FW_DEVLOG_FACILITY_FLR] = "FLR", + [FW_DEVLOG_FACILITY_DMAQ] = "DMAQ", + [FW_DEVLOG_FACILITY_PHY] = "PHY", + [FW_DEVLOG_FACILITY_MAC] = "MAC", + [FW_DEVLOG_FACILITY_PORT] = "PORT", + [FW_DEVLOG_FACILITY_VI] = "VI", + [FW_DEVLOG_FACILITY_FILTER] = "FILTER", + [FW_DEVLOG_FACILITY_ACL] = "ACL", + [FW_DEVLOG_FACILITY_TM] = "TM", + [FW_DEVLOG_FACILITY_QFC] = "QFC", + [FW_DEVLOG_FACILITY_DCB] = "DCB", + [FW_DEVLOG_FACILITY_ETH] = "ETH", + [FW_DEVLOG_FACILITY_OFLD] = "OFLD", + [FW_DEVLOG_FACILITY_RI] = "RI", + [FW_DEVLOG_FACILITY_ISCSI] = "ISCSI", + [FW_DEVLOG_FACILITY_FCOE] = "FCOE", + [FW_DEVLOG_FACILITY_FOISCSI] = "FOISCSI", + [FW_DEVLOG_FACILITY_FOFCOE] = "FOFCOE", + [FW_DEVLOG_FACILITY_CHNET] = "CHNET", +}; + +static const char *progname; + +static void usage(FILE *fp) +{ + fprintf(fp, "Usage: %s <path to t4nex#> [operation]\n", progname); + fprintf(fp, + "\tdevlog show device log\n" + "\tloadfw <FW image> Flash the FW image\n"); + exit(fp == stderr ? 1 : 0); +} + +static void +err(int code, const char *fmt, ...) +{ + va_list ap; + int e = errno; + + va_start(ap, fmt); + fprintf(stderr, "error: "); + vfprintf(stderr, fmt, ap); + fprintf(stderr, ": %s\n", strerror(e)); + va_end(ap); + exit(code); +} + +static int +doit(const char *iff_name, unsigned long cmd, void *data) +{ + int fd = 0; + int rc = 0; + + if ((fd = open(iff_name, O_RDWR)) < 0) + return (-1); + + rc = (ioctl(fd, cmd, data) < 0) ? errno : rc; + close(fd); + return (rc); +} + +static void +get_devlog(int argc, char *argv[], int start_arg, const char *iff_name) +{ + struct t4_devlog *devlog; + struct fw_devlog_e *entry, *buf; + int rc = 0, first = 0, nentries, i, j, len; + uint64_t ftstamp = UINT64_MAX; + + devlog = malloc(T4_DEVLOG_SIZE + sizeof (struct t4_devlog)); + if (!devlog) + err(1, "%s: can't allocate devlog buffer", __func__); + + devlog->len = T4_DEVLOG_SIZE; + /* Get device log */ + rc = doit(iff_name, T4_IOCTL_DEVLOG, devlog); + if (rc == ENOBUFS) { + /* + * Default buffer size is not sufficient to hold device log. + * Driver has updated the devlog.len to indicate the expected + * size. Free the currently allocated devlog.data, allocate + * again with right size and retry. + */ + len = devlog->len; + free(devlog); + + if ((devlog = malloc(len + sizeof (struct t4_devlog))) == NULL) + err(1, "%s: can't reallocate devlog buffer", __func__); + + rc = doit(iff_name, T4_IOCTL_DEVLOG, devlog); + } + if (rc) { + free(devlog); + err(1, "%s: can't get device log", __func__); + } + + /* There are nentries number of entries in the buffer */ + nentries = (devlog->len / sizeof (struct fw_devlog_e)); + + buf = (struct fw_devlog_e *)devlog->data; + + /* Find the first entry */ + for (i = 0; i < nentries; i++) { + entry = &buf[i]; + + if (entry->timestamp == 0) + break; + + entry->timestamp = BE_64(entry->timestamp); + entry->seqno = BE_32(entry->seqno); + for (j = 0; j < 8; j++) + entry->params[j] = BE_32(entry->params[j]); + + if (entry->timestamp < ftstamp) { + ftstamp = entry->timestamp; + first = i; + } + } + + printf("%10s %15s %8s %8s %s\n", "Seq#", "Tstamp", "Level", + "Facility", "Message"); + + i = first; + + do { + entry = &buf[i]; + + if (entry->timestamp == 0) + break; + + printf("%10d %15llu %8s %8s ", entry->seqno, + entry->timestamp, + (entry->level < ARRAY_SIZE(devlog_level_strings) ? + devlog_level_strings[entry->level] : "UNKNOWN"), + (entry->facility < ARRAY_SIZE(devlog_facility_strings) ? + devlog_facility_strings[entry->facility] : "UNKNOWN")); + + printf((const char *)entry->fmt, entry->params[0], + entry->params[1], entry->params[2], entry->params[3], + entry->params[4], entry->params[5], entry->params[6], + entry->params[7]); + + if (++i == nentries) + i = 0; + + } while (i != first); + + free(devlog); +} + +static void +load_fw(int argc, char *argv[], int start_arg, const char *iff_name) +{ + const char *fname = argv[start_arg]; + struct t4_ldfw *fw; + struct stat sb; + size_t len; + int fd; + + if (argc != 4) + err(1, "incorrect number of arguments."); + + fd = open(fname, O_RDONLY); + if (fd < 0) + err(1, "%s: opening %s failed", __func__, fname); + if (fstat(fd, &sb) < 0) { + close(fd); + err(1, "%s: fstat %s failed", __func__, fname); + } + len = (size_t)sb.st_size; + + fw = malloc(sizeof (struct t4_ldfw) + len); + if (!fw) { + close(fd); + err(1, "%s: %s allocate %ld bytes failed", + __func__, fname, sizeof (struct t4_ldfw) + len); + } + + if (read(fd, fw->data, len) < len) { + close(fd); + free(fw); + err(1, "%s: %s read failed", __func__, fname); + } + + close(fd); + + fw->len = len; + + if (doit(iff_name, T4_IOCTL_LOAD_FW, fw)) { + free(fw); + err(1, "%s: IOCTL failed", __func__); + } else { + printf("FW flash success, reload driver/reboot to take " + "effect\n"); + } + + free(fw); +} + +static void +run_cmd(int argc, char *argv[], const char *iff_name) +{ + if (strcmp(argv[2], "devlog") == 0) + get_devlog(argc, argv, 3, iff_name); + else if (strcmp(argv[2], "loadfw") == 0) + load_fw(argc, argv, 3, iff_name); + else + usage(stderr); +} + +int +main(int argc, char *argv[]) +{ + const char *iff_name; + + progname = argv[0]; + + if (argc == 2) { + if (strcmp(argv[1], "-h") == 0 || + strcmp(argv[1], "--help") == 0) { + usage(stdout); + } + + if (strcmp(argv[1], "-v") == 0 || + strcmp(argv[1], "--version") == 0) { + printf("cxgbetool version %s\n", DRV_VERSION); + exit(0); + } + } + + if (argc < 3) + usage(stderr); + + iff_name = argv[1]; + + run_cmd(argc, argv, iff_name); + + return (0); +} diff --git a/usr/src/pkg/manifests/driver-network-cxgbe.mf b/usr/src/pkg/manifests/driver-network-cxgbe.mf index 17193f1732..da644e6268 100644 --- a/usr/src/pkg/manifests/driver-network-cxgbe.mf +++ b/usr/src/pkg/manifests/driver-network-cxgbe.mf @@ -24,6 +24,8 @@ set name=variant.arch value=i386 dir path=kernel group=sys dir path=kernel/drv group=sys dir path=kernel/drv/$(ARCH64) group=sys +dir path=usr group=sys +dir path=usr/sbin group=sys driver name=cxgbe alias=cxgbe clone_perms="cxgbe 0666 root sys" \ perms="* 0666 root sys" driver name=t4nex clone_perms="t4nex 0666 root sys" \ @@ -111,5 +113,6 @@ driver name=t4nex clone_perms="t4nex 0666 root sys" \ alias=pciex1425,6481 file path=kernel/drv/$(ARCH64)/cxgbe group=sys file path=kernel/drv/$(ARCH64)/t4nex group=sys +file path=usr/sbin/cxgbetool mode=0555 license cr_Sun license=cr_Sun license lic_CDDL license=lic_CDDL diff --git a/usr/src/uts/common/io/cxgbe/t4nex/t4_ioctl.c b/usr/src/uts/common/io/cxgbe/t4nex/t4_ioctl.c index 1fd98e4c52..7fffa8076b 100644 --- a/usr/src/uts/common/io/cxgbe/t4nex/t4_ioctl.c +++ b/usr/src/uts/common/io/cxgbe/t4nex/t4_ioctl.c @@ -44,6 +44,7 @@ static int read_cim_la(struct adapter *sc, void *data, int flags); static int read_cim_qcfg(struct adapter *sc, void *data, int flags); static int read_cim_ibq(struct adapter *sc, void *data, int flags); static int read_edc(struct adapter *sc, void *data, int flags); +static int flash_fw(struct adapter *, void *, int); int t4_ioctl(struct adapter *sc, int cmd, void *data, int mode) @@ -89,6 +90,9 @@ t4_ioctl(struct adapter *sc, int cmd, void *data, int mode) case T4_IOCTL_GET_EDC: rc = read_edc(sc, data, mode); break; + case T4_IOCTL_LOAD_FW: + rc = flash_fw(sc, data, mode); + break; default: return (EINVAL); } @@ -1426,9 +1430,11 @@ get_devlog(struct adapter *sc, void *data, int flags) goto done1; /* Copyout device log buffer and then carrier buffer */ - if (ddi_copyout(buf, dl.data, dl.len, flags) < 0) + if (ddi_copyout(buf, (void *)((uintptr_t)data + sizeof(dl)), dl.len, + flags) < 0) rc = EFAULT; - else if (ddi_copyout(&dl, data, sizeof (dl), flags) < 0) + + if (ddi_copyout(&dl, data, sizeof(dl), flags) < 0) rc = EFAULT; done1: @@ -1635,3 +1641,37 @@ read_mbox(struct adapter *sc, void *data, int flags) _exit: return (rc); } + +static int +flash_fw(struct adapter *sc, void *data, int flags) +{ + unsigned int mbox = M_PCIE_FW_MASTER + 1; + struct t4_ldfw fw; + u8 *ptr = NULL; + int rc = 0; + + if (ddi_copyin(data, &fw, sizeof(struct t4_ldfw), flags) < 0) + return EFAULT; + + if (!fw.len) + return EINVAL; + + ptr = (u8 *)kmem_zalloc(fw.len, KM_NOSLEEP); + if (ptr == NULL) + return ENOMEM; + + if (ddi_copyin((void *)((uintptr_t)data + sizeof(fw)), ptr, fw.len, + flags) < 0) { + kmem_free(ptr, fw.len); + return EFAULT; + } + + if (sc->flags & FULL_INIT_DONE) + mbox = sc->mbox; + + rc = -t4_fw_upgrade(sc, mbox, ptr, fw.len, true); + + kmem_free(ptr, fw.len); + + return (rc); +} diff --git a/usr/src/uts/common/io/cxgbe/t4nex/t4nex.h b/usr/src/uts/common/io/cxgbe/t4nex/t4nex.h index 5e8cd96a36..da6edbd88b 100644 --- a/usr/src/uts/common/io/cxgbe/t4nex/t4nex.h +++ b/usr/src/uts/common/io/cxgbe/t4nex/t4nex.h @@ -42,6 +42,7 @@ extern "C" { #define T4_IOCTL_GET_CIM_QCFG (T4_IOCTL + 12) #define T4_IOCTL_GET_CIM_IBQ (T4_IOCTL + 13) #define T4_IOCTL_GET_EDC (T4_IOCTL + 14) +#define T4_IOCTL_LOAD_FW (T4_IOCTL + 15) enum { T4_CTXT_EGRESS, @@ -115,7 +116,12 @@ struct t4_cim_qcfg { #define T4_DEVLOG_SIZE 32768 struct t4_devlog { uint32_t len; - uint8_t *data; + uint32_t data[0]; +}; + +struct t4_ldfw { + uint32_t len; + uint32_t data[0]; }; #ifdef __cplusplus |
