aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/cxl/irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/cxl/irq.c')
-rw-r--r--drivers/misc/cxl/irq.c144
1 files changed, 117 insertions, 27 deletions
diff --git a/drivers/misc/cxl/irq.c b/drivers/misc/cxl/irq.c
index 336020c8e1af..c294925f73ee 100644
--- a/drivers/misc/cxl/irq.c
+++ b/drivers/misc/cxl/irq.c
@@ -92,20 +92,13 @@ static irqreturn_t schedule_cxl_fault(struct cxl_context *ctx, u64 dsisr, u64 da
92 return IRQ_HANDLED; 92 return IRQ_HANDLED;
93} 93}
94 94
95static irqreturn_t cxl_irq(int irq, void *data) 95static irqreturn_t cxl_irq(int irq, void *data, struct cxl_irq_info *irq_info)
96{ 96{
97 struct cxl_context *ctx = data; 97 struct cxl_context *ctx = data;
98 struct cxl_irq_info irq_info;
99 u64 dsisr, dar; 98 u64 dsisr, dar;
100 int result;
101
102 if ((result = cxl_get_irq(ctx, &irq_info))) {
103 WARN(1, "Unable to get CXL IRQ Info: %i\n", result);
104 return IRQ_HANDLED;
105 }
106 99
107 dsisr = irq_info.dsisr; 100 dsisr = irq_info->dsisr;
108 dar = irq_info.dar; 101 dar = irq_info->dar;
109 102
110 pr_devel("CXL interrupt %i for afu pe: %i DSISR: %#llx DAR: %#llx\n", irq, ctx->pe, dsisr, dar); 103 pr_devel("CXL interrupt %i for afu pe: %i DSISR: %#llx DAR: %#llx\n", irq, ctx->pe, dsisr, dar);
111 104
@@ -149,9 +142,9 @@ static irqreturn_t cxl_irq(int irq, void *data)
149 if (dsisr & CXL_PSL_DSISR_An_UR) 142 if (dsisr & CXL_PSL_DSISR_An_UR)
150 pr_devel("CXL interrupt: AURP PTE not found\n"); 143 pr_devel("CXL interrupt: AURP PTE not found\n");
151 if (dsisr & CXL_PSL_DSISR_An_PE) 144 if (dsisr & CXL_PSL_DSISR_An_PE)
152 return handle_psl_slice_error(ctx, dsisr, irq_info.errstat); 145 return handle_psl_slice_error(ctx, dsisr, irq_info->errstat);
153 if (dsisr & CXL_PSL_DSISR_An_AE) { 146 if (dsisr & CXL_PSL_DSISR_An_AE) {
154 pr_devel("CXL interrupt: AFU Error %.llx\n", irq_info.afu_err); 147 pr_devel("CXL interrupt: AFU Error %.llx\n", irq_info->afu_err);
155 148
156 if (ctx->pending_afu_err) { 149 if (ctx->pending_afu_err) {
157 /* 150 /*
@@ -163,10 +156,10 @@ static irqreturn_t cxl_irq(int irq, void *data)
163 */ 156 */
164 dev_err_ratelimited(&ctx->afu->dev, "CXL AFU Error " 157 dev_err_ratelimited(&ctx->afu->dev, "CXL AFU Error "
165 "undelivered to pe %i: %.llx\n", 158 "undelivered to pe %i: %.llx\n",
166 ctx->pe, irq_info.afu_err); 159 ctx->pe, irq_info->afu_err);
167 } else { 160 } else {
168 spin_lock(&ctx->lock); 161 spin_lock(&ctx->lock);
169 ctx->afu_err = irq_info.afu_err; 162 ctx->afu_err = irq_info->afu_err;
170 ctx->pending_afu_err = 1; 163 ctx->pending_afu_err = 1;
171 spin_unlock(&ctx->lock); 164 spin_unlock(&ctx->lock);
172 165
@@ -182,24 +175,43 @@ static irqreturn_t cxl_irq(int irq, void *data)
182 return IRQ_HANDLED; 175 return IRQ_HANDLED;
183} 176}
184 177
178static irqreturn_t fail_psl_irq(struct cxl_afu *afu, struct cxl_irq_info *irq_info)
179{
180 if (irq_info->dsisr & CXL_PSL_DSISR_TRANS)
181 cxl_p2n_write(afu, CXL_PSL_TFC_An, CXL_PSL_TFC_An_AE);
182 else
183 cxl_p2n_write(afu, CXL_PSL_TFC_An, CXL_PSL_TFC_An_A);
184
185 return IRQ_HANDLED;
186}
187
185static irqreturn_t cxl_irq_multiplexed(int irq, void *data) 188static irqreturn_t cxl_irq_multiplexed(int irq, void *data)
186{ 189{
187 struct cxl_afu *afu = data; 190 struct cxl_afu *afu = data;
188 struct cxl_context *ctx; 191 struct cxl_context *ctx;
192 struct cxl_irq_info irq_info;
189 int ph = cxl_p2n_read(afu, CXL_PSL_PEHandle_An) & 0xffff; 193 int ph = cxl_p2n_read(afu, CXL_PSL_PEHandle_An) & 0xffff;
190 int ret; 194 int ret;
191 195
196 if ((ret = cxl_get_irq(afu, &irq_info))) {
197 WARN(1, "Unable to get CXL IRQ Info: %i\n", ret);
198 return fail_psl_irq(afu, &irq_info);
199 }
200
192 rcu_read_lock(); 201 rcu_read_lock();
193 ctx = idr_find(&afu->contexts_idr, ph); 202 ctx = idr_find(&afu->contexts_idr, ph);
194 if (ctx) { 203 if (ctx) {
195 ret = cxl_irq(irq, ctx); 204 ret = cxl_irq(irq, ctx, &irq_info);
196 rcu_read_unlock(); 205 rcu_read_unlock();
197 return ret; 206 return ret;
198 } 207 }
199 rcu_read_unlock(); 208 rcu_read_unlock();
200 209
201 WARN(1, "Unable to demultiplex CXL PSL IRQ\n"); 210 WARN(1, "Unable to demultiplex CXL PSL IRQ for PE %i DSISR %.16llx DAR"
202 return IRQ_HANDLED; 211 " %.16llx\n(Possible AFU HW issue - was a term/remove acked"
212 " with outstanding transactions?)\n", ph, irq_info.dsisr,
213 irq_info.dar);
214 return fail_psl_irq(afu, &irq_info);
203} 215}
204 216
205static irqreturn_t cxl_irq_afu(int irq, void *data) 217static irqreturn_t cxl_irq_afu(int irq, void *data)
@@ -243,7 +255,7 @@ static irqreturn_t cxl_irq_afu(int irq, void *data)
243} 255}
244 256
245unsigned int cxl_map_irq(struct cxl *adapter, irq_hw_number_t hwirq, 257unsigned int cxl_map_irq(struct cxl *adapter, irq_hw_number_t hwirq,
246 irq_handler_t handler, void *cookie) 258 irq_handler_t handler, void *cookie, const char *name)
247{ 259{
248 unsigned int virq; 260 unsigned int virq;
249 int result; 261 int result;
@@ -259,7 +271,7 @@ unsigned int cxl_map_irq(struct cxl *adapter, irq_hw_number_t hwirq,
259 271
260 pr_devel("hwirq %#lx mapped to virq %u\n", hwirq, virq); 272 pr_devel("hwirq %#lx mapped to virq %u\n", hwirq, virq);
261 273
262 result = request_irq(virq, handler, 0, "cxl", cookie); 274 result = request_irq(virq, handler, 0, name, cookie);
263 if (result) { 275 if (result) {
264 dev_warn(&adapter->dev, "cxl_map_irq: request_irq failed: %i\n", result); 276 dev_warn(&adapter->dev, "cxl_map_irq: request_irq failed: %i\n", result);
265 return 0; 277 return 0;
@@ -278,14 +290,15 @@ static int cxl_register_one_irq(struct cxl *adapter,
278 irq_handler_t handler, 290 irq_handler_t handler,
279 void *cookie, 291 void *cookie,
280 irq_hw_number_t *dest_hwirq, 292 irq_hw_number_t *dest_hwirq,
281 unsigned int *dest_virq) 293 unsigned int *dest_virq,
294 const char *name)
282{ 295{
283 int hwirq, virq; 296 int hwirq, virq;
284 297
285 if ((hwirq = cxl_alloc_one_irq(adapter)) < 0) 298 if ((hwirq = cxl_alloc_one_irq(adapter)) < 0)
286 return hwirq; 299 return hwirq;
287 300
288 if (!(virq = cxl_map_irq(adapter, hwirq, handler, cookie))) 301 if (!(virq = cxl_map_irq(adapter, hwirq, handler, cookie, name)))
289 goto err; 302 goto err;
290 303
291 *dest_hwirq = hwirq; 304 *dest_hwirq = hwirq;
@@ -302,10 +315,19 @@ int cxl_register_psl_err_irq(struct cxl *adapter)
302{ 315{
303 int rc; 316 int rc;
304 317
318 adapter->irq_name = kasprintf(GFP_KERNEL, "cxl-%s-err",
319 dev_name(&adapter->dev));
320 if (!adapter->irq_name)
321 return -ENOMEM;
322
305 if ((rc = cxl_register_one_irq(adapter, cxl_irq_err, adapter, 323 if ((rc = cxl_register_one_irq(adapter, cxl_irq_err, adapter,
306 &adapter->err_hwirq, 324 &adapter->err_hwirq,
307 &adapter->err_virq))) 325 &adapter->err_virq,
326 adapter->irq_name))) {
327 kfree(adapter->irq_name);
328 adapter->irq_name = NULL;
308 return rc; 329 return rc;
330 }
309 331
310 cxl_p1_write(adapter, CXL_PSL_ErrIVTE, adapter->err_hwirq & 0xffff); 332 cxl_p1_write(adapter, CXL_PSL_ErrIVTE, adapter->err_hwirq & 0xffff);
311 333
@@ -317,6 +339,7 @@ void cxl_release_psl_err_irq(struct cxl *adapter)
317 cxl_p1_write(adapter, CXL_PSL_ErrIVTE, 0x0000000000000000); 339 cxl_p1_write(adapter, CXL_PSL_ErrIVTE, 0x0000000000000000);
318 cxl_unmap_irq(adapter->err_virq, adapter); 340 cxl_unmap_irq(adapter->err_virq, adapter);
319 cxl_release_one_irq(adapter, adapter->err_hwirq); 341 cxl_release_one_irq(adapter, adapter->err_hwirq);
342 kfree(adapter->irq_name);
320} 343}
321 344
322int cxl_register_serr_irq(struct cxl_afu *afu) 345int cxl_register_serr_irq(struct cxl_afu *afu)
@@ -324,10 +347,18 @@ int cxl_register_serr_irq(struct cxl_afu *afu)
324 u64 serr; 347 u64 serr;
325 int rc; 348 int rc;
326 349
350 afu->err_irq_name = kasprintf(GFP_KERNEL, "cxl-%s-err",
351 dev_name(&afu->dev));
352 if (!afu->err_irq_name)
353 return -ENOMEM;
354
327 if ((rc = cxl_register_one_irq(afu->adapter, cxl_slice_irq_err, afu, 355 if ((rc = cxl_register_one_irq(afu->adapter, cxl_slice_irq_err, afu,
328 &afu->serr_hwirq, 356 &afu->serr_hwirq,
329 &afu->serr_virq))) 357 &afu->serr_virq, afu->err_irq_name))) {
358 kfree(afu->err_irq_name);
359 afu->err_irq_name = NULL;
330 return rc; 360 return rc;
361 }
331 362
332 serr = cxl_p1n_read(afu, CXL_PSL_SERR_An); 363 serr = cxl_p1n_read(afu, CXL_PSL_SERR_An);
333 serr = (serr & 0x00ffffffffff0000ULL) | (afu->serr_hwirq & 0xffff); 364 serr = (serr & 0x00ffffffffff0000ULL) | (afu->serr_hwirq & 0xffff);
@@ -341,24 +372,50 @@ void cxl_release_serr_irq(struct cxl_afu *afu)
341 cxl_p1n_write(afu, CXL_PSL_SERR_An, 0x0000000000000000); 372 cxl_p1n_write(afu, CXL_PSL_SERR_An, 0x0000000000000000);
342 cxl_unmap_irq(afu->serr_virq, afu); 373 cxl_unmap_irq(afu->serr_virq, afu);
343 cxl_release_one_irq(afu->adapter, afu->serr_hwirq); 374 cxl_release_one_irq(afu->adapter, afu->serr_hwirq);
375 kfree(afu->err_irq_name);
344} 376}
345 377
346int cxl_register_psl_irq(struct cxl_afu *afu) 378int cxl_register_psl_irq(struct cxl_afu *afu)
347{ 379{
348 return cxl_register_one_irq(afu->adapter, cxl_irq_multiplexed, afu, 380 int rc;
349 &afu->psl_hwirq, &afu->psl_virq); 381
382 afu->psl_irq_name = kasprintf(GFP_KERNEL, "cxl-%s",
383 dev_name(&afu->dev));
384 if (!afu->psl_irq_name)
385 return -ENOMEM;
386
387 if ((rc = cxl_register_one_irq(afu->adapter, cxl_irq_multiplexed, afu,
388 &afu->psl_hwirq, &afu->psl_virq,
389 afu->psl_irq_name))) {
390 kfree(afu->psl_irq_name);
391 afu->psl_irq_name = NULL;
392 }
393 return rc;
350} 394}
351 395
352void cxl_release_psl_irq(struct cxl_afu *afu) 396void cxl_release_psl_irq(struct cxl_afu *afu)
353{ 397{
354 cxl_unmap_irq(afu->psl_virq, afu); 398 cxl_unmap_irq(afu->psl_virq, afu);
355 cxl_release_one_irq(afu->adapter, afu->psl_hwirq); 399 cxl_release_one_irq(afu->adapter, afu->psl_hwirq);
400 kfree(afu->psl_irq_name);
401}
402
403void afu_irq_name_free(struct cxl_context *ctx)
404{
405 struct cxl_irq_name *irq_name, *tmp;
406
407 list_for_each_entry_safe(irq_name, tmp, &ctx->irq_names, list) {
408 kfree(irq_name->name);
409 list_del(&irq_name->list);
410 kfree(irq_name);
411 }
356} 412}
357 413
358int afu_register_irqs(struct cxl_context *ctx, u32 count) 414int afu_register_irqs(struct cxl_context *ctx, u32 count)
359{ 415{
360 irq_hw_number_t hwirq; 416 irq_hw_number_t hwirq;
361 int rc, r, i; 417 int rc, r, i, j = 1;
418 struct cxl_irq_name *irq_name;
362 419
363 if ((rc = cxl_alloc_irq_ranges(&ctx->irqs, ctx->afu->adapter, count))) 420 if ((rc = cxl_alloc_irq_ranges(&ctx->irqs, ctx->afu->adapter, count)))
364 return rc; 421 return rc;
@@ -372,15 +429,47 @@ int afu_register_irqs(struct cxl_context *ctx, u32 count)
372 sizeof(*ctx->irq_bitmap), GFP_KERNEL); 429 sizeof(*ctx->irq_bitmap), GFP_KERNEL);
373 if (!ctx->irq_bitmap) 430 if (!ctx->irq_bitmap)
374 return -ENOMEM; 431 return -ENOMEM;
432
433 /*
434 * Allocate names first. If any fail, bail out before allocating
435 * actual hardware IRQs.
436 */
437 INIT_LIST_HEAD(&ctx->irq_names);
438 for (r = 1; r < CXL_IRQ_RANGES; r++) {
439 for (i = 0; i < ctx->irqs.range[r]; hwirq++, i++) {
440 irq_name = kmalloc(sizeof(struct cxl_irq_name),
441 GFP_KERNEL);
442 if (!irq_name)
443 goto out;
444 irq_name->name = kasprintf(GFP_KERNEL, "cxl-%s-pe%i-%i",
445 dev_name(&ctx->afu->dev),
446 ctx->pe, j);
447 if (!irq_name->name) {
448 kfree(irq_name);
449 goto out;
450 }
451 /* Add to tail so next look get the correct order */
452 list_add_tail(&irq_name->list, &ctx->irq_names);
453 j++;
454 }
455 }
456
457 /* We've allocated all memory now, so let's do the irq allocations */
458 irq_name = list_first_entry(&ctx->irq_names, struct cxl_irq_name, list);
375 for (r = 1; r < CXL_IRQ_RANGES; r++) { 459 for (r = 1; r < CXL_IRQ_RANGES; r++) {
376 hwirq = ctx->irqs.offset[r]; 460 hwirq = ctx->irqs.offset[r];
377 for (i = 0; i < ctx->irqs.range[r]; hwirq++, i++) { 461 for (i = 0; i < ctx->irqs.range[r]; hwirq++, i++) {
378 cxl_map_irq(ctx->afu->adapter, hwirq, 462 cxl_map_irq(ctx->afu->adapter, hwirq,
379 cxl_irq_afu, ctx); 463 cxl_irq_afu, ctx, irq_name->name);
464 irq_name = list_next_entry(irq_name, list);
380 } 465 }
381 } 466 }
382 467
383 return 0; 468 return 0;
469
470out:
471 afu_irq_name_free(ctx);
472 return -ENOMEM;
384} 473}
385 474
386void afu_release_irqs(struct cxl_context *ctx) 475void afu_release_irqs(struct cxl_context *ctx)
@@ -398,5 +487,6 @@ void afu_release_irqs(struct cxl_context *ctx)
398 } 487 }
399 } 488 }
400 489
490 afu_irq_name_free(ctx);
401 cxl_release_irq_ranges(&ctx->irqs, ctx->afu->adapter); 491 cxl_release_irq_ranges(&ctx->irqs, ctx->afu->adapter);
402} 492}