Skip to content

Commit 2f86e45

Browse files
committed
Merge tag 'irqchip-fixes-5.6-1' of git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms into irq/urgent
Pull irqchip fixes for 5.6, take #1 from Marc Zyngier: - Guarantee allocation of L2 vPE table for GICv4.1 - Fix GICv4.1 VPROPBASER programming - Numerous GICv4.1 tidy ups - Fix disabled GICv3 redistributor provisioning with ACPI - KConfig cleanup for C-SKY
2 parents f9f21ce + 5186a6c commit 2f86e45

File tree

6 files changed

+120
-35
lines changed

6 files changed

+120
-35
lines changed

arch/arm/include/asm/arch_gicv3.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -326,16 +326,16 @@ static inline u64 __gic_readq_nonatomic(const volatile void __iomem *addr)
326326
#define gits_write_cwriter(v, c) __gic_writeq_nonatomic(v, c)
327327

328328
/*
329-
* GITS_VPROPBASER - hi and lo bits may be accessed independently.
329+
* GICR_VPROPBASER - hi and lo bits may be accessed independently.
330330
*/
331-
#define gits_read_vpropbaser(c) __gic_readq_nonatomic(c)
332-
#define gits_write_vpropbaser(v, c) __gic_writeq_nonatomic(v, c)
331+
#define gicr_read_vpropbaser(c) __gic_readq_nonatomic(c)
332+
#define gicr_write_vpropbaser(v, c) __gic_writeq_nonatomic(v, c)
333333

334334
/*
335-
* GITS_VPENDBASER - the Valid bit must be cleared before changing
335+
* GICR_VPENDBASER - the Valid bit must be cleared before changing
336336
* anything else.
337337
*/
338-
static inline void gits_write_vpendbaser(u64 val, void __iomem *addr)
338+
static inline void gicr_write_vpendbaser(u64 val, void __iomem *addr)
339339
{
340340
u32 tmp;
341341

@@ -352,7 +352,7 @@ static inline void gits_write_vpendbaser(u64 val, void __iomem *addr)
352352
__gic_writeq_nonatomic(val, addr);
353353
}
354354

355-
#define gits_read_vpendbaser(c) __gic_readq_nonatomic(c)
355+
#define gicr_read_vpendbaser(c) __gic_readq_nonatomic(c)
356356

