.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright 2016,2017 IBM Corporation. |
---|
3 | | - * |
---|
4 | | - * This program is free software; you can redistribute it and/or |
---|
5 | | - * modify it under the terms of the GNU General Public License |
---|
6 | | - * as published by the Free Software Foundation; either version |
---|
7 | | - * 2 of the License, or (at your option) any later version. |
---|
8 | 4 | */ |
---|
9 | 5 | |
---|
10 | 6 | #define pr_fmt(fmt) "xive: " fmt |
---|
.. | .. |
---|
25 | 21 | #include <linux/msi.h> |
---|
26 | 22 | #include <linux/vmalloc.h> |
---|
27 | 23 | |
---|
| 24 | +#include <asm/debugfs.h> |
---|
28 | 25 | #include <asm/prom.h> |
---|
29 | 26 | #include <asm/io.h> |
---|
30 | 27 | #include <asm/smp.h> |
---|
.. | .. |
---|
133 | 130 | static u32 xive_scan_interrupts(struct xive_cpu *xc, bool just_peek) |
---|
134 | 131 | { |
---|
135 | 132 | u32 irq = 0; |
---|
136 | | - u8 prio; |
---|
| 133 | + u8 prio = 0; |
---|
137 | 134 | |
---|
138 | 135 | /* Find highest pending priority */ |
---|
139 | 136 | while (xc->pending_prio != 0) { |
---|
.. | .. |
---|
146 | 143 | irq = xive_read_eq(&xc->queue[prio], just_peek); |
---|
147 | 144 | |
---|
148 | 145 | /* Found something ? That's it */ |
---|
149 | | - if (irq) |
---|
150 | | - break; |
---|
| 146 | + if (irq) { |
---|
| 147 | + if (just_peek || irq_to_desc(irq)) |
---|
| 148 | + break; |
---|
| 149 | + /* |
---|
| 150 | + * We should never get here; if we do then we must |
---|
| 151 | + * have failed to synchronize the interrupt properly |
---|
| 152 | + * when shutting it down. |
---|
| 153 | + */ |
---|
| 154 | + pr_crit("xive: got interrupt %d without descriptor, dropping\n", |
---|
| 155 | + irq); |
---|
| 156 | + WARN_ON(1); |
---|
| 157 | + continue; |
---|
| 158 | + } |
---|
151 | 159 | |
---|
152 | 160 | /* Clear pending bits */ |
---|
153 | 161 | xc->pending_prio &= ~(1 << prio); |
---|
.. | .. |
---|
183 | 191 | |
---|
184 | 192 | /* |
---|
185 | 193 | * This is used to perform the magic loads from an ESB |
---|
186 | | - * described in xive.h |
---|
| 194 | + * described in xive-regs.h |
---|
187 | 195 | */ |
---|
188 | 196 | static notrace u8 xive_esb_read(struct xive_irq_data *xd, u32 offset) |
---|
189 | 197 | { |
---|
190 | 198 | u64 val; |
---|
| 199 | + |
---|
| 200 | + if (offset == XIVE_ESB_SET_PQ_10 && xd->flags & XIVE_IRQ_FLAG_STORE_EOI) |
---|
| 201 | + offset |= XIVE_ESB_LD_ST_MO; |
---|
191 | 202 | |
---|
192 | 203 | /* Handle HW errata */ |
---|
193 | 204 | if (xd->flags & XIVE_IRQ_FLAG_SHIFT_BUG) |
---|
.. | .. |
---|
224 | 235 | i0 = be32_to_cpup(q->qpage + idx); |
---|
225 | 236 | idx = (idx + 1) & q->msk; |
---|
226 | 237 | i1 = be32_to_cpup(q->qpage + idx); |
---|
227 | | - xmon_printf(" %s Q T=%d %08x %08x ...\n", name, |
---|
228 | | - q->toggle, i0, i1); |
---|
| 238 | + xmon_printf("%s idx=%d T=%d %08x %08x ...", name, |
---|
| 239 | + q->idx, q->toggle, i0, i1); |
---|
229 | 240 | } |
---|
230 | 241 | |
---|
231 | 242 | notrace void xmon_xive_do_dump(int cpu) |
---|
232 | 243 | { |
---|
233 | 244 | struct xive_cpu *xc = per_cpu(xive_cpu, cpu); |
---|
234 | 245 | |
---|
235 | | - xmon_printf("XIVE state for CPU %d:\n", cpu); |
---|
236 | | - xmon_printf(" pp=%02x cppr=%02x\n", xc->pending_prio, xc->cppr); |
---|
237 | | - xive_dump_eq("IRQ", &xc->queue[xive_irq_priority]); |
---|
| 246 | + xmon_printf("CPU %d:", cpu); |
---|
| 247 | + if (xc) { |
---|
| 248 | + xmon_printf("pp=%02x CPPR=%02x ", xc->pending_prio, xc->cppr); |
---|
| 249 | + |
---|
238 | 250 | #ifdef CONFIG_SMP |
---|
239 | | - { |
---|
240 | | - u64 val = xive_esb_read(&xc->ipi_data, XIVE_ESB_GET); |
---|
241 | | - xmon_printf(" IPI state: %x:%c%c\n", xc->hw_ipi, |
---|
242 | | - val & XIVE_ESB_VAL_P ? 'P' : 'p', |
---|
243 | | - val & XIVE_ESB_VAL_Q ? 'Q' : 'q'); |
---|
244 | | - } |
---|
| 251 | + { |
---|
| 252 | + u64 val = xive_esb_read(&xc->ipi_data, XIVE_ESB_GET); |
---|
| 253 | + |
---|
| 254 | + xmon_printf("IPI=0x%08x PQ=%c%c ", xc->hw_ipi, |
---|
| 255 | + val & XIVE_ESB_VAL_P ? 'P' : '-', |
---|
| 256 | + val & XIVE_ESB_VAL_Q ? 'Q' : '-'); |
---|
| 257 | + } |
---|
245 | 258 | #endif |
---|
| 259 | + xive_dump_eq("EQ", &xc->queue[xive_irq_priority]); |
---|
| 260 | + } |
---|
| 261 | + xmon_printf("\n"); |
---|
246 | 262 | } |
---|
| 263 | + |
---|
| 264 | +static struct irq_data *xive_get_irq_data(u32 hw_irq) |
---|
| 265 | +{ |
---|
| 266 | + unsigned int irq = irq_find_mapping(xive_irq_domain, hw_irq); |
---|
| 267 | + |
---|
| 268 | + return irq ? irq_get_irq_data(irq) : NULL; |
---|
| 269 | +} |
---|
| 270 | + |
---|
| 271 | +int xmon_xive_get_irq_config(u32 hw_irq, struct irq_data *d) |
---|
| 272 | +{ |
---|
| 273 | + int rc; |
---|
| 274 | + u32 target; |
---|
| 275 | + u8 prio; |
---|
| 276 | + u32 lirq; |
---|
| 277 | + |
---|
| 278 | + rc = xive_ops->get_irq_config(hw_irq, &target, &prio, &lirq); |
---|
| 279 | + if (rc) { |
---|
| 280 | + xmon_printf("IRQ 0x%08x : no config rc=%d\n", hw_irq, rc); |
---|
| 281 | + return rc; |
---|
| 282 | + } |
---|
| 283 | + |
---|
| 284 | + xmon_printf("IRQ 0x%08x : target=0x%x prio=%02x lirq=0x%x ", |
---|
| 285 | + hw_irq, target, prio, lirq); |
---|
| 286 | + |
---|
| 287 | + if (!d) |
---|
| 288 | + d = xive_get_irq_data(hw_irq); |
---|
| 289 | + |
---|
| 290 | + if (d) { |
---|
| 291 | + struct xive_irq_data *xd = irq_data_get_irq_handler_data(d); |
---|
| 292 | + u64 val = xive_esb_read(xd, XIVE_ESB_GET); |
---|
| 293 | + |
---|
| 294 | + xmon_printf("flags=%c%c%c PQ=%c%c", |
---|
| 295 | + xd->flags & XIVE_IRQ_FLAG_STORE_EOI ? 'S' : ' ', |
---|
| 296 | + xd->flags & XIVE_IRQ_FLAG_LSI ? 'L' : ' ', |
---|
| 297 | + xd->flags & XIVE_IRQ_FLAG_H_INT_ESB ? 'H' : ' ', |
---|
| 298 | + val & XIVE_ESB_VAL_P ? 'P' : '-', |
---|
| 299 | + val & XIVE_ESB_VAL_Q ? 'Q' : '-'); |
---|
| 300 | + } |
---|
| 301 | + |
---|
| 302 | + xmon_printf("\n"); |
---|
| 303 | + return 0; |
---|
| 304 | +} |
---|
| 305 | + |
---|
247 | 306 | #endif /* CONFIG_XMON */ |
---|
248 | 307 | |
---|
249 | 308 | static unsigned int xive_get_irq(void) |
---|
.. | .. |
---|
303 | 362 | * EOI an interrupt at the source. There are several methods |
---|
304 | 363 | * to do this depending on the HW version and source type |
---|
305 | 364 | */ |
---|
306 | | -void xive_do_source_eoi(u32 hw_irq, struct xive_irq_data *xd) |
---|
| 365 | +static void xive_do_source_eoi(u32 hw_irq, struct xive_irq_data *xd) |
---|
307 | 366 | { |
---|
| 367 | + xd->stale_p = false; |
---|
308 | 368 | /* If the XIVE supports the new "store EOI facility, use it */ |
---|
309 | 369 | if (xd->flags & XIVE_IRQ_FLAG_STORE_EOI) |
---|
310 | 370 | xive_esb_write(xd, XIVE_ESB_STORE_EOI, 0); |
---|
.. | .. |
---|
348 | 408 | } |
---|
349 | 409 | } |
---|
350 | 410 | |
---|
351 | | -/* irq_chip eoi callback */ |
---|
| 411 | +/* irq_chip eoi callback, called with irq descriptor lock held */ |
---|
352 | 412 | static void xive_irq_eoi(struct irq_data *d) |
---|
353 | 413 | { |
---|
354 | 414 | struct xive_irq_data *xd = irq_data_get_irq_handler_data(d); |
---|
.. | .. |
---|
364 | 424 | if (!irqd_irq_disabled(d) && !irqd_is_forwarded_to_vcpu(d) && |
---|
365 | 425 | !(xd->flags & XIVE_IRQ_NO_EOI)) |
---|
366 | 426 | xive_do_source_eoi(irqd_to_hwirq(d), xd); |
---|
| 427 | + else |
---|
| 428 | + xd->stale_p = true; |
---|
367 | 429 | |
---|
368 | 430 | /* |
---|
369 | 431 | * Clear saved_p to indicate that it's no longer occupying |
---|
.. | .. |
---|
395 | 457 | */ |
---|
396 | 458 | if (mask) { |
---|
397 | 459 | val = xive_esb_read(xd, XIVE_ESB_SET_PQ_01); |
---|
398 | | - xd->saved_p = !!(val & XIVE_ESB_VAL_P); |
---|
399 | | - } else if (xd->saved_p) |
---|
| 460 | + if (!xd->stale_p && !!(val & XIVE_ESB_VAL_P)) |
---|
| 461 | + xd->saved_p = true; |
---|
| 462 | + xd->stale_p = false; |
---|
| 463 | + } else if (xd->saved_p) { |
---|
400 | 464 | xive_esb_read(xd, XIVE_ESB_SET_PQ_10); |
---|
401 | | - else |
---|
| 465 | + xd->saved_p = false; |
---|
| 466 | + } else { |
---|
402 | 467 | xive_esb_read(xd, XIVE_ESB_SET_PQ_00); |
---|
| 468 | + xd->stale_p = false; |
---|
| 469 | + } |
---|
403 | 470 | } |
---|
404 | 471 | |
---|
405 | 472 | /* |
---|
.. | .. |
---|
436 | 503 | struct xive_cpu *xc = per_cpu(xive_cpu, cpu); |
---|
437 | 504 | struct xive_q *q = &xc->queue[xive_irq_priority]; |
---|
438 | 505 | |
---|
439 | | - if (unlikely(WARN_ON(cpu < 0 || !xc))) { |
---|
| 506 | + if (WARN_ON(cpu < 0 || !xc)) { |
---|
440 | 507 | pr_err("%s: cpu=%d xc=%p\n", __func__, cpu, xc); |
---|
441 | 508 | return; |
---|
442 | 509 | } |
---|
.. | .. |
---|
539 | 606 | unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d); |
---|
540 | 607 | int target, rc; |
---|
541 | 608 | |
---|
| 609 | + xd->saved_p = false; |
---|
| 610 | + xd->stale_p = false; |
---|
542 | 611 | pr_devel("xive_irq_startup: irq %d [0x%x] data @%p\n", |
---|
543 | 612 | d->irq, hw_irq, d); |
---|
544 | 613 | |
---|
.. | .. |
---|
585 | 654 | return 0; |
---|
586 | 655 | } |
---|
587 | 656 | |
---|
| 657 | +/* called with irq descriptor lock held */ |
---|
588 | 658 | static void xive_irq_shutdown(struct irq_data *d) |
---|
589 | 659 | { |
---|
590 | 660 | struct xive_irq_data *xd = irq_data_get_irq_handler_data(d); |
---|
.. | .. |
---|
598 | 668 | |
---|
599 | 669 | /* Mask the interrupt at the source */ |
---|
600 | 670 | xive_do_source_set_mask(xd, true); |
---|
601 | | - |
---|
602 | | - /* |
---|
603 | | - * The above may have set saved_p. We clear it otherwise it |
---|
604 | | - * will prevent re-enabling later on. It is ok to forget the |
---|
605 | | - * fact that the interrupt might be in a queue because we are |
---|
606 | | - * accounting that already in xive_dec_target_count() and will |
---|
607 | | - * be re-routing it to a new queue with proper accounting when |
---|
608 | | - * it's started up again |
---|
609 | | - */ |
---|
610 | | - xd->saved_p = false; |
---|
611 | 671 | |
---|
612 | 672 | /* |
---|
613 | 673 | * Mask the interrupt in HW in the IVT/EAS and set the number |
---|
.. | .. |
---|
795 | 855 | return 1; |
---|
796 | 856 | } |
---|
797 | 857 | |
---|
| 858 | +/* |
---|
| 859 | + * Caller holds the irq descriptor lock, so this won't be called |
---|
| 860 | + * concurrently with xive_get_irqchip_state on the same interrupt. |
---|
| 861 | + */ |
---|
798 | 862 | static int xive_irq_set_vcpu_affinity(struct irq_data *d, void *state) |
---|
799 | 863 | { |
---|
800 | 864 | struct xive_irq_data *xd = irq_data_get_irq_handler_data(d); |
---|
.. | .. |
---|
818 | 882 | |
---|
819 | 883 | /* Set it to PQ=10 state to prevent further sends */ |
---|
820 | 884 | pq = xive_esb_read(xd, XIVE_ESB_SET_PQ_10); |
---|
| 885 | + if (!xd->stale_p) { |
---|
| 886 | + xd->saved_p = !!(pq & XIVE_ESB_VAL_P); |
---|
| 887 | + xd->stale_p = !xd->saved_p; |
---|
| 888 | + } |
---|
821 | 889 | |
---|
822 | 890 | /* No target ? nothing to do */ |
---|
823 | 891 | if (xd->target == XIVE_INVALID_TARGET) { |
---|
.. | .. |
---|
825 | 893 | * An untargetted interrupt should have been |
---|
826 | 894 | * also masked at the source |
---|
827 | 895 | */ |
---|
828 | | - WARN_ON(pq & 2); |
---|
| 896 | + WARN_ON(xd->saved_p); |
---|
829 | 897 | |
---|
830 | 898 | return 0; |
---|
831 | 899 | } |
---|
.. | .. |
---|
845 | 913 | * This saved_p is cleared by the host EOI, when we know |
---|
846 | 914 | * for sure the queue slot is no longer in use. |
---|
847 | 915 | */ |
---|
848 | | - if (pq & 2) { |
---|
849 | | - pq = xive_esb_read(xd, XIVE_ESB_SET_PQ_11); |
---|
850 | | - xd->saved_p = true; |
---|
| 916 | + if (xd->saved_p) { |
---|
| 917 | + xive_esb_read(xd, XIVE_ESB_SET_PQ_11); |
---|
851 | 918 | |
---|
852 | 919 | /* |
---|
853 | 920 | * Sync the XIVE source HW to ensure the interrupt |
---|
.. | .. |
---|
860 | 927 | */ |
---|
861 | 928 | if (xive_ops->sync_source) |
---|
862 | 929 | xive_ops->sync_source(hw_irq); |
---|
863 | | - } else |
---|
864 | | - xd->saved_p = false; |
---|
| 930 | + } |
---|
865 | 931 | } else { |
---|
866 | 932 | irqd_clr_forwarded_to_vcpu(d); |
---|
867 | 933 | |
---|
.. | .. |
---|
912 | 978 | return 0; |
---|
913 | 979 | } |
---|
914 | 980 | |
---|
| 981 | +/* Called with irq descriptor lock held. */ |
---|
| 982 | +static int xive_get_irqchip_state(struct irq_data *data, |
---|
| 983 | + enum irqchip_irq_state which, bool *state) |
---|
| 984 | +{ |
---|
| 985 | + struct xive_irq_data *xd = irq_data_get_irq_handler_data(data); |
---|
| 986 | + u8 pq; |
---|
| 987 | + |
---|
| 988 | + switch (which) { |
---|
| 989 | + case IRQCHIP_STATE_ACTIVE: |
---|
| 990 | + pq = xive_esb_read(xd, XIVE_ESB_GET); |
---|
| 991 | + |
---|
| 992 | + /* |
---|
| 993 | + * The esb value being all 1's means we couldn't get |
---|
| 994 | + * the PQ state of the interrupt through mmio. It may |
---|
| 995 | + * happen, for example when querying a PHB interrupt |
---|
| 996 | + * while the PHB is in an error state. We consider the |
---|
| 997 | + * interrupt to be inactive in that case. |
---|
| 998 | + */ |
---|
| 999 | + *state = (pq != XIVE_ESB_INVALID) && !xd->stale_p && |
---|
| 1000 | + (xd->saved_p || (!!(pq & XIVE_ESB_VAL_P) && |
---|
| 1001 | + !irqd_irq_disabled(data))); |
---|
| 1002 | + return 0; |
---|
| 1003 | + default: |
---|
| 1004 | + return -EINVAL; |
---|
| 1005 | + } |
---|
| 1006 | +} |
---|
| 1007 | + |
---|
915 | 1008 | static struct irq_chip xive_irq_chip = { |
---|
916 | 1009 | .name = "XIVE-IRQ", |
---|
917 | 1010 | .irq_startup = xive_irq_startup, |
---|
.. | .. |
---|
923 | 1016 | .irq_set_type = xive_irq_set_type, |
---|
924 | 1017 | .irq_retrigger = xive_irq_retrigger, |
---|
925 | 1018 | .irq_set_vcpu_affinity = xive_irq_set_vcpu_affinity, |
---|
| 1019 | + .irq_get_irqchip_state = xive_get_irqchip_state, |
---|
926 | 1020 | }; |
---|
927 | 1021 | |
---|
928 | 1022 | bool is_xive_irq(struct irq_chip *chip) |
---|
.. | .. |
---|
1350 | 1444 | xd = irq_desc_get_handler_data(desc); |
---|
1351 | 1445 | |
---|
1352 | 1446 | /* |
---|
| 1447 | + * Clear saved_p to indicate that it's no longer pending |
---|
| 1448 | + */ |
---|
| 1449 | + xd->saved_p = false; |
---|
| 1450 | + |
---|
| 1451 | + /* |
---|
1353 | 1452 | * For LSIs, we EOI, this will cause a resend if it's |
---|
1354 | 1453 | * still asserted. Otherwise do an MSI retrigger. |
---|
1355 | 1454 | */ |
---|
.. | .. |
---|
1472 | 1571 | return 0; |
---|
1473 | 1572 | } |
---|
1474 | 1573 | __setup("xive=off", xive_off); |
---|
| 1574 | + |
---|
| 1575 | +static void xive_debug_show_cpu(struct seq_file *m, int cpu) |
---|
| 1576 | +{ |
---|
| 1577 | + struct xive_cpu *xc = per_cpu(xive_cpu, cpu); |
---|
| 1578 | + |
---|
| 1579 | + seq_printf(m, "CPU %d:", cpu); |
---|
| 1580 | + if (xc) { |
---|
| 1581 | + seq_printf(m, "pp=%02x CPPR=%02x ", xc->pending_prio, xc->cppr); |
---|
| 1582 | + |
---|
| 1583 | +#ifdef CONFIG_SMP |
---|
| 1584 | + { |
---|
| 1585 | + u64 val = xive_esb_read(&xc->ipi_data, XIVE_ESB_GET); |
---|
| 1586 | + |
---|
| 1587 | + seq_printf(m, "IPI=0x%08x PQ=%c%c ", xc->hw_ipi, |
---|
| 1588 | + val & XIVE_ESB_VAL_P ? 'P' : '-', |
---|
| 1589 | + val & XIVE_ESB_VAL_Q ? 'Q' : '-'); |
---|
| 1590 | + } |
---|
| 1591 | +#endif |
---|
| 1592 | + { |
---|
| 1593 | + struct xive_q *q = &xc->queue[xive_irq_priority]; |
---|
| 1594 | + u32 i0, i1, idx; |
---|
| 1595 | + |
---|
| 1596 | + if (q->qpage) { |
---|
| 1597 | + idx = q->idx; |
---|
| 1598 | + i0 = be32_to_cpup(q->qpage + idx); |
---|
| 1599 | + idx = (idx + 1) & q->msk; |
---|
| 1600 | + i1 = be32_to_cpup(q->qpage + idx); |
---|
| 1601 | + seq_printf(m, "EQ idx=%d T=%d %08x %08x ...", |
---|
| 1602 | + q->idx, q->toggle, i0, i1); |
---|
| 1603 | + } |
---|
| 1604 | + } |
---|
| 1605 | + } |
---|
| 1606 | + seq_puts(m, "\n"); |
---|
| 1607 | +} |
---|
| 1608 | + |
---|
| 1609 | +static void xive_debug_show_irq(struct seq_file *m, u32 hw_irq, struct irq_data *d) |
---|
| 1610 | +{ |
---|
| 1611 | + struct irq_chip *chip = irq_data_get_irq_chip(d); |
---|
| 1612 | + int rc; |
---|
| 1613 | + u32 target; |
---|
| 1614 | + u8 prio; |
---|
| 1615 | + u32 lirq; |
---|
| 1616 | + struct xive_irq_data *xd; |
---|
| 1617 | + u64 val; |
---|
| 1618 | + |
---|
| 1619 | + if (!is_xive_irq(chip)) |
---|
| 1620 | + return; |
---|
| 1621 | + |
---|
| 1622 | + rc = xive_ops->get_irq_config(hw_irq, &target, &prio, &lirq); |
---|
| 1623 | + if (rc) { |
---|
| 1624 | + seq_printf(m, "IRQ 0x%08x : no config rc=%d\n", hw_irq, rc); |
---|
| 1625 | + return; |
---|
| 1626 | + } |
---|
| 1627 | + |
---|
| 1628 | + seq_printf(m, "IRQ 0x%08x : target=0x%x prio=%02x lirq=0x%x ", |
---|
| 1629 | + hw_irq, target, prio, lirq); |
---|
| 1630 | + |
---|
| 1631 | + xd = irq_data_get_irq_handler_data(d); |
---|
| 1632 | + val = xive_esb_read(xd, XIVE_ESB_GET); |
---|
| 1633 | + seq_printf(m, "flags=%c%c%c PQ=%c%c", |
---|
| 1634 | + xd->flags & XIVE_IRQ_FLAG_STORE_EOI ? 'S' : ' ', |
---|
| 1635 | + xd->flags & XIVE_IRQ_FLAG_LSI ? 'L' : ' ', |
---|
| 1636 | + xd->flags & XIVE_IRQ_FLAG_H_INT_ESB ? 'H' : ' ', |
---|
| 1637 | + val & XIVE_ESB_VAL_P ? 'P' : '-', |
---|
| 1638 | + val & XIVE_ESB_VAL_Q ? 'Q' : '-'); |
---|
| 1639 | + seq_puts(m, "\n"); |
---|
| 1640 | +} |
---|
| 1641 | + |
---|
| 1642 | +static int xive_core_debug_show(struct seq_file *m, void *private) |
---|
| 1643 | +{ |
---|
| 1644 | + unsigned int i; |
---|
| 1645 | + struct irq_desc *desc; |
---|
| 1646 | + int cpu; |
---|
| 1647 | + |
---|
| 1648 | + if (xive_ops->debug_show) |
---|
| 1649 | + xive_ops->debug_show(m, private); |
---|
| 1650 | + |
---|
| 1651 | + for_each_possible_cpu(cpu) |
---|
| 1652 | + xive_debug_show_cpu(m, cpu); |
---|
| 1653 | + |
---|
| 1654 | + for_each_irq_desc(i, desc) { |
---|
| 1655 | + struct irq_data *d = irq_desc_get_irq_data(desc); |
---|
| 1656 | + unsigned int hw_irq; |
---|
| 1657 | + |
---|
| 1658 | + if (!d) |
---|
| 1659 | + continue; |
---|
| 1660 | + |
---|
| 1661 | + hw_irq = (unsigned int)irqd_to_hwirq(d); |
---|
| 1662 | + |
---|
| 1663 | + /* IPIs are special (HW number 0) */ |
---|
| 1664 | + if (hw_irq) |
---|
| 1665 | + xive_debug_show_irq(m, hw_irq, d); |
---|
| 1666 | + } |
---|
| 1667 | + return 0; |
---|
| 1668 | +} |
---|
| 1669 | +DEFINE_SHOW_ATTRIBUTE(xive_core_debug); |
---|
| 1670 | + |
---|
| 1671 | +int xive_core_debug_init(void) |
---|
| 1672 | +{ |
---|
| 1673 | + if (xive_enabled()) |
---|
| 1674 | + debugfs_create_file("xive", 0400, powerpc_debugfs_root, |
---|
| 1675 | + NULL, &xive_core_debug_fops); |
---|
| 1676 | + return 0; |
---|
| 1677 | +} |
---|