lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Message-Id: <1193193859.27150.16.camel@sli10-conroe.sh.intel.com>
Date:	Wed, 24 Oct 2007 10:44:19 +0800
From:	Shaohua Li <shaohua.li@...el.com>
To:	linux-pci <linux-pci@...ey.karlin.mff.cuni.cz>,
	lkml <linux-kernel@...r.kernel.org>
Cc:	Greg KH <greg@...ah.com>
Subject: [RFC] pcie port driver: fix something inconsist with spec

The port driver interrupt assignment has two issues for MSI-X:
1. PME and HP share an interrupt, VC hasn't interrupt and only root port and event collector has interrupt for AER.
2. For each capability, its interrupt should be read from specific PCI config register per spec.

This is true for multiple vector MSI, but as we didn't support it so far, I just ignore it.

Note, this is just passed compiling, I can't find a root port which supports MSI-X.

Signed-off-by: Shaohua Li <shaohua.li@...el.com>
---
 drivers/pci/pcie/portdrv_core.c |   70 +++++++++++++++++++++++++++++++++-------
 1 file changed, 58 insertions(+), 12 deletions(-)

Index: linux/drivers/pci/pcie/portdrv_core.c
===================================================================
--- linux.orig/drivers/pci/pcie/portdrv_core.c	2007-10-22 09:41:25.000000000 +0800
+++ linux/drivers/pci/pcie/portdrv_core.c	2007-10-22 14:54:36.000000000 +0800
@@ -128,7 +128,62 @@ static int is_msi_quirked(struct pci_dev
 	}
 	return quirk;
 }
-	
+
+static int assign_msix_interrupt_mode(struct pci_dev *dev, int *vectors, int mask)
+{
+	struct msix_entry msix_entries[2] = {{0, 0}, {0, 1}};
+	int nvec = 0;
+	int status;
+	int pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+	u16 reg;
+	int i;
+
+	pci_read_config_word(dev, pos + PCIE_CAPABILITIES_REG, &reg);
+	/*
+	 * PME and HP share an interrupt, VC hasn't interrupt, so we needs 2
+	 * interrupts at most
+	 */
+	if (mask & (PCIE_PORT_SERVICE_PME|PCIE_PORT_SERVICE_HP))
+		nvec ++;
+	/* root port needs interrupt */
+	if ((mask & PCIE_PORT_SERVICE_AER)
+		 && ((reg >> 4) & PORT_TYPE_MASK) == PCIE_RC_PORT)
+			nvec ++;
+
+	status = pci_enable_msix(dev, msix_entries, nvec);
+	if (status)
+		return status;
+
+	for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) {
+		if (!(mask & (1 << i)))
+			continue;
+		if (mask & (PCIE_PORT_SERVICE_PME|PCIE_PORT_SERVICE_HP)) {
+			u16 reg16;
+
+			pci_read_config_word(dev,
+				pos + PCIE_CAPABILITIES_REG, &reg16);
+			reg16 = (reg16 & PCI_EXP_FLAGS_IRQ) >> 9;
+			BUG_ON(reg16 >= nvec);
+			vectors[i] = msix_entries[reg16].vector;
+			printk("Capability %d uses %d MSI-X entry\n", i, reg16);
+		}
+		if ((mask & PCIE_PORT_SERVICE_AER)
+		   && ((reg >> 4) & PORT_TYPE_MASK) == PCIE_RC_PORT) {
+			u32 reg32;
+			int aer_pos = pci_find_ext_capability(dev,
+				PCI_EXT_CAP_ID_ERR);
+
+			pci_read_config_dword(dev,
+				aer_pos + PCI_ERR_ROOT_STATUS, &reg32);
+			reg32 >>= 27;
+			BUG_ON(reg32 >= nvec);
+			vectors[i] = msix_entries[reg32].vector;
+			printk("Capability %d uses %d MSI-X entry\n", i, reg32);
+		}
+	}
+	return 0;
+}
+
 static int assign_interrupt_mode(struct pci_dev *dev, int *vectors, int mask)
 {
 	int i, pos, nvec, status = -EINVAL;
@@ -148,19 +203,10 @@ static int assign_interrupt_mode(struct 
 	/* Select MSI-X over MSI if supported */		
 	pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
 	if (pos) {
-		struct msix_entry msix_entries[PCIE_PORT_DEVICE_MAXSERVICES] = 
-			{{0, 0}, {0, 1}, {0, 2}, {0, 3}};
 		printk("%s Found MSIX capability\n", __FUNCTION__);
-		status = pci_enable_msix(dev, msix_entries, nvec);
-		if (!status) {
-			int j = 0;
-
+		status = assign_msix_interrupt_mode(dev, vectors, mask);
+		if (!status)
 			interrupt_mode = PCIE_PORT_MSIX_MODE;
-			for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) {
-				if (mask & (1 << i)) 
-					vectors[i] = msix_entries[j++].vector;
-			}
-		}
 	} 
 	if (status) {
 		pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