Skip to content

Commit 60eabd6

Browse files
paligregkh
authored andcommitted
PCI: aardvark: Fix support for MSI interrupts
[ Upstream commit b0b0b8b ] Aardvark hardware supports Multi-MSI and MSI_FLAG_MULTI_PCI_MSI is already set for the MSI chip. But when allocating MSI interrupt numbers for Multi-MSI, the numbers need to be properly aligned, otherwise endpoint devices send MSI interrupt with incorrect numbers. Fix this issue by using function bitmap_find_free_region() instead of bitmap_find_next_zero_area(). To ensure that aligned MSI interrupt numbers are used by endpoint devices, we cannot use Linux virtual irq numbers (as they are random and not properly aligned). Instead we need to use the aligned hwirq numbers. This change fixes receiving MSI interrupts on Armada 3720 boards and allows using NVMe disks which use Multi-MSI feature with 3 interrupts. Without this NVMe disks freeze booting as linux nvme-core.c is waiting 60s for an interrupt. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Pali Rohár <[email protected]> Signed-off-by: Marek Behún <[email protected]> Signed-off-by: Lorenzo Pieralisi <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent 330c4e1 commit 60eabd6

File tree

1 file changed

+6
-10
lines changed

1 file changed

+6
-10
lines changed

drivers/pci/controller/pci-aardvark.c

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1179,7 +1179,7 @@ static void advk_msi_irq_compose_msi_msg(struct irq_data *data,
11791179

11801180
msg->address_lo = lower_32_bits(msi_msg);
11811181
msg->address_hi = upper_32_bits(msi_msg);
1182-
msg->data = data->irq;
1182+
msg->data = data->hwirq;
11831183
}
11841184

11851185
static int advk_msi_set_affinity(struct irq_data *irq_data,
@@ -1196,15 +1196,11 @@ static int advk_msi_irq_domain_alloc(struct irq_domain *domain,
11961196
int hwirq, i;
11971197

11981198
mutex_lock(&pcie->msi_used_lock);
1199-
hwirq = bitmap_find_next_zero_area(pcie->msi_used, MSI_IRQ_NUM,
1200-
0, nr_irqs, 0);
1201-
if (hwirq >= MSI_IRQ_NUM) {
1202-
mutex_unlock(&pcie->msi_used_lock);
1203-
return -ENOSPC;
1204-
}
1205-
1206-
bitmap_set(pcie->msi_used, hwirq, nr_irqs);
1199+
hwirq = bitmap_find_free_region(pcie->msi_used, MSI_IRQ_NUM,
1200+
order_base_2(nr_irqs));
12071201
mutex_unlock(&pcie->msi_used_lock);
1202+
if (hwirq < 0)
1203+
return -ENOSPC;
12081204

12091205
for (i = 0; i < nr_irqs; i++)
12101206
irq_domain_set_info(domain, virq + i, hwirq + i,
@@ -1222,7 +1218,7 @@ static void advk_msi_irq_domain_free(struct irq_domain *domain,
12221218
struct advk_pcie *pcie = domain->host_data;
12231219

12241220
mutex_lock(&pcie->msi_used_lock);
1225-
bitmap_clear(pcie->msi_used, d->hwirq, nr_irqs);
1221+
bitmap_release_region(pcie->msi_used, d->hwirq, order_base_2(nr_irqs));
12261222
mutex_unlock(&pcie->msi_used_lock);
12271223
}
12281224

0 commit comments

Comments
 (0)