hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/misc/ocxl/afu_irq.c
....@@ -1,8 +1,8 @@
11 // SPDX-License-Identifier: GPL-2.0+
22 // Copyright 2017 IBM Corp.
33 #include <linux/interrupt.h>
4
-#include <linux/eventfd.h>
54 #include <asm/pnv-ocxl.h>
5
+#include <asm/xive.h>
66 #include "ocxl_internal.h"
77 #include "trace.h"
88
....@@ -11,28 +11,59 @@
1111 int hw_irq;
1212 unsigned int virq;
1313 char *name;
14
- u64 trigger_page;
15
- struct eventfd_ctx *ev_ctx;
14
+ irqreturn_t (*handler)(void *private);
15
+ void (*free_private)(void *private);
16
+ void *private;
1617 };
1718
18
-static int irq_offset_to_id(struct ocxl_context *ctx, u64 offset)
19
+int ocxl_irq_offset_to_id(struct ocxl_context *ctx, u64 offset)
1920 {
2021 return (offset - ctx->afu->irq_base_offset) >> PAGE_SHIFT;
2122 }
2223
23
-static u64 irq_id_to_offset(struct ocxl_context *ctx, int id)
24
+u64 ocxl_irq_id_to_offset(struct ocxl_context *ctx, int irq_id)
2425 {
25
- return ctx->afu->irq_base_offset + (id << PAGE_SHIFT);
26
+ return ctx->afu->irq_base_offset + (irq_id << PAGE_SHIFT);
2627 }
28
+
29
+int ocxl_irq_set_handler(struct ocxl_context *ctx, int irq_id,
30
+ irqreturn_t (*handler)(void *private),
31
+ void (*free_private)(void *private),
32
+ void *private)
33
+{
34
+ struct afu_irq *irq;
35
+ int rc;
36
+
37
+ mutex_lock(&ctx->irq_lock);
38
+ irq = idr_find(&ctx->irq_idr, irq_id);
39
+ if (!irq) {
40
+ rc = -EINVAL;
41
+ goto unlock;
42
+ }
43
+
44
+ irq->handler = handler;
45
+ irq->private = private;
46
+ irq->free_private = free_private;
47
+
48
+ rc = 0;
49
+ // Fall through to unlock
50
+
51
+unlock:
52
+ mutex_unlock(&ctx->irq_lock);
53
+ return rc;
54
+}
55
+EXPORT_SYMBOL_GPL(ocxl_irq_set_handler);
2756
2857 static irqreturn_t afu_irq_handler(int virq, void *data)
2958 {
3059 struct afu_irq *irq = (struct afu_irq *) data;
3160
3261 trace_ocxl_afu_irq_receive(virq);
33
- if (irq->ev_ctx)
34
- eventfd_signal(irq->ev_ctx, 1);
35
- return IRQ_HANDLED;
62
+
63
+ if (irq->handler)
64
+ return irq->handler(irq->private);
65
+
66
+ return IRQ_HANDLED; // Just drop it on the ground
3667 }
3768
3869 static int setup_afu_irq(struct ocxl_context *ctx, struct afu_irq *irq)
....@@ -70,7 +101,7 @@
70101 kfree(irq->name);
71102 }
72103
73
-int ocxl_afu_irq_alloc(struct ocxl_context *ctx, u64 *irq_offset)
104
+int ocxl_afu_irq_alloc(struct ocxl_context *ctx, int *irq_id)
74105 {
75106 struct afu_irq *irq;
76107 int rc;
....@@ -93,8 +124,7 @@
93124 goto err_unlock;
94125 }
95126
96
- rc = ocxl_link_irq_alloc(ctx->afu->fn->link, &irq->hw_irq,
97
- &irq->trigger_page);
127
+ rc = ocxl_link_irq_alloc(ctx->afu->fn->link, &irq->hw_irq);
98128 if (rc)
99129 goto err_idr;
100130
....@@ -102,11 +132,11 @@
102132 if (rc)
103133 goto err_alloc;
104134
105
- *irq_offset = irq_id_to_offset(ctx, irq->id);
106
-
107
- trace_ocxl_afu_irq_alloc(ctx->pasid, irq->id, irq->virq, irq->hw_irq,
108
- *irq_offset);
135
+ trace_ocxl_afu_irq_alloc(ctx->pasid, irq->id, irq->virq, irq->hw_irq);
109136 mutex_unlock(&ctx->irq_lock);
137
+
138
+ *irq_id = irq->id;
139
+
110140 return 0;
111141
112142 err_alloc:
....@@ -118,29 +148,29 @@
118148 kfree(irq);
119149 return rc;
120150 }
151
+EXPORT_SYMBOL_GPL(ocxl_afu_irq_alloc);
121152
122153 static void afu_irq_free(struct afu_irq *irq, struct ocxl_context *ctx)
123154 {
124155 trace_ocxl_afu_irq_free(ctx->pasid, irq->id);
125156 if (ctx->mapping)
126157 unmap_mapping_range(ctx->mapping,
127
- irq_id_to_offset(ctx, irq->id),
158
+ ocxl_irq_id_to_offset(ctx, irq->id),
128159 1 << PAGE_SHIFT, 1);
129160 release_afu_irq(irq);
130
- if (irq->ev_ctx)
131
- eventfd_ctx_put(irq->ev_ctx);
161
+ if (irq->free_private)
162
+ irq->free_private(irq->private);
132163 ocxl_link_free_irq(ctx->afu->fn->link, irq->hw_irq);
133164 kfree(irq);
134165 }
135166
136
-int ocxl_afu_irq_free(struct ocxl_context *ctx, u64 irq_offset)
167
+int ocxl_afu_irq_free(struct ocxl_context *ctx, int irq_id)
137168 {
138169 struct afu_irq *irq;
139
- int id = irq_offset_to_id(ctx, irq_offset);
140170
141171 mutex_lock(&ctx->irq_lock);
142172
143
- irq = idr_find(&ctx->irq_idr, id);
173
+ irq = idr_find(&ctx->irq_idr, irq_id);
144174 if (!irq) {
145175 mutex_unlock(&ctx->irq_lock);
146176 return -EINVAL;
....@@ -150,6 +180,7 @@
150180 mutex_unlock(&ctx->irq_lock);
151181 return 0;
152182 }
183
+EXPORT_SYMBOL_GPL(ocxl_afu_irq_free);
153184
154185 void ocxl_afu_irq_free_all(struct ocxl_context *ctx)
155186 {
....@@ -162,41 +193,19 @@
162193 mutex_unlock(&ctx->irq_lock);
163194 }
164195
165
-int ocxl_afu_irq_set_fd(struct ocxl_context *ctx, u64 irq_offset, int eventfd)
196
+u64 ocxl_afu_irq_get_addr(struct ocxl_context *ctx, int irq_id)
166197 {
198
+ struct xive_irq_data *xd;
167199 struct afu_irq *irq;
168
- struct eventfd_ctx *ev_ctx;
169
- int rc = 0, id = irq_offset_to_id(ctx, irq_offset);
170
-
171
- mutex_lock(&ctx->irq_lock);
172
- irq = idr_find(&ctx->irq_idr, id);
173
- if (!irq) {
174
- rc = -EINVAL;
175
- goto unlock;
176
- }
177
-
178
- ev_ctx = eventfd_ctx_fdget(eventfd);
179
- if (IS_ERR(ev_ctx)) {
180
- rc = -EINVAL;
181
- goto unlock;
182
- }
183
-
184
- irq->ev_ctx = ev_ctx;
185
-unlock:
186
- mutex_unlock(&ctx->irq_lock);
187
- return rc;
188
-}
189
-
190
-u64 ocxl_afu_irq_get_addr(struct ocxl_context *ctx, u64 irq_offset)
191
-{
192
- struct afu_irq *irq;
193
- int id = irq_offset_to_id(ctx, irq_offset);
194200 u64 addr = 0;
195201
196202 mutex_lock(&ctx->irq_lock);
197
- irq = idr_find(&ctx->irq_idr, id);
198
- if (irq)
199
- addr = irq->trigger_page;
203
+ irq = idr_find(&ctx->irq_idr, irq_id);
204
+ if (irq) {
205
+ xd = irq_get_handler_data(irq->virq);
206
+ addr = xd ? xd->trig_page : 0;
207
+ }
200208 mutex_unlock(&ctx->irq_lock);
201209 return addr;
202210 }
211
+EXPORT_SYMBOL_GPL(ocxl_afu_irq_get_addr);