xref: /freebsd/usr.sbin/mlx5tool/mlx5tool.c (revision f3365f07a309bb47249475816a3e6b5faf7f4bec)
1e808190aSHans Petter Selasky /*-
2e808190aSHans Petter Selasky  * Copyright (c) 2018, Mellanox Technologies, Ltd.  All rights reserved.
3e808190aSHans Petter Selasky  *
4e808190aSHans Petter Selasky  * Redistribution and use in source and binary forms, with or without
5e808190aSHans Petter Selasky  * modification, are permitted provided that the following conditions
6e808190aSHans Petter Selasky  * are met:
7e808190aSHans Petter Selasky  * 1. Redistributions of source code must retain the above copyright
8e808190aSHans Petter Selasky  *    notice, this list of conditions and the following disclaimer.
9e808190aSHans Petter Selasky  * 2. Redistributions in binary form must reproduce the above copyright
10e808190aSHans Petter Selasky  *    notice, this list of conditions and the following disclaimer in the
11e808190aSHans Petter Selasky  *    documentation and/or other materials provided with the distribution.
12e808190aSHans Petter Selasky  *
13e808190aSHans Petter Selasky  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND
14e808190aSHans Petter Selasky  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15e808190aSHans Petter Selasky  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16e808190aSHans Petter Selasky  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
17e808190aSHans Petter Selasky  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18e808190aSHans Petter Selasky  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19e808190aSHans Petter Selasky  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20e808190aSHans Petter Selasky  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21e808190aSHans Petter Selasky  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22e808190aSHans Petter Selasky  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23e808190aSHans Petter Selasky  * SUCH DAMAGE.
24e808190aSHans Petter Selasky  */
25e808190aSHans Petter Selasky 
26e808190aSHans Petter Selasky #include <sys/cdefs.h>
27e808190aSHans Petter Selasky __FBSDID("$FreeBSD$");
28e808190aSHans Petter Selasky 
29e808190aSHans Petter Selasky #include <sys/param.h>
30e808190aSHans Petter Selasky #include <sys/ioctl.h>
31e808190aSHans Petter Selasky #include <dev/mlx5/mlx5io.h>
32e808190aSHans Petter Selasky #include <ctype.h>
33e808190aSHans Petter Selasky #include <err.h>
34e808190aSHans Petter Selasky #include <errno.h>
35e808190aSHans Petter Selasky #include <fcntl.h>
36e808190aSHans Petter Selasky #include <paths.h>
37e808190aSHans Petter Selasky #include <stdio.h>
38e808190aSHans Petter Selasky #include <stdlib.h>
39e808190aSHans Petter Selasky #include <string.h>
40e808190aSHans Petter Selasky #include <unistd.h>
41e808190aSHans Petter Selasky 
42e808190aSHans Petter Selasky /* stolen from pciconf.c: parsesel() */
43e808190aSHans Petter Selasky static int
44e808190aSHans Petter Selasky parse_pci_addr(const char *addrstr, struct mlx5_fwdump_addr *addr)
45e808190aSHans Petter Selasky {
46e808190aSHans Petter Selasky 	char *eppos;
47e808190aSHans Petter Selasky 	unsigned long selarr[4];
48e808190aSHans Petter Selasky 	int i;
49e808190aSHans Petter Selasky 
50*f3365f07SHans Petter Selasky 	if (addrstr == NULL) {
51*f3365f07SHans Petter Selasky 		warnx("no pci address specified");
52*f3365f07SHans Petter Selasky 		return (1);
53*f3365f07SHans Petter Selasky 	}
54e808190aSHans Petter Selasky 	if (strncmp(addrstr, "pci", 3) == 0) {
55e808190aSHans Petter Selasky 		addrstr += 3;
56e808190aSHans Petter Selasky 		i = 0;
57e808190aSHans Petter Selasky 		while (isdigit(*addrstr) && i < 4) {
58e808190aSHans Petter Selasky 			selarr[i++] = strtoul(addrstr, &eppos, 10);
59e808190aSHans Petter Selasky 			addrstr = eppos;
60e808190aSHans Petter Selasky 			if (*addrstr == ':')
61e808190aSHans Petter Selasky 				addrstr++;
62e808190aSHans Petter Selasky 		}
63e808190aSHans Petter Selasky 		if (i > 0 && *addrstr == '\0') {
64e808190aSHans Petter Selasky 			addr->func = (i > 2) ? selarr[--i] : 0;
65e808190aSHans Petter Selasky 			addr->slot = (i > 0) ? selarr[--i] : 0;
66e808190aSHans Petter Selasky 			addr->bus = (i > 0) ? selarr[--i] : 0;
67e808190aSHans Petter Selasky 			addr->domain = (i > 0) ? selarr[--i] : 0;
68e808190aSHans Petter Selasky 			return (0);
69e808190aSHans Petter Selasky 		}
70e808190aSHans Petter Selasky 	}
71e808190aSHans Petter Selasky 	warnx("invalid pci address %s", addrstr);
72e808190aSHans Petter Selasky 	return (1);
73e808190aSHans Petter Selasky }
74e808190aSHans Petter Selasky 
75e808190aSHans Petter Selasky static int
76e808190aSHans Petter Selasky mlx5tool_save_dump(int ctldev, const struct mlx5_fwdump_addr *addr,
77e808190aSHans Petter Selasky     const char *dumpname)
78e808190aSHans Petter Selasky {
79e808190aSHans Petter Selasky 	struct mlx5_fwdump_get fdg;
80e808190aSHans Petter Selasky 	struct mlx5_fwdump_reg *rege;
81e808190aSHans Petter Selasky 	FILE *dump;
82e808190aSHans Petter Selasky 	size_t cnt;
83e808190aSHans Petter Selasky 	int error, res;
84e808190aSHans Petter Selasky 
85e808190aSHans Petter Selasky 	if (dumpname == NULL)
86e808190aSHans Petter Selasky 		dump = stdout;
87e808190aSHans Petter Selasky 	else
88e808190aSHans Petter Selasky 		dump = fopen(dumpname, "w");
89e808190aSHans Petter Selasky 	if (dump == NULL) {
90e808190aSHans Petter Selasky 		warn("open %s", dumpname);
91e808190aSHans Petter Selasky 		return (1);
92e808190aSHans Petter Selasky 	}
93e808190aSHans Petter Selasky 	res = 1;
94e808190aSHans Petter Selasky 	memset(&fdg, 0, sizeof(fdg));
95e808190aSHans Petter Selasky 	fdg.devaddr = *addr;
96e808190aSHans Petter Selasky 	error = ioctl(ctldev, MLX5_FWDUMP_GET, &fdg);
97e808190aSHans Petter Selasky 	if (error != 0) {
98e808190aSHans Petter Selasky 		warn("MLX5_FWDUMP_GET dumpsize");
99e808190aSHans Petter Selasky 		goto out;
100e808190aSHans Petter Selasky 	}
101e808190aSHans Petter Selasky 	rege = calloc(fdg.reg_filled, sizeof(*rege));
102e808190aSHans Petter Selasky 	if (rege == NULL) {
103e808190aSHans Petter Selasky 		warn("alloc rege");
104e808190aSHans Petter Selasky 		goto out;
105e808190aSHans Petter Selasky 	}
106e808190aSHans Petter Selasky 	fdg.buf = rege;
107e808190aSHans Petter Selasky 	fdg.reg_cnt = fdg.reg_filled;
108e808190aSHans Petter Selasky 	error = ioctl(ctldev, MLX5_FWDUMP_GET, &fdg);
109e808190aSHans Petter Selasky 	if (error != 0) {
110e808190aSHans Petter Selasky 		if (errno == ENOENT)
111e808190aSHans Petter Selasky 			warnx("no dump recorded");
112e808190aSHans Petter Selasky 		else
113e808190aSHans Petter Selasky 			warn("MLX5_FWDUMP_GET dump fetch");
114e808190aSHans Petter Selasky 		goto out;
115e808190aSHans Petter Selasky 	}
116e808190aSHans Petter Selasky 	for (cnt = 0; cnt < fdg.reg_cnt; cnt++, rege++)
117e808190aSHans Petter Selasky 		fprintf(dump, "0x%08x\t0x%08x\n", rege->addr, rege->val);
118e808190aSHans Petter Selasky 	res = 0;
119e808190aSHans Petter Selasky out:
120e808190aSHans Petter Selasky 	if (dump != stdout)
121e808190aSHans Petter Selasky 		fclose(dump);
122e808190aSHans Petter Selasky 	return (res);
123e808190aSHans Petter Selasky }
124e808190aSHans Petter Selasky 
125e808190aSHans Petter Selasky static int
126e808190aSHans Petter Selasky mlx5tool_dump_reset(int ctldev, const struct mlx5_fwdump_addr *addr)
127e808190aSHans Petter Selasky {
128e808190aSHans Petter Selasky 
129e808190aSHans Petter Selasky 	if (ioctl(ctldev, MLX5_FWDUMP_RESET, addr) == -1) {
130e808190aSHans Petter Selasky 		warn("MLX5_FWDUMP_RESET");
131e808190aSHans Petter Selasky 		return (1);
132e808190aSHans Petter Selasky 	}
133e808190aSHans Petter Selasky 	return (0);
134e808190aSHans Petter Selasky }
135e808190aSHans Petter Selasky 
136e808190aSHans Petter Selasky static int
137e808190aSHans Petter Selasky mlx5tool_dump_force(int ctldev, const struct mlx5_fwdump_addr *addr)
138e808190aSHans Petter Selasky {
139e808190aSHans Petter Selasky 
140e808190aSHans Petter Selasky 	if (ioctl(ctldev, MLX5_FWDUMP_FORCE, addr) == -1) {
141e808190aSHans Petter Selasky 		warn("MLX5_FWDUMP_FORCE");
142e808190aSHans Petter Selasky 		return (1);
143e808190aSHans Petter Selasky 	}
144e808190aSHans Petter Selasky 	return (0);
145e808190aSHans Petter Selasky }
146e808190aSHans Petter Selasky 
147e808190aSHans Petter Selasky static void
148e808190aSHans Petter Selasky usage(void)
149e808190aSHans Petter Selasky {
150e808190aSHans Petter Selasky 
151e808190aSHans Petter Selasky 	fprintf(stderr,
152e808190aSHans Petter Selasky 	    "Usage: mlx5tool -d pci<d:b:s:f> [-w -o dump.file | -r | -e]\n");
153e808190aSHans Petter Selasky 	fprintf(stderr, "\t-w - write firmware dump to the specified file\n");
154e808190aSHans Petter Selasky 	fprintf(stderr, "\t-r - reset dump\n");
155e808190aSHans Petter Selasky 	fprintf(stderr, "\t-e - force dump\n");
156e808190aSHans Petter Selasky 	exit(1);
157e808190aSHans Petter Selasky }
158e808190aSHans Petter Selasky 
159e808190aSHans Petter Selasky enum mlx5_action {
160e808190aSHans Petter Selasky 	ACTION_DUMP_GET,
161e808190aSHans Petter Selasky 	ACTION_DUMP_RESET,
162e808190aSHans Petter Selasky 	ACTION_DUMP_FORCE,
163e808190aSHans Petter Selasky 	ACTION_NONE,
164e808190aSHans Petter Selasky };
165e808190aSHans Petter Selasky 
166e808190aSHans Petter Selasky int
167e808190aSHans Petter Selasky main(int argc, char *argv[])
168e808190aSHans Petter Selasky {
169e808190aSHans Petter Selasky 	struct mlx5_fwdump_addr addr;
170e808190aSHans Petter Selasky 	char *dumpname;
171e808190aSHans Petter Selasky 	char *addrstr;
172e808190aSHans Petter Selasky 	int c, ctldev, res;
173e808190aSHans Petter Selasky 	enum mlx5_action act;
174e808190aSHans Petter Selasky 
175e808190aSHans Petter Selasky 	act = ACTION_NONE;
176e808190aSHans Petter Selasky 	addrstr = NULL;
177e808190aSHans Petter Selasky 	dumpname = NULL;
178e808190aSHans Petter Selasky 	while ((c = getopt(argc, argv, "d:eho:rw")) != -1) {
179e808190aSHans Petter Selasky 		switch (c) {
180e808190aSHans Petter Selasky 		case 'd':
181e808190aSHans Petter Selasky 			addrstr = optarg;
182e808190aSHans Petter Selasky 			break;
183e808190aSHans Petter Selasky 		case 'w':
184e808190aSHans Petter Selasky 			act = ACTION_DUMP_GET;
185e808190aSHans Petter Selasky 			break;
186e808190aSHans Petter Selasky 		case 'e':
187e808190aSHans Petter Selasky 			act= ACTION_DUMP_FORCE;
188e808190aSHans Petter Selasky 			break;
189e808190aSHans Petter Selasky 		case 'o':
190e808190aSHans Petter Selasky 			dumpname = optarg;
191e808190aSHans Petter Selasky 			break;
192e808190aSHans Petter Selasky 		case 'r':
193e808190aSHans Petter Selasky 			act = ACTION_DUMP_RESET;
194e808190aSHans Petter Selasky 			break;
195e808190aSHans Petter Selasky 		case 'h':
196e808190aSHans Petter Selasky 		default:
197e808190aSHans Petter Selasky 			usage();
198e808190aSHans Petter Selasky 		}
199e808190aSHans Petter Selasky 	}
200e808190aSHans Petter Selasky 	if (act == ACTION_NONE || (dumpname != NULL && act != ACTION_DUMP_GET))
201e808190aSHans Petter Selasky 		usage();
202e808190aSHans Petter Selasky 	if (parse_pci_addr(addrstr, &addr) != 0)
203e808190aSHans Petter Selasky 		exit(1);
204e808190aSHans Petter Selasky 
205e808190aSHans Petter Selasky 	ctldev = open(MLX5_DEV_PATH, O_RDWR);
206e808190aSHans Petter Selasky 	if (ctldev == -1)
207e808190aSHans Petter Selasky 		err(1, "open "MLX5_DEV_PATH);
208e808190aSHans Petter Selasky 	switch (act) {
209e808190aSHans Petter Selasky 	case ACTION_DUMP_GET:
210e808190aSHans Petter Selasky 		res = mlx5tool_save_dump(ctldev, &addr, dumpname);
211e808190aSHans Petter Selasky 		break;
212e808190aSHans Petter Selasky 	case ACTION_DUMP_RESET:
213e808190aSHans Petter Selasky 		res = mlx5tool_dump_reset(ctldev, &addr);
214e808190aSHans Petter Selasky 		break;
215e808190aSHans Petter Selasky 	case ACTION_DUMP_FORCE:
216e808190aSHans Petter Selasky 		res = mlx5tool_dump_force(ctldev, &addr);
217e808190aSHans Petter Selasky 		break;
218e808190aSHans Petter Selasky 	default:
219e808190aSHans Petter Selasky 		res = 0;
220e808190aSHans Petter Selasky 		break;
221e808190aSHans Petter Selasky 	}
222e808190aSHans Petter Selasky 	close(ctldev);
223e808190aSHans Petter Selasky 	exit(res);
224e808190aSHans Petter Selasky }
225