xref: /freebsd/contrib/ofed/infiniband-diags/src/ibportstate.c (revision e2c0e292e8a7ca00ba99bcfccc9e637f45c3e8b1)
1d6b92ffaSHans Petter Selasky /*
2d6b92ffaSHans Petter Selasky  * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
3d6b92ffaSHans Petter Selasky  * Copyright (c) 2010,2011 Mellanox Technologies LTD.  All rights reserved.
4d6b92ffaSHans Petter Selasky  * Copyright (c) 2011,2016 Oracle and/or its affiliates. All rights reserved.
5d6b92ffaSHans Petter Selasky  *
6d6b92ffaSHans Petter Selasky  * This software is available to you under a choice of one of two
7d6b92ffaSHans Petter Selasky  * licenses.  You may choose to be licensed under the terms of the GNU
8d6b92ffaSHans Petter Selasky  * General Public License (GPL) Version 2, available from the file
9d6b92ffaSHans Petter Selasky  * COPYING in the main directory of this source tree, or the
10d6b92ffaSHans Petter Selasky  * OpenIB.org BSD license below:
11d6b92ffaSHans Petter Selasky  *
12d6b92ffaSHans Petter Selasky  *     Redistribution and use in source and binary forms, with or
13d6b92ffaSHans Petter Selasky  *     without modification, are permitted provided that the following
14d6b92ffaSHans Petter Selasky  *     conditions are met:
15d6b92ffaSHans Petter Selasky  *
16d6b92ffaSHans Petter Selasky  *      - Redistributions of source code must retain the above
17d6b92ffaSHans Petter Selasky  *        copyright notice, this list of conditions and the following
18d6b92ffaSHans Petter Selasky  *        disclaimer.
19d6b92ffaSHans Petter Selasky  *
20d6b92ffaSHans Petter Selasky  *      - Redistributions in binary form must reproduce the above
21d6b92ffaSHans Petter Selasky  *        copyright notice, this list of conditions and the following
22d6b92ffaSHans Petter Selasky  *        disclaimer in the documentation and/or other materials
23d6b92ffaSHans Petter Selasky  *        provided with the distribution.
24d6b92ffaSHans Petter Selasky  *
25d6b92ffaSHans Petter Selasky  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26d6b92ffaSHans Petter Selasky  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27d6b92ffaSHans Petter Selasky  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28d6b92ffaSHans Petter Selasky  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29d6b92ffaSHans Petter Selasky  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30d6b92ffaSHans Petter Selasky  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31d6b92ffaSHans Petter Selasky  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32d6b92ffaSHans Petter Selasky  * SOFTWARE.
33d6b92ffaSHans Petter Selasky  *
34d6b92ffaSHans Petter Selasky  */
35d6b92ffaSHans Petter Selasky 
36d6b92ffaSHans Petter Selasky #if HAVE_CONFIG_H
37d6b92ffaSHans Petter Selasky #  include <config.h>
38d6b92ffaSHans Petter Selasky #endif				/* HAVE_CONFIG_H */
39d6b92ffaSHans Petter Selasky 
40d6b92ffaSHans Petter Selasky #include <stdio.h>
41d6b92ffaSHans Petter Selasky #include <stdlib.h>
42d6b92ffaSHans Petter Selasky #include <unistd.h>
43d6b92ffaSHans Petter Selasky #include <string.h>
44d6b92ffaSHans Petter Selasky #include <getopt.h>
45d6b92ffaSHans Petter Selasky #include <errno.h>
46d6b92ffaSHans Petter Selasky 
47d6b92ffaSHans Petter Selasky #include <infiniband/umad.h>
48d6b92ffaSHans Petter Selasky #include <infiniband/mad.h>
49d6b92ffaSHans Petter Selasky 
50d6b92ffaSHans Petter Selasky #include "ibdiag_common.h"
51d6b92ffaSHans Petter Selasky 
52d6b92ffaSHans Petter Selasky enum port_ops {
53d6b92ffaSHans Petter Selasky 	QUERY,
54d6b92ffaSHans Petter Selasky 	ENABLE,
55d6b92ffaSHans Petter Selasky 	RESET,
56d6b92ffaSHans Petter Selasky 	DISABLE,
57d6b92ffaSHans Petter Selasky 	SPEED,
58d6b92ffaSHans Petter Selasky 	ESPEED,
59d6b92ffaSHans Petter Selasky 	FDR10SPEED,
60d6b92ffaSHans Petter Selasky 	WIDTH,
61d6b92ffaSHans Petter Selasky 	DOWN,
62d6b92ffaSHans Petter Selasky 	ARM,
63d6b92ffaSHans Petter Selasky 	ACTIVE,
64d6b92ffaSHans Petter Selasky 	VLS,
65d6b92ffaSHans Petter Selasky 	MTU,
66d6b92ffaSHans Petter Selasky 	LID,
67d6b92ffaSHans Petter Selasky 	SMLID,
68d6b92ffaSHans Petter Selasky 	LMC,
69d6b92ffaSHans Petter Selasky 	MKEY,
70d6b92ffaSHans Petter Selasky 	MKEYLEASE,
71d6b92ffaSHans Petter Selasky 	MKEYPROT,
72d6b92ffaSHans Petter Selasky 	ON,
73d6b92ffaSHans Petter Selasky 	OFF
74d6b92ffaSHans Petter Selasky };
75d6b92ffaSHans Petter Selasky 
76d6b92ffaSHans Petter Selasky struct ibmad_port *srcport;
77d6b92ffaSHans Petter Selasky uint64_t speed = 0; /* no state change */
78d6b92ffaSHans Petter Selasky uint64_t espeed = 0; /* no state change */
79d6b92ffaSHans Petter Selasky uint64_t fdr10 = 0; /* no state change */
80d6b92ffaSHans Petter Selasky uint64_t width = 0; /* no state change */
81d6b92ffaSHans Petter Selasky uint64_t lid;
82d6b92ffaSHans Petter Selasky uint64_t smlid;
83d6b92ffaSHans Petter Selasky uint64_t lmc;
84d6b92ffaSHans Petter Selasky uint64_t mtu;
85d6b92ffaSHans Petter Selasky uint64_t vls = 0; /* no state change */
86d6b92ffaSHans Petter Selasky uint64_t mkey;
87d6b92ffaSHans Petter Selasky uint64_t mkeylease;
88d6b92ffaSHans Petter Selasky uint64_t mkeyprot;
89d6b92ffaSHans Petter Selasky 
90d6b92ffaSHans Petter Selasky struct {
91d6b92ffaSHans Petter Selasky 	const char *name;
92d6b92ffaSHans Petter Selasky 	uint64_t *val;
93d6b92ffaSHans Petter Selasky 	int set;
94d6b92ffaSHans Petter Selasky } port_args[] = {
95d6b92ffaSHans Petter Selasky 	{"query", NULL, 0},	/* QUERY */
96d6b92ffaSHans Petter Selasky 	{"enable", NULL, 0},	/* ENABLE */
97d6b92ffaSHans Petter Selasky 	{"reset", NULL, 0},	/* RESET */
98d6b92ffaSHans Petter Selasky 	{"disable", NULL, 0},	/* DISABLE */
99d6b92ffaSHans Petter Selasky 	{"speed", &speed, 0},	/* SPEED */
100d6b92ffaSHans Petter Selasky 	{"espeed", &espeed, 0},	/* EXTENDED SPEED */
101d6b92ffaSHans Petter Selasky 	{"fdr10", &fdr10, 0},	/* FDR10 SPEED */
102d6b92ffaSHans Petter Selasky 	{"width", &width, 0},	/* WIDTH */
103d6b92ffaSHans Petter Selasky 	{"down", NULL, 0},	/* DOWN */
104d6b92ffaSHans Petter Selasky 	{"arm", NULL, 0},	/* ARM */
105d6b92ffaSHans Petter Selasky 	{"active", NULL, 0},	/* ACTIVE */
106d6b92ffaSHans Petter Selasky 	{"vls", &vls, 0},	/* VLS */
107d6b92ffaSHans Petter Selasky 	{"mtu", &mtu, 0},	/* MTU */
108d6b92ffaSHans Petter Selasky 	{"lid", &lid, 0},	/* LID */
109d6b92ffaSHans Petter Selasky 	{"smlid", &smlid, 0},	/* SMLID */
110d6b92ffaSHans Petter Selasky 	{"lmc", &lmc, 0},	/* LMC */
111d6b92ffaSHans Petter Selasky 	{"mkey", &mkey, 0},	/* MKEY */
112d6b92ffaSHans Petter Selasky 	{"mkeylease", &mkeylease, 0},	/* MKEY LEASE */
113d6b92ffaSHans Petter Selasky 	{"mkeyprot", &mkeyprot, 0},	/* MKEY PROTECT BITS */
114d6b92ffaSHans Petter Selasky 	{"on", NULL, 0},	/* ON */
115d6b92ffaSHans Petter Selasky 	{"off", NULL, 0},	/* OFF */
116d6b92ffaSHans Petter Selasky };
117d6b92ffaSHans Petter Selasky 
118d6b92ffaSHans Petter Selasky #define NPORT_ARGS (sizeof(port_args) / sizeof(port_args[0]))
119d6b92ffaSHans Petter Selasky 
120d6b92ffaSHans Petter Selasky /*******************************************/
121d6b92ffaSHans Petter Selasky 
122d6b92ffaSHans Petter Selasky /*
123d6b92ffaSHans Petter Selasky  * Return 1 if node is a switch, else zero.
124d6b92ffaSHans Petter Selasky  */
get_node_info(ib_portid_t * dest,uint8_t * data)125d6b92ffaSHans Petter Selasky static int get_node_info(ib_portid_t * dest, uint8_t * data)
126d6b92ffaSHans Petter Selasky {
127d6b92ffaSHans Petter Selasky 	int node_type;
128d6b92ffaSHans Petter Selasky 
129d6b92ffaSHans Petter Selasky 	if (!smp_query_via(data, dest, IB_ATTR_NODE_INFO, 0, 0, srcport))
130d6b92ffaSHans Petter Selasky 		IBEXIT("smp query nodeinfo failed");
131d6b92ffaSHans Petter Selasky 
132d6b92ffaSHans Petter Selasky 	node_type = mad_get_field(data, 0, IB_NODE_TYPE_F);
133d6b92ffaSHans Petter Selasky 	if (node_type == IB_NODE_SWITCH)	/* Switch NodeType ? */
134d6b92ffaSHans Petter Selasky 		return 1;
135d6b92ffaSHans Petter Selasky 	else
136d6b92ffaSHans Petter Selasky 		return 0;
137d6b92ffaSHans Petter Selasky }
138d6b92ffaSHans Petter Selasky 
get_port_info(ib_portid_t * dest,uint8_t * data,int portnum,int is_switch)139d6b92ffaSHans Petter Selasky static int get_port_info(ib_portid_t * dest, uint8_t * data, int portnum,
140d6b92ffaSHans Petter Selasky 			 int is_switch)
141d6b92ffaSHans Petter Selasky {
142d6b92ffaSHans Petter Selasky 	uint8_t smp[IB_SMP_DATA_SIZE];
143d6b92ffaSHans Petter Selasky 	uint8_t *info;
144d6b92ffaSHans Petter Selasky 	int cap_mask;
145d6b92ffaSHans Petter Selasky 
146d6b92ffaSHans Petter Selasky 	if (is_switch) {
147d6b92ffaSHans Petter Selasky 		if (!smp_query_via(smp, dest, IB_ATTR_PORT_INFO, 0, 0, srcport))
148d6b92ffaSHans Petter Selasky 			IBEXIT("smp query port 0 portinfo failed");
149d6b92ffaSHans Petter Selasky 		info = smp;
150d6b92ffaSHans Petter Selasky 	} else
151d6b92ffaSHans Petter Selasky 		info = data;
152d6b92ffaSHans Petter Selasky 
153d6b92ffaSHans Petter Selasky 	if (!smp_query_via(data, dest, IB_ATTR_PORT_INFO, portnum, 0, srcport))
154d6b92ffaSHans Petter Selasky 		IBEXIT("smp query portinfo failed");
155d6b92ffaSHans Petter Selasky 	cap_mask = mad_get_field(info, 0, IB_PORT_CAPMASK_F);
156d6b92ffaSHans Petter Selasky 	return (cap_mask & CL_NTOH32(IB_PORT_CAP_HAS_EXT_SPEEDS));
157d6b92ffaSHans Petter Selasky }
158d6b92ffaSHans Petter Selasky 
show_port_info(ib_portid_t * dest,uint8_t * data,int portnum,int espeed_cap,int is_switch)159d6b92ffaSHans Petter Selasky static void show_port_info(ib_portid_t * dest, uint8_t * data, int portnum,
160d6b92ffaSHans Petter Selasky 			   int espeed_cap, int is_switch)
161d6b92ffaSHans Petter Selasky {
162d6b92ffaSHans Petter Selasky 	char buf[2300];
163d6b92ffaSHans Petter Selasky 	char val[64];
164d6b92ffaSHans Petter Selasky 
165d6b92ffaSHans Petter Selasky 	mad_dump_portstates(buf, sizeof buf, data, sizeof *data);
166d6b92ffaSHans Petter Selasky 	mad_decode_field(data, IB_PORT_LID_F, val);
167d6b92ffaSHans Petter Selasky 	mad_dump_field(IB_PORT_LID_F, buf + strlen(buf),
168d6b92ffaSHans Petter Selasky 		       sizeof buf - strlen(buf), val);
169d6b92ffaSHans Petter Selasky 	sprintf(buf + strlen(buf), "%s", "\n");
170d6b92ffaSHans Petter Selasky 	mad_decode_field(data, IB_PORT_SMLID_F, val);
171d6b92ffaSHans Petter Selasky 	mad_dump_field(IB_PORT_SMLID_F, buf + strlen(buf),
172d6b92ffaSHans Petter Selasky 		       sizeof buf - strlen(buf), val);
173d6b92ffaSHans Petter Selasky 	sprintf(buf + strlen(buf), "%s", "\n");
174d6b92ffaSHans Petter Selasky 	mad_decode_field(data, IB_PORT_LMC_F, val);
175d6b92ffaSHans Petter Selasky 	mad_dump_field(IB_PORT_LMC_F, buf + strlen(buf),
176d6b92ffaSHans Petter Selasky 		       sizeof buf - strlen(buf), val);
177d6b92ffaSHans Petter Selasky 	sprintf(buf + strlen(buf), "%s", "\n");
178d6b92ffaSHans Petter Selasky 	mad_decode_field(data, IB_PORT_LINK_WIDTH_SUPPORTED_F, val);
179d6b92ffaSHans Petter Selasky 	mad_dump_field(IB_PORT_LINK_WIDTH_SUPPORTED_F, buf + strlen(buf),
180d6b92ffaSHans Petter Selasky 		       sizeof buf - strlen(buf), val);
181d6b92ffaSHans Petter Selasky 	sprintf(buf + strlen(buf), "%s", "\n");
182d6b92ffaSHans Petter Selasky 	mad_decode_field(data, IB_PORT_LINK_WIDTH_ENABLED_F, val);
183d6b92ffaSHans Petter Selasky 	mad_dump_field(IB_PORT_LINK_WIDTH_ENABLED_F, buf + strlen(buf),
184d6b92ffaSHans Petter Selasky 		       sizeof buf - strlen(buf), val);
185d6b92ffaSHans Petter Selasky 	sprintf(buf + strlen(buf), "%s", "\n");
186d6b92ffaSHans Petter Selasky 	mad_decode_field(data, IB_PORT_LINK_WIDTH_ACTIVE_F, val);
187d6b92ffaSHans Petter Selasky 	mad_dump_field(IB_PORT_LINK_WIDTH_ACTIVE_F, buf + strlen(buf),
188d6b92ffaSHans Petter Selasky 		       sizeof buf - strlen(buf), val);
189d6b92ffaSHans Petter Selasky 	sprintf(buf + strlen(buf), "%s", "\n");
190d6b92ffaSHans Petter Selasky 	mad_decode_field(data, IB_PORT_LINK_SPEED_SUPPORTED_F, val);
191d6b92ffaSHans Petter Selasky 	mad_dump_field(IB_PORT_LINK_SPEED_SUPPORTED_F, buf + strlen(buf),
192d6b92ffaSHans Petter Selasky 		       sizeof buf - strlen(buf), val);
193d6b92ffaSHans Petter Selasky 	sprintf(buf + strlen(buf), "%s", "\n");
194d6b92ffaSHans Petter Selasky 	mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F, val);
195d6b92ffaSHans Petter Selasky 	mad_dump_field(IB_PORT_LINK_SPEED_ENABLED_F, buf + strlen(buf),
196d6b92ffaSHans Petter Selasky 		       sizeof buf - strlen(buf), val);
197d6b92ffaSHans Petter Selasky 	sprintf(buf + strlen(buf), "%s", "\n");
198d6b92ffaSHans Petter Selasky 	mad_decode_field(data, IB_PORT_LINK_SPEED_ACTIVE_F, val);
199d6b92ffaSHans Petter Selasky 	mad_dump_field(IB_PORT_LINK_SPEED_ACTIVE_F, buf + strlen(buf),
200d6b92ffaSHans Petter Selasky 		       sizeof buf - strlen(buf), val);
201d6b92ffaSHans Petter Selasky 	sprintf(buf + strlen(buf), "%s", "\n");
202d6b92ffaSHans Petter Selasky 	if (espeed_cap) {
203d6b92ffaSHans Petter Selasky 		mad_decode_field(data, IB_PORT_LINK_SPEED_EXT_SUPPORTED_F, val);
204d6b92ffaSHans Petter Selasky 		mad_dump_field(IB_PORT_LINK_SPEED_EXT_SUPPORTED_F,
205d6b92ffaSHans Petter Selasky 			       buf + strlen(buf), sizeof buf - strlen(buf),
206d6b92ffaSHans Petter Selasky 			       val);
207d6b92ffaSHans Petter Selasky 		sprintf(buf + strlen(buf), "%s", "\n");
208d6b92ffaSHans Petter Selasky 		mad_decode_field(data, IB_PORT_LINK_SPEED_EXT_ENABLED_F, val);
209d6b92ffaSHans Petter Selasky 		mad_dump_field(IB_PORT_LINK_SPEED_EXT_ENABLED_F,
210d6b92ffaSHans Petter Selasky 			       buf + strlen(buf), sizeof buf - strlen(buf),
211d6b92ffaSHans Petter Selasky 			       val);
212d6b92ffaSHans Petter Selasky 		sprintf(buf + strlen(buf), "%s", "\n");
213d6b92ffaSHans Petter Selasky 		mad_decode_field(data, IB_PORT_LINK_SPEED_EXT_ACTIVE_F, val);
214d6b92ffaSHans Petter Selasky 		mad_dump_field(IB_PORT_LINK_SPEED_EXT_ACTIVE_F,
215d6b92ffaSHans Petter Selasky 			       buf + strlen(buf), sizeof buf - strlen(buf),
216d6b92ffaSHans Petter Selasky 			       val);
217d6b92ffaSHans Petter Selasky 		sprintf(buf + strlen(buf), "%s", "\n");
218d6b92ffaSHans Petter Selasky 	}
219d6b92ffaSHans Petter Selasky 	if (!is_switch || portnum == 0) {
220d6b92ffaSHans Petter Selasky 		if (show_keys) {
221d6b92ffaSHans Petter Selasky 			mad_decode_field(data, IB_PORT_MKEY_F, val);
222d6b92ffaSHans Petter Selasky 			mad_dump_field(IB_PORT_MKEY_F, buf + strlen(buf),
223d6b92ffaSHans Petter Selasky 				       sizeof buf - strlen(buf), val);
224d6b92ffaSHans Petter Selasky 		} else
225d6b92ffaSHans Petter Selasky 			snprint_field(buf+strlen(buf), sizeof(buf)-strlen(buf),
226d6b92ffaSHans Petter Selasky 				      IB_PORT_MKEY_F, 32, NOT_DISPLAYED_STR);
227d6b92ffaSHans Petter Selasky 		sprintf(buf+strlen(buf), "%s", "\n");
228d6b92ffaSHans Petter Selasky 		mad_decode_field(data, IB_PORT_MKEY_LEASE_F, val);
229d6b92ffaSHans Petter Selasky 		mad_dump_field(IB_PORT_MKEY_LEASE_F, buf + strlen(buf),
230d6b92ffaSHans Petter Selasky 			       sizeof buf - strlen(buf), val);
231d6b92ffaSHans Petter Selasky 		sprintf(buf+strlen(buf), "%s", "\n");
232d6b92ffaSHans Petter Selasky 		mad_decode_field(data, IB_PORT_MKEY_PROT_BITS_F, val);
233d6b92ffaSHans Petter Selasky 		mad_dump_field(IB_PORT_MKEY_PROT_BITS_F, buf + strlen(buf),
234d6b92ffaSHans Petter Selasky 			       sizeof buf - strlen(buf), val);
235d6b92ffaSHans Petter Selasky 		sprintf(buf+strlen(buf), "%s", "\n");
236d6b92ffaSHans Petter Selasky 	}
237d6b92ffaSHans Petter Selasky 
238d6b92ffaSHans Petter Selasky 	printf("# Port info: %s port %d\n%s", portid2str(dest), portnum, buf);
239d6b92ffaSHans Petter Selasky }
240d6b92ffaSHans Petter Selasky 
set_port_info(ib_portid_t * dest,uint8_t * data,int portnum,int espeed_cap,int is_switch)241d6b92ffaSHans Petter Selasky static void set_port_info(ib_portid_t * dest, uint8_t * data, int portnum,
242d6b92ffaSHans Petter Selasky 			  int espeed_cap, int is_switch)
243d6b92ffaSHans Petter Selasky {
244d6b92ffaSHans Petter Selasky 	unsigned mod;
245d6b92ffaSHans Petter Selasky 
246d6b92ffaSHans Petter Selasky 	mod = portnum;
247d6b92ffaSHans Petter Selasky 	if (espeed_cap)
248d6b92ffaSHans Petter Selasky 		mod |= 1<<31;
249d6b92ffaSHans Petter Selasky 	if (!smp_set_via(data, dest, IB_ATTR_PORT_INFO, mod, 0, srcport))
250d6b92ffaSHans Petter Selasky 		IBEXIT("smp set portinfo failed");
251d6b92ffaSHans Petter Selasky 
252d6b92ffaSHans Petter Selasky 	printf("\nAfter PortInfo set:\n");
253d6b92ffaSHans Petter Selasky 	show_port_info(dest, data, portnum, espeed_cap, is_switch);
254d6b92ffaSHans Petter Selasky }
255d6b92ffaSHans Petter Selasky 
get_mlnx_ext_port_info(ib_portid_t * dest,uint8_t * data,int portnum)256d6b92ffaSHans Petter Selasky static void get_mlnx_ext_port_info(ib_portid_t * dest, uint8_t * data, int portnum)
257d6b92ffaSHans Petter Selasky {
258d6b92ffaSHans Petter Selasky 	if (!smp_query_via(data, dest, IB_ATTR_MLNX_EXT_PORT_INFO,
259d6b92ffaSHans Petter Selasky 			   portnum, 0, srcport))
260d6b92ffaSHans Petter Selasky 		IBEXIT("smp query ext portinfo failed");
261d6b92ffaSHans Petter Selasky }
262d6b92ffaSHans Petter Selasky 
show_mlnx_ext_port_info(ib_portid_t * dest,uint8_t * data,int portnum)263d6b92ffaSHans Petter Selasky static void show_mlnx_ext_port_info(ib_portid_t * dest, uint8_t * data, int portnum)
264d6b92ffaSHans Petter Selasky {
265d6b92ffaSHans Petter Selasky 	char buf[256];
266d6b92ffaSHans Petter Selasky 
267d6b92ffaSHans Petter Selasky 	mad_dump_mlnx_ext_port_info(buf, sizeof buf, data, IB_SMP_DATA_SIZE);
268d6b92ffaSHans Petter Selasky 
269d6b92ffaSHans Petter Selasky 	printf("# MLNX ext Port info: %s port %d\n%s", portid2str(dest),
270d6b92ffaSHans Petter Selasky 	       portnum, buf);
271d6b92ffaSHans Petter Selasky }
272d6b92ffaSHans Petter Selasky 
set_mlnx_ext_port_info(ib_portid_t * dest,uint8_t * data,int portnum)273d6b92ffaSHans Petter Selasky static void set_mlnx_ext_port_info(ib_portid_t * dest, uint8_t * data, int portnum)
274d6b92ffaSHans Petter Selasky {
275d6b92ffaSHans Petter Selasky 	if (!smp_set_via(data, dest, IB_ATTR_MLNX_EXT_PORT_INFO,
276d6b92ffaSHans Petter Selasky 			 portnum, 0, srcport))
277d6b92ffaSHans Petter Selasky 		IBEXIT("smp set MLNX ext portinfo failed");
278d6b92ffaSHans Petter Selasky 
279d6b92ffaSHans Petter Selasky 	printf("\nAfter MLNXExtendedPortInfo set:\n");
280d6b92ffaSHans Petter Selasky 	show_mlnx_ext_port_info(dest, data, portnum);
281d6b92ffaSHans Petter Selasky }
282d6b92ffaSHans Petter Selasky 
get_link_width(int lwe,int lws)283d6b92ffaSHans Petter Selasky static int get_link_width(int lwe, int lws)
284d6b92ffaSHans Petter Selasky {
285d6b92ffaSHans Petter Selasky 	if (lwe == 255)
286d6b92ffaSHans Petter Selasky 		return lws;
287d6b92ffaSHans Petter Selasky 	else
288d6b92ffaSHans Petter Selasky 		return lwe;
289d6b92ffaSHans Petter Selasky }
290d6b92ffaSHans Petter Selasky 
get_link_speed(int lse,int lss)291d6b92ffaSHans Petter Selasky static int get_link_speed(int lse, int lss)
292d6b92ffaSHans Petter Selasky {
293d6b92ffaSHans Petter Selasky 	if (lse == 15)
294d6b92ffaSHans Petter Selasky 		return lss;
295d6b92ffaSHans Petter Selasky 	else
296d6b92ffaSHans Petter Selasky 		return lse;
297d6b92ffaSHans Petter Selasky }
298d6b92ffaSHans Petter Selasky 
get_link_speed_ext(int lsee,int lses)299d6b92ffaSHans Petter Selasky static int get_link_speed_ext(int lsee, int lses)
300d6b92ffaSHans Petter Selasky {
301d6b92ffaSHans Petter Selasky 	if (lsee == 31)
302d6b92ffaSHans Petter Selasky 		return lses;
303d6b92ffaSHans Petter Selasky 	else
304d6b92ffaSHans Petter Selasky 		return lsee;
305d6b92ffaSHans Petter Selasky }
306d6b92ffaSHans Petter Selasky 
validate_width(int width,int peerwidth,int lwa)307d6b92ffaSHans Petter Selasky static void validate_width(int width, int peerwidth, int lwa)
308d6b92ffaSHans Petter Selasky {
309d6b92ffaSHans Petter Selasky 	if ((width & peerwidth & 0x8)) {
310d6b92ffaSHans Petter Selasky 		if (lwa != 8)
311d6b92ffaSHans Petter Selasky 			IBWARN
312d6b92ffaSHans Petter Selasky 			    ("Peer ports operating at active width %d rather than 8 (12x)",
313d6b92ffaSHans Petter Selasky 			     lwa);
314d6b92ffaSHans Petter Selasky 	} else if ((width & peerwidth & 0x4)) {
315d6b92ffaSHans Petter Selasky 		if (lwa != 4)
316d6b92ffaSHans Petter Selasky 			IBWARN
317d6b92ffaSHans Petter Selasky 			    ("Peer ports operating at active width %d rather than 4 (8x)",
318d6b92ffaSHans Petter Selasky 			     lwa);
319d6b92ffaSHans Petter Selasky 	} else if ((width & peerwidth & 0x2)) {
320d6b92ffaSHans Petter Selasky 		if (lwa != 2)
321d6b92ffaSHans Petter Selasky 			IBWARN
322d6b92ffaSHans Petter Selasky 			    ("Peer ports operating at active width %d rather than 2 (4x)",
323d6b92ffaSHans Petter Selasky 			     lwa);
324d6b92ffaSHans Petter Selasky 	} else if ((width & peerwidth & 0x10)) {
325d6b92ffaSHans Petter Selasky 		if (lwa != 16)
326d6b92ffaSHans Petter Selasky 			IBWARN
327d6b92ffaSHans Petter Selasky 			    ("Peer ports operating at active width %d rather than 16 (2x)",
328d6b92ffaSHans Petter Selasky 			      lwa);
329d6b92ffaSHans Petter Selasky 	} else if ((width & peerwidth & 0x1)) {
330d6b92ffaSHans Petter Selasky 		if (lwa != 1)
331d6b92ffaSHans Petter Selasky 			IBWARN
332d6b92ffaSHans Petter Selasky 			    ("Peer ports operating at active width %d rather than 1 (1x)",
333d6b92ffaSHans Petter Selasky 			     lwa);
334d6b92ffaSHans Petter Selasky 	}
335d6b92ffaSHans Petter Selasky }
336d6b92ffaSHans Petter Selasky 
validate_speed(int speed,int peerspeed,int lsa)337d6b92ffaSHans Petter Selasky static void validate_speed(int speed, int peerspeed, int lsa)
338d6b92ffaSHans Petter Selasky {
339d6b92ffaSHans Petter Selasky 	if ((speed & peerspeed & 0x4)) {
340d6b92ffaSHans Petter Selasky 		if (lsa != 4)
341d6b92ffaSHans Petter Selasky 			IBWARN
342d6b92ffaSHans Petter Selasky 			    ("Peer ports operating at active speed %d rather than 4 (10.0 Gbps)",
343d6b92ffaSHans Petter Selasky 			     lsa);
344d6b92ffaSHans Petter Selasky 	} else if ((speed & peerspeed & 0x2)) {
345d6b92ffaSHans Petter Selasky 		if (lsa != 2)
346d6b92ffaSHans Petter Selasky 			IBWARN
347d6b92ffaSHans Petter Selasky 			    ("Peer ports operating at active speed %d rather than 2 (5.0 Gbps)",
348d6b92ffaSHans Petter Selasky 			     lsa);
349d6b92ffaSHans Petter Selasky 	} else if ((speed & peerspeed & 0x1)) {
350d6b92ffaSHans Petter Selasky 		if (lsa != 1)
351d6b92ffaSHans Petter Selasky 			IBWARN
352d6b92ffaSHans Petter Selasky 			    ("Peer ports operating at active speed %d rather than 1 (2.5 Gbps)",
353d6b92ffaSHans Petter Selasky 			     lsa);
354d6b92ffaSHans Petter Selasky 	}
355d6b92ffaSHans Petter Selasky }
356d6b92ffaSHans Petter Selasky 
validate_extended_speed(int espeed,int peerespeed,int lsea)357d6b92ffaSHans Petter Selasky static void validate_extended_speed(int espeed, int peerespeed, int lsea)
358d6b92ffaSHans Petter Selasky {
359d6b92ffaSHans Petter Selasky 	if ((espeed & peerespeed & 0x2)) {
360d6b92ffaSHans Petter Selasky 		if (lsea != 2)
361d6b92ffaSHans Petter Selasky 			IBWARN
362d6b92ffaSHans Petter Selasky 			    ("Peer ports operating at active extended speed %d rather than 2 (25.78125 Gbps)",
363d6b92ffaSHans Petter Selasky 			     lsea);
364d6b92ffaSHans Petter Selasky 	} else if ((espeed & peerespeed & 0x1)) {
365d6b92ffaSHans Petter Selasky 		if (lsea != 1)
366d6b92ffaSHans Petter Selasky 			IBWARN
367d6b92ffaSHans Petter Selasky 			    ("Peer ports operating at active extended speed %d rather than 1 (14.0625 Gbps)",
368d6b92ffaSHans Petter Selasky 			     lsea);
369d6b92ffaSHans Petter Selasky 	}
370d6b92ffaSHans Petter Selasky }
371d6b92ffaSHans Petter Selasky 
main(int argc,char ** argv)372d6b92ffaSHans Petter Selasky int main(int argc, char **argv)
373d6b92ffaSHans Petter Selasky {
374d6b92ffaSHans Petter Selasky 	int mgmt_classes[3] =
375d6b92ffaSHans Petter Selasky 	    { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS };
376d6b92ffaSHans Petter Selasky 	ib_portid_t portid = { 0 };
377d6b92ffaSHans Petter Selasky 	int port_op = -1;
378d6b92ffaSHans Petter Selasky 	int is_switch, is_peer_switch, espeed_cap, peer_espeed_cap;
379d6b92ffaSHans Petter Selasky 	int state, physstate, lwe, lws, lwa, lse, lss, lsa, lsee, lses, lsea,
380d6b92ffaSHans Petter Selasky 	    fdr10s, fdr10e, fdr10a;
381d6b92ffaSHans Petter Selasky 	int peerlocalportnum, peerlwe, peerlws, peerlwa, peerlse, peerlss,
382d6b92ffaSHans Petter Selasky 	    peerlsa, peerlsee, peerlses, peerlsea, peerfdr10s, peerfdr10e,
383d6b92ffaSHans Petter Selasky 	    peerfdr10a;
384d6b92ffaSHans Petter Selasky 	int peerwidth, peerspeed, peerespeed;
385d6b92ffaSHans Petter Selasky 	uint8_t data[IB_SMP_DATA_SIZE] = { 0 };
386d6b92ffaSHans Petter Selasky 	uint8_t data2[IB_SMP_DATA_SIZE] = { 0 };
387d6b92ffaSHans Petter Selasky 	ib_portid_t peerportid = { 0 };
388d6b92ffaSHans Petter Selasky 	int portnum = 0;
389d6b92ffaSHans Petter Selasky 	ib_portid_t selfportid = { 0 };
390d6b92ffaSHans Petter Selasky 	int selfport = 0;
391d6b92ffaSHans Petter Selasky 	int changed = 0;
392d6b92ffaSHans Petter Selasky 	int i;
393d6b92ffaSHans Petter Selasky 	uint32_t vendorid, rem_vendorid;
394d6b92ffaSHans Petter Selasky 	uint16_t devid, rem_devid;
395d6b92ffaSHans Petter Selasky 	uint64_t val;
396d6b92ffaSHans Petter Selasky 	char *endp;
397d6b92ffaSHans Petter Selasky 	char usage_args[] = "<dest dr_path|lid|guid> <portnum> [<op>]\n"
398d6b92ffaSHans Petter Selasky 	    "\nSupported ops: enable, disable, on, off, reset, speed, espeed, fdr10,\n"
399d6b92ffaSHans Petter Selasky 	    "\twidth, query, down, arm, active, vls, mtu, lid, smlid, lmc,\n"
400d6b92ffaSHans Petter Selasky 	    "\tmkey, mkeylease, mkeyprot\n";
401d6b92ffaSHans Petter Selasky 	const char *usage_examples[] = {
402d6b92ffaSHans Petter Selasky 		"3 1 disable\t\t\t# by lid",
403d6b92ffaSHans Petter Selasky 		"-G 0x2C9000100D051 1 enable\t# by guid",
404d6b92ffaSHans Petter Selasky 		"-D 0 1\t\t\t# (query) by direct route",
405d6b92ffaSHans Petter Selasky 		"3 1 reset\t\t\t# by lid",
406d6b92ffaSHans Petter Selasky 		"3 1 speed 1\t\t\t# by lid",
407d6b92ffaSHans Petter Selasky 		"3 1 width 1\t\t\t# by lid",
408d6b92ffaSHans Petter Selasky 		"-D 0 1 lid 0x1234 arm\t\t# by direct route",
409d6b92ffaSHans Petter Selasky 		NULL
410d6b92ffaSHans Petter Selasky 	};
411d6b92ffaSHans Petter Selasky 
412d6b92ffaSHans Petter Selasky 	ibdiag_process_opts(argc, argv, NULL, NULL, NULL, NULL,
413d6b92ffaSHans Petter Selasky 			    usage_args, usage_examples);
414d6b92ffaSHans Petter Selasky 
415d6b92ffaSHans Petter Selasky 	argc -= optind;
416d6b92ffaSHans Petter Selasky 	argv += optind;
417d6b92ffaSHans Petter Selasky 
418d6b92ffaSHans Petter Selasky 	if (argc < 2)
419d6b92ffaSHans Petter Selasky 		ibdiag_show_usage();
420d6b92ffaSHans Petter Selasky 
421d6b92ffaSHans Petter Selasky 	srcport = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 3);
422d6b92ffaSHans Petter Selasky 	if (!srcport)
423d6b92ffaSHans Petter Selasky 		IBEXIT("Failed to open '%s' port '%d'", ibd_ca, ibd_ca_port);
424d6b92ffaSHans Petter Selasky 
425d6b92ffaSHans Petter Selasky 	smp_mkey_set(srcport, ibd_mkey);
426d6b92ffaSHans Petter Selasky 
427d6b92ffaSHans Petter Selasky 	if (resolve_portid_str(ibd_ca, ibd_ca_port, &portid, argv[0],
428d6b92ffaSHans Petter Selasky 			       ibd_dest_type, ibd_sm_id, srcport) < 0)
429d6b92ffaSHans Petter Selasky 		IBEXIT("can't resolve destination port %s", argv[0]);
430d6b92ffaSHans Petter Selasky 
431d6b92ffaSHans Petter Selasky 	if (argc > 1)
432d6b92ffaSHans Petter Selasky 		portnum = strtol(argv[1], 0, 0);
433d6b92ffaSHans Petter Selasky 
434d6b92ffaSHans Petter Selasky 	for (i = 2; i < argc; i++) {
435d6b92ffaSHans Petter Selasky 		int j;
436d6b92ffaSHans Petter Selasky 
437d6b92ffaSHans Petter Selasky 		for (j = 0; j < NPORT_ARGS; j++) {
438d6b92ffaSHans Petter Selasky 			if (strcmp(argv[i], port_args[j].name))
439d6b92ffaSHans Petter Selasky 				continue;
440d6b92ffaSHans Petter Selasky 			port_args[j].set = 1;
441d6b92ffaSHans Petter Selasky 			if (!port_args[j].val) {
442d6b92ffaSHans Petter Selasky 				if (port_op >= 0)
443d6b92ffaSHans Petter Selasky 					IBEXIT("%s only one of: ",
444d6b92ffaSHans Petter Selasky 						"query, enable, disable, "
445d6b92ffaSHans Petter Selasky 						"reset, down, arm, active, "
446d6b92ffaSHans Petter Selasky 						"can be specified",
447d6b92ffaSHans Petter Selasky 						port_args[j].name);
448d6b92ffaSHans Petter Selasky 				port_op = j;
449d6b92ffaSHans Petter Selasky 				break;
450d6b92ffaSHans Petter Selasky 			}
451d6b92ffaSHans Petter Selasky 			if (++i >= argc)
452d6b92ffaSHans Petter Selasky 				IBEXIT("%s requires an additional parameter",
453d6b92ffaSHans Petter Selasky 					port_args[j].name);
454d6b92ffaSHans Petter Selasky 			val = strtoull(argv[i], 0, 0);
455d6b92ffaSHans Petter Selasky 			switch (j) {
456d6b92ffaSHans Petter Selasky 			case SPEED:
457d6b92ffaSHans Petter Selasky 				if (val > 15)
458d6b92ffaSHans Petter Selasky 					IBEXIT("invalid speed value %ld", val);
459d6b92ffaSHans Petter Selasky 				break;
460d6b92ffaSHans Petter Selasky 			case ESPEED:
461d6b92ffaSHans Petter Selasky 				if (val > 31)
462d6b92ffaSHans Petter Selasky 					IBEXIT("invalid extended speed value %ld", val);
463d6b92ffaSHans Petter Selasky 				break;
464d6b92ffaSHans Petter Selasky 			case FDR10SPEED:
465d6b92ffaSHans Petter Selasky 				if (val > 1)
466d6b92ffaSHans Petter Selasky 					IBEXIT("invalid fdr10 speed value %ld", val);
467d6b92ffaSHans Petter Selasky 				break;
468d6b92ffaSHans Petter Selasky 			case WIDTH:
469d6b92ffaSHans Petter Selasky 				if ((val > 31 && val != 255))
470d6b92ffaSHans Petter Selasky 					IBEXIT("invalid width value %ld", val);
471d6b92ffaSHans Petter Selasky 				break;
472d6b92ffaSHans Petter Selasky 			case VLS:
473d6b92ffaSHans Petter Selasky 				if (val == 0 || val > 5)
474d6b92ffaSHans Petter Selasky 					IBEXIT("invalid vls value %ld", val);
475d6b92ffaSHans Petter Selasky 				break;
476d6b92ffaSHans Petter Selasky 			case MTU:
477d6b92ffaSHans Petter Selasky 				if (val == 0 || val > 5)
478d6b92ffaSHans Petter Selasky 					IBEXIT("invalid mtu value %ld", val);
479d6b92ffaSHans Petter Selasky 				break;
480d6b92ffaSHans Petter Selasky 			case LID:
481d6b92ffaSHans Petter Selasky 				if (val == 0 || val >= 0xC000)
482d6b92ffaSHans Petter Selasky 					IBEXIT("invalid lid value 0x%lx", val);
483d6b92ffaSHans Petter Selasky 				break;
484d6b92ffaSHans Petter Selasky 			case SMLID:
485d6b92ffaSHans Petter Selasky 				if (val == 0 || val >= 0xC000)
486d6b92ffaSHans Petter Selasky 					IBEXIT("invalid smlid value 0x%lx",
487d6b92ffaSHans Petter Selasky 						val);
488d6b92ffaSHans Petter Selasky 				break;
489d6b92ffaSHans Petter Selasky 			case LMC:
490d6b92ffaSHans Petter Selasky 				if (val > 7)
491d6b92ffaSHans Petter Selasky 					IBEXIT("invalid lmc value %ld", val);
492d6b92ffaSHans Petter Selasky 				break;
493d6b92ffaSHans Petter Selasky 			case MKEY:
494d6b92ffaSHans Petter Selasky 				errno = 0;
495d6b92ffaSHans Petter Selasky 				val = strtoull(argv[i], &endp, 0);
496d6b92ffaSHans Petter Selasky 				if (errno || *endp != '\0') {
497d6b92ffaSHans Petter Selasky 					errno = 0;
498d6b92ffaSHans Petter Selasky 					val = strtoull(getpass("New M_Key: "),
499d6b92ffaSHans Petter Selasky 						       &endp, 0);
500d6b92ffaSHans Petter Selasky 					if (errno || *endp != '\0') {
501d6b92ffaSHans Petter Selasky 						IBEXIT("Bad new M_Key\n");
502d6b92ffaSHans Petter Selasky 					}
503d6b92ffaSHans Petter Selasky 				}
504d6b92ffaSHans Petter Selasky 				/* All 64-bit values are legal */
505d6b92ffaSHans Petter Selasky 				break;
506d6b92ffaSHans Petter Selasky 			case MKEYLEASE:
507d6b92ffaSHans Petter Selasky 				if (val > 0xFFFF)
508d6b92ffaSHans Petter Selasky 					IBEXIT("invalid mkey lease time %ld", val);
509d6b92ffaSHans Petter Selasky 				break;
510d6b92ffaSHans Petter Selasky 			case MKEYPROT:
511d6b92ffaSHans Petter Selasky 				if (val > 3)
512d6b92ffaSHans Petter Selasky 					IBEXIT("invalid mkey protection bit setting %ld", val);
513d6b92ffaSHans Petter Selasky 			}
514d6b92ffaSHans Petter Selasky 			*port_args[j].val = val;
515d6b92ffaSHans Petter Selasky 			changed = 1;
516d6b92ffaSHans Petter Selasky 			break;
517d6b92ffaSHans Petter Selasky 		}
518d6b92ffaSHans Petter Selasky 		if (j == NPORT_ARGS)
519d6b92ffaSHans Petter Selasky 			IBEXIT("invalid operation: %s", argv[i]);
520d6b92ffaSHans Petter Selasky 	}
521d6b92ffaSHans Petter Selasky 	if (port_op < 0)
522d6b92ffaSHans Petter Selasky 		port_op = QUERY;
523d6b92ffaSHans Petter Selasky 
524d6b92ffaSHans Petter Selasky 	is_switch = get_node_info(&portid, data);
525d6b92ffaSHans Petter Selasky 	vendorid = (uint32_t) mad_get_field(data, 0, IB_NODE_VENDORID_F);
526d6b92ffaSHans Petter Selasky 	devid = (uint16_t) mad_get_field(data, 0, IB_NODE_DEVID_F);
527d6b92ffaSHans Petter Selasky 
528d6b92ffaSHans Petter Selasky 	if ((port_args[MKEY].set || port_args[MKEYLEASE].set ||
529d6b92ffaSHans Petter Selasky 	     port_args[MKEYPROT].set) && is_switch && portnum != 0)
530d6b92ffaSHans Petter Selasky 		IBEXIT("Can't set M_Key fields on switch port != 0");
531d6b92ffaSHans Petter Selasky 
532d6b92ffaSHans Petter Selasky 	if (port_op != QUERY || changed)
533d6b92ffaSHans Petter Selasky 		printf("Initial %s PortInfo:\n", is_switch ? "Switch" : "CA/RT");
534d6b92ffaSHans Petter Selasky 	else
535d6b92ffaSHans Petter Selasky 		printf("%s PortInfo:\n", is_switch ? "Switch" : "CA/RT");
536d6b92ffaSHans Petter Selasky 	espeed_cap = get_port_info(&portid, data, portnum, is_switch);
537d6b92ffaSHans Petter Selasky 	show_port_info(&portid, data, portnum, espeed_cap, is_switch);
538d6b92ffaSHans Petter Selasky 	if (is_mlnx_ext_port_info_supported(vendorid, devid)) {
539d6b92ffaSHans Petter Selasky 		get_mlnx_ext_port_info(&portid, data2, portnum);
540d6b92ffaSHans Petter Selasky 		show_mlnx_ext_port_info(&portid, data2, portnum);
541d6b92ffaSHans Petter Selasky 	}
542d6b92ffaSHans Petter Selasky 
543d6b92ffaSHans Petter Selasky 	if (port_op != QUERY || changed) {
544d6b92ffaSHans Petter Selasky 		/*
545d6b92ffaSHans Petter Selasky 		 * If we aren't setting the LID and the LID is the default,
546d6b92ffaSHans Petter Selasky 		 * the SMA command will fail due to an invalid LID.
547d6b92ffaSHans Petter Selasky 		 * Set it to something unlikely but valid.
548d6b92ffaSHans Petter Selasky 		 */
549d6b92ffaSHans Petter Selasky 		physstate = mad_get_field(data, 0, IB_PORT_PHYS_STATE_F);
550d6b92ffaSHans Petter Selasky 
551d6b92ffaSHans Petter Selasky 		val = mad_get_field(data, 0, IB_PORT_LID_F);
552d6b92ffaSHans Petter Selasky 		if (!port_args[LID].set && (!val || val == 0xFFFF))
553d6b92ffaSHans Petter Selasky 			mad_set_field(data, 0, IB_PORT_LID_F, 0x1234);
554d6b92ffaSHans Petter Selasky 		val = mad_get_field(data, 0, IB_PORT_SMLID_F);
555d6b92ffaSHans Petter Selasky 		if (!port_args[SMLID].set && (!val || val == 0xFFFF))
556d6b92ffaSHans Petter Selasky 			mad_set_field(data, 0, IB_PORT_SMLID_F, 0x1234);
557d6b92ffaSHans Petter Selasky 		mad_set_field(data, 0, IB_PORT_STATE_F, 0);	/* NOP */
558d6b92ffaSHans Petter Selasky 		mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 0);	/* NOP */
559d6b92ffaSHans Petter Selasky 
560d6b92ffaSHans Petter Selasky 		switch (port_op) {
561d6b92ffaSHans Petter Selasky 		case ON:
562d6b92ffaSHans Petter Selasky 			/* Enable only if state is Disable */
563d6b92ffaSHans Petter Selasky 			if(physstate != 3) {
564d6b92ffaSHans Petter Selasky 				printf("Port is already in enable state\n");
565d6b92ffaSHans Petter Selasky 				goto close_port;
566d6b92ffaSHans Petter Selasky 			}
567*d13def78SEric van Gyzen 			/* FALLTHROUGH */
568d6b92ffaSHans Petter Selasky 		case ENABLE:
569d6b92ffaSHans Petter Selasky 		case RESET:
570d6b92ffaSHans Petter Selasky 			/* Polling */
571d6b92ffaSHans Petter Selasky 			mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 2);
572d6b92ffaSHans Petter Selasky 			break;
573d6b92ffaSHans Petter Selasky 		case OFF:
574d6b92ffaSHans Petter Selasky 		case DISABLE:
575d6b92ffaSHans Petter Selasky 			printf("Disable may be irreversible\n");
576d6b92ffaSHans Petter Selasky 			mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 3);
577d6b92ffaSHans Petter Selasky 			break;
578d6b92ffaSHans Petter Selasky 		case DOWN:
579d6b92ffaSHans Petter Selasky 			mad_set_field(data, 0, IB_PORT_STATE_F, 1);
580d6b92ffaSHans Petter Selasky 			break;
581d6b92ffaSHans Petter Selasky 		case ARM:
582d6b92ffaSHans Petter Selasky 			mad_set_field(data, 0, IB_PORT_STATE_F, 3);
583d6b92ffaSHans Petter Selasky 			break;
584d6b92ffaSHans Petter Selasky 		case ACTIVE:
585d6b92ffaSHans Petter Selasky 			mad_set_field(data, 0, IB_PORT_STATE_F, 4);
586d6b92ffaSHans Petter Selasky 			break;
587d6b92ffaSHans Petter Selasky 		}
588d6b92ffaSHans Petter Selasky 
589d6b92ffaSHans Petter Selasky 		/* always set enabled speeds/width - defaults to NOP */
590d6b92ffaSHans Petter Selasky 		mad_set_field(data, 0, IB_PORT_LINK_SPEED_ENABLED_F, speed);
591d6b92ffaSHans Petter Selasky 		mad_set_field(data, 0, IB_PORT_LINK_SPEED_EXT_ENABLED_F, espeed);
592d6b92ffaSHans Petter Selasky 		mad_set_field(data, 0, IB_PORT_LINK_WIDTH_ENABLED_F, width);
593d6b92ffaSHans Petter Selasky 
594d6b92ffaSHans Petter Selasky 		if (port_args[VLS].set)
595d6b92ffaSHans Petter Selasky 			mad_set_field(data, 0, IB_PORT_OPER_VLS_F, vls);
596d6b92ffaSHans Petter Selasky 		if (port_args[MTU].set)
597d6b92ffaSHans Petter Selasky 			mad_set_field(data, 0, IB_PORT_NEIGHBOR_MTU_F, mtu);
598d6b92ffaSHans Petter Selasky 		if (port_args[LID].set)
599d6b92ffaSHans Petter Selasky 			mad_set_field(data, 0, IB_PORT_LID_F, lid);
600d6b92ffaSHans Petter Selasky 		if (port_args[SMLID].set)
601d6b92ffaSHans Petter Selasky 			mad_set_field(data, 0, IB_PORT_SMLID_F, smlid);
602d6b92ffaSHans Petter Selasky 		if (port_args[LMC].set)
603d6b92ffaSHans Petter Selasky 			mad_set_field(data, 0, IB_PORT_LMC_F, lmc);
604d6b92ffaSHans Petter Selasky 
605d6b92ffaSHans Petter Selasky 		if (port_args[FDR10SPEED].set) {
606d6b92ffaSHans Petter Selasky 			mad_set_field(data2, 0,
607d6b92ffaSHans Petter Selasky 				      IB_MLNX_EXT_PORT_STATE_CHG_ENABLE_F,
608d6b92ffaSHans Petter Selasky 				      FDR10);
609d6b92ffaSHans Petter Selasky 			mad_set_field(data2, 0,
610d6b92ffaSHans Petter Selasky 				      IB_MLNX_EXT_PORT_LINK_SPEED_ENABLED_F,
611d6b92ffaSHans Petter Selasky 				      fdr10);
612d6b92ffaSHans Petter Selasky 			set_mlnx_ext_port_info(&portid, data2, portnum);
613d6b92ffaSHans Petter Selasky 		}
614d6b92ffaSHans Petter Selasky 
615d6b92ffaSHans Petter Selasky 		if (port_args[MKEY].set)
616d6b92ffaSHans Petter Selasky 			mad_set_field64(data, 0, IB_PORT_MKEY_F, mkey);
617d6b92ffaSHans Petter Selasky 		if (port_args[MKEYLEASE].set)
618d6b92ffaSHans Petter Selasky 			mad_set_field(data, 0, IB_PORT_MKEY_LEASE_F,
619d6b92ffaSHans Petter Selasky 				      mkeylease);
620d6b92ffaSHans Petter Selasky 		if (port_args[MKEYPROT].set)
621d6b92ffaSHans Petter Selasky 			mad_set_field(data, 0, IB_PORT_MKEY_PROT_BITS_F,
622d6b92ffaSHans Petter Selasky 				      mkeyprot);
623d6b92ffaSHans Petter Selasky 
624d6b92ffaSHans Petter Selasky 		set_port_info(&portid, data, portnum, espeed_cap, is_switch);
625d6b92ffaSHans Petter Selasky 
626d6b92ffaSHans Petter Selasky 	} else if (is_switch && portnum) {
627d6b92ffaSHans Petter Selasky 		/* Now, make sure PortState is Active */
628d6b92ffaSHans Petter Selasky 		/* Or is PortPhysicalState LinkUp sufficient ? */
629d6b92ffaSHans Petter Selasky 		mad_decode_field(data, IB_PORT_STATE_F, &state);
630d6b92ffaSHans Petter Selasky 		mad_decode_field(data, IB_PORT_PHYS_STATE_F, &physstate);
631d6b92ffaSHans Petter Selasky 		if (state == 4) {	/* Active */
632d6b92ffaSHans Petter Selasky 			mad_decode_field(data, IB_PORT_LINK_WIDTH_ENABLED_F,
633d6b92ffaSHans Petter Selasky 					 &lwe);
634d6b92ffaSHans Petter Selasky 			mad_decode_field(data, IB_PORT_LINK_WIDTH_SUPPORTED_F,
635d6b92ffaSHans Petter Selasky 					 &lws);
636d6b92ffaSHans Petter Selasky 			mad_decode_field(data, IB_PORT_LINK_WIDTH_ACTIVE_F,
637d6b92ffaSHans Petter Selasky 					 &lwa);
638d6b92ffaSHans Petter Selasky 			mad_decode_field(data, IB_PORT_LINK_SPEED_SUPPORTED_F,
639d6b92ffaSHans Petter Selasky 					 &lss);
640d6b92ffaSHans Petter Selasky 			mad_decode_field(data, IB_PORT_LINK_SPEED_ACTIVE_F,
641d6b92ffaSHans Petter Selasky 					 &lsa);
642d6b92ffaSHans Petter Selasky 			mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F,
643d6b92ffaSHans Petter Selasky 					 &lse);
644d6b92ffaSHans Petter Selasky 			mad_decode_field(data2,
645d6b92ffaSHans Petter Selasky 					 IB_MLNX_EXT_PORT_LINK_SPEED_SUPPORTED_F,
646d6b92ffaSHans Petter Selasky 					 &fdr10s);
647d6b92ffaSHans Petter Selasky 			mad_decode_field(data2,
648d6b92ffaSHans Petter Selasky 					 IB_MLNX_EXT_PORT_LINK_SPEED_ENABLED_F,
649d6b92ffaSHans Petter Selasky 					 &fdr10e);
650d6b92ffaSHans Petter Selasky 			mad_decode_field(data2,
651d6b92ffaSHans Petter Selasky 					 IB_MLNX_EXT_PORT_LINK_SPEED_ACTIVE_F,
652d6b92ffaSHans Petter Selasky 					 &fdr10a);
653d6b92ffaSHans Petter Selasky 			if (espeed_cap) {
654d6b92ffaSHans Petter Selasky 				mad_decode_field(data,
655d6b92ffaSHans Petter Selasky 						 IB_PORT_LINK_SPEED_EXT_SUPPORTED_F,
656d6b92ffaSHans Petter Selasky 						 &lses);
657d6b92ffaSHans Petter Selasky 				mad_decode_field(data,
658d6b92ffaSHans Petter Selasky 						 IB_PORT_LINK_SPEED_EXT_ACTIVE_F,
659d6b92ffaSHans Petter Selasky 						 &lsea);
660d6b92ffaSHans Petter Selasky 				mad_decode_field(data,
661d6b92ffaSHans Petter Selasky 						 IB_PORT_LINK_SPEED_EXT_ENABLED_F,
662d6b92ffaSHans Petter Selasky 						 &lsee);
663d6b92ffaSHans Petter Selasky 			}
664d6b92ffaSHans Petter Selasky 
665d6b92ffaSHans Petter Selasky 			/* Setup portid for peer port */
666d6b92ffaSHans Petter Selasky 			memcpy(&peerportid, &portid, sizeof(peerportid));
667d6b92ffaSHans Petter Selasky 			if (portid.lid == 0) {
668d6b92ffaSHans Petter Selasky 				peerportid.drpath.cnt++;
669d6b92ffaSHans Petter Selasky 				if (peerportid.drpath.cnt == IB_SUBNET_PATH_HOPS_MAX) {
670d6b92ffaSHans Petter Selasky 					IBEXIT("Too many hops");
671d6b92ffaSHans Petter Selasky 				}
672d6b92ffaSHans Petter Selasky 			} else {
673d6b92ffaSHans Petter Selasky 				peerportid.drpath.cnt = 1;
674d6b92ffaSHans Petter Selasky 
675d6b92ffaSHans Petter Selasky 				/* Set DrSLID to local lid */
676d6b92ffaSHans Petter Selasky 				if (resolve_self(ibd_ca, ibd_ca_port, &selfportid,
677d6b92ffaSHans Petter Selasky 						         &selfport, 0) < 0)
678d6b92ffaSHans Petter Selasky 					IBEXIT("could not resolve self");
679d6b92ffaSHans Petter Selasky 				peerportid.drpath.drslid = (uint16_t) selfportid.lid;
680d6b92ffaSHans Petter Selasky 				peerportid.drpath.drdlid = 0xffff;
681d6b92ffaSHans Petter Selasky 			}
682d6b92ffaSHans Petter Selasky 			peerportid.drpath.p[peerportid.drpath.cnt] = (uint8_t) portnum;
683d6b92ffaSHans Petter Selasky 
684d6b92ffaSHans Petter Selasky 			/* Get peer port NodeInfo to obtain peer port number */
685d6b92ffaSHans Petter Selasky 			is_peer_switch = get_node_info(&peerportid, data);
686d6b92ffaSHans Petter Selasky 			rem_vendorid = (uint32_t) mad_get_field(data, 0, IB_NODE_VENDORID_F);
687d6b92ffaSHans Petter Selasky 			rem_devid = (uint16_t) mad_get_field(data, 0, IB_NODE_DEVID_F);
688d6b92ffaSHans Petter Selasky 
689d6b92ffaSHans Petter Selasky 			mad_decode_field(data, IB_NODE_LOCAL_PORT_F,
690d6b92ffaSHans Petter Selasky 					 &peerlocalportnum);
691d6b92ffaSHans Petter Selasky 
692d6b92ffaSHans Petter Selasky 			printf("Peer PortInfo:\n");
693d6b92ffaSHans Petter Selasky 			/* Get peer port characteristics */
694d6b92ffaSHans Petter Selasky 			peer_espeed_cap = get_port_info(&peerportid, data,
695d6b92ffaSHans Petter Selasky 							peerlocalportnum,
696d6b92ffaSHans Petter Selasky 							is_peer_switch);
697d6b92ffaSHans Petter Selasky 			if (is_mlnx_ext_port_info_supported(rem_vendorid, rem_devid))
698d6b92ffaSHans Petter Selasky 				get_mlnx_ext_port_info(&peerportid, data2,
699d6b92ffaSHans Petter Selasky 						       peerlocalportnum);
700d6b92ffaSHans Petter Selasky 			show_port_info(&peerportid, data, peerlocalportnum,
701d6b92ffaSHans Petter Selasky 				       peer_espeed_cap, is_peer_switch);
702d6b92ffaSHans Petter Selasky 			if (is_mlnx_ext_port_info_supported(rem_vendorid, rem_devid))
703d6b92ffaSHans Petter Selasky 				show_mlnx_ext_port_info(&peerportid, data2,
704d6b92ffaSHans Petter Selasky 							peerlocalportnum);
705d6b92ffaSHans Petter Selasky 
706d6b92ffaSHans Petter Selasky 			mad_decode_field(data, IB_PORT_LINK_WIDTH_ENABLED_F,
707d6b92ffaSHans Petter Selasky 					 &peerlwe);
708d6b92ffaSHans Petter Selasky 			mad_decode_field(data, IB_PORT_LINK_WIDTH_SUPPORTED_F,
709d6b92ffaSHans Petter Selasky 					 &peerlws);
710d6b92ffaSHans Petter Selasky 			mad_decode_field(data, IB_PORT_LINK_WIDTH_ACTIVE_F,
711d6b92ffaSHans Petter Selasky 					 &peerlwa);
712d6b92ffaSHans Petter Selasky 			mad_decode_field(data, IB_PORT_LINK_SPEED_SUPPORTED_F,
713d6b92ffaSHans Petter Selasky 					 &peerlss);
714d6b92ffaSHans Petter Selasky 			mad_decode_field(data, IB_PORT_LINK_SPEED_ACTIVE_F,
715d6b92ffaSHans Petter Selasky 					 &peerlsa);
716d6b92ffaSHans Petter Selasky 			mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F,
717d6b92ffaSHans Petter Selasky 					 &peerlse);
718d6b92ffaSHans Petter Selasky 			mad_decode_field(data2,
719d6b92ffaSHans Petter Selasky 					 IB_MLNX_EXT_PORT_LINK_SPEED_SUPPORTED_F,
720d6b92ffaSHans Petter Selasky 					 &peerfdr10s);
721d6b92ffaSHans Petter Selasky 			mad_decode_field(data2,
722d6b92ffaSHans Petter Selasky 					 IB_MLNX_EXT_PORT_LINK_SPEED_ENABLED_F,
723d6b92ffaSHans Petter Selasky 					 &peerfdr10e);
724d6b92ffaSHans Petter Selasky 			mad_decode_field(data2,
725d6b92ffaSHans Petter Selasky 					 IB_MLNX_EXT_PORT_LINK_SPEED_ACTIVE_F,
726d6b92ffaSHans Petter Selasky 					 &peerfdr10a);
727d6b92ffaSHans Petter Selasky 			if (peer_espeed_cap) {
728d6b92ffaSHans Petter Selasky 				mad_decode_field(data,
729d6b92ffaSHans Petter Selasky 						 IB_PORT_LINK_SPEED_EXT_SUPPORTED_F,
730d6b92ffaSHans Petter Selasky 						 &peerlses);
731d6b92ffaSHans Petter Selasky 				mad_decode_field(data,
732d6b92ffaSHans Petter Selasky 						 IB_PORT_LINK_SPEED_EXT_ACTIVE_F,
733d6b92ffaSHans Petter Selasky 						 &peerlsea);
734d6b92ffaSHans Petter Selasky 				mad_decode_field(data,
735d6b92ffaSHans Petter Selasky 						 IB_PORT_LINK_SPEED_EXT_ENABLED_F,
736d6b92ffaSHans Petter Selasky 						 &peerlsee);
737d6b92ffaSHans Petter Selasky 			}
738d6b92ffaSHans Petter Selasky 
739d6b92ffaSHans Petter Selasky 			/* Now validate peer port characteristics */
740d6b92ffaSHans Petter Selasky 			/* Examine Link Width */
741d6b92ffaSHans Petter Selasky 			width = get_link_width(lwe, lws);
742d6b92ffaSHans Petter Selasky 			peerwidth = get_link_width(peerlwe, peerlws);
743d6b92ffaSHans Petter Selasky 			validate_width(width, peerwidth, lwa);
744d6b92ffaSHans Petter Selasky 
745d6b92ffaSHans Petter Selasky 			/* Examine Link Speeds */
746d6b92ffaSHans Petter Selasky 			speed = get_link_speed(lse, lss);
747d6b92ffaSHans Petter Selasky 			peerspeed = get_link_speed(peerlse, peerlss);
748d6b92ffaSHans Petter Selasky 			validate_speed(speed, peerspeed, lsa);
749d6b92ffaSHans Petter Selasky 
750d6b92ffaSHans Petter Selasky 			if (espeed_cap && peer_espeed_cap) {
751d6b92ffaSHans Petter Selasky 				espeed = get_link_speed_ext(lsee, lses);
752d6b92ffaSHans Petter Selasky 				peerespeed = get_link_speed_ext(peerlsee,
753d6b92ffaSHans Petter Selasky 								peerlses);
754d6b92ffaSHans Petter Selasky 				validate_extended_speed(espeed, peerespeed,
755d6b92ffaSHans Petter Selasky 							lsea);
756d6b92ffaSHans Petter Selasky 			} else {
757d6b92ffaSHans Petter Selasky 				if (fdr10e & FDR10 && peerfdr10e & FDR10) {
758d6b92ffaSHans Petter Selasky 					if (!(fdr10a & FDR10))
759d6b92ffaSHans Petter Selasky 						IBWARN("Peer ports operating at active speed %d rather than FDR10", lsa);
760d6b92ffaSHans Petter Selasky 				}
761d6b92ffaSHans Petter Selasky 			}
762d6b92ffaSHans Petter Selasky 		}
763d6b92ffaSHans Petter Selasky 	}
764d6b92ffaSHans Petter Selasky 
765d6b92ffaSHans Petter Selasky close_port:
766d6b92ffaSHans Petter Selasky 	mad_rpc_close_port(srcport);
767d6b92ffaSHans Petter Selasky 	exit(0);
768d6b92ffaSHans Petter Selasky }
769