Author: hselasky
Date: Wed May  8 10:50:35 2019
New Revision: 347288
URL: https://svnweb.freebsd.org/changeset/base/347288

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

Modified:
  head/sys/dev/mlx5/mlx5_core/mlx5_fwdump.c
  head/sys/dev/mlx5/mlx5io.h
  head/usr.sbin/mlx5tool/mlx5tool.c

Modified: head/sys/dev/mlx5/mlx5_core/mlx5_fwdump.c
==============================================================================
--- head/sys/dev/mlx5/mlx5_core/mlx5_fwdump.c   Wed May  8 10:50:08 2019        
(r347287)
+++ head/sys/dev/mlx5/mlx5_core/mlx5_fwdump.c   Wed May  8 10:50:35 2019        
(r347288)
@@ -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: head/sys/dev/mlx5/mlx5io.h
==============================================================================
--- head/sys/dev/mlx5/mlx5io.h  Wed May  8 10:50:08 2019        (r347287)
+++ head/sys/dev/mlx5/mlx5io.h  Wed May  8 10:50:35 2019        (r347288)
@@ -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: head/usr.sbin/mlx5tool/mlx5tool.c
==============================================================================
--- head/usr.sbin/mlx5tool/mlx5tool.c   Wed May  8 10:50:08 2019        
(r347287)
+++ head/usr.sbin/mlx5tool/mlx5tool.c   Wed May  8 10:50:35 2019        
(r347288)
@@ -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;
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to