1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (C) 2018 Google, Inc. */
4 #include "gasket_interrupt.h"
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>
17 #define trace_gasket_interrupt_event(x, ...)
19 /* Retry attempts if the requested number of interrupts aren't available. */
20 #define MSIX_RETRY_COUNT 3
22 /* Instance interrupt management data. */
23 struct gasket_interrupt_data {
24 /* The name associated with this interrupt data. */
27 /* Interrupt type. See gasket_interrupt_type in gasket_core.h */
30 /* The PCI device [if any] associated with the owning device. */
31 struct pci_dev *pci_dev;
33 /* Set to 1 if MSI-X has successfully been configred, 0 otherwise. */
36 /* The number of interrupts requested by the owning device. */
39 /* A pointer to the interrupt descriptor struct for this device. */
40 const struct gasket_interrupt_desc *interrupts;
42 /* The index of the bar into which interrupts should be mapped. */
43 int interrupt_bar_index;
45 /* The width of a single interrupt in a packed interrupt register. */
48 /* offset of wire interrupt registers */
49 const struct gasket_wire_interrupt_offsets *wire_interrupt_offsets;
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).
57 /* The number of successfully configured interrupts. */
60 /* The MSI-X data for each requested/configured interrupt. */
61 struct msix_entry *msix_entries;
63 /* The eventfd "callback" data for each interrupt. */
64 struct eventfd_ctx **eventfd_ctxs;
66 /* The number of times each interrupt has been called. */
67 ulong *interrupt_counts;
69 /* Linux IRQ number. */
73 /* Structures to display interrupt counts in sysfs. */
74 enum interrupt_sysfs_attribute_type {
75 ATTR_INTERRUPT_COUNTS,
78 /* Set up device registers for interrupt handling. */
79 static void gasket_interrupt_setup(struct gasket_dev *gasket_dev)
85 struct gasket_interrupt_data *interrupt_data =
86 gasket_dev->interrupt_data;
88 if (!interrupt_data) {
89 dev_dbg(gasket_dev->dev, "Interrupt data is not initialized\n");
93 dev_dbg(gasket_dev->dev, "Running interrupt setup\n");
95 if (interrupt_data->type == PLATFORM_WIRE ||
96 interrupt_data->type == PCI_MSI) {
97 /* Nothing needs to be done for platform or PCI devices. */
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);
108 /* Setup the MSIX table. */
110 for (i = 0; i < interrupt_data->num_interrupts; i++) {
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.
116 dev_dbg(gasket_dev->dev,
117 "Setting up interrupt index %d with index 0x%llx and "
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;
125 switch (interrupt_data->interrupts[i].packing) {
130 pack_shift = interrupt_data->pack_width;
133 pack_shift = 2 * interrupt_data->pack_width;
136 pack_shift = 3 * interrupt_data->pack_width;
139 dev_dbg(gasket_dev->dev,
140 "Found interrupt description with "
142 interrupt_data->interrupts[i].packing);
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);
151 value |= interrupt_data->interrupts[i].index
154 gasket_dev_write_64(gasket_dev, value,
155 interrupt_data->interrupt_bar_index,
156 interrupt_data->interrupts[i].reg);
160 static irqreturn_t gasket_msix_interrupt_handler(int irq, void *dev_id)
162 struct eventfd_ctx *ctx;
163 struct gasket_interrupt_data *interrupt_data = dev_id;
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;
174 if (interrupt == -1) {
175 pr_err("Received unknown irq %d\n", irq);
178 trace_gasket_interrupt_event(interrupt_data->name, interrupt);
180 ctx = interrupt_data->eventfd_ctxs[interrupt];
182 eventfd_signal(ctx, 1);
184 ++(interrupt_data->interrupt_counts[interrupt]);
190 gasket_interrupt_msix_init(struct gasket_interrupt_data *interrupt_data)
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;
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);
208 return ret > 0 ? -EBUSY : ret;
209 interrupt_data->msix_configured = 1;
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);
217 dev_err(&interrupt_data->pci_dev->dev,
218 "Cannot get IRQ for interrupt %d, vector %d; "
220 i, interrupt_data->msix_entries[i].vector, ret);
224 interrupt_data->num_configured++;
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.
235 * As a temporary hack, force unmasking there.
237 * TODO: Figure out why QCM kernel doesn't unmask the MSIX vectors, after
238 * gasket_interrupt_msix_init(), and remove this code.
240 static void force_msix_interrupt_unmasking(struct gasket_dev *gasket_dev)
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;
251 gasket_dev_read_32(gasket_dev,
252 gasket_dev->interrupt_data->interrupt_bar_index,
256 /* Unmask the msix vector (clear 32 bits) */
257 gasket_dev_write_32(gasket_dev, 0,
258 gasket_dev->interrupt_data->interrupt_bar_index,
261 #undef MSIX_VECTOR_SIZE
262 #undef MSIX_MASK_BIT_OFFSET
263 #undef APEX_BAR2_REG_KERNEL_HIB_MSIX_TABLE
266 static ssize_t interrupt_sysfs_show(struct device *device,
267 struct device_attribute *attr, char *buf)
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;
276 gasket_dev = gasket_sysfs_get_device_data(device);
278 dev_dbg(device, "No sysfs mapping found for device\n");
282 gasket_attr = gasket_sysfs_get_attr(device, attr);
284 dev_dbg(device, "No sysfs attr data found for device\n");
285 gasket_sysfs_put_device_data(device, gasket_dev);
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) {
296 scnprintf(buf, PAGE_SIZE - total_written,
298 interrupt_data->interrupt_counts[i]);
299 total_written += written;
305 dev_dbg(gasket_dev->dev, "Unknown attribute: %s\n",
311 gasket_sysfs_put_attr(device, gasket_attr);
312 gasket_sysfs_put_device_data(device, gasket_dev);
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,
322 int gasket_interrupt_init(struct gasket_dev *gasket_dev, const char *name,
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)
329 struct gasket_interrupt_data *interrupt_data;
331 interrupt_data = kzalloc(sizeof(struct gasket_interrupt_data),
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;
346 /* Allocate all dynamic structures. */
347 interrupt_data->msix_entries = kcalloc(num_interrupts,
348 sizeof(struct msix_entry),
350 if (!interrupt_data->msix_entries) {
351 kfree(interrupt_data);
355 interrupt_data->eventfd_ctxs = kcalloc(num_interrupts,
356 sizeof(struct eventfd_ctx *),
358 if (!interrupt_data->eventfd_ctxs) {
359 kfree(interrupt_data->msix_entries);
360 kfree(interrupt_data);
364 interrupt_data->interrupt_counts = kcalloc(num_interrupts,
367 if (!interrupt_data->interrupt_counts) {
368 kfree(interrupt_data->eventfd_ctxs);
369 kfree(interrupt_data->msix_entries);
370 kfree(interrupt_data);
374 switch (interrupt_data->type) {
376 ret = gasket_interrupt_msix_init(interrupt_data);
379 force_msix_interrupt_unmasking(gasket_dev);
385 dev_err(gasket_dev->dev,
386 "Cannot handle unsupported interrupt type %d\n",
387 interrupt_data->type);
392 /* Failing to setup interrupts will cause the device to report
393 * GASKET_STATUS_LAMED. But it is not fatal.
395 dev_warn(gasket_dev->dev,
396 "Couldn't initialize interrupts: %d\n", ret);
400 gasket_interrupt_setup(gasket_dev);
401 gasket_sysfs_create_entries(gasket_dev->dev_info.device,
402 interrupt_sysfs_attrs);
408 gasket_interrupt_msix_cleanup(struct gasket_interrupt_data *interrupt_data)
412 for (i = 0; i < interrupt_data->num_configured; i++)
413 free_irq(interrupt_data->msix_entries[i].vector,
415 interrupt_data->num_configured = 0;
417 if (interrupt_data->msix_configured)
418 pci_disable_msix(interrupt_data->pci_dev);
419 interrupt_data->msix_configured = 0;
422 int gasket_interrupt_reinit(struct gasket_dev *gasket_dev)
426 if (!gasket_dev->interrupt_data) {
427 dev_dbg(gasket_dev->dev,
428 "Attempted to reinit uninitialized interrupt data\n");
432 switch (gasket_dev->interrupt_data->type) {
434 gasket_interrupt_msix_cleanup(gasket_dev->interrupt_data);
435 ret = gasket_interrupt_msix_init(gasket_dev->interrupt_data);
438 force_msix_interrupt_unmasking(gasket_dev);
444 dev_dbg(gasket_dev->dev,
445 "Cannot handle unsupported interrupt type %d\n",
446 gasket_dev->interrupt_data->type);
451 /* Failing to setup MSIx will cause the device
452 * to report GASKET_STATUS_LAMED, but is not fatal.
454 dev_warn(gasket_dev->dev, "Couldn't init msix: %d\n", ret);
458 gasket_interrupt_setup(gasket_dev);
463 /* See gasket_interrupt.h for description. */
464 int gasket_interrupt_reset_counts(struct gasket_dev *gasket_dev)
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));
473 /* See gasket_interrupt.h for description. */
474 void gasket_interrupt_cleanup(struct gasket_dev *gasket_dev)
476 struct gasket_interrupt_data *interrupt_data =
477 gasket_dev->interrupt_data;
479 * It is possible to get an error code from gasket_interrupt_init
480 * before interrupt_data has been allocated, so check it.
485 switch (interrupt_data->type) {
487 gasket_interrupt_msix_cleanup(interrupt_data);
493 dev_dbg(gasket_dev->dev,
494 "Cannot handle unsupported interrupt type %d\n",
495 interrupt_data->type);
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;
505 int gasket_interrupt_system_status(struct gasket_dev *gasket_dev)
507 if (!gasket_dev->interrupt_data) {
508 dev_dbg(gasket_dev->dev, "Interrupt data is null\n");
509 return GASKET_STATUS_DEAD;
512 if (!gasket_dev->interrupt_data->msix_configured) {
513 dev_dbg(gasket_dev->dev, "Interrupt not initialized\n");
514 return GASKET_STATUS_LAMED;
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;
524 return GASKET_STATUS_ALIVE;
527 int gasket_interrupt_set_eventfd(struct gasket_interrupt_data *interrupt_data,
528 int interrupt, int event_fd)
530 struct eventfd_ctx *ctx = eventfd_ctx_fdget(event_fd);
535 if (interrupt < 0 || interrupt >= interrupt_data->num_interrupts)
538 interrupt_data->eventfd_ctxs[interrupt] = ctx;
542 int gasket_interrupt_clear_eventfd(struct gasket_interrupt_data *interrupt_data,
545 if (interrupt < 0 || interrupt >= interrupt_data->num_interrupts)
548 interrupt_data->eventfd_ctxs[interrupt] = NULL;