Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 97ea9d8e authored by Michael S. Tsirkin's avatar Michael S. Tsirkin Committed by Alex Shi
Browse files

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 d5dea7d9 ("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: default avatarMichael S. Tsirkin <mst@redhat.com>
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>

(cherry picked from commit 1851617cd2da9cc53cdc1738f4148f4f042c0e56)
Signed-off-by: default avatarAlex Shi <alex.shi@linaro.org>

Conflicts solution:
	drivers/pci/msi.c /* force remove contents in pci_msi_init_pci_dev */
parent c56c7188
Loading
Loading
Loading
Loading
+0 −12
Original line number Diff line number Diff line
@@ -1036,18 +1036,6 @@ EXPORT_SYMBOL(pci_msi_enabled);
void pci_msi_init_pci_dev(struct pci_dev *dev)
{
	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)
		msi_set_enable(dev, 0);

	dev->msix_cap = pci_find_capability(dev, PCI_CAP_ID_MSIX);
	if (dev->msix_cap)
		msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0);
}

/**
+18 −0
Original line number Diff line number Diff line
@@ -1097,6 +1097,22 @@ int pci_cfg_space_size(struct pci_dev *dev)

#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
 * @dev: the device structure to fill
@@ -1152,6 +1168,8 @@ int pci_setup_device(struct pci_dev *dev)
	/* "Unknown power state" */
	dev->current_state = PCI_UNKNOWN;

	pci_msi_setup_pci_dev(dev);

	/* Early fixups, before probing the BARs */
	pci_fixup_device(pci_fixup_early, dev);
	/* device class may be changed after fixup */