.. | .. |
---|
| 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); |
---|