Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 16 May 2019 17:50:53 +0000 (UTC)
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r347841 - in stable/11: sys/dev/mlx5 sys/dev/mlx5/mlx5_core usr.sbin/mlx5tool
Message-ID:  <201905161750.x4GHorvH020200@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: hselasky
Date: Thu May 16 17:50:52 2019
New Revision: 347841
URL: https://svnweb.freebsd.org/changeset/base/347841

Log:
  MFC r347288:
  Implement userspace firmware update for ConnectX-4/5/6.
  
  Submitted by:	kib@
  Sponsored by:	Mellanox Technologies

Modified:
  stable/11/sys/dev/mlx5/mlx5_core/mlx5_fwdump.c
  stable/11/sys/dev/mlx5/mlx5io.h
  stable/11/usr.sbin/mlx5tool/mlx5tool.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/dev/mlx5/mlx5_core/mlx5_fwdump.c
==============================================================================
--- stable/11/sys/dev/mlx5/mlx5_core/mlx5_fwdump.c	Thu May 16 17:50:15 2019	(r347840)
+++ stable/11/sys/dev/mlx5/mlx5_core/mlx5_fwdump.c	Thu May 16 17:50:52 2019	(r347841)
@@ -233,6 +233,8 @@ mlx5_fwdump_ioctl(struct cdev *dev, u_long cmd, caddr_
 	struct mlx5_fwdump_get *fwg;
 	struct mlx5_tool_addr *devaddr;
 	struct mlx5_dump_data *dd;
+	struct mlx5_fw_update *fu;
+	struct firmware fake_fw;
 	int error;
 
 	error = 0;
@@ -274,6 +276,36 @@ mlx5_fwdump_ioctl(struct cdev *dev, u_long cmd, caddr_
 		if (error != 0)
 			break;
 		mlx5_fwdump(mdev);
+		break;
+	case MLX5_FW_UPDATE:
+		if ((fflag & FWRITE) == 0) {
+			error = EBADF;
+			break;
+		}
+		fu = (struct mlx5_fw_update *)data;
+		if (fu->img_fw_data_len > 10 * 1024 * 1024) {
+			error = EINVAL;
+			break;
+		}
+		devaddr = &fu->devaddr;
+		error = mlx5_dbsf_to_core(devaddr, &mdev);
+		if (error != 0)
+			break;
+		bzero(&fake_fw, sizeof(fake_fw));
+		fake_fw.name = "umlx_fw_up";
+		fake_fw.datasize = fu->img_fw_data_len;
+		fake_fw.version = 1;
+		fake_fw.data = (void *)kmem_malloc(fu->img_fw_data_len,
+		    M_WAITOK);
+		if (fake_fw.data == NULL) {
+			error = ENOMEM;
+			break;
+		}
+		error = copyin(fu->img_fw_data, __DECONST(void *, fake_fw.data),
+		    fu->img_fw_data_len);
+		if (error == 0)
+			error = -mlx5_firmware_flash(mdev, &fake_fw);
+		kmem_free((vm_offset_t)fake_fw.data, fu->img_fw_data_len);
 		break;
 	default:
 		error = ENOTTY;

Modified: stable/11/sys/dev/mlx5/mlx5io.h
==============================================================================
--- stable/11/sys/dev/mlx5/mlx5io.h	Thu May 16 17:50:15 2019	(r347840)
+++ stable/11/sys/dev/mlx5/mlx5io.h	Thu May 16 17:50:52 2019	(r347841)
@@ -49,9 +49,16 @@ struct mlx5_fwdump_get {
 	size_t reg_filled; /* out */
 };
 
+struct mlx5_fw_update {
+	struct mlx5_tool_addr devaddr;
+	void *img_fw_data;
+	size_t img_fw_data_len;
+};
+
 #define	MLX5_FWDUMP_GET		_IOWR('m', 1, struct mlx5_fwdump_get)
 #define	MLX5_FWDUMP_RESET	_IOW('m', 2, struct mlx5_tool_addr)
 #define	MLX5_FWDUMP_FORCE	_IOW('m', 3, struct mlx5_tool_addr)
+#define	MLX5_FW_UPDATE		_IOW('m', 4, struct mlx5_fw_update)
 
 #ifndef _KERNEL
 #define	MLX5_DEV_PATH	_PATH_DEV"mlx5ctl"

Modified: stable/11/usr.sbin/mlx5tool/mlx5tool.c
==============================================================================
--- stable/11/usr.sbin/mlx5tool/mlx5tool.c	Thu May 16 17:50:15 2019	(r347840)
+++ stable/11/usr.sbin/mlx5tool/mlx5tool.c	Thu May 16 17:50:52 2019	(r347841)
@@ -28,6 +28,8 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
 #include <dev/mlx5/mlx5io.h>
 #include <ctype.h>
 #include <err.h>
@@ -144,15 +146,60 @@ mlx5tool_dump_force(int ctldev, const struct mlx5_tool
 	return (0);
 }
 
+static int
+mlx5tool_fw_update(int ctldev, const struct mlx5_tool_addr *addr,
+    const char *img_fw_path)
+{
+	struct stat st;
+	struct mlx5_fw_update fwup;
+	int error, fd, res;
+
+	res = 0;
+	fd = open(img_fw_path, O_RDONLY);
+	if (fd == -1) {
+		warn("Unable to open %s", img_fw_path);
+		res = 1;
+		goto close_fd;
+	}
+	error = fstat(fd, &st);
+	if (error != 0) {
+		warn("Unable to stat %s", img_fw_path);
+		res = 1;
+		goto close_fd;
+	}
+	memset(&fwup, 0, sizeof(fwup));
+	memcpy(&fwup.devaddr, addr, sizeof(fwup.devaddr));
+	fwup.img_fw_data = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE,
+	    fd, 0);
+	if (fwup.img_fw_data == MAP_FAILED) {
+		warn("Unable to mmap %s", img_fw_path);
+		res = 1;
+		goto close_fd;
+	}
+	fwup.img_fw_data_len = st.st_size;
+
+	error = ioctl(ctldev, MLX5_FW_UPDATE, &fwup);
+	if (error == -1) {
+		warn("MLX5_FW_UPDATE");
+	}
+
+	munmap(fwup.img_fw_data, st.st_size);
+close_fd:
+	close(fd);
+	return (res);
+}
+
 static void
 usage(void)
 {
 
 	fprintf(stderr,
-	    "Usage: mlx5tool -d pci<d:b:s:f> [-w -o dump.file | -r | -e]\n");
+	    "Usage: mlx5tool -d pci<d:b:s:f> [-w -o dump.file | -r |"
+	    "    -e | -f fw.mfa2]\n");
 	fprintf(stderr, "\t-w - write firmware dump to the specified file\n");
 	fprintf(stderr, "\t-r - reset dump\n");
 	fprintf(stderr, "\t-e - force dump\n");
+	fprintf(stderr, "\t-f fw.img - flash firmware from fw.img\n");
 	exit(1);
 }
 
