Skip to content

Commit 7cb7c32

Browse files
committed
Merge tag 'irq_urgent_for_v6.8_rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull irq fixes from Borislav Petkov: - Fix GICv4.1 affinity update - Restore a quirk for ACPI-based GICv4 systems - Handle non-coherent GICv4 redistributors properly - Prevent spurious interrupts on Broadcom devices using GIC v3 architecture - Other minor fixes * tag 'irq_urgent_for_v6.8_rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: irqchip/gic-v3-its: Fix GICv4.1 VPE affinity update irqchip/gic-v3-its: Restore quirk probing for ACPI-based systems irqchip/gic-v3-its: Handle non-coherent GICv4 redistributors irqchip/qcom-mpm: Fix IS_ERR() vs NULL check in qcom_mpm_init() irqchip/loongson-eiointc: Use correct struct type in eiointc_domain_alloc() irqchip/irq-brcmstb-l2: Add write memory barrier before exit
2 parents 626721e + af9acbf commit 7cb7c32

File tree

4 files changed

+47
-26
lines changed

4 files changed

+47
-26
lines changed

drivers/irqchip/irq-brcmstb-l2.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
/*
33
* Generic Broadcom Set Top Box Level 2 Interrupt controller driver
44
*
5-
* Copyright (C) 2014-2017 Broadcom
5+
* Copyright (C) 2014-2024 Broadcom
66
*/
77

88
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -112,6 +112,9 @@ static void brcmstb_l2_intc_irq_handle(struct irq_desc *desc)
112112
generic_handle_domain_irq(b->domain, irq);
113113
} while (status);
114114
out:
115+
/* Don't ack parent before all device writes are done */
116+
wmb();
117+
115118
chained_irq_exit(chip, desc);
116119
}
117120

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

Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,11 @@ static bool require_its_list_vmovp(struct its_vm *vm, struct its_node *its)
207207
return (gic_rdists->has_rvpeid || vm->vlpi_count[its->list_nr]);
208208
}
209209

210+
static bool rdists_support_shareable(void)
211+
{
212+
return !(gic_rdists->flags & RDIST_FLAGS_FORCE_NON_SHAREABLE);
213+
}
214+
210215
static u16 get_its_list(struct its_vm *vm)
211216
{
212217
struct its_node *its;
@@ -2710,10 +2715,12 @@ static u64 inherit_vpe_l1_table_from_its(void)
27102715
break;
27112716
}
27122717
val |= FIELD_PREP(GICR_VPROPBASER_4_1_ADDR, addr >> 12);
2713-
val |= FIELD_PREP(GICR_VPROPBASER_SHAREABILITY_MASK,
2714-
FIELD_GET(GITS_BASER_SHAREABILITY_MASK, baser));
2715-
val |= FIELD_PREP(GICR_VPROPBASER_INNER_CACHEABILITY_MASK,
2716-
FIELD_GET(GITS_BASER_INNER_CACHEABILITY_MASK, baser));
2718+
if (rdists_support_shareable()) {
2719+
val |= FIELD_PREP(GICR_VPROPBASER_SHAREABILITY_MASK,
2720+
FIELD_GET(GITS_BASER_SHAREABILITY_MASK, baser));
2721+
val |= FIELD_PREP(GICR_VPROPBASER_INNER_CACHEABILITY_MASK,
2722+
FIELD_GET(GITS_BASER_INNER_CACHEABILITY_MASK, baser));
2723+
}
27172724
val |= FIELD_PREP(GICR_VPROPBASER_4_1_SIZE, GITS_BASER_NR_PAGES(baser) - 1);
27182725

27192726
return val;
@@ -2936,8 +2943,10 @@ static int allocate_vpe_l1_table(void)
29362943
WARN_ON(!IS_ALIGNED(pa, psz));
29372944

29382945
val |= FIELD_PREP(GICR_VPROPBASER_4_1_ADDR, pa >> 12);
2939-
val |= GICR_VPROPBASER_RaWb;
2940-
val |= GICR_VPROPBASER_InnerShareable;
2946+
if (rdists_support_shareable()) {
2947+
val |= GICR_VPROPBASER_RaWb;
2948+
val |= GICR_VPROPBASER_InnerShareable;
2949+
}
29412950
val |= GICR_VPROPBASER_4_1_Z;
29422951
val |= GICR_VPROPBASER_4_1_VALID;
29432952

@@ -3126,7 +3135,7 @@ static void its_cpu_init_lpis(void)
31263135
gicr_write_propbaser(val, rbase + GICR_PROPBASER);
31273136
tmp = gicr_read_propbaser(rbase + GICR_PROPBASER);
31283137

3129-
if (gic_rdists->flags & RDIST_FLAGS_FORCE_NON_SHAREABLE)
3138+
if (!rdists_support_shareable())
31303139
tmp &= ~GICR_PROPBASER_SHAREABILITY_MASK;
31313140

