Switchtec Userspace PROJECT_NUMBER = 4.4
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
29
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
56
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 EV(GLOBAL, ASSERT_ERR, 3, "Global Assert Error"),
108};
109
110#define EVBIT(t, n, b)[b] = SWITCHTEC_ ## t ## _EVT_ ## n
111static const enum switchtec_event_id global_event_bits[64] = {
112 [0 ... 63] = -1,
113 EVBIT(GLOBAL, STACK_ERROR, 0),
114 EVBIT(GLOBAL, PPU_ERROR, 1),
115 EVBIT(GLOBAL, ISP_ERROR, 2),
116 EVBIT(GLOBAL, SYS_RESET, 3),
117 EVBIT(GLOBAL, FW_EXC, 4),
118 EVBIT(GLOBAL, FW_NMI, 5),
119 EVBIT(GLOBAL, FW_NON_FATAL, 6),
120 EVBIT(GLOBAL, FW_FATAL, 7),
121 EVBIT(GLOBAL, TWI_MRPC_COMP, 8),
122 EVBIT(GLOBAL, TWI_MRPC_COMP_ASYNC, 9),
123 EVBIT(GLOBAL, CLI_MRPC_COMP, 10),
124 EVBIT(GLOBAL, CLI_MRPC_COMP_ASYNC, 11),
125 EVBIT(GLOBAL, GPIO_INT, 12),
126};
127
128static const enum switchtec_event_id part_event_bits[64] = {
129 [0 ... 63] = -1,
130 EVBIT(PART, PART_RESET, 0),
131 EVBIT(PART, MRPC_COMP, 1),
132 EVBIT(PART, MRPC_COMP_ASYNC, 2),
133 EVBIT(PART, DYN_PART_BIND_COMP, 3),
134};
135
136static const enum switchtec_event_id pff_event_bits[64] = {
137 [0 ... 63] = -1,
138 EVBIT(PFF, AER_IN_P2P, 0),
139 EVBIT(PFF, AER_IN_VEP, 1),
140 EVBIT(PFF, DPC, 2),
141 EVBIT(PFF, CTS, 3),
142 EVBIT(PFF, UEC, 4),
143 EVBIT(PFF, HOTPLUG, 5),
144 EVBIT(PFF, IER, 6),
145 EVBIT(PFF, THRESH, 7),
146 EVBIT(PFF, POWER_MGMT, 8),
147 EVBIT(PFF, TLP_THROTTLING, 9),
148 EVBIT(PFF, FORCE_SPEED, 10),
149 EVBIT(PFF, CREDIT_TIMEOUT, 11),
150 EVBIT(PFF, LINK_STATE, 12),
151};
152
153static void set_all_parts(struct switchtec_event_summary *sum, uint64_t bit)
154{
155 int i;
156
157 for (i = 0; i < ARRAY_SIZE(sum->part); i++)
158 sum->part[i] |= bit;
159}
160
161static void set_all_pffs(struct switchtec_event_summary *sum, uint64_t bit)
162{
163 int i;
164
165 for (i = 0; i < ARRAY_SIZE(sum->pff); i++)
166 sum->pff[i] |= bit;
167}
168
177 enum switchtec_event_id e,
178 int index)
179{
180 uint64_t bit = events[e].summary_bit;
181
182 switch (events[e].type) {
183 case GLOBAL:
184 sum->global |= bit;
185 break;
186 case PART:
187 if (index == SWITCHTEC_EVT_IDX_LOCAL) {
188 sum->local_part |= bit;
189 } else if (index == SWITCHTEC_EVT_IDX_ALL) {
190 set_all_parts(sum, bit);
191 } else if (index < 0 || index >= ARRAY_SIZE(sum->part)) {
192 errno = EINVAL;
193 return -EINVAL;
194 } else {
195 sum->part[index] |= bit;
196 }
197 break;
198 case PFF:
199 if (index == SWITCHTEC_EVT_IDX_ALL) {
200 set_all_pffs(sum, bit);
201 } else if (index < 0 || index >= ARRAY_SIZE(sum->pff)) {
202 errno = EINVAL;
203 return -EINVAL;
204 } else {
205 sum->pff[index] |= bit;
206 }
207 break;
208 }
209
210 return 0;
211}
212
221 enum switchtec_event_id e,
222 int index)
223{
224 uint64_t bit = events[e].summary_bit;
225
226 switch (events[e].type) {
227 case GLOBAL:
228 return sum->global & bit;
229 case PART:
230 return sum->part[index] & bit;
231 case PFF:
232 return sum->pff[index] & bit;
233 }
234
235 return 0;
236}
237
249int switchtec_event_summary_iter(struct switchtec_dev *dev,
250 struct switchtec_event_summary *sum,
251 enum switchtec_event_id *e,
252 int *idx)
253{
254 int bit;
255
256 if (!idx || !e)
257 return -EINVAL;
258
259 *idx = 0;
260
261 bit = ffs(sum->global) - 1;
262 if (bit >= 0) {
263 if (bit == 3 && dev && switchtec_is_gen6(dev))
264 *e = SWITCHTEC_GLOBAL_EVT_ASSERT_ERR;
265 else
266 *e = global_event_bits[bit];
267 sum->global &= ~(1 << bit);
268 return 1;
269 }
270
271 for (*idx = 0; *idx < ARRAY_SIZE(sum->part); (*idx)++) {
272 bit = ffs(sum->part[*idx]) - 1;
273 if (bit < 0)
274 continue;
275
276 *e = part_event_bits[bit];
277 sum->part[*idx] &= ~(1 << bit);
278 return 1;
279 }
280
281 for (*idx = 0; *idx < ARRAY_SIZE(sum->pff); (*idx)++) {
282 bit = ffs(sum->pff[*idx]) - 1;
283 if (bit < 0)
284 continue;
285
286 *e = pff_event_bits[bit];
287 sum->pff[*idx] &= ~(1 << bit);
288 return 1;
289 }
290
291 return 0;
292}
293
302int switchtec_event_check(struct switchtec_dev *dev,
303 struct switchtec_event_summary *chk,
304 struct switchtec_event_summary *res)
305{
306 struct switchtec_event_summary res_tmp;
307 int i;
308 int ret;
309
310 if (!chk)
311 return -EINVAL;
312
313 if (!res)
314 res = &res_tmp;
315
316 ret = switchtec_event_summary(dev, res);
317 if (ret)
318 return ret;
319
320 if (chk->global & res->global)
321 return 1;
322
323 if (chk->part_bitmap & res->part_bitmap)
324 return 1;
325
326 if (chk->local_part & res->local_part)
327 return 1;
328
329 for (i = 0; i < SWITCHTEC_MAX_PARTS; i++)
330 if (chk->part[i] & res->part[i])
331 return 1;
332
333 for (i = 0; i < SWITCHTEC_MAX_PFF_CSR; i++)
334 if (chk->pff[i] & res->pff[i])
335 return 1;
336
337 return 0;
338}
339
349 const char **name,
350 const char **desc)
351{
352 if (e <= SWITCHTEC_EVT_INVALID || e >= SWITCHTEC_MAX_EVENTS)
353 return -1;
354
355 if (name)
356 *name = events[e].short_name;
357
358 if (desc)
359 *desc = events[e].desc;
360
361 return events[e].type;
362}
363
374int switchtec_event_wait_for(struct switchtec_dev *dev,
375 enum switchtec_event_id e, int index,
376 struct switchtec_event_summary *res,
377 int timeout_ms)
378{
379 struct timeval tv;
380 long long start, now;
381 struct switchtec_event_summary wait_for = {0};
382 int ret;
383
384 if (dev->ops->event_wait_for)
385 return dev->ops->event_wait_for(dev, e, index, res, timeout_ms);
386
387 ret = switchtec_event_summary_set(&wait_for, e, index);
388 if (ret)
389 return ret;
390
391 ret = switchtec_event_ctl(dev, e, index,
392 SWITCHTEC_EVT_FLAG_CLEAR |
393 SWITCHTEC_EVT_FLAG_EN_POLL,
394 NULL);
395 if (ret < 0)
396 return ret;
397
398 ret = gettimeofday(&tv, NULL);
399 if (ret)
400 return ret;
401
402 now = start = ((tv.tv_sec) * 1000 + tv.tv_usec / 1000);
403
404 while (1) {
405 ret = switchtec_event_wait(dev, timeout_ms > 0 ?
406 now - start + timeout_ms : -1);
407 if (ret < 0)
408 return ret;
409
410 if (ret == 0)
411 goto next;
412
413 ret = switchtec_event_check(dev, &wait_for, res);
414 if (ret < 0)
415 return ret;
416
417 if (ret)
418 return 1;
419
420next:
421 ret = gettimeofday(&tv, NULL);
422 if (ret)
423 return ret;
424
425 now = ((tv.tv_sec) * 1000 + tv.tv_usec / 1000);
426
427 if (timeout_ms > 0 && now - start >= timeout_ms) {
428 ret = switchtec_event_summary(dev, res);
429 return ret;
430 }
431 }
432}
433
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:328
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:348
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:374
int switchtec_event_summary_iter(struct switchtec_dev *dev, 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:249
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:176
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:312
int switchtec_event_wait(struct switchtec_dev *dev, int timeout_ms)
Wait for any event to occur (typically just an interrupt).
Definition platform.c:344
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:220
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:302
Event summary bitmaps.
Definition switchtec.h:343
uint64_t part_bitmap
Bitmap of partitions with active events.
Definition switchtec.h:345
uint64_t global
Bitmap of global events.
Definition switchtec.h:344
unsigned part[SWITCHTEC_MAX_PARTS]
Bitmap of events in each partition.
Definition switchtec.h:349
unsigned local_part
Bitmap of events in the local partition.
Definition switchtec.h:346
unsigned pff[SWITCHTEC_MAX_PFF_CSR]
Bitmap of events in each port function.
Definition switchtec.h:352
Main Switchtec header.
switchtec_event_id
Enumeration of all possible events.
Definition switchtec.h:358
static int switchtec_is_gen6(struct switchtec_dev *dev)
Return whether a Switchtec device is a Gen 6 device.
Definition switchtec.h:524
switchtec_event_type
There are three event types indicated by this enumeration: global, partition and port function.
Definition switchtec.h:1024