summaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
authorMichael Neuling <mikey@neuling.org>2014-11-14 02:09:28 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-11-26 22:29:36 -0500
commitca4f8280ff227e215f44e10f8f110b4c882b084b (patch)
tree8bc623085f0b03ed0922a489f480314cdc89ea48 /drivers/misc
parent27bbcef20a47c1b0f1ec6cc6b0d27470dbcaa05a (diff)
cxl: Name interrupts in /proc/interrupt
Currently all interrupts generated by cxl are named "cxl". This is not very informative as we can't distinguish between cards, AFUs, error interrupts, user contexts and user interrupts numbers. Being able to distinguish them is useful for setting affinity. This patch gives each of these names in /proc/interrupts. A two card CAPI system, with afu0.0 having 2 active contexts each with 4 user IRQs each, will now look like this: % grep cxl /proc/interrupts 444: 0 OPAL ICS 141312 Level cxl-card1-err 445: 0 OPAL ICS 141313 Level cxl-afu1.0-err 446: 0 OPAL ICS 141314 Level cxl-afu1.0 462: 0 OPAL ICS 2052 Level cxl-afu0.0-pe0-1 463: 75517 OPAL ICS 2053 Level cxl-afu0.0-pe0-2 468: 0 OPAL ICS 2054 Level cxl-afu0.0-pe0-3 469: 0 OPAL ICS 2055 Level cxl-afu0.0-pe0-4 470: 0 OPAL ICS 2056 Level cxl-afu0.0-pe1-1 471: 75506 OPAL ICS 2057 Level cxl-afu0.0-pe1-2 472: 0 OPAL ICS 2058 Level cxl-afu0.0-pe1-3 473: 0 OPAL ICS 2059 Level cxl-afu0.0-pe1-4 502: 1066 OPAL ICS 2050 Level cxl-afu0.0 514: 0 OPAL ICS 2048 Level cxl-card0-err 515: 0 OPAL ICS 2049 Level cxl-afu0.0-err Signed-off-by: Michael Neuling <mikey@neuling.org> Signed-off-by: Ian Munsie <imunsie@au1.ibm.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/cxl/cxl.h13
-rw-r--r--drivers/misc/cxl/irq.c98
2 files changed, 98 insertions, 13 deletions
diff --git a/drivers/misc/cxl/cxl.h b/drivers/misc/cxl/cxl.h
index 64a4aa3a5c5d..b5b6bda44a00 100644
--- a/drivers/misc/cxl/cxl.h
+++ b/drivers/misc/cxl/cxl.h
@@ -336,6 +336,8 @@ struct cxl_sste {
336struct cxl_afu { 336struct cxl_afu {
337 irq_hw_number_t psl_hwirq; 337 irq_hw_number_t psl_hwirq;
338 irq_hw_number_t serr_hwirq; 338 irq_hw_number_t serr_hwirq;
339 char *err_irq_name;
340 char *psl_irq_name;
339 unsigned int serr_virq; 341 unsigned int serr_virq;
340 void __iomem *p1n_mmio; 342 void __iomem *p1n_mmio;
341 void __iomem *p2n_mmio; 343 void __iomem *p2n_mmio;
@@ -379,6 +381,12 @@ struct cxl_afu {
379 bool enabled; 381 bool enabled;
380}; 382};
381 383
384
385struct cxl_irq_name {
386 struct list_head list;
387 char *name;
388};
389
382/* 390/*
383 * This is a cxl context. If the PSL is in dedicated mode, there will be one 391 * This is a cxl context. If the PSL is in dedicated mode, there will be one
384 * of these per AFU. If in AFU directed there can be lots of these. 392 * of these per AFU. If in AFU directed there can be lots of these.
@@ -403,6 +411,7 @@ struct cxl_context {
403 411
404 unsigned long *irq_bitmap; /* Accessed from IRQ context */ 412 unsigned long *irq_bitmap; /* Accessed from IRQ context */
405 struct cxl_irq_ranges irqs; 413 struct cxl_irq_ranges irqs;
414 struct list_head irq_names;
406 u64 fault_addr; 415 u64 fault_addr;
407 u64 fault_dsisr; 416 u64 fault_dsisr;
408 u64 afu_err; 417 u64 afu_err;
@@ -444,6 +453,7 @@ struct cxl {
444 struct dentry *trace; 453 struct dentry *trace;
445 struct dentry *psl_err_chk; 454 struct dentry *psl_err_chk;
446 struct dentry *debugfs; 455 struct dentry *debugfs;
456 char *irq_name;
447 struct bin_attribute cxl_attr; 457 struct bin_attribute cxl_attr;
448 int adapter_num; 458 int adapter_num;
449 int user_irqs; 459 int user_irqs;
@@ -563,9 +573,6 @@ int _cxl_afu_deactivate_mode(struct cxl_afu *afu, int mode);
563int cxl_afu_deactivate_mode(struct cxl_afu *afu); 573int cxl_afu_deactivate_mode(struct cxl_afu *afu);
564int cxl_afu_select_best_mode(struct cxl_afu *afu); 574int cxl_afu_select_best_mode(struct cxl_afu *afu);
565 575
566unsigned int cxl_map_irq(struct cxl *adapter, irq_hw_number_t hwirq,
567 irq_handler_t handler, void *cookie);
568void cxl_unmap_irq(unsigned int virq, void *cookie);
569int cxl_register_psl_irq(struct cxl_afu *afu); 576int cxl_register_psl_irq(struct cxl_afu *afu);
570void cxl_release_psl_irq(struct cxl_afu *afu); 577void cxl_release_psl_irq(struct cxl_afu *afu);
571int cxl_register_psl_err_irq(struct cxl *adapter); 578int cxl_register_psl_err_irq(struct cxl *adapter);
diff --git a/drivers/misc/cxl/irq.c b/drivers/misc/cxl/irq.c
index 35fcb3d43dc0..08fb4a7ec4af 100644
--- a/drivers/misc/cxl/irq.c
+++ b/drivers/misc/cxl/irq.c
@@ -255,7 +255,7 @@ static irqreturn_t cxl_irq_afu(int irq, void *data)
255} 255}
256 256
257unsigned 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,
258 irq_handler_t handler, void *cookie) 258 irq_handler_t handler, void *cookie, const char *name)
259{ 259{
260 unsigned int virq; 260 unsigned int virq;
261 int result; 261 int result;
@@ -271,7 +271,7 @@ unsigned int cxl_map_irq(struct cxl *adapter, irq_hw_number_t hwirq,
271 271
272 pr_devel("hwirq %#lx mapped to virq %u\n", hwirq, virq); 272 pr_devel("hwirq %#lx mapped to virq %u\n", hwirq, virq);
273 273
274 result = request_irq(virq, handler, 0, "cxl", cookie); 274 result = request_irq(virq, handler, 0, name, cookie);
275 if (result) { 275 if (result) {
276 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);
277 return 0; 277 return 0;
@@ -290,14 +290,15 @@ static int cxl_register_one_irq(struct cxl *adapter,
290 irq_handler_t handler, 290 irq_handler_t handler,
291 void *cookie, 291 void *cookie,
292 irq_hw_number_t *dest_hwirq, 292 irq_hw_number_t *dest_hwirq,
293 unsigned int *dest_virq) 293 unsigned int *dest_virq,
294 const char *name)
294{ 295{
295 int hwirq, virq; 296 int hwirq, virq;
296 297
297 if ((hwirq = cxl_alloc_one_irq(adapter)) < 0) 298 if ((hwirq = cxl_alloc_one_irq(adapter)) < 0)
298 return hwirq; 299 return hwirq;
299 300
300 if (!(virq = cxl_map_irq(adapter, hwirq, handler, cookie))) 301 if (!(virq = cxl_map_irq(adapter, hwirq, handler, cookie, name)))
301 goto err; 302 goto err;
302 303
303 *dest_hwirq = hwirq; 304 *dest_hwirq = hwirq;
@@ -314,10 +315,19 @@ int cxl_register_psl_err_irq(struct cxl *adapter)
314{ 315{
315 int rc; 316 int rc;
316 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
317 if ((rc = cxl_register_one_irq(adapter, cxl_irq_err, adapter, 323 if ((rc = cxl_register_one_irq(adapter, cxl_irq_err, adapter,
318 &adapter->err_hwirq, 324 &adapter->err_hwirq,
319 &adapter->err_virq))) 325 &adapter->err_virq,
326 adapter->irq_name))) {
327 kfree(adapter->irq_name);
328 adapter->irq_name = NULL;
320 return rc; 329 return rc;
330 }
321 331
322 cxl_p1_write(adapter, CXL_PSL_ErrIVTE, adapter->err_hwirq & 0xffff); 332 cxl_p1_write(adapter, CXL_PSL_ErrIVTE, adapter->err_hwirq & 0xffff);
323 333
@@ -329,6 +339,7 @@ void cxl_release_psl_err_irq(struct cxl *adapter)
329 cxl_p1_write(adapter, CXL_PSL_ErrIVTE, 0x0000000000000000); 339 cxl_p1_write(adapter, CXL_PSL_ErrIVTE, 0x0000000000000000);
330 cxl_unmap_irq(adapter->err_virq, adapter); 340 cxl_unmap_irq(adapter->err_virq, adapter);
331 cxl_release_one_irq(adapter, adapter->err_hwirq); 341 cxl_release_one_irq(adapter, adapter->err_hwirq);
342 kfree(adapter->irq_name);
332} 343}
333 344
334int cxl_register_serr_irq(struct cxl_afu *afu) 345int cxl_register_serr_irq(struct cxl_afu *afu)
@@ -336,10 +347,18 @@ int cxl_register_serr_irq(struct cxl_afu *afu)
336 u64 serr; 347 u64 serr;
337 int rc; 348 int rc;
338 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
339 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,
340 &afu->serr_hwirq, 356 &afu->serr_hwirq,
341 &afu->serr_virq))) 357 &afu->serr_virq, afu->err_irq_name))) {
358 kfree(afu->err_irq_name);
359 afu->err_irq_name = NULL;
342 return rc; 360 return rc;
361 }
343 362
344 serr = cxl_p1n_read(afu, CXL_PSL_SERR_An); 363 serr = cxl_p1n_read(afu, CXL_PSL_SERR_An);
345 serr = (serr & 0x00ffffffffff0000ULL) | (afu->serr_hwirq & 0xffff); 364 serr = (serr & 0x00ffffffffff0000ULL) | (afu->serr_hwirq & 0xffff);
@@ -353,24 +372,50 @@ void cxl_release_serr_irq(struct cxl_afu *afu)
353 cxl_p1n_write(afu, CXL_PSL_SERR_An, 0x0000000000000000); 372 cxl_p1n_write(afu, CXL_PSL_SERR_An, 0x0000000000000000);
354 cxl_unmap_irq(afu->serr_virq, afu); 373 cxl_unmap_irq(afu->serr_virq, afu);
355 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);
356} 376}
357 377
358int cxl_register_psl_irq(struct cxl_afu *afu) 378int cxl_register_psl_irq(struct cxl_afu *afu)
359{ 379{
360 return cxl_register_one_irq(afu->adapter, cxl_irq_multiplexed, afu, 380 int rc;
361 &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;
362} 394}
363 395
364void cxl_release_psl_irq(struct cxl_afu *afu) 396void cxl_release_psl_irq(struct cxl_afu *afu)
365{ 397{
366 cxl_unmap_irq(afu->psl_virq, afu); 398 cxl_unmap_irq(afu->psl_virq, afu);
367 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 }
368} 412}
369 413
370int afu_register_irqs(struct cxl_context *ctx, u32 count) 414int afu_register_irqs(struct cxl_context *ctx, u32 count)
371{ 415{
372 irq_hw_number_t hwirq; 416 irq_hw_number_t hwirq;
373 int rc, r, i; 417 int rc, r, i, j = 1;
418 struct cxl_irq_name *irq_name;
374 419
375 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)))
376 return rc; 421 return rc;
@@ -384,15 +429,47 @@ int afu_register_irqs(struct cxl_context *ctx, u32 count)
384 sizeof(*ctx->irq_bitmap), GFP_KERNEL); 429 sizeof(*ctx->irq_bitmap), GFP_KERNEL);
385 if (!ctx->irq_bitmap) 430 if (!ctx->irq_bitmap)
386 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);
387 for (r = 1; r < CXL_IRQ_RANGES; r++) { 459 for (r = 1; r < CXL_IRQ_RANGES; r++) {
388 hwirq = ctx->irqs.offset[r]; 460 hwirq = ctx->irqs.offset[r];
389 for (i = 0; i < ctx->irqs.range[r]; hwirq++, i++) { 461 for (i = 0; i < ctx->irqs.range[r]; hwirq++, i++) {
390 cxl_map_irq(ctx->afu->adapter, hwirq, 462 cxl_map_irq(ctx->afu->adapter, hwirq,
391 cxl_irq_afu, ctx); 463 cxl_irq_afu, ctx, irq_name->name);
464 irq_name = list_next_entry(irq_name, list);
392 } 465 }
393 } 466 }
394 467
395 return 0; 468 return 0;
469
470out:
471 afu_irq_name_free(ctx);
472 return -ENOMEM;
396} 473}
397 474
398void afu_release_irqs(struct cxl_context *ctx) 475void afu_release_irqs(struct cxl_context *ctx)
@@ -410,5 +487,6 @@ void afu_release_irqs(struct cxl_context *ctx)
410 } 487 }
411 } 488 }
412 489
490 afu_irq_name_free(ctx);
413 cxl_release_irq_ranges(&ctx->irqs, ctx->afu->adapter); 491 cxl_release_irq_ranges(&ctx->irqs, ctx->afu->adapter);
414} 492}