All of lore.kernel.org
 help / color / mirror / Atom feed
From: Prarit Bhargava <prarit@redhat.com>
To: Matthew Wilcox <matthew@wil.cx>
Cc: Don Dutile <ddutile@redhat.com>,
	Bjorn Helgaas <bhelgaas@google.com>,
	James Paradis <jparadis@redhat.com>,
	linux-pci@vger.kernel.org, mstowe@redhat.com,
	jbarnes@virtuousgeek.org
Subject: Re: [PATCH] pci: Workaround Stratus broken PCIE hierarchy
Date: Wed, 16 Nov 2011 19:18:41 -0500	[thread overview]
Message-ID: <4EC452E1.9010601@redhat.com> (raw)
In-Reply-To: <4EC3EA8B.6030108@redhat.com>


[v2]
- ddutile@redhat.com requested drivers/pci/quirks.c code
- matthew@wil.cx requested that dmi_name_in_vendors() be called only once with a static var check
- added a kernel parameter to enable scanning of all PCIE devices.

[v3]
- matthew@wil.cx requested a clean up of is_broken_pcie_port(
- eike-kernel@sf-tec.de requested a clean up of the printk level and message

[v4]
- ddutile pointed out a logic error in is_broken_pcie_port.  It was no longer
being called only once on failure.

----8<----

pci: Workaround Stratus broken PCIE hierarchy

Stratus systems have a hierarchy that includes a PCIE Downstream bridge
connected to a PCIE Upstream bridge and a PCI Downstream bridge.  The system
boots with this wrong hierarchy into a crippled mode (USB doesn't work,
network doesn't work ...).  Avoiding the Downstream bridge check in
only_one_child() causes all the bridges to be enumerated and the system
to function properly.

Unfortunately this hardware is currently available so we should at least
keep it functional.

Signed-off-by: Prarit Bhargava <prarit@redhat.com>

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index a0c5c5f..7af458f 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -2069,6 +2069,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 				on: Turn ECRC on.
 		realloc		reallocate PCI resources if allocations done by BIOS
 				are erroneous.
+		pcie_scan_all	Scan all possible PCIE devices.
 
 	pcie_aspm=	[PCIE] Forcibly enable or disable PCIe Active State Power
 			Management.
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 6f45a73..8c96fff 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -3589,6 +3589,9 @@ static int __init pci_setup(char *str)
 				pcie_bus_config = PCIE_BUS_PERFORMANCE;
 			} else if (!strncmp(str, "pcie_bus_peer2peer", 18)) {
 				pcie_bus_config = PCIE_BUS_PEER2PEER;
+			} else if (!strncmp(str, "pcie_scan_all", 13)) {
+				printk(KERN_INFO HW_ERR "PCIE: User request scan of all PCIE devices.  Your PCIE hardware is broken if you require this to boot.\n");
+				pcie_scan_all = 1;
 			} else {
 				printk(KERN_ERR "PCI: Unknown option `%s'\n",
 						str);
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index b74084e..5a07895 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -309,11 +309,16 @@ struct pci_dev_reset_methods {
 
 #ifdef CONFIG_PCI_QUIRKS
 extern int pci_dev_specific_reset(struct pci_dev *dev, int probe);
+extern int is_broken_pcie_port(void);
 #else
 static inline int pci_dev_specific_reset(struct pci_dev *dev, int probe)
 {
 	return -ENOTTY;
 }
+static inline int is_broken_pcie_port(void)
+{
+	return 0;
+}
 #endif
 
 #endif /* DRIVERS_PCI_H */
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 04e74f4..fc88a9b 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1270,13 +1270,18 @@ static unsigned no_next_fn(struct pci_dev *dev, unsigned fn)
 	return 0;
 }
 
+int pcie_scan_all = 0; /* set via pci=pcie_scan_all */
 static int only_one_child(struct pci_bus *bus)
 {
 	struct pci_dev *parent = bus->self;
+	if (pcie_scan_all)
+		return 0;
 	if (!parent || !pci_is_pcie(parent))
 		return 0;
-	if (parent->pcie_type == PCI_EXP_TYPE_ROOT_PORT ||
-	    parent->pcie_type == PCI_EXP_TYPE_DOWNSTREAM)
+	if (parent->pcie_type == PCI_EXP_TYPE_ROOT_PORT)
+		return 1;
+	if (parent->pcie_type == PCI_EXP_TYPE_DOWNSTREAM &&
+	    !is_broken_pcie_port())
 		return 1;
 	return 0;
 }
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 7285145..6c9f72b 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -3092,3 +3092,21 @@ int pci_dev_specific_reset(struct pci_dev *dev, int probe)
 
 	return -ENOTTY;
 }
+
+static int is_broken_pcie_port_called;
+int is_broken_pcie_port(void)
+{
+	if (is_broken_pcie_port_called)
+		return pcie_scan_all;
+	/*
+	 * Stratus/NEC ftServer systems have a broken PCIE hierarchy in which
+	 * one upstream and one downstream port are plugged into a downstream
+	 * port.  Avoiding the downstream port check in only_one_child() results
+	 * in a functional system.
+	 */
+	if (dmi_name_in_vendors("ftServer"))
+		pcie_scan_all = 1;
+
+	is_broken_pcie_port_called = 1;
+	return pcie_scan_all;
+}
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 337df0d..745b98e 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1647,5 +1647,7 @@ static inline void pci_release_bus_of_node(struct pci_bus *bus) { }
  */
 struct pci_dev *pci_find_upstream_pcie_bridge(struct pci_dev *pdev);
 
+/* set via pci=pcie_scan_all in order to enumerate all possible PCIE busses */
+extern int pcie_scan_all;
 #endif /* __KERNEL__ */
 #endif /* LINUX_PCI_H */

  reply	other threads:[~2011-11-17  0:19 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-11-10 14:00 [PATCH] pci: Workaround Stratus broken PCIE hierarchy Prarit Bhargava
2011-11-10 14:31 ` Matthew Wilcox
2011-11-10 16:50   ` Don Dutile
2011-11-11 17:41     ` James Paradis
2011-11-11 19:13       ` Don Dutile
2011-11-11 20:29         ` Bjorn Helgaas
2011-11-11 20:35           ` Don Dutile
2011-11-14 14:44             ` Prarit Bhargava
2011-11-14 18:14               ` Matthew Wilcox
2011-11-14 19:50                 ` Prarit Bhargava
2011-11-15 20:16                   ` Matthew Wilcox
2011-11-15 15:56                 ` Prarit Bhargava
2011-11-15 16:08                   ` Rolf Eike Beer
2011-11-15 18:14                     ` Bjorn Helgaas
2011-11-15 18:25                       ` Prarit Bhargava
2011-11-15 21:08                         ` James Paradis
2011-11-15 21:52                           ` Myron Stowe
2011-11-15 22:14                             ` James Paradis
2011-11-15 20:15                   ` Matthew Wilcox
2011-11-16 16:53                     ` Prarit Bhargava
2011-11-17  0:18                       ` Prarit Bhargava [this message]
2011-11-15 21:53                   ` James Paradis
2011-11-15 22:27           ` James Paradis
2011-11-15 23:07             ` Don Dutile
  -- strict thread matches above, loose matches on Subject: below --
2012-04-25 17:56 Prarit Bhargava
2012-04-25 23:35 ` Bjorn Helgaas

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=4EC452E1.9010601@redhat.com \
    --to=prarit@redhat.com \
    --cc=bhelgaas@google.com \
    --cc=ddutile@redhat.com \
    --cc=jbarnes@virtuousgeek.org \
    --cc=jparadis@redhat.com \
    --cc=linux-pci@vger.kernel.org \
    --cc=matthew@wil.cx \
    --cc=mstowe@redhat.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.