mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Shaohua Li <shaohua.li@intel.com>
To: linux-pci <linux-pci@atrey.karlin.mff.cuni.cz>,
	lkml <linux-kernel@vger.kernel.org>
Cc: Greg KH <greg@kroah.com>
Subject: [RFC] pcie port driver: fix something inconsist with spec
Date: Wed, 24 Oct 2007 10:44:19 +0800	[thread overview]
Message-ID: <1193193859.27150.16.camel@sli10-conroe.sh.intel.com> (raw)

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@intel.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);

                 reply	other threads:[~2007-10-24  2:45 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1193193859.27150.16.camel@sli10-conroe.sh.intel.com \
    --to=shaohua.li@intel.com \
    --cc=greg@kroah.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@atrey.karlin.mff.cuni.cz \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®