357357
static inline bool gic_prio_masking_enabled(void)
358358
{

arch/arm64/include/asm/arch_gicv3.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,11 +140,11 @@ static inline u32 gic_read_rpr(void)
140140
#define gicr_write_pendbaser(v, c) writeq_relaxed(v, c)
141141
#define gicr_read_pendbaser(c) readq_relaxed(c)
142142

143-
#define gits_write_vpropbaser(v, c) writeq_relaxed(v, c)
144-
#define gits_read_vpropbaser(c) readq_relaxed(c)
143+
#define gicr_write_vpropbaser(v, c) writeq_relaxed(v, c)
144+
#define gicr_read_vpropbaser(c) readq_relaxed(c)
145145

146-
#define gits_write_vpendbaser(v, c) writeq_relaxed(v, c)
147-
#define gits_read_vpendbaser(c) readq_relaxed(c)
146+
#define gicr_write_vpendbaser(v, c) writeq_relaxed(v, c)
147+
#define gicr_read_vpendbaser(c) readq_relaxed(c)
148148

149149
static inline bool gic_prio_masking_enabled(void)
150150
{

drivers/irqchip/Kconfig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -438,15 +438,15 @@ config CSKY_MPINTC
438438
help
439439
Say yes here to enable C-SKY SMP interrupt controller driver used
440440
for C-SKY SMP system.
441-
In fact it's not mmio map in hw and it use ld/st to visit the
441+
In fact it's not mmio map in hardware and it uses ld/st to visit the
442442
controller's register inside CPU.
443443

444444
config CSKY_APB_INTC
445445
bool "C-SKY APB Interrupt Controller"
446446
depends on CSKY
447447
help
448448
Say yes here to enable C-SKY APB interrupt controller driver used
449-
by C-SKY single core SOC system. It use mmio map apb-bus to visit
449+
by C-SKY single core SOC system. It uses mmio map apb-bus to visit
450450
the controller's register.
451451

452452
config IMX_IRQSTEER

drivers/irqchip/irq-gic-v3-its.c

Lines changed: 100 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -661,7 +661,7 @@ static struct its_collection *its_build_invall_cmd(struct its_node *its,
661661
struct its_cmd_desc *desc)
662662
{
663663
its_encode_cmd(cmd, GITS_CMD_INVALL);
664-
its_encode_collection(cmd, desc->its_mapc_cmd.col->col_id);
664+
its_encode_collection(cmd, desc->its_invall_cmd.col->col_id);
665665

666666
its_fixup_cmd(cmd);
667667

@@ -2376,6 +2376,8 @@ static u64 inherit_vpe_l1_table_from_its(void)
23762376
continue;
23772377

23782378
/* We have a winner! */
2379+
gic_data_rdist()->vpe_l1_base = its->tables[2].base;
2380+
23792381
val = GICR_VPROPBASER_4_1_VALID;
23802382
if (baser & GITS_BASER_INDIRECT)
23812383
val |= GICR_VPROPBASER_4_1_INDIRECT;
@@ -2413,14 +2415,12 @@ static u64 inherit_vpe_l1_table_from_rd(cpumask_t **mask)
24132415

24142416
for_each_possible_cpu(cpu) {
24152417
void __iomem *base = gic_data_rdist_cpu(cpu)->rd_base;
2416-
u32 tmp;
24172418

24182419
if (!base || cpu == smp_processor_id())
24192420
continue;
24202421

24212422
val = gic_read_typer(base + GICR_TYPER);
2422-
tmp = compute_common_aff(val);
2423-
if (tmp != aff)
2423+
if (aff != compute_common_aff(val))
24242424
continue;
24252425

24262426
/*
@@ -2429,9 +2429,10 @@ static u64 inherit_vpe_l1_table_from_rd(cpumask_t **mask)
24292429
* ours wrt CommonLPIAff. Let's use its own VPROPBASER.
24302430
* Make sure we don't write the Z bit in that case.
24312431
*/
2432-
val = gits_read_vpropbaser(base + SZ_128K + GICR_VPROPBASER);
2432+
val = gicr_read_vpropbaser(base + SZ_128K + GICR_VPROPBASER);
24332433
val &= ~GICR_VPROPBASER_4_1_Z;
24342434

2435+
gic_data_rdist()->vpe_l1_base = gic_data_rdist_cpu(cpu)->vpe_l1_base;
24352436
*mask = gic_data_rdist_cpu(cpu)->vpe_table_mask;
24362437

24372438
return val;
@@ -2440,6 +2441,72 @@ static u64 inherit_vpe_l1_table_from_rd(cpumask_t **mask)
24402441
return 0;
24412442
}
24422443

2444+
static bool allocate_vpe_l2_table(int cpu, u32 id)
2445+
{
2446+
void __iomem *base = gic_data_rdist_cpu(cpu)->rd_base;
2447+
u64 val, gpsz, npg;
2448+
unsigned int psz, esz, idx;
2449+
struct page *page;
2450+
__le64 *table;
2451+
2452+
if (!gic_rdists->has_rvpeid)
2453+
return true;
2454+
2455+
val = gicr_read_vpropbaser(base + SZ_128K + GICR_VPROPBASER);
2456+
2457+
esz = FIELD_GET(GICR_VPROPBASER_4_1_ENTRY_SIZE, val) + 1;
2458+
gpsz = FIELD_GET(GICR_VPROPBASER_4_1_PAGE_SIZE, val);
2459+
npg = FIELD_GET(GICR_VPROPBASER_4_1_SIZE, val) + 1;
2460+
2461+
switch (gpsz) {
2462+
default:
2463+
WARN_ON(1);
2464+
/* fall through */
2465+
case GIC_PAGE_SIZE_4K:
2466+
psz = SZ_4K;
2467+
break;
2468+
case GIC_PAGE_SIZE_16K:
2469+
psz = SZ_16K;
2470+
break;
2471+
case GIC_PAGE_SIZE_64K:
2472+
psz = SZ_64K;
2473+
break;
2474+
}
2475+
2476+
/* Don't allow vpe_id that exceeds single, flat table limit */
2477+
if (!(val & GICR_VPROPBASER_4_1_INDIRECT))
2478+
return (id < (npg * psz / (esz * SZ_8)));
2479+
2480+
/* Compute 1st level table index & check if that exceeds table limit */
2481+
idx = id >> ilog2(psz / (esz * SZ_8));
2482+
if (idx >= (npg * psz / GITS_LVL1_ENTRY_SIZE))
2483+
return false;
2484+
2485+
table = gic_data_rdist_cpu(cpu)->vpe_l1_base;
2486+
2487+
/* Allocate memory for 2nd level table */
2488+
if (!table[idx]) {
2489+
page = alloc_pages(GFP_KERNEL | __GFP_ZERO, get_order(psz));
2490+
if (!page)
2491+
return false;
2492+
2493+
/* Flush Lvl2 table to PoC if hw doesn't support coherency */
2494+
if (!(val & GICR_VPROPBASER_SHAREABILITY_MASK))
2495+
gic_flush_dcache_to_poc(page_address(page), psz);
2496+
2497+
table[idx] = cpu_to_le64(page_to_phys(page) | GITS_BASER_VALID);
2498+
2499+
/* Flush Lvl1 entry to PoC if hw doesn't support coherency */
2500+
if (!(val & GICR_VPROPBASER_SHAREABILITY_MASK))
2501+
gic_flush_dcache_to_poc(table + idx, GITS_LVL1_ENTRY_SIZE);
2502+
2503+
/* Ensure updated table contents are visible to RD hardware */
2504+
dsb(sy);
2505+
}
2506+
2507+
return true;
2508+
}
2509+
24432510
static int allocate_vpe_l1_table(void)
24442511
{
24452512
void __iomem *vlpi_base = gic_data_rdist_vlpi_base();
@@ -2457,8 +2524,8 @@ static int allocate_vpe_l1_table(void)
24572524
* effect of making sure no doorbell will be generated and we can
24582525
* then safely clear VPROPBASER.Valid.
24592526
*/
2460-
if (gits_read_vpendbaser(vlpi_base + GICR_VPENDBASER) & GICR_VPENDBASER_Valid)
2461-
gits_write_vpendbaser(GICR_VPENDBASER_PendingLast,
2527+
if (gicr_read_vpendbaser(vlpi_base + GICR_VPENDBASER) & GICR_VPENDBASER_Valid)
2528+
gicr_write_vpendbaser(GICR_VPENDBASER_PendingLast,
24622529
vlpi_base + GICR_VPENDBASER);
24632530

24642531
/*
@@ -2481,8 +2548,8 @@ static int allocate_vpe_l1_table(void)
24812548

24822549
/* First probe the page size */
24832550
val = FIELD_PREP(GICR_VPROPBASER_4_1_PAGE_SIZE, GIC_PAGE_SIZE_64K);
2484-
gits_write_vpropbaser(val, vlpi_base + GICR_VPROPBASER);
2485-
val = gits_read_vpropbaser(vlpi_base + GICR_VPROPBASER);
2551+
gicr_write_vpropbaser(val, vlpi_base + GICR_VPROPBASER);
2552+
val = gicr_read_vpropbaser(vlpi_base + GICR_VPROPBASER);
24862553
gpsz = FIELD_GET(GICR_VPROPBASER_4_1_PAGE_SIZE, val);
24872554
esz = FIELD_GET(GICR_VPROPBASER_4_1_ENTRY_SIZE, val);
24882555

@@ -2531,7 +2598,7 @@ static int allocate_vpe_l1_table(void)
25312598
npg = 1;
25322599
}
25332600

2534-
val |= FIELD_PREP(GICR_VPROPBASER_4_1_SIZE, npg);
2601+
val |= FIELD_PREP(GICR_VPROPBASER_4_1_SIZE, npg - 1);
25352602

25362603
/* Right, that's the number of CPU pages we need for L1 */
25372604
np = DIV_ROUND_UP(npg * psz, PAGE_SIZE);
@@ -2542,7 +2609,7 @@ static int allocate_vpe_l1_table(void)
25422609
if (!page)
25432610
return -ENOMEM;
25442611

2545-
gic_data_rdist()->vpe_l1_page = page;
2612+
gic_data_rdist()->vpe_l1_base = page_address(page);
25462613
pa = virt_to_phys(page_address(page));
25472614
WARN_ON(!IS_ALIGNED(pa, psz));
25482615

@@ -2553,7 +2620,7 @@ static int allocate_vpe_l1_table(void)
25532620
val |= GICR_VPROPBASER_4_1_VALID;
25542621

25552622
out:
2556-
gits_write_vpropbaser(val, vlpi_base + GICR_VPROPBASER);
2623+
gicr_write_vpropbaser(val, vlpi_base + GICR_VPROPBASER);
25572624
cpumask_set_cpu(smp_processor_id(), gic_data_rdist()->vpe_table_mask);
25582625

25592626
pr_debug("CPU%d: VPROPBASER = %llx %*pbl\n",
@@ -2660,14 +2727,14 @@ static u64 its_clear_vpend_valid(void __iomem *vlpi_base, u64 clr, u64 set)
26602727
bool clean;
26612728
u64 val;
26622729

2663-
val = gits_read_vpendbaser(vlpi_base + GICR_VPENDBASER);
2730+
val = gicr_read_vpendbaser(vlpi_base + GICR_VPENDBASER);
26642731
val &= ~GICR_VPENDBASER_Valid;
26652732
val &= ~clr;
26662733
val |= set;
2667-
gits_write_vpendbaser(val, vlpi_base + GICR_VPENDBASER);
2734+
gicr_write_vpendbaser(val, vlpi_base + GICR_VPENDBASER);
26682735

26692736
do {
2670-
val = gits_read_vpendbaser(vlpi_base + GICR_VPENDBASER);
2737+
val = gicr_read_vpendbaser(vlpi_base + GICR_VPENDBASER);
26712738
clean = !(val & GICR_VPENDBASER_Dirty);
26722739
if (!clean) {
26732740
count--;
@@ -2782,15 +2849,14 @@ static void its_cpu_init_lpis(void)
27822849
val = (LPI_NRBITS - 1) & GICR_VPROPBASER_IDBITS_MASK;
27832850
pr_debug("GICv4: CPU%d: Init IDbits to 0x%llx for GICR_VPROPBASER\n",
27842851
smp_processor_id(), val);
2785-
gits_write_vpropbaser(val, vlpi_base + GICR_VPROPBASER);
2852+
gicr_write_vpropbaser(val, vlpi_base + GICR_VPROPBASER);
27862853

27872854
/*
27882855
* Also clear Valid bit of GICR_VPENDBASER, in case some
27892856
* ancient programming gets left in and has possibility of
27902857
* corrupting memory.
27912858
*/
27922859
val = its_clear_vpend_valid(vlpi_base, 0, 0);
2793-
WARN_ON(val & GICR_VPENDBASER_Dirty);
27942860
}
27952861

27962862
if (allocate_vpe_l1_table()) {
@@ -2954,6 +3020,7 @@ static bool its_alloc_device_table(struct its_node *its, u32 dev_id)
29543020
static bool its_alloc_vpe_table(u32 vpe_id)
29553021
{
29563022
struct its_node *its;
3023+
int cpu;
29573024

29583025
/*
29593026
* Make sure the L2 tables are allocated on *all* v4 ITSs. We
@@ -2976,6 +3043,19 @@ static bool its_alloc_vpe_table(u32 vpe_id)
29763043
return false;
29773044
}
29783045

3046+
/* Non v4.1? No need to iterate RDs and go back early. */
3047+
if (!gic_rdists->has_rvpeid)
3048+
return true;
3049+
3050+
/*
3051+
* Make sure the L2 tables are allocated for all copies of
3052+
* the L1 table on *all* v4.1 RDs.
3053+
*/
3054+
for_each_possible_cpu(cpu) {
3055+
if (!allocate_vpe_l2_table(cpu, vpe_id))
3056+
return false;
3057+
}
3058+
29793059
return true;
29803060
}
29813061

@@ -3443,7 +3523,7 @@ static void its_vpe_schedule(struct its_vpe *vpe)
34433523
val |= (LPI_NRBITS - 1) & GICR_VPROPBASER_IDBITS_MASK;
34443524
val |= GICR_VPROPBASER_RaWb;
34453525
val |= GICR_VPROPBASER_InnerShareable;
3446-
gits_write_vpropbaser(val, vlpi_base + GICR_VPROPBASER);
3526+
gicr_write_vpropbaser(val, vlpi_base + GICR_VPROPBASER);
34473527

34483528
val = virt_to_phys(page_address(vpe->vpt_page)) &
34493529
GENMASK_ULL(51, 16);
@@ -3461,7 +3541,7 @@ static void its_vpe_schedule(struct its_vpe *vpe)
34613541
val |= GICR_VPENDBASER_PendingLast;
34623542
val |= vpe->idai ? GICR_VPENDBASER_IDAI : 0;
34633543
val |= GICR_VPENDBASER_Valid;
3464-
gits_write_vpendbaser(val, vlpi_base + GICR_VPENDBASER);
3544+
gicr_write_vpendbaser(val, vlpi_base + GICR_VPENDBASER);
34653545
}
34663546

34673547
static void its_vpe_deschedule(struct its_vpe *vpe)
@@ -3661,7 +3741,7 @@ static void its_vpe_4_1_schedule(struct its_vpe *vpe,
36613741
val |= info->g1en ? GICR_VPENDBASER_4_1_VGRP1EN : 0;
36623742
val |= FIELD_PREP(GICR_VPENDBASER_4_1_VPEID, vpe->vpe_id);
36633743

3664-
gits_write_vpendbaser(val, vlpi_base + GICR_VPENDBASER);
3744+
gicr_write_vpendbaser(val, vlpi_base + GICR_VPENDBASER);
36653745
}
36663746

36673747
static void its_vpe_4_1_deschedule(struct its_vpe *vpe,

drivers/irqchip/irq-gic-v3.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1839,6 +1839,7 @@ static struct
18391839
struct redist_region *redist_regs;
18401840
u32 nr_redist_regions;
18411841
bool single_redist;
1842+
int enabled_rdists;
18421843
u32 maint_irq;
18431844
int maint_irq_mode;
18441845
phys_addr_t vcpu_base;
@@ -1933,8 +1934,10 @@ static int __init gic_acpi_match_gicc(union acpi_subtable_headers *header,
19331934
* If GICC is enabled and has valid gicr base address, then it means
19341935
* GICR base is presented via GICC
19351936
*/
1936-
if ((gicc->flags & ACPI_MADT_ENABLED) && gicc->gicr_base_address)
1937+
if ((gicc->flags & ACPI_MADT_ENABLED) && gicc->gicr_base_address) {
1938+
acpi_data.enabled_rdists++;
19371939
return 0;
1940+
}
19381941

19391942
/*
19401943
* It's perfectly valid firmware can pass disabled GICC entry, driver
@@ -1964,8 +1967,10 @@ static int __init gic_acpi_count_gicr_regions(void)
19641967

19651968
count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT,
19661969
gic_acpi_match_gicc, 0);
1967-
if (count > 0)
1970+
if (count > 0) {
19681971
acpi_data.single_redist = true;
1972+
count = acpi_data.enabled_rdists;
1973+
}
19691974

19701975
return count;
19711976
}

include/linux/irqchip/arm-gic-v3.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -652,10 +652,10 @@ struct rdists {
652652
struct {
653653
void __iomem *rd_base;
654654
struct page *pend_page;
655-
struct page *vpe_l1_page;
656655
phys_addr_t phys_base;
657656
bool lpi_enabled;
658657
cpumask_t *vpe_table_mask;
658+
void *vpe_l1_base;
659659
} __percpu *rdist;
660660
phys_addr_t prop_table_pa;
661661
void *prop_table_va;

0 commit comments

Comments
 (0)