Switchtec Userspace PROJECT_NUMBER = 4.2
Loading...
Searching...
No Matches
pmon.c
Go to the documentation of this file.
1/*
2 * Microsemi Switchtec(tm) PCIe Management Library
3 * Copyright (c) 2017, Microsemi Corporation
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21 * OTHER DEALINGS IN THE SOFTWARE.
22 *
23 */
24
29
30#define SWITCHTEC_LIB_CORE
31
32#include "switchtec/pmon.h"
33#include "switchtec_priv.h"
34#include "switchtec/switchtec.h"
35#include "switchtec/endian.h"
36
37#include <stddef.h>
38#include <errno.h>
39
59
60#define ENTRY(x, h) {.mask=x, .name=#x, .help=h}
61
63 ENTRY(ALL, "all events"),
64 ENTRY(ALL_TLPS, "all TLPs"),
65 ENTRY(ALL_ERRORS, "all errors"),
66 ENTRY(UNSUP_REQ_ERR, "Unsupported Request error"),
67 ENTRY(ECRC_ERR, "ECRC error"),
68 ENTRY(MALFORM_TLP_ERR, "Malformed TLP error"),
69 ENTRY(RCVR_OFLOW_ERR, "Receiver Overflow error"),
70 ENTRY(CMPLTR_ABORT_ERR, "Completer Abort error"),
71 ENTRY(POISONED_TLP_ERR, "Poisoned TLP error"),
72 ENTRY(SURPRISE_DOWN_ERR, "Surprise Down error"),
73 ENTRY(DATA_LINK_PROTO_ERR, "Data Link Protocol error"),
74 ENTRY(HDR_LOG_OFLOW_ERR, "Header Log Overflow error"),
75 ENTRY(UNCOR_INT_ERR, "Uncorrectable Internal Error"),
76 ENTRY(REPLAY_TMR_TIMEOUT, "Replay Timer Timeout"),
77 ENTRY(REPLAY_NUM_ROLLOVER, "Replay Number Rollover"),
78 ENTRY(BAD_DLLP, "Bad DLLP"),
79 ENTRY(BAD_TLP, "Bad TLP"),
80 ENTRY(RCVR_ERR, "Receiver Error"),
81 ENTRY(RCV_FATAL_MSG, "Fatal Error Message received"),
82 ENTRY(RCV_NON_FATAL_MSG, "Non-fatal Error Message received"),
83 ENTRY(RCV_CORR_MSG, "Correctable Error Message received"),
84 ENTRY(NAK_RCVD, "NAK received"),
85 ENTRY(RULE_TABLE_HIT, "Rule Search Table rule hit"),
86 ENTRY(POSTED_TLP, "Posted TLP"),
87 ENTRY(COMP_TLP, "Completion TLP"),
88 ENTRY(NON_POSTED_TLP, "Non-Posted TLP"),
89 {0}};
90
96{
97 const struct switchtec_evcntr_type_list *t;
98 int i = 0;
99
100 for (t = switchtec_evcntr_type_list; t->name; t++, i++);
101
102 return i;
103}
104
116const char *switchtec_evcntr_type_str(int *type_mask)
117{
118 const struct switchtec_evcntr_type_list *t;
119
120 for (t = switchtec_evcntr_type_list; t->name; t++) {
121 if ((t->mask & *type_mask) != t->mask)
122 continue;
123
124 *type_mask &= ~t->mask;
125 return t->name;
126 }
127
128 return NULL;
129}
130
139int switchtec_evcntr_setup(struct switchtec_dev *dev, unsigned stack_id,
140 unsigned cntr_id,
141 struct switchtec_evcntr_setup *setup)
142{
143 struct pmon_event_counter_setup cmd = {
144 .sub_cmd_id = MRPC_PMON_SETUP_EV_COUNTER,
145 .stack_id = stack_id,
146 .counter_id = cntr_id,
147 .num_counters = 1,
148
149 .counters = {
150 [0] = {
151 .mask = htole32((setup->type_mask << 8) |
152 (setup->port_mask & 0xFF)),
153 .ieg = setup->egress,
154 .thresh = htole32(setup->threshold),
155 },
156 },
157 };
158
159 if (cntr_id >= SWITCHTEC_MAX_EVENT_COUNTERS) {
160 errno = EINVAL;
161 return -errno;
162 }
163
164 return switchtec_cmd(dev, MRPC_PMON, &cmd, sizeof(cmd),
165 NULL, 0);
166}
167
168static int evcntr_get(struct switchtec_dev *dev, int sub_cmd,
169 unsigned stack_id, unsigned cntr_id, unsigned nr_cntrs,
170 void *res, size_t res_size, int clear)
171{
172 int ret;
173
174 struct pmon_event_counter_get cmd = {
175 .sub_cmd_id = sub_cmd,
176 .stack_id = stack_id,
177 .counter_id = cntr_id,
178 .num_counters = nr_cntrs,
179 .read_clear = clear,
180 };
181
182 if (res_size > MRPC_MAX_DATA_LEN ||
183 cntr_id >= SWITCHTEC_MAX_EVENT_COUNTERS ||
184 nr_cntrs > SWITCHTEC_MAX_EVENT_COUNTERS ||
185 cntr_id + nr_cntrs > SWITCHTEC_MAX_EVENT_COUNTERS)
186 {
187 errno = EINVAL;
188 return -errno;
189 }
190
191 ret = switchtec_cmd(dev, MRPC_PMON, &cmd, sizeof(cmd),
192 res, res_size);
193
194 if (ret) {
195 errno = ret;
196 return -EINVAL;
197 }
198
199 return 0;
200}
201
214int switchtec_evcntr_get_setup(struct switchtec_dev *dev, unsigned stack_id,
215 unsigned cntr_id, unsigned nr_cntrs,
216 struct switchtec_evcntr_setup *res)
217{
218 int ret;
219 int i;
220 struct pmon_event_counter_get_setup_result data[nr_cntrs];
221
222 if (res == NULL) {
223 errno = EINVAL;
224 return -errno;
225 }
226
227 ret = evcntr_get(dev, MRPC_PMON_GET_EV_COUNTER_SETUP,
228 stack_id, cntr_id, nr_cntrs, data,
229 sizeof(*data) * nr_cntrs, 0);
230 if (ret)
231 return ret;
232
233 for (i = 0; i < nr_cntrs; i++) {
234 res[i].port_mask = le32toh(data[i].mask) & 0xFF;
235 res[i].type_mask = le32toh(data[i].mask) >> 8;
236 res[i].egress = data[i].ieg;
237 res[i].threshold = le32toh(data[i].thresh);
238 }
239
240 return nr_cntrs;
241}
242
257int switchtec_evcntr_get(struct switchtec_dev *dev, unsigned stack_id,
258 unsigned cntr_id, unsigned nr_cntrs, unsigned *res,
259 int clear)
260{
261 int ret;
262 int i;
263 struct pmon_event_counter_result data[nr_cntrs];
264
265 if (res == NULL) {
266 errno = EINVAL;
267 return -errno;
268 }
269
270 ret = evcntr_get(dev, MRPC_PMON_GET_EV_COUNTER,
271 stack_id, cntr_id, nr_cntrs, data,
272 sizeof(*data) * nr_cntrs, clear);
273 if (ret)
274 return ret;
275
276 for (i = 0; i < nr_cntrs; i++)
277 res[i] = le32toh(data[i].value);
278
279 return nr_cntrs;
280}
281
301int switchtec_evcntr_get_both(struct switchtec_dev *dev, unsigned stack_id,
302 unsigned cntr_id, unsigned nr_cntrs,
303 struct switchtec_evcntr_setup *setup,
304 unsigned *counts, int clear)
305{
306 int ret = 0;
307
308 ret = switchtec_evcntr_get_setup(dev, stack_id, cntr_id, nr_cntrs,
309 setup);
310 if (ret < 0)
311 return ret;
312
313 return switchtec_evcntr_get(dev, stack_id, cntr_id, nr_cntrs,
314 counts, clear);
315}
316
325int switchtec_evcntr_wait(struct switchtec_dev *dev, int timeout_ms)
326{
327 return switchtec_event_wait_for(dev, SWITCHTEC_PFF_EVT_THRESH,
328 SWITCHTEC_EVT_IDX_ALL,
329 NULL, timeout_ms);
330}
331
340 struct switchtec_bwcntr_res *old_cntr)
341{
342 new_cntr->time_us -= old_cntr->time_us;
343 new_cntr->egress.posted -= old_cntr->egress.posted;
344 new_cntr->egress.nonposted -= old_cntr->egress.nonposted;
345 new_cntr->egress.comp -= old_cntr->egress.comp;
346 new_cntr->ingress.posted -= old_cntr->ingress.posted;
347 new_cntr->ingress.nonposted -= old_cntr->ingress.nonposted;
348 new_cntr->ingress.comp -= old_cntr->ingress.comp;
349}
350
359int switchtec_bwcntr_set_many(struct switchtec_dev *dev, int nr_ports,
360 int * phys_port_ids,
361 enum switchtec_bw_type bw_type)
362{
363 int i;
364 size_t cmd_size;
365 struct pmon_bw_set cmd = {
366 .sub_cmd_id = MRPC_PMON_SET_BW_COUNTER,
367 .count = nr_ports,
368 };
369
370 for (i = 0; i < cmd.count; i++) {
371 cmd.ports[i].id = phys_port_ids[i];
372 cmd.ports[i].bw_type = bw_type;
373 }
374
375 cmd_size = offsetof(struct pmon_bw_set, ports) +
376 sizeof(cmd.ports[0]) * cmd.count;
377
378 return switchtec_cmd(dev, MRPC_PMON, &cmd, cmd_size, NULL, 0);
379}
380
387int switchtec_bwcntr_set_all(struct switchtec_dev *dev,
388 enum switchtec_bw_type bw_type)
389{
390 int ret, i;
391 struct switchtec_status *status;
392 int ids[SWITCHTEC_MAX_PORTS];
393
394 ret = switchtec_status(dev, &status);
395 if (ret < 0)
396 return ret;
397
398 for (i = 0; i < ret; i++) {
399 ids[i] = status[i].port.phys_id;
400 }
401
402 ret = switchtec_bwcntr_set_many(dev, ret, ids, bw_type);
403 free(status);
404 return ret;
405}
406
419int switchtec_bwcntr_many(struct switchtec_dev *dev, int nr_ports,
420 int *phys_port_ids, int clear,
421 struct switchtec_bwcntr_res *res)
422{
423 int i;
424 int ret;
425 int remain = nr_ports;
426 size_t cmd_size;
427 struct pmon_bw_get cmd = {
428 .sub_cmd_id = MRPC_PMON_GET_BW_COUNTER,
429 };
430 int cmd_max_count = ((MRPC_MAX_DATA_LEN - sizeof(struct pmon_bw_get))
431 / sizeof(*res));
432
433 while (remain) {
434 cmd.count = remain;
435 if (cmd.count > cmd_max_count)
436 cmd.count = cmd_max_count;
437
438 for (i = 0; i < cmd.count; i++) {
439 cmd.ports[i].id = phys_port_ids[i];
440 cmd.ports[i].clear = clear;
441 }
442
443 cmd_size = offsetof(struct pmon_bw_get, ports) +
444 sizeof(cmd.ports[0]) * cmd.count;
445
446 ret = switchtec_cmd(dev, MRPC_PMON, &cmd, cmd_size, res,
447 sizeof(*res) * cmd.count);
448 if (ret)
449 return -1;
450
451 remain -= cmd.count;
452 phys_port_ids += cmd.count;
453
454 if (res)
455 res += cmd.count;
456 }
457
458 return nr_ports;
459}
460
473int switchtec_bwcntr_all(struct switchtec_dev *dev, int clear,
474 struct switchtec_port_id **ports,
475 struct switchtec_bwcntr_res **res)
476{
477 int ret, i;
478 struct switchtec_status *status;
479 int ids[SWITCHTEC_MAX_PORTS];
480
481 ret = switchtec_status(dev, &status);
482 if (ret < 0)
483 return ret;
484
485 if (ports)
486 *ports = calloc(ret, sizeof(**ports));
487 if (res)
488 *res = calloc(ret, sizeof(**res));
489
490 for (i = 0; i < ret; i++) {
491 ids[i] = status[i].port.phys_id;
492 if (ports)
493 (*ports)[i] = status[i].port;
494 }
495
496 ret = switchtec_bwcntr_many(dev, ret, ids, clear, *res);
497 if (ret < 0) {
498 if (ports)
499 free(*ports);
500 if (res)
501 free(*res);
502 }
503
504 free(status);
505 return ret;
506}
507
513uint64_t switchtec_bwcntr_tot(struct switchtec_bwcntr_dir *d)
514{
515 return d->posted + d->nonposted + d->comp;
516}
517
527int switchtec_lat_setup_many(struct switchtec_dev *dev, int nr_ports,
528 int *egress_port_ids, int *ingress_port_ids)
529{
530 int i;
531 size_t cmd_size;
532 struct pmon_lat_setup cmd = {
533 .sub_cmd_id = MRPC_PMON_SETUP_LAT_COUNTER,
534 .count = nr_ports,
535 };
536
537 for (i = 0; i < nr_ports; i++) {
538 cmd.ports[i].egress = egress_port_ids[i];
539 cmd.ports[i].ingress = ingress_port_ids[i];
540 }
541
542 cmd_size = offsetof(struct pmon_lat_setup, ports) +
543 sizeof(cmd.ports[0]) * nr_ports;
544
545 return switchtec_cmd(dev, MRPC_PMON, &cmd, cmd_size, NULL, 0);
546}
547
557int switchtec_lat_setup(struct switchtec_dev *dev, int egress_port_id,
558 int ingress_port_id, int clear)
559{
560 int ret;
561
562 ret = switchtec_lat_setup_many(dev, 1, &egress_port_id,
563 &ingress_port_id);
564 if (ret)
565 return ret;
566
567 if (!clear)
568 return ret;
569
570 return switchtec_lat_get(dev, 1, egress_port_id, NULL, NULL);
571}
572
585int switchtec_lat_get_many(struct switchtec_dev *dev, int nr_ports,
586 int clear, int *egress_port_ids,
587 int *cur_ns, int *max_ns)
588{
589 int ret, i;
590 size_t cmd_size;
591 struct pmon_lat_data resp[nr_ports];
592 struct pmon_lat_get cmd = {
593 .sub_cmd_id = MRPC_PMON_GET_LAT_COUNTER,
594 .count = nr_ports,
595 .clear = clear,
596 };
597
598 for (i = 0; i < nr_ports; i++)
599 cmd.port_ids[i] = egress_port_ids[i];
600
601 cmd_size = offsetof(struct pmon_lat_get, port_ids) +
602 sizeof(cmd.port_ids[0]) * nr_ports;
603
604 ret = switchtec_cmd(dev, MRPC_PMON, &cmd, cmd_size, resp,
605 sizeof(*resp) * nr_ports);
606
607 if (ret)
608 return -1;
609
610 if (cur_ns)
611 for (i = 0; i < nr_ports; i++)
612 cur_ns[i] = resp[i].cur_ns;
613
614 if (max_ns)
615 for (i = 0; i < nr_ports; i++)
616 max_ns[i] = resp[i].max_ns;
617
618 return nr_ports;
619}
620
633int switchtec_lat_get(struct switchtec_dev *dev, int clear,
634 int egress_port_ids, int *cur_ns,
635 int *max_ns)
636{
637 return switchtec_lat_get_many(dev, 1, clear, &egress_port_ids,
638 cur_ns, max_ns);
639}
640
int switchtec_cmd(struct switchtec_dev *dev, uint32_t cmd, const void *payload, size_t payload_len, void *resp, size_t resp_len)
Execute an MRPC command.
Definition platform.c:164
int switchtec_status(struct switchtec_dev *dev, struct switchtec_status **status)
Get the status of all the ports on a switchtec device.
Definition switchtec.c:496
int switchtec_event_wait_for(struct switchtec_dev *dev, enum switchtec_event_id e, int index, struct switchtec_event_summary *res, int timeout_ms)
Block until a specific event occurs.
Definition events.c:369
const char * switchtec_evcntr_type_str(int *type_mask)
Get a string for the event indicated by lowest bit set in the type_mask.
Definition pmon.c:116
int switchtec_evcntr_type_count(void)
Get the number of event counter types.
Definition pmon.c:95
int switchtec_lat_get(struct switchtec_dev *dev, int clear, int egress_port_ids, int *cur_ns, int *max_ns)
Get a single latency counter result.
Definition pmon.c:633
void switchtec_bwcntr_sub(struct switchtec_bwcntr_res *new_cntr, struct switchtec_bwcntr_res *old_cntr)
Subtract all the values between two bwcntr result structures.
Definition pmon.c:339
int switchtec_evcntr_setup(struct switchtec_dev *dev, unsigned stack_id, unsigned cntr_id, struct switchtec_evcntr_setup *setup)
Setup an event counter performance monitor.
Definition pmon.c:139
int switchtec_bwcntr_set_all(struct switchtec_dev *dev, enum switchtec_bw_type bw_type)
Set bandwidth type for all the ports in the system.
Definition pmon.c:387
int switchtec_evcntr_wait(struct switchtec_dev *dev, int timeout_ms)
Block until any event counter has reached its threshold.
Definition pmon.c:325
int switchtec_evcntr_get_both(struct switchtec_dev *dev, unsigned stack_id, unsigned cntr_id, unsigned nr_cntrs, struct switchtec_evcntr_setup *setup, unsigned *counts, int clear)
Retrieve the current counts and setup information for one or more event counters.
Definition pmon.c:301
int switchtec_lat_setup(struct switchtec_dev *dev, int egress_port_id, int ingress_port_id, int clear)
Setup a latency counter.
Definition pmon.c:557
int switchtec_bwcntr_many(struct switchtec_dev *dev, int nr_ports, int *phys_port_ids, int clear, struct switchtec_bwcntr_res *res)
Retrieve the bandwidth counter results for a number of ports.
Definition pmon.c:419
int switchtec_bwcntr_all(struct switchtec_dev *dev, int clear, struct switchtec_port_id **ports, struct switchtec_bwcntr_res **res)
Retrieve the bandwidth counter results for all the ports in the system.
Definition pmon.c:473
uint64_t switchtec_bwcntr_tot(struct switchtec_bwcntr_dir *d)
Get the total.
Definition pmon.c:513
int switchtec_lat_get_many(struct switchtec_dev *dev, int nr_ports, int clear, int *egress_port_ids, int *cur_ns, int *max_ns)
Get a number of latency counter results.
Definition pmon.c:585
int switchtec_lat_setup_many(struct switchtec_dev *dev, int nr_ports, int *egress_port_ids, int *ingress_port_ids)
Setup a number of latency counters.
Definition pmon.c:527
int switchtec_evcntr_get(struct switchtec_dev *dev, unsigned stack_id, unsigned cntr_id, unsigned nr_cntrs, unsigned *res, int clear)
Retrieve the current counts for one or more event counters.
Definition pmon.c:257
int switchtec_bwcntr_set_many(struct switchtec_dev *dev, int nr_ports, int *phys_port_ids, enum switchtec_bw_type bw_type)
Set bandwidth type for a number of ports.
Definition pmon.c:359
int switchtec_evcntr_get_setup(struct switchtec_dev *dev, unsigned stack_id, unsigned cntr_id, unsigned nr_cntrs, struct switchtec_evcntr_setup *res)
Retrieve the setup information for one or more event counters.
Definition pmon.c:214
uint64_t comp
Completion TLP bytes.
Definition switchtec.h:991
uint64_t nonposted
Non-Posted TLP bytes.
Definition switchtec.h:992
Bandwidth counter result struct.
Definition switchtec.h:987
struct switchtec_bwcntr_res::switchtec_bwcntr_dir ingress
Bandwidth into the port.
uint64_t time_us
Time (in microseconds)
Definition switchtec.h:988
struct switchtec_bwcntr_res::switchtec_bwcntr_dir egress
Bandwidth out of the port.
Structure used to setup an event counter.
Definition switchtec.h:951
unsigned threshold
Threshold to count to before generating an interrupt.
Definition switchtec.h:962
enum switchtec_evcntr_type_mask type_mask
Event counter types to count.
Definition switchtec.h:955
Null-terminated list of all event counter types with a name and help text.
Definition switchtec.h:942
Port identification.
Definition switchtec.h:144
unsigned char phys_id
Physical port number.
Definition switchtec.h:150
Port status structure.
Definition switchtec.h:160
struct switchtec_port_id port
Port ID.
Definition switchtec.h:161
Main Switchtec header.
switchtec_bw_type
The types of bandwidth.
Definition switchtec.h:186
@ ALL_TLPS
Mask indicating all TLP types.
Definition switchtec.h:930
@ RCVR_ERR
Receiver Error.
Definition switchtec.h:907
@ RCVR_OFLOW_ERR
Receiver Overflow Error.
Definition switchtec.h:896
@ REPLAY_NUM_ROLLOVER
Replay Number Rollover.
Definition switchtec.h:904
@ COMP_TLP
Completion TLP.
Definition switchtec.h:914
@ BAD_TLP
Bad TLP.
Definition switchtec.h:906
@ NON_POSTED_TLP
Non-Posted TLP.
Definition switchtec.h:915
@ BAD_DLLP
Bad DLLP.
Definition switchtec.h:905
@ SURPRISE_DOWN_ERR
Surprise Down Error.
Definition switchtec.h:899
@ POISONED_TLP_ERR
Poisoned TLP Error.
Definition switchtec.h:898
@ ALL_ERRORS
Mask indicating all possible errors.
Definition switchtec.h:920
@ RCV_CORR_MSG
Receive Correctable Error Message.
Definition switchtec.h:910
@ RCV_NON_FATAL_MSG
Receive Non-FATAL Error Message.
Definition switchtec.h:909
@ NAK_RCVD
NAK Received.
Definition switchtec.h:911
@ UNSUP_REQ_ERR
Unsupported Request Error.
Definition switchtec.h:893
@ POSTED_TLP
Posted TLP.
Definition switchtec.h:913
@ RULE_TABLE_HIT
Rule Search Table Rule Hit.
Definition switchtec.h:912
@ ALL
Mask indicating all event types.
Definition switchtec.h:935
@ ECRC_ERR
ECRC Error.
Definition switchtec.h:894
@ REPLAY_TMR_TIMEOUT
Replay Timer Timeout.
Definition switchtec.h:903
@ HDR_LOG_OFLOW_ERR
Header Log Overflow Error.
Definition switchtec.h:901
@ DATA_LINK_PROTO_ERR
Data Link Protocol Error.
Definition switchtec.h:900
@ UNCOR_INT_ERR
Uncorrectable Internal Error.
Definition switchtec.h:902
@ CMPLTR_ABORT_ERR
Completer Abort Error.
Definition switchtec.h:897
@ RCV_FATAL_MSG
Receive FATAL Error Message.
Definition switchtec.h:908
@ MALFORM_TLP_ERR
Malformed TLP Error.
Definition switchtec.h:895