Miscellaneous fixes:
- Fix possible memory leak the riscv-intc irqchip driver load failures - Fix boot crash in the sifive-plic irqchip driver caused by recently changed boot initialization order - Fix race condition in the gic-v3-its irqchip driver Signed-off-by: Ingo Molnar <mingo@kernel.org> -----BEGIN PGP SIGNATURE----- iQJFBAABCgAvFiEEBpT5eoXrXCwVQwEKEnMQ0APhK1gFAmZkDTMRHG1pbmdvQGtl cm5lbC5vcmcACgkQEnMQ0APhK1hPsRAAoHgcHw9KGhI9+y7Xnnjt4W9Ud6S3W8cs AcmP9x83+iilnPQrrWlB/v5p02qBPPdpqnDvOnB/7bITxJGxnSBXj1awUuV45qX2 QRS4sIDq6zkDH6pX0diiwqLbfWZwpcbvtnR3nXSGImOK0jI3yQiSLEc8vswt88Jr HnYg9UdvKCt7j+jbqf9PzPHJP8z/U+Kx6eMPF4H/6R+nccedtQ0D2BdR5RSKFVZM aQwpZp6LTTapp3B1lXOx6IJaVTkRMeEm9J2Zc4R/pD3dvKof0xpEwJ+dqBrPAjb0 +ospUJcPz4Sw9XhBIrqq4A+LUewiVa9grI3t1qit+VtbXkVHfLK9mUlyXfQzgMFz JTlUgt3V4vpbceUbFZsefXeB2TDGAPpFQvwgNozvEx+IgEZjryrSa2SgAuhl4Y6b nIxwBYFMlG6GI8CIDVGyl3XK/DcKUXM1XloJwTRDWjN/cZloxaZjRIpIiACr+SYW S1axryYDqDG4VU3vfTEqb75VGm4rPtHLXqRDmu/ZL8/BIQ7CQqnD0eMGIQ79aEXj Ia5CccTWqu0dufA5rxl47lcacPEKYlVFTkTul1ujzM2ymllmwjTpPKvSEhcwUC6J XRR7iv372AUo1xnk1G34Wl6Mp9nbxW2DXNinX/eDuV0AqV/1EKxs6vqgddGKhOuX K+ER8F+is64= =98O/ -----END PGP SIGNATURE----- Merge tag 'irq-urgent-2024-06-08' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip Pull irq fixes from Ingo Molnar: - Fix possible memory leak the riscv-intc irqchip driver load failures - Fix boot crash in the sifive-plic irqchip driver caused by recently changed boot initialization order - Fix race condition in the gic-v3-its irqchip driver * tag 'irq-urgent-2024-06-08' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: irqchip/gic-v3-its: Fix potential race condition in its_vlpi_prop_update() irqchip/sifive-plic: Chain to parent IRQ after handlers are ready irqchip/riscv-intc: Prevent memory leak when riscv_intc_init_common() fails
This commit is contained in:
commit
36714d69b1
@ -1846,28 +1846,22 @@ static int its_vlpi_map(struct irq_data *d, struct its_cmd_info *info)
|
||||
{
|
||||
struct its_device *its_dev = irq_data_get_irq_chip_data(d);
|
||||
u32 event = its_get_event_id(d);
|
||||
int ret = 0;
|
||||
|
||||
if (!info->map)
|
||||
return -EINVAL;
|
||||
|
||||
raw_spin_lock(&its_dev->event_map.vlpi_lock);
|
||||
|
||||
if (!its_dev->event_map.vm) {
|
||||
struct its_vlpi_map *maps;
|
||||
|
||||
maps = kcalloc(its_dev->event_map.nr_lpis, sizeof(*maps),
|
||||
GFP_ATOMIC);
|
||||
if (!maps) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
if (!maps)
|
||||
return -ENOMEM;
|
||||
|
||||
its_dev->event_map.vm = info->map->vm;
|
||||
its_dev->event_map.vlpi_maps = maps;
|
||||
} else if (its_dev->event_map.vm != info->map->vm) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Get our private copy of the mapping information */
|
||||
@ -1899,46 +1893,32 @@ static int its_vlpi_map(struct irq_data *d, struct its_cmd_info *info)
|
||||
its_dev->event_map.nr_vlpis++;
|
||||
}
|
||||
|
||||
out:
|
||||
raw_spin_unlock(&its_dev->event_map.vlpi_lock);
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int its_vlpi_get(struct irq_data *d, struct its_cmd_info *info)
|
||||
{
|
||||
struct its_device *its_dev = irq_data_get_irq_chip_data(d);
|
||||
struct its_vlpi_map *map;
|
||||
int ret = 0;
|
||||
|
||||
raw_spin_lock(&its_dev->event_map.vlpi_lock);
|
||||
|
||||
map = get_vlpi_map(d);
|
||||
|
||||
if (!its_dev->event_map.vm || !map) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (!its_dev->event_map.vm || !map)
|
||||
return -EINVAL;
|
||||
|
||||
/* Copy our mapping information to the incoming request */
|
||||
*info->map = *map;
|
||||
|
||||
out:
|
||||
raw_spin_unlock(&its_dev->event_map.vlpi_lock);
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int its_vlpi_unmap(struct irq_data *d)
|
||||
{
|
||||
struct its_device *its_dev = irq_data_get_irq_chip_data(d);
|
||||
u32 event = its_get_event_id(d);
|
||||
int ret = 0;
|
||||
|
||||
raw_spin_lock(&its_dev->event_map.vlpi_lock);
|
||||
|
||||
if (!its_dev->event_map.vm || !irqd_is_forwarded_to_vcpu(d)) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (!its_dev->event_map.vm || !irqd_is_forwarded_to_vcpu(d))
|
||||
return -EINVAL;
|
||||
|
||||
/* Drop the virtual mapping */
|
||||
its_send_discard(its_dev, event);
|
||||
@ -1962,9 +1942,7 @@ static int its_vlpi_unmap(struct irq_data *d)
|
||||
kfree(its_dev->event_map.vlpi_maps);
|
||||
}
|
||||
|
||||
out:
|
||||
raw_spin_unlock(&its_dev->event_map.vlpi_lock);
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int its_vlpi_prop_update(struct irq_data *d, struct its_cmd_info *info)
|
||||
@ -1992,6 +1970,8 @@ static int its_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu_info)
|
||||
if (!is_v4(its_dev->its))
|
||||
return -EINVAL;
|
||||
|
||||
guard(raw_spinlock_irq)(&its_dev->event_map.vlpi_lock);
|
||||
|
||||
/* Unmap request? */
|
||||
if (!info)
|
||||
return its_vlpi_unmap(d);
|
||||
|
@ -253,8 +253,9 @@ IRQCHIP_DECLARE(andes, "andestech,cpu-intc", riscv_intc_init);
|
||||
static int __init riscv_intc_acpi_init(union acpi_subtable_headers *header,
|
||||
const unsigned long end)
|
||||
{
|
||||
struct fwnode_handle *fn;
|
||||
struct acpi_madt_rintc *rintc;
|
||||
struct fwnode_handle *fn;
|
||||
int rc;
|
||||
|
||||
rintc = (struct acpi_madt_rintc *)header;
|
||||
|
||||
@ -273,7 +274,11 @@ static int __init riscv_intc_acpi_init(union acpi_subtable_headers *header,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return riscv_intc_init_common(fn, &riscv_intc_chip);
|
||||
rc = riscv_intc_init_common(fn, &riscv_intc_chip);
|
||||
if (rc)
|
||||
irq_domain_free_fwnode(fn);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
IRQCHIP_ACPI_DECLARE(riscv_intc, ACPI_MADT_TYPE_RINTC, NULL,
|
||||
|
@ -85,7 +85,7 @@ struct plic_handler {
|
||||
struct plic_priv *priv;
|
||||
};
|
||||
static int plic_parent_irq __ro_after_init;
|
||||
static bool plic_cpuhp_setup_done __ro_after_init;
|
||||
static bool plic_global_setup_done __ro_after_init;
|
||||
static DEFINE_PER_CPU(struct plic_handler, plic_handlers);
|
||||
|
||||
static int plic_irq_set_type(struct irq_data *d, unsigned int type);
|
||||
@ -487,10 +487,8 @@ static int plic_probe(struct platform_device *pdev)
|
||||
unsigned long plic_quirks = 0;
|
||||
struct plic_handler *handler;
|
||||
u32 nr_irqs, parent_hwirq;
|
||||
struct irq_domain *domain;
|
||||
struct plic_priv *priv;
|
||||
irq_hw_number_t hwirq;
|
||||
bool cpuhp_setup;
|
||||
|
||||
if (is_of_node(dev->fwnode)) {
|
||||
const struct of_device_id *id;
|
||||
@ -549,14 +547,6 @@ static int plic_probe(struct platform_device *pdev)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Find parent domain and register chained handler */
|
||||
domain = irq_find_matching_fwnode(riscv_get_intc_hwnode(), DOMAIN_BUS_ANY);
|
||||
if (!plic_parent_irq && domain) {
|
||||
plic_parent_irq = irq_create_mapping(domain, RV_IRQ_EXT);
|
||||
if (plic_parent_irq)
|
||||
irq_set_chained_handler(plic_parent_irq, plic_handle_irq);
|
||||
}
|
||||
|
||||
/*
|
||||
* When running in M-mode we need to ignore the S-mode handler.
|
||||
* Here we assume it always comes later, but that might be a
|
||||
@ -597,25 +587,35 @@ done:
|
||||
goto fail_cleanup_contexts;
|
||||
|
||||
/*
|
||||
* We can have multiple PLIC instances so setup cpuhp state
|
||||
* We can have multiple PLIC instances so setup global state
|
||||
* and register syscore operations only once after context
|
||||
* handlers of all online CPUs are initialized.
|
||||
*/
|
||||
if (!plic_cpuhp_setup_done) {
|
||||
cpuhp_setup = true;
|
||||
if (!plic_global_setup_done) {
|
||||
struct irq_domain *domain;
|
||||
bool global_setup = true;
|
||||
|
||||
for_each_online_cpu(cpu) {
|
||||
handler = per_cpu_ptr(&plic_handlers, cpu);
|
||||
if (!handler->present) {
|
||||
cpuhp_setup = false;
|
||||
global_setup = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cpuhp_setup) {
|
||||
|
||||
if (global_setup) {
|
||||
/* Find parent domain and register chained handler */
|
||||
domain = irq_find_matching_fwnode(riscv_get_intc_hwnode(), DOMAIN_BUS_ANY);
|
||||
if (domain)
|
||||
plic_parent_irq = irq_create_mapping(domain, RV_IRQ_EXT);
|
||||
if (plic_parent_irq)
|
||||
irq_set_chained_handler(plic_parent_irq, plic_handle_irq);
|
||||
|
||||
cpuhp_setup_state(CPUHP_AP_IRQ_SIFIVE_PLIC_STARTING,
|
||||
"irqchip/sifive/plic:starting",
|
||||
plic_starting_cpu, plic_dying_cpu);
|
||||
register_syscore_ops(&plic_irq_syscore_ops);
|
||||
plic_cpuhp_setup_done = true;
|
||||
plic_global_setup_done = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user