All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jayachandran C <jchandra@broadcom.com>
To: linux-pci@vger.kernel.org, Bjorn Helgaas <bhelgaas@google.com>,
	linux-acpi@vger.kernel.org, Arnd Bergmann <arnd@arndb.de>,
	linux-arm-kernel@lists.infradead.org,
	"Rafael J. Wysocki" <rjw@rjwysocki.net>
Cc: Jayachandran C <jchandra@broadcom.com>,
	Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>,
	Tomasz Nowicki <tn@semihalf.com>,
	xen-devel@lists.xenproject.org
Subject: [PATCH v6 2/5] PCI: Handle ACPI companion and domain number
Date: Thu, 14 Jan 2016 13:02:38 +0530	[thread overview]
Message-ID: <1452756761-29584-3-git-send-email-jchandra@broadcom.com> (raw)
In-Reply-To: <1452756761-29584-1-git-send-email-jchandra@broadcom.com>

pci_create_root_bus is called with NULL as parent in ACPI. This
ends up calling pci_bus_assign_domain_nr with a NULL parent, which
crashes when dereferencing parent.

Fix this by providing a way to set the ACPI domain number and ACPI
companion in PCI code. We define pci_acpi_set_companion() to set
the ACPI companion pointer and acpi_pci_get_segment() and to get
the PCI domain number. This is just defined for the generic ACPI
PCI controller, using the corresponding sysdata.

pci_bus_assign_domain_nr is updated to call acpi_pci_get_segment()
to get the domain number to set on the root bus, in case of ACPI.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 drivers/pci/pci.c        | 15 ++++++++++++++-
 drivers/pci/probe.c      |  2 ++
 include/linux/pci-acpi.h | 28 +++++++++++++++++++++++++++-
 3 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 314db8c..39d2bcc 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -20,6 +20,7 @@
 #include <linux/string.h>
 #include <linux/log2.h>
 #include <linux/pci-aspm.h>
+#include <linux/pci-acpi.h>
 #include <linux/pm_wakeup.h>
 #include <linux/interrupt.h>
 #include <linux/device.h>
