xref: /freebsd/sys/ofed/drivers/infiniband/util/madeye.c (revision 1866c98e64d654649d6e134c20e3e6db7823915d)
1fe267a55SPedro F. Giffuni /*-
2fe267a55SPedro F. Giffuni  * SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0
3fe267a55SPedro F. Giffuni  *
4aa0a1e58SJeff Roberson  * Copyright (c) 2004, 2005 Intel Corporation.  All rights reserved.
5aa0a1e58SJeff Roberson  * Copyright (c) 2005, 2006 Voltaire Inc.  All rights reserved.
6aa0a1e58SJeff Roberson  *
7aa0a1e58SJeff Roberson  * This software is available to you under a choice of one of two
8aa0a1e58SJeff Roberson  * licenses.  You may choose to be licensed under the terms of the GNU
9aa0a1e58SJeff Roberson  * General Public License (GPL) Version 2, available from the file
10aa0a1e58SJeff Roberson  * COPYING in the main directorY of this source tree, or the
11aa0a1e58SJeff Roberson  * OpenIB.org BSD license below:
12aa0a1e58SJeff Roberson  *
13aa0a1e58SJeff Roberson  *     Redistribution and use in source and binary forms, with or
14aa0a1e58SJeff Roberson  *     without modification, are permitted provided that the following
15aa0a1e58SJeff Roberson  *     conditions are met:
16aa0a1e58SJeff Roberson  *
17aa0a1e58SJeff Roberson  *      - Redistributions of source code must retain the above
18aa0a1e58SJeff Roberson  *        copyright notice, this list of conditions and the following
19aa0a1e58SJeff Roberson  *        disclaimer.
20aa0a1e58SJeff Roberson  *
21aa0a1e58SJeff Roberson  *      - Redistributions in binary form must reproduce the above
22aa0a1e58SJeff Roberson  *        copyright notice, this list of conditions and the following
23aa0a1e58SJeff Roberson  *        disclaimer in the documentation and/or other materials
24aa0a1e58SJeff Roberson  *        provided with the distribution.
25aa0a1e58SJeff Roberson  *
26aa0a1e58SJeff Roberson  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27aa0a1e58SJeff Roberson  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28aa0a1e58SJeff Roberson  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29aa0a1e58SJeff Roberson  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
30aa0a1e58SJeff Roberson  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
31aa0a1e58SJeff Roberson  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
32aa0a1e58SJeff Roberson  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33aa0a1e58SJeff Roberson  * SOFTWARE.
34aa0a1e58SJeff Roberson  *
35aa0a1e58SJeff Roberson  * $Id$
36aa0a1e58SJeff Roberson  */
37fa201e28SHans Petter Selasky 
38fa201e28SHans Petter Selasky #define	LINUXKPI_PARAM_PREFIX ib_madeye_
39fa201e28SHans Petter Selasky 
40aa0a1e58SJeff Roberson #include <linux/module.h>
41aa0a1e58SJeff Roberson #include <linux/device.h>
42aa0a1e58SJeff Roberson #include <linux/err.h>
43aa0a1e58SJeff Roberson 
44aa0a1e58SJeff Roberson #include <rdma/ib_mad.h>
45aa0a1e58SJeff Roberson #include <rdma/ib_smi.h>
46aa0a1e58SJeff Roberson #include <rdma/ib_sa.h>
47aa0a1e58SJeff Roberson 
48aa0a1e58SJeff Roberson MODULE_AUTHOR("Sean Hefty");
49aa0a1e58SJeff Roberson MODULE_DESCRIPTION("InfiniBand MAD viewer");
50aa0a1e58SJeff Roberson MODULE_LICENSE("Dual BSD/GPL");
51aa0a1e58SJeff Roberson 
52aa0a1e58SJeff Roberson static void madeye_remove_one(struct ib_device *device);
53aa0a1e58SJeff Roberson static void madeye_add_one(struct ib_device *device);
54aa0a1e58SJeff Roberson 
55aa0a1e58SJeff Roberson static struct ib_client madeye_client = {
56aa0a1e58SJeff Roberson 	.name   = "madeye",
57aa0a1e58SJeff Roberson 	.add    = madeye_add_one,
58aa0a1e58SJeff Roberson 	.remove = madeye_remove_one
59aa0a1e58SJeff Roberson };
60aa0a1e58SJeff Roberson 
61aa0a1e58SJeff Roberson struct madeye_port {
62aa0a1e58SJeff Roberson 	struct ib_mad_agent *smi_agent;
63aa0a1e58SJeff Roberson 	struct ib_mad_agent *gsi_agent;
64aa0a1e58SJeff Roberson };
65aa0a1e58SJeff Roberson 
66aa0a1e58SJeff Roberson static int smp = 1;
67aa0a1e58SJeff Roberson static int gmp = 1;
68aa0a1e58SJeff Roberson static int mgmt_class = 0;
69aa0a1e58SJeff Roberson static int attr_id = 0;
70aa0a1e58SJeff Roberson static int data = 0;
71aa0a1e58SJeff Roberson 
72aa0a1e58SJeff Roberson module_param(smp, int, 0444);
73aa0a1e58SJeff Roberson module_param(gmp, int, 0444);
74aa0a1e58SJeff Roberson module_param(mgmt_class, int, 0444);
75aa0a1e58SJeff Roberson module_param(attr_id, int, 0444);
76aa0a1e58SJeff Roberson module_param(data, int, 0444);
77aa0a1e58SJeff Roberson 
78aa0a1e58SJeff Roberson MODULE_PARM_DESC(smp, "Display all SMPs (default=1)");
79aa0a1e58SJeff Roberson MODULE_PARM_DESC(gmp, "Display all GMPs (default=1)");
80aa0a1e58SJeff Roberson MODULE_PARM_DESC(mgmt_class, "Display all MADs of specified class (default=0)");
81aa0a1e58SJeff Roberson MODULE_PARM_DESC(attr_id, "Display add MADs of specified attribute ID (default=0)");
82aa0a1e58SJeff Roberson MODULE_PARM_DESC(data, "Display data area of MADs (default=0)");
83aa0a1e58SJeff Roberson 
get_class_name(u8 mgmt_class)84aa0a1e58SJeff Roberson static char * get_class_name(u8 mgmt_class)
85aa0a1e58SJeff Roberson {
86aa0a1e58SJeff Roberson 	switch(mgmt_class) {
87aa0a1e58SJeff Roberson 	case IB_MGMT_CLASS_SUBN_LID_ROUTED:
88aa0a1e58SJeff Roberson 		return "LID routed SMP";
89aa0a1e58SJeff Roberson 	case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE:
90aa0a1e58SJeff Roberson 		return "Directed route SMP";
91aa0a1e58SJeff Roberson 	case IB_MGMT_CLASS_SUBN_ADM:
92aa0a1e58SJeff Roberson 		return "Subnet admin.";
93aa0a1e58SJeff Roberson 	case IB_MGMT_CLASS_PERF_MGMT:
94aa0a1e58SJeff Roberson 		return "Perf. mgmt.";
95aa0a1e58SJeff Roberson 	case IB_MGMT_CLASS_BM:
96aa0a1e58SJeff Roberson 		return "Baseboard mgmt.";
97aa0a1e58SJeff Roberson 	case IB_MGMT_CLASS_DEVICE_MGMT:
98aa0a1e58SJeff Roberson 		return "Device mgmt.";
99aa0a1e58SJeff Roberson 	case IB_MGMT_CLASS_CM:
100aa0a1e58SJeff Roberson 		return "Comm. mgmt.";
101aa0a1e58SJeff Roberson 	case IB_MGMT_CLASS_SNMP:
102aa0a1e58SJeff Roberson 		return "SNMP";
103aa0a1e58SJeff Roberson 	default:
104aa0a1e58SJeff Roberson 		return "Unknown vendor/application";
105aa0a1e58SJeff Roberson 	}
106aa0a1e58SJeff Roberson }
107aa0a1e58SJeff Roberson 
get_method_name(u8 mgmt_class,u8 method)108aa0a1e58SJeff Roberson static char * get_method_name(u8 mgmt_class, u8 method)
109aa0a1e58SJeff Roberson {
110aa0a1e58SJeff Roberson 	switch(method) {
111aa0a1e58SJeff Roberson 	case IB_MGMT_METHOD_GET:
112aa0a1e58SJeff Roberson 		return "Get";
113aa0a1e58SJeff Roberson 	case IB_MGMT_METHOD_SET:
114aa0a1e58SJeff Roberson 		return "Set";
115aa0a1e58SJeff Roberson 	case IB_MGMT_METHOD_GET_RESP:
116aa0a1e58SJeff Roberson 		return "Get response";
117aa0a1e58SJeff Roberson 	case IB_MGMT_METHOD_SEND:
118aa0a1e58SJeff Roberson 		return "Send";
119aa0a1e58SJeff Roberson 	case IB_MGMT_METHOD_SEND | IB_MGMT_METHOD_RESP:
120aa0a1e58SJeff Roberson 		return "Send response";
121aa0a1e58SJeff Roberson 	case IB_MGMT_METHOD_TRAP:
122aa0a1e58SJeff Roberson 		return "Trap";
123aa0a1e58SJeff Roberson 	case IB_MGMT_METHOD_REPORT:
124aa0a1e58SJeff Roberson 		return "Report";
125aa0a1e58SJeff Roberson 	case IB_MGMT_METHOD_REPORT_RESP:
126aa0a1e58SJeff Roberson 		return "Report response";
127aa0a1e58SJeff Roberson 	case IB_MGMT_METHOD_TRAP_REPRESS:
128aa0a1e58SJeff Roberson 		return "Trap repress";
129aa0a1e58SJeff Roberson 	default:
130aa0a1e58SJeff Roberson 		break;
131aa0a1e58SJeff Roberson 	}
132aa0a1e58SJeff Roberson 
133aa0a1e58SJeff Roberson 	switch (mgmt_class) {
134aa0a1e58SJeff Roberson 	case IB_MGMT_CLASS_SUBN_ADM:
135aa0a1e58SJeff Roberson 		switch (method) {
136aa0a1e58SJeff Roberson 		case IB_SA_METHOD_GET_TABLE:
137aa0a1e58SJeff Roberson 			return "Get table";
138aa0a1e58SJeff Roberson 		case IB_SA_METHOD_GET_TABLE_RESP:
139aa0a1e58SJeff Roberson 			return "Get table response";
140aa0a1e58SJeff Roberson 		case IB_SA_METHOD_DELETE:
141aa0a1e58SJeff Roberson 			return "Delete";
142aa0a1e58SJeff Roberson 		case IB_SA_METHOD_DELETE_RESP:
143aa0a1e58SJeff Roberson 			return "Delete response";
144aa0a1e58SJeff Roberson 		case IB_SA_METHOD_GET_MULTI:
145aa0a1e58SJeff Roberson 			return "Get Multi";
146aa0a1e58SJeff Roberson 		case IB_SA_METHOD_GET_MULTI_RESP:
147aa0a1e58SJeff Roberson 			return "Get Multi response";
148aa0a1e58SJeff Roberson 		case IB_SA_METHOD_GET_TRACE_TBL:
149aa0a1e58SJeff Roberson 			return "Get Trace Table response";
150aa0a1e58SJeff Roberson 		default:
151aa0a1e58SJeff Roberson 			break;
152aa0a1e58SJeff Roberson 		}
153aa0a1e58SJeff Roberson 	default:
154aa0a1e58SJeff Roberson 		break;
155aa0a1e58SJeff Roberson 	}
156aa0a1e58SJeff Roberson 
157aa0a1e58SJeff Roberson 	return "Unknown";
158aa0a1e58SJeff Roberson }
159aa0a1e58SJeff Roberson 
print_status_details(u16 status)160aa0a1e58SJeff Roberson static void print_status_details(u16 status)
161aa0a1e58SJeff Roberson {
162aa0a1e58SJeff Roberson 	if (status & 0x0001)
163aa0a1e58SJeff Roberson 		printk("               busy\n");
164aa0a1e58SJeff Roberson 	if (status & 0x0002)
165aa0a1e58SJeff Roberson 		printk("               redirection required\n");
166aa0a1e58SJeff Roberson 	switch((status & 0x001C) >> 2) {
167aa0a1e58SJeff Roberson 	case 1:
168aa0a1e58SJeff Roberson 		printk("               bad version\n");
169aa0a1e58SJeff Roberson 		break;
170aa0a1e58SJeff Roberson 	case 2:
171aa0a1e58SJeff Roberson 		printk("               method not supported\n");
172aa0a1e58SJeff Roberson 		break;
173aa0a1e58SJeff Roberson 	case 3:
174aa0a1e58SJeff Roberson 		printk("               method/attribute combo not supported\n");
175aa0a1e58SJeff Roberson 		break;
176aa0a1e58SJeff Roberson 	case 7:
177aa0a1e58SJeff Roberson 		printk("               invalid attribute/modifier value\n");
178aa0a1e58SJeff Roberson 		break;
179aa0a1e58SJeff Roberson 	}
180aa0a1e58SJeff Roberson }
181aa0a1e58SJeff Roberson 
get_sa_attr(__be16 attr)182aa0a1e58SJeff Roberson static char * get_sa_attr(__be16 attr)
183aa0a1e58SJeff Roberson {
184aa0a1e58SJeff Roberson 	switch(attr) {
185aa0a1e58SJeff Roberson 	case IB_SA_ATTR_CLASS_PORTINFO:
186aa0a1e58SJeff Roberson 		return "Class Port Info";
187aa0a1e58SJeff Roberson 	case IB_SA_ATTR_NOTICE:
188aa0a1e58SJeff Roberson 		return "Notice";
189aa0a1e58SJeff Roberson 	case IB_SA_ATTR_INFORM_INFO:
190aa0a1e58SJeff Roberson 		return "Inform Info";
191aa0a1e58SJeff Roberson 	case IB_SA_ATTR_NODE_REC:
192aa0a1e58SJeff Roberson 		return "Node Record";
193aa0a1e58SJeff Roberson 	case IB_SA_ATTR_PORT_INFO_REC:
194aa0a1e58SJeff Roberson 		return "PortInfo Record";
195aa0a1e58SJeff Roberson 	case IB_SA_ATTR_SL2VL_REC:
196aa0a1e58SJeff Roberson 		return "SL to VL Record";
197aa0a1e58SJeff Roberson 	case IB_SA_ATTR_SWITCH_REC:
198aa0a1e58SJeff Roberson 		return "Switch Record";
199aa0a1e58SJeff Roberson 	case IB_SA_ATTR_LINEAR_FDB_REC:
200aa0a1e58SJeff Roberson 		return "Linear FDB Record";
201aa0a1e58SJeff Roberson 	case IB_SA_ATTR_RANDOM_FDB_REC:
202aa0a1e58SJeff Roberson 		return "Random FDB Record";
203aa0a1e58SJeff Roberson 	case IB_SA_ATTR_MCAST_FDB_REC:
204aa0a1e58SJeff Roberson 		return "Multicast FDB Record";
205aa0a1e58SJeff Roberson 	case IB_SA_ATTR_SM_INFO_REC:
206aa0a1e58SJeff Roberson 		return "SM Info Record";
207aa0a1e58SJeff Roberson 	case IB_SA_ATTR_LINK_REC:
208aa0a1e58SJeff Roberson 		return "Link Record";
209aa0a1e58SJeff Roberson 	case IB_SA_ATTR_GUID_INFO_REC:
210aa0a1e58SJeff Roberson 		return "Guid Info Record";
211aa0a1e58SJeff Roberson 	case IB_SA_ATTR_SERVICE_REC:
212aa0a1e58SJeff Roberson 		return "Service Record";
213aa0a1e58SJeff Roberson 	case IB_SA_ATTR_PARTITION_REC:
214aa0a1e58SJeff Roberson 		return "Partition Record";
215aa0a1e58SJeff Roberson 	case IB_SA_ATTR_PATH_REC:
216aa0a1e58SJeff Roberson 		return "Path Record";
217aa0a1e58SJeff Roberson 	case IB_SA_ATTR_VL_ARB_REC:
218aa0a1e58SJeff Roberson 		return "VL Arb Record";
219aa0a1e58SJeff Roberson 	case IB_SA_ATTR_MC_MEMBER_REC:
220aa0a1e58SJeff Roberson 		return "MC Member Record";
221aa0a1e58SJeff Roberson 	case IB_SA_ATTR_TRACE_REC:
222aa0a1e58SJeff Roberson 		return "Trace Record";
223aa0a1e58SJeff Roberson 	case IB_SA_ATTR_MULTI_PATH_REC:
224aa0a1e58SJeff Roberson 		return "Multi Path Record";
225aa0a1e58SJeff Roberson 	case IB_SA_ATTR_SERVICE_ASSOC_REC:
226aa0a1e58SJeff Roberson 		return "Service Assoc Record";
227aa0a1e58SJeff Roberson 	case IB_SA_ATTR_INFORM_INFO_REC:
228aa0a1e58SJeff Roberson 		return "Inform Info Record";
229aa0a1e58SJeff Roberson 	default:
230aa0a1e58SJeff Roberson 		return "";
231aa0a1e58SJeff Roberson 	}
232aa0a1e58SJeff Roberson }
233aa0a1e58SJeff Roberson 
print_mad_hdr(struct ib_mad_hdr * mad_hdr)234aa0a1e58SJeff Roberson static void print_mad_hdr(struct ib_mad_hdr *mad_hdr)
235aa0a1e58SJeff Roberson {
236aa0a1e58SJeff Roberson 	printk("MAD version....0x%01x\n", mad_hdr->base_version);
237aa0a1e58SJeff Roberson 	printk("Class..........0x%01x (%s)\n", mad_hdr->mgmt_class,
238aa0a1e58SJeff Roberson 	       get_class_name(mad_hdr->mgmt_class));
239aa0a1e58SJeff Roberson 	printk("Class version..0x%01x\n", mad_hdr->class_version);
240aa0a1e58SJeff Roberson 	printk("Method.........0x%01x (%s)\n", mad_hdr->method,
241aa0a1e58SJeff Roberson 	       get_method_name(mad_hdr->mgmt_class, mad_hdr->method));
242aa0a1e58SJeff Roberson 	printk("Status.........0x%02x\n", be16_to_cpu(mad_hdr->status));
243aa0a1e58SJeff Roberson 	if (mad_hdr->status)
244aa0a1e58SJeff Roberson 		print_status_details(be16_to_cpu(mad_hdr->status));
245aa0a1e58SJeff Roberson 	printk("Class specific.0x%02x\n", be16_to_cpu(mad_hdr->class_specific));
246aa0a1e58SJeff Roberson 	printk("Trans ID.......0x%llx\n",
247aa0a1e58SJeff Roberson 		(unsigned long long)be64_to_cpu(mad_hdr->tid));
248aa0a1e58SJeff Roberson 	if (mad_hdr->mgmt_class == IB_MGMT_CLASS_SUBN_ADM)
249aa0a1e58SJeff Roberson 		printk("Attr ID........0x%02x (%s)\n",
250aa0a1e58SJeff Roberson 		       be16_to_cpu(mad_hdr->attr_id),
251aa0a1e58SJeff Roberson 		       get_sa_attr(be16_to_cpu(mad_hdr->attr_id)));
252aa0a1e58SJeff Roberson 	else
253aa0a1e58SJeff Roberson 		printk("Attr ID........0x%02x\n",
254aa0a1e58SJeff Roberson 		       be16_to_cpu(mad_hdr->attr_id));
255aa0a1e58SJeff Roberson 	printk("Attr modifier..0x%04x\n", be32_to_cpu(mad_hdr->attr_mod));
256aa0a1e58SJeff Roberson }
257aa0a1e58SJeff Roberson 
get_rmpp_type(u8 rmpp_type)258aa0a1e58SJeff Roberson static char * get_rmpp_type(u8 rmpp_type)
259aa0a1e58SJeff Roberson {
260aa0a1e58SJeff Roberson 	switch (rmpp_type) {
261aa0a1e58SJeff Roberson 	case IB_MGMT_RMPP_TYPE_DATA:
262aa0a1e58SJeff Roberson 		return "Data";
263aa0a1e58SJeff Roberson 	case IB_MGMT_RMPP_TYPE_ACK:
264aa0a1e58SJeff Roberson 		return "Ack";
265aa0a1e58SJeff Roberson 	case IB_MGMT_RMPP_TYPE_STOP:
266aa0a1e58SJeff Roberson 		return "Stop";
267aa0a1e58SJeff Roberson 	case IB_MGMT_RMPP_TYPE_ABORT:
268aa0a1e58SJeff Roberson 		return "Abort";
269aa0a1e58SJeff Roberson 	default:
270aa0a1e58SJeff Roberson 		return "Unknown";
271aa0a1e58SJeff Roberson 	}
272aa0a1e58SJeff Roberson }
273aa0a1e58SJeff Roberson 
get_rmpp_flags(u8 rmpp_flags)274aa0a1e58SJeff Roberson static char * get_rmpp_flags(u8 rmpp_flags)
275aa0a1e58SJeff Roberson {
276aa0a1e58SJeff Roberson 	if (rmpp_flags & IB_MGMT_RMPP_FLAG_ACTIVE)
277aa0a1e58SJeff Roberson 		if (rmpp_flags & IB_MGMT_RMPP_FLAG_FIRST)
278aa0a1e58SJeff Roberson 			if (rmpp_flags & IB_MGMT_RMPP_FLAG_LAST)
279aa0a1e58SJeff Roberson 				return "Active - First & Last";
280aa0a1e58SJeff Roberson 			else
281aa0a1e58SJeff Roberson 				return "Active - First";
282aa0a1e58SJeff Roberson 		else
283aa0a1e58SJeff Roberson 			if (rmpp_flags & IB_MGMT_RMPP_FLAG_LAST)
284aa0a1e58SJeff Roberson 				return "Active - Last";
285aa0a1e58SJeff Roberson 			else
286aa0a1e58SJeff Roberson 				return "Active";
287aa0a1e58SJeff Roberson 	else
288aa0a1e58SJeff Roberson 		return "Inactive";
289aa0a1e58SJeff Roberson }
290aa0a1e58SJeff Roberson 
print_rmpp_hdr(struct ib_rmpp_hdr * rmpp_hdr)291aa0a1e58SJeff Roberson static void print_rmpp_hdr(struct ib_rmpp_hdr *rmpp_hdr)
292aa0a1e58SJeff Roberson {
293aa0a1e58SJeff Roberson 	printk("RMPP version...0x%01x\n", rmpp_hdr->rmpp_version);
294aa0a1e58SJeff Roberson 	printk("RMPP type......0x%01x (%s)\n", rmpp_hdr->rmpp_type,
295aa0a1e58SJeff Roberson 	       get_rmpp_type(rmpp_hdr->rmpp_type));
296aa0a1e58SJeff Roberson 	printk("RMPP RRespTime.0x%01x\n", ib_get_rmpp_resptime(rmpp_hdr));
297aa0a1e58SJeff Roberson 	printk("RMPP flags.....0x%01x (%s)\n", ib_get_rmpp_flags(rmpp_hdr),
298aa0a1e58SJeff Roberson 	       get_rmpp_flags(ib_get_rmpp_flags(rmpp_hdr)));
299aa0a1e58SJeff Roberson 	printk("RMPP status....0x%01x\n", rmpp_hdr->rmpp_status);
300aa0a1e58SJeff Roberson 	printk("Seg number.....0x%04x\n", be32_to_cpu(rmpp_hdr->seg_num));
301aa0a1e58SJeff Roberson 	switch (rmpp_hdr->rmpp_type) {
302aa0a1e58SJeff Roberson 	case IB_MGMT_RMPP_TYPE_DATA:
303aa0a1e58SJeff Roberson 		printk("Payload len....0x%04x\n",
304aa0a1e58SJeff Roberson 		       be32_to_cpu(rmpp_hdr->paylen_newwin));
305aa0a1e58SJeff Roberson 		break;
306aa0a1e58SJeff Roberson 	case IB_MGMT_RMPP_TYPE_ACK:
307aa0a1e58SJeff Roberson 		printk("New window.....0x%04x\n",
308aa0a1e58SJeff Roberson 		       be32_to_cpu(rmpp_hdr->paylen_newwin));
309aa0a1e58SJeff Roberson 		break;
310aa0a1e58SJeff Roberson 	default:
311aa0a1e58SJeff Roberson 		printk("Data 2.........0x%04x\n",
312aa0a1e58SJeff Roberson 		       be32_to_cpu(rmpp_hdr->paylen_newwin));
313aa0a1e58SJeff Roberson 		break;
314aa0a1e58SJeff Roberson 	}
315aa0a1e58SJeff Roberson }
316aa0a1e58SJeff Roberson 
get_smp_attr(__be16 attr)317aa0a1e58SJeff Roberson static char * get_smp_attr(__be16 attr)
318aa0a1e58SJeff Roberson {
319aa0a1e58SJeff Roberson 	switch (attr) {
320aa0a1e58SJeff Roberson 	case IB_SMP_ATTR_NOTICE:
321aa0a1e58SJeff Roberson 		return "notice";
322aa0a1e58SJeff Roberson 	case IB_SMP_ATTR_NODE_DESC:
323aa0a1e58SJeff Roberson 		return "node description";
324aa0a1e58SJeff Roberson 	case IB_SMP_ATTR_NODE_INFO:
325aa0a1e58SJeff Roberson 		return "node info";
326aa0a1e58SJeff Roberson 	case IB_SMP_ATTR_SWITCH_INFO:
327aa0a1e58SJeff Roberson 		return "switch info";
328aa0a1e58SJeff Roberson 	case IB_SMP_ATTR_GUID_INFO:
329aa0a1e58SJeff Roberson 		return "GUID info";
330aa0a1e58SJeff Roberson 	case IB_SMP_ATTR_PORT_INFO:
331aa0a1e58SJeff Roberson 		return "port info";
332aa0a1e58SJeff Roberson 	case IB_SMP_ATTR_PKEY_TABLE:
333aa0a1e58SJeff Roberson 		return "pkey table";
334aa0a1e58SJeff Roberson 	case IB_SMP_ATTR_SL_TO_VL_TABLE:
335aa0a1e58SJeff Roberson 		return "SL to VL table";
336aa0a1e58SJeff Roberson 	case IB_SMP_ATTR_VL_ARB_TABLE:
337aa0a1e58SJeff Roberson 		return "VL arbitration table";
338aa0a1e58SJeff Roberson 	case IB_SMP_ATTR_LINEAR_FORWARD_TABLE:
339aa0a1e58SJeff Roberson 		return "linear forwarding table";
340aa0a1e58SJeff Roberson 	case IB_SMP_ATTR_RANDOM_FORWARD_TABLE:
341aa0a1e58SJeff Roberson 		return "random forward table";
342aa0a1e58SJeff Roberson 	case IB_SMP_ATTR_MCAST_FORWARD_TABLE:
343aa0a1e58SJeff Roberson 		return "multicast forward table";
344aa0a1e58SJeff Roberson 	case IB_SMP_ATTR_SM_INFO:
345aa0a1e58SJeff Roberson 		return "SM info";
346aa0a1e58SJeff Roberson 	case IB_SMP_ATTR_VENDOR_DIAG:
347aa0a1e58SJeff Roberson 		return "vendor diags";
348aa0a1e58SJeff Roberson 	case IB_SMP_ATTR_LED_INFO:
349aa0a1e58SJeff Roberson 		return "LED info";
350aa0a1e58SJeff Roberson 	default:
351aa0a1e58SJeff Roberson 		return "";
352aa0a1e58SJeff Roberson 	}
353aa0a1e58SJeff Roberson }
354aa0a1e58SJeff Roberson 
print_smp(struct ib_smp * smp)355aa0a1e58SJeff Roberson static void print_smp(struct ib_smp *smp)
356aa0a1e58SJeff Roberson {
357aa0a1e58SJeff Roberson 	int i;
358aa0a1e58SJeff Roberson 
359aa0a1e58SJeff Roberson 	printk("MAD version....0x%01x\n", smp->base_version);
360aa0a1e58SJeff Roberson 	printk("Class..........0x%01x (%s)\n", smp->mgmt_class,
361aa0a1e58SJeff Roberson 	       get_class_name(smp->mgmt_class));
362aa0a1e58SJeff Roberson 	printk("Class version..0x%01x\n", smp->class_version);
363aa0a1e58SJeff Roberson 	printk("Method.........0x%01x (%s)\n", smp->method,
364aa0a1e58SJeff Roberson 	       get_method_name(smp->mgmt_class, smp->method));
365aa0a1e58SJeff Roberson 	printk("Status.........0x%02x\n", be16_to_cpu(smp->status));
366aa0a1e58SJeff Roberson 	if (smp->status)
367aa0a1e58SJeff Roberson 		print_status_details(be16_to_cpu(smp->status));
368aa0a1e58SJeff Roberson 	printk("Hop pointer....0x%01x\n", smp->hop_ptr);
369aa0a1e58SJeff Roberson 	printk("Hop counter....0x%01x\n", smp->hop_cnt);
370aa0a1e58SJeff Roberson 	printk("Trans ID.......0x%llx\n",
371aa0a1e58SJeff Roberson 		(unsigned long long)be64_to_cpu(smp->tid));
372aa0a1e58SJeff Roberson 	printk("Attr ID........0x%02x (%s)\n", be16_to_cpu(smp->attr_id),
373aa0a1e58SJeff Roberson 		get_smp_attr(smp->attr_id));
374aa0a1e58SJeff Roberson 	printk("Attr modifier..0x%04x\n", be32_to_cpu(smp->attr_mod));
375aa0a1e58SJeff Roberson 
376aa0a1e58SJeff Roberson 	printk("Mkey...........0x%llx\n",
377aa0a1e58SJeff Roberson 		(unsigned long long)be64_to_cpu(smp->mkey));
378aa0a1e58SJeff Roberson 	printk("DR SLID........0x%02x\n", be16_to_cpu(smp->dr_slid));
379aa0a1e58SJeff Roberson 	printk("DR DLID........0x%02x", be16_to_cpu(smp->dr_dlid));
380aa0a1e58SJeff Roberson 
381aa0a1e58SJeff Roberson 	if (data) {
382aa0a1e58SJeff Roberson 		for (i = 0; i < IB_SMP_DATA_SIZE; i++) {
383aa0a1e58SJeff Roberson 			if (i % 16 == 0)
384aa0a1e58SJeff Roberson 				printk("\nSMP Data.......");
385aa0a1e58SJeff Roberson 			printk("%01x ", smp->data[i]);
386aa0a1e58SJeff Roberson 		}
387aa0a1e58SJeff Roberson 		for (i = 0; i < IB_SMP_MAX_PATH_HOPS; i++) {
388aa0a1e58SJeff Roberson 			if (i % 16 == 0)
389aa0a1e58SJeff Roberson 				printk("\nInitial path...");
390aa0a1e58SJeff Roberson 			printk("%01x ", smp->initial_path[i]);
391aa0a1e58SJeff Roberson 		}
392aa0a1e58SJeff Roberson 		for (i = 0; i < IB_SMP_MAX_PATH_HOPS; i++) {
393aa0a1e58SJeff Roberson 			if (i % 16 == 0)
394aa0a1e58SJeff Roberson 				printk("\nReturn path....");
395aa0a1e58SJeff Roberson 			printk("%01x ", smp->return_path[i]);
396aa0a1e58SJeff Roberson 		}
397aa0a1e58SJeff Roberson 	}
398aa0a1e58SJeff Roberson 	printk("\n");
399aa0a1e58SJeff Roberson }
400aa0a1e58SJeff Roberson 
snoop_smi_handler(struct ib_mad_agent * mad_agent,struct ib_mad_send_buf * send_buf,struct ib_mad_send_wc * mad_send_wc)401aa0a1e58SJeff Roberson static void snoop_smi_handler(struct ib_mad_agent *mad_agent,
402aa0a1e58SJeff Roberson 			      struct ib_mad_send_buf *send_buf,
403aa0a1e58SJeff Roberson 			      struct ib_mad_send_wc *mad_send_wc)
404aa0a1e58SJeff Roberson {
405aa0a1e58SJeff Roberson 	struct ib_mad_hdr *hdr = send_buf->mad;
406aa0a1e58SJeff Roberson 
407aa0a1e58SJeff Roberson 	if (!smp && hdr->mgmt_class != mgmt_class)
408aa0a1e58SJeff Roberson 		return;
409aa0a1e58SJeff Roberson 	if (attr_id && be16_to_cpu(hdr->attr_id) != attr_id)
410aa0a1e58SJeff Roberson 		return;
411aa0a1e58SJeff Roberson 
412aa0a1e58SJeff Roberson 	printk("Madeye:sent SMP\n");
413aa0a1e58SJeff Roberson 	print_smp(send_buf->mad);
414aa0a1e58SJeff Roberson }
415aa0a1e58SJeff Roberson 
recv_smi_handler(struct ib_mad_agent * mad_agent,struct ib_mad_recv_wc * mad_recv_wc)416aa0a1e58SJeff Roberson static void recv_smi_handler(struct ib_mad_agent *mad_agent,
417aa0a1e58SJeff Roberson 			     struct ib_mad_recv_wc *mad_recv_wc)
418aa0a1e58SJeff Roberson {
419aa0a1e58SJeff Roberson 	if (!smp && mad_recv_wc->recv_buf.mad->mad_hdr.mgmt_class != mgmt_class)
420aa0a1e58SJeff Roberson 		return;
421aa0a1e58SJeff Roberson 	if (attr_id && be16_to_cpu(mad_recv_wc->recv_buf.mad->mad_hdr.attr_id) != attr_id)
422aa0a1e58SJeff Roberson 		return;
423aa0a1e58SJeff Roberson 
424aa0a1e58SJeff Roberson 	printk("Madeye:recv SMP\n");
425aa0a1e58SJeff Roberson 	print_smp((struct ib_smp *)&mad_recv_wc->recv_buf.mad->mad_hdr);
426aa0a1e58SJeff Roberson }
427aa0a1e58SJeff Roberson 
is_rmpp_mad(struct ib_mad_hdr * mad_hdr)428aa0a1e58SJeff Roberson static int is_rmpp_mad(struct ib_mad_hdr *mad_hdr)
429aa0a1e58SJeff Roberson {
430aa0a1e58SJeff Roberson 	if (mad_hdr->mgmt_class == IB_MGMT_CLASS_SUBN_ADM) {
431aa0a1e58SJeff Roberson 		switch (mad_hdr->method) {
432aa0a1e58SJeff Roberson 		case IB_SA_METHOD_GET_TABLE:
433aa0a1e58SJeff Roberson 		case IB_SA_METHOD_GET_TABLE_RESP:
434aa0a1e58SJeff Roberson 		case IB_SA_METHOD_GET_MULTI_RESP:
435aa0a1e58SJeff Roberson 			return 1;
436aa0a1e58SJeff Roberson 		default:
437aa0a1e58SJeff Roberson 			break;
438aa0a1e58SJeff Roberson 		}
439aa0a1e58SJeff Roberson 	} else if ((mad_hdr->mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) &&
440aa0a1e58SJeff Roberson 		   (mad_hdr->mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END))
441aa0a1e58SJeff Roberson 		return 1;
442aa0a1e58SJeff Roberson 
443aa0a1e58SJeff Roberson 	return 0;
444aa0a1e58SJeff Roberson }
445aa0a1e58SJeff Roberson 
snoop_gsi_handler(struct ib_mad_agent * mad_agent,struct ib_mad_send_buf * send_buf,struct ib_mad_send_wc * mad_send_wc)446aa0a1e58SJeff Roberson static void snoop_gsi_handler(struct ib_mad_agent *mad_agent,
447aa0a1e58SJeff Roberson 			      struct ib_mad_send_buf *send_buf,
448aa0a1e58SJeff Roberson 			      struct ib_mad_send_wc *mad_send_wc)
449aa0a1e58SJeff Roberson {
450aa0a1e58SJeff Roberson 	struct ib_mad_hdr *hdr = send_buf->mad;
451aa0a1e58SJeff Roberson 
452aa0a1e58SJeff Roberson 	if (!gmp && hdr->mgmt_class != mgmt_class)
453aa0a1e58SJeff Roberson 		return;
454aa0a1e58SJeff Roberson 	if (attr_id && be16_to_cpu(hdr->attr_id) != attr_id)
455aa0a1e58SJeff Roberson 		return;
456aa0a1e58SJeff Roberson 
457aa0a1e58SJeff Roberson 	printk("Madeye:sent GMP\n");
458aa0a1e58SJeff Roberson 	print_mad_hdr(hdr);
459aa0a1e58SJeff Roberson 
460aa0a1e58SJeff Roberson 	if (is_rmpp_mad(hdr))
461aa0a1e58SJeff Roberson 		print_rmpp_hdr(&((struct ib_rmpp_mad *) hdr)->rmpp_hdr);
462aa0a1e58SJeff Roberson }
463aa0a1e58SJeff Roberson 
recv_gsi_handler(struct ib_mad_agent * mad_agent,struct ib_mad_recv_wc * mad_recv_wc)464aa0a1e58SJeff Roberson static void recv_gsi_handler(struct ib_mad_agent *mad_agent,
465aa0a1e58SJeff Roberson 			     struct ib_mad_recv_wc *mad_recv_wc)
466aa0a1e58SJeff Roberson {
467aa0a1e58SJeff Roberson 	struct ib_mad_hdr *hdr = &mad_recv_wc->recv_buf.mad->mad_hdr;
468aa0a1e58SJeff Roberson 	struct ib_rmpp_mad *mad = NULL;
469aa0a1e58SJeff Roberson 	struct ib_sa_mad *sa_mad;
470aa0a1e58SJeff Roberson 	struct ib_vendor_mad *vendor_mad;
471aa0a1e58SJeff Roberson 	u8 *mad_data;
472aa0a1e58SJeff Roberson 	int i, j;
473aa0a1e58SJeff Roberson 
474aa0a1e58SJeff Roberson 	if (!gmp && hdr->mgmt_class != mgmt_class)
475aa0a1e58SJeff Roberson 		return;
476aa0a1e58SJeff Roberson 	if (attr_id && be16_to_cpu(mad_recv_wc->recv_buf.mad->mad_hdr.attr_id) != attr_id)
477aa0a1e58SJeff Roberson 		return;
478aa0a1e58SJeff Roberson 
479aa0a1e58SJeff Roberson 	printk("Madeye:recv GMP\n");
480aa0a1e58SJeff Roberson 	print_mad_hdr(hdr);
481aa0a1e58SJeff Roberson 
482aa0a1e58SJeff Roberson 	if (is_rmpp_mad(hdr)) {
483aa0a1e58SJeff Roberson 		mad = (struct ib_rmpp_mad *) hdr;
484aa0a1e58SJeff Roberson 		print_rmpp_hdr(&mad->rmpp_hdr);
485aa0a1e58SJeff Roberson 	}
486aa0a1e58SJeff Roberson 
487aa0a1e58SJeff Roberson 	if (data) {
488aa0a1e58SJeff Roberson 		if (hdr->mgmt_class == IB_MGMT_CLASS_SUBN_ADM) {
489aa0a1e58SJeff Roberson 			j = IB_MGMT_SA_DATA;
490aa0a1e58SJeff Roberson 			/* Display SA header */
491aa0a1e58SJeff Roberson 			if (is_rmpp_mad(hdr) &&
492aa0a1e58SJeff Roberson 			    mad->rmpp_hdr.rmpp_type != IB_MGMT_RMPP_TYPE_DATA)
493aa0a1e58SJeff Roberson 				return;
494aa0a1e58SJeff Roberson 			sa_mad = (struct ib_sa_mad *)
495aa0a1e58SJeff Roberson 				 &mad_recv_wc->recv_buf.mad;
496aa0a1e58SJeff Roberson 			mad_data = sa_mad->data;
497aa0a1e58SJeff Roberson 		} else {
498aa0a1e58SJeff Roberson 			if (is_rmpp_mad(hdr)) {
499aa0a1e58SJeff Roberson 				j = IB_MGMT_VENDOR_DATA;
500aa0a1e58SJeff Roberson 				/* Display OUI */
501aa0a1e58SJeff Roberson 				vendor_mad = (struct ib_vendor_mad *)
502aa0a1e58SJeff Roberson 					     &mad_recv_wc->recv_buf.mad;
503aa0a1e58SJeff Roberson 				printk("Vendor OUI......%01x %01x %01x\n",
504aa0a1e58SJeff Roberson 					vendor_mad->oui[0],
505aa0a1e58SJeff Roberson 					vendor_mad->oui[1],
506aa0a1e58SJeff Roberson 					vendor_mad->oui[2]);
507aa0a1e58SJeff Roberson 				mad_data = vendor_mad->data;
508aa0a1e58SJeff Roberson 			} else {
509aa0a1e58SJeff Roberson 				j = IB_MGMT_MAD_DATA;
510aa0a1e58SJeff Roberson 				mad_data = mad_recv_wc->recv_buf.mad->data;
511aa0a1e58SJeff Roberson 			}
512aa0a1e58SJeff Roberson 		}
513aa0a1e58SJeff Roberson 		for (i = 0; i < j; i++) {
514aa0a1e58SJeff Roberson 			if (i % 16 == 0)
515aa0a1e58SJeff Roberson 				printk("\nData...........");
516aa0a1e58SJeff Roberson 			printk("%01x ", mad_data[i]);
517aa0a1e58SJeff Roberson 		}
518aa0a1e58SJeff Roberson 		printk("\n");
519aa0a1e58SJeff Roberson 	}
520aa0a1e58SJeff Roberson }
521aa0a1e58SJeff Roberson 
madeye_add_one(struct ib_device * device)522aa0a1e58SJeff Roberson static void madeye_add_one(struct ib_device *device)
523aa0a1e58SJeff Roberson {
524aa0a1e58SJeff Roberson 	struct madeye_port *port;
525aa0a1e58SJeff Roberson 	int reg_flags;
526aa0a1e58SJeff Roberson 	u8 i, s, e;
527aa0a1e58SJeff Roberson 
528aa0a1e58SJeff Roberson 	if (device->node_type == RDMA_NODE_IB_SWITCH) {
529aa0a1e58SJeff Roberson 		s = 0;
530aa0a1e58SJeff Roberson 		e = 0;
531aa0a1e58SJeff Roberson 	} else {
532aa0a1e58SJeff Roberson 		s = 1;
533aa0a1e58SJeff Roberson 		e = device->phys_port_cnt;
534aa0a1e58SJeff Roberson 	}
535aa0a1e58SJeff Roberson 
536aa0a1e58SJeff Roberson 	port = kmalloc(sizeof *port * (e - s + 1), GFP_KERNEL);
537aa0a1e58SJeff Roberson 	if (!port)
538aa0a1e58SJeff Roberson 		goto out;
539aa0a1e58SJeff Roberson 
540aa0a1e58SJeff Roberson 	reg_flags = IB_MAD_SNOOP_SEND_COMPLETIONS | IB_MAD_SNOOP_RECVS;
541aa0a1e58SJeff Roberson 	for (i = 0; i <= e - s; i++) {
542aa0a1e58SJeff Roberson 		port[i].smi_agent = ib_register_mad_snoop(device, i + s,
543aa0a1e58SJeff Roberson 							  IB_QPT_SMI,
544aa0a1e58SJeff Roberson 							  reg_flags,
545aa0a1e58SJeff Roberson 							  snoop_smi_handler,
546aa0a1e58SJeff Roberson 							  recv_smi_handler,
547aa0a1e58SJeff Roberson 							  &port[i]);
548aa0a1e58SJeff Roberson 		port[i].gsi_agent = ib_register_mad_snoop(device, i + s,
549aa0a1e58SJeff Roberson 							  IB_QPT_GSI,
550aa0a1e58SJeff Roberson 							  reg_flags,
551aa0a1e58SJeff Roberson 							  snoop_gsi_handler,
552aa0a1e58SJeff Roberson 							  recv_gsi_handler,
553aa0a1e58SJeff Roberson 							  &port[i]);
554aa0a1e58SJeff Roberson 	}
555aa0a1e58SJeff Roberson 
556aa0a1e58SJeff Roberson out:
557aa0a1e58SJeff Roberson 	ib_set_client_data(device, &madeye_client, port);
558aa0a1e58SJeff Roberson }
559aa0a1e58SJeff Roberson 
madeye_remove_one(struct ib_device * device)560aa0a1e58SJeff Roberson static void madeye_remove_one(struct ib_device *device)
561aa0a1e58SJeff Roberson {
562aa0a1e58SJeff Roberson 	struct madeye_port *port;
563aa0a1e58SJeff Roberson 	int i, s, e;
564aa0a1e58SJeff Roberson 
565aa0a1e58SJeff Roberson 	port = (struct madeye_port *)
566aa0a1e58SJeff Roberson 		ib_get_client_data(device, &madeye_client);
567aa0a1e58SJeff Roberson 	if (!port)
568aa0a1e58SJeff Roberson 		return;
569aa0a1e58SJeff Roberson 
570aa0a1e58SJeff Roberson 	if (device->node_type == RDMA_NODE_IB_SWITCH) {
571aa0a1e58SJeff Roberson 		s = 0;
572aa0a1e58SJeff Roberson 		e = 0;
573aa0a1e58SJeff Roberson 	} else {
574aa0a1e58SJeff Roberson 		s = 1;
575aa0a1e58SJeff Roberson 		e = device->phys_port_cnt;
576aa0a1e58SJeff Roberson 	}
577aa0a1e58SJeff Roberson 
578aa0a1e58SJeff Roberson 	for (i = 0; i <= e - s; i++) {
579aa0a1e58SJeff Roberson 		if (!IS_ERR(port[i].smi_agent))
580aa0a1e58SJeff Roberson 			ib_unregister_mad_agent(port[i].smi_agent);
581aa0a1e58SJeff Roberson 		if (!IS_ERR(port[i].gsi_agent))
582aa0a1e58SJeff Roberson 			ib_unregister_mad_agent(port[i].gsi_agent);
583aa0a1e58SJeff Roberson 	}
584aa0a1e58SJeff Roberson 	kfree(port);
585aa0a1e58SJeff Roberson }
586aa0a1e58SJeff Roberson 
ib_madeye_init(void)587aa0a1e58SJeff Roberson static int __init ib_madeye_init(void)
588aa0a1e58SJeff Roberson {
589aa0a1e58SJeff Roberson 	return ib_register_client(&madeye_client);
590aa0a1e58SJeff Roberson }
591aa0a1e58SJeff Roberson 
ib_madeye_cleanup(void)592aa0a1e58SJeff Roberson static void __exit ib_madeye_cleanup(void)
593aa0a1e58SJeff Roberson {
594aa0a1e58SJeff Roberson 	ib_unregister_client(&madeye_client);
595aa0a1e58SJeff Roberson }
596aa0a1e58SJeff Roberson 
597*1866c98eSHans Petter Selasky module_init_order(ib_madeye_init, SI_ORDER_THIRD);
598*1866c98eSHans Petter Selasky module_exit_order(ib_madeye_cleanup, SI_ORDER_THIRD);
599