| From d3663b5b0881dc397f8ce61a43bde3e0ee2d35a7 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Tue, 22 Jun 2021 17:26:29 +0200 |
| Subject: PCI: iproc: Fix multi-MSI base vector number allocation |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: Sandor Bodo-Merle <sbodomerle@gmail.com> |
| |
| [ Upstream commit e673d697b9a234fc3544ac240e173cef8c82b349 ] |
| |
| Commit fc54bae28818 ("PCI: iproc: Allow allocation of multiple MSIs") |
| introduced multi-MSI support with a broken allocation mechanism (it failed |
| to reserve the proper number of bits from the inner domain). Natural |
| alignment of the base vector number was also not guaranteed. |
| |
| Link: https://lore.kernel.org/r/20210622152630.40842-1-sbodomerle@gmail.com |
| Fixes: fc54bae28818 ("PCI: iproc: Allow allocation of multiple MSIs") |
| Reported-by: Pali Rohár <pali@kernel.org> |
| Signed-off-by: Sandor Bodo-Merle <sbodomerle@gmail.com> |
| Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> |
| Acked-by: Marc Zyngier <maz@kernel.org> |
| Acked-by: Pali Rohár <pali@kernel.org> |
| Acked-by: Ray Jui <ray.jui@broadcom.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/pci/controller/pcie-iproc-msi.c | 21 +++++++++++---------- |
| 1 file changed, 11 insertions(+), 10 deletions(-) |
| |
| diff --git a/drivers/pci/controller/pcie-iproc-msi.c b/drivers/pci/controller/pcie-iproc-msi.c |
| index eede4e8f3f75..557d93dcb3bc 100644 |
| --- a/drivers/pci/controller/pcie-iproc-msi.c |
| +++ b/drivers/pci/controller/pcie-iproc-msi.c |
| @@ -252,18 +252,18 @@ static int iproc_msi_irq_domain_alloc(struct irq_domain *domain, |
| |
| mutex_lock(&msi->bitmap_lock); |
| |
| - /* Allocate 'nr_cpus' number of MSI vectors each time */ |
| - hwirq = bitmap_find_next_zero_area(msi->bitmap, msi->nr_msi_vecs, 0, |
| - msi->nr_cpus, 0); |
| - if (hwirq < msi->nr_msi_vecs) { |
| - bitmap_set(msi->bitmap, hwirq, msi->nr_cpus); |
| - } else { |
| - mutex_unlock(&msi->bitmap_lock); |
| - return -ENOSPC; |
| - } |
| + /* |
| + * Allocate 'nr_irqs' multiplied by 'nr_cpus' number of MSI vectors |
| + * each time |
| + */ |
| + hwirq = bitmap_find_free_region(msi->bitmap, msi->nr_msi_vecs, |
| + order_base_2(msi->nr_cpus * nr_irqs)); |
| |
| mutex_unlock(&msi->bitmap_lock); |
| |
| + if (hwirq < 0) |
| + return -ENOSPC; |
| + |
| for (i = 0; i < nr_irqs; i++) { |
| irq_domain_set_info(domain, virq + i, hwirq + i, |
| &iproc_msi_bottom_irq_chip, |
| @@ -284,7 +284,8 @@ static void iproc_msi_irq_domain_free(struct irq_domain *domain, |
| mutex_lock(&msi->bitmap_lock); |
| |
| hwirq = hwirq_to_canonical_hwirq(msi, data->hwirq); |
| - bitmap_clear(msi->bitmap, hwirq, msi->nr_cpus); |
| + bitmap_release_region(msi->bitmap, hwirq, |
| + order_base_2(msi->nr_cpus * nr_irqs)); |
| |
| mutex_unlock(&msi->bitmap_lock); |
| |
| -- |
| 2.30.2 |
| |