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