mfi_debug.c revision 331722
1/*-
2 * Copyright (c) 2006 IronPort Systems
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: stable/11/sys/dev/mfi/mfi_debug.c 331722 2018-03-29 02:50:57Z eadler $");
29
30#include "opt_mfi.h"
31
32#ifdef MFI_DEBUG
33
34#include <sys/param.h>
35#include <sys/systm.h>
36#include <sys/kernel.h>
37#include <sys/conf.h>
38#include <sys/bus.h>
39#include <sys/bio.h>
40#include <sys/lock.h>
41#include <sys/mutex.h>
42#include <sys/malloc.h>
43#include <sys/selinfo.h>
44#include <sys/sysctl.h>
45#include <sys/taskqueue.h>
46#include <sys/uio.h>
47#include <machine/resource.h>
48#include <machine/bus.h>
49
50#include <vm/vm.h>
51#include <vm/pmap.h>
52
53#include <dev/mfi/mfireg.h>
54#include <dev/mfi/mfi_ioctl.h>
55#include <dev/mfi/mfivar.h>
56
57static void
58mfi_print_frame_flags(device_t dev, uint32_t flags)
59{
60	device_printf(dev, "flags=%b\n", flags, MFI_FRAME_FMT);
61}
62
63static void
64mfi_print_sgl(struct mfi_frame_header *hdr, union mfi_sgl *sgl, int count)
65{
66	int i, columns = 0;
67
68	printf("SG List:\n");
69	for (i = 0; i < count; i++) {
70		if (hdr->flags & MFI_FRAME_IEEE_SGL) {
71			printf("0x%lx:%06d ", (u_long)sgl->sg_skinny[i].addr,
72			    sgl->sg_skinny[i].len);
73			columns += 26;
74			if (columns > 77) {
75				printf("\n");
76				columns = 0;
77			}
78		} else if (hdr->flags & MFI_FRAME_SGL64) {
79			printf("0x%lx:%06d ", (u_long)sgl->sg64[i].addr,
80			    sgl->sg64[i].len);
81			columns += 26;
82			if (columns > 77) {
83				printf("\n");
84				columns = 0;
85			}
86		} else {
87			printf("0x%x:%06d ", sgl->sg32[i].addr,
88			    sgl->sg32[i].len);
89			columns += 18;
90			if (columns > 71) {
91				printf("\n");
92				columns = 0;
93			}
94		}
95	}
96	if (columns != 0)
97		printf("\n");
98
99}
100
101static void
102mfi_print_ldio(struct mfi_softc *sc, device_t dev, struct mfi_command *cm)
103{
104	struct mfi_io_frame *io;
105	struct mfi_frame_header *hdr;
106
107	io = &cm->cm_frame->io;
108	hdr = &io->header;
109
110	device_printf(dev, "cmd=%s target_id=%d sg_count=%d data_len=%d "
111	    "lba=%d\n", (hdr->cmd == MFI_CMD_LD_READ) ? "LD_READ":"LD_WRITE",
112	     hdr->target_id, hdr->sg_count, hdr->data_len, io->lba_lo);
113	mfi_print_frame_flags(dev, hdr->flags);
114	mfi_print_sgl(hdr, &io->sgl, hdr->sg_count);
115
116}
117
118static void
119mfi_print_dcmd(struct mfi_softc *sc, device_t dev, struct mfi_command *cm)
120{
121	struct mfi_dcmd_frame *dcmd;
122	struct mfi_frame_header *hdr;
123	const char *opcode;
124
125	dcmd = &cm->cm_frame->dcmd;
126	hdr = &dcmd->header;
127
128	switch (dcmd->opcode) {
129	case MFI_DCMD_CTRL_GETINFO:
130		opcode = "CTRL_GETINFO";
131		break;
132	case MFI_DCMD_CTRL_FLUSHCACHE:
133		opcode = "CTRL_FLUSHCACHE";
134		break;
135	case MFI_DCMD_CTRL_SHUTDOWN:
136		opcode = "CTRL_SHUTDOWN";
137		break;
138	case MFI_DCMD_CTRL_EVENT_GETINFO:
139		opcode = "EVENT_GETINFO";
140		break;
141	case MFI_DCMD_CTRL_EVENT_GET:
142		opcode = "EVENT_GET";
143		break;
144	case MFI_DCMD_CTRL_EVENT_WAIT:
145		opcode = "EVENT_WAIT";
146		break;
147	case MFI_DCMD_LD_GET_LIST:
148		opcode = "LD_GET_LIST";
149		break;
150	case MFI_DCMD_LD_GET_INFO:
151		opcode = "LD_GET_INFO";
152		break;
153	case MFI_DCMD_LD_GET_PROP:
154		opcode = "LD_GET_PROP";
155		break;
156	case MFI_DCMD_LD_SET_PROP:
157		opcode = "LD_SET_PROP";
158		break;
159	case MFI_DCMD_CLUSTER:
160		opcode = "CLUSTER";
161		break;
162	case MFI_DCMD_CLUSTER_RESET_ALL:
163		opcode = "CLUSTER_RESET_ALL";
164		break;
165	case MFI_DCMD_CLUSTER_RESET_LD:
166		opcode = "CLUSTER_RESET_LD";
167		break;
168	case MFI_DCMD_LD_MAP_GET_INFO:
169		opcode = "LD_MAP_GET_INFO";
170		break;
171	case MFI_DCMD_BBU_START_LEARN:
172		opcode = "BBU_START_LEARN";
173		break;
174	case MFI_DCMD_BBU_GET_PROP:
175		opcode = "BBU_GET_PROP";
176		break;
177	case MFI_DCMD_BBU_SET_PROP:
178		opcode = "BBU_SET_PROP";
179		break;
180	default:
181		opcode = "UNKNOWN";
182		break;
183	}
184
185	device_printf(dev, "cmd=MFI_CMD_DCMD opcode=%s data_len=%d\n",
186	    opcode, hdr->data_len);
187	mfi_print_frame_flags(dev, hdr->flags);
188	mfi_print_sgl(hdr, &dcmd->sgl, hdr->sg_count);
189
190}
191
192static void
193mfi_print_generic_frame(struct mfi_softc *sc, struct mfi_command *cm)
194{
195	hexdump(cm->cm_frame, cm->cm_total_frame_size, NULL, HD_OMIT_CHARS);
196}
197
198void
199mfi_print_cmd(struct mfi_command *cm)
200{
201	device_t dev;
202	struct mfi_softc *sc;
203
204	sc = cm->cm_sc;
205	dev = sc->mfi_dev;
206
207	device_printf(dev, "cm=%p index=%d total_frame_size=%d "
208	    "extra_frames=%d\n", cm, cm->cm_index, cm->cm_total_frame_size,
209	    cm->cm_extra_frames);
210	device_printf(dev, "flags=%b\n", cm->cm_flags, MFI_CMD_FLAGS_FMT);
211
212	switch (cm->cm_frame->header.cmd) {
213	case MFI_CMD_DCMD:
214		mfi_print_dcmd(sc, dev, cm);
215		break;
216	case MFI_CMD_LD_READ:
217	case MFI_CMD_LD_WRITE:
218		mfi_print_ldio(sc, dev, cm);
219		break;
220	default:
221		mfi_print_generic_frame(sc, cm);
222		break;
223	}
224
225	return;
226}
227
228void
229mfi_dump_cmds(struct mfi_softc *sc)
230{
231	int i;
232
233	for (i = 0; i < sc->mfi_max_fw_cmds; i++)
234		mfi_print_generic_frame(sc, &sc->mfi_commands[i]);
235}
236
237void
238mfi_validate_sg(struct mfi_softc *sc, struct mfi_command *cm,
239	const char *function, int line)
240{
241	struct mfi_frame_header *hdr;
242	int i;
243	uint32_t count = 0, data_len;
244
245	hdr = &cm->cm_frame->header;
246	count = 0;
247	for (i = 0; i < hdr->sg_count; i++) {
248		if (hdr->flags & MFI_FRAME_IEEE_SGL)
249			count += cm->cm_sg->sg_skinny[i].len;
250		else if (hdr->flags & MFI_FRAME_SGL64)
251			count += cm->cm_sg->sg64[i].len;
252		else
253			count += cm->cm_sg->sg32[i].len;
254	}
255	/*
256	count++;
257	*/
258	data_len = hdr->data_len;
259	switch (hdr->cmd) {
260	case MFI_CMD_LD_READ:
261	case MFI_CMD_LD_WRITE:
262		data_len = data_len * 512;
263	case MFI_CMD_DCMD:
264		if (count != data_len) {
265			device_printf(sc->mfi_dev,
266			    "%s %d COMMAND %p S/G count bad %d %d %d 0x%jx\n",
267			    function, line, cm, count, data_len, cm->cm_len,
268			    (intmax_t)pmap_kextract((vm_offset_t)cm->cm_data));
269			MFI_PRINT_CMD(cm);
270		}
271	}
272}
273
274#endif
275