Skip to content

Commit 36714d6

Browse files
committed
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
2 parents 7cedb02 + b97e8a2 commit 36714d6

File tree

3 files changed

+36
-51
lines changed

3 files changed

+36
-51
lines changed

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

Lines changed: 12 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1846,28 +1846,22 @@ static int its_vlpi_map(struct irq_data *d, struct its_cmd_info *info)
18461846
{
18471847
struct its_device *its_dev = irq_data_get_irq_chip_data(d);
18481848
u32 event = its_get_event_id(d);
1849-
int ret = 0;
18501849

18511850
if (!info->map)
18521851
return -EINVAL;
18531852

1854-
raw_spin_lock(&its_dev->event_map.vlpi_lock);
1855-
18561853
if (!its_dev->event_map.vm) {
18571854
struct its_vlpi_map *maps;
18581855

18591856
maps = kcalloc(its_dev->event_map.nr_lpis, sizeof(*maps),
18601857
GFP_ATOMIC);
1861-
if (!maps) {
1862-
ret = -ENOMEM;
1863-
goto out;
1864-
}
1858+
if (!maps)
1859+
return -ENOMEM;
18651860

18661861
its_dev->event_map.vm = info->map->vm;
18671862
its_dev->event_map.vlpi_maps = maps;
18681863
} else if (its_dev->event_map.vm != info->map->vm) {
1869-
ret = -EINVAL;
1870-
goto out;
1864+
return -EINVAL;
18711865
}
18721866

18731867
/* 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)
18991893
its_dev->event_map.nr_vlpis++;
19001894
}
19011895

1902-
out:
1903-
raw_spin_unlock(&its_dev->event_map.vlpi_lock);
1904-
return ret;
1896+
return 0;
19051897
}
19061898

19071899
static int its_vlpi_get(struct irq_data *d, struct its_cmd_info *info)
19081900
{
19091901
struct its_device *its_dev = irq_data_get_irq_chip_data(d);
19101902
struct its_vlpi_map *map;
1911-
int ret = 0;
1912-
1913-
raw_spin_lock(&its_dev->event_map.vlpi_lock);
19141903

19151904
map = get_vlpi_map(d);
19161905

1917-
if (!its_dev->event_map.vm || !map) {
1918-
ret = -EINVAL;
1919-
goto out;
1920-
}
1906+
if (!its_dev->event_map.vm || !map)
1907+
return -EINVAL;
19211908

19221909
/* Copy our mapping information to the incoming request */
19231910
*info->map = *map;
19241911

1925-
out:
1926-
raw_spin_unlock(&its_dev->event_map.vlpi_lock);
1927-
return ret;
1912+
return 0;
19281913
}
19291914

19301915
static int its_vlpi_unmap(struct irq_data *d)
19311916
{
19321917
struct its_device *its_dev = irq_data_get_irq_chip_data(d);
19331918
u32 event = its_get_event_id(d);
1934-
int ret = 0;
1935-
1936-
raw_spin_lock(&its_dev->event_map.vlpi_lock);
19371919

1938-
if (!its_dev->event_map.vm || !irqd_is_forwarded_to_vcpu(d)) {
1939-
ret = -EINVAL;
1940-
goto out;
1941-
}
1920+
if (!its_dev->event_map.vm || !irqd_is_forwarded_to_vcpu(d))
1921+
return -EINVAL;
19421922

19431923
/* Drop the virtual mapping */
19441924
its_send_discard(its_dev, event);
@@ -1962,9 +1942,7 @@ static int its_vlpi_unmap(struct irq_data *d)
19621942
kfree(its_dev->event_map.vlpi_maps);
19631943
}
19641944

1965-
out:
1966-
raw_spin_unlock(&its_dev->event_map.vlpi_lock);
1967-
return ret;
1945+
return 0;
19681946
}
19691947

19701948
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)
19921970
if (!is_v4(its_dev->its))
19931971
return -EINVAL;
19941972

1973+
guard(raw_spinlock_irq)(&its_dev->event_map.vlpi_lock);
1974+
19951975
/* Unmap request? */
19961976
if (!info)
19971977
return its_vlpi_unmap(d);

