linux/3.8: implement pcibios_get_phb_of_node for MIPS
[oweals/openwrt.git] / target / linux / generic / patches-3.8 / 031-pci-of-remove-weak-annotation-of-pcibios_get_phb_of_.patch
1 From 61cb343b4ac20d2d957811cd492fec770646dda8 Mon Sep 17 00:00:00 2001
2 From: Gabor Juhos <juhosg@openwrt.org>
3 Date: Wed, 3 Apr 2013 19:47:50 +0200
4 Subject: [PATCH 1/2] pci/of: remove weak annotation of
5  pcibios_get_phb_of_node
6
7 Due to the __weak annotation in the forward declaration
8 of the 'pcibios_get_phb_of_node' function GCC will emit
9 a weak symbol for this functions even if the actual
10 implementation does not use the weak attribute.
11
12 If an architecture tries to override the function
13 by providing its own implementation there will be
14 multiple weak symbols with the same name in the
15 object files. When the kernel is linked from the
16 object files the linking order determines which
17 implementation will be used in the final image.
18
19 On x86 and on powerpc the architecture specific
20 version gets used:
21
22   $ readelf -s  arch/x86/kernel/built-in.o drivers/pci/built-in.o \
23     vmlinux.o | grep pcibios_get_phb_of_node
24     3338: 00029b80    86 FUNC    WEAK   DEFAULT    1 pcibios_get_phb_of_node
25     1701: 00012710    77 FUNC    WEAK   DEFAULT    1 pcibios_get_phb_of_node
26    52072: 0002a170    86 FUNC    WEAK   DEFAULT    1 pcibios_get_phb_of_node
27   $
28
29   $ powerpc-openwrt-linux-uclibc-readelf -s arch/powerpc/kernel/built-in.o \
30     drivers/pci/built-in.o vmlinux.o | grep pcibios_get_phb_of_node
31     1001: 0000cbb8    12 FUNC    WEAK   DEFAULT    1 pcibios_get_phb_of_node
32     1484: 0001471c    88 FUNC    WEAK   DEFAULT    1 pcibios_get_phb_of_node
33    28652: 0000d6f8    12 FUNC    WEAK   DEFAULT    1 pcibios_get_phb_of_node
34   $
35
36 However on MIPS, the linker puts the default
37 implementation into the final image:
38
39   $ mipsel-openwrt-linux-readelf -s arch/mips/pci/built-in.o \
40     drivers/pci/built-in.o vmlinux.o | grep pcibios_get_phb_of_node
41       86: 0000046c    12 FUNC    WEAK   DEFAULT    2 pcibios_get_phb_of_node
42     1430: 00012e2c   104 FUNC    WEAK   DEFAULT    2 pcibios_get_phb_of_node
43    31898: 0017e4ec   104 FUNC    WEAK   DEFAULT    2 pcibios_get_phb_of_node
44   $
45
46 Rename the default implementation and remove the
47 __weak annotation of that. This ensures that there
48 will be no multiple weak symbols with the same name
49 in the object files. In order to keep the expected
50 behaviour, call the architecture specific function
51 if the weak symbol is resolved.
52
53 Also move the renamed function to the top instead
54 of adding a new forward declaration for that.
55
56 Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
57 ---
58 Notes:
59
60 Unfortunately I'm not a binutils/gcc expert, so
61 I don't know if this is the expected behaviour
62 of those or not.
63
64 Removing the __weak annotation from the forward
65 declaration of 'pcibios_get_phb_of_node' in
66 'include/linux/pci.h' also fixes the problem.
67
68 The microblaze architecture also provides its own
69 implementation. The behaviour of that is not tested
70 but I assume that the linker chooses the arch specific
71 implementation on that as well similarly to the
72 x86/powerpc.
73
74 The MIPS version is implemented in the followup
75 patch.
76
77 Removing the __weak annotation from the forward
78 declaration of 'pcibios_get_phb_of_node' in
79 'include/linux/pci.h' also fixes the problem.
80
81 -Gabor
82 ---
83  drivers/pci/of.c |   41 +++++++++++++++++++++++------------------
84  1 file changed, 23 insertions(+), 18 deletions(-)
85
86 --- a/drivers/pci/of.c
87 +++ b/drivers/pci/of.c
88 @@ -15,10 +15,32 @@
89  #include <linux/of_pci.h>
90  #include "pci.h"
91  
92 +static struct device_node *__pcibios_get_phb_of_node(struct pci_bus *bus)
93 +{
94 +       /* This should only be called for PHBs */
95 +       if (WARN_ON(bus->self || bus->parent))
96 +               return NULL;
97 +
98 +       if (pcibios_get_phb_of_node)
99 +               return pcibios_get_phb_of_node(bus);
100 +
101 +       /* Look for a node pointer in either the intermediary device we
102 +        * create above the root bus or it's own parent. Normally only
103 +        * the later is populated.
104 +        */
105 +       if (bus->bridge->of_node)
106 +               return of_node_get(bus->bridge->of_node);
107 +       if (bus->bridge->parent && bus->bridge->parent->of_node)
108 +               return of_node_get(bus->bridge->parent->of_node);
109 +
110 +       return NULL;
111 +}
112 +
113  void pci_set_of_node(struct pci_dev *dev)
114  {
115         if (!dev->bus->dev.of_node)
116                 return;
117 +
118         dev->dev.of_node = of_pci_find_child_device(dev->bus->dev.of_node,
119                                                     dev->devfn);
120  }
121 @@ -32,7 +54,7 @@ void pci_release_of_node(struct pci_dev
122  void pci_set_bus_of_node(struct pci_bus *bus)
123  {
124         if (bus->self == NULL)
125 -               bus->dev.of_node = pcibios_get_phb_of_node(bus);
126 +               bus->dev.of_node = __pcibios_get_phb_of_node(bus);
127         else
128                 bus->dev.of_node = of_node_get(bus->self->dev.of_node);
129  }
130 @@ -42,20 +64,3 @@ void pci_release_bus_of_node(struct pci_
131         of_node_put(bus->dev.of_node);
132         bus->dev.of_node = NULL;
133  }
134 -
135 -struct device_node * __weak pcibios_get_phb_of_node(struct pci_bus *bus)
136 -{
137 -       /* This should only be called for PHBs */
138 -       if (WARN_ON(bus->self || bus->parent))
139 -               return NULL;
140 -
141 -       /* Look for a node pointer in either the intermediary device we
142 -        * create above the root bus or it's own parent. Normally only
143 -        * the later is populated.
144 -        */
145 -       if (bus->bridge->of_node)
146 -               return of_node_get(bus->bridge->of_node);
147 -       if (bus->bridge->parent && bus->bridge->parent->of_node)
148 -               return of_node_get(bus->bridge->parent->of_node);
149 -       return NULL;
150 -}