diff --git a/xen/arch/x86/include/asm/msi.h b/xen/arch/x86/include/asm/msi.h index c1ece2786e..997ccb87be 100644 --- a/xen/arch/x86/include/asm/msi.h +++ b/xen/arch/x86/include/asm/msi.h @@ -81,7 +81,8 @@ struct irq_desc; struct hw_interrupt_type; struct msi_desc; /* Helper functions */ -extern int pci_enable_msi(struct msi_info *msi, struct msi_desc **desc); +extern int pci_enable_msi(struct pci_dev *pdev, struct msi_info *msi, + struct msi_desc **desc); extern void pci_disable_msi(struct msi_desc *msi_desc); extern int pci_prepare_msix(u16 seg, u8 bus, u8 devfn, bool off); extern void pci_cleanup_msi(struct pci_dev *pdev); diff --git a/xen/arch/x86/irq.c b/xen/arch/x86/irq.c index 6e668b1b4f..50e49e1a4b 100644 --- a/xen/arch/x86/irq.c +++ b/xen/arch/x86/irq.c @@ -2176,7 +2176,7 @@ int map_domain_pirq( if ( !pdev ) goto done; - ret = pci_enable_msi(msi, &msi_desc); + ret = pci_enable_msi(pdev, msi, &msi_desc); if ( ret ) { if ( ret > 0 ) diff --git a/xen/arch/x86/msi.c b/xen/arch/x86/msi.c index 7f8e794254..335c0868a2 100644 --- a/xen/arch/x86/msi.c +++ b/xen/arch/x86/msi.c @@ -983,13 +983,13 @@ static int msix_capability_init(struct pci_dev *dev, * irq or non-zero for otherwise. **/ -static int __pci_enable_msi(struct msi_info *msi, struct msi_desc **desc) +static int __pci_enable_msi(struct pci_dev *pdev, struct msi_info *msi, + struct msi_desc **desc) { - struct pci_dev *pdev; struct msi_desc *old_desc; ASSERT(pcidevs_locked()); - pdev = pci_get_pdev(NULL, msi->sbdf); + if ( !pdev ) return -ENODEV; @@ -1038,13 +1038,13 @@ static void __pci_disable_msi(struct msi_desc *entry) * of irqs available. Driver should use the returned value to re-send * its request. **/ -static int __pci_enable_msix(struct msi_info *msi, struct msi_desc **desc) +static int __pci_enable_msix(struct pci_dev *pdev, struct msi_info *msi, + struct msi_desc **desc) { - struct pci_dev *pdev; struct msi_desc *old_desc; ASSERT(pcidevs_locked()); - pdev = pci_get_pdev(NULL, msi->sbdf); + if ( !pdev || !pdev->msix ) return -ENODEV; @@ -1151,15 +1151,16 @@ int pci_prepare_msix(u16 seg, u8 bus, u8 devfn, bool off) * Notice: only construct the msi_desc * no change to irq_desc here, and the interrupt is masked */ -int pci_enable_msi(struct msi_info *msi, struct msi_desc **desc) +int pci_enable_msi(struct pci_dev *pdev, struct msi_info *msi, + struct msi_desc **desc) { ASSERT(pcidevs_locked()); if ( !use_msi ) return -EPERM; - return msi->table_base ? __pci_enable_msix(msi, desc) : - __pci_enable_msi(msi, desc); + return msi->table_base ? __pci_enable_msix(pdev, msi, desc) : + __pci_enable_msi(pdev, msi, desc); } /* diff --git a/xen/drivers/char/ns16550.c b/xen/drivers/char/ns16550.c index 29691e8d3a..afe3d514b9 100644 --- a/xen/drivers/char/ns16550.c +++ b/xen/drivers/char/ns16550.c @@ -448,10 +448,13 @@ static void __init cf_check ns16550_init_postirq(struct serial_port *port) if ( rc > 0 ) { struct msi_desc *msi_desc = NULL; + struct pci_dev *pdev; pcidevs_lock(); - rc = pci_enable_msi(&msi, &msi_desc); + pdev = pci_get_pdev(NULL, msi.sbdf); + rc = pdev ? pci_enable_msi(pdev, &msi, &msi_desc) : -ENODEV; + if ( !rc ) { struct irq_desc *desc = irq_to_desc(msi.irq);