@@ -4772,9 +4773,21 @@ int pci_get_new_domain_nr(void)
 void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent)
 {
 	static int use_dt_domains = -1;
-	int domain = of_get_pci_domain_nr(parent->of_node);
+	int domain;
 
 	/*
+	 * Handle ACPI early
+	 *
+	 * The companion is not set at this point, and ACPI sets parent to
+	 * NULL, we have to try to get the segment from acpi root info.
+	 */
+	if (!parent || !parent->of_node) {
+		bus->domain_nr = acpi_pci_get_segment(bus->sysdata);
+		return;
+	}
+
+	domain = of_get_pci_domain_nr(parent->of_node);
+	/*
 	 * Check DT domain and use_dt_domains values.
 	 *
 	 * If DT domain property is valid (domain >= 0) and
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index edb1984..5af66496 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/cpumask.h>
 #include <linux/pci-aspm.h>
+#include <linux/pci-acpi.h>
 #include <linux/aer.h>
 #include <linux/acpi.h>
 #include <asm-generic/pci-bridge.h>
@@ -2105,6 +2106,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
 	bridge->dev.parent = parent;
 	bridge->dev.release = pci_release_host_bridge_dev;
 	dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
+	pci_acpi_set_companion(bridge);
 	error = pcibios_root_bridge_prepare(bridge);
 	if (error) {
 		kfree(bridge);
diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
index e9450ef..f8d62e3 100644
--- a/include/linux/pci-acpi.h
+++ b/include/linux/pci-acpi.h
@@ -138,12 +138,38 @@ extern struct list_head pci_mmcfg_list;
 
 #define PCI_MMCFG_BUS_OFFSET(bus)      ((bus) << 20)
 #define PCI_MMCFG_OFFSET(bus, devfn)   ((bus) << 20 | (devfn) << 12)
-
 #else	/* CONFIG_ACPI */
 static inline void acpi_pci_add_bus(struct pci_bus *bus) { }
 static inline void acpi_pci_remove_bus(struct pci_bus *bus) { }
 #endif	/* CONFIG_ACPI */
 
+#if defined(CONFIG_ACPI) && defined(CONFIG_ACPI_PCI_HOST_GENERIC)
+static inline void pci_acpi_set_companion(struct pci_host_bridge *bridge)
+{
+	struct pci_bus *b = bridge->bus;
+	struct acpi_pci_root_info *ci = (struct acpi_pci_root_info *)b->sysdata;
+
+	ACPI_COMPANION_SET(&bridge->dev, ci->bridge);
+}
+
+static inline u16 acpi_pci_get_segment(void *sysdata)
+{
+	struct acpi_pci_root_info *ci = (struct acpi_pci_root_info *)sysdata;
+
+	return ci->root->segment;
+}
+#else
+static inline void pci_acpi_set_companion(struct pci_host_bridge *bridge)
+{
+	/* leave it to the platform for now */
+}
+
+static inline u16 acpi_pci_get_segment(void *sysdata)
+{
+	return 0;
+}
+#endif
+
 #ifdef CONFIG_ACPI_APEI
 extern bool aer_acpi_firmware_first(void);
 #else
-- 
1.9.1


WARNING: multiple messages have this Message-ID (diff)
From: Jayachandran C <jchandra@broadcom.com>
To: <linux-pci@vger.kernel.org>, Bjorn Helgaas <bhelgaas@google.com>,
	<linux-acpi@vger.kernel.org>, Arnd Bergmann <arnd@arndb.de>,
	<linux-arm-kernel@lists.infradead.org>,
	"Rafael J. Wysocki" <rjw@rjwysocki.net>
Cc: Jayachandran C <jchandra@broadcom.com>,
	Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>,
	Tomasz Nowicki <tn@semihalf.com>,
	<xen-devel@lists.xenproject.org>
Subject: [PATCH v6 2/5] PCI: Handle ACPI companion and domain number
Date: Thu, 14 Jan 2016 13:02:38 +0530	[thread overview]
Message-ID: <1452756761-29584-3-git-send-email-jchandra@broadcom.com> (raw)
In-Reply-To: <1452756761-29584-1-git-send-email-jchandra@broadcom.com>

pci_create_root_bus is called with NULL as parent in ACPI. This
ends up calling pci_bus_assign_domain_nr with a NULL parent, which
crashes when dereferencing parent.

Fix this by providing a way to set the ACPI domain number and ACPI
companion in PCI code. We define pci_acpi_set_companion() to set
the ACPI companion pointer and acpi_pci_get_segment() and to get
the PCI domain number. This is just defined for the generic ACPI
PCI controller, using the corresponding sysdata.

pci_bus_assign_domain_nr is updated to call acpi_pci_get_segment()
to get the domain number to set on the root bus, in case of ACPI.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 drivers/pci/pci.c        | 15 ++++++++++++++-
 drivers/pci/probe.c      |  2 ++
 include/linux/pci-acpi.h | 28 +++++++++++++++++++++++++++-
 3 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 314db8c..39d2bcc 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -20,6 +20,7 @@
 #include <linux/string.h>
 #include <linux/log2.h>
 #include <linux/pci-aspm.h>
+#include <linux/pci-acpi.h>
 #include <linux/pm_wakeup.h>
 #include <linux/interrupt.h>
 #include <linux/device.h>
@@ -4772,9 +4773,21 @@ int pci_get_new_domain_nr(void)
 void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent)
 {
 	static int use_dt_domains = -1;
-	int domain = of_get_pci_domain_nr(parent->of_node);
+	int domain;
 
 	/*
+	 * Handle ACPI early
+	 *
+	 * The companion is not set at this point, and ACPI sets parent to
+	 * NULL, we have to try to get the segment from acpi root info.
+	 */
+	if (!parent || !parent->of_node) {
+		bus->domain_nr = acpi_pci_get_segment(bus->sysdata);
+		return;
+	}
+
+	domain = of_get_pci_domain_nr(parent->of_node);
+	/*
 	 * Check DT domain and use_dt_domains values.
 	 *
 	 * If DT domain property is valid (domain >= 0) and
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index edb1984..5af66496 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/cpumask.h>
 #include <linux/pci-aspm.h>
+#include <linux/pci-acpi.h>
 #include <linux/aer.h>
 #include <linux/acpi.h>
 #include <asm-generic/pci-bridge.h>
@@ -2105,6 +2106,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
 	bridge->dev.parent = parent;
 	bridge->dev.release = pci_release_host_bridge_dev;
 	dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
+	pci_acpi_set_companion(bridge);
 	error = pcibios_root_bridge_prepare(bridge);
 	if (error) {
 		kfree(bridge);
diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
index e9450ef..f8d62e3 100644
--- a/include/linux/pci-acpi.h
+++ b/include/linux/pci-acpi.h
@@ -138,12 +138,38 @@ extern struct list_head pci_mmcfg_list;
 
 #define PCI_MMCFG_BUS_OFFSET(bus)      ((bus) << 20)
 #define PCI_MMCFG_OFFSET(bus, devfn)   ((bus) << 20 | (devfn) << 12)
-
 #else	/* CONFIG_ACPI */
 static inline void acpi_pci_add_bus(struct pci_bus *bus) { }
 static inline void acpi_pci_remove_bus(struct pci_bus *bus) { }
 #endif	/* CONFIG_ACPI */
 
+#if defined(CONFIG_ACPI) && defined(CONFIG_ACPI_PCI_HOST_GENERIC)
+static inline void pci_acpi_set_companion(struct pci_host_bridge *bridge)
+{
+	struct pci_bus *b = bridge->bus;
+	struct acpi_pci_root_info *ci = (struct acpi_pci_root_info *)b->sysdata;
+
+	ACPI_COMPANION_SET(&bridge->dev, ci->bridge);
+}
+
+static inline u16 acpi_pci_get_segment(void *sysdata)
+{
+	struct acpi_pci_root_info *ci = (struct acpi_pci_root_info *)sysdata;
+
+	return ci->root->segment;
+}
+#else
+static inline void pci_acpi_set_companion(struct pci_host_bridge *bridge)
+{
+	/* leave it to the platform for now */
+}
+
+static inline u16 acpi_pci_get_segment(void *sysdata)
+{
+	return 0;
+}
+#endif
+
 #ifdef CONFIG_ACPI_APEI
 extern bool aer_acpi_firmware_first(void);
 #else
-- 
1.9.1


WARNING: multiple messages have this Message-ID (diff)
From: jchandra@broadcom.com (Jayachandran C)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v6 2/5] PCI: Handle ACPI companion and domain number
Date: Thu, 14 Jan 2016 13:02:38 +0530	[thread overview]
Message-ID: <1452756761-29584-3-git-send-email-jchandra@broadcom.com> (raw)
In-Reply-To: <1452756761-29584-1-git-send-email-jchandra@broadcom.com>

