提交 e44d8eea 编写于 作者: P Pali Rohár 提交者: Zheng Zengkai

PCI: aardvark: Fix support for MSI interrupts

stable inclusion
from stable-v5.10.111
commit e07e420a00564863b45f88e3bd26860e803d87fe
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I5GL1Z

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=e07e420a00564863b45f88e3bd26860e803d87fe

--------------------------------

[ Upstream commit b0b0b8b8 ]

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/20220110015018.26359-4-kabel@kernel.orgSigned-off-by: NPali Rohár <pali@kernel.org>
Signed-off-by: NMarek Behún <kabel@kernel.org>
Signed-off-by: NLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Signed-off-by: NSasha Levin <sashal@kernel.org>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
Reviewed-by: NWei Li <liwei391@huawei.com>
上级 1f1b4f34
...@@ -1186,7 +1186,7 @@ static void advk_msi_irq_compose_msi_msg(struct irq_data *data, ...@@ -1186,7 +1186,7 @@ static void advk_msi_irq_compose_msi_msg(struct irq_data *data,
msg->address_lo = lower_32_bits(msi_msg); msg->address_lo = lower_32_bits(msi_msg);
msg->address_hi = upper_32_bits(msi_msg); msg->address_hi = upper_32_bits(msi_msg);
msg->data = data->irq; msg->data = data->hwirq;
} }
static int advk_msi_set_affinity(struct irq_data *irq_data, static int advk_msi_set_affinity(struct irq_data *irq_data,
...@@ -1203,15 +1203,11 @@ static int advk_msi_irq_domain_alloc(struct irq_domain *domain, ...@@ -1203,15 +1203,11 @@ static int advk_msi_irq_domain_alloc(struct irq_domain *domain,
int hwirq, i; int hwirq, i;
mutex_lock(&pcie->msi_used_lock); mutex_lock(&pcie->msi_used_lock);
hwirq = bitmap_find_next_zero_area(pcie->msi_used, MSI_IRQ_NUM, hwirq = bitmap_find_free_region(pcie->msi_used, MSI_IRQ_NUM,
0, nr_irqs, 0); order_base_2(nr_irqs));
if (hwirq >= MSI_IRQ_NUM) {
mutex_unlock(&pcie->msi_used_lock); mutex_unlock(&pcie->msi_used_lock);
if (hwirq < 0)
return -ENOSPC; return -ENOSPC;
}
bitmap_set(pcie->msi_used, hwirq, nr_irqs);
mutex_unlock(&pcie->msi_used_lock);
for (i = 0; i < nr_irqs; i++) for (i = 0; i < nr_irqs; i++)
irq_domain_set_info(domain, virq + i, hwirq + i, irq_domain_set_info(domain, virq + i, hwirq + i,
...@@ -1229,7 +1225,7 @@ static void advk_msi_irq_domain_free(struct irq_domain *domain, ...@@ -1229,7 +1225,7 @@ static void advk_msi_irq_domain_free(struct irq_domain *domain,
struct advk_pcie *pcie = domain->host_data; struct advk_pcie *pcie = domain->host_data;
mutex_lock(&pcie->msi_used_lock); mutex_lock(&pcie->msi_used_lock);
bitmap_clear(pcie->msi_used, d->hwirq, nr_irqs); bitmap_release_region(pcie->msi_used, d->hwirq, order_base_2(nr_irqs));
mutex_unlock(&pcie->msi_used_lock); mutex_unlock(&pcie->msi_used_lock);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册