Index: sys/compat/linuxkpi/common/include/linux/device.h =================================================================== --- sys/compat/linuxkpi/common/include/linux/device.h +++ sys/compat/linuxkpi/common/include/linux/device.h @@ -110,6 +110,7 @@ void *driver_data; unsigned int irq; #define LINUX_IRQ_INVALID 65535 + bool msi; unsigned int msix; unsigned int msix_max; const struct attribute_group **groups; Index: sys/compat/linuxkpi/common/include/linux/interrupt.h =================================================================== --- sys/compat/linuxkpi/common/include/linux/interrupt.h +++ sys/compat/linuxkpi/common/include/linux/interrupt.h @@ -55,6 +55,8 @@ static inline int linux_irq_rid(struct device *dev, unsigned int irq) { + if (dev->msi) + return (1); if (irq == dev->irq) return (0); return irq - dev->msix + 1; Index: sys/compat/linuxkpi/common/include/linux/pci.h =================================================================== --- sys/compat/linuxkpi/common/include/linux/pci.h +++ sys/compat/linuxkpi/common/include/linux/pci.h @@ -227,6 +227,7 @@ unsigned int devfn; uint32_t class; uint8_t revision; + bool msi_enabled; }; static inline struct resource_list_entry * @@ -447,6 +448,19 @@ pdev->dev.msix_max = 0; } +#define pci_disable_msi(pdev) \ + linux_pci_disable_msi(pdev) + +static inline void +linux_pci_disable_msi(struct pci_dev *pdev) +{ + + pci_release_msi(pdev->dev.bsddev); + pdev->dev.msi = false; + pdev->msi_enabled = false; +} + + static inline bus_addr_t pci_bus_address(struct pci_dev *pdev, int bar) { @@ -611,6 +625,32 @@ return (nvec); } +#define pci_enable_msi(pdev) \ + linux_pci_enable_msi(pdev) + +static inline int +pci_enable_msi(struct pci_dev *pdev) +{ + struct resource_list_entry *rle; + int error; + int avail; + + avail = pci_msi_count(pdev->dev.bsddev); + if (avail < 1) { + return -EINVAL; + } + avail = 1; + if ((error = -pci_alloc_msi(pdev->dev.bsddev, &avail)) != 0) { + return error; + } + rle = linux_pci_get_rle(pdev, SYS_RES_IRQ, 1); + pdev->dev.msi = true; + pdev->dev.irq = rle->start; + pdev->irq = rle->start; + pdev->msi_enabled = true; + return (0); +} + static inline int pci_channel_offline(struct pci_dev *pdev) { Index: sys/compat/linuxkpi/common/src/linux_pci.c =================================================================== --- sys/compat/linuxkpi/common/src/linux_pci.c +++ sys/compat/linuxkpi/common/src/linux_pci.c @@ -247,6 +247,7 @@ else pdev->dev.irq = LINUX_IRQ_INVALID; pdev->irq = pdev->dev.irq; + pdev->msi_enabled = false; error = linux_pdev_dma_init(pdev); if (error) goto out_dma_init;