mirror of
https://git.FreeBSD.org/src.git
synced 2024-11-23 07:31:31 +00:00
Implement userspace firmware update for ConnectX-4/5/6.
Submitted by: kib@ MFC after: 3 days Sponsored by: Mellanox Technologies
This commit is contained in:
parent
b255ca093a
commit
ea78f07b5e
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=347288
@ -233,6 +233,8 @@ mlx5_fwdump_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
|
||||
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;
|
||||
@ -275,6 +277,36 @@ mlx5_fwdump_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
|
||||
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;
|
||||
break;
|
||||
|
@ -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"
|
||||
|
@ -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_addr *addr)
|
||||
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);
|
||||
@ -215,6 +271,9 @@ main(int argc, char *argv[])
|
||||
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;
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user