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

+4 -1
drivers/irqchip/irq-brcmstb-l2.c
··· 2 2 /* 3 3 * Generic Broadcom Set Top Box Level 2 Interrupt controller driver 4 4 * 5 - * Copyright (C) 2014-2017 Broadcom 5 + * Copyright (C) 2014-2024 Broadcom 6 6 */ 7 7 8 8 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ··· 112 112 generic_handle_domain_irq(b->domain, irq); 113 113 } while (status); 114 114 out: 115 + /* Don't ack parent before all device writes are done */ 116 + wmb(); 117 + 115 118 chained_irq_exit(chip, desc); 116 119 } 117 120
+40 -22
drivers/irqchip/irq-gic-v3-its.c
··· 207 207 return (gic_rdists->has_rvpeid || vm->vlpi_count[its->list_nr]); 208 208 } 209 209 210 + static bool rdists_support_shareable(void) 211 + { 212 + return !(gic_rdists->flags & RDIST_FLAGS_FORCE_NON_SHAREABLE); 213 + } 214 + 210 215 static u16 get_its_list(struct its_vm *vm) 211 216 { 212 217 struct its_node *its; ··· 2715 2710 break; 2716 2711 } 2717 2712 val |= FIELD_PREP(GICR_VPROPBASER_4_1_ADDR, addr >> 12); 2718 - val |= FIELD_PREP(GICR_VPROPBASER_SHAREABILITY_MASK, 2719 - FIELD_GET(GITS_BASER_SHAREABILITY_MASK, baser)); 2720 - val |= FIELD_PREP(GICR_VPROPBASER_INNER_CACHEABILITY_MASK, 2721 - FIELD_GET(GITS_BASER_INNER_CACHEABILITY_MASK, baser)); 2713 + if (rdists_support_shareable()) { 2714 + val |= FIELD_PREP(GICR_VPROPBASER_SHAREABILITY_MASK, 2715 + FIELD_GET(GITS_BASER_SHAREABILITY_MASK, baser)); 2716 + val |= FIELD_PREP(GICR_VPROPBASER_INNER_CACHEABILITY_MASK, 2717 + FIELD_GET(GITS_BASER_INNER_CACHEABILITY_MASK, baser)); 2718 + } 2722 2719 val |= FIELD_PREP(GICR_VPROPBASER_4_1_SIZE, GITS_BASER_NR_PAGES(baser) - 1); 2723 2720 2724 2721 return val; ··· 2943 2936 WARN_ON(!IS_ALIGNED(pa, psz)); 2944 2937 2945 2938 val |= FIELD_PREP(GICR_VPROPBASER_4_1_ADDR, pa >> 12); 2946 - val |= GICR_VPROPBASER_RaWb; 2947 - val |= GICR_VPROPBASER_InnerShareable; 2939 + if (rdists_support_shareable()) { 2940 + val |= GICR_VPROPBASER_RaWb; 2941 + val |= GICR_VPROPBASER_InnerShareable; 2942 + } 2948 2943 val |= GICR_VPROPBASER_4_1_Z; 2949 2944 val |= GICR_VPROPBASER_4_1_VALID; 2950 2945 ··· 3135 3126 gicr_write_propbaser(val, rbase + GICR_PROPBASER); 3136 3127 tmp = gicr_read_propbaser(rbase + GICR_PROPBASER); 3137 3128 3138 - if (gic_rdists->flags & RDIST_FLAGS_FORCE_NON_SHAREABLE) 3129 + if (!rdists_support_shareable()) 3139 3130 tmp &= ~GICR_PROPBASER_SHAREABILITY_MASK; 3140 3131 3141 3132 if ((tmp ^ val) & GICR_PROPBASER_SHAREABILITY_MASK) { ··· 3162 3153 gicr_write_pendbaser(val, rbase + GICR_PENDBASER); 3163 3154 tmp = gicr_read_pendbaser(rbase + GICR_PENDBASER); 3164 3155 3165 - if (gic_rdists->flags & RDIST_FLAGS_FORCE_NON_SHAREABLE) 3156 + if (!rdists_support_shareable()) 3166 3157 tmp &= ~GICR_PENDBASER_SHAREABILITY_MASK; 3167 3158 3168 3159 if (!(tmp & GICR_PENDBASER_SHAREABILITY_MASK)) { ··· 3826 3817 bool force) 3827 3818 { 3828 3819 struct its_vpe *vpe = irq_data_get_irq_chip_data(d); 3829 - int from, cpu = cpumask_first(mask_val); 3820 + struct cpumask common, *table_mask; 3830 3821 unsigned long flags; 3822 + int from, cpu; 3831 3823 3832 3824 /* 3833 3825 * Changing affinity is mega expensive, so let's be as lazy as ··· 3844 3834 * taken on any vLPI handling path that evaluates vpe->col_idx. 3845 3835 */ 3846 3836 from = vpe_to_cpuid_lock(vpe, &flags); 3837 + table_mask = gic_data_rdist_cpu(from)->vpe_table_mask; 3838 + 3839 + /* 3840 + * If we are offered another CPU in the same GICv4.1 ITS 3841 + * affinity, pick this one. Otherwise, any CPU will do. 3842 + */ 3843 + if (table_mask && cpumask_and(&common, mask_val, table_mask)) 3844 + cpu = cpumask_test_cpu(from, &common) ? from : cpumask_first(&common); 3845 + else 3846 + cpu = cpumask_first(mask_val); 3847 + 3847 3848 if (from == cpu) 3848 3849 goto out; 3849 3850 3850 3851 vpe->col_idx = cpu; 3851 - 3852 - /* 3853 - * GICv4.1 allows us to skip VMOVP if moving to a cpu whose RD 3854 - * is sharing its VPE table with the current one. 3855 - */ 3856 - if (gic_data_rdist_cpu(cpu)->vpe_table_mask && 3857 - cpumask_test_cpu(from, gic_data_rdist_cpu(cpu)->vpe_table_mask)) 3858 - goto out; 3859 3852 3860 3853 its_send_vmovp(vpe); 3861 3854 its_vpe_db_proxy_move(vpe, from, cpu); ··· 3893 3880 val = virt_to_phys(page_address(vpe->its_vm->vprop_page)) & 3894 3881 GENMASK_ULL(51, 12); 3895 3882 val |= (LPI_NRBITS - 1) & GICR_VPROPBASER_IDBITS_MASK; 3896 - val |= GICR_VPROPBASER_RaWb; 3897 - val |= GICR_VPROPBASER_InnerShareable; 3883 + if (rdists_support_shareable()) { 3884 + val |= GICR_VPROPBASER_RaWb; 3885 + val |= GICR_VPROPBASER_InnerShareable; 3886 + } 3898 3887 gicr_write_vpropbaser(val, vlpi_base + GICR_VPROPBASER); 3899 3888 3900 3889 val = virt_to_phys(page_address(vpe->vpt_page)) & 3901 3890 GENMASK_ULL(51, 16); 3902 - val |= GICR_VPENDBASER_RaWaWb; 3903 - val |= GICR_VPENDBASER_InnerShareable; 3891 + if (rdists_support_shareable()) { 3892 + val |= GICR_VPENDBASER_RaWaWb; 3893 + val |= GICR_VPENDBASER_InnerShareable; 3894 + } 3904 3895 /* 3905 3896 * There is no good way of finding out if the pending table is 3906 3897 * empty as we can race against the doorbell interrupt very ··· 5095 5078 u32 ctlr; 5096 5079 int err; 5097 5080 5081 + its_enable_quirks(its); 5082 + 5098 5083 if (is_v4(its)) { 5099 5084 if (!(its->typer & GITS_TYPER_VMOVP)) { 5100 5085 err = its_compute_its_list_map(its); ··· 5448 5429 if (!its) 5449 5430 return -ENOMEM; 5450 5431 5451 - its_enable_quirks(its); 5452 5432 err = its_probe_one(its); 5453 5433 if (err) { 5454 5434 its_node_destroy(its);
+1 -1
drivers/irqchip/irq-loongson-eiointc.c
··· 241 241 int ret; 242 242 unsigned int i, type; 243 243 unsigned long hwirq = 0; 244 - struct eiointc *priv = domain->host_data; 244 + struct eiointc_priv *priv = domain->host_data; 245 245 246 246 ret = irq_domain_translate_onecell(domain, arg, &hwirq, &type); 247 247 if (ret)
+2 -2
drivers/irqchip/irq-qcom-mpm.c
··· 389 389 /* Don't use devm_ioremap_resource, as we're accessing a shared region. */ 390 390 priv->base = devm_ioremap(dev, res.start, resource_size(&res)); 391 391 of_node_put(msgram_np); 392 - if (IS_ERR(priv->base)) 393 - return PTR_ERR(priv->base); 392 + if (!priv->base) 393 + return -ENOMEM; 394 394 } else { 395 395 /* Otherwise, fall back to simple MMIO. */ 396 396 priv->base = devm_platform_ioremap_resource(pdev, 0);