Implement firmware reset from userspace in mlx5tool(8).

Submitted by:	kib@
MFC after:	3 days
Sponsored by:	Mellanox Technologies
This commit is contained in:
Hans Petter Selasky 2019-05-08 11:05:09 +00:00
parent 939c79a213
commit 998c9a2bbc
5 changed files with 67 additions and 2 deletions

View File

@ -142,6 +142,11 @@ Image address in memory is passed in
the length of the image is specified in
.Dv img_fw_data_len
field.
.It Dv MLX5_FW_RESET
Requests PCIe link-level reset on the device.
The address of the device is specified by the
.Vt struct mlx5_tool_addr
structure, which should be passed as an argument.
.El
.Sh FILES
The

View File

@ -225,6 +225,24 @@ mlx5_fwdump_copyout(struct mlx5_dump_data *dd, struct mlx5_fwdump_get *fwg)
return (0);
}
static int
mlx5_fw_reset(struct mlx5_core_dev *mdev)
{
device_t dev, bus;
int error;
error = -mlx5_set_mfrl_reg(mdev, MLX5_FRL_LEVEL3);
if (error == 0) {
dev = mdev->pdev->dev.bsddev;
mtx_lock(&Giant);
bus = device_get_parent(dev);
error = BUS_RESET_CHILD(device_get_parent(bus), bus,
DEVF_RESET_DETACH);
mtx_unlock(&Giant);
}
return (error);
}
static int
mlx5_fwdump_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
struct thread *td)
@ -307,6 +325,17 @@ mlx5_fwdump_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
error = -mlx5_firmware_flash(mdev, &fake_fw);
kmem_free((vm_offset_t)fake_fw.data, fu->img_fw_data_len);
break;
case MLX5_FW_RESET:
if ((fflag & FWRITE) == 0) {
error = EBADF;
break;
}
devaddr = (struct mlx5_tool_addr *)data;
error = mlx5_dbsf_to_core(devaddr, &mdev);
if (error != 0)
break;
error = mlx5_fw_reset(mdev);
break;
default:
error = ENOTTY;
break;

View File

@ -59,6 +59,7 @@ struct mlx5_fw_update {
#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)
#define MLX5_FW_RESET _IOW('m', 5, struct mlx5_tool_addr)
#ifndef _KERNEL
#define MLX5_DEV_PATH _PATH_DEV"mlx5ctl"

View File

@ -45,6 +45,9 @@
.Nm
.Fl d Ar domain:bus:slot:func
.Fl f Ar file.mfa2
.Nm
.Fl d Ar domain:bus:slot:func
.Fl z
.Sh DESCRIPTION
The
.Nm
@ -91,6 +94,14 @@ Flashes the firmware image
to the specified adapter.
Image must be in MFA2 pack format and contain a component suitable
for the adapter hardware.
.Pp
Typically, PCIe link-level reset is required to activate the
newly flashed image, which can be performed by the system reboot
or using the
.Fl z
option.
.It Fl z
Performs PCIe link-level reset on the specified device.
.El
.Sh FILES
The

View File

@ -189,17 +189,29 @@ mlx5tool_fw_update(int ctldev, const struct mlx5_tool_addr *addr,
return (res);
}
static int
mlx5tool_fw_reset(int ctldev, const struct mlx5_tool_addr *addr)
{
if (ioctl(ctldev, MLX5_FW_RESET, addr) == -1) {
warn("MLX5_FW_RESET");
return (1);
}
return (0);
}
static void
usage(void)
{
fprintf(stderr,
"Usage: mlx5tool -d pci<d:b:s:f> [-w -o dump.file | -r |"
" -e | -f fw.mfa2]\n");
" -e | -f fw.mfa2 | -z]\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");
fprintf(stderr, "\t-z - initiate firmware reset\n");
exit(1);
}
@ -208,6 +220,7 @@ enum mlx5_action {
ACTION_DUMP_RESET,
ACTION_DUMP_FORCE,
ACTION_FW_UPDATE,
ACTION_FW_RESET,
ACTION_NONE,
};
@ -225,7 +238,7 @@ main(int argc, char *argv[])
addrstr = NULL;
dumpname = NULL;
img_fw_path = NULL;
while ((c = getopt(argc, argv, "d:ef:ho:rw")) != -1) {
while ((c = getopt(argc, argv, "d:ef:ho:rwz")) != -1) {
switch (c) {
case 'd':
addrstr = optarg;
@ -246,6 +259,9 @@ main(int argc, char *argv[])
act = ACTION_FW_UPDATE;
img_fw_path = optarg;
break;
case 'z':
act = ACTION_FW_RESET;
break;
case 'h':
default:
usage();
@ -274,6 +290,9 @@ main(int argc, char *argv[])
case ACTION_FW_UPDATE:
res = mlx5tool_fw_update(ctldev, &addr, img_fw_path);
break;
case ACTION_FW_RESET:
res = mlx5tool_fw_reset(ctldev, &addr);
break;
default:
res = 0;
break;