31323141
if ((tmp ^ val) & GICR_PROPBASER_SHAREABILITY_MASK) {
@@ -3153,7 +3162,7 @@ static void its_cpu_init_lpis(void)
31533162
gicr_write_pendbaser(val, rbase + GICR_PENDBASER);
31543163
tmp = gicr_read_pendbaser(rbase + GICR_PENDBASER);
31553164

3156-
if (gic_rdists->flags & RDIST_FLAGS_FORCE_NON_SHAREABLE)
3165+
if (!rdists_support_shareable())
31573166
tmp &= ~GICR_PENDBASER_SHAREABILITY_MASK;
31583167

31593168
if (!(tmp & GICR_PENDBASER_SHAREABILITY_MASK)) {
@@ -3817,8 +3826,9 @@ static int its_vpe_set_affinity(struct irq_data *d,
38173826
bool force)
38183827
{
38193828
struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
3820-
int from, cpu = cpumask_first(mask_val);
3829+
struct cpumask common, *table_mask;
38213830
unsigned long flags;
3831+
int from, cpu;
38223832

38233833
/*
38243834
* Changing affinity is mega expensive, so let's be as lazy as
@@ -3834,19 +3844,22 @@ static int its_vpe_set_affinity(struct irq_data *d,
38343844
* taken on any vLPI handling path that evaluates vpe->col_idx.
38353845
*/
38363846
from = vpe_to_cpuid_lock(vpe, &flags);
3837-
if (from == cpu)
3838-
goto out;
3839-
3840-
vpe->col_idx = cpu;
3847+
table_mask = gic_data_rdist_cpu(from)->vpe_table_mask;
38413848

38423849
/*
3843-
* GICv4.1 allows us to skip VMOVP if moving to a cpu whose RD
3844-
* is sharing its VPE table with the current one.
3850+
* If we are offered another CPU in the same GICv4.1 ITS
3851+
* affinity, pick this one. Otherwise, any CPU will do.
38453852
*/
3846-
if (gic_data_rdist_cpu(cpu)->vpe_table_mask &&
3847-
cpumask_test_cpu(from, gic_data_rdist_cpu(cpu)->vpe_table_mask))
3853+
if (table_mask && cpumask_and(&common, mask_val, table_mask))
3854+
cpu = cpumask_test_cpu(from, &common) ? from : cpumask_first(&common);
3855+
else
3856+
cpu = cpumask_first(mask_val);
3857+
3858+
if (from == cpu)
38483859
goto out;
38493860

3861+
vpe->col_idx = cpu;
3862+
38503863
its_send_vmovp(vpe);
38513864
its_vpe_db_proxy_move(vpe, from, cpu);
38523865

@@ -3880,14 +3893,18 @@ static void its_vpe_schedule(struct its_vpe *vpe)
38803893
val = virt_to_phys(page_address(vpe->its_vm->vprop_page)) &
38813894
GENMASK_ULL(51, 12);
38823895
val |= (LPI_NRBITS - 1) & GICR_VPROPBASER_IDBITS_MASK;
3883-
val |= GICR_VPROPBASER_RaWb;
3884-
val |= GICR_VPROPBASER_InnerShareable;
3896+
if (rdists_support_shareable()) {
3897+
val |= GICR_VPROPBASER_RaWb;
3898+
val |= GICR_VPROPBASER_InnerShareable;
3899+
}
38853900
gicr_write_vpropbaser(val, vlpi_base + GICR_VPROPBASER);
38863901

38873902
val = virt_to_phys(page_address(vpe->vpt_page)) &
38883903
GENMASK_ULL(51, 16);
3889-
val |= GICR_VPENDBASER_RaWaWb;
3890-
val |= GICR_VPENDBASER_InnerShareable;
3904+
if (rdists_support_shareable()) {
3905+
val |= GICR_VPENDBASER_RaWaWb;
3906+
val |= GICR_VPENDBASER_InnerShareable;
3907+
}
38913908
/*
38923909
* There is no good way of finding out if the pending table is
38933910
* empty as we can race against the doorbell interrupt very
@@ -5078,6 +5095,8 @@ static int __init its_probe_one(struct its_node *its)
50785095
u32 ctlr;
50795096
int err;
50805097

5098+
its_enable_quirks(its);
5099+
50815100
if (is_v4(its)) {
50825101
if (!(its->typer & GITS_TYPER_VMOVP)) {
50835102
err = its_compute_its_list_map(its);
@@ -5429,7 +5448,6 @@ static int __init its_of_probe(struct device_node *node)
54295448
if (!its)
54305449
return -ENOMEM;
54315450

5432-
its_enable_quirks(its);
54335451
err = its_probe_one(its);
54345452
if (err) {
54355453
its_node_destroy(its);

drivers/irqchip/irq-loongson-eiointc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ static int eiointc_domain_alloc(struct irq_domain *domain, unsigned int virq,
241241
int ret;
242242
unsigned int i, type;
243243
unsigned long hwirq = 0;
244-
struct eiointc *priv = domain->host_data;
244+
struct eiointc_priv *priv = domain->host_data;
245245

246246
ret = irq_domain_translate_onecell(domain, arg, &hwirq, &type);
247247
if (ret)

drivers/irqchip/irq-qcom-mpm.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -389,8 +389,8 @@ static int qcom_mpm_init(struct device_node *np, struct device_node *parent)
389389
/* Don't use devm_ioremap_resource, as we're accessing a shared region. */
390390
priv->base = devm_ioremap(dev, res.start, resource_size(&res));
391391
of_node_put(msgram_np);
392-
if (IS_ERR(priv->base))
393-
return PTR_ERR(priv->base);
392+
if (!priv->base)
393+
return -ENOMEM;
394394
} else {
395395
/* Otherwise, fall back to simple MMIO. */
396396
priv->base = devm_platform_ioremap_resource(pdev, 0);

0 commit comments

Comments
 (0)