@@ -160,6 +207,7 @@ enum mlx5_action {
 	ACTION_DUMP_GET,
 	ACTION_DUMP_RESET,
 	ACTION_DUMP_FORCE,
+	ACTION_FW_UPDATE,
 	ACTION_NONE,
 };
 
@@ -169,13 +217,15 @@ main(int argc, char *argv[])
 	struct mlx5_tool_addr addr;
 	char *dumpname;
 	char *addrstr;
+	char *img_fw_path;
 	int c, ctldev, res;
 	enum mlx5_action act;
 
 	act = ACTION_NONE;
 	addrstr = NULL;
 	dumpname = NULL;
-	while ((c = getopt(argc, argv, "d:eho:rw")) != -1) {
+	img_fw_path = NULL;
+	while ((c = getopt(argc, argv, "d:ef:ho:rw")) != -1) {
 		switch (c) {
 		case 'd':
 			addrstr = optarg;
@@ -192,12 +242,18 @@ main(int argc, char *argv[])
 		case 'r':
 			act = ACTION_DUMP_RESET;
 			break;
+		case 'f':
+			act = ACTION_FW_UPDATE;
+			img_fw_path = optarg;
+			break;
 		case 'h':
 		default:
 			usage();
 		}
 	}
-	if (act == ACTION_NONE || (dumpname != NULL && act != ACTION_DUMP_GET))
+	if (act == ACTION_NONE || (dumpname != NULL &&
+	    act != ACTION_DUMP_GET) || (img_fw_path != NULL &&
+	    act != ACTION_FW_UPDATE))
 		usage();
 	if (parse_pci_addr(addrstr, &addr) != 0)
 		exit(1);
@@ -214,6 +270,9 @@ main(int argc, char *argv[])
 		break;
 	case ACTION_DUMP_FORCE:
 		res = mlx5tool_dump_force(ctldev, &addr);
+		break;
+	case ACTION_FW_UPDATE:
+		res = mlx5tool_fw_update(ctldev, &addr, img_fw_path);
 		break;
 	default:
 		res = 0;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201905161750.x4GHorvH020200>