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

Commit e375b561 authored by Gavin Shan's avatar Gavin Shan Committed by Bjorn Helgaas
Browse files

PCI: Cache MSI/MSI-X capability offsets in struct pci_dev



The patch caches the MSI and MSI-X capability offset in PCI device
(struct pci_dev) so that we needn't read it from the config space
upon enabling or disabling MSI or MSI-X interrupts.

[bhelgaas: moved pm_cap size change to separate patch]
Signed-off-by: default avatarGavin Shan <shangw@linux.vnet.ibm.com>
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
parent 703860ed
Loading
Loading
Loading
Loading
+19 −23
Original line number Diff line number Diff line
@@ -111,32 +111,26 @@ void default_restore_msi_irqs(struct pci_dev *dev, int irq)
}
#endif

static void msi_set_enable(struct pci_dev *dev, int pos, int enable)
static void msi_set_enable(struct pci_dev *dev, int enable)
{
	u16 control;

	BUG_ON(!pos);

	pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control);
	pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control);
	control &= ~PCI_MSI_FLAGS_ENABLE;
	if (enable)
		control |= PCI_MSI_FLAGS_ENABLE;
	pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control);
	pci_write_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, control);
}

static void msix_set_enable(struct pci_dev *dev, int enable)
{
	int pos;
	u16 control;

	pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
	if (pos) {
		pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control);
	pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control);
	control &= ~PCI_MSIX_FLAGS_ENABLE;
	if (enable)
		control |= PCI_MSIX_FLAGS_ENABLE;
		pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
	}
	pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control);
}

static inline __attribute_const__ u32 msi_mask(unsigned x)
@@ -402,7 +396,7 @@ static void __pci_restore_msi_state(struct pci_dev *dev)
	pos = entry->msi_attrib.pos;

	pci_intx_for_msi(dev, 0);
	msi_set_enable(dev, pos, 0);
	msi_set_enable(dev, 0);
	arch_restore_msi_irqs(dev, dev->irq);

	pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control);
@@ -557,7 +551,7 @@ static int msi_capability_init(struct pci_dev *dev, int nvec)
	unsigned mask;

	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
	msi_set_enable(dev, pos, 0);	/* Disable MSI during set up */
	msi_set_enable(dev, 0);	/* Disable MSI during set up */

	pci_read_config_word(dev, msi_control_reg(pos), &control);
	/* MSI Entry Initialization */
@@ -598,7 +592,7 @@ static int msi_capability_init(struct pci_dev *dev, int nvec)

	/* Set MSI enabled bits	 */
	pci_intx_for_msi(dev, 0);
	msi_set_enable(dev, pos, 1);
	msi_set_enable(dev, 1);
	dev->msi_enabled = 1;

	dev->irq = entry->irq;
@@ -885,7 +879,7 @@ void pci_msi_shutdown(struct pci_dev *dev)
	desc = list_first_entry(&dev->msi_list, struct msi_desc, list);
	pos = desc->msi_attrib.pos;

	msi_set_enable(dev, pos, 0);
	msi_set_enable(dev, 0);
	pci_intx_for_msi(dev, 1);
	dev->msi_enabled = 0;

@@ -1048,15 +1042,17 @@ EXPORT_SYMBOL(pci_msi_enabled);

void pci_msi_init_pci_dev(struct pci_dev *dev)
{
	int pos;
	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.
	 */
	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
	if (pos)
		msi_set_enable(dev, pos, 0);
	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_set_enable(dev, 0);
}
+2 −0
Original line number Diff line number Diff line
@@ -232,6 +232,8 @@ struct pci_dev {
	u8		revision;	/* PCI revision, low byte of class word */
	u8		hdr_type;	/* PCI header type (`multi' flag masked out) */
	u8		pcie_cap;	/* PCI-E capability offset */
	u8		msi_cap;	/* MSI capability offset */
	u8		msix_cap;	/* MSI-X capability offset */
	u8		pcie_mpss:3;	/* PCI-E Max Payload Size Supported */
	u8		rom_base_reg;	/* which config register controls the ROM */
	u8		pin;  		/* which interrupt pin this device uses */