linux/3.8: use backported pcibios_get_phb_of_node patches

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>

SVN-Revision: 36494
This commit is contained in:
Gabor Juhos 2013-04-30 10:44:07 +00:00
parent f718179af5
commit 41445b41cc
3 changed files with 44 additions and 153 deletions

View file

@ -0,0 +1,40 @@
From 10629d711ed780470937ecda50d9ffa0e925a4ee Mon Sep 17 00:00:00 2001
From: Bjorn Helgaas <bhelgaas@google.com>
Date: Wed, 10 Apr 2013 09:56:54 -0600
Subject: [PATCH 1/2] PCI: Remove __weak annotation from
pcibios_get_phb_of_node decl
The __weak annotation on the pcibios_get_phb_of_node() declaration
causes *every* definition to be marked "weak." The linker then
selects one based on link order, which may be the wrong one.
Gabor found that on MIPS, the linker selected the generic implementation
from drivers/pci even though arch/mips supplied a definition without the
__weak annotation:
$ 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
This removes the __weak annotation from the pcibios_get_phb_of_node()
declaration so arch-specific non-weak implementations work reliably.
Suggested-by: Gabor Juhos <juhosg@openwrt.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
---
include/linux/pci.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1803,7 +1803,7 @@ extern void pci_set_bus_of_node(struct p
extern void pci_release_bus_of_node(struct pci_bus *bus);
/* Arch may override this (weak) */
-extern struct device_node * __weak pcibios_get_phb_of_node(struct pci_bus *bus);
+extern struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus);
static inline struct device_node *
pci_device_to_OF_node(const struct pci_dev *pdev)

View file

@ -1,150 +0,0 @@
From 61cb343b4ac20d2d957811cd492fec770646dda8 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
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 <juhosg@openwrt.org>
---
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;
-}

View file

@ -1,7 +1,7 @@
From fe17cba0e4efb6cf6d1e4e79fa4c6e062fe32b39 Mon Sep 17 00:00:00 2001
From 9a97cd43f4ef62520a852b5a2348233b0f37455b Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Wed, 3 Apr 2013 19:28:50 +0200
Subject: [PATCH 2/2] MIPS: implement pcibios_get_phb_of_node
Date: Thu, 4 Apr 2013 20:01:23 +0200
Subject: [PATCH 2/2] MIPS/PCI: Implement pcibios_get_phb_of_node
The of_node field of the device assigned to a
PCI bus is used during scanning of the PCI bus.
@ -17,6 +17,7 @@ Also remove the local assignment of bus->dev.of_node,
it is not needed after the patch.
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
---
arch/mips/pci/pci.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)