irqchip/armada-370-xp: Allow allocation of multiple MSIs
authorThomas Petazzoni <thomas.petazzoni@free-electrons.com>
Wed, 10 Feb 2016 14:47:00 +0000 (15:47 +0100)
committerJason Cooper <jason@lakedaemon.net>
Tue, 16 Feb 2016 17:36:16 +0000 (17:36 +0000)
Add support for allocating multiple MSIs at the same time, so that the
MSI_FLAG_MULTI_PCI_MSI flag can be added to the msi_domain_info
structure.

Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Reviewed-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
Link: https://lkml.kernel.org/r/1455115621-22846-6-git-send-email-thomas.petazzoni@free-electrons.com
Signed-off-by: Jason Cooper <jason@lakedaemon.net>
drivers/irqchip/irq-armada-370-xp.c

index c99ae5fc5500ba5bf8330767e090a378966f83c5..e7dc6cbda2a1bb61d5b4817dc14649133f1ab5eb 100644 (file)
@@ -123,7 +123,8 @@ static struct irq_chip armada_370_xp_msi_irq_chip = {
 };
 
 static struct msi_domain_info armada_370_xp_msi_domain_info = {
-       .flags  = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS),
+       .flags  = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
+                  MSI_FLAG_MULTI_PCI_MSI),
        .chip   = &armada_370_xp_msi_irq_chip,
 };
 
@@ -149,21 +150,26 @@ static struct irq_chip armada_370_xp_msi_bottom_irq_chip = {
 static int armada_370_xp_msi_alloc(struct irq_domain *domain, unsigned int virq,
                                   unsigned int nr_irqs, void *args)
 {
-       int hwirq;
+       int hwirq, i;
 
        mutex_lock(&msi_used_lock);
-       hwirq = find_first_zero_bit(&msi_used, PCI_MSI_DOORBELL_NR);
+
+       hwirq = bitmap_find_next_zero_area(msi_used, PCI_MSI_DOORBELL_NR,
+                                          0, nr_irqs, 0);
        if (hwirq >= PCI_MSI_DOORBELL_NR) {
                mutex_unlock(&msi_used_lock);
                return -ENOSPC;
        }
 
-       set_bit(hwirq, msi_used);
+       bitmap_set(msi_used, hwirq, nr_irqs);
        mutex_unlock(&msi_used_lock);
 
-       irq_domain_set_info(domain, virq, hwirq, &armada_370_xp_msi_bottom_irq_chip,
-                           domain->host_data, handle_simple_irq,
-                           NULL, NULL);
+       for (i = 0; i < nr_irqs; i++) {
+               irq_domain_set_info(domain, virq + i, hwirq + i,
+                                   &armada_370_xp_msi_bottom_irq_chip,
+                                   domain->host_data, handle_simple_irq,
+                                   NULL, NULL);
+       }
 
        return hwirq;
 }
@@ -174,10 +180,7 @@ static void armada_370_xp_msi_free(struct irq_domain *domain,
        struct irq_data *d = irq_domain_get_irq_data(domain, virq);
 
        mutex_lock(&msi_used_lock);
-       if (!test_bit(d->hwirq, msi_used))
-               pr_err("trying to free unused MSI#%lu\n", d->hwirq);
-       else
-               clear_bit(d->hwirq, msi_used);
+       bitmap_clear(msi_used, d->hwirq, nr_irqs);
        mutex_unlock(&msi_used_lock);
 }