infiniband-diags: initial port of linux ib diags
[mirror/winof/.git] / tools / infiniband_diags / src / vendstat.c
1 /*\r
2  * Copyright (c) 2004-2008 Voltaire Inc.  All rights reserved.\r
3  *\r
4  * This software is available to you under a choice of one of two\r
5  * licenses.  You may choose to be licensed under the terms of the GNU\r
6  * General Public License (GPL) Version 2, available from the file\r
7  * COPYING in the main directory of this source tree, or the\r
8  * OpenIB.org BSD license below:\r
9  *\r
10  *     Redistribution and use in source and binary forms, with or\r
11  *     without modification, are permitted provided that the following\r
12  *     conditions are met:\r
13  *\r
14  *      - Redistributions of source code must retain the above\r
15  *        copyright notice, this list of conditions and the following\r
16  *        disclaimer.\r
17  *\r
18  *      - Redistributions in binary form must reproduce the above\r
19  *        copyright notice, this list of conditions and the following\r
20  *        disclaimer in the documentation and/or other materials\r
21  *        provided with the distribution.\r
22  *\r
23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
24  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
25  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
26  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
27  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
28  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
29  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
30  * SOFTWARE.\r
31  *\r
32  */\r
33 \r
34 #if HAVE_CONFIG_H\r
35 #  include <config.h>\r
36 #endif /* HAVE_CONFIG_H */\r
37 \r
38 #include <stdio.h>\r
39 #include <stdlib.h>\r
40 #if defined(_WIN32) \r
41 #include <windows.h>\r
42 #include <winsock2.h>\r
43 #include "..\..\..\..\etc\user\getopt.c"\r
44 #else\r
45 #include <unistd.h>\r
46 #include <stdarg.h>\r
47 #include <getopt.h>\r
48 #include <netinet/in.h>\r
49 #endif\r
50 \r
51 #include <infiniband/umad.h>\r
52 #include <infiniband/mad.h>\r
53 \r
54 #include "ibdiag_common.h"\r
55 \r
56 #define IS3_DEVICE_ID                   47396\r
57 \r
58 #define IB_MLX_VENDOR_CLASS             10\r
59 /* Vendor specific Attribute IDs */\r
60 #define IB_MLX_IS3_GENERAL_INFO         0x17\r
61 #define IB_MLX_IS3_CONFIG_SPACE_ACCESS  0x50\r
62 /* Config space addresses */\r
63 #define IB_MLX_IS3_PORT_XMIT_WAIT       0x10013C\r
64 \r
65 char *argv0 = "vendstat";\r
66 \r
67 typedef struct {\r
68         uint16_t hw_revision;\r
69         uint16_t device_id;\r
70         uint8_t  reserved[24];\r
71         uint32_t uptime;\r
72 } is3_hw_info_t;\r
73 \r
74 typedef struct {\r
75         uint8_t resv1;\r
76         uint8_t major;\r
77         uint8_t minor;\r
78         uint8_t sub_minor;\r
79         uint32_t build_id;\r
80         uint8_t month;\r
81         uint8_t day;\r
82         uint16_t year;\r
83         uint16_t resv2;\r
84         uint16_t hour;\r
85         uint8_t psid[16];\r
86         uint32_t ini_file_version;\r
87 } is3_fw_info_t;\r
88 \r
89 typedef struct {\r
90         uint8_t resv1;\r
91         uint8_t major;\r
92         uint8_t minor;\r
93         uint8_t sub_minor;\r
94         uint8_t resv2[28];\r
95 } is3_sw_info_t;\r
96 \r
97 typedef struct {\r
98         uint8_t       reserved[8];\r
99         is3_hw_info_t hw_info;\r
100         is3_fw_info_t fw_info;\r
101         is3_sw_info_t sw_info;\r
102 } is3_general_info_t;\r
103 \r
104 typedef struct {\r
105         uint32_t address;\r
106         uint32_t data;\r
107         uint32_t mask;\r
108 } is3_record_t;\r
109 \r
110 typedef struct {\r
111         uint8_t      reserved[8];\r
112         is3_record_t record[18];\r
113 } is3_config_space_t;\r
114 \r
115 static void\r
116 usage(void)\r
117 {\r
118         char *basename;\r
119 \r
120         if (!(basename = strrchr(argv0, '/')))\r
121                 basename = argv0;\r
122         else\r
123                 basename++;\r
124 \r
125         fprintf(stderr, "Usage: %s [-d(ebug) -N -w -G(uid) -C ca_name -P ca_port "\r
126                         "-t(imeout) timeout_ms -V(ersion) -h(elp)] <lid|guid>\n",\r
127                         basename);\r
128         fprintf(stderr, "\tExamples:\n");\r
129         fprintf(stderr, "\t\t%s -N 6\t\t# read IS3 general information\n", basename);\r
130         fprintf(stderr, "\t\t%s -w 6\t\t# read IS3 port xmit wait counters\n", basename);\r
131         exit(-1);\r
132 }\r
133 \r
134 int __cdecl\r
135 main(int argc, char **argv)\r
136 {\r
137         int mgmt_classes[4] = {IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS, IB_MLX_VENDOR_CLASS};\r
138         ib_portid_t *sm_id = 0, sm_portid = {0};\r
139         ib_portid_t portid = {0};\r
140         extern int ibdebug;\r
141         int dest_type = IB_DEST_LID;\r
142         int timeout = 0;        /* use default */\r
143         int port = 0;\r
144         char buf[1024];\r
145         int udebug = 0;\r
146         char *ca = 0;\r
147         int ca_port = 0;\r
148         ib_vendor_call_t call;\r
149         is3_general_info_t *gi;\r
150         is3_config_space_t *cs;\r
151         int general_info = 0;\r
152         int xmit_wait = 0;\r
153         int i;\r
154 \r
155         static char str_opts[] = "C:P:s:t:dNwGVhu";\r
156         static struct option long_opts[] = {\r
157                 { "C", 1, 0, 'C'},\r
158                 { "P", 1, 0, 'P'},\r
159                 { "N", 1, 0, 'N'},\r
160                 { "w", 1, 0, 'w'},\r
161                 { "debug", 0, 0, 'd'},\r
162                 { "Guid", 0, 0, 'G'},\r
163                 { "sm_portid", 1, 0, 's'},\r
164                 { "timeout", 1, 0, 't'},\r
165                 { "Version", 0, 0, 'V'},\r
166                 { "help", 0, 0, 'h'},\r
167                 { "usage", 0, 0, 'u'},\r
168                 { 0 }\r
169         };\r
170 \r
171         argv0 = argv[0];\r
172 \r
173         while (1) {\r
174                 int ch = getopt_long(argc, argv, str_opts, long_opts, NULL);\r
175                 if ( ch == -1 )\r
176                         break;\r
177                 switch(ch) {\r
178                 case 'C':\r
179                         ca = optarg;\r
180                         break;\r
181                 case 'P':\r
182                         ca_port = strtoul(optarg, 0, 0);\r
183                         break;\r
184                 case 'N':\r
185                         general_info = 1;\r
186                         break;\r
187                 case 'w':\r
188                         xmit_wait = 1;\r
189                         break;\r
190                 case 'd':\r
191                         ibdebug++;\r
192                         madrpc_show_errors(1);\r
193                         umad_debug(udebug);\r
194                         udebug++;\r
195                         break;\r
196                 case 'G':\r
197                         dest_type = IB_DEST_GUID;\r
198                         break;\r
199                 case 's':\r
200                         if (ib_resolve_portid_str(&sm_portid, optarg, IB_DEST_LID, 0) < 0)\r
201                                 IBERROR("can't resolve SM destination port %s", optarg);\r
202                         sm_id = &sm_portid;\r
203                         break;\r
204                 case 't':\r
205                         timeout = strtoul(optarg, 0, 0);\r
206                         madrpc_set_timeout(timeout);\r
207                         break;\r
208                 case 'V':\r
209                         fprintf(stderr, "%s %s\n", argv0, get_build_version() );\r
210                         exit(-1);\r
211                 default:\r
212                         usage();\r
213                         break;\r
214                 }\r
215         }\r
216         argc -= optind;\r
217         argv += optind;\r
218 \r
219         if (argc > 1)\r
220                 port = strtoul(argv[1], 0, 0);\r
221 \r
222         madrpc_init(ca, ca_port, mgmt_classes, 4);\r
223 \r
224         if (argc) {\r
225                 if (ib_resolve_portid_str(&portid, argv[0], dest_type, sm_id) < 0)\r
226                         IBERROR("can't resolve destination port %s", argv[0]);\r
227         } else {\r
228                 if (ib_resolve_self(&portid, &port, 0) < 0)\r
229                         IBERROR("can't resolve self port %s", argv[0]);\r
230         }\r
231 \r
232         /* Only General Info and Port Xmit Wait Counters */\r
233         /* queries are currently supported */\r
234         if (!general_info && !xmit_wait)\r
235                 IBERROR("at least one of -N and -w must be specified");\r
236 \r
237         /* These are Mellanox specific vendor MADs */\r
238         /* but vendors change the VendorId so how know for sure ? */\r
239         /* Would need a list of these and it might not be complete */\r
240         /* so for right now, punt on this */\r
241 \r
242         memset(&call, 0, sizeof(call));\r
243         call.mgmt_class = IB_MLX_VENDOR_CLASS;\r
244         call.method = IB_MAD_METHOD_GET;\r
245         call.timeout = timeout;\r
246 \r
247         memset(&buf, 0, sizeof(buf));\r
248         /* vendor ClassPortInfo is required attribute if class supported */\r
249         call.attrid = CLASS_PORT_INFO;\r
250         if (!ib_vendor_call(&buf, &portid, &call))\r
251                 IBERROR("classportinfo query");\r
252 \r
253         memset(&buf, 0, sizeof(buf));\r
254         call.attrid = IB_MLX_IS3_GENERAL_INFO;\r
255         if (!ib_vendor_call(&buf, &portid, &call))\r
256                 IBERROR("vendstat");\r
257         gi = (is3_general_info_t *)&buf;\r
258 \r
259         if (general_info) {\r
260                 /* dump IS3 general info here */\r
261                 printf("hw_dev_rev:  0x%04x\n", ntohs(gi->hw_info.hw_revision));\r
262                 printf("hw_dev_id:   0x%04x\n", ntohs(gi->hw_info.device_id));\r
263                 printf("hw_uptime:   0x%08x\n", ntohl(gi->hw_info.uptime));\r
264                 printf("fw_version:  %02d.%02d.%02d\n",\r
265                        gi->fw_info.major, gi->fw_info.minor, gi->fw_info.sub_minor);\r
266                 printf("fw_build_id: 0x%04x\n", ntohl(gi->fw_info.build_id));\r
267                 printf("fw_date:     %02d/%02d/%04x\n",\r
268                        gi->fw_info.month, gi->fw_info.day, ntohs(gi->fw_info.year));\r
269                 printf("fw_psid:     '%s'\n", gi->fw_info.psid);\r
270                 printf("fw_ini_ver:  %d\n", ntohl(gi->fw_info.ini_file_version));\r
271                 printf("sw_version:  %02d.%02d.%02d\n",\r
272                        gi->sw_info.major, gi->sw_info.minor, gi->sw_info.sub_minor);\r
273         }\r
274 \r
275         if (xmit_wait) {\r
276                 if (ntohs(gi->hw_info.device_id) != IS3_DEVICE_ID)\r
277                         IBERROR("Unsupported device ID 0x%x", ntohs(gi->hw_info.device_id));\r
278 \r
279                 memset(&buf, 0, sizeof(buf));\r
280                 call.attrid = IB_MLX_IS3_CONFIG_SPACE_ACCESS;\r
281                 /* Limit of 18 accesses per MAD ? */\r
282                 call.mod = 2 << 22 | 16 << 16; /* 16 records */\r
283                 /* Set record addresses for each port */\r
284                 cs = (is3_config_space_t *)&buf;\r
285                 for (i = 0; i < 16; i++)\r
286                         cs->record[i].address = htonl(IB_MLX_IS3_PORT_XMIT_WAIT + ((i + 1) << 12));\r
287                 if (!ib_vendor_call(&buf, &portid, &call))\r
288                         IBERROR("vendstat");\r
289 \r
290                 for (i = 0; i < 16; i++)\r
291                         if (cs->record[i].data) /* PortXmitWait is 32 bit counter */\r
292                                 printf("Port %d: PortXmitWait 0x%x\n", i + 4, ntohl(cs->record[i].data)); /* port 4 is first port */\r
293 \r
294                 /* Last 8 ports is another query */\r
295                 memset(&buf, 0, sizeof(buf));\r
296                 call.attrid = IB_MLX_IS3_CONFIG_SPACE_ACCESS;\r
297                 call.mod = 2 << 22 | 8 << 16; /* 8 records */\r
298                 /* Set record addresses for each port */\r
299                 cs = (is3_config_space_t *)&buf;\r
300                 for (i = 0; i < 8; i++)\r
301                         cs->record[i].address = htonl(IB_MLX_IS3_PORT_XMIT_WAIT + ((i + 17) << 12));\r
302                 if (!ib_vendor_call(&buf, &portid, &call))\r
303                         IBERROR("vendstat");\r
304 \r
305                 for (i = 0; i < 8; i++)\r
306                         if (cs->record[i].data) /* PortXmitWait is 32 bit counter */\r
307                                 printf("Port %d: PortXmitWait 0x%x\n",\r
308                                        i < 4 ? i + 21 : i - 3,\r
309                                        ntohl(cs->record[i].data));\r
310         }\r
311 \r
312         exit(0);\r
313 }\r