PCI/MSI: Disable MSI at enumeration even if kernel doesn't support MSI
If we enable MSI, then kexec a new kernel, the new kernel may receive MSIs
it is not prepared for. Commit d5dea7d95c
("PCI: msi: Disable msi
interrupts when we initialize a pci device") prevents this, but only if the
new kernel is built with CONFIG_PCI_MSI=y.
Move the "disable MSI" functionality from drivers/pci/msi.c to a new
pci_msi_setup_pci_dev() in drivers/pci/probe.c so we can disable MSIs when
we enumerate devices even if the kernel doesn't include full MSI support.
[bhelgaas: changelog, disable MSIs in pci_setup_device(), put
pci_msi_setup_pci_dev() at its final destination]
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
This commit is contained in:
parent
6a25f5e35a
commit
1851617cd2
|
@ -1041,18 +1041,6 @@ EXPORT_SYMBOL(pci_msi_enabled);
|
||||||
void pci_msi_init_pci_dev(struct pci_dev *dev)
|
void pci_msi_init_pci_dev(struct pci_dev *dev)
|
||||||
{
|
{
|
||||||
INIT_LIST_HEAD(&dev->msi_list);
|
INIT_LIST_HEAD(&dev->msi_list);
|
||||||
|
|
||||||
/* Disable the msi hardware to avoid screaming interrupts
|
|
||||||
* during boot. This is the power on reset default so
|
|
||||||
* usually this should be a noop.
|
|
||||||
*/
|
|
||||||
dev->msi_cap = pci_find_capability(dev, PCI_CAP_ID_MSI);
|
|
||||||
if (dev->msi_cap)
|
|
||||||
pci_msi_set_enable(dev, 0);
|
|
||||||
|
|
||||||
dev->msix_cap = pci_find_capability(dev, PCI_CAP_ID_MSIX);
|
|
||||||
if (dev->msix_cap)
|
|
||||||
pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1085,6 +1085,22 @@ int pci_cfg_space_size(struct pci_dev *dev)
|
||||||
|
|
||||||
#define LEGACY_IO_RESOURCE (IORESOURCE_IO | IORESOURCE_PCI_FIXED)
|
#define LEGACY_IO_RESOURCE (IORESOURCE_IO | IORESOURCE_PCI_FIXED)
|
||||||
|
|
||||||
|
static void pci_msi_setup_pci_dev(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Disable the MSI hardware to avoid screaming interrupts
|
||||||
|
* during boot. This is the power on reset default so
|
||||||
|
* usually this should be a noop.
|
||||||
|
*/
|
||||||
|
dev->msi_cap = pci_find_capability(dev, PCI_CAP_ID_MSI);
|
||||||
|
if (dev->msi_cap)
|
||||||
|
pci_msi_set_enable(dev, 0);
|
||||||
|
|
||||||
|
dev->msix_cap = pci_find_capability(dev, PCI_CAP_ID_MSIX);
|
||||||
|
if (dev->msix_cap)
|
||||||
|
pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pci_setup_device - fill in class and map information of a device
|
* pci_setup_device - fill in class and map information of a device
|
||||||
* @dev: the device structure to fill
|
* @dev: the device structure to fill
|
||||||
|
@ -1140,6 +1156,8 @@ int pci_setup_device(struct pci_dev *dev)
|
||||||
/* "Unknown power state" */
|
/* "Unknown power state" */
|
||||||
dev->current_state = PCI_UNKNOWN;
|
dev->current_state = PCI_UNKNOWN;
|
||||||
|
|
||||||
|
pci_msi_setup_pci_dev(dev);
|
||||||
|
|
||||||
/* Early fixups, before probing the BARs */
|
/* Early fixups, before probing the BARs */
|
||||||
pci_fixup_device(pci_fixup_early, dev);
|
pci_fixup_device(pci_fixup_early, dev);
|
||||||
/* device class may be changed after fixup */
|
/* device class may be changed after fixup */
|
||||||
|
|
Loading…
Reference in New Issue