irqchip/gic-v3: Add redistributor iterator

In order to discover the VLPI properties, we need to iterate over
the redistributor regions. As we already have code that does this,
let's factor it out and make it slightly more generic.

Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

+47 -22
+47 -22
drivers/irqchip/irq-gic-v3.c
··· 421 421 gic_write_irouter(affinity, base + GICD_IROUTER + i * 8); 422 422 } 423 423 424 - static int gic_populate_rdist(void) 424 + static int gic_iterate_rdists(int (*fn)(struct redist_region *, void __iomem *)) 425 425 { 426 - unsigned long mpidr = cpu_logical_map(smp_processor_id()); 427 - u64 typer; 428 - u32 aff; 426 + int ret = -ENODEV; 429 427 int i; 430 - 431 - /* 432 - * Convert affinity to a 32bit value that can be matched to 433 - * GICR_TYPER bits [63:32]. 434 - */ 435 - aff = (MPIDR_AFFINITY_LEVEL(mpidr, 3) << 24 | 436 - MPIDR_AFFINITY_LEVEL(mpidr, 2) << 16 | 437 - MPIDR_AFFINITY_LEVEL(mpidr, 1) << 8 | 438 - MPIDR_AFFINITY_LEVEL(mpidr, 0)); 439 428 440 429 for (i = 0; i < gic_data.nr_redist_regions; i++) { 441 430 void __iomem *ptr = gic_data.redist_regions[i].redist_base; 431 + u64 typer; 442 432 u32 reg; 443 433 444 434 reg = readl_relaxed(ptr + GICR_PIDR2) & GIC_PIDR2_ARCH_MASK; ··· 440 450 441 451 do { 442 452 typer = gic_read_typer(ptr + GICR_TYPER); 443 - if ((typer >> 32) == aff) { 444 - u64 offset = ptr - gic_data.redist_regions[i].redist_base; 445 - gic_data_rdist_rd_base() = ptr; 446 - gic_data_rdist()->phys_base = gic_data.redist_regions[i].phys_base + offset; 447 - pr_info("CPU%d: found redistributor %lx region %d:%pa\n", 448 - smp_processor_id(), mpidr, i, 449 - &gic_data_rdist()->phys_base); 453 + ret = fn(gic_data.redist_regions + i, ptr); 454 + if (!ret) 450 455 return 0; 451 - } 452 456 453 457 if (gic_data.redist_regions[i].single_redist) 454 458 break; ··· 457 473 } while (!(typer & GICR_TYPER_LAST)); 458 474 } 459 475 476 + return ret ? -ENODEV : 0; 477 + } 478 + 479 + static int __gic_populate_rdist(struct redist_region *region, void __iomem *ptr) 480 + { 481 + unsigned long mpidr = cpu_logical_map(smp_processor_id()); 482 + u64 typer; 483 + u32 aff; 484 + 485 + /* 486 + * Convert affinity to a 32bit value that can be matched to 487 + * GICR_TYPER bits [63:32]. 488 + */ 489 + aff = (MPIDR_AFFINITY_LEVEL(mpidr, 3) << 24 | 490 + MPIDR_AFFINITY_LEVEL(mpidr, 2) << 16 | 491 + MPIDR_AFFINITY_LEVEL(mpidr, 1) << 8 | 492 + MPIDR_AFFINITY_LEVEL(mpidr, 0)); 493 + 494 + typer = gic_read_typer(ptr + GICR_TYPER); 495 + if ((typer >> 32) == aff) { 496 + u64 offset = ptr - region->redist_base; 497 + gic_data_rdist_rd_base() = ptr; 498 + gic_data_rdist()->phys_base = region->phys_base + offset; 499 + 500 + pr_info("CPU%d: found redistributor %lx region %d:%pa\n", 501 + smp_processor_id(), mpidr, 502 + (int)(region - gic_data.redist_regions), 503 + &gic_data_rdist()->phys_base); 504 + return 0; 505 + } 506 + 507 + /* Try next one */ 508 + return 1; 509 + } 510 + 511 + static int gic_populate_rdist(void) 512 + { 513 + if (gic_iterate_rdists(__gic_populate_rdist) == 0) 514 + return 0; 515 + 460 516 /* We couldn't even deal with ourselves... */ 461 517 WARN(true, "CPU%d: mpidr %lx has no re-distributor!\n", 462 - smp_processor_id(), mpidr); 518 + smp_processor_id(), 519 + (unsigned long)cpu_logical_map(smp_processor_id())); 463 520 return -ENODEV; 464 521 } 465 522