| .. | .. |
|---|
| 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 | +} |
|---|