850-0003-PCI-aardvark-Fix-support-for-MSI-interrupts.patch 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. From bb03b126ea6c9e57177b537dd022246fa5dbef16 Mon Sep 17 00:00:00 2001
  2. From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <[email protected]>
  3. Date: Fri, 12 Feb 2021 16:24:07 +0100
  4. Subject: [PATCH] PCI: aardvark: Fix support for MSI interrupts
  5. MIME-Version: 1.0
  6. Content-Type: text/plain; charset=UTF-8
  7. Content-Transfer-Encoding: 8bit
  8. Aardvark hardware supports Multi-MSI and MSI_FLAG_MULTI_PCI_MSI is already
  9. set for the MSI chip. But when allocating MSI interrupt numbers for
  10. Multi-MSI, the numbers need to be properly aligned, otherwise endpoint
  11. devices send MSI interrupt with incorrect numbers.
  12. Fix this issue by using function bitmap_find_free_region() instead of
  13. bitmap_find_next_zero_area().
  14. To ensure that aligned MSI interrupt numbers are used by endpoint devices,
  15. we cannot use Linux virtual irq numbers (as they are random and not
  16. properly aligned). Instead we need to use the aligned hwirq numbers.
  17. This change fixes receiving MSI interrupts on Armada 3720 boards and
  18. allows using NVMe disks which use Multi-MSI feature with 3 interrupts.
  19. Without this NVMe disks freeze booting as linux nvme-core.c is waiting
  20. 60s for an interrupt.
  21. Signed-off-by: Pali Rohár <[email protected]>
  22. Signed-off-by: Marek Behún <[email protected]>
  23. ---
  24. drivers/pci/controller/pci-aardvark.c | 16 ++++++----------
  25. 1 file changed, 6 insertions(+), 10 deletions(-)
  26. --- a/drivers/pci/controller/pci-aardvark.c
  27. +++ b/drivers/pci/controller/pci-aardvark.c
  28. @@ -1184,7 +1184,7 @@ static void advk_msi_irq_compose_msi_msg
  29. msg->address_lo = lower_32_bits(msi_msg);
  30. msg->address_hi = upper_32_bits(msi_msg);
  31. - msg->data = data->irq;
  32. + msg->data = data->hwirq;
  33. }
  34. static int advk_msi_set_affinity(struct irq_data *irq_data,
  35. @@ -1201,15 +1201,11 @@ static int advk_msi_irq_domain_alloc(str
  36. int hwirq, i;
  37. mutex_lock(&pcie->msi_used_lock);
  38. - hwirq = bitmap_find_next_zero_area(pcie->msi_used, MSI_IRQ_NUM,
  39. - 0, nr_irqs, 0);
  40. - if (hwirq >= MSI_IRQ_NUM) {
  41. - mutex_unlock(&pcie->msi_used_lock);
  42. - return -ENOSPC;
  43. - }
  44. -
  45. - bitmap_set(pcie->msi_used, hwirq, nr_irqs);
  46. + hwirq = bitmap_find_free_region(pcie->msi_used, MSI_IRQ_NUM,
  47. + order_base_2(nr_irqs));
  48. mutex_unlock(&pcie->msi_used_lock);
  49. + if (hwirq < 0)
  50. + return -ENOSPC;
  51. for (i = 0; i < nr_irqs; i++)
  52. irq_domain_set_info(domain, virq + i, hwirq + i,
  53. @@ -1227,7 +1223,7 @@ static void advk_msi_irq_domain_free(str
  54. struct advk_pcie *pcie = domain->host_data;
  55. mutex_lock(&pcie->msi_used_lock);
  56. - bitmap_clear(pcie->msi_used, d->hwirq, nr_irqs);
  57. + bitmap_release_region(pcie->msi_used, d->hwirq, order_base_2(nr_irqs));
  58. mutex_unlock(&pcie->msi_used_lock);
  59. }