diff options
author | Thomas Petazzoni <thomas.petazzoni@free-electrons.com> | 2016-02-10 09:47:00 -0500 |
---|---|---|
committer | Jason Cooper <jason@lakedaemon.net> | 2016-02-16 12:36:16 -0500 |
commit | a71b9412c90ca784ae68d32ec307cc527b5962a9 (patch) | |
tree | df963eb1711df7b4c773e84819f54f71d6e0371f /drivers/irqchip | |
parent | f692a172deb5cda8874a44782401901597c526a2 (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.c | 25 |
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 | ||
125 | static struct msi_domain_info armada_370_xp_msi_domain_info = { | 125 | static 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 = { | |||
149 | static int armada_370_xp_msi_alloc(struct irq_domain *domain, unsigned int virq, | 150 | static 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 | ||