1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (C) 2018 Google, Inc. */
3
4 #include "gasket_interrupt.h"
5
6 #include "gasket_constants.h"
7 #include "gasket_core.h"
8 #include "gasket_sysfs.h"
9 #include <linux/device.h>
10 #include <linux/interrupt.h>
11 #include <linux/printk.h>
12 #include <linux/version.h>
13 #ifdef GASKET_KERNEL_TRACE_SUPPORT
14 #define CREATE_TRACE_POINTS
15 #include <trace/events/gasket_interrupt.h>
16 #else
17 #define trace_gasket_interrupt_event(x, ...)
18 #endif
19 /* Retry attempts if the requested number of interrupts aren't available. */
20 #define MSIX_RETRY_COUNT 3
21
22 /* Instance interrupt management data. */
23 struct gasket_interrupt_data {
24 /* The name associated with this interrupt data. */
25 const char *name;
26
27 /* Interrupt type. See gasket_interrupt_type in gasket_core.h */
28 int type;
29
30 /* The PCI device [if any] associated with the owning device. */
31 struct pci_dev *pci_dev;
32
33 /* Set to 1 if MSI-X has successfully been configred, 0 otherwise. */
34 int msix_configured;
35
36 /* The number of interrupts requested by the owning device. */
37 int num_interrupts;
38
39 /* A pointer to the interrupt descriptor struct for this device. */
40 const struct gasket_interrupt_desc *interrupts;
41
42 /* The index of the bar into which interrupts should be mapped. */
43 int interrupt_bar_index;
44
45 /* The width of a single interrupt in a packed interrupt register. */
46 int pack_width;
47
48 /* offset of wire interrupt registers */
49 const struct gasket_wire_interrupt_offsets *wire_interrupt_offsets;
50
51 /*
52 * Design-wise, these elements should be bundled together, but
53 * pci_enable_msix's interface requires that they be managed
54 * individually (requires array of struct msix_entry).
55 */
56
57 /* The number of successfully configured interrupts. */
58 int num_configured;
59
60 /* The MSI-X data for each requested/configured interrupt. */
61 struct msix_entry *msix_entries;
62
63 /* The eventfd "callback" data for each interrupt. */
64 struct eventfd_ctx **eventfd_ctxs;
65
66 /* The number of times each interrupt has been called. */
67 ulong *interrupt_counts;
68
69 /* Linux IRQ number. */
70 int irq;
71 };
72
73 /* Structures to display interrupt counts in sysfs. */
74 enum interrupt_sysfs_attribute_type {
75 ATTR_INTERRUPT_COUNTS,
76 };
77
78 /* Set up device registers for interrupt handling. */
gasket_interrupt_setup(struct gasket_dev * gasket_dev)79 static void gasket_interrupt_setup(struct gasket_dev *gasket_dev)
80 {
81 int i;
82 int pack_shift;
83 ulong mask;
84 ulong value;
85 struct gasket_interrupt_data *interrupt_data =
86 gasket_dev->interrupt_data;
87
88 if (!interrupt_data) {
89 dev_dbg(gasket_dev->dev, "Interrupt data is not initialized\n");
90 return;
91 }
92
93 dev_dbg(gasket_dev->dev, "Running interrupt setup\n");
94
95 if (interrupt_data->type == PLATFORM_WIRE ||
96 interrupt_data->type == PCI_MSI) {
97 /* Nothing needs to be done for platform or PCI devices. */
98 return;
99 }
100
101 if (interrupt_data->type != PCI_MSIX) {
102 dev_dbg(gasket_dev->dev,
103 "Cannot handle unsupported interrupt type %d\n",
104 interrupt_data->type);
105 return;
106 }
107
108 /* Setup the MSIX table. */
109
110 for (i = 0; i < interrupt_data->num_interrupts; i++) {
111 /*
112 * If the interrupt is not packed, we can write the index into
113 * the register directly. If not, we need to deal with a read-
114 * modify-write and shift based on the packing index.
115 */
116 dev_dbg(gasket_dev->dev,
117 "Setting up interrupt index %d with index 0x%llx and "
118 "packing %d\n",
119 interrupt_data->interrupts[i].index,
120 interrupt_data->interrupts[i].reg,
121 interrupt_data->interrupts[i].packing);
122 if (interrupt_data->interrupts[i].packing == UNPACKED) {
123 value = interrupt_data->interrupts[i].index;
124 } else {
125 switch (interrupt_data->interrupts[i].packing) {
126 case PACK_0:
127 pack_shift = 0;
128 break;
129 case PACK_1:
130 pack_shift = interrupt_data->pack_width;
131 break;
132 case PACK_2:
133 pack_shift = 2 * interrupt_data->pack_width;
134 break;
135 case PACK_3:
136 pack_shift = 3 * interrupt_data->pack_width;
137 break;
138 default:
139 dev_dbg(gasket_dev->dev,
140 "Found interrupt description with "
141 "unknown enum %d\n",
142 interrupt_data->interrupts[i].packing);
143 return;
144 }
145
146 mask = ~(0xFFFF << pack_shift);
147 value = gasket_dev_read_64(gasket_dev,
148 interrupt_data->interrupt_bar_index,
149 interrupt_data->interrupts[i].reg);
150 value &= mask;
151 value |= interrupt_data->interrupts[i].index
152 << pack_shift;
153 }
154 gasket_dev_write_64(gasket_dev, value,
155 interrupt_data->interrupt_bar_index,
156 interrupt_data->interrupts[i].reg);
157 }
158 }
159
gasket_msix_interrupt_handler(int irq,void * dev_id)160 static irqreturn_t gasket_msix_interrupt_handler(int irq, void *dev_id)
161 {
162 struct eventfd_ctx *ctx;
163 struct gasket_interrupt_data *interrupt_data = dev_id;
164 int interrupt = -1;
165 int i;
166
167 /* If this linear lookup is a problem, we can maintain a map/hash. */
168 for (i = 0; i < interrupt_data->num_interrupts; i++) {
169 if (interrupt_data->msix_entries[i].vector == irq) {
170 interrupt = interrupt_data->msix_entries[i].entry;
171 break;
172 }
173 }
174 if (interrupt == -1) {
175 pr_err("Received unknown irq %d\n", irq);
176 return IRQ_HANDLED;
177 }
178 trace_gasket_interrupt_event(interrupt_data->name, interrupt);
179
180 ctx = interrupt_data->eventfd_ctxs[interrupt];
181 if (ctx)
182 eventfd_signal(ctx, 1);
183
184 ++(interrupt_data->interrupt_counts[interrupt]);
185
186 return IRQ_HANDLED;
187 }
188
189 static int
gasket_interrupt_msix_init(struct gasket_interrupt_data * interrupt_data)190 gasket_interrupt_msix_init(struct gasket_interrupt_data *interrupt_data)
191 {
192 int ret = 1;
193 int i;
194
195 for (i = 0; i < interrupt_data->num_interrupts; i++) {
196 interrupt_data->msix_entries[i].entry = i;
197 interrupt_data->msix_entries[i].vector = 0;
198 interrupt_data->eventfd_ctxs[i] = NULL;
199 }
200
201 /* Retry MSIX_RETRY_COUNT times if not enough IRQs are available. */
202 for (i = 0; i < MSIX_RETRY_COUNT && ret > 0; i++)
203 ret = pci_enable_msix_exact(interrupt_data->pci_dev,
204 interrupt_data->msix_entries,
205 interrupt_data->num_interrupts);
206
207 if (ret)
208 return ret > 0 ? -EBUSY : ret;
209 interrupt_data->msix_configured = 1;
210
211 for (i = 0; i < interrupt_data->num_interrupts; i++) {
212 ret = request_irq(interrupt_data->msix_entries[i].vector,
213 gasket_msix_interrupt_handler, 0,
214 interrupt_data->name, interrupt_data);
215
216 if (ret) {
217 dev_err(&interrupt_data->pci_dev->dev,
218 "Cannot get IRQ for interrupt %d, vector %d; "
219 "%d\n",
220 i, interrupt_data->msix_entries[i].vector, ret);
221 return ret;
222 }
223
224 interrupt_data->num_configured++;
225 }
226
227 return 0;
228 }
229
230 /*
231 * On QCM DragonBoard, we exit gasket_interrupt_msix_init() and kernel interrupt
232 * setup code with MSIX vectors masked. This is wrong because nothing else in
233 * the driver will normally touch the MSIX vectors.
234 *
235 * As a temporary hack, force unmasking there.
236 *
237 * TODO: Figure out why QCM kernel doesn't unmask the MSIX vectors, after
238 * gasket_interrupt_msix_init(), and remove this code.
239 */
force_msix_interrupt_unmasking(struct gasket_dev * gasket_dev)240 static void force_msix_interrupt_unmasking(struct gasket_dev *gasket_dev)
241 {
242 int i;
243 #define MSIX_VECTOR_SIZE 16
244 #define MSIX_MASK_BIT_OFFSET 12
245 #define APEX_BAR2_REG_KERNEL_HIB_MSIX_TABLE 0x46800
246 for (i = 0; i < gasket_dev->interrupt_data->num_configured; i++) {
247 /* Check if the MSIX vector is unmasked */
248 ulong location = APEX_BAR2_REG_KERNEL_HIB_MSIX_TABLE +
249 MSIX_MASK_BIT_OFFSET + i * MSIX_VECTOR_SIZE;
250 u32 mask =
251 gasket_dev_read_32(gasket_dev,
252 gasket_dev->interrupt_data->interrupt_bar_index,
253 location);
254 if (!(mask & 1))
255 continue;
256 /* Unmask the msix vector (clear 32 bits) */
257 gasket_dev_write_32(gasket_dev, 0,
258 gasket_dev->interrupt_data->interrupt_bar_index,
259 location);
260 }
261 #undef MSIX_VECTOR_SIZE
262 #undef MSIX_MASK_BIT_OFFSET
263 #undef APEX_BAR2_REG_KERNEL_HIB_MSIX_TABLE
264 }
265
interrupt_sysfs_show(struct device * device,struct device_attribute * attr,char * buf)266 static ssize_t interrupt_sysfs_show(struct device *device,
267 struct device_attribute *attr, char *buf)
268 {
269 int i, ret;
270 ssize_t written = 0, total_written = 0;
271 struct gasket_interrupt_data *interrupt_data;
272 struct gasket_dev *gasket_dev;
273 struct gasket_sysfs_attribute *gasket_attr;
274 enum interrupt_sysfs_attribute_type sysfs_type;
275
276 gasket_dev = gasket_sysfs_get_device_data(device);
277 if (!gasket_dev) {
278 dev_dbg(device, "No sysfs mapping found for device\n");
279 return 0;
280 }
281
282 gasket_attr = gasket_sysfs_get_attr(device, attr);
283 if (!gasket_attr) {
284 dev_dbg(device, "No sysfs attr data found for device\n");
285 gasket_sysfs_put_device_data(device, gasket_dev);
286 return 0;
287 }
288
289 sysfs_type = (enum interrupt_sysfs_attribute_type)
290 gasket_attr->data.attr_type;
291 interrupt_data = gasket_dev->interrupt_data;
292 switch (sysfs_type) {
293 case ATTR_INTERRUPT_COUNTS:
294 for (i = 0; i < interrupt_data->num_interrupts; ++i) {
295 written =
296 scnprintf(buf, PAGE_SIZE - total_written,
297 "0x%02x: %ld\n", i,
298 interrupt_data->interrupt_counts[i]);
299 total_written += written;
300 buf += written;
301 }
302 ret = total_written;
303 break;
304 default:
305 dev_dbg(gasket_dev->dev, "Unknown attribute: %s\n",
306 attr->attr.name);
307 ret = 0;
308 break;
309 }
310
311 gasket_sysfs_put_attr(device, gasket_attr);
312 gasket_sysfs_put_device_data(device, gasket_dev);
313 return ret;
314 }
315
316 static struct gasket_sysfs_attribute interrupt_sysfs_attrs[] = {
317 GASKET_SYSFS_RO(interrupt_counts, interrupt_sysfs_show,
318 ATTR_INTERRUPT_COUNTS),
319 GASKET_END_OF_ATTR_ARRAY,
320 };
321
gasket_interrupt_init(struct gasket_dev * gasket_dev,const char * name,int type,const struct gasket_interrupt_desc * interrupts,int num_interrupts,int pack_width,int bar_index,const struct gasket_wire_interrupt_offsets * wire_int_offsets)322 int gasket_interrupt_init(struct gasket_dev *gasket_dev, const char *name,
323 int type,
324 const struct gasket_interrupt_desc *interrupts,
325 int num_interrupts, int pack_width, int bar_index,
326 const struct gasket_wire_interrupt_offsets *wire_int_offsets)
327 {
328 int ret;
329 struct gasket_interrupt_data *interrupt_data;
330
331 interrupt_data = kzalloc(sizeof(struct gasket_interrupt_data),
332 GFP_KERNEL);
333 if (!interrupt_data)
334 return -ENOMEM;
335 gasket_dev->interrupt_data = interrupt_data;
336 interrupt_data->name = name;
337 interrupt_data->type = type;
338 interrupt_data->pci_dev = gasket_dev->pci_dev;
339 interrupt_data->num_interrupts = num_interrupts;
340 interrupt_data->interrupts = interrupts;
341 interrupt_data->interrupt_bar_index = bar_index;
342 interrupt_data->pack_width = pack_width;
343 interrupt_data->num_configured = 0;
344 interrupt_data->wire_interrupt_offsets = wire_int_offsets;
345
346 /* Allocate all dynamic structures. */
347 interrupt_data->msix_entries = kcalloc(num_interrupts,
348 sizeof(struct msix_entry),
349 GFP_KERNEL);
350 if (!interrupt_data->msix_entries) {
351 kfree(interrupt_data);
352 return -ENOMEM;
353 }
354
355 interrupt_data->eventfd_ctxs = kcalloc(num_interrupts,
356 sizeof(struct eventfd_ctx *),
357 GFP_KERNEL);
358 if (!interrupt_data->eventfd_ctxs) {
359 kfree(interrupt_data->msix_entries);
360 kfree(interrupt_data);
361 return -ENOMEM;
362 }
363
364 interrupt_data->interrupt_counts = kcalloc(num_interrupts,
365 sizeof(ulong),
366 GFP_KERNEL);
367 if (!interrupt_data->interrupt_counts) {
368 kfree(interrupt_data->eventfd_ctxs);
369 kfree(interrupt_data->msix_entries);
370 kfree(interrupt_data);
371 return -ENOMEM;
372 }
373
374 switch (interrupt_data->type) {
375 case PCI_MSIX:
376 ret = gasket_interrupt_msix_init(interrupt_data);
377 if (ret)
378 break;
379 force_msix_interrupt_unmasking(gasket_dev);
380 break;
381
382 case PCI_MSI:
383 case PLATFORM_WIRE:
384 default:
385 dev_err(gasket_dev->dev,
386 "Cannot handle unsupported interrupt type %d\n",
387 interrupt_data->type);
388 ret = -EINVAL;
389 }
390
391 if (ret) {
392 /* Failing to setup interrupts will cause the device to report
393 * GASKET_STATUS_LAMED. But it is not fatal.
394 */
395 dev_warn(gasket_dev->dev,
396 "Couldn't initialize interrupts: %d\n", ret);
397 return 0;
398 }
399
400 gasket_interrupt_setup(gasket_dev);
401 gasket_sysfs_create_entries(gasket_dev->dev_info.device,
402 interrupt_sysfs_attrs);
403
404 return 0;
405 }
406
407 static void
gasket_interrupt_msix_cleanup(struct gasket_interrupt_data * interrupt_data)408 gasket_interrupt_msix_cleanup(struct gasket_interrupt_data *interrupt_data)
409 {
410 int i;
411
412 for (i = 0; i < interrupt_data->num_configured; i++)
413 free_irq(interrupt_data->msix_entries[i].vector,
414 interrupt_data);
415 interrupt_data->num_configured = 0;
416
417 if (interrupt_data->msix_configured)
418 pci_disable_msix(interrupt_data->pci_dev);
419 interrupt_data->msix_configured = 0;
420 }
421
gasket_interrupt_reinit(struct gasket_dev * gasket_dev)422 int gasket_interrupt_reinit(struct gasket_dev *gasket_dev)
423 {
424 int ret;
425
426 if (!gasket_dev->interrupt_data) {
427 dev_dbg(gasket_dev->dev,
428 "Attempted to reinit uninitialized interrupt data\n");
429 return -EINVAL;
430 }
431
432 switch (gasket_dev->interrupt_data->type) {
433 case PCI_MSIX:
434 gasket_interrupt_msix_cleanup(gasket_dev->interrupt_data);
435 ret = gasket_interrupt_msix_init(gasket_dev->interrupt_data);
436 if (ret)
437 break;
438 force_msix_interrupt_unmasking(gasket_dev);
439 break;
440
441 case PCI_MSI:
442 case PLATFORM_WIRE:
443 default:
444 dev_dbg(gasket_dev->dev,
445 "Cannot handle unsupported interrupt type %d\n",
446 gasket_dev->interrupt_data->type);
447 ret = -EINVAL;
448 }
449
450 if (ret) {
451 /* Failing to setup MSIx will cause the device
452 * to report GASKET_STATUS_LAMED, but is not fatal.
453 */
454 dev_warn(gasket_dev->dev, "Couldn't init msix: %d\n", ret);
455 return 0;
456 }
457
458 gasket_interrupt_setup(gasket_dev);
459
460 return 0;
461 }
462
463 /* See gasket_interrupt.h for description. */
gasket_interrupt_reset_counts(struct gasket_dev * gasket_dev)464 int gasket_interrupt_reset_counts(struct gasket_dev *gasket_dev)
465 {
466 dev_dbg(gasket_dev->dev, "Clearing interrupt counts\n");
467 memset(gasket_dev->interrupt_data->interrupt_counts, 0,
468 gasket_dev->interrupt_data->num_interrupts *
469 sizeof(*gasket_dev->interrupt_data->interrupt_counts));
470 return 0;
471 }
472
473 /* See gasket_interrupt.h for description. */
gasket_interrupt_cleanup(struct gasket_dev * gasket_dev)474 void gasket_interrupt_cleanup(struct gasket_dev *gasket_dev)
475 {
476 struct gasket_interrupt_data *interrupt_data =
477 gasket_dev->interrupt_data;
478 /*
479 * It is possible to get an error code from gasket_interrupt_init
480 * before interrupt_data has been allocated, so check it.
481 */
482 if (!interrupt_data)
483 return;
484
485 switch (interrupt_data->type) {
486 case PCI_MSIX:
487 gasket_interrupt_msix_cleanup(interrupt_data);
488 break;
489
490 case PCI_MSI:
491 case PLATFORM_WIRE:
492 default:
493 dev_dbg(gasket_dev->dev,
494 "Cannot handle unsupported interrupt type %d\n",
495 interrupt_data->type);
496 }
497
498 kfree(interrupt_data->interrupt_counts);
499 kfree(interrupt_data->eventfd_ctxs);
500 kfree(interrupt_data->msix_entries);
501 kfree(interrupt_data);
502 gasket_dev->interrupt_data = NULL;
503 }
504
gasket_interrupt_system_status(struct gasket_dev * gasket_dev)505 int gasket_interrupt_system_status(struct gasket_dev *gasket_dev)
506 {
507 if (!gasket_dev->interrupt_data) {
508 dev_dbg(gasket_dev->dev, "Interrupt data is null\n");
509 return GASKET_STATUS_DEAD;
510 }
511
512 if (!gasket_dev->interrupt_data->msix_configured) {
513 dev_dbg(gasket_dev->dev, "Interrupt not initialized\n");
514 return GASKET_STATUS_LAMED;
515 }
516
517 if (gasket_dev->interrupt_data->num_configured !=
518 gasket_dev->interrupt_data->num_interrupts) {
519 dev_dbg(gasket_dev->dev,
520 "Not all interrupts were configured\n");
521 return GASKET_STATUS_LAMED;
522 }
523
524 return GASKET_STATUS_ALIVE;
525 }
526
gasket_interrupt_set_eventfd(struct gasket_interrupt_data * interrupt_data,int interrupt,int event_fd)527 int gasket_interrupt_set_eventfd(struct gasket_interrupt_data *interrupt_data,
528 int interrupt, int event_fd)
529 {
530 struct eventfd_ctx *ctx = eventfd_ctx_fdget(event_fd);
531
532 if (IS_ERR(ctx))
533 return PTR_ERR(ctx);
534
535 if (interrupt < 0 || interrupt >= interrupt_data->num_interrupts)
536 return -EINVAL;
537
538 interrupt_data->eventfd_ctxs[interrupt] = ctx;
539 return 0;
540 }
541
gasket_interrupt_clear_eventfd(struct gasket_interrupt_data * interrupt_data,int interrupt)542 int gasket_interrupt_clear_eventfd(struct gasket_interrupt_data *interrupt_data,
543 int interrupt)
544 {
545 if (interrupt < 0 || interrupt >= interrupt_data->num_interrupts)
546 return -EINVAL;
547
548 interrupt_data->eventfd_ctxs[interrupt] = NULL;
549 return 0;
550 }
551