drivers/irqchip/irq-riscv-intc.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,8 +253,9 @@ IRQCHIP_DECLARE(andes, "andestech,cpu-intc", riscv_intc_init);
253253
static int __init riscv_intc_acpi_init(union acpi_subtable_headers *header,
254254
const unsigned long end)
255255
{
256-
struct fwnode_handle *fn;
257256
struct acpi_madt_rintc *rintc;
257+
struct fwnode_handle *fn;
258+
int rc;
258259

259260
rintc = (struct acpi_madt_rintc *)header;
260261

@@ -273,7 +274,11 @@ static int __init riscv_intc_acpi_init(union acpi_subtable_headers *header,
273274
return -ENOMEM;
274275
}
275276

276-
return riscv_intc_init_common(fn, &riscv_intc_chip);
277+
rc = riscv_intc_init_common(fn, &riscv_intc_chip);
278+
if (rc)
279+
irq_domain_free_fwnode(fn);
280+
281+
return rc;
277282
}
278283

279284
IRQCHIP_ACPI_DECLARE(riscv_intc, ACPI_MADT_TYPE_RINTC, NULL,

drivers/irqchip/irq-sifive-plic.c

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ struct plic_handler {
8585
struct plic_priv *priv;
8686
};
8787
static int plic_parent_irq __ro_after_init;
88-
static bool plic_cpuhp_setup_done __ro_after_init;
88+
static bool plic_global_setup_done __ro_after_init;
8989
static DEFINE_PER_CPU(struct plic_handler, plic_handlers);
9090

9191
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)
487487
unsigned long plic_quirks = 0;
488488
struct plic_handler *handler;
489489
u32 nr_irqs, parent_hwirq;
490-
struct irq_domain *domain;
491490
struct plic_priv *priv;
492491
irq_hw_number_t hwirq;
493-
bool cpuhp_setup;
494492

495493
if (is_of_node(dev->fwnode)) {
496494
const struct of_device_id *id;
@@ -549,14 +547,6 @@ static int plic_probe(struct platform_device *pdev)
549547
continue;
550548
}
551549

552-
/* Find parent domain and register chained handler */
553-
domain = irq_find_matching_fwnode(riscv_get_intc_hwnode(), DOMAIN_BUS_ANY);
554-
if (!plic_parent_irq && domain) {
555-
plic_parent_irq = irq_create_mapping(domain, RV_IRQ_EXT);
556-
if (plic_parent_irq)
557-
irq_set_chained_handler(plic_parent_irq, plic_handle_irq);
558-
}
559-
560550
/*
561551
* When running in M-mode we need to ignore the S-mode handler.
562552
* Here we assume it always comes later, but that might be a
@@ -597,25 +587,35 @@ static int plic_probe(struct platform_device *pdev)
597587
goto fail_cleanup_contexts;
598588

599589
/*
600-
* We can have multiple PLIC instances so setup cpuhp state
590+
* We can have multiple PLIC instances so setup global state
601591
* and register syscore operations only once after context
602592
* handlers of all online CPUs are initialized.
603593
*/
604-
if (!plic_cpuhp_setup_done) {
605-
cpuhp_setup = true;
594+
if (!plic_global_setup_done) {
595+
struct irq_domain *domain;
596+
bool global_setup = true;
597+
606598
for_each_online_cpu(cpu) {
607599
handler = per_cpu_ptr(&plic_handlers, cpu);
608600
if (!handler->present) {
609-
cpuhp_setup = false;
601+
global_setup = false;
610602
break;
611603
}
612604
}
613-
if (cpuhp_setup) {
605+
606+
if (global_setup) {
607+
/* Find parent domain and register chained handler */
608+
domain = irq_find_matching_fwnode(riscv_get_intc_hwnode(), DOMAIN_BUS_ANY);
609+
if (domain)
610+
plic_parent_irq = irq_create_mapping(domain, RV_IRQ_EXT);
611+
if (plic_parent_irq)
612+
irq_set_chained_handler(plic_parent_irq, plic_handle_irq);
613+
614614
cpuhp_setup_state(CPUHP_AP_IRQ_SIFIVE_PLIC_STARTING,
615615
"irqchip/sifive/plic:starting",
616616
plic_starting_cpu, plic_dying_cpu);
617617
register_syscore_ops(&plic_irq_syscore_ops);
618-
plic_cpuhp_setup_done = true;
618+
plic_global_setup_done = true;
619619
}
620620
}
621621

0 commit comments

Comments
 (0)