]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/ofed/infiniband-diags/src/perfquery.c
Merge compiler-rt trunk r366426, resolve conflicts, and add
[FreeBSD/FreeBSD.git] / contrib / ofed / infiniband-diags / src / perfquery.c
1 /*
2  * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
3  * Copyright (c) 2007 Xsigo Systems Inc.  All rights reserved.
4  * Copyright (c) 2009 HNR Consulting.  All rights reserved.
5  * Copyright (c) 2011 Mellanox Technologies LTD.  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  */
36
37 #if HAVE_CONFIG_H
38 #  include <config.h>
39 #endif                          /* HAVE_CONFIG_H */
40
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <unistd.h>
44 #include <getopt.h>
45 #include <netinet/in.h>
46
47 #include <infiniband/umad.h>
48 #include <infiniband/mad.h>
49 #include <infiniband/iba/ib_types.h>
50
51 #include "ibdiag_common.h"
52
53 struct ibmad_port *srcport;
54
55 static ibmad_gid_t dgid;
56 static int with_grh;
57
58 struct perf_count {
59         uint32_t portselect;
60         uint32_t counterselect;
61         uint32_t symbolerrors;
62         uint32_t linkrecovers;
63         uint32_t linkdowned;
64         uint32_t rcverrors;
65         uint32_t rcvremotephyerrors;
66         uint32_t rcvswrelayerrors;
67         uint32_t xmtdiscards;
68         uint32_t xmtconstrainterrors;
69         uint32_t rcvconstrainterrors;
70         uint32_t linkintegrityerrors;
71         uint32_t excbufoverrunerrors;
72         uint32_t qp1dropped;
73         uint32_t vl15dropped;
74         uint32_t xmtdata;
75         uint32_t rcvdata;
76         uint32_t xmtpkts;
77         uint32_t rcvpkts;
78         uint32_t xmtwait;
79 };
80
81 struct perf_count_ext {
82         uint32_t portselect;
83         uint32_t counterselect;
84         uint64_t portxmitdata;
85         uint64_t portrcvdata;
86         uint64_t portxmitpkts;
87         uint64_t portrcvpkts;
88         uint64_t portunicastxmitpkts;
89         uint64_t portunicastrcvpkts;
90         uint64_t portmulticastxmitpkits;
91         uint64_t portmulticastrcvpkts;
92
93         uint32_t counterSelect2;
94         uint64_t symbolErrorCounter;
95         uint64_t linkErrorRecoveryCounter;
96         uint64_t linkDownedCounter;
97         uint64_t portRcvErrors;
98         uint64_t portRcvRemotePhysicalErrors;
99         uint64_t portRcvSwitchRelayErrors;
100         uint64_t portXmitDiscards;
101         uint64_t portXmitConstraintErrors;
102         uint64_t portRcvConstraintErrors;
103         uint64_t localLinkIntegrityErrors;
104         uint64_t excessiveBufferOverrunErrors;
105         uint64_t VL15Dropped;
106         uint64_t portXmitWait;
107         uint64_t QP1Dropped;
108 };
109
110 static uint8_t pc[1024];
111
112 struct perf_count perf_count = {0};
113 struct perf_count_ext perf_count_ext = {0};
114
115 #define ALL_PORTS 0xFF
116 #define MAX_PORTS 255
117
118 /* Notes: IB semantics is to cap counters if count has exceeded limits.
119  * Therefore we must check for overflows and cap the counters if necessary.
120  *
121  * mad_decode_field and mad_encode_field assume 32 bit integers passed in
122  * for fields < 32 bits in length.
123  */
124
125 static void aggregate_4bit(uint32_t * dest, uint32_t val)
126 {
127         if ((((*dest) + val) < (*dest)) || ((*dest) + val) > 0xf)
128                 (*dest) = 0xf;
129         else
130                 (*dest) = (*dest) + val;
131 }
132
133 static void aggregate_8bit(uint32_t * dest, uint32_t val)
134 {
135         if ((((*dest) + val) < (*dest))
136             || ((*dest) + val) > 0xff)
137                 (*dest) = 0xff;
138         else
139                 (*dest) = (*dest) + val;
140 }
141
142 static void aggregate_16bit(uint32_t * dest, uint32_t val)
143 {
144         if ((((*dest) + val) < (*dest))
145             || ((*dest) + val) > 0xffff)
146                 (*dest) = 0xffff;
147         else
148                 (*dest) = (*dest) + val;
149 }
150
151 static void aggregate_32bit(uint32_t * dest, uint32_t val)
152 {
153         if (((*dest) + val) < (*dest))
154                 (*dest) = 0xffffffff;
155         else
156                 (*dest) = (*dest) + val;
157 }
158
159 static void aggregate_64bit(uint64_t * dest, uint64_t val)
160 {
161         if (((*dest) + val) < (*dest))
162                 (*dest) = 0xffffffffffffffffULL;
163         else
164                 (*dest) = (*dest) + val;
165 }
166
167 static void aggregate_perfcounters(void)
168 {
169         uint32_t val;
170
171         mad_decode_field(pc, IB_PC_PORT_SELECT_F, &val);
172         perf_count.portselect = val;
173         mad_decode_field(pc, IB_PC_COUNTER_SELECT_F, &val);
174         perf_count.counterselect = val;
175         mad_decode_field(pc, IB_PC_ERR_SYM_F, &val);
176         aggregate_16bit(&perf_count.symbolerrors, val);
177         mad_decode_field(pc, IB_PC_LINK_RECOVERS_F, &val);
178         aggregate_8bit(&perf_count.linkrecovers, val);
179         mad_decode_field(pc, IB_PC_LINK_DOWNED_F, &val);
180         aggregate_8bit(&perf_count.linkdowned, val);
181         mad_decode_field(pc, IB_PC_ERR_RCV_F, &val);
182         aggregate_16bit(&perf_count.rcverrors, val);
183         mad_decode_field(pc, IB_PC_ERR_PHYSRCV_F, &val);
184         aggregate_16bit(&perf_count.rcvremotephyerrors, val);
185         mad_decode_field(pc, IB_PC_ERR_SWITCH_REL_F, &val);
186         aggregate_16bit(&perf_count.rcvswrelayerrors, val);
187         mad_decode_field(pc, IB_PC_XMT_DISCARDS_F, &val);
188         aggregate_16bit(&perf_count.xmtdiscards, val);
189         mad_decode_field(pc, IB_PC_ERR_XMTCONSTR_F, &val);
190         aggregate_8bit(&perf_count.xmtconstrainterrors, val);
191         mad_decode_field(pc, IB_PC_ERR_RCVCONSTR_F, &val);
192         aggregate_8bit(&perf_count.rcvconstrainterrors, val);
193         mad_decode_field(pc, IB_PC_ERR_LOCALINTEG_F, &val);
194         aggregate_4bit(&perf_count.linkintegrityerrors, val);
195         mad_decode_field(pc, IB_PC_ERR_EXCESS_OVR_F, &val);
196         aggregate_4bit(&perf_count.excbufoverrunerrors, val);
197 #ifdef HAVE_IB_PC_QP1_DROP_F
198         mad_decode_field(pc, IB_PC_QP1_DROP_F, &val);
199         aggregate_16bit(&perf_count.qp1dropped, val);
200 #endif
201         mad_decode_field(pc, IB_PC_VL15_DROPPED_F, &val);
202         aggregate_16bit(&perf_count.vl15dropped, val);
203         mad_decode_field(pc, IB_PC_XMT_BYTES_F, &val);
204         aggregate_32bit(&perf_count.xmtdata, val);
205         mad_decode_field(pc, IB_PC_RCV_BYTES_F, &val);
206         aggregate_32bit(&perf_count.rcvdata, val);
207         mad_decode_field(pc, IB_PC_XMT_PKTS_F, &val);
208         aggregate_32bit(&perf_count.xmtpkts, val);
209         mad_decode_field(pc, IB_PC_RCV_PKTS_F, &val);
210         aggregate_32bit(&perf_count.rcvpkts, val);
211         mad_decode_field(pc, IB_PC_XMT_WAIT_F, &val);
212         aggregate_32bit(&perf_count.xmtwait, val);
213 }
214
215 static void output_aggregate_perfcounters(ib_portid_t * portid,
216                                           uint16_t cap_mask)
217 {
218         char buf[1024];
219         uint32_t val = ALL_PORTS;
220
221         /* set port_select to 255 to emulate AllPortSelect */
222         mad_encode_field(pc, IB_PC_PORT_SELECT_F, &val);
223         mad_encode_field(pc, IB_PC_COUNTER_SELECT_F, &perf_count.counterselect);
224         mad_encode_field(pc, IB_PC_ERR_SYM_F, &perf_count.symbolerrors);
225         mad_encode_field(pc, IB_PC_LINK_RECOVERS_F, &perf_count.linkrecovers);
226         mad_encode_field(pc, IB_PC_LINK_DOWNED_F, &perf_count.linkdowned);
227         mad_encode_field(pc, IB_PC_ERR_RCV_F, &perf_count.rcverrors);
228         mad_encode_field(pc, IB_PC_ERR_PHYSRCV_F,
229                          &perf_count.rcvremotephyerrors);
230         mad_encode_field(pc, IB_PC_ERR_SWITCH_REL_F,
231                          &perf_count.rcvswrelayerrors);
232         mad_encode_field(pc, IB_PC_XMT_DISCARDS_F, &perf_count.xmtdiscards);
233         mad_encode_field(pc, IB_PC_ERR_XMTCONSTR_F,
234                          &perf_count.xmtconstrainterrors);
235         mad_encode_field(pc, IB_PC_ERR_RCVCONSTR_F,
236                          &perf_count.rcvconstrainterrors);
237         mad_encode_field(pc, IB_PC_ERR_LOCALINTEG_F,
238                          &perf_count.linkintegrityerrors);
239         mad_encode_field(pc, IB_PC_ERR_EXCESS_OVR_F,
240                          &perf_count.excbufoverrunerrors);
241 #ifdef HAVE_IB_PC_QP1_DROP_F
242         mad_encode_field(pc, IB_PC_QP1_DROP_F, &perf_count.qp1dropped);
243 #endif
244         mad_encode_field(pc, IB_PC_VL15_DROPPED_F, &perf_count.vl15dropped);
245         mad_encode_field(pc, IB_PC_XMT_BYTES_F, &perf_count.xmtdata);
246         mad_encode_field(pc, IB_PC_RCV_BYTES_F, &perf_count.rcvdata);
247         mad_encode_field(pc, IB_PC_XMT_PKTS_F, &perf_count.xmtpkts);
248         mad_encode_field(pc, IB_PC_RCV_PKTS_F, &perf_count.rcvpkts);
249         mad_encode_field(pc, IB_PC_XMT_WAIT_F, &perf_count.xmtwait);
250
251         mad_dump_perfcounters(buf, sizeof buf, pc, sizeof pc);
252
253         printf("# Port counters: %s port %d (CapMask: 0x%02X)\n%s",
254                portid2str(portid), ALL_PORTS, ntohs(cap_mask), buf);
255 }
256
257 static void aggregate_perfcounters_ext(uint16_t cap_mask, uint32_t cap_mask2)
258 {
259         uint32_t val;
260         uint64_t val64;
261
262         mad_decode_field(pc, IB_PC_EXT_PORT_SELECT_F, &val);
263         perf_count_ext.portselect = val;
264         mad_decode_field(pc, IB_PC_EXT_COUNTER_SELECT_F, &val);
265         perf_count_ext.counterselect = val;
266         mad_decode_field(pc, IB_PC_EXT_XMT_BYTES_F, &val64);
267         aggregate_64bit(&perf_count_ext.portxmitdata, val64);
268         mad_decode_field(pc, IB_PC_EXT_RCV_BYTES_F, &val64);
269         aggregate_64bit(&perf_count_ext.portrcvdata, val64);
270         mad_decode_field(pc, IB_PC_EXT_XMT_PKTS_F, &val64);
271         aggregate_64bit(&perf_count_ext.portxmitpkts, val64);
272         mad_decode_field(pc, IB_PC_EXT_RCV_PKTS_F, &val64);
273         aggregate_64bit(&perf_count_ext.portrcvpkts, val64);
274
275         if (cap_mask & IB_PM_EXT_WIDTH_SUPPORTED) {
276                 mad_decode_field(pc, IB_PC_EXT_XMT_UPKTS_F, &val64);
277                 aggregate_64bit(&perf_count_ext.portunicastxmitpkts, val64);
278                 mad_decode_field(pc, IB_PC_EXT_RCV_UPKTS_F, &val64);
279                 aggregate_64bit(&perf_count_ext.portunicastrcvpkts, val64);
280                 mad_decode_field(pc, IB_PC_EXT_XMT_MPKTS_F, &val64);
281                 aggregate_64bit(&perf_count_ext.portmulticastxmitpkits, val64);
282                 mad_decode_field(pc, IB_PC_EXT_RCV_MPKTS_F, &val64);
283                 aggregate_64bit(&perf_count_ext.portmulticastrcvpkts, val64);
284         }
285
286         if (htonl(cap_mask2) & IB_PM_IS_ADDL_PORT_CTRS_EXT_SUP) {
287                 mad_decode_field(pc, IB_PC_EXT_COUNTER_SELECT2_F, &val);
288                 perf_count_ext.counterSelect2 = val;
289                 mad_decode_field(pc, IB_PC_EXT_ERR_SYM_F, &val64);
290                 aggregate_64bit(&perf_count_ext.symbolErrorCounter, val64);
291                 mad_decode_field(pc, IB_PC_EXT_LINK_RECOVERS_F, &val64);
292                 aggregate_64bit(&perf_count_ext.linkErrorRecoveryCounter, val64);
293                 mad_decode_field(pc, IB_PC_EXT_LINK_DOWNED_F, &val64);
294                 aggregate_64bit(&perf_count_ext.linkDownedCounter, val64);
295                 mad_decode_field(pc, IB_PC_EXT_ERR_RCV_F, &val64);
296                 aggregate_64bit(&perf_count_ext.portRcvErrors, val64);
297                 mad_decode_field(pc, IB_PC_EXT_ERR_PHYSRCV_F, &val64);
298                 aggregate_64bit(&perf_count_ext.portRcvRemotePhysicalErrors, val64);
299                 mad_decode_field(pc, IB_PC_EXT_ERR_SWITCH_REL_F, &val64);
300                 aggregate_64bit(&perf_count_ext.portRcvSwitchRelayErrors, val64);
301                 mad_decode_field(pc, IB_PC_EXT_XMT_DISCARDS_F, &val64);
302                 aggregate_64bit(&perf_count_ext.portXmitDiscards, val64);
303                 mad_decode_field(pc, IB_PC_EXT_ERR_XMTCONSTR_F, &val64);
304                 aggregate_64bit(&perf_count_ext.portXmitConstraintErrors, val64);
305                 mad_decode_field(pc, IB_PC_EXT_ERR_RCVCONSTR_F, &val64);
306                 aggregate_64bit(&perf_count_ext.portRcvConstraintErrors, val64);
307                 mad_decode_field(pc, IB_PC_EXT_ERR_LOCALINTEG_F, &val64);
308                 aggregate_64bit(&perf_count_ext.localLinkIntegrityErrors, val64);
309                 mad_decode_field(pc, IB_PC_EXT_ERR_EXCESS_OVR_F, &val64);
310                 aggregate_64bit(&perf_count_ext.excessiveBufferOverrunErrors, val64);
311                 mad_decode_field(pc, IB_PC_EXT_VL15_DROPPED_F, &val64);
312                 aggregate_64bit(&perf_count_ext.VL15Dropped, val64);
313                 mad_decode_field(pc, IB_PC_EXT_XMT_WAIT_F, &val64);
314                 aggregate_64bit(&perf_count_ext.portXmitWait, val64);
315                 mad_decode_field(pc, IB_PC_EXT_QP1_DROP_F, &val64);
316                 aggregate_64bit(&perf_count_ext.QP1Dropped, val64);
317         }
318 }
319
320 static void output_aggregate_perfcounters_ext(ib_portid_t * portid,
321                                               uint16_t cap_mask, uint32_t cap_mask2)
322 {
323         char buf[1536];
324         uint32_t val = ALL_PORTS;
325
326         memset(buf, 0, sizeof(buf));
327
328         /* set port_select to 255 to emulate AllPortSelect */
329         mad_encode_field(pc, IB_PC_EXT_PORT_SELECT_F, &val);
330         mad_encode_field(pc, IB_PC_EXT_COUNTER_SELECT_F,
331                          &perf_count_ext.counterselect);
332         mad_encode_field(pc, IB_PC_EXT_XMT_BYTES_F,
333                          &perf_count_ext.portxmitdata);
334         mad_encode_field(pc, IB_PC_EXT_RCV_BYTES_F,
335                          &perf_count_ext.portrcvdata);
336         mad_encode_field(pc, IB_PC_EXT_XMT_PKTS_F,
337                          &perf_count_ext.portxmitpkts);
338         mad_encode_field(pc, IB_PC_EXT_RCV_PKTS_F, &perf_count_ext.portrcvpkts);
339
340         if (cap_mask & IB_PM_EXT_WIDTH_SUPPORTED) {
341                 mad_encode_field(pc, IB_PC_EXT_XMT_UPKTS_F,
342                                  &perf_count_ext.portunicastxmitpkts);
343                 mad_encode_field(pc, IB_PC_EXT_RCV_UPKTS_F,
344                                  &perf_count_ext.portunicastrcvpkts);
345                 mad_encode_field(pc, IB_PC_EXT_XMT_MPKTS_F,
346                                  &perf_count_ext.portmulticastxmitpkits);
347                 mad_encode_field(pc, IB_PC_EXT_RCV_MPKTS_F,
348                                  &perf_count_ext.portmulticastrcvpkts);
349         }
350
351         if (htonl(cap_mask2) & IB_PM_IS_ADDL_PORT_CTRS_EXT_SUP) {
352                 mad_encode_field(pc, IB_PC_EXT_COUNTER_SELECT2_F,
353                                  &perf_count_ext.counterSelect2);
354                 mad_encode_field(pc, IB_PC_EXT_ERR_SYM_F,
355                                  &perf_count_ext.symbolErrorCounter);
356                 mad_encode_field(pc, IB_PC_EXT_LINK_RECOVERS_F,
357                                  &perf_count_ext.linkErrorRecoveryCounter);
358                 mad_encode_field(pc, IB_PC_EXT_LINK_DOWNED_F,
359                                  &perf_count_ext.linkDownedCounter);
360                 mad_encode_field(pc, IB_PC_EXT_ERR_RCV_F,
361                                  &perf_count_ext.portRcvErrors);
362                 mad_encode_field(pc, IB_PC_EXT_ERR_PHYSRCV_F,
363                                  &perf_count_ext.portRcvRemotePhysicalErrors);
364                 mad_encode_field(pc, IB_PC_EXT_ERR_SWITCH_REL_F,
365                                  &perf_count_ext.portRcvSwitchRelayErrors);
366                 mad_encode_field(pc, IB_PC_EXT_XMT_DISCARDS_F,
367                                  &perf_count_ext.portXmitDiscards);
368                 mad_encode_field(pc, IB_PC_EXT_ERR_XMTCONSTR_F,
369                                  &perf_count_ext.portXmitConstraintErrors);
370                 mad_encode_field(pc, IB_PC_EXT_ERR_RCVCONSTR_F,
371                                  &perf_count_ext.portRcvConstraintErrors);
372                 mad_encode_field(pc, IB_PC_EXT_ERR_LOCALINTEG_F,
373                                  &perf_count_ext.localLinkIntegrityErrors);
374                 mad_encode_field(pc, IB_PC_EXT_ERR_EXCESS_OVR_F,
375                                  &perf_count_ext.excessiveBufferOverrunErrors);
376                 mad_encode_field(pc, IB_PC_EXT_VL15_DROPPED_F,
377                                  &perf_count_ext.VL15Dropped);
378                 mad_encode_field(pc, IB_PC_EXT_XMT_WAIT_F,
379                                  &perf_count_ext.portXmitWait);
380                 mad_encode_field(pc, IB_PC_EXT_QP1_DROP_F,
381                                  &perf_count_ext.QP1Dropped);
382         }
383
384         mad_dump_perfcounters_ext(buf, sizeof buf, pc, sizeof pc);
385
386         printf("# Port extended counters: %s port %d (CapMask: 0x%02X CapMask2: 0x%07X)\n%s",
387                portid2str(portid), ALL_PORTS, ntohs(cap_mask), cap_mask2, buf);
388 }
389
390 static void dump_perfcounters(int extended, int timeout, uint16_t cap_mask,
391                               uint32_t cap_mask2, ib_portid_t * portid,
392                               int port, int aggregate)
393 {
394         char buf[1536];
395
396         if (extended != 1) {
397                 memset(pc, 0, sizeof(pc));
398                 if (!pma_query_via(pc, portid, port, timeout,
399                                    IB_GSI_PORT_COUNTERS, srcport))
400                         IBEXIT("perfquery");
401                 if (!(cap_mask & IB_PM_PC_XMIT_WAIT_SUP)) {
402                         /* if PortCounters:PortXmitWait not supported clear this counter */
403                         VERBOSE("PortXmitWait not indicated"
404                                 " so ignore this counter");
405                         perf_count.xmtwait = 0;
406                         mad_encode_field(pc, IB_PC_XMT_WAIT_F,
407                                          &perf_count.xmtwait);
408                 }
409                 if (aggregate)
410                         aggregate_perfcounters();
411                 else {
412 #ifdef HAVE_IB_PC_QP1_DROP_F
413                         mad_dump_perfcounters(buf, sizeof buf, pc, sizeof pc);
414 #else
415                         mad_dump_fields(buf, sizeof buf, pc, sizeof pc,
416                                                         IB_PC_FIRST_F,
417                                                         (cap_mask & IB_PM_PC_XMIT_WAIT_SUP)?IB_PC_LAST_F:(IB_PC_RCV_PKTS_F+1));
418 #endif
419                 }
420         } else {
421                 /* 1.2 errata: bit 9 is extended counter support
422                  * bit 10 is extended counter NoIETF
423                  */
424                 if (!(cap_mask & IB_PM_EXT_WIDTH_SUPPORTED) &&
425                     !(cap_mask & IB_PM_EXT_WIDTH_NOIETF_SUP))
426                         IBWARN
427                             ("PerfMgt ClassPortInfo CapMask 0x%02X; No extended counter support indicated\n",
428                              ntohs(cap_mask));
429
430                 memset(pc, 0, sizeof(pc));
431                 if (!pma_query_via(pc, portid, port, timeout,
432                                    IB_GSI_PORT_COUNTERS_EXT, srcport))
433                         IBEXIT("perfextquery");
434                 if (aggregate)
435                         aggregate_perfcounters_ext(cap_mask, cap_mask2);
436                 else
437                         mad_dump_perfcounters_ext(buf, sizeof buf, pc,
438                                                   sizeof pc);
439         }
440
441         if (!aggregate) {
442                 if (extended)
443                         printf("# Port extended counters: %s port %d "
444                                "(CapMask: 0x%02X CapMask2: 0x%07X)\n%s",
445                                portid2str(portid), port, ntohs(cap_mask),
446                                cap_mask2, buf);
447                 else
448                         printf("# Port counters: %s port %d "
449                                "(CapMask: 0x%02X)\n%s",
450                                portid2str(portid), port, ntohs(cap_mask), buf);
451         }
452 }
453
454 static void reset_counters(int extended, int timeout, int mask,
455                            ib_portid_t * portid, int port)
456 {
457         memset(pc, 0, sizeof(pc));
458         if (extended != 1) {
459                 if (!performance_reset_via(pc, portid, port, mask, timeout,
460                                            IB_GSI_PORT_COUNTERS, srcport))
461                         IBEXIT("perf reset");
462         } else {
463                 if (!performance_reset_via(pc, portid, port, mask, timeout,
464                                            IB_GSI_PORT_COUNTERS_EXT, srcport))
465                         IBEXIT("perf ext reset");
466         }
467 }
468
469 static int reset, reset_only, all_ports, loop_ports, port, extended, xmt_sl,
470     rcv_sl, xmt_disc, rcv_err, extended_speeds, smpl_ctl, oprcvcounters, flowctlcounters,
471     vloppackets, vlopdata, vlxmitflowctlerrors, vlxmitcounters, swportvlcong,
472     rcvcc, slrcvfecn, slrcvbecn, xmitcc, vlxmittimecc;
473 static int ports[MAX_PORTS];
474 static int ports_count;
475
476 static void common_func(ib_portid_t * portid, int port_num, int mask,
477                         unsigned query, unsigned reset,
478                         const char *name, uint16_t attr,
479                         void dump_func(char *, int, void *, int))
480 {
481         char buf[1536];
482
483         if (query) {
484                 memset(pc, 0, sizeof(pc));
485                 if (!pma_query_via(pc, portid, port_num, ibd_timeout, attr,
486                                    srcport))
487                         IBEXIT("cannot query %s", name);
488
489                 dump_func(buf, sizeof(buf), pc, sizeof(pc));
490
491                 printf("# %s counters: %s port %d\n%s", name,
492                        portid2str(portid), port_num, buf);
493         }
494
495         memset(pc, 0, sizeof(pc));
496         if (reset && !performance_reset_via(pc, portid, port, mask, ibd_timeout,
497                                             attr, srcport))
498                 IBEXIT("cannot reset %s", name);
499 }
500
501 static void xmt_sl_query(ib_portid_t * portid, int port, int mask)
502 {
503         common_func(portid, port, mask, !reset_only, (reset_only || reset),
504                     "PortXmitDataSL", IB_GSI_PORT_XMIT_DATA_SL,
505                     mad_dump_perfcounters_xmt_sl);
506 }
507
508 static void rcv_sl_query(ib_portid_t * portid, int port, int mask)
509 {
510         common_func(portid, port, mask, !reset_only, (reset_only || reset),
511                     "PortRcvDataSL", IB_GSI_PORT_RCV_DATA_SL,
512                     mad_dump_perfcounters_rcv_sl);
513 }
514
515 static void xmt_disc_query(ib_portid_t * portid, int port, int mask)
516 {
517         common_func(portid, port, mask, !reset_only, (reset_only || reset),
518                     "PortXmitDiscardDetails", IB_GSI_PORT_XMIT_DISCARD_DETAILS,
519                     mad_dump_perfcounters_xmt_disc);
520 }
521
522 static void rcv_err_query(ib_portid_t * portid, int port, int mask)
523 {
524         common_func(portid, port, mask, !reset_only, (reset_only || reset),
525                     "PortRcvErrorDetails", IB_GSI_PORT_RCV_ERROR_DETAILS,
526                     mad_dump_perfcounters_rcv_err);
527 }
528
529 static uint8_t *ext_speeds_reset_via(void *rcvbuf, ib_portid_t * dest,
530                                      int port, uint64_t mask, unsigned timeout,
531                                      const struct ibmad_port * srcport)
532 {
533         ib_rpc_t rpc = { 0 };
534         int lid = dest->lid;
535
536         DEBUG("lid %u port %d mask 0x%" PRIx64, lid, port, mask);
537
538         if (lid == -1) {
539                 IBWARN("only lid routed is supported");
540                 return NULL;
541         }
542
543         if (!mask)
544                 mask = ~0;
545
546         rpc.mgtclass = IB_PERFORMANCE_CLASS;
547         rpc.method = IB_MAD_METHOD_SET;
548         rpc.attr.id = IB_GSI_PORT_EXT_SPEEDS_COUNTERS;
549
550         memset(rcvbuf, 0, IB_MAD_SIZE);
551
552         mad_set_field(rcvbuf, 0, IB_PESC_PORT_SELECT_F, port);
553         mad_set_field64(rcvbuf, 0, IB_PESC_COUNTER_SELECT_F, mask);
554         rpc.attr.mod = 0;
555         rpc.timeout = timeout;
556         rpc.datasz = IB_PC_DATA_SZ;
557         rpc.dataoffs = IB_PC_DATA_OFFS;
558         if (!dest->qp)
559                 dest->qp = 1;
560         if (!dest->qkey)
561                 dest->qkey = IB_DEFAULT_QP1_QKEY;
562
563         return mad_rpc(srcport, &rpc, dest, rcvbuf, rcvbuf);
564 }
565
566 static uint8_t is_rsfec_mode_active(ib_portid_t * portid, int port,
567                                   uint16_t cap_mask)
568 {
569         uint8_t data[IB_SMP_DATA_SIZE] = { 0 };
570         uint32_t fec_mode_active = 0;
571         uint32_t pie_capmask = 0;
572         if (cap_mask & IS_PM_RSFEC_COUNTERS_SUP) {
573                 if (!is_port_info_extended_supported(portid, port, srcport)) {
574                         IBWARN("Port Info Extended not supported");
575                         return 0;
576                 }
577
578                 if (!smp_query_via(data, portid, IB_ATTR_PORT_INFO_EXT, port, 0,
579                                    srcport))
580                         IBEXIT("smp query portinfo extended failed");
581
582                 mad_decode_field(data, IB_PORT_EXT_CAPMASK_F, &pie_capmask);
583                 mad_decode_field(data, IB_PORT_EXT_FEC_MODE_ACTIVE_F,
584                                  &fec_mode_active);
585                 if((pie_capmask &
586                     CL_NTOH32(IB_PORT_EXT_CAP_IS_FEC_MODE_SUPPORTED)) &&
587                    (CL_NTOH16(IB_PORT_EXT_RS_FEC_MODE_ACTIVE) == (fec_mode_active & 0xffff)))
588                         return 1;
589         }
590
591         return 0;
592 }
593
594 static void extended_speeds_query(ib_portid_t * portid, int port,
595                                   uint64_t ext_mask, uint16_t cap_mask)
596 {
597         int mask = ext_mask;
598
599         if (!reset_only) {
600                 if (is_rsfec_mode_active(portid, port, cap_mask))
601                         common_func(portid, port, mask, 1, 0,
602                                     "PortExtendedSpeedsCounters with RS-FEC Active",
603                                     IB_GSI_PORT_EXT_SPEEDS_COUNTERS,
604                                     mad_dump_port_ext_speeds_counters_rsfec_active);
605                 else
606                         common_func(portid, port, mask, 1, 0,
607                             "PortExtendedSpeedsCounters",
608                             IB_GSI_PORT_EXT_SPEEDS_COUNTERS,
609                             mad_dump_port_ext_speeds_counters);
610         }
611
612         if ((reset_only || reset) &&
613             !ext_speeds_reset_via(pc, portid, port, ext_mask, ibd_timeout, srcport))
614                 IBEXIT("cannot reset PortExtendedSpeedsCounters");
615 }
616
617 static void oprcvcounters_query(ib_portid_t * portid, int port, int mask)
618 {
619         common_func(portid, port, mask, !reset_only, (reset_only || reset),
620                     "PortOpRcvCounters", IB_GSI_PORT_PORT_OP_RCV_COUNTERS,
621                     mad_dump_perfcounters_port_op_rcv_counters);
622 }
623
624 static void flowctlcounters_query(ib_portid_t * portid, int port, int mask)
625 {
626         common_func(portid, port, mask, !reset_only, (reset_only || reset),
627                     "PortFlowCtlCounters", IB_GSI_PORT_PORT_FLOW_CTL_COUNTERS,
628                     mad_dump_perfcounters_port_flow_ctl_counters);
629 }
630
631 static void vloppackets_query(ib_portid_t * portid, int port, int mask)
632 {
633         common_func(portid, port, mask, !reset_only, (reset_only || reset),
634                     "PortVLOpPackets", IB_GSI_PORT_PORT_VL_OP_PACKETS,
635                     mad_dump_perfcounters_port_vl_op_packet);
636 }
637
638 static void vlopdata_query(ib_portid_t * portid, int port, int mask)
639 {
640         common_func(portid, port, mask, !reset_only, (reset_only || reset),
641                     "PortVLOpData", IB_GSI_PORT_PORT_VL_OP_DATA,
642                     mad_dump_perfcounters_port_vl_op_data);
643 }
644
645 static void vlxmitflowctlerrors_query(ib_portid_t * portid, int port, int mask)
646 {
647         common_func(portid, port, mask, !reset_only, (reset_only || reset),
648                     "PortVLXmitFlowCtlUpdateErrors", IB_GSI_PORT_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS,
649                     mad_dump_perfcounters_port_vl_xmit_flow_ctl_update_errors);
650 }
651
652 static void vlxmitcounters_query(ib_portid_t * portid, int port, int mask)
653 {
654         common_func(portid, port, mask, !reset_only, (reset_only || reset),
655                     "PortVLXmitWaitCounters", IB_GSI_PORT_PORT_VL_XMIT_WAIT_COUNTERS,
656                     mad_dump_perfcounters_port_vl_xmit_wait_counters);
657 }
658
659 static void swportvlcong_query(ib_portid_t * portid, int port, int mask)
660 {
661         common_func(portid, port, mask, !reset_only, (reset_only || reset),
662                     "SwPortVLCongestion", IB_GSI_SW_PORT_VL_CONGESTION,
663                     mad_dump_perfcounters_sw_port_vl_congestion);
664 }
665
666 static void rcvcc_query(ib_portid_t * portid, int port, int mask)
667 {
668         common_func(portid, port, mask, !reset_only, (reset_only || reset),
669                     "PortRcvConCtrl", IB_GSI_PORT_RCV_CON_CTRL,
670                     mad_dump_perfcounters_rcv_con_ctrl);
671 }
672
673 static void slrcvfecn_query(ib_portid_t * portid, int port, int mask)
674 {
675         common_func(portid, port, mask, !reset_only, (reset_only || reset),
676                     "PortSLRcvFECN", IB_GSI_PORT_SL_RCV_FECN,
677                     mad_dump_perfcounters_sl_rcv_fecn);
678 }
679
680 static void slrcvbecn_query(ib_portid_t * portid, int port, int mask)
681 {
682         common_func(portid, port, mask, !reset_only, (reset_only || reset),
683                     "PortSLRcvBECN", IB_GSI_PORT_SL_RCV_BECN,
684                     mad_dump_perfcounters_sl_rcv_becn);
685 }
686
687 static void xmitcc_query(ib_portid_t * portid, int port, int mask)
688 {
689         common_func(portid, port, mask, !reset_only, (reset_only || reset),
690                     "PortXmitConCtrl", IB_GSI_PORT_XMIT_CON_CTRL,
691                     mad_dump_perfcounters_xmit_con_ctrl);
692 }
693
694 static void vlxmittimecc_query(ib_portid_t * portid, int port, int mask)
695 {
696         common_func(portid, port, mask, !reset_only, (reset_only || reset),
697                     "PortVLXmitTimeCong", IB_GSI_PORT_VL_XMIT_TIME_CONG,
698                     mad_dump_perfcounters_vl_xmit_time_cong);
699 }
700
701 void dump_portsamples_control(ib_portid_t * portid, int port)
702 {
703         char buf[1280];
704
705         memset(pc, 0, sizeof(pc));
706         if (!pma_query_via(pc, portid, port, ibd_timeout,
707                            IB_GSI_PORT_SAMPLES_CONTROL, srcport))
708                 IBEXIT("sampctlquery");
709
710         mad_dump_portsamples_control(buf, sizeof buf, pc, sizeof pc);
711         printf("# PortSamplesControl: %s port %d\n%s", portid2str(portid),
712                port, buf);
713 }
714
715 static int process_opt(void *context, int ch, char *optarg)
716 {
717         switch (ch) {
718         case 'x':
719                 extended = 1;
720                 break;
721         case 'X':
722                 xmt_sl = 1;
723                 break;
724         case 'S':
725                 rcv_sl = 1;
726                 break;
727         case 'D':
728                 xmt_disc = 1;
729                 break;
730         case 'E':
731                 rcv_err = 1;
732                 break;
733         case 'T':
734                 extended_speeds = 1;
735                 break;
736         case 'c':
737                 smpl_ctl = 1;
738                 break;
739         case 1:
740                 oprcvcounters = 1;
741                 break;
742         case 2:
743                 flowctlcounters = 1;
744                 break;
745         case 3:
746                 vloppackets = 1;
747                 break;
748         case 4:
749                 vlopdata = 1;
750                 break;
751         case 5:
752                 vlxmitflowctlerrors = 1;
753                 break;
754         case 6:
755                 vlxmitcounters = 1;
756                 break;
757         case 7:
758                 swportvlcong = 1;
759                 break;
760         case 8:
761                 rcvcc = 1;
762                 break;
763         case 9:
764                 slrcvfecn = 1;
765                 break;
766         case 10:
767                 slrcvbecn = 1;
768                 break;
769         case 11:
770                 xmitcc = 1;
771                 break;
772         case 12:
773                 vlxmittimecc = 1;
774                 break;
775         case 'a':
776                 all_ports++;
777                 port = ALL_PORTS;
778                 break;
779         case 'l':
780                 loop_ports++;
781                 break;
782         case 'r':
783                 reset++;
784                 break;
785         case 'R':
786                 reset_only++;
787                 break;
788         case 25:
789                 if (!inet_pton(AF_INET6, optarg, &dgid)) {
790                         fprintf(stderr, "dgid format is wrong!\n");
791                         ibdiag_show_usage();
792                         return 1;
793                 }
794                 with_grh = 1;
795                 break;
796         default:
797                 return -1;
798         }
799         return 0;
800 }
801
802 int main(int argc, char **argv)
803 {
804         int mgmt_classes[3] = { IB_SMI_CLASS, IB_SA_CLASS, IB_PERFORMANCE_CLASS };
805         ib_portid_t portid = { 0 };
806         int mask = 0xffff;
807         uint64_t ext_mask = 0xffffffffffffffffULL;
808         uint32_t cap_mask2;
809         uint16_t cap_mask;
810         int all_ports_loop = 0;
811         int node_type, num_ports = 0;
812         uint8_t data[IB_SMP_DATA_SIZE] = { 0 };
813         int start_port = 1;
814         int enhancedport0;
815         char *tmpstr;
816         int i;
817
818         const struct ibdiag_opt opts[] = {
819                 {"extended", 'x', 0, NULL, "show extended port counters"},
820                 {"xmtsl", 'X', 0, NULL, "show Xmt SL port counters"},
821                 {"rcvsl", 'S', 0, NULL, "show Rcv SL port counters"},
822                 {"xmtdisc", 'D', 0, NULL, "show Xmt Discard Details"},
823                 {"rcverr", 'E', 0, NULL, "show Rcv Error Details"},
824                 {"extended_speeds", 'T', 0, NULL, "show port extended speeds counters"},
825                 {"oprcvcounters", 1, 0, NULL, "show Rcv Counters per Op code"},
826                 {"flowctlcounters", 2, 0, NULL, "show flow control counters"},
827                 {"vloppackets", 3, 0, NULL, "show packets received per Op code per VL"},
828                 {"vlopdata", 4, 0, NULL, "show data received per Op code per VL"},
829                 {"vlxmitflowctlerrors", 5, 0, NULL, "show flow control update errors per VL"},
830                 {"vlxmitcounters", 6, 0, NULL, "show ticks waiting to transmit counters per VL"},
831                 {"swportvlcong", 7, 0, NULL, "show sw port VL congestion"},
832                 {"rcvcc", 8, 0, NULL, "show Rcv congestion control counters"},
833                 {"slrcvfecn", 9, 0, NULL, "show SL Rcv FECN counters"},
834                 {"slrcvbecn", 10, 0, NULL, "show SL Rcv BECN counters"},
835                 {"xmitcc", 11, 0, NULL, "show Xmit congestion control counters"},
836                 {"vlxmittimecc", 12, 0, NULL, "show VL Xmit Time congestion control counters"},
837                 {"smplctl", 'c', 0, NULL, "show samples control"},
838                 {"all_ports", 'a', 0, NULL, "show aggregated counters"},
839                 {"loop_ports", 'l', 0, NULL, "iterate through each port"},
840                 {"reset_after_read", 'r', 0, NULL, "reset counters after read"},
841                 {"Reset_only", 'R', 0, NULL, "only reset counters"},
842                 {"dgid", 25, 1, NULL, "remote gid (IPv6 format)"},
843                 {0}
844         };
845         char usage_args[] = " [<lid|guid> [[port(s)] [reset_mask]]]";
846         const char *usage_examples[] = {
847                 "\t\t# read local port's performance counters",
848                 "32 1\t\t# read performance counters from lid 32, port 1",
849                 "-x 32 1\t# read extended performance counters from lid 32, port 1",
850                 "-a 32\t\t# read performance counters from lid 32, all ports",
851                 "-r 32 1\t# read performance counters and reset",
852                 "-x -r 32 1\t# read extended performance counters and reset",
853                 "-R 0x20 1\t# reset performance counters of port 1 only",
854                 "-x -R 0x20 1\t# reset extended performance counters of port 1 only",
855                 "-R -a 32\t# reset performance counters of all ports",
856                 "-R 32 2 0x0fff\t# reset only error counters of port 2",
857                 "-R 32 2 0xf000\t# reset only non-error counters of port 2",
858                 "-a 32 1-10\t# read performance counters from lid 32, port 1-10, aggregate output",
859                 "-l 32 1-10\t# read performance counters from lid 32, port 1-10, output each port",
860                 "-a 32 1,4,8\t# read performance counters from lid 32, port 1, 4, and 8, aggregate output",
861                 "-l 32 1,4,8\t# read performance counters from lid 32, port 1, 4, and 8, output each port",
862                 NULL,
863         };
864
865         ibdiag_process_opts(argc, argv, NULL, "DK", opts, process_opt,
866                             usage_args, usage_examples);
867
868         argc -= optind;
869         argv += optind;
870
871         if (argc > 1) {
872                 if (strchr(argv[1], ',')) {
873                         tmpstr = strtok(argv[1], ",");
874                         while (tmpstr) {
875                                 ports[ports_count++] = strtoul(tmpstr, 0, 0);
876                                 tmpstr = strtok(NULL, ",");
877                         }
878                         port = ports[0];
879                 }
880                 else if ((tmpstr = strchr(argv[1], '-'))) {
881                         int pmin, pmax;
882
883                         *tmpstr = '\0';
884                         tmpstr++;
885
886                         pmin = strtoul(argv[1], 0, 0);
887                         pmax = strtoul(tmpstr, 0, 0);
888
889                         if (pmin >= pmax)
890                                 IBEXIT("max port must be greater than min port in range");
891
892                         while (pmin <= pmax)
893                                 ports[ports_count++] = pmin++;
894
895                         port = ports[0];
896                 }
897                 else
898                         port = strtoul(argv[1], 0, 0);
899         }
900         if (argc > 2) {
901                 ext_mask = strtoull(argv[2], 0, 0);
902                 mask = ext_mask;
903         }
904
905         srcport = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 3);
906         if (!srcport)
907                 IBEXIT("Failed to open '%s' port '%d'", ibd_ca, ibd_ca_port);
908
909         smp_mkey_set(srcport, ibd_mkey);
910
911         if (argc) {
912                 if (with_grh && ibd_dest_type != IB_DEST_LID)
913                         IBEXIT("When using GRH, LID should be provided");
914                 if (resolve_portid_str(ibd_ca, ibd_ca_port, &portid, argv[0],
915                                        ibd_dest_type, ibd_sm_id, srcport) < 0)
916                         IBEXIT("can't resolve destination port %s", argv[0]);
917                 if (with_grh) {
918                         portid.grh_present = 1;
919                         memcpy(&portid.gid, &dgid, sizeof(portid.gid));
920                 }
921         } else {
922                 if (resolve_self(ibd_ca, ibd_ca_port, &portid, &port, 0) < 0)
923                         IBEXIT("can't resolve self port %s", argv[0]);
924         }
925
926         /* PerfMgt ClassPortInfo is a required attribute */
927         memset(pc, 0, sizeof(pc));
928         if (!pma_query_via(pc, &portid, port, ibd_timeout, CLASS_PORT_INFO,
929                            srcport))
930                 IBEXIT("classportinfo query");
931         /* ClassPortInfo should be supported as part of libibmad */
932         memcpy(&cap_mask, pc + 2, sizeof(cap_mask));    /* CapabilityMask */
933         memcpy(&cap_mask2, pc + 4, sizeof(cap_mask2));  /* CapabilityMask2 */
934         cap_mask2 = ntohl(cap_mask2) >> 5;
935
936         if (!(cap_mask & IB_PM_ALL_PORT_SELECT)) {      /* bit 8 is AllPortSelect */
937                 if (!all_ports && port == ALL_PORTS)
938                         IBEXIT("AllPortSelect not supported");
939                 if (all_ports && port == ALL_PORTS)
940                         all_ports_loop = 1;
941         }
942
943         if (xmt_sl) {
944                 xmt_sl_query(&portid, port, mask);
945                 goto done;
946         }
947
948         if (rcv_sl) {
949                 rcv_sl_query(&portid, port, mask);
950                 goto done;
951         }
952
953         if (xmt_disc) {
954                 xmt_disc_query(&portid, port, mask);
955                 goto done;
956         }
957
958         if (rcv_err) {
959                 rcv_err_query(&portid, port, mask);
960                 goto done;
961         }
962
963         if (extended_speeds) {
964                 extended_speeds_query(&portid, port, ext_mask, cap_mask);
965                 goto done;
966         }
967
968         if (oprcvcounters) {
969                 oprcvcounters_query(&portid, port, mask);
970                 goto done;
971         }
972
973         if (flowctlcounters) {
974                 flowctlcounters_query(&portid, port, mask);
975                 goto done;
976         }
977
978         if (vloppackets) {
979                 vloppackets_query(&portid, port, mask);
980                 goto done;
981         }
982
983         if (vlopdata) {
984                 vlopdata_query(&portid, port, mask);
985                 goto done;
986         }
987
988         if (vlxmitflowctlerrors) {
989                 vlxmitflowctlerrors_query(&portid, port, mask);
990                 goto done;
991         }
992
993         if (vlxmitcounters) {
994                 vlxmitcounters_query(&portid, port, mask);
995                 goto done;
996         }
997
998         if (swportvlcong) {
999                 swportvlcong_query(&portid, port, mask);
1000                 goto done;
1001         }
1002
1003         if (rcvcc) {
1004                 rcvcc_query(&portid, port, mask);
1005                 goto done;
1006         }
1007
1008         if (slrcvfecn) {
1009                 slrcvfecn_query(&portid, port, mask);
1010                 goto done;
1011         }
1012
1013         if (slrcvbecn) {
1014                 slrcvbecn_query(&portid, port, mask);
1015                 goto done;
1016         }
1017
1018         if (xmitcc) {
1019                 xmitcc_query(&portid, port, mask);
1020                 goto done;
1021         }
1022
1023         if (vlxmittimecc) {
1024                 vlxmittimecc_query(&portid, port, mask);
1025                 goto done;
1026         }
1027
1028         if (smpl_ctl) {
1029                 dump_portsamples_control(&portid, port);
1030                 goto done;
1031         }
1032
1033
1034         if (all_ports_loop || (loop_ports && (all_ports || port == ALL_PORTS))) {
1035                 if (!smp_query_via(data, &portid, IB_ATTR_NODE_INFO, 0, 0,
1036                                    srcport))
1037                         IBEXIT("smp query nodeinfo failed");
1038                 node_type = mad_get_field(data, 0, IB_NODE_TYPE_F);
1039                 mad_decode_field(data, IB_NODE_NPORTS_F, &num_ports);
1040                 if (!num_ports)
1041                         IBEXIT("smp query nodeinfo: num ports invalid");
1042
1043                 if (node_type == IB_NODE_SWITCH) {
1044                         if (!smp_query_via(data, &portid, IB_ATTR_SWITCH_INFO,
1045                                            0, 0, srcport))
1046                                 IBEXIT("smp query nodeinfo failed");
1047                         enhancedport0 =
1048                             mad_get_field(data, 0, IB_SW_ENHANCED_PORT0_F);
1049                         if (enhancedport0)
1050                                 start_port = 0;
1051                 }
1052                 if (all_ports_loop && !loop_ports)
1053                         IBWARN
1054                             ("Emulating AllPortSelect by iterating through all ports");
1055         }
1056
1057         if (reset_only)
1058                 goto do_reset;
1059
1060         if (all_ports_loop || (loop_ports && (all_ports || port == ALL_PORTS))) {
1061                 for (i = start_port; i <= num_ports; i++)
1062                         dump_perfcounters(extended, ibd_timeout,
1063                                           cap_mask, cap_mask2,
1064                                           &portid, i, (all_ports_loop
1065                                                        && !loop_ports));
1066                 if (all_ports_loop && !loop_ports) {
1067                         if (extended != 1)
1068                                 output_aggregate_perfcounters(&portid,
1069                                                               cap_mask);
1070                         else
1071                                 output_aggregate_perfcounters_ext(&portid,
1072                                                                   cap_mask, cap_mask2);
1073                 }
1074         } else if (ports_count > 1) {
1075                 for (i = 0; i < ports_count; i++)
1076                         dump_perfcounters(extended, ibd_timeout, cap_mask,
1077                                           cap_mask2, &portid, ports[i],
1078                                           (all_ports && !loop_ports));
1079                 if (all_ports && !loop_ports) {
1080                         if (extended != 1)
1081                                 output_aggregate_perfcounters(&portid,
1082                                                               cap_mask);
1083                         else
1084                                 output_aggregate_perfcounters_ext(&portid,
1085                                                                   cap_mask, cap_mask2);
1086                 }
1087         } else
1088                 dump_perfcounters(extended, ibd_timeout, cap_mask, cap_mask2,
1089                                   &portid, port, 0);
1090
1091         if (!reset)
1092                 goto done;
1093
1094 do_reset:
1095         if (argc <= 2 && !extended) {
1096                 if (cap_mask & IB_PM_PC_XMIT_WAIT_SUP)
1097                         mask |= (1 << 16);      /* reset portxmitwait */
1098                 if (cap_mask & IB_PM_IS_QP1_DROP_SUP)
1099                         mask |= (1 << 17);      /* reset qp1dropped */
1100         }
1101
1102         if (extended) {
1103                 mask |= 0xfff0000;
1104                 if (cap_mask & IB_PM_PC_XMIT_WAIT_SUP)
1105                         mask |= (1 << 28);
1106                 if (cap_mask & IB_PM_IS_QP1_DROP_SUP)
1107                         mask |= (1 << 29);
1108         }
1109
1110         if (all_ports_loop || (loop_ports && (all_ports || port == ALL_PORTS))) {
1111                 for (i = start_port; i <= num_ports; i++)
1112                         reset_counters(extended, ibd_timeout, mask, &portid, i);
1113         } else if (ports_count > 1) {
1114                 for (i = 0; i < ports_count; i++)
1115                         reset_counters(extended, ibd_timeout, mask, &portid, ports[i]);
1116         } else
1117                 reset_counters(extended, ibd_timeout, mask, &portid, port);
1118
1119 done:
1120         mad_rpc_close_port(srcport);
1121         exit(0);
1122 }