Merge branch 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 12 Sep 2017 18:25:56 +0000 (11:25 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 12 Sep 2017 18:25:56 +0000 (11:25 -0700)
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

kernel/irq/irqdesc.c
kernel/irq/msi.c

index 73be2b3909bd40a373e9c5237575faed5812945f..82afb7ed369f0df70bcd5d6fdc110addda5b842f 100644 (file)
@@ -421,10 +421,8 @@ static void free_desc(unsigned int irq)
         * The sysfs entry must be serialized against a concurrent
         * irq_sysfs_init() as well.
         */
-       mutex_lock(&sparse_irq_lock);
        kobject_del(&desc->kobj);
        delete_irq_desc(irq);
-       mutex_unlock(&sparse_irq_lock);
 
        /*
         * 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,
                desc = alloc_desc(start + i, node, flags, mask, owner);
                if (!desc)
                        goto err;
-               mutex_lock(&sparse_irq_lock);
                irq_insert_desc(start + i, desc);
                irq_sysfs_add(start + i, desc);
-               mutex_unlock(&sparse_irq_lock);
        }
+       bitmap_set(allocated_irqs, start, cnt);
        return start;
 
 err:
        for (i--; i >= 0; i--)
                free_desc(start + i);
-
-       mutex_lock(&sparse_irq_lock);
-       bitmap_clear(allocated_irqs, start, cnt);
-       mutex_unlock(&sparse_irq_lock);
        return -ENOMEM;
 }
 
@@ -575,6 +568,7 @@ static inline int alloc_descs(unsigned int start, unsigned int cnt, int node,
 
                desc->owner = owner;
        }
+       bitmap_set(allocated_irqs, start, cnt);
        return start;
 }
 
@@ -670,10 +664,10 @@ void irq_free_descs(unsigned int from, unsigned int cnt)
        if (from >= nr_irqs || (from + cnt) > nr_irqs)
                return;
 
+       mutex_lock(&sparse_irq_lock);
        for (i = 0; i < cnt; i++)
                free_desc(from + i);
 
-       mutex_lock(&sparse_irq_lock);
        bitmap_clear(allocated_irqs, from, cnt);
        mutex_unlock(&sparse_irq_lock);
 }
@@ -720,19 +714,15 @@ __irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node,
                                           from, cnt, 0);
        ret = -EEXIST;
        if (irq >=0 && start != irq)
-               goto err;
+               goto unlock;
 
        if (start + cnt > nr_irqs) {
                ret = irq_expand_nr_irqs(start + cnt);
                if (ret)
-                       goto err;
+                       goto unlock;
        }
-
-       bitmap_set(allocated_irqs, start, cnt);
-       mutex_unlock(&sparse_irq_lock);
-       return alloc_descs(start, cnt, node, affinity, owner);
-
-err:
+       ret = alloc_descs(start, cnt, node, affinity, owner);
+unlock:
        mutex_unlock(&sparse_irq_lock);
        return ret;
 }
index 48eadf416c24b3c86f540ab94c6e519557b9b036..3fa4bd59f569865703bb9ab189d24401e99bbf38 100644 (file)
@@ -315,11 +315,12 @@ int msi_domain_populate_irqs(struct irq_domain *domain, struct device *dev,
 
                ops->set_desc(arg, desc);
                /* Assumes the domain mutex is held! */
-               ret = irq_domain_alloc_irqs_hierarchy(domain, virq, 1, arg);
+               ret = irq_domain_alloc_irqs_hierarchy(domain, desc->irq, 1,
+                                                     arg);
                if (ret)
                        break;
 
-               irq_set_msi_desc_off(virq, 0, desc);
+               irq_set_msi_desc_off(desc->irq, 0, desc);
        }
 
        if (ret) {