aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/irqchip
diff options
context:
space:
mode:
authorThomas Petazzoni <thomas.petazzoni@free-electrons.com>2016-02-10 09:47:00 -0500
committerJason Cooper <jason@lakedaemon.net>2016-02-16 12:36:16 -0500
commita71b9412c90ca784ae68d32ec307cc527b5962a9 (patch)
treedf963eb1711df7b4c773e84819f54f71d6e0371f /drivers/irqchip
parentf692a172deb5cda8874a44782401901597c526a2 (diff)
irqchip/armada-370-xp: Allow allocation of multiple MSIs
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>
Diffstat (limited to 'drivers/irqchip')
-rw-r--r--drivers/irqchip/irq-armada-370-xp.c25
1 files changed, 14 insertions, 11 deletions
diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c
index c99ae5fc5500..e7dc6cbda2a1 100644
--- a/drivers/irqchip/irq-armada-370-xp.c
+++ b/drivers/irqchip/irq-armada-370-xp.c
@@ -123,7 +123,8 @@ static struct irq_chip armada_370_xp_msi_irq_chip = {
123}; 123};
124 124
125static struct msi_domain_info armada_370_xp_msi_domain_info = { 125static struct msi_domain_info armada_370_xp_msi_domain_info = {
126 .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS), 126 .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
127 MSI_FLAG_MULTI_PCI_MSI),
127 .chip = &armada_370_xp_msi_irq_chip, 128 .chip = &armada_370_xp_msi_irq_chip,
128}; 129};
129 130
@@ -149,21 +150,26 @@ static struct irq_chip armada_370_xp_msi_bottom_irq_chip = {
149static int armada_370_xp_msi_alloc(struct irq_domain *domain, unsigned int virq, 150static int armada_370_xp_msi_alloc(struct irq_domain *domain, unsigned int virq,
150 unsigned int nr_irqs, void *args) 151 unsigned int nr_irqs, void *args)
151{ 152{
152 int hwirq; 153 int hwirq, i;
153 154
154 mutex_lock(&msi_used_lock); 155 mutex_lock(&msi_used_lock);
155 hwirq = find_first_zero_bit(&msi_used, PCI_MSI_DOORBELL_NR); 156
157 hwirq = bitmap_find_next_zero_area(msi_used, PCI_MSI_DOORBELL_NR,
158 0, nr_irqs, 0);
156 if (hwirq >= PCI_MSI_DOORBELL_NR) { 159 if (hwirq >= PCI_MSI_DOORBELL_NR) {
157 mutex_unlock(&msi_used_lock); 160 mutex_unlock(&msi_used_lock);
158 return -ENOSPC; 161 return -ENOSPC;
159 } 162 }
160 163
161 set_bit(hwirq, msi_used); 164 bitmap_set(msi_used, hwirq, nr_irqs);
162 mutex_unlock(&msi_used_lock); 165 mutex_unlock(&msi_used_lock);
163 166
164 irq_domain_set_info(domain, virq, hwirq, &armada_370_xp_msi_bottom_irq_chip, 167 for (i = 0; i < nr_irqs; i++) {
165 domain->host_data, handle_simple_irq, 168 irq_domain_set_info(domain, virq + i, hwirq + i,
166 NULL, NULL); 169 &armada_370_xp_msi_bottom_irq_chip,
170 domain->host_data, handle_simple_irq,
171 NULL, NULL);
172 }
167 173
168 return hwirq; 174 return hwirq;
169} 175}
@@ -174,10 +180,7 @@ static void armada_370_xp_msi_free(struct irq_domain *domain,
174 struct irq_data *d = irq_domain_get_irq_data(domain, virq); 180 struct irq_data *d = irq_domain_get_irq_data(domain, virq);
175 181
176 mutex_lock(&msi_used_lock); 182 mutex_lock(&msi_used_lock);
177 if (!test_bit(d->hwirq, msi_used)) 183 bitmap_clear(msi_used, d->hwirq, nr_irqs);
178 pr_err("trying to free unused MSI#%lu\n", d->hwirq);
179 else
180 clear_bit(d->hwirq, msi_used);
181 mutex_unlock(&msi_used_lock); 184 mutex_unlock(&msi_used_lock);
182} 185}
183 186