| .. | .. |
|---|
| 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 |
|---|
| .. | .. |
|---|
| 24 | 20 | #include <linux/mm.h> |
|---|
| 25 | 21 | #include <linux/kmemleak.h> |
|---|
| 26 | 22 | |
|---|
| 23 | +#include <asm/machdep.h> |
|---|
| 27 | 24 | #include <asm/prom.h> |
|---|
| 28 | 25 | #include <asm/io.h> |
|---|
| 29 | 26 | #include <asm/smp.h> |
|---|
| .. | .. |
|---|
| 116 | 113 | } |
|---|
| 117 | 114 | EXPORT_SYMBOL_GPL(xive_native_configure_irq); |
|---|
| 118 | 115 | |
|---|
| 116 | +static int xive_native_get_irq_config(u32 hw_irq, u32 *target, u8 *prio, |
|---|
| 117 | + u32 *sw_irq) |
|---|
| 118 | +{ |
|---|
| 119 | + s64 rc; |
|---|
| 120 | + __be64 vp; |
|---|
| 121 | + __be32 lirq; |
|---|
| 122 | + |
|---|
| 123 | + rc = opal_xive_get_irq_config(hw_irq, &vp, prio, &lirq); |
|---|
| 124 | + |
|---|
| 125 | + *target = be64_to_cpu(vp); |
|---|
| 126 | + *sw_irq = be32_to_cpu(lirq); |
|---|
| 127 | + |
|---|
| 128 | + return rc == 0 ? 0 : -ENXIO; |
|---|
| 129 | +} |
|---|
| 119 | 130 | |
|---|
| 120 | 131 | /* This can be called multiple time to change a queue configuration */ |
|---|
| 121 | 132 | int xive_native_configure_queue(u32 vp_id, struct xive_q *q, u8 prio, |
|---|
| .. | .. |
|---|
| 250 | 261 | #ifdef CONFIG_SMP |
|---|
| 251 | 262 | static int xive_native_get_ipi(unsigned int cpu, struct xive_cpu *xc) |
|---|
| 252 | 263 | { |
|---|
| 253 | | - struct device_node *np; |
|---|
| 254 | | - unsigned int chip_id; |
|---|
| 255 | 264 | s64 irq; |
|---|
| 256 | | - |
|---|
| 257 | | - /* Find the chip ID */ |
|---|
| 258 | | - np = of_get_cpu_node(cpu, NULL); |
|---|
| 259 | | - if (np) { |
|---|
| 260 | | - if (of_property_read_u32(np, "ibm,chip-id", &chip_id) < 0) |
|---|
| 261 | | - chip_id = 0; |
|---|
| 262 | | - } |
|---|
| 263 | 265 | |
|---|
| 264 | 266 | /* Allocate an IPI and populate info about it */ |
|---|
| 265 | 267 | for (;;) { |
|---|
| 266 | | - irq = opal_xive_allocate_irq(chip_id); |
|---|
| 268 | + irq = opal_xive_allocate_irq(xc->chip_id); |
|---|
| 267 | 269 | if (irq == OPAL_BUSY) { |
|---|
| 268 | 270 | msleep(OPAL_BUSY_DELAY_MS); |
|---|
| 269 | 271 | continue; |
|---|
| .. | .. |
|---|
| 279 | 281 | } |
|---|
| 280 | 282 | #endif /* CONFIG_SMP */ |
|---|
| 281 | 283 | |
|---|
| 282 | | -u32 xive_native_alloc_irq(void) |
|---|
| 284 | +u32 xive_native_alloc_irq_on_chip(u32 chip_id) |
|---|
| 283 | 285 | { |
|---|
| 284 | 286 | s64 rc; |
|---|
| 285 | 287 | |
|---|
| 286 | 288 | for (;;) { |
|---|
| 287 | | - rc = opal_xive_allocate_irq(OPAL_XIVE_ANY_CHIP); |
|---|
| 289 | + rc = opal_xive_allocate_irq(chip_id); |
|---|
| 288 | 290 | if (rc != OPAL_BUSY) |
|---|
| 289 | 291 | break; |
|---|
| 290 | 292 | msleep(OPAL_BUSY_DELAY_MS); |
|---|
| .. | .. |
|---|
| 293 | 295 | return 0; |
|---|
| 294 | 296 | return rc; |
|---|
| 295 | 297 | } |
|---|
| 296 | | -EXPORT_SYMBOL_GPL(xive_native_alloc_irq); |
|---|
| 298 | +EXPORT_SYMBOL_GPL(xive_native_alloc_irq_on_chip); |
|---|
| 297 | 299 | |
|---|
| 298 | 300 | void xive_native_free_irq(u32 irq) |
|---|
| 299 | 301 | { |
|---|
| .. | .. |
|---|
| 458 | 460 | } |
|---|
| 459 | 461 | EXPORT_SYMBOL_GPL(xive_native_sync_source); |
|---|
| 460 | 462 | |
|---|
| 463 | +void xive_native_sync_queue(u32 hw_irq) |
|---|
| 464 | +{ |
|---|
| 465 | + opal_xive_sync(XIVE_SYNC_QUEUE, hw_irq); |
|---|
| 466 | +} |
|---|
| 467 | +EXPORT_SYMBOL_GPL(xive_native_sync_queue); |
|---|
| 468 | + |
|---|
| 461 | 469 | static const struct xive_ops xive_native_ops = { |
|---|
| 462 | 470 | .populate_irq_data = xive_native_populate_irq_data, |
|---|
| 463 | 471 | .configure_irq = xive_native_configure_irq, |
|---|
| 472 | + .get_irq_config = xive_native_get_irq_config, |
|---|
| 464 | 473 | .setup_queue = xive_native_setup_queue, |
|---|
| 465 | 474 | .cleanup_queue = xive_native_cleanup_queue, |
|---|
| 466 | 475 | .match = xive_native_match, |
|---|
| .. | .. |
|---|
| 536 | 545 | } |
|---|
| 537 | 546 | EXPORT_SYMBOL_GPL(xive_native_default_eq_shift); |
|---|
| 538 | 547 | |
|---|
| 548 | +unsigned long xive_tima_os; |
|---|
| 549 | +EXPORT_SYMBOL_GPL(xive_tima_os); |
|---|
| 550 | + |
|---|
| 539 | 551 | bool __init xive_native_init(void) |
|---|
| 540 | 552 | { |
|---|
| 541 | 553 | struct device_node *np; |
|---|
| .. | .. |
|---|
| 587 | 599 | /* Configure Thread Management areas for KVM */ |
|---|
| 588 | 600 | for_each_possible_cpu(cpu) |
|---|
| 589 | 601 | kvmppc_set_xive_tima(cpu, r.start, tima); |
|---|
| 602 | + |
|---|
| 603 | + /* Resource 2 is OS window */ |
|---|
| 604 | + if (of_address_to_resource(np, 2, &r)) { |
|---|
| 605 | + pr_err("Failed to get thread mgmnt area resource\n"); |
|---|
| 606 | + return false; |
|---|
| 607 | + } |
|---|
| 608 | + |
|---|
| 609 | + xive_tima_os = r.start; |
|---|
| 590 | 610 | |
|---|
| 591 | 611 | /* Grab size of provisionning pages */ |
|---|
| 592 | 612 | xive_parse_provisioning(np); |
|---|
| .. | .. |
|---|
| 733 | 753 | return xive_has_single_esc; |
|---|
| 734 | 754 | } |
|---|
| 735 | 755 | EXPORT_SYMBOL_GPL(xive_native_has_single_escalation); |
|---|
| 756 | + |
|---|
| 757 | +int xive_native_get_queue_info(u32 vp_id, u32 prio, |
|---|
| 758 | + u64 *out_qpage, |
|---|
| 759 | + u64 *out_qsize, |
|---|
| 760 | + u64 *out_qeoi_page, |
|---|
| 761 | + u32 *out_escalate_irq, |
|---|
| 762 | + u64 *out_qflags) |
|---|
| 763 | +{ |
|---|
| 764 | + __be64 qpage; |
|---|
| 765 | + __be64 qsize; |
|---|
| 766 | + __be64 qeoi_page; |
|---|
| 767 | + __be32 escalate_irq; |
|---|
| 768 | + __be64 qflags; |
|---|
| 769 | + s64 rc; |
|---|
| 770 | + |
|---|
| 771 | + rc = opal_xive_get_queue_info(vp_id, prio, &qpage, &qsize, |
|---|
| 772 | + &qeoi_page, &escalate_irq, &qflags); |
|---|
| 773 | + if (rc) { |
|---|
| 774 | + pr_err("OPAL failed to get queue info for VCPU %d/%d : %lld\n", |
|---|
| 775 | + vp_id, prio, rc); |
|---|
| 776 | + return -EIO; |
|---|
| 777 | + } |
|---|
| 778 | + |
|---|
| 779 | + if (out_qpage) |
|---|
| 780 | + *out_qpage = be64_to_cpu(qpage); |
|---|
| 781 | + if (out_qsize) |
|---|
| 782 | + *out_qsize = be32_to_cpu(qsize); |
|---|
| 783 | + if (out_qeoi_page) |
|---|
| 784 | + *out_qeoi_page = be64_to_cpu(qeoi_page); |
|---|
| 785 | + if (out_escalate_irq) |
|---|
| 786 | + *out_escalate_irq = be32_to_cpu(escalate_irq); |
|---|
| 787 | + if (out_qflags) |
|---|
| 788 | + *out_qflags = be64_to_cpu(qflags); |
|---|
| 789 | + |
|---|
| 790 | + return 0; |
|---|
| 791 | +} |
|---|
| 792 | +EXPORT_SYMBOL_GPL(xive_native_get_queue_info); |
|---|
| 793 | + |
|---|
| 794 | +int xive_native_get_queue_state(u32 vp_id, u32 prio, u32 *qtoggle, u32 *qindex) |
|---|
| 795 | +{ |
|---|
| 796 | + __be32 opal_qtoggle; |
|---|
| 797 | + __be32 opal_qindex; |
|---|
| 798 | + s64 rc; |
|---|
| 799 | + |
|---|
| 800 | + rc = opal_xive_get_queue_state(vp_id, prio, &opal_qtoggle, |
|---|
| 801 | + &opal_qindex); |
|---|
| 802 | + if (rc) { |
|---|
| 803 | + pr_err("OPAL failed to get queue state for VCPU %d/%d : %lld\n", |
|---|
| 804 | + vp_id, prio, rc); |
|---|
| 805 | + return -EIO; |
|---|
| 806 | + } |
|---|
| 807 | + |
|---|
| 808 | + if (qtoggle) |
|---|
| 809 | + *qtoggle = be32_to_cpu(opal_qtoggle); |
|---|
| 810 | + if (qindex) |
|---|
| 811 | + *qindex = be32_to_cpu(opal_qindex); |
|---|
| 812 | + |
|---|
| 813 | + return 0; |
|---|
| 814 | +} |
|---|
| 815 | +EXPORT_SYMBOL_GPL(xive_native_get_queue_state); |
|---|
| 816 | + |
|---|
| 817 | +int xive_native_set_queue_state(u32 vp_id, u32 prio, u32 qtoggle, u32 qindex) |
|---|
| 818 | +{ |
|---|
| 819 | + s64 rc; |
|---|
| 820 | + |
|---|
| 821 | + rc = opal_xive_set_queue_state(vp_id, prio, qtoggle, qindex); |
|---|
| 822 | + if (rc) { |
|---|
| 823 | + pr_err("OPAL failed to set queue state for VCPU %d/%d : %lld\n", |
|---|
| 824 | + vp_id, prio, rc); |
|---|
| 825 | + return -EIO; |
|---|
| 826 | + } |
|---|
| 827 | + |
|---|
| 828 | + return 0; |
|---|
| 829 | +} |
|---|
| 830 | +EXPORT_SYMBOL_GPL(xive_native_set_queue_state); |
|---|
| 831 | + |
|---|
| 832 | +bool xive_native_has_queue_state_support(void) |
|---|
| 833 | +{ |
|---|
| 834 | + return opal_check_token(OPAL_XIVE_GET_QUEUE_STATE) && |
|---|
| 835 | + opal_check_token(OPAL_XIVE_SET_QUEUE_STATE); |
|---|
| 836 | +} |
|---|
| 837 | +EXPORT_SYMBOL_GPL(xive_native_has_queue_state_support); |
|---|
| 838 | + |
|---|
| 839 | +int xive_native_get_vp_state(u32 vp_id, u64 *out_state) |
|---|
| 840 | +{ |
|---|
| 841 | + __be64 state; |
|---|
| 842 | + s64 rc; |
|---|
| 843 | + |
|---|
| 844 | + rc = opal_xive_get_vp_state(vp_id, &state); |
|---|
| 845 | + if (rc) { |
|---|
| 846 | + pr_err("OPAL failed to get vp state for VCPU %d : %lld\n", |
|---|
| 847 | + vp_id, rc); |
|---|
| 848 | + return -EIO; |
|---|
| 849 | + } |
|---|
| 850 | + |
|---|
| 851 | + if (out_state) |
|---|
| 852 | + *out_state = be64_to_cpu(state); |
|---|
| 853 | + return 0; |
|---|
| 854 | +} |
|---|
| 855 | +EXPORT_SYMBOL_GPL(xive_native_get_vp_state); |
|---|
| 856 | + |
|---|
| 857 | +machine_arch_initcall(powernv, xive_core_debug_init); |
|---|