Home Home > GIT Browse > openSUSE-15.0
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2017-05-16 17:08:15 +0200
committerTakashi Iwai <tiwai@suse.de>2017-05-16 17:08:15 +0200
commit08cedeed697c61e1ec2d0611f0e033eaff848c24 (patch)
tree21efbd3d045f4468d265b855277e5f230e43152a
parent5486de59b752130a0f346381740cc9b13f65bdaf (diff)
parentfbc8b0f6975828d400163b716792ccc4dd7da580 (diff)
Merge branch 'users/ykaukab/SLE12-SP3/for-next' into SLE12-SP3rpm-4.4.68-2
Pull cn88xx pci fixes from Mian Yousaf Kaukab (bsc#1039149).
-rw-r--r--patches.drivers/0001-PCI-Add-pci_register_host_bridge-interface.patch366
-rw-r--r--patches.drivers/0002-PCI-Allow-driver-specific-data-in-host-bridge.patch76
-rw-r--r--patches.drivers/0003-PCI-Export-host-bridge-registration-interface.patch74
-rw-r--r--series.conf5
4 files changed, 521 insertions, 0 deletions
diff --git a/patches.drivers/0001-PCI-Add-pci_register_host_bridge-interface.patch b/patches.drivers/0001-PCI-Add-pci_register_host_bridge-interface.patch
new file mode 100644
index 0000000000..23dcd83c91
--- /dev/null
+++ b/patches.drivers/0001-PCI-Add-pci_register_host_bridge-interface.patch
@@ -0,0 +1,366 @@
+From 0c032d7eae07d538737d5bf7d75fc36bcc449765 Mon Sep 17 00:00:00 2001
+From: Arnd Bergmann <arnd@arndb.de>
+Date: Fri, 25 Nov 2016 11:57:09 +0100
+Subject: [PATCH 1/3] PCI: Add pci_register_host_bridge() interface
+
+Git-commit: 37d6a0a6f4700ad3ae7bbf8db38b4557e97b3fe4
+Patch-mainline: v4.10-rc1
+References: bsc#1039149
+
+Make the existing pci_host_bridge structure a proper device that is usable
+by PCI host drivers in a more standard way. In addition to the existing
+pci_scan_bus(), pci_scan_root_bus(), pci_scan_root_bus_msi(), and
+pci_create_root_bus() interfaces, this unfortunately means having to add
+yet another interface doing basically the same thing, and add some extra
+code in the initial step.
+
+However, this time it's more likely to be extensible enough that we won't
+have to do another one again in the future, and we should be able to reduce
+code much more as a result.
+
+The main idea is to pull the allocation of 'struct pci_host_bridge' out of
+the registration, and let individual host drivers and architecture code
+fill the members before calling the registration function.
+
+There are a number of things we can do based on this:
+
+* Use a single memory allocation for the driver-specific structure
+ and the generic PCI host bridge
+* consolidate the contents of driver-specific structures by moving
+ them into pci_host_bridge
+* Add a consistent interface for removing a PCI host bridge again
+ when unloading a host driver module
+* Replace the architecture specific __weak pcibios_*() functions with
+ callbacks in a pci_host_bridge device
+* Move common boilerplate code from host drivers into the generic
+ function, based on contents of the structure
+* Extend pci_host_bridge with additional members when needed without
+ having to add arguments to pci_scan_*().
+* Move members of struct pci_bus into pci_host_bridge to avoid
+ having lots of identical copies.
+
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Thierry Reding <treding@nvidia.com>
+Signed-off-by: Bjorn Helgaas <helgaas@kernel.org>
+Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+---
+ drivers/pci/probe.c | 238 +++++++++++++++++++++++++++++++---------------------
+ include/linux/pci.h | 4 +
+ 2 files changed, 145 insertions(+), 97 deletions(-)
+
+diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
+index 7b650e3e6463..482cd8bad504 100644
+--- a/drivers/pci/probe.c
++++ b/drivers/pci/probe.c
+@@ -522,7 +522,7 @@ static void pci_release_host_bridge_dev(struct device *dev)
+ kfree(bridge);
+ }
+
+-static struct pci_host_bridge *pci_alloc_host_bridge(struct pci_bus *b)
++static struct pci_host_bridge *pci_alloc_host_bridge(void)
+ {
+ struct pci_host_bridge *bridge;
+
+@@ -531,7 +531,7 @@ static struct pci_host_bridge *pci_alloc_host_bridge(struct pci_bus *b)
+ return NULL;
+
+ INIT_LIST_HEAD(&bridge->windows);
+- bridge->bus = b;
++
+ return bridge;
+ }
+
+@@ -718,6 +718,122 @@ static void pci_set_bus_msi_domain(struct pci_bus *bus)
+ dev_set_msi_domain(&bus->dev, d);
+ }
+
++static int pci_register_host_bridge(struct pci_host_bridge *bridge)
++{
++ struct device *parent = bridge->dev.parent;
++ struct resource_entry *window, *n;
++ struct pci_bus *bus, *b;
++ resource_size_t offset;
++ LIST_HEAD(resources);
++ struct resource *res;
++ char addr[64], *fmt;
++ const char *name;
++ int err;
++
++ bus = pci_alloc_bus(NULL);
++ if (!bus)
++ return -ENOMEM;
++
++ bridge->bus = bus;
++
++ /* temporarily move resources off the list */
++ list_splice_init(&bridge->windows, &resources);
++ bus->sysdata = bridge->sysdata;
++ bus->msi = bridge->msi;
++ bus->ops = bridge->ops;
++ bus->number = bus->busn_res.start = bridge->busnr;
++#ifdef CONFIG_PCI_DOMAINS_GENERIC
++ bus->domain_nr = pci_bus_find_domain_nr(bus, parent);
++#endif
++
++ b = pci_find_bus(pci_domain_nr(bus), bridge->busnr);
++ if (b) {
++ /* If we already got to this bus through a different bridge, ignore it */
++ dev_dbg(&b->dev, "bus already known\n");
++ err = -EEXIST;
++ goto free;
++ }
++
++ dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(bus),
++ bridge->busnr);
++
++ err = pcibios_root_bridge_prepare(bridge);
++ if (err)
++ goto free;
++
++ err = device_register(&bridge->dev);
++ if (err)
++ put_device(&bridge->dev);
++
++ bus->bridge = get_device(&bridge->dev);
++ device_enable_async_suspend(bus->bridge);
++ pci_set_bus_of_node(bus);
++ pci_set_bus_msi_domain(bus);
++
++ if (!parent)
++ set_dev_node(bus->bridge, pcibus_to_node(bus));
++
++ bus->dev.class = &pcibus_class;
++ bus->dev.parent = bus->bridge;
++
++ dev_set_name(&bus->dev, "%04x:%02x", pci_domain_nr(bus), bus->number);
++ name = dev_name(&bus->dev);
++
++ err = device_register(&bus->dev);
++ if (err)
++ goto unregister;
++
++ pcibios_add_bus(bus);
++
++ /* Create legacy_io and legacy_mem files for this bus */
++ pci_create_legacy_files(bus);
++
++ if (parent)
++ dev_info(parent, "PCI host bridge to bus %s\n", name);
++ else
++ pr_info("PCI host bridge to bus %s\n", name);
++
++ /* Add initial resources to the bus */
++ resource_list_for_each_entry_safe(window, n, &resources) {
++ list_move_tail(&window->node, &bridge->windows);
++ offset = window->offset;
++ res = window->res;
++
++ if (res->flags & IORESOURCE_BUS)
++ pci_bus_insert_busn_res(bus, bus->number, res->end);
++ else
++ pci_bus_add_resource(bus, res, 0);
++
++ if (offset) {
++ if (resource_type(res) == IORESOURCE_IO)
++ fmt = " (bus address [%#06llx-%#06llx])";
++ else
++ fmt = " (bus address [%#010llx-%#010llx])";
++
++ snprintf(addr, sizeof(addr), fmt,
++ (unsigned long long)(res->start - offset),
++ (unsigned long long)(res->end - offset));
++ } else
++ addr[0] = '\0';
++
++ dev_info(&bus->dev, "root bus resource %pR%s\n", res, addr);
++ }
++
++ down_write(&pci_bus_sem);
++ list_add_tail(&bus->node, &pci_root_buses);
++ up_write(&pci_bus_sem);
++
++ return 0;
++
++unregister:
++ put_device(&bridge->dev);
++ device_unregister(&bridge->dev);
++
++free:
++ kfree(bus);
++ return err;
++}
++
+ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
+ struct pci_dev *bridge, int busnr)
+ {
+@@ -2140,113 +2256,43 @@ void __weak pcibios_remove_bus(struct pci_bus *bus)
+ {
+ }
+
+-struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
+- struct pci_ops *ops, void *sysdata, struct list_head *resources)
++static struct pci_bus *pci_create_root_bus_msi(struct device *parent,
++ int bus, struct pci_ops *ops, void *sysdata,
++ struct list_head *resources, struct msi_controller *msi)
+ {
+ int error;
+ struct pci_host_bridge *bridge;
+- struct pci_bus *b, *b2;
+- struct resource_entry *window, *n;
+- struct resource *res;
+- resource_size_t offset;
+- char bus_addr[64];
+- char *fmt;
+-
+- b = pci_alloc_bus(NULL);
+- if (!b)
+- return NULL;
+
+- b->sysdata = sysdata;
+- b->ops = ops;
+- b->number = b->busn_res.start = bus;
+-#ifdef CONFIG_PCI_DOMAINS_GENERIC
+- b->domain_nr = pci_bus_find_domain_nr(b, parent);
+-#endif
+- b2 = pci_find_bus(pci_domain_nr(b), bus);
+- if (b2) {
+- /* If we already got to this bus through a different bridge, ignore it */
+- dev_dbg(&b2->dev, "bus already known\n");
+- goto err_out;
+- }
+-
+- bridge = pci_alloc_host_bridge(b);
++ bridge = pci_alloc_host_bridge();
+ if (!bridge)
+- goto err_out;
++ return NULL;
+
+ 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);
+- error = pcibios_root_bridge_prepare(bridge);
+- if (error) {
+- kfree(bridge);
+- goto err_out;
+- }
+-
+- error = device_register(&bridge->dev);
+- if (error) {
+- put_device(&bridge->dev);
+- goto err_out;
+- }
+- b->bridge = get_device(&bridge->dev);
+- device_enable_async_suspend(b->bridge);
+- pci_set_bus_of_node(b);
+- pci_set_bus_msi_domain(b);
+
+- if (!parent)
+- set_dev_node(b->bridge, pcibus_to_node(b));
+-
+- b->dev.class = &pcibus_class;
+- b->dev.parent = b->bridge;
+- dev_set_name(&b->dev, "%04x:%02x", pci_domain_nr(b), bus);
+- error = device_register(&b->dev);
+- if (error)
+- goto class_dev_reg_err;
++ list_splice_init(resources, &bridge->windows);
++ bridge->sysdata = sysdata;
++ bridge->busnr = bus;
++ bridge->ops = ops;
++ bridge->msi = msi;
+
+- pcibios_add_bus(b);
+-
+- /* Create legacy_io and legacy_mem files for this bus */
+- pci_create_legacy_files(b);
+-
+- if (parent)
+- dev_info(parent, "PCI host bridge to bus %s\n", dev_name(&b->dev));
+- else
+- printk(KERN_INFO "PCI host bridge to bus %s\n", dev_name(&b->dev));
+-
+- /* Add initial resources to the bus */
+- resource_list_for_each_entry_safe(window, n, resources) {
+- list_move_tail(&window->node, &bridge->windows);
+- res = window->res;
+- offset = window->offset;
+- if (res->flags & IORESOURCE_BUS)
+- pci_bus_insert_busn_res(b, bus, res->end);
+- else
+- pci_bus_add_resource(b, res, 0);
+- if (offset) {
+- if (resource_type(res) == IORESOURCE_IO)
+- fmt = " (bus address [%#06llx-%#06llx])";
+- else
+- fmt = " (bus address [%#010llx-%#010llx])";
+- snprintf(bus_addr, sizeof(bus_addr), fmt,
+- (unsigned long long) (res->start - offset),
+- (unsigned long long) (res->end - offset));
+- } else
+- bus_addr[0] = '\0';
+- dev_info(&b->dev, "root bus resource %pR%s\n", res, bus_addr);
+- }
++ error = pci_register_host_bridge(bridge);
++ if (error < 0)
++ goto err_out;
+
+- down_write(&pci_bus_sem);
+- list_add_tail(&b->node, &pci_root_buses);
+- up_write(&pci_bus_sem);
++ return bridge->bus;
+
+- return b;
+-
+-class_dev_reg_err:
+- put_device(&bridge->dev);
+- device_unregister(&bridge->dev);
+ err_out:
+- kfree(b);
++ kfree(bridge);
+ return NULL;
+ }
++
++struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
++ struct pci_ops *ops, void *sysdata, struct list_head *resources)
++{
++ return pci_create_root_bus_msi(parent, bus, ops, sysdata, resources,
++ NULL);
++}
+ EXPORT_SYMBOL_GPL(pci_create_root_bus);
+
+ int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int bus_max)
+@@ -2327,12 +2373,10 @@ struct pci_bus *pci_scan_root_bus_msi(struct device *parent, int bus,
+ break;
+ }
+
+- b = pci_create_root_bus(parent, bus, ops, sysdata, resources);
++ b = pci_create_root_bus_msi(parent, bus, ops, sysdata, resources, msi);
+ if (!b)
+ return NULL;
+
+- b->msi = msi;
+-
+ if (!found) {
+ dev_info(&b->dev,
+ "No busn resource found for root bus, will use [bus %02x-ff]\n",
+diff --git a/include/linux/pci.h b/include/linux/pci.h
+index 690a3c201a3e..dd8a92e54740 100644
+--- a/include/linux/pci.h
++++ b/include/linux/pci.h
+@@ -416,9 +416,13 @@ static inline int pci_channel_offline(struct pci_dev *pdev)
+ struct pci_host_bridge {
+ struct device dev;
+ struct pci_bus *bus; /* root bus */
++ struct pci_ops *ops;
++ void *sysdata;
++ int busnr;
+ struct list_head windows; /* resource_entry */
+ void (*release_fn)(struct pci_host_bridge *);
+ void *release_data;
++ struct msi_controller *msi;
+ unsigned int ignore_reset_delay:1; /* for entire hierarchy */
+ /* Resource alignment requirements */
+ resource_size_t (*align_resource)(struct pci_dev *dev,
+--
+2.11.0
+
diff --git a/patches.drivers/0002-PCI-Allow-driver-specific-data-in-host-bridge.patch b/patches.drivers/0002-PCI-Allow-driver-specific-data-in-host-bridge.patch
new file mode 100644
index 0000000000..1fc945e427
--- /dev/null
+++ b/patches.drivers/0002-PCI-Allow-driver-specific-data-in-host-bridge.patch
@@ -0,0 +1,76 @@
+From be71fb4dbd68ec6d8b43edae5317fd482d046239 Mon Sep 17 00:00:00 2001
+From: Thierry Reding <treding@nvidia.com>
+Date: Fri, 25 Nov 2016 11:57:10 +0100
+Subject: [PATCH 2/3] PCI: Allow driver-specific data in host bridge
+
+Git-commit: 5909406598d9fab58be860b72dff9409bff11653
+Patch-mainline: v4.10-rc1
+References: bsc#1039149
+
+Provide a way to allocate driver-specific data along with a PCI host bridge
+structure. The bridge's ->private field points to this data.
+
+Signed-off-by: Thierry Reding <treding@nvidia.com>
+Signed-off-by: Bjorn Helgaas <helgaas@kernel.org>
+Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+---
+ drivers/pci/probe.c | 6 +++---
+ include/linux/pci.h | 11 +++++++++++
+ 2 files changed, 14 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
+index 482cd8bad504..e28d0f7df6f6 100644
+--- a/drivers/pci/probe.c
++++ b/drivers/pci/probe.c
+@@ -522,11 +522,11 @@ static void pci_release_host_bridge_dev(struct device *dev)
+ kfree(bridge);
+ }
+
+-static struct pci_host_bridge *pci_alloc_host_bridge(void)
++static struct pci_host_bridge *pci_alloc_host_bridge(size_t priv)
+ {
+ struct pci_host_bridge *bridge;
+
+- bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
++ bridge = kzalloc(sizeof(*bridge) + priv, GFP_KERNEL);
+ if (!bridge)
+ return NULL;
+
+@@ -2263,7 +2263,7 @@ static struct pci_bus *pci_create_root_bus_msi(struct device *parent,
+ int error;
+ struct pci_host_bridge *bridge;
+
+- bridge = pci_alloc_host_bridge();
++ bridge = pci_alloc_host_bridge(0);
+ if (!bridge)
+ return NULL;
+
+diff --git a/include/linux/pci.h b/include/linux/pci.h
+index dd8a92e54740..c9556503b7cd 100644
+--- a/include/linux/pci.h
++++ b/include/linux/pci.h
+@@ -430,10 +430,21 @@ struct pci_host_bridge {
+ resource_size_t start,
+ resource_size_t size,
+ resource_size_t align);
++ unsigned long private[0] ____cacheline_aligned;
+ };
+
+ #define to_pci_host_bridge(n) container_of(n, struct pci_host_bridge, dev)
+
++static inline void *pci_host_bridge_priv(struct pci_host_bridge *bridge)
++{
++ return (void *)bridge->private;
++}
++
++static inline struct pci_host_bridge *pci_host_bridge_from_priv(void *priv)
++{
++ return container_of(priv, struct pci_host_bridge, private);
++}
++
+ struct pci_host_bridge *pci_find_host_bridge(struct pci_bus *bus);
+
+ void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
+--
+2.11.0
+
diff --git a/patches.drivers/0003-PCI-Export-host-bridge-registration-interface.patch b/patches.drivers/0003-PCI-Export-host-bridge-registration-interface.patch
new file mode 100644
index 0000000000..3f6eaf35a1
--- /dev/null
+++ b/patches.drivers/0003-PCI-Export-host-bridge-registration-interface.patch
@@ -0,0 +1,74 @@
+From 7467cc974d8e90b847b01a9beb4faa743db5607e Mon Sep 17 00:00:00 2001
+From: Thierry Reding <treding@nvidia.com>
+Date: Fri, 25 Nov 2016 11:57:11 +0100
+Subject: [PATCH 3/3] PCI: Export host bridge registration interface
+
+Git-commit: a52d1443bba1db98907521414727eee22ae8c380
+Patch-mainline: v4.10-rc1
+References: bsc#1039149
+
+Allow PCI host bridge drivers to use the new host bridge interfaces to
+register their host bridge.
+
+Signed-off-by: Thierry Reding <treding@nvidia.com>
+Signed-off-by: Bjorn Helgaas <helgaas@kernel.org>
+Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+---
+ drivers/pci/probe.c | 6 ++++--
+ include/linux/pci.h | 2 ++
+ 2 files changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
+index e28d0f7df6f6..a83a573c9ab6 100644
+--- a/drivers/pci/probe.c
++++ b/drivers/pci/probe.c
+@@ -522,7 +522,7 @@ static void pci_release_host_bridge_dev(struct device *dev)
+ kfree(bridge);
+ }
+
+-static struct pci_host_bridge *pci_alloc_host_bridge(size_t priv)
++struct pci_host_bridge *pci_alloc_host_bridge(size_t priv)
+ {
+ struct pci_host_bridge *bridge;
+
+@@ -534,6 +534,7 @@ static struct pci_host_bridge *pci_alloc_host_bridge(size_t priv)
+
+ return bridge;
+ }
++EXPORT_SYMBOL(pci_alloc_host_bridge);
+
+ static const unsigned char pcix_bus_speed[] = {
+ PCI_SPEED_UNKNOWN, /* 0 */
+@@ -718,7 +719,7 @@ static void pci_set_bus_msi_domain(struct pci_bus *bus)
+ dev_set_msi_domain(&bus->dev, d);
+ }
+
+-static int pci_register_host_bridge(struct pci_host_bridge *bridge)
++int pci_register_host_bridge(struct pci_host_bridge *bridge)
+ {
+ struct device *parent = bridge->dev.parent;
+ struct resource_entry *window, *n;
+@@ -833,6 +834,7 @@ free:
+ kfree(bus);
+ return err;
+ }
++EXPORT_SYMBOL(pci_register_host_bridge);
+
+ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
+ struct pci_dev *bridge, int busnr)
+diff --git a/include/linux/pci.h b/include/linux/pci.h
+index c9556503b7cd..9c6667dd8130 100644
+--- a/include/linux/pci.h
++++ b/include/linux/pci.h
+@@ -445,6 +445,8 @@ static inline struct pci_host_bridge *pci_host_bridge_from_priv(void *priv)
+ return container_of(priv, struct pci_host_bridge, private);
+ }
+
++struct pci_host_bridge *pci_alloc_host_bridge(size_t priv);
++int pci_register_host_bridge(struct pci_host_bridge *bridge);
+ struct pci_host_bridge *pci_find_host_bridge(struct pci_bus *bus);
+
+ void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
+--
+2.11.0
+
diff --git a/series.conf b/series.conf
index 2a0184ba7f..0cfb6d55d4 100644
--- a/series.conf
+++ b/series.conf
@@ -15679,6 +15679,11 @@
patches.drivers/0002-arm64-traps-fix-userspace-cache-maintenance-emulatio.patch
patches.drivers/0003-tty-pl011-use-qdf2400_e44-as-the-earlycon-name-for-Q.patch
+ #bsc#1039149
+ patches.drivers/0001-PCI-Add-pci_register_host_bridge-interface.patch
+ patches.drivers/0002-PCI-Allow-driver-specific-data-in-host-bridge.patch
+ patches.drivers/0003-PCI-Export-host-bridge-registration-interface.patch
+
# KVM updates (bsc#1033416 and bsc#1033418)
patches.arch/kvmarm-sp3-0004-KVM-arm64-Ensure-LRs-are-clear-when-they-should-be.patch
patches.arch/kvmarm-sp3-0005-KVM-arm64-Fix-the-issues-when-guest-PMCCFILTR-is-con.patch