Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Michael Ellerman <mpe@ellerman.id.au>

authored by

Michael Neuling and committed by
Michael Ellerman
80fa93fc bc78b05b

+98 -13
+10 -3
drivers/misc/cxl/cxl.h
··· 336 336 struct cxl_afu { 337 337 irq_hw_number_t psl_hwirq; 338 338 irq_hw_number_t serr_hwirq; 339 + char *err_irq_name; 340 + char *psl_irq_name; 339 341 unsigned int serr_virq; 340 342 void __iomem *p1n_mmio; 341 343 void __iomem *p2n_mmio; ··· 381 379 bool enabled; 382 380 }; 383 381 382 + 383 + struct cxl_irq_name { 384 + struct list_head list; 385 + char *name; 386 + }; 387 + 384 388 /* 385 389 * This is a cxl context. If the PSL is in dedicated mode, there will be one 386 390 * of these per AFU. If in AFU directed there can be lots of these. ··· 411 403 412 404 unsigned long *irq_bitmap; /* Accessed from IRQ context */ 413 405 struct cxl_irq_ranges irqs; 406 + struct list_head irq_names; 414 407 u64 fault_addr; 415 408 u64 fault_dsisr; 416 409 u64 afu_err; ··· 453 444 struct dentry *trace; 454 445 struct dentry *psl_err_chk; 455 446 struct dentry *debugfs; 447 + char *irq_name; 456 448 struct bin_attribute cxl_attr; 457 449 int adapter_num; 458 450 int user_irqs; ··· 573 563 int cxl_afu_deactivate_mode(struct cxl_afu *afu); 574 564 int cxl_afu_select_best_mode(struct cxl_afu *afu); 575 565 576 - unsigned int cxl_map_irq(struct cxl *adapter, irq_hw_number_t hwirq, 577 - irq_handler_t handler, void *cookie); 578 - void cxl_unmap_irq(unsigned int virq, void *cookie); 579 566 int cxl_register_psl_irq(struct cxl_afu *afu); 580 567 void cxl_release_psl_irq(struct cxl_afu *afu); 581 568 int cxl_register_psl_err_irq(struct cxl *adapter);
+88 -10
drivers/misc/cxl/irq.c
··· 255 255 } 256 256 257 257 unsigned 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 260 unsigned int virq; 261 261 int result; ··· 271 271 272 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 275 if (result) { 276 276 dev_warn(&adapter->dev, "cxl_map_irq: request_irq failed: %i\n", result); 277 277 return 0; ··· 290 290 irq_handler_t handler, 291 291 void *cookie, 292 292 irq_hw_number_t *dest_hwirq, 293 - unsigned int *dest_virq) 293 + unsigned int *dest_virq, 294 + const char *name) 294 295 { 295 296 int hwirq, virq; 296 297 297 298 if ((hwirq = cxl_alloc_one_irq(adapter)) < 0) 298 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 302 goto err; 302 303 303 304 *dest_hwirq = hwirq; ··· 315 314 { 316 315 int rc; 317 316 317 + adapter->irq_name = kasprintf(GFP_KERNEL, "cxl-%s-err", 318 + dev_name(&adapter->dev)); 319 + if (!adapter->irq_name) 320 + return -ENOMEM; 321 + 318 322 if ((rc = cxl_register_one_irq(adapter, cxl_irq_err, adapter, 319 323 &adapter->err_hwirq, 320 - &adapter->err_virq))) 324 + &adapter->err_virq, 325 + adapter->irq_name))) { 326 + kfree(adapter->irq_name); 327 + adapter->irq_name = NULL; 321 328 return rc; 329 + } 322 330 323 331 cxl_p1_write(adapter, CXL_PSL_ErrIVTE, adapter->err_hwirq & 0xffff); 324 332 ··· 339 329 cxl_p1_write(adapter, CXL_PSL_ErrIVTE, 0x0000000000000000); 340 330 cxl_unmap_irq(adapter->err_virq, adapter); 341 331 cxl_release_one_irq(adapter, adapter->err_hwirq); 332 + kfree(adapter->irq_name); 342 333 } 343 334 344 335 int cxl_register_serr_irq(struct cxl_afu *afu) ··· 347 336 u64 serr; 348 337 int rc; 349 338 339 + afu->err_irq_name = kasprintf(GFP_KERNEL, "cxl-%s-err", 340 + dev_name(&afu->dev)); 341 + if (!afu->err_irq_name) 342 + return -ENOMEM; 343 + 350 344 if ((rc = cxl_register_one_irq(afu->adapter, cxl_slice_irq_err, afu, 351 345 &afu->serr_hwirq, 352 - &afu->serr_virq))) 346 + &afu->serr_virq, afu->err_irq_name))) { 347 + kfree(afu->err_irq_name); 348 + afu->err_irq_name = NULL; 353 349 return rc; 350 + } 354 351 355 352 serr = cxl_p1n_read(afu, CXL_PSL_SERR_An); 356 353 serr = (serr & 0x00ffffffffff0000ULL) | (afu->serr_hwirq & 0xffff); ··· 372 353 cxl_p1n_write(afu, CXL_PSL_SERR_An, 0x0000000000000000); 373 354 cxl_unmap_irq(afu->serr_virq, afu); 374 355 cxl_release_one_irq(afu->adapter, afu->serr_hwirq); 356 + kfree(afu->err_irq_name); 375 357 } 376 358 377 359 int cxl_register_psl_irq(struct cxl_afu *afu) 378 360 { 379 - return cxl_register_one_irq(afu->adapter, cxl_irq_multiplexed, afu, 380 - &afu->psl_hwirq, &afu->psl_virq); 361 + int rc; 362 + 363 + afu->psl_irq_name = kasprintf(GFP_KERNEL, "cxl-%s", 364 + dev_name(&afu->dev)); 365 + if (!afu->psl_irq_name) 366 + return -ENOMEM; 367 + 368 + if ((rc = cxl_register_one_irq(afu->adapter, cxl_irq_multiplexed, afu, 369 + &afu->psl_hwirq, &afu->psl_virq, 370 + afu->psl_irq_name))) { 371 + kfree(afu->psl_irq_name); 372 + afu->psl_irq_name = NULL; 373 + } 374 + return rc; 381 375 } 382 376 383 377 void cxl_release_psl_irq(struct cxl_afu *afu) 384 378 { 385 379 cxl_unmap_irq(afu->psl_virq, afu); 386 380 cxl_release_one_irq(afu->adapter, afu->psl_hwirq); 381 + kfree(afu->psl_irq_name); 382 + } 383 + 384 + void afu_irq_name_free(struct cxl_context *ctx) 385 + { 386 + struct cxl_irq_name *irq_name, *tmp; 387 + 388 + list_for_each_entry_safe(irq_name, tmp, &ctx->irq_names, list) { 389 + kfree(irq_name->name); 390 + list_del(&irq_name->list); 391 + kfree(irq_name); 392 + } 387 393 } 388 394 389 395 int afu_register_irqs(struct cxl_context *ctx, u32 count) 390 396 { 391 397 irq_hw_number_t hwirq; 392 - int rc, r, i; 398 + int rc, r, i, j = 1; 399 + struct cxl_irq_name *irq_name; 393 400 394 401 if ((rc = cxl_alloc_irq_ranges(&ctx->irqs, ctx->afu->adapter, count))) 395 402 return rc; ··· 429 384 sizeof(*ctx->irq_bitmap), GFP_KERNEL); 430 385 if (!ctx->irq_bitmap) 431 386 return -ENOMEM; 387 + 388 + /* 389 + * Allocate names first. If any fail, bail out before allocating 390 + * actual hardware IRQs. 391 + */ 392 + INIT_LIST_HEAD(&ctx->irq_names); 393 + for (r = 1; r < CXL_IRQ_RANGES; r++) { 394 + for (i = 0; i < ctx->irqs.range[r]; hwirq++, i++) { 395 + irq_name = kmalloc(sizeof(struct cxl_irq_name), 396 + GFP_KERNEL); 397 + if (!irq_name) 398 + goto out; 399 + irq_name->name = kasprintf(GFP_KERNEL, "cxl-%s-pe%i-%i", 400 + dev_name(&ctx->afu->dev), 401 + ctx->pe, j); 402 + if (!irq_name->name) { 403 + kfree(irq_name); 404 + goto out; 405 + } 406 + /* Add to tail so next look get the correct order */ 407 + list_add_tail(&irq_name->list, &ctx->irq_names); 408 + j++; 409 + } 410 + } 411 + 412 + /* We've allocated all memory now, so let's do the irq allocations */ 413 + irq_name = list_first_entry(&ctx->irq_names, struct cxl_irq_name, list); 432 414 for (r = 1; r < CXL_IRQ_RANGES; r++) { 433 415 hwirq = ctx->irqs.offset[r]; 434 416 for (i = 0; i < ctx->irqs.range[r]; hwirq++, i++) { 435 417 cxl_map_irq(ctx->afu->adapter, hwirq, 436 - cxl_irq_afu, ctx); 418 + cxl_irq_afu, ctx, irq_name->name); 419 + irq_name = list_next_entry(irq_name, list); 437 420 } 438 421 } 439 422 440 423 return 0; 424 + 425 + out: 426 + afu_irq_name_free(ctx); 427 + return -ENOMEM; 441 428 } 442 429 443 430 void afu_release_irqs(struct cxl_context *ctx) ··· 487 410 } 488 411 } 489 412 413 + afu_irq_name_free(ctx); 490 414 cxl_release_irq_ranges(&ctx->irqs, ctx->afu->adapter); 491 415 }