hc
2023-12-11 1f93a7dfd1f8d5ff7a5c53246c7534fe2332d6f4
kernel/arch/powerpc/platforms/powernv/vas.c
....@@ -1,10 +1,6 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Copyright 2016-17 IBM Corp.
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.
84 */
95
106 #define pr_fmt(fmt) "vas: " fmt
....@@ -18,7 +14,10 @@
1814 #include <linux/of_platform.h>
1915 #include <linux/of_address.h>
2016 #include <linux/of.h>
17
+#include <linux/irqdomain.h>
18
+#include <linux/interrupt.h>
2119 #include <asm/prom.h>
20
+#include <asm/xive.h>
2221
2322 #include "vas.h"
2423
....@@ -27,16 +26,47 @@
2726
2827 static DEFINE_PER_CPU(int, cpu_vas_id);
2928
29
+static int vas_irq_fault_window_setup(struct vas_instance *vinst)
30
+{
31
+ char devname[64];
32
+ int rc = 0;
33
+
34
+ snprintf(devname, sizeof(devname), "vas-%d", vinst->vas_id);
35
+ rc = request_threaded_irq(vinst->virq, vas_fault_handler,
36
+ vas_fault_thread_fn, 0, devname, vinst);
37
+
38
+ if (rc) {
39
+ pr_err("VAS[%d]: Request IRQ(%d) failed with %d\n",
40
+ vinst->vas_id, vinst->virq, rc);
41
+ goto out;
42
+ }
43
+
44
+ rc = vas_setup_fault_window(vinst);
45
+ if (rc)
46
+ free_irq(vinst->virq, vinst);
47
+
48
+out:
49
+ return rc;
50
+}
51
+
3052 static int init_vas_instance(struct platform_device *pdev)
3153 {
32
- int rc, cpu, vasid;
33
- struct resource *res;
34
- struct vas_instance *vinst;
3554 struct device_node *dn = pdev->dev.of_node;
55
+ struct vas_instance *vinst;
56
+ struct xive_irq_data *xd;
57
+ uint32_t chipid, hwirq;
58
+ struct resource *res;
59
+ int rc, cpu, vasid;
3660
3761 rc = of_property_read_u32(dn, "ibm,vas-id", &vasid);
3862 if (rc) {
3963 pr_err("No ibm,vas-id property for %s?\n", pdev->name);
64
+ return -ENODEV;
65
+ }
66
+
67
+ rc = of_property_read_u32(dn, "ibm,chip-id", &chipid);
68
+ if (rc) {
69
+ pr_err("No ibm,chip-id property for %s?\n", pdev->name);
4070 return -ENODEV;
4171 }
4272
....@@ -73,9 +103,32 @@
73103
74104 vinst->paste_win_id_shift = 63 - res->end;
75105
76
- pr_devel("Initialized instance [%s, %d], paste_base 0x%llx, "
77
- "paste_win_id_shift 0x%llx\n", pdev->name, vasid,
78
- vinst->paste_base_addr, vinst->paste_win_id_shift);
106
+ hwirq = xive_native_alloc_irq_on_chip(chipid);
107
+ if (!hwirq) {
108
+ pr_err("Inst%d: Unable to allocate global irq for chip %d\n",
109
+ vinst->vas_id, chipid);
110
+ return -ENOENT;
111
+ }
112
+
113
+ vinst->virq = irq_create_mapping(NULL, hwirq);
114
+ if (!vinst->virq) {
115
+ pr_err("Inst%d: Unable to map global irq %d\n",
116
+ vinst->vas_id, hwirq);
117
+ return -EINVAL;
118
+ }
119
+
120
+ xd = irq_get_handler_data(vinst->virq);
121
+ if (!xd) {
122
+ pr_err("Inst%d: Invalid virq %d\n",
123
+ vinst->vas_id, vinst->virq);
124
+ return -EINVAL;
125
+ }
126
+
127
+ vinst->irq_port = xd->trig_page;
128
+ pr_devel("Initialized instance [%s, %d] paste_base 0x%llx paste_win_id_shift 0x%llx IRQ %d Port 0x%llx\n",
129
+ pdev->name, vasid, vinst->paste_base_addr,
130
+ vinst->paste_win_id_shift, vinst->virq,
131
+ vinst->irq_port);
79132
80133 for_each_possible_cpu(cpu) {
81134 if (cpu_to_chip_id(cpu) == of_get_ibm_chip_id(dn))
....@@ -86,6 +139,22 @@
86139 list_add(&vinst->node, &vas_instances);
87140 mutex_unlock(&vas_mutex);
88141
142
+ spin_lock_init(&vinst->fault_lock);
143
+ /*
144
+ * IRQ and fault handling setup is needed only for user space
145
+ * send windows.
146
+ */
147
+ if (vinst->virq) {
148
+ rc = vas_irq_fault_window_setup(vinst);
149
+ /*
150
+ * Fault window is used only for user space send windows.
151
+ * So if vinst->virq is NULL, tx_win_open returns -ENODEV
152
+ * for user space.
153
+ */
154
+ if (rc)
155
+ vinst->virq = 0;
156
+ }
157
+
89158 vas_instance_init_dbgdir(vinst);
90159
91160 dev_set_drvdata(&pdev->dev, vinst);