xref: /freebsd/contrib/ofed/infiniband-diags/src/smpdump.c (revision 87181516ef48be852d5e5fee53c6e0dbfc62f21e)
1*d6b92ffaSHans Petter Selasky /*
2*d6b92ffaSHans Petter Selasky  * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
3*d6b92ffaSHans Petter Selasky  *
4*d6b92ffaSHans Petter Selasky  * This software is available to you under a choice of one of two
5*d6b92ffaSHans Petter Selasky  * licenses.  You may choose to be licensed under the terms of the GNU
6*d6b92ffaSHans Petter Selasky  * General Public License (GPL) Version 2, available from the file
7*d6b92ffaSHans Petter Selasky  * COPYING in the main directory of this source tree, or the
8*d6b92ffaSHans Petter Selasky  * OpenIB.org BSD license below:
9*d6b92ffaSHans Petter Selasky  *
10*d6b92ffaSHans Petter Selasky  *     Redistribution and use in source and binary forms, with or
11*d6b92ffaSHans Petter Selasky  *     without modification, are permitted provided that the following
12*d6b92ffaSHans Petter Selasky  *     conditions are met:
13*d6b92ffaSHans Petter Selasky  *
14*d6b92ffaSHans Petter Selasky  *      - Redistributions of source code must retain the above
15*d6b92ffaSHans Petter Selasky  *        copyright notice, this list of conditions and the following
16*d6b92ffaSHans Petter Selasky  *        disclaimer.
17*d6b92ffaSHans Petter Selasky  *
18*d6b92ffaSHans Petter Selasky  *      - Redistributions in binary form must reproduce the above
19*d6b92ffaSHans Petter Selasky  *        copyright notice, this list of conditions and the following
20*d6b92ffaSHans Petter Selasky  *        disclaimer in the documentation and/or other materials
21*d6b92ffaSHans Petter Selasky  *        provided with the distribution.
22*d6b92ffaSHans Petter Selasky  *
23*d6b92ffaSHans Petter Selasky  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24*d6b92ffaSHans Petter Selasky  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25*d6b92ffaSHans Petter Selasky  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26*d6b92ffaSHans Petter Selasky  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27*d6b92ffaSHans Petter Selasky  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28*d6b92ffaSHans Petter Selasky  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29*d6b92ffaSHans Petter Selasky  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30*d6b92ffaSHans Petter Selasky  * SOFTWARE.
31*d6b92ffaSHans Petter Selasky  *
32*d6b92ffaSHans Petter Selasky  */
33*d6b92ffaSHans Petter Selasky 
34*d6b92ffaSHans Petter Selasky #define _GNU_SOURCE
35*d6b92ffaSHans Petter Selasky 
36*d6b92ffaSHans Petter Selasky #if HAVE_CONFIG_H
37*d6b92ffaSHans Petter Selasky #  include <config.h>
38*d6b92ffaSHans Petter Selasky #endif				/* HAVE_CONFIG_H */
39*d6b92ffaSHans Petter Selasky 
40*d6b92ffaSHans Petter Selasky #include <inttypes.h>
41*d6b92ffaSHans Petter Selasky #include <string.h>
42*d6b92ffaSHans Petter Selasky #include <errno.h>
43*d6b92ffaSHans Petter Selasky #include <stdio.h>
44*d6b92ffaSHans Petter Selasky #include <stdlib.h>
45*d6b92ffaSHans Petter Selasky #include <getopt.h>
46*d6b92ffaSHans Petter Selasky #include <netinet/in.h>
47*d6b92ffaSHans Petter Selasky 
48*d6b92ffaSHans Petter Selasky #include <infiniband/mad.h>
49*d6b92ffaSHans Petter Selasky #include <infiniband/umad.h>
50*d6b92ffaSHans Petter Selasky 
51*d6b92ffaSHans Petter Selasky #include <ibdiag_common.h>
52*d6b92ffaSHans Petter Selasky 
53*d6b92ffaSHans Petter Selasky static int mad_agent;
54*d6b92ffaSHans Petter Selasky static int drmad_tid = 0x123;
55*d6b92ffaSHans Petter Selasky 
56*d6b92ffaSHans Petter Selasky typedef struct {
57*d6b92ffaSHans Petter Selasky 	char path[64];
58*d6b92ffaSHans Petter Selasky 	int hop_cnt;
59*d6b92ffaSHans Petter Selasky } DRPath;
60*d6b92ffaSHans Petter Selasky 
61*d6b92ffaSHans Petter Selasky struct drsmp {
62*d6b92ffaSHans Petter Selasky 	uint8_t base_version;
63*d6b92ffaSHans Petter Selasky 	uint8_t mgmt_class;
64*d6b92ffaSHans Petter Selasky 	uint8_t class_version;
65*d6b92ffaSHans Petter Selasky 	uint8_t method;
66*d6b92ffaSHans Petter Selasky 	uint16_t status;
67*d6b92ffaSHans Petter Selasky 	uint8_t hop_ptr;
68*d6b92ffaSHans Petter Selasky 	uint8_t hop_cnt;
69*d6b92ffaSHans Petter Selasky 	uint64_t tid;
70*d6b92ffaSHans Petter Selasky 	uint16_t attr_id;
71*d6b92ffaSHans Petter Selasky 	uint16_t resv;
72*d6b92ffaSHans Petter Selasky 	uint32_t attr_mod;
73*d6b92ffaSHans Petter Selasky 	uint64_t mkey;
74*d6b92ffaSHans Petter Selasky 	uint16_t dr_slid;
75*d6b92ffaSHans Petter Selasky 	uint16_t dr_dlid;
76*d6b92ffaSHans Petter Selasky 	uint8_t reserved[28];
77*d6b92ffaSHans Petter Selasky 	uint8_t data[64];
78*d6b92ffaSHans Petter Selasky 	uint8_t initial_path[64];
79*d6b92ffaSHans Petter Selasky 	uint8_t return_path[64];
80*d6b92ffaSHans Petter Selasky };
81*d6b92ffaSHans Petter Selasky 
drsmp_get_init(void * umad,DRPath * path,int attr,int mod)82*d6b92ffaSHans Petter Selasky void drsmp_get_init(void *umad, DRPath * path, int attr, int mod)
83*d6b92ffaSHans Petter Selasky {
84*d6b92ffaSHans Petter Selasky 	struct drsmp *smp = (struct drsmp *)(umad_get_mad(umad));
85*d6b92ffaSHans Petter Selasky 
86*d6b92ffaSHans Petter Selasky 	memset(smp, 0, sizeof(*smp));
87*d6b92ffaSHans Petter Selasky 
88*d6b92ffaSHans Petter Selasky 	smp->base_version = 1;
89*d6b92ffaSHans Petter Selasky 	smp->mgmt_class = IB_SMI_DIRECT_CLASS;
90*d6b92ffaSHans Petter Selasky 	smp->class_version = 1;
91*d6b92ffaSHans Petter Selasky 
92*d6b92ffaSHans Petter Selasky 	smp->method = 1;
93*d6b92ffaSHans Petter Selasky 	smp->attr_id = (uint16_t) htons((uint16_t) attr);
94*d6b92ffaSHans Petter Selasky 	smp->attr_mod = htonl(mod);
95*d6b92ffaSHans Petter Selasky 	smp->tid = htonll(drmad_tid++);
96*d6b92ffaSHans Petter Selasky 	smp->dr_slid = 0xffff;
97*d6b92ffaSHans Petter Selasky 	smp->dr_dlid = 0xffff;
98*d6b92ffaSHans Petter Selasky 
99*d6b92ffaSHans Petter Selasky 	umad_set_addr(umad, 0xffff, 0, 0, 0);
100*d6b92ffaSHans Petter Selasky 
101*d6b92ffaSHans Petter Selasky 	if (path)
102*d6b92ffaSHans Petter Selasky 		memcpy(smp->initial_path, path->path, path->hop_cnt + 1);
103*d6b92ffaSHans Petter Selasky 
104*d6b92ffaSHans Petter Selasky 	smp->hop_cnt = (uint8_t) path->hop_cnt;
105*d6b92ffaSHans Petter Selasky }
106*d6b92ffaSHans Petter Selasky 
smp_get_init(void * umad,int lid,int attr,int mod)107*d6b92ffaSHans Petter Selasky void smp_get_init(void *umad, int lid, int attr, int mod)
108*d6b92ffaSHans Petter Selasky {
109*d6b92ffaSHans Petter Selasky 	struct drsmp *smp = (struct drsmp *)(umad_get_mad(umad));
110*d6b92ffaSHans Petter Selasky 
111*d6b92ffaSHans Petter Selasky 	memset(smp, 0, sizeof(*smp));
112*d6b92ffaSHans Petter Selasky 
113*d6b92ffaSHans Petter Selasky 	smp->base_version = 1;
114*d6b92ffaSHans Petter Selasky 	smp->mgmt_class = IB_SMI_CLASS;
115*d6b92ffaSHans Petter Selasky 	smp->class_version = 1;
116*d6b92ffaSHans Petter Selasky 
117*d6b92ffaSHans Petter Selasky 	smp->method = 1;
118*d6b92ffaSHans Petter Selasky 	smp->attr_id = (uint16_t) htons((uint16_t) attr);
119*d6b92ffaSHans Petter Selasky 	smp->attr_mod = htonl(mod);
120*d6b92ffaSHans Petter Selasky 	smp->tid = htonll(drmad_tid++);
121*d6b92ffaSHans Petter Selasky 
122*d6b92ffaSHans Petter Selasky 	umad_set_addr(umad, lid, 0, 0, 0);
123*d6b92ffaSHans Petter Selasky }
124*d6b92ffaSHans Petter Selasky 
drsmp_set_init(void * umad,DRPath * path,int attr,int mod,void * data)125*d6b92ffaSHans Petter Selasky void drsmp_set_init(void *umad, DRPath * path, int attr, int mod, void *data)
126*d6b92ffaSHans Petter Selasky {
127*d6b92ffaSHans Petter Selasky 	struct drsmp *smp = (struct drsmp *)(umad_get_mad(umad));
128*d6b92ffaSHans Petter Selasky 
129*d6b92ffaSHans Petter Selasky 	memset(smp, 0, sizeof(*smp));
130*d6b92ffaSHans Petter Selasky 
131*d6b92ffaSHans Petter Selasky 	smp->method = 2;	/* SET */
132*d6b92ffaSHans Petter Selasky 	smp->attr_id = (uint16_t) htons((uint16_t) attr);
133*d6b92ffaSHans Petter Selasky 	smp->attr_mod = htonl(mod);
134*d6b92ffaSHans Petter Selasky 	smp->tid = htonll(drmad_tid++);
135*d6b92ffaSHans Petter Selasky 	smp->dr_slid = 0xffff;
136*d6b92ffaSHans Petter Selasky 	smp->dr_dlid = 0xffff;
137*d6b92ffaSHans Petter Selasky 
138*d6b92ffaSHans Petter Selasky 	umad_set_addr(umad, 0xffff, 0, 0, 0);
139*d6b92ffaSHans Petter Selasky 
140*d6b92ffaSHans Petter Selasky 	if (path)
141*d6b92ffaSHans Petter Selasky 		memcpy(smp->initial_path, path->path, path->hop_cnt + 1);
142*d6b92ffaSHans Petter Selasky 
143*d6b92ffaSHans Petter Selasky 	if (data)
144*d6b92ffaSHans Petter Selasky 		memcpy(smp->data, data, sizeof smp->data);
145*d6b92ffaSHans Petter Selasky 
146*d6b92ffaSHans Petter Selasky 	smp->hop_cnt = (uint8_t) path->hop_cnt;
147*d6b92ffaSHans Petter Selasky }
148*d6b92ffaSHans Petter Selasky 
drmad_status_str(struct drsmp * drsmp)149*d6b92ffaSHans Petter Selasky char *drmad_status_str(struct drsmp *drsmp)
150*d6b92ffaSHans Petter Selasky {
151*d6b92ffaSHans Petter Selasky 	switch (drsmp->status) {
152*d6b92ffaSHans Petter Selasky 	case 0:
153*d6b92ffaSHans Petter Selasky 		return "success";
154*d6b92ffaSHans Petter Selasky 	case ETIMEDOUT:
155*d6b92ffaSHans Petter Selasky 		return "timeout";
156*d6b92ffaSHans Petter Selasky 	}
157*d6b92ffaSHans Petter Selasky 	return "unknown error";
158*d6b92ffaSHans Petter Selasky }
159*d6b92ffaSHans Petter Selasky 
str2DRPath(char * str,DRPath * path)160*d6b92ffaSHans Petter Selasky int str2DRPath(char *str, DRPath * path)
161*d6b92ffaSHans Petter Selasky {
162*d6b92ffaSHans Petter Selasky 	char *s;
163*d6b92ffaSHans Petter Selasky 
164*d6b92ffaSHans Petter Selasky 	path->hop_cnt = -1;
165*d6b92ffaSHans Petter Selasky 
166*d6b92ffaSHans Petter Selasky 	DEBUG("DR str: %s", str);
167*d6b92ffaSHans Petter Selasky 	while (str && *str) {
168*d6b92ffaSHans Petter Selasky 		if ((s = strchr(str, ',')))
169*d6b92ffaSHans Petter Selasky 			*s = 0;
170*d6b92ffaSHans Petter Selasky 		path->path[++path->hop_cnt] = (char)atoi(str);
171*d6b92ffaSHans Petter Selasky 		if (!s)
172*d6b92ffaSHans Petter Selasky 			break;
173*d6b92ffaSHans Petter Selasky 		str = s + 1;
174*d6b92ffaSHans Petter Selasky 	}
175*d6b92ffaSHans Petter Selasky 
176*d6b92ffaSHans Petter Selasky #if 0
177*d6b92ffaSHans Petter Selasky 	if (path->path[0] != 0 ||
178*d6b92ffaSHans Petter Selasky 	    (path->hop_cnt > 0 && dev_port && path->path[1] != dev_port)) {
179*d6b92ffaSHans Petter Selasky 		DEBUG("hop 0 != 0 or hop 1 != dev_port");
180*d6b92ffaSHans Petter Selasky 		return -1;
181*d6b92ffaSHans Petter Selasky 	}
182*d6b92ffaSHans Petter Selasky #endif
183*d6b92ffaSHans Petter Selasky 
184*d6b92ffaSHans Petter Selasky 	return path->hop_cnt;
185*d6b92ffaSHans Petter Selasky }
186*d6b92ffaSHans Petter Selasky 
187*d6b92ffaSHans Petter Selasky static int dump_char, mgmt_class = IB_SMI_CLASS;
188*d6b92ffaSHans Petter Selasky 
process_opt(void * context,int ch,char * optarg)189*d6b92ffaSHans Petter Selasky static int process_opt(void *context, int ch, char *optarg)
190*d6b92ffaSHans Petter Selasky {
191*d6b92ffaSHans Petter Selasky 	switch (ch) {
192*d6b92ffaSHans Petter Selasky 	case 's':
193*d6b92ffaSHans Petter Selasky 		dump_char++;
194*d6b92ffaSHans Petter Selasky 		break;
195*d6b92ffaSHans Petter Selasky 	case 'D':
196*d6b92ffaSHans Petter Selasky 		mgmt_class = IB_SMI_DIRECT_CLASS;
197*d6b92ffaSHans Petter Selasky 		break;
198*d6b92ffaSHans Petter Selasky 	case 'L':
199*d6b92ffaSHans Petter Selasky 		mgmt_class = IB_SMI_CLASS;
200*d6b92ffaSHans Petter Selasky 		break;
201*d6b92ffaSHans Petter Selasky 	default:
202*d6b92ffaSHans Petter Selasky 		return -1;
203*d6b92ffaSHans Petter Selasky 	}
204*d6b92ffaSHans Petter Selasky 	return 0;
205*d6b92ffaSHans Petter Selasky }
206*d6b92ffaSHans Petter Selasky 
207*d6b92ffaSHans Petter Selasky #ifndef strdupa
208*d6b92ffaSHans Petter Selasky #define	strdupa(_s)						\
209*d6b92ffaSHans Petter Selasky ({								\
210*d6b92ffaSHans Petter Selasky 	char *_d;						\
211*d6b92ffaSHans Petter Selasky 	int _len;						\
212*d6b92ffaSHans Petter Selasky 								\
213*d6b92ffaSHans Petter Selasky 	_len = strlen(_s) + 1;					\
214*d6b92ffaSHans Petter Selasky 	_d = alloca(_len);					\
215*d6b92ffaSHans Petter Selasky 	if (_d)							\
216*d6b92ffaSHans Petter Selasky 		memcpy(_d, _s, _len);				\
217*d6b92ffaSHans Petter Selasky 	_d;							\
218*d6b92ffaSHans Petter Selasky })
219*d6b92ffaSHans Petter Selasky #endif
220*d6b92ffaSHans Petter Selasky 
main(int argc,char * argv[])221*d6b92ffaSHans Petter Selasky int main(int argc, char *argv[])
222*d6b92ffaSHans Petter Selasky {
223*d6b92ffaSHans Petter Selasky 	int dlid = 0;
224*d6b92ffaSHans Petter Selasky 	void *umad;
225*d6b92ffaSHans Petter Selasky 	struct drsmp *smp;
226*d6b92ffaSHans Petter Selasky 	int i, portid, mod = 0, attr;
227*d6b92ffaSHans Petter Selasky 	DRPath path;
228*d6b92ffaSHans Petter Selasky 	uint8_t *desc;
229*d6b92ffaSHans Petter Selasky 	int length;
230*d6b92ffaSHans Petter Selasky 
231*d6b92ffaSHans Petter Selasky 	const struct ibdiag_opt opts[] = {
232*d6b92ffaSHans Petter Selasky 		{"string", 's', 0, NULL, ""},
233*d6b92ffaSHans Petter Selasky 		{0}
234*d6b92ffaSHans Petter Selasky 	};
235*d6b92ffaSHans Petter Selasky 	char usage_args[] = "<dlid|dr_path> <attr> [mod]";
236*d6b92ffaSHans Petter Selasky 	const char *usage_examples[] = {
237*d6b92ffaSHans Petter Selasky 		" -- DR routed examples:",
238*d6b92ffaSHans Petter Selasky 		"-D 0,1,2,3,5 16	# NODE DESC",
239*d6b92ffaSHans Petter Selasky 		"-D 0,1,2 0x15 2	# PORT INFO, port 2",
240*d6b92ffaSHans Petter Selasky 		" -- LID routed examples:",
241*d6b92ffaSHans Petter Selasky 		"3 0x15 2	# PORT INFO, lid 3 port 2",
242*d6b92ffaSHans Petter Selasky 		"0xa0 0x11	# NODE INFO, lid 0xa0",
243*d6b92ffaSHans Petter Selasky 		NULL
244*d6b92ffaSHans Petter Selasky 	};
245*d6b92ffaSHans Petter Selasky 
246*d6b92ffaSHans Petter Selasky 	ibd_timeout = 1000;
247*d6b92ffaSHans Petter Selasky 
248*d6b92ffaSHans Petter Selasky 	ibdiag_process_opts(argc, argv, NULL, "GKs", opts, process_opt,
249*d6b92ffaSHans Petter Selasky 			    usage_args, usage_examples);
250*d6b92ffaSHans Petter Selasky 
251*d6b92ffaSHans Petter Selasky 	argc -= optind;
252*d6b92ffaSHans Petter Selasky 	argv += optind;
253*d6b92ffaSHans Petter Selasky 
254*d6b92ffaSHans Petter Selasky 	if (argc < 2)
255*d6b92ffaSHans Petter Selasky 		ibdiag_show_usage();
256*d6b92ffaSHans Petter Selasky 
257*d6b92ffaSHans Petter Selasky 	if (mgmt_class == IB_SMI_DIRECT_CLASS &&
258*d6b92ffaSHans Petter Selasky 	    str2DRPath(strdupa(argv[0]), &path) < 0)
259*d6b92ffaSHans Petter Selasky 		IBPANIC("bad path str '%s'", argv[0]);
260*d6b92ffaSHans Petter Selasky 
261*d6b92ffaSHans Petter Selasky 	if (mgmt_class == IB_SMI_CLASS)
262*d6b92ffaSHans Petter Selasky 		dlid = strtoul(argv[0], 0, 0);
263*d6b92ffaSHans Petter Selasky 
264*d6b92ffaSHans Petter Selasky 	attr = strtoul(argv[1], 0, 0);
265*d6b92ffaSHans Petter Selasky 	if (argc > 2)
266*d6b92ffaSHans Petter Selasky 		mod = strtoul(argv[2], 0, 0);
267*d6b92ffaSHans Petter Selasky 
268*d6b92ffaSHans Petter Selasky 	if (umad_init() < 0)
269*d6b92ffaSHans Petter Selasky 		IBPANIC("can't init UMAD library");
270*d6b92ffaSHans Petter Selasky 
271*d6b92ffaSHans Petter Selasky 	if ((portid = umad_open_port(ibd_ca, ibd_ca_port)) < 0)
272*d6b92ffaSHans Petter Selasky 		IBPANIC("can't open UMAD port (%s:%d)", ibd_ca, ibd_ca_port);
273*d6b92ffaSHans Petter Selasky 
274*d6b92ffaSHans Petter Selasky 	if ((mad_agent = umad_register(portid, mgmt_class, 1, 0, 0)) < 0)
275*d6b92ffaSHans Petter Selasky 		IBPANIC("Couldn't register agent for SMPs");
276*d6b92ffaSHans Petter Selasky 
277*d6b92ffaSHans Petter Selasky 	if (!(umad = umad_alloc(1, umad_size() + IB_MAD_SIZE)))
278*d6b92ffaSHans Petter Selasky 		IBPANIC("can't alloc MAD");
279*d6b92ffaSHans Petter Selasky 
280*d6b92ffaSHans Petter Selasky 	smp = umad_get_mad(umad);
281*d6b92ffaSHans Petter Selasky 
282*d6b92ffaSHans Petter Selasky 	if (mgmt_class == IB_SMI_DIRECT_CLASS)
283*d6b92ffaSHans Petter Selasky 		drsmp_get_init(umad, &path, attr, mod);
284*d6b92ffaSHans Petter Selasky 	else
285*d6b92ffaSHans Petter Selasky 		smp_get_init(umad, dlid, attr, mod);
286*d6b92ffaSHans Petter Selasky 
287*d6b92ffaSHans Petter Selasky 	if (ibdebug > 1)
288*d6b92ffaSHans Petter Selasky 		xdump(stderr, "before send:\n", smp, 256);
289*d6b92ffaSHans Petter Selasky 
290*d6b92ffaSHans Petter Selasky 	length = IB_MAD_SIZE;
291*d6b92ffaSHans Petter Selasky 	if (umad_send(portid, mad_agent, umad, length, ibd_timeout, 0) < 0)
292*d6b92ffaSHans Petter Selasky 		IBPANIC("send failed");
293*d6b92ffaSHans Petter Selasky 
294*d6b92ffaSHans Petter Selasky 	if (umad_recv(portid, umad, &length, -1) != mad_agent)
295*d6b92ffaSHans Petter Selasky 		IBPANIC("recv error: %s", drmad_status_str(smp));
296*d6b92ffaSHans Petter Selasky 
297*d6b92ffaSHans Petter Selasky 	if (!dump_char) {
298*d6b92ffaSHans Petter Selasky 		xdump(stdout, 0, smp->data, 64);
299*d6b92ffaSHans Petter Selasky 		if (smp->status)
300*d6b92ffaSHans Petter Selasky 			fprintf(stdout, "SMP status: 0x%x\n",
301*d6b92ffaSHans Petter Selasky 				ntohs(smp->status));
302*d6b92ffaSHans Petter Selasky 		goto exit;
303*d6b92ffaSHans Petter Selasky 	}
304*d6b92ffaSHans Petter Selasky 
305*d6b92ffaSHans Petter Selasky 	desc = smp->data;
306*d6b92ffaSHans Petter Selasky 	for (i = 0; i < 64; ++i) {
307*d6b92ffaSHans Petter Selasky 		if (!desc[i])
308*d6b92ffaSHans Petter Selasky 			break;
309*d6b92ffaSHans Petter Selasky 		putchar(desc[i]);
310*d6b92ffaSHans Petter Selasky 	}
311*d6b92ffaSHans Petter Selasky 	putchar('\n');
312*d6b92ffaSHans Petter Selasky 	if (smp->status)
313*d6b92ffaSHans Petter Selasky 		fprintf(stdout, "SMP status: 0x%x\n", ntohs(smp->status));
314*d6b92ffaSHans Petter Selasky 
315*d6b92ffaSHans Petter Selasky exit:
316*d6b92ffaSHans Petter Selasky 	umad_free(umad);
317*d6b92ffaSHans Petter Selasky 	return 0;
318*d6b92ffaSHans Petter Selasky }
319