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