Switchtec Userspace PROJECT_NUMBER = 4.2
Loading...
Searching...
No Matches
events.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
30#define SWITCHTEC_LIB_CORE
31
32#include "switchtec_priv.h"
33
34#include "switchtec/switchtec.h"
35#include "switchtec/utils.h"
36
37#include <sys/time.h>
38
39#include <errno.h>
40#include <string.h>
41#include <strings.h>
42
57#define EV(t, n, s, d)[SWITCHTEC_ ## t ## _EVT_ ## n] = {\
58 .type = t, \
59 .summary_bit = (1 << (s)), \
60 .short_name = #n, \
61 .desc = d, \
62}
63
64#define GLOBAL SWITCHTEC_EVT_GLOBAL
65#define PART SWITCHTEC_EVT_PART
66#define PFF SWITCHTEC_EVT_PFF
67
68static const struct {
69 enum switchtec_event_id id;
70 enum switchtec_event_type type;
71 uint64_t summary_bit;
72 const char *short_name;
73 const char *desc;
74} events[] = {
75 EV(GLOBAL, STACK_ERROR, 0, "Stack Error"),
76 EV(GLOBAL, PPU_ERROR, 1, "PPU Error"),
77 EV(GLOBAL, ISP_ERROR, 2, "ISP Error"),
78 EV(GLOBAL, SYS_RESET, 3, "System Reset"),
79 EV(GLOBAL, FW_EXC, 4, "Firmware Exception"),
80 EV(GLOBAL, FW_NMI, 5, "Firmware Non-Maskable Interrupt"),
81 EV(GLOBAL, FW_NON_FATAL, 6, "Firmware Non-Fatal Error"),
82 EV(GLOBAL, FW_FATAL, 7, "Firmware Fatal Error"),
83 EV(GLOBAL, TWI_MRPC_COMP, 8, "TWI MRPC Completion"),
84 EV(GLOBAL, TWI_MRPC_COMP_ASYNC, 9, "TWI MRPC Async Completion"),
85 EV(GLOBAL, CLI_MRPC_COMP, 10, "CLI MRPC Completion"),
86 EV(GLOBAL, CLI_MRPC_COMP_ASYNC, 11, "CLI MRPC Async Completion"),
87 EV(GLOBAL, GPIO_INT, 12, "GPIO Interrupt"),
88 EV(GLOBAL, GFMS, 13, "Global Fabric Management Server Event"),
89 EV(PART, PART_RESET, 0, "Partition Reset"),
90 EV(PART, MRPC_COMP, 1, "MRPC Completion"),
91 EV(PART, MRPC_COMP_ASYNC, 2, "MRPC Async Completion"),
92 EV(PART, DYN_PART_BIND_COMP, 3,
93 "Dynamic Partition Binding Completion"),
94 EV(PFF, AER_IN_P2P, 0, "Advanced Error Reporting in P2P Port"),
95 EV(PFF, AER_IN_VEP, 1, "Advanced Error Reporting in vEP"),
96 EV(PFF, DPC, 2, "Downstream Port Containment Event"),
97 EV(PFF, CTS, 3, "Completion Timeout Synthesis Event"),
98 EV(PFF, UEC, 4, "Upstream Error Containment Event"),
99 EV(PFF, HOTPLUG, 5, "Hotplug Event"),
100 EV(PFF, IER, 6, "Internal Error Reporting Event"),
101 EV(PFF, THRESH, 7, "Event Counter Threshold Reached"),
102 EV(PFF, POWER_MGMT, 8, "Power Management Event"),
103 EV(PFF, TLP_THROTTLING, 9, "TLP Throttling Event"),
104 EV(PFF, FORCE_SPEED, 10, "Force Speed Error"),
105 EV(PFF, CREDIT_TIMEOUT, 11, "Credit Timeout"),
106 EV(PFF, LINK_STATE, 12, "Link State Change Event"),
107};
108
109#define EVBIT(t, n, b)[b] = SWITCHTEC_ ## t ## _EVT_ ## n
110static const enum switchtec_event_id global_event_bits[64] = {
111 [0 ... 63] = -1,
112 EVBIT(GLOBAL, STACK_ERROR, 0),
113 EVBIT(GLOBAL, PPU_ERROR, 1),
114 EVBIT(GLOBAL, ISP_ERROR, 2),
115 EVBIT(GLOBAL, SYS_RESET, 3),
116 EVBIT(GLOBAL, FW_EXC, 4),
117 EVBIT(GLOBAL, FW_NMI, 5),
118 EVBIT(GLOBAL, FW_NON_FATAL, 6),
119 EVBIT(GLOBAL, FW_FATAL, 7),
120 EVBIT(GLOBAL, TWI_MRPC_COMP, 8),
121 EVBIT(GLOBAL, TWI_MRPC_COMP_ASYNC, 9),
122 EVBIT(GLOBAL, CLI_MRPC_COMP, 10),
123 EVBIT(GLOBAL, CLI_MRPC_COMP_ASYNC, 11),
124 EVBIT(GLOBAL, GPIO_INT, 12),
125};
126
127static const enum switchtec_event_id part_event_bits[64] = {
128 [0 ... 63] = -1,
129 EVBIT(PART, PART_RESET, 0),
130 EVBIT(PART, MRPC_COMP, 1),
131 EVBIT(PART, MRPC_COMP_ASYNC, 2),
132 EVBIT(PART, DYN_PART_BIND_COMP, 3),
133};
134
135static const enum switchtec_event_id pff_event_bits[64] = {
136 [0 ... 63] = -1,
137 EVBIT(PFF, AER_IN_P2P, 0),
138 EVBIT(PFF, AER_IN_VEP, 1),
139 EVBIT(PFF, DPC, 2),
140 EVBIT(PFF, CTS, 3),
141 EVBIT(PFF, UEC, 4),
142 EVBIT(PFF, HOTPLUG, 5),
143 EVBIT(PFF, IER, 6),
144 EVBIT(PFF, THRESH, 7),
145 EVBIT(PFF, POWER_MGMT, 8),
146 EVBIT(PFF, TLP_THROTTLING, 9),
147 EVBIT(PFF, FORCE_SPEED, 10),
148 EVBIT(PFF, CREDIT_TIMEOUT, 11),
149 EVBIT(PFF, LINK_STATE, 12),
150};
151
152static void set_all_parts(struct switchtec_event_summary *sum, uint64_t bit)
153{
154 int i;
155
156 for (i = 0; i < ARRAY_SIZE(sum->part); i++)
157 sum->part[i] |= bit;
158}
159
160static void set_all_pffs(struct switchtec_event_summary *sum, uint64_t bit)
161{
162 int i;
163
164 for (i = 0; i < ARRAY_SIZE(sum->pff); i++)
165 sum->pff[i] |= bit;
166}
167
176 enum switchtec_event_id e,
177 int index)
178{
179 uint64_t bit = events[e].summary_bit;
180
181 switch (events[e].type) {
182 case GLOBAL:
183 sum->global |= bit;
184 break;
185 case PART:
186 if (index == SWITCHTEC_EVT_IDX_LOCAL) {
187 sum->local_part |= bit;
188 } else if (index == SWITCHTEC_EVT_IDX_ALL) {
189 set_all_parts(sum, bit);
190 } else if (index < 0 || index >= ARRAY_SIZE(sum->part)) {
191 errno = EINVAL;
192 return -EINVAL;
193 } else {
194 sum->part[index] |= bit;
195 }
196 break;
197 case PFF:
198 if (index == SWITCHTEC_EVT_IDX_ALL) {
199 set_all_pffs(sum, bit);
200 } else if (index < 0 || index >= ARRAY_SIZE(sum->pff)) {
201 errno = EINVAL;
202 return -EINVAL;
203 } else {
204 sum->pff[index] |= bit;
205 }
206 break;
207 }
208
209 return 0;
210}
211
220 enum switchtec_event_id e,
221 int index)
222{
223 uint64_t bit = events[e].summary_bit;
224
225 switch (events[e].type) {
226 case GLOBAL:
227 return sum->global & bit;
228 case PART:
229 return sum->part[index] & bit;
230 case PFF:
231 return sum->pff[index] & bit;
232 }
233
234 return 0;
235}
236
249 enum switchtec_event_id *e,
250 int *idx)
251{
252 int bit;
253
254 if (!idx || !e)
255 return -EINVAL;
256
257 *idx = 0;
258
259 bit = ffs(sum->global) - 1;
260 if (bit >= 0) {
261 *e = global_event_bits[bit];
262 sum->global &= ~(1 << bit);
263 return 1;
264 }
265
266 for (*idx = 0; *idx < ARRAY_SIZE(sum->part); (*idx)++) {
267 bit = ffs(sum->part[*idx]) - 1;
268 if (bit < 0)
269 continue;
270
271 *e = part_event_bits[bit];
272 sum->part[*idx] &= ~(1 << bit);
273 return 1;
274 }
275
276 for (*idx = 0; *idx < ARRAY_SIZE(sum->pff); (*idx)++) {
277 bit = ffs(sum->pff[*idx]) - 1;
278 if (bit < 0)
279 continue;
280
281 *e = pff_event_bits[bit];
282 sum->pff[*idx] &= ~(1 << bit);
283 return 1;
284 }
285
286 return 0;
287}
288
297int switchtec_event_check(struct switchtec_dev *dev,
298 struct switchtec_event_summary *chk,
299 struct switchtec_event_summary *res)
300{
301 struct switchtec_event_summary res_tmp;
302 int i;
303 int ret;
304
305 if (!chk)
306 return -EINVAL;
307
308 if (!res)
309 res = &res_tmp;
310
311 ret = switchtec_event_summary(dev, res);
312 if (ret)
313 return ret;
314
315 if (chk->global & res->global)
316 return 1;
317
318 if (chk->part_bitmap & res->part_bitmap)
319 return 1;
320
321 if (chk->local_part & res->local_part)
322 return 1;
323
324 for (i = 0; i < SWITCHTEC_MAX_PARTS; i++)
325 if (chk->part[i] & res->part[i])
326 return 1;
327
328 for (i = 0; i < SWITCHTEC_MAX_PFF_CSR; i++)
329 if (chk->pff[i] & res->pff[i])
330 return 1;
331
332 return 0;
333}
334
344 const char **name,
345 const char **desc)
346{
347 if (e <= SWITCHTEC_EVT_INVALID || e >= SWITCHTEC_MAX_EVENTS)
348 return -1;
349
350 if (name)
351 *name = events[e].short_name;
352
353 if (desc)
354 *desc = events[e].desc;
355
356 return events[e].type;
357}
358
369int switchtec_event_wait_for(struct switchtec_dev *dev,
370 enum switchtec_event_id e, int index,
371 struct switchtec_event_summary *res,
372 int timeout_ms)
373{
374 struct timeval tv;
375 long long start, now;
376 struct switchtec_event_summary wait_for = {0};
377 int ret;
378
379 if (dev->ops->event_wait_for)
380 return dev->ops->event_wait_for(dev, e, index, res, timeout_ms);
381
382 ret = switchtec_event_summary_set(&wait_for, e, index);
383 if (ret)
384 return ret;
385
386 ret = switchtec_event_ctl(dev, e, index,
387 SWITCHTEC_EVT_FLAG_CLEAR |
388 SWITCHTEC_EVT_FLAG_EN_POLL,
389 NULL);
390 if (ret < 0)
391 return ret;
392
393 ret = gettimeofday(&tv, NULL);
394 if (ret)
395 return ret;
396
397 now = start = ((tv.tv_sec) * 1000 + tv.tv_usec / 1000);
398
399 while (1) {
400 ret = switchtec_event_wait(dev, timeout_ms > 0 ?
401 now - start + timeout_ms : -1);
402 if (ret < 0)
403 return ret;
404
405 if (ret == 0)
406 goto next;
407
408 ret = switchtec_event_check(dev, &wait_for, res);
409 if (ret < 0)
410 return ret;
411
412 if (ret)
413 return 1;
414
415next:
416 ret = gettimeofday(&tv, NULL);
417 if (ret)
418 return ret;
419
420 now = ((tv.tv_sec) * 1000 + tv.tv_usec / 1000);
421
422 if (timeout_ms > 0 && now - start >= timeout_ms) {
423 ret = switchtec_event_summary(dev, res);
424 return ret;
425 }
426 }
427}
428
int switchtec_event_ctl(struct switchtec_dev *dev, enum switchtec_event_id e, int index, int flags, uint32_t data[5])
Enable, disable and clear events or retrieve event data.
Definition platform.c:313
int switchtec_event_summary_iter(struct switchtec_event_summary *sum, enum switchtec_event_id *e, int *idx)
Iterate through all set bits in an event summary structure.
Definition events.c:248
enum switchtec_event_type switchtec_event_info(enum switchtec_event_id e, const char **name, const char **desc)
Get the name and description strings as well as the type (global, partition or pff) for a specific ev...
Definition events.c:343
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
int switchtec_event_summary_set(struct switchtec_event_summary *sum, enum switchtec_event_id e, int index)
Set a bit corresponding to an event in a summary structure.
Definition events.c:175
int switchtec_event_summary(struct switchtec_dev *dev, struct switchtec_event_summary *sum)
Retrieve a summary of all the events that have occurred in the switch.
Definition platform.c:297
int switchtec_event_wait(struct switchtec_dev *dev, int timeout_ms)
Wait for any event to occur (typically just an interrupt)
Definition platform.c:329
int switchtec_event_summary_test(struct switchtec_event_summary *sum, enum switchtec_event_id e, int index)
Test if a bit corresponding to an event is set in a summary structure.
Definition events.c:219
int switchtec_event_check(struct switchtec_dev *dev, struct switchtec_event_summary *chk, struct switchtec_event_summary *res)
Check if one or more events have occurred.
Definition events.c:297
Event summary bitmaps.
Definition switchtec.h:289
uint64_t part_bitmap
Bitmap of partitions with active events.
Definition switchtec.h:291
uint64_t global
Bitmap of global events.
Definition switchtec.h:290
unsigned part[SWITCHTEC_MAX_PARTS]
Bitmap of events in each partition.
Definition switchtec.h:295
unsigned local_part
Bitmap of events in the local partition.
Definition switchtec.h:292
unsigned pff[SWITCHTEC_MAX_PFF_CSR]
Bitmap of events in each port function.
Definition switchtec.h:298
Main Switchtec header.
switchtec_event_id
Enumeration of all possible events.
Definition switchtec.h:304
switchtec_event_type
There are three event types indicated by this enumeration: global, partition and port function.
Definition switchtec.h:775