pci_create_root_bus is called with NULL as parent in ACPI. This
ends up calling pci_bus_assign_domain_nr with a NULL parent, which
crashes when dereferencing parent.

Fix this by providing a way to set the ACPI domain number and ACPI
companion in PCI code. We define pci_acpi_set_companion() to set
the ACPI companion pointer and acpi_pci_get_segment() and to get
the PCI domain number. This is just defined for the generic ACPI
PCI controller, using the corresponding sysdata.

pci_bus_assign_domain_nr is updated to call acpi_pci_get_segment()
to get the domain number to set on the root bus, in case of ACPI.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
---
 drivers/pci/pci.c        | 15 ++++++++++++++-
 drivers/pci/probe.c      |  2 ++
 include/linux/pci-acpi.h | 28 +++++++++++++++++++++++++++-
 3 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 314db8c..39d2bcc 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -20,6 +20,7 @@
 #include <linux/string.h>
 #include <linux/log2.h>
 #include <linux/pci-aspm.h>
+#include <linux/pci-acpi.h>
 #include <linux/pm_wakeup.h>
 #include <linux/interrupt.h>
 #include <linux/device.h>
@@ -4772,9 +4773,21 @@ int pci_get_new_domain_nr(void)
 void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent)
 {
 	static int use_dt_domains = -1;
-	int domain = of_get_pci_domain_nr(parent->of_node);
+	int domain;
 
 	/*
+	 * Handle ACPI early
+	 *
+	 * The companion is not set at this point, and ACPI sets parent to
+	 * NULL, we have to try to get the segment from acpi root info.
+	 */
+	if (!parent || !parent->of_node) {
+		bus->domain_nr = acpi_pci_get_segment(bus->sysdata);
+		return;
+	}
+
+	domain = of_get_pci_domain_nr(parent->of_node);
+	/*
 	 * Check DT domain and use_dt_domains values.
 	 *
 	 * If DT domain property is valid (domain >= 0) and
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index edb1984..5af66496 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/cpumask.h>
 #include <linux/pci-aspm.h>
+#include <linux/pci-acpi.h>
 #include <linux/aer.h>
 #include <linux/acpi.h>
 #include <asm-generic/pci-bridge.h>
@@ -2105,6 +2106,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
 	bridge->dev.parent = parent;
 	bridge->dev.release = pci_release_host_bridge_dev;
 	dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
+	pci_acpi_set_companion(bridge);
 	error = pcibios_root_bridge_prepare(bridge);
 	if (error) {
 		kfree(bridge);
diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
index e9450ef..f8d62e3 100644
--- a/include/linux/pci-acpi.h
+++ b/include/linux/pci-acpi.h
@@ -138,12 +138,38 @@ extern struct list_head pci_mmcfg_list;
 
 #define PCI_MMCFG_BUS_OFFSET(bus)      ((bus) << 20)
 #define PCI_MMCFG_OFFSET(bus, devfn)   ((bus) << 20 | (devfn) << 12)
-
 #else	/* CONFIG_ACPI */
 static inline void acpi_pci_add_bus(struct pci_bus *bus) { }
 static inline void acpi_pci_remove_bus(struct pci_bus *bus) { }
 #endif	/* CONFIG_ACPI */
 
+#if defined(CONFIG_ACPI) && defined(CONFIG_ACPI_PCI_HOST_GENERIC)
+static inline void pci_acpi_set_companion(struct pci_host_bridge *bridge)
+{
+	struct pci_bus *b = bridge->bus;
+	struct acpi_pci_root_info *ci = (struct acpi_pci_root_info *)b->sysdata;
+
+	ACPI_COMPANION_SET(&bridge->dev, ci->bridge);
+}
+
+static inline u16 acpi_pci_get_segment(void *sysdata)
+{
+	struct acpi_pci_root_info *ci = (struct acpi_pci_root_info *)sysdata;
+
+	return ci->root->segment;
+}
+#else
+static inline void pci_acpi_set_companion(struct pci_host_bridge *bridge)
+{
+	/* leave it to the platform for now */
+}
+
+static inline u16 acpi_pci_get_segment(void *sysdata)
+{
+	return 0;
+}
+#endif
+
 #ifdef CONFIG_ACPI_APEI
 extern bool aer_acpi_firmware_first(void);
 #else
-- 
1.9.1

  parent reply	other threads:[~2016-01-14  7:08 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-01-14  7:32 [PATCH v6 0/5] ACPI based PCI support for arm64 Jayachandran C
2016-01-14  7:32 ` Jayachandran C
2016-01-14  7:32 ` Jayachandran C
2016-01-14  7:32 ` [PATCH v6 1/5] APCI: MCFG: Move mmcfg_list management to drivers/acpi Jayachandran C
2016-01-14  7:32 ` Jayachandran C
2016-01-14  7:32   ` Jayachandran C
2016-01-14  7:32   ` Jayachandran C
2016-01-14  8:48   ` Dennis Chen
2016-01-14  8:48     ` Dennis Chen
2016-01-14  8:48   ` Dennis Chen
2016-01-14 10:33   ` [Xen-devel] " David Vrabel
2016-01-14 10:33     ` David Vrabel
2016-01-14 10:33     ` David Vrabel
2016-01-14 10:33   ` David Vrabel
2016-01-14  7:32 ` Jayachandran C [this message]
2016-01-14  7:32   ` [PATCH v6 2/5] PCI: Handle ACPI companion and domain number Jayachandran C
2016-01-14  7:32   ` Jayachandran C
2016-01-14  7:32 ` Jayachandran C
2016-01-14  7:32 ` [PATCH v6 3/5] ACPI: PCI: Support platforms that need pci_remap_iospace Jayachandran C
2016-01-14  7:32 ` Jayachandran C
2016-01-14  7:32   ` Jayachandran C
2016-01-14  7:32   ` Jayachandran C
2016-01-14  7:32 ` [PATCH v6 4/5] arm64: pci: Add ACPI support Jayachandran C
2016-01-14  7:32   ` Jayachandran C
2016-01-14  7:32   ` Jayachandran C
2016-01-14  7:32 ` Jayachandran C
2016-01-14  7:32 ` [PATCH v6 5/5] PCI: ACPI: Add a generic ACPI based host controller Jayachandran C
2016-01-14  7:32 ` Jayachandran C
2016-01-14  7:32   ` Jayachandran C
2016-01-14  7:32   ` Jayachandran C

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=1452756761-29584-3-git-send-email-jchandra@broadcom.com \
    --to=jchandra@broadcom.com \
    --cc=arnd@arndb.de \
    --cc=bhelgaas@google.com \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=lorenzo.pieralisi@arm.com \
    --cc=rjw@rjwysocki.net \
    --cc=tn@semihalf.com \
    --cc=xen-devel@lists.xenproject.org \
    /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.