aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjoern A. Zeeb <bz@FreeBSD.org>2022-11-28 18:05:48 +0000
committerBjoern A. Zeeb <bz@FreeBSD.org>2023-01-18 13:26:44 +0000
commit3292a54f1ba9ccbc18e15290eb35665dc964b1c3 (patch)
tree6b603d74e2f85c45b6ff7d416a5258af37f7370a
parentb1479a5409cfe186b45322dbed034f024bfc6ed0 (diff)
downloadsrc-3292a54f1ba9ccbc18e15290eb35665dc964b1c3.tar.gz
src-3292a54f1ba9ccbc18e15290eb35665dc964b1c3.zip
LinuxKPI: fix pci_alloc_irq_vectors() for MSI
pci_alloc_irq_vectors() is given a min and max vector value. pci_enable_msi() will always succeed independent of these arguments as it does not know about them. Further it will only ever allocate 1 "vector" not supporting any other amount. So upfront check that (a) the available pci_msi_count() can satisfy the requested minv and (b) given the pci_enable_msi() hard coded limit check that minv is not larger than 1. If we cannot satisfy either requirement return an error. This fixes problems with drivers which check that the returned value of allocated "vectors" will match their requests and only otherwise try to fall back to ask for 1 or deal otherwise. Sponsored by: The FreeBSD Foundation Reviewed by: hselasky (earlier version) Differential Revision: https://reviews.freebsd.org/D37522 (cherry picked from commit e9715b1c4474333ff119aba3a9a74bff91f72372)
-rw-r--r--sys/compat/linuxkpi/common/src/linux_pci.c5
1 files changed, 5 insertions, 0 deletions
diff --git a/sys/compat/linuxkpi/common/src/linux_pci.c b/sys/compat/linuxkpi/common/src/linux_pci.c
index b0820c9b2c3e..a9c859d29623 100644
--- a/sys/compat/linuxkpi/common/src/linux_pci.c
+++ b/sys/compat/linuxkpi/common/src/linux_pci.c
@@ -928,6 +928,11 @@ out:
return (pdev->dev.irq_end - pdev->dev.irq_start);
}
if (flags & PCI_IRQ_MSI) {
+ if (pci_msi_count(pdev->dev.bsddev) < minv)
+ return (-ENOSPC);
+ /* We only support 1 vector in pci_enable_msi() */
+ if (minv != 1)
+ return (-ENOSPC);
error = pci_enable_msi(pdev);
if (error == 0 && pdev->msi_enabled)
return (pdev->dev.irq_end - pdev->dev.irq_start);