Skip to content

Commit 33f82bd

Browse files
committed
Merge branch 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull irq fixes from Ingo Molnar: "A sparse irq race/locking fix, and a MSI irq domains population fix" * 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: genirq: Make sparse_irq_lock protect what it should protect genirq/msi: Fix populating multiple interrupts
2 parents 8fac2f9 + 12ac1d0 commit 33f82bd

File tree

2 files changed

+10
-19
lines changed

2 files changed

+10
-19
lines changed

kernel/irq/irqdesc.c

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -421,10 +421,8 @@ static void free_desc(unsigned int irq)
421421
* The sysfs entry must be serialized against a concurrent
422422
* irq_sysfs_init() as well.
423423
*/
424-
mutex_lock(&sparse_irq_lock);
425424
kobject_del(&desc->kobj);
426425
delete_irq_desc(irq);
427-
mutex_unlock(&sparse_irq_lock);
428426

429427
/*
430428
* We free the descriptor, masks and stat fields via RCU. That
@@ -462,20 +460,15 @@ static int alloc_descs(unsigned int start, unsigned int cnt, int node,
462460
desc = alloc_desc(start + i, node, flags, mask, owner);
463461
if (!desc)
464462
goto err;
465-
mutex_lock(&sparse_irq_lock);
466463
irq_insert_desc(start + i, desc);
467464
irq_sysfs_add(start + i, desc);
468-
mutex_unlock(&sparse_irq_lock);
469465
}
466+
bitmap_set(allocated_irqs, start, cnt);
470467
return start;
471468

472469
err:
473470
for (i--; i >= 0; i--)
474471
free_desc(start + i);
475-
476-
mutex_lock(&sparse_irq_lock);
477-
bitmap_clear(allocated_irqs, start, cnt);
478-
mutex_unlock(&sparse_irq_lock);
479472
return -ENOMEM;
480473
}
481474

@@ -575,6 +568,7 @@ static inline int alloc_descs(unsigned int start, unsigned int cnt, int node,
575568

576569
desc->owner = owner;
577570
}
571+
bitmap_set(allocated_irqs, start, cnt);
578572
return start;
579573
}
580574

@@ -670,10 +664,10 @@ void irq_free_descs(unsigned int from, unsigned int cnt)
670664
if (from >= nr_irqs || (from + cnt) > nr_irqs)
671665
return;
672666

667+
mutex_lock(&sparse_irq_lock);
673668
for (i = 0; i < cnt; i++)
674669
free_desc(from + i);
675670

676-
mutex_lock(&sparse_irq_lock);
677671
bitmap_clear(allocated_irqs, from, cnt);
678672
mutex_unlock(&sparse_irq_lock);
679673
}
@@ -720,19 +714,15 @@ __irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node,
720714
from, cnt, 0);
721715
ret = -EEXIST;
722716
if (irq >=0 && start != irq)
723-
goto err;
717+
goto unlock;
724718

725719
if (start + cnt > nr_irqs) {
726720
ret = irq_expand_nr_irqs(start + cnt);
727721
if (ret)
728-
goto err;
722+
goto unlock;
729723
}
730-
731-
bitmap_set(allocated_irqs, start, cnt);
732-
mutex_unlock(&sparse_irq_lock);
733-
return alloc_descs(start, cnt, node, affinity, owner);
734-
735-
err:
724+
ret = alloc_descs(start, cnt, node, affinity, owner);
725+
unlock:
736726
mutex_unlock(&sparse_irq_lock);
737727
return ret;
738728
}

kernel/irq/msi.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -315,11 +315,12 @@ int msi_domain_populate_irqs(struct irq_domain *domain, struct device *dev,
315315

316316
ops->set_desc(arg, desc);
317317
/* Assumes the domain mutex is held! */
318-
ret = irq_domain_alloc_irqs_hierarchy(domain, virq, 1, arg);
318+
ret = irq_domain_alloc_irqs_hierarchy(domain, desc->irq, 1,
319+
arg);
319320
if (ret)
320321
break;
321322

322-
irq_set_msi_desc_off(virq, 0, desc);
323+
irq_set_msi_desc_off(desc->irq, 0, desc);
323324
}
324325

325326
if (ret) {

0 commit comments

Comments
 (0)