|
|
@@ -1,150 +0,0 @@
|
|
|
-From 61cb343b4ac20d2d957811cd492fec770646dda8 Mon Sep 17 00:00:00 2001
|
|
|
-From: Gabor Juhos <[email protected]>
|
|
|
-Date: Wed, 3 Apr 2013 19:47:50 +0200
|
|
|
-Subject: [PATCH 1/2] pci/of: remove weak annotation of
|
|
|
- pcibios_get_phb_of_node
|
|
|
-
|
|
|
-Due to the __weak annotation in the forward declaration
|
|
|
-of the 'pcibios_get_phb_of_node' function GCC will emit
|
|
|
-a weak symbol for this functions even if the actual
|
|
|
-implementation does not use the weak attribute.
|
|
|
-
|
|
|
-If an architecture tries to override the function
|
|
|
-by providing its own implementation there will be
|
|
|
-multiple weak symbols with the same name in the
|
|
|
-object files. When the kernel is linked from the
|
|
|
-object files the linking order determines which
|
|
|
-implementation will be used in the final image.
|
|
|
-
|
|
|
-On x86 and on powerpc the architecture specific
|
|
|
-version gets used:
|
|
|
-
|
|
|
- $ readelf -s arch/x86/kernel/built-in.o drivers/pci/built-in.o \
|
|
|
- vmlinux.o | grep pcibios_get_phb_of_node
|
|
|
- 3338: 00029b80 86 FUNC WEAK DEFAULT 1 pcibios_get_phb_of_node
|
|
|
- 1701: 00012710 77 FUNC WEAK DEFAULT 1 pcibios_get_phb_of_node
|
|
|
- 52072: 0002a170 86 FUNC WEAK DEFAULT 1 pcibios_get_phb_of_node
|
|
|
- $
|
|
|
-
|
|
|
- $ powerpc-openwrt-linux-uclibc-readelf -s arch/powerpc/kernel/built-in.o \
|
|
|
- drivers/pci/built-in.o vmlinux.o | grep pcibios_get_phb_of_node
|
|
|
- 1001: 0000cbb8 12 FUNC WEAK DEFAULT 1 pcibios_get_phb_of_node
|
|
|
- 1484: 0001471c 88 FUNC WEAK DEFAULT 1 pcibios_get_phb_of_node
|
|
|
- 28652: 0000d6f8 12 FUNC WEAK DEFAULT 1 pcibios_get_phb_of_node
|
|
|
- $
|
|
|
-
|
|
|
-However on MIPS, the linker puts the default
|
|
|
-implementation into the final image:
|
|
|
-
|
|
|
- $ mipsel-openwrt-linux-readelf -s arch/mips/pci/built-in.o \
|
|
|
- drivers/pci/built-in.o vmlinux.o | grep pcibios_get_phb_of_node
|
|
|
- 86: 0000046c 12 FUNC WEAK DEFAULT 2 pcibios_get_phb_of_node
|
|
|
- 1430: 00012e2c 104 FUNC WEAK DEFAULT 2 pcibios_get_phb_of_node
|
|
|
- 31898: 0017e4ec 104 FUNC WEAK DEFAULT 2 pcibios_get_phb_of_node
|
|
|
- $
|
|
|
-
|
|
|
-Rename the default implementation and remove the
|
|
|
-__weak annotation of that. This ensures that there
|
|
|
-will be no multiple weak symbols with the same name
|
|
|
-in the object files. In order to keep the expected
|
|
|
-behaviour, call the architecture specific function
|
|
|
-if the weak symbol is resolved.
|
|
|
-
|
|
|
-Also move the renamed function to the top instead
|
|
|
-of adding a new forward declaration for that.
|
|
|
-
|
|
|
-Signed-off-by: Gabor Juhos <[email protected]>
|
|
|
----
|
|
|
-Notes:
|
|
|
-
|
|
|
-Unfortunately I'm not a binutils/gcc expert, so
|
|
|
-I don't know if this is the expected behaviour
|
|
|
-of those or not.
|
|
|
-
|
|
|
-Removing the __weak annotation from the forward
|
|
|
-declaration of 'pcibios_get_phb_of_node' in
|
|
|
-'include/linux/pci.h' also fixes the problem.
|
|
|
-
|
|
|
-The microblaze architecture also provides its own
|
|
|
-implementation. The behaviour of that is not tested
|
|
|
-but I assume that the linker chooses the arch specific
|
|
|
-implementation on that as well similarly to the
|
|
|
-x86/powerpc.
|
|
|
-
|
|
|
-The MIPS version is implemented in the followup
|
|
|
-patch.
|
|
|
-
|
|
|
-Removing the __weak annotation from the forward
|
|
|
-declaration of 'pcibios_get_phb_of_node' in
|
|
|
-'include/linux/pci.h' also fixes the problem.
|
|
|
-
|
|
|
--Gabor
|
|
|
----
|
|
|
- drivers/pci/of.c | 41 +++++++++++++++++++++++------------------
|
|
|
- 1 file changed, 23 insertions(+), 18 deletions(-)
|
|
|
-
|
|
|
---- a/drivers/pci/of.c
|
|
|
-+++ b/drivers/pci/of.c
|
|
|
-@@ -15,10 +15,32 @@
|
|
|
- #include <linux/of_pci.h>
|
|
|
- #include "pci.h"
|
|
|
-
|
|
|
-+static struct device_node *__pcibios_get_phb_of_node(struct pci_bus *bus)
|
|
|
-+{
|
|
|
-+ /* This should only be called for PHBs */
|
|
|
-+ if (WARN_ON(bus->self || bus->parent))
|
|
|
-+ return NULL;
|
|
|
-+
|
|
|
-+ if (pcibios_get_phb_of_node)
|
|
|
-+ return pcibios_get_phb_of_node(bus);
|
|
|
-+
|
|
|
-+ /* Look for a node pointer in either the intermediary device we
|
|
|
-+ * create above the root bus or it's own parent. Normally only
|
|
|
-+ * the later is populated.
|
|
|
-+ */
|
|
|
-+ if (bus->bridge->of_node)
|
|
|
-+ return of_node_get(bus->bridge->of_node);
|
|
|
-+ if (bus->bridge->parent && bus->bridge->parent->of_node)
|
|
|
-+ return of_node_get(bus->bridge->parent->of_node);
|
|
|
-+
|
|
|
-+ return NULL;
|
|
|
-+}
|
|
|
-+
|
|
|
- void pci_set_of_node(struct pci_dev *dev)
|
|
|
- {
|
|
|
- if (!dev->bus->dev.of_node)
|
|
|
- return;
|
|
|
-+
|
|
|
- dev->dev.of_node = of_pci_find_child_device(dev->bus->dev.of_node,
|
|
|
- dev->devfn);
|
|
|
- }
|
|
|
-@@ -32,7 +54,7 @@ void pci_release_of_node(struct pci_dev
|
|
|
- void pci_set_bus_of_node(struct pci_bus *bus)
|
|
|
- {
|
|
|
- if (bus->self == NULL)
|
|
|
-- bus->dev.of_node = pcibios_get_phb_of_node(bus);
|
|
|
-+ bus->dev.of_node = __pcibios_get_phb_of_node(bus);
|
|
|
- else
|
|
|
- bus->dev.of_node = of_node_get(bus->self->dev.of_node);
|
|
|
- }
|
|
|
-@@ -42,20 +64,3 @@ void pci_release_bus_of_node(struct pci_
|
|
|
- of_node_put(bus->dev.of_node);
|
|
|
- bus->dev.of_node = NULL;
|
|
|
- }
|
|
|
--
|
|
|
--struct device_node * __weak pcibios_get_phb_of_node(struct pci_bus *bus)
|
|
|
--{
|
|
|
-- /* This should only be called for PHBs */
|
|
|
-- if (WARN_ON(bus->self || bus->parent))
|
|
|
-- return NULL;
|
|
|
--
|
|
|
-- /* Look for a node pointer in either the intermediary device we
|
|
|
-- * create above the root bus or it's own parent. Normally only
|
|
|
-- * the later is populated.
|
|
|
-- */
|
|
|
-- if (bus->bridge->of_node)
|
|
|
-- return of_node_get(bus->bridge->of_node);
|
|
|
-- if (bus->bridge->parent && bus->bridge->parent->of_node)
|
|
|
-- return of_node_get(bus->bridge->parent->of_node);
|
|
|
-- return NULL;
|
|
|
--}
|