diff options
author | David S. Miller <davem@sunset.davemloft.net> | 2006-06-22 19:18:54 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-06-24 02:15:26 -0400 |
commit | de8d28b16f5614aeb12bb69c8f9a38578b8d3ada (patch) | |
tree | 152f0930dc099606342e9cc6d9a3892cd9f3f192 /arch | |
parent | 765b5f32730cfd2608291e679060b0391570c8b3 (diff) |
[SPARC64]: Convert sparc64 PCI layer to in-kernel device tree.
One thing this change pointed out was that we really should
pull the "get 'local-mac-address' property" logic into a helper
function all the network drivers can call.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/sparc64/kernel/ebus.c | 6 | ||||
-rw-r--r-- | arch/sparc64/kernel/isa.c | 4 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_common.c | 196 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_impl.h | 3 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_psycho.c | 2 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_sabre.c | 4 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_schizo.c | 2 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_sun4v.c | 3 | ||||
-rw-r--r-- | arch/sparc64/kernel/prom.c | 25 |
9 files changed, 140 insertions, 105 deletions
diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c index c69504aa638f..3125a5b49775 100644 --- a/arch/sparc64/kernel/ebus.c +++ b/arch/sparc64/kernel/ebus.c | |||
@@ -553,7 +553,7 @@ void __init ebus_init(void) | |||
553 | } | 553 | } |
554 | 554 | ||
555 | cookie = pdev->sysdata; | 555 | cookie = pdev->sysdata; |
556 | ebusnd = cookie->prom_node; | 556 | ebusnd = cookie->prom_node->node; |
557 | 557 | ||
558 | ebus_chain = ebus = ebus_alloc(sizeof(struct linux_ebus)); | 558 | ebus_chain = ebus = ebus_alloc(sizeof(struct linux_ebus)); |
559 | ebus->next = NULL; | 559 | ebus->next = NULL; |
@@ -578,7 +578,7 @@ void __init ebus_init(void) | |||
578 | } | 578 | } |
579 | ebus->is_rio = is_rio; | 579 | ebus->is_rio = is_rio; |
580 | cookie = pdev->sysdata; | 580 | cookie = pdev->sysdata; |
581 | ebusnd = cookie->prom_node; | 581 | ebusnd = cookie->prom_node->node; |
582 | continue; | 582 | continue; |
583 | } | 583 | } |
584 | printk("ebus%d:", num_ebus); | 584 | printk("ebus%d:", num_ebus); |
@@ -622,7 +622,7 @@ void __init ebus_init(void) | |||
622 | break; | 622 | break; |
623 | 623 | ||
624 | cookie = pdev->sysdata; | 624 | cookie = pdev->sysdata; |
625 | ebusnd = cookie->prom_node; | 625 | ebusnd = cookie->prom_node->node; |
626 | 626 | ||
627 | ebus->next = ebus_alloc(sizeof(struct linux_ebus)); | 627 | ebus->next = ebus_alloc(sizeof(struct linux_ebus)); |
628 | ebus = ebus->next; | 628 | ebus = ebus->next; |
diff --git a/arch/sparc64/kernel/isa.c b/arch/sparc64/kernel/isa.c index 30862abee611..ae02c3820eab 100644 --- a/arch/sparc64/kernel/isa.c +++ b/arch/sparc64/kernel/isa.c | |||
@@ -291,8 +291,8 @@ void __init isa_init(void) | |||
291 | isa_br->parent = pbm; | 291 | isa_br->parent = pbm; |
292 | isa_br->self = pdev; | 292 | isa_br->self = pdev; |
293 | isa_br->index = index++; | 293 | isa_br->index = index++; |
294 | isa_br->prom_node = pdev_cookie->prom_node; | 294 | isa_br->prom_node = pdev_cookie->prom_node->node; |
295 | strncpy(isa_br->prom_name, pdev_cookie->prom_name, | 295 | strncpy(isa_br->prom_name, pdev_cookie->prom_node->name, |
296 | sizeof(isa_br->prom_name)); | 296 | sizeof(isa_br->prom_name)); |
297 | 297 | ||
298 | prop_len = prom_getproperty(isa_br->prom_node, | 298 | prop_len = prom_getproperty(isa_br->prom_node, |
diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c index 2319d732b13e..b06a2955bf5f 100644 --- a/arch/sparc64/kernel/pci_common.c +++ b/arch/sparc64/kernel/pci_common.c | |||
@@ -9,6 +9,9 @@ | |||
9 | #include <linux/init.h> | 9 | #include <linux/init.h> |
10 | 10 | ||
11 | #include <asm/pbm.h> | 11 | #include <asm/pbm.h> |
12 | #include <asm/prom.h> | ||
13 | |||
14 | #include "pci_impl.h" | ||
12 | 15 | ||
13 | /* Pass "pci=irq_verbose" on the kernel command line to enable this. */ | 16 | /* Pass "pci=irq_verbose" on the kernel command line to enable this. */ |
14 | int pci_irq_verbose; | 17 | int pci_irq_verbose; |
@@ -31,16 +34,14 @@ void __init pci_fixup_host_bridge_self(struct pci_bus *pbus) | |||
31 | prom_halt(); | 34 | prom_halt(); |
32 | } | 35 | } |
33 | 36 | ||
34 | /* Find the OBP PROM device tree node for a PCI device. | 37 | /* Find the OBP PROM device tree node for a PCI device. */ |
35 | * Return zero if not found. | 38 | static struct device_node * __init |
36 | */ | 39 | find_device_prom_node(struct pci_pbm_info *pbm, struct pci_dev *pdev, |
37 | static int __init find_device_prom_node(struct pci_pbm_info *pbm, | 40 | struct device_node *bus_node, |
38 | struct pci_dev *pdev, | 41 | struct linux_prom_pci_registers **pregs, |
39 | int bus_prom_node, | 42 | int *nregs) |
40 | struct linux_prom_pci_registers *pregs, | ||
41 | int *nregs) | ||
42 | { | 43 | { |
43 | int node; | 44 | struct device_node *dp; |
44 | 45 | ||
45 | *nregs = 0; | 46 | *nregs = 0; |
46 | 47 | ||
@@ -57,24 +58,30 @@ static int __init find_device_prom_node(struct pci_pbm_info *pbm, | |||
57 | pdev->device == PCI_DEVICE_ID_SUN_TOMATILLO || | 58 | pdev->device == PCI_DEVICE_ID_SUN_TOMATILLO || |
58 | pdev->device == PCI_DEVICE_ID_SUN_SABRE || | 59 | pdev->device == PCI_DEVICE_ID_SUN_SABRE || |
59 | pdev->device == PCI_DEVICE_ID_SUN_HUMMINGBIRD)) | 60 | pdev->device == PCI_DEVICE_ID_SUN_HUMMINGBIRD)) |
60 | return bus_prom_node; | 61 | return bus_node; |
61 | 62 | ||
62 | node = prom_getchild(bus_prom_node); | 63 | dp = bus_node->child; |
63 | while (node != 0) { | 64 | while (dp) { |
64 | int err = prom_getproperty(node, "reg", | 65 | struct linux_prom_pci_registers *regs; |
65 | (char *)pregs, | 66 | struct property *prop; |
66 | sizeof(*pregs) * PROMREG_MAX); | 67 | int len; |
67 | if (err == 0 || err == -1) | 68 | |
69 | prop = of_find_property(dp, "reg", &len); | ||
70 | if (!prop) | ||
68 | goto do_next_sibling; | 71 | goto do_next_sibling; |
69 | if (((pregs[0].phys_hi >> 8) & 0xff) == pdev->devfn) { | 72 | |
70 | *nregs = err / sizeof(*pregs); | 73 | regs = prop->value; |
71 | return node; | 74 | if (((regs[0].phys_hi >> 8) & 0xff) == pdev->devfn) { |
75 | *pregs = regs; | ||
76 | *nregs = len / sizeof(struct linux_prom_pci_registers); | ||
77 | return dp; | ||
72 | } | 78 | } |
73 | 79 | ||
74 | do_next_sibling: | 80 | do_next_sibling: |
75 | node = prom_getsibling(node); | 81 | dp = dp->sibling; |
76 | } | 82 | } |
77 | return 0; | 83 | |
84 | return NULL; | ||
78 | } | 85 | } |
79 | 86 | ||
80 | /* Older versions of OBP on PCI systems encode 64-bit MEM | 87 | /* Older versions of OBP on PCI systems encode 64-bit MEM |
@@ -131,15 +138,17 @@ static void __init fixup_obp_assignments(struct pci_dev *pdev, | |||
131 | */ | 138 | */ |
132 | static void __init pdev_cookie_fillin(struct pci_pbm_info *pbm, | 139 | static void __init pdev_cookie_fillin(struct pci_pbm_info *pbm, |
133 | struct pci_dev *pdev, | 140 | struct pci_dev *pdev, |
134 | int bus_prom_node) | 141 | struct device_node *bus_node) |
135 | { | 142 | { |
136 | struct linux_prom_pci_registers pregs[PROMREG_MAX]; | 143 | struct linux_prom_pci_registers *pregs = NULL; |
137 | struct pcidev_cookie *pcp; | 144 | struct pcidev_cookie *pcp; |
138 | int device_prom_node, nregs, err; | 145 | struct device_node *dp; |
146 | struct property *prop; | ||
147 | int nregs, len; | ||
139 | 148 | ||
140 | device_prom_node = find_device_prom_node(pbm, pdev, bus_prom_node, | 149 | dp = find_device_prom_node(pbm, pdev, bus_node, |
141 | pregs, &nregs); | 150 | &pregs, &nregs); |
142 | if (device_prom_node == 0) { | 151 | if (!dp) { |
143 | /* If it is not in the OBP device tree then | 152 | /* If it is not in the OBP device tree then |
144 | * there must be a damn good reason for it. | 153 | * there must be a damn good reason for it. |
145 | * | 154 | * |
@@ -153,45 +162,43 @@ static void __init pdev_cookie_fillin(struct pci_pbm_info *pbm, | |||
153 | return; | 162 | return; |
154 | } | 163 | } |
155 | 164 | ||
156 | pcp = kmalloc(sizeof(*pcp), GFP_ATOMIC); | 165 | pcp = kzalloc(sizeof(*pcp), GFP_ATOMIC); |
157 | if (pcp == NULL) { | 166 | if (pcp == NULL) { |
158 | prom_printf("PCI_COOKIE: Fatal malloc error, aborting...\n"); | 167 | prom_printf("PCI_COOKIE: Fatal malloc error, aborting...\n"); |
159 | prom_halt(); | 168 | prom_halt(); |
160 | } | 169 | } |
161 | pcp->pbm = pbm; | 170 | pcp->pbm = pbm; |
162 | pcp->prom_node = device_prom_node; | 171 | pcp->prom_node = dp; |
163 | memcpy(pcp->prom_regs, pregs, sizeof(pcp->prom_regs)); | 172 | memcpy(pcp->prom_regs, pregs, |
173 | nregs * sizeof(struct linux_prom_pci_registers)); | ||
164 | pcp->num_prom_regs = nregs; | 174 | pcp->num_prom_regs = nregs; |
165 | err = prom_getproperty(device_prom_node, "name", | 175 | |
166 | pcp->prom_name, sizeof(pcp->prom_name)); | 176 | /* We can't have the pcidev_cookie assignments be just |
167 | if (err > 0) | 177 | * direct pointers into the property value, since they |
168 | pcp->prom_name[err] = 0; | 178 | * are potentially modified by the probing process. |
169 | else | 179 | */ |
170 | pcp->prom_name[0] = 0; | 180 | prop = of_find_property(dp, "assigned-addresses", &len); |
171 | 181 | if (!prop) { | |
172 | err = prom_getproperty(device_prom_node, | ||
173 | "assigned-addresses", | ||
174 | (char *)pcp->prom_assignments, | ||
175 | sizeof(pcp->prom_assignments)); | ||
176 | if (err == 0 || err == -1) | ||
177 | pcp->num_prom_assignments = 0; | 182 | pcp->num_prom_assignments = 0; |
178 | else | 183 | } else { |
184 | memcpy(pcp->prom_assignments, prop->value, len); | ||
179 | pcp->num_prom_assignments = | 185 | pcp->num_prom_assignments = |
180 | (err / sizeof(pcp->prom_assignments[0])); | 186 | (len / sizeof(pcp->prom_assignments[0])); |
187 | } | ||
181 | 188 | ||
182 | if (strcmp(pcp->prom_name, "ebus") == 0) { | 189 | if (strcmp(dp->name, "ebus") == 0) { |
183 | struct linux_prom_ebus_ranges erng[PROM_PCIRNG_MAX]; | 190 | struct linux_prom_ebus_ranges *erng; |
184 | int iter; | 191 | int iter; |
185 | 192 | ||
186 | /* EBUS is special... */ | 193 | /* EBUS is special... */ |
187 | err = prom_getproperty(device_prom_node, "ranges", | 194 | prop = of_find_property(dp, "ranges", &len); |
188 | (char *)&erng[0], sizeof(erng)); | 195 | if (!prop) { |
189 | if (err == 0 || err == -1) { | ||
190 | prom_printf("EBUS: Fatal error, no range property\n"); | 196 | prom_printf("EBUS: Fatal error, no range property\n"); |
191 | prom_halt(); | 197 | prom_halt(); |
192 | } | 198 | } |
193 | err = (err / sizeof(erng[0])); | 199 | erng = prop->value; |
194 | for(iter = 0; iter < err; iter++) { | 200 | len = (len / sizeof(erng[0])); |
201 | for (iter = 0; iter < len; iter++) { | ||
195 | struct linux_prom_ebus_ranges *ep = &erng[iter]; | 202 | struct linux_prom_ebus_ranges *ep = &erng[iter]; |
196 | struct linux_prom_pci_registers *ap; | 203 | struct linux_prom_pci_registers *ap; |
197 | 204 | ||
@@ -203,7 +210,7 @@ static void __init pdev_cookie_fillin(struct pci_pbm_info *pbm, | |||
203 | ap->size_hi = 0; | 210 | ap->size_hi = 0; |
204 | ap->size_lo = ep->size; | 211 | ap->size_lo = ep->size; |
205 | } | 212 | } |
206 | pcp->num_prom_assignments = err; | 213 | pcp->num_prom_assignments = len; |
207 | } | 214 | } |
208 | 215 | ||
209 | fixup_obp_assignments(pdev, pcp); | 216 | fixup_obp_assignments(pdev, pcp); |
@@ -213,7 +220,7 @@ static void __init pdev_cookie_fillin(struct pci_pbm_info *pbm, | |||
213 | 220 | ||
214 | void __init pci_fill_in_pbm_cookies(struct pci_bus *pbus, | 221 | void __init pci_fill_in_pbm_cookies(struct pci_bus *pbus, |
215 | struct pci_pbm_info *pbm, | 222 | struct pci_pbm_info *pbm, |
216 | int prom_node) | 223 | struct device_node *dp) |
217 | { | 224 | { |
218 | struct pci_dev *pdev, *pdev_next; | 225 | struct pci_dev *pdev, *pdev_next; |
219 | struct pci_bus *this_pbus, *pbus_next; | 226 | struct pci_bus *this_pbus, *pbus_next; |
@@ -221,7 +228,7 @@ void __init pci_fill_in_pbm_cookies(struct pci_bus *pbus, | |||
221 | /* This must be _safe because the cookie fillin | 228 | /* This must be _safe because the cookie fillin |
222 | routine can delete devices from the tree. */ | 229 | routine can delete devices from the tree. */ |
223 | list_for_each_entry_safe(pdev, pdev_next, &pbus->devices, bus_list) | 230 | list_for_each_entry_safe(pdev, pdev_next, &pbus->devices, bus_list) |
224 | pdev_cookie_fillin(pbm, pdev, prom_node); | 231 | pdev_cookie_fillin(pbm, pdev, dp); |
225 | 232 | ||
226 | list_for_each_entry_safe(this_pbus, pbus_next, &pbus->children, node) { | 233 | list_for_each_entry_safe(this_pbus, pbus_next, &pbus->children, node) { |
227 | struct pcidev_cookie *pcp = this_pbus->self->sysdata; | 234 | struct pcidev_cookie *pcp = this_pbus->self->sysdata; |
@@ -244,7 +251,6 @@ static void __init bad_assignment(struct pci_dev *pdev, | |||
244 | if (res) | 251 | if (res) |
245 | prom_printf("PCI: RES[%016lx-->%016lx:(%lx)]\n", | 252 | prom_printf("PCI: RES[%016lx-->%016lx:(%lx)]\n", |
246 | res->start, res->end, res->flags); | 253 | res->start, res->end, res->flags); |
247 | prom_printf("Please email this information to davem@redhat.com\n"); | ||
248 | if (do_prom_halt) | 254 | if (do_prom_halt) |
249 | prom_halt(); | 255 | prom_halt(); |
250 | } | 256 | } |
@@ -276,8 +282,7 @@ __init get_root_resource(struct linux_prom_pci_registers *ap, | |||
276 | return &pbm->mem_space; | 282 | return &pbm->mem_space; |
277 | 283 | ||
278 | default: | 284 | default: |
279 | printk("PCI: What is resource space %x? " | 285 | printk("PCI: What is resource space %x?\n", space); |
280 | "Tell davem@redhat.com about it!\n", space); | ||
281 | return NULL; | 286 | return NULL; |
282 | }; | 287 | }; |
283 | } | 288 | } |
@@ -572,50 +577,51 @@ static inline unsigned int pci_apply_intmap(struct pci_pbm_info *pbm, | |||
572 | struct pci_dev *pbus, | 577 | struct pci_dev *pbus, |
573 | struct pci_dev *pdev, | 578 | struct pci_dev *pdev, |
574 | unsigned int interrupt, | 579 | unsigned int interrupt, |
575 | unsigned int *cnode) | 580 | struct device_node **cnode) |
576 | { | 581 | { |
577 | struct linux_prom_pci_intmap imap[PROM_PCIIMAP_MAX]; | 582 | struct linux_prom_pci_intmap *imap; |
578 | struct linux_prom_pci_intmask imask; | 583 | struct linux_prom_pci_intmask *imask; |
579 | struct pcidev_cookie *pbus_pcp = pbus->sysdata; | 584 | struct pcidev_cookie *pbus_pcp = pbus->sysdata; |
580 | struct pcidev_cookie *pdev_pcp = pdev->sysdata; | 585 | struct pcidev_cookie *pdev_pcp = pdev->sysdata; |
581 | struct linux_prom_pci_registers *pregs = pdev_pcp->prom_regs; | 586 | struct linux_prom_pci_registers *pregs = pdev_pcp->prom_regs; |
587 | struct property *prop; | ||
582 | int plen, num_imap, i; | 588 | int plen, num_imap, i; |
583 | unsigned int hi, mid, lo, irq, orig_interrupt; | 589 | unsigned int hi, mid, lo, irq, orig_interrupt; |
584 | 590 | ||
585 | *cnode = pbus_pcp->prom_node; | 591 | *cnode = pbus_pcp->prom_node; |
586 | 592 | ||
587 | plen = prom_getproperty(pbus_pcp->prom_node, "interrupt-map", | 593 | prop = of_find_property(pbus_pcp->prom_node, "interrupt-map", &plen); |
588 | (char *) &imap[0], sizeof(imap)); | 594 | if (!prop || |
589 | if (plen <= 0 || | ||
590 | (plen % sizeof(struct linux_prom_pci_intmap)) != 0) { | 595 | (plen % sizeof(struct linux_prom_pci_intmap)) != 0) { |
591 | printk("%s: Device %s interrupt-map has bad len %d\n", | 596 | printk("%s: Device %s interrupt-map has bad len %d\n", |
592 | pbm->name, pci_name(pbus), plen); | 597 | pbm->name, pci_name(pbus), plen); |
593 | goto no_intmap; | 598 | goto no_intmap; |
594 | } | 599 | } |
600 | imap = prop->value; | ||
595 | num_imap = plen / sizeof(struct linux_prom_pci_intmap); | 601 | num_imap = plen / sizeof(struct linux_prom_pci_intmap); |
596 | 602 | ||
597 | plen = prom_getproperty(pbus_pcp->prom_node, "interrupt-map-mask", | 603 | prop = of_find_property(pbus_pcp->prom_node, "interrupt-map-mask", &plen); |
598 | (char *) &imask, sizeof(imask)); | 604 | if (!prop || |
599 | if (plen <= 0 || | ||
600 | (plen % sizeof(struct linux_prom_pci_intmask)) != 0) { | 605 | (plen % sizeof(struct linux_prom_pci_intmask)) != 0) { |
601 | printk("%s: Device %s interrupt-map-mask has bad len %d\n", | 606 | printk("%s: Device %s interrupt-map-mask has bad len %d\n", |
602 | pbm->name, pci_name(pbus), plen); | 607 | pbm->name, pci_name(pbus), plen); |
603 | goto no_intmap; | 608 | goto no_intmap; |
604 | } | 609 | } |
610 | imask = prop->value; | ||
605 | 611 | ||
606 | orig_interrupt = interrupt; | 612 | orig_interrupt = interrupt; |
607 | 613 | ||
608 | hi = pregs->phys_hi & imask.phys_hi; | 614 | hi = pregs->phys_hi & imask->phys_hi; |
609 | mid = pregs->phys_mid & imask.phys_mid; | 615 | mid = pregs->phys_mid & imask->phys_mid; |
610 | lo = pregs->phys_lo & imask.phys_lo; | 616 | lo = pregs->phys_lo & imask->phys_lo; |
611 | irq = interrupt & imask.interrupt; | 617 | irq = interrupt & imask->interrupt; |
612 | 618 | ||
613 | for (i = 0; i < num_imap; i++) { | 619 | for (i = 0; i < num_imap; i++) { |
614 | if (imap[i].phys_hi == hi && | 620 | if (imap[i].phys_hi == hi && |
615 | imap[i].phys_mid == mid && | 621 | imap[i].phys_mid == mid && |
616 | imap[i].phys_lo == lo && | 622 | imap[i].phys_lo == lo && |
617 | imap[i].interrupt == irq) { | 623 | imap[i].interrupt == irq) { |
618 | *cnode = imap[i].cnode; | 624 | *cnode = of_find_node_by_phandle(imap[i].cnode); |
619 | interrupt = imap[i].cinterrupt; | 625 | interrupt = imap[i].cinterrupt; |
620 | } | 626 | } |
621 | } | 627 | } |
@@ -638,21 +644,22 @@ no_intmap: | |||
638 | * all interrupt translations are complete, else we should use that node's | 644 | * all interrupt translations are complete, else we should use that node's |
639 | * "reg" property to apply the PBM's "interrupt-{map,mask}" to the interrupt. | 645 | * "reg" property to apply the PBM's "interrupt-{map,mask}" to the interrupt. |
640 | */ | 646 | */ |
641 | static unsigned int __init pci_intmap_match_to_root(struct pci_pbm_info *pbm, | 647 | static struct device_node * __init |
642 | struct pci_dev *pdev, | 648 | pci_intmap_match_to_root(struct pci_pbm_info *pbm, |
643 | unsigned int *interrupt) | 649 | struct pci_dev *pdev, |
650 | unsigned int *interrupt) | ||
644 | { | 651 | { |
645 | struct pci_dev *toplevel_pdev = pdev; | 652 | struct pci_dev *toplevel_pdev = pdev; |
646 | struct pcidev_cookie *toplevel_pcp = toplevel_pdev->sysdata; | 653 | struct pcidev_cookie *toplevel_pcp = toplevel_pdev->sysdata; |
647 | unsigned int cnode = toplevel_pcp->prom_node; | 654 | struct device_node *cnode = toplevel_pcp->prom_node; |
648 | 655 | ||
649 | while (pdev->bus->number != pbm->pci_first_busno) { | 656 | while (pdev->bus->number != pbm->pci_first_busno) { |
650 | struct pci_dev *pbus = pdev->bus->self; | 657 | struct pci_dev *pbus = pdev->bus->self; |
651 | struct pcidev_cookie *pcp = pbus->sysdata; | 658 | struct pcidev_cookie *pcp = pbus->sysdata; |
652 | int plen; | 659 | struct property *prop; |
653 | 660 | ||
654 | plen = prom_getproplen(pcp->prom_node, "interrupt-map"); | 661 | prop = of_find_property(pcp->prom_node, "interrupt-map", NULL); |
655 | if (plen <= 0) { | 662 | if (!prop) { |
656 | *interrupt = pci_slot_swivel(pbm, toplevel_pdev, | 663 | *interrupt = pci_slot_swivel(pbm, toplevel_pdev, |
657 | pdev, *interrupt); | 664 | pdev, *interrupt); |
658 | cnode = pcp->prom_node; | 665 | cnode = pcp->prom_node; |
@@ -669,7 +676,7 @@ static unsigned int __init pci_intmap_match_to_root(struct pci_pbm_info *pbm, | |||
669 | } | 676 | } |
670 | pdev = pbus; | 677 | pdev = pbus; |
671 | 678 | ||
672 | if (cnode == pbm->prom_node->node) | 679 | if (cnode == pbm->prom_node) |
673 | break; | 680 | break; |
674 | } | 681 | } |
675 | 682 | ||
@@ -680,21 +687,24 @@ static int __init pci_intmap_match(struct pci_dev *pdev, unsigned int *interrupt | |||
680 | { | 687 | { |
681 | struct pcidev_cookie *dev_pcp = pdev->sysdata; | 688 | struct pcidev_cookie *dev_pcp = pdev->sysdata; |
682 | struct pci_pbm_info *pbm = dev_pcp->pbm; | 689 | struct pci_pbm_info *pbm = dev_pcp->pbm; |
683 | struct linux_prom_pci_registers reg[PROMREG_MAX]; | 690 | struct linux_prom_pci_registers *reg; |
691 | struct device_node *cnode; | ||
692 | struct property *prop; | ||
684 | unsigned int hi, mid, lo, irq; | 693 | unsigned int hi, mid, lo, irq; |
685 | int i, cnode, plen; | 694 | int i, plen; |
686 | 695 | ||
687 | cnode = pci_intmap_match_to_root(pbm, pdev, interrupt); | 696 | cnode = pci_intmap_match_to_root(pbm, pdev, interrupt); |
688 | if (cnode == pbm->prom_node->node) | 697 | if (cnode == pbm->prom_node) |
689 | goto success; | 698 | goto success; |
690 | 699 | ||
691 | plen = prom_getproperty(cnode, "reg", (char *) reg, sizeof(reg)); | 700 | prop = of_find_property(cnode, "reg", &plen); |
692 | if (plen <= 0 || | 701 | if (!prop || |
693 | (plen % sizeof(struct linux_prom_pci_registers)) != 0) { | 702 | (plen % sizeof(struct linux_prom_pci_registers)) != 0) { |
694 | printk("%s: OBP node %x reg property has bad len %d\n", | 703 | printk("%s: OBP node %s reg property has bad len %d\n", |
695 | pbm->name, cnode, plen); | 704 | pbm->name, cnode->full_name, plen); |
696 | goto fail; | 705 | goto fail; |
697 | } | 706 | } |
707 | reg = prop->value; | ||
698 | 708 | ||
699 | hi = reg[0].phys_hi & pbm->pbm_intmask->phys_hi; | 709 | hi = reg[0].phys_hi & pbm->pbm_intmask->phys_hi; |
700 | mid = reg[0].phys_mid & pbm->pbm_intmask->phys_mid; | 710 | mid = reg[0].phys_mid & pbm->pbm_intmask->phys_mid; |
@@ -734,8 +744,8 @@ static void __init pdev_fixup_irq(struct pci_dev *pdev) | |||
734 | struct pci_controller_info *p = pbm->parent; | 744 | struct pci_controller_info *p = pbm->parent; |
735 | unsigned int portid = pbm->portid; | 745 | unsigned int portid = pbm->portid; |
736 | unsigned int prom_irq; | 746 | unsigned int prom_irq; |
737 | int prom_node = pcp->prom_node; | 747 | struct device_node *dp = pcp->prom_node; |
738 | int err; | 748 | struct property *prop; |
739 | 749 | ||
740 | /* If this is an empty EBUS device, sometimes OBP fails to | 750 | /* If this is an empty EBUS device, sometimes OBP fails to |
741 | * give it a valid fully specified interrupts property. | 751 | * give it a valid fully specified interrupts property. |
@@ -746,17 +756,17 @@ static void __init pdev_fixup_irq(struct pci_dev *pdev) | |||
746 | */ | 756 | */ |
747 | if (pdev->vendor == PCI_VENDOR_ID_SUN && | 757 | if (pdev->vendor == PCI_VENDOR_ID_SUN && |
748 | pdev->device == PCI_DEVICE_ID_SUN_EBUS && | 758 | pdev->device == PCI_DEVICE_ID_SUN_EBUS && |
749 | !prom_getchild(prom_node)) { | 759 | !dp->child) { |
750 | pdev->irq = 0; | 760 | pdev->irq = 0; |
751 | return; | 761 | return; |
752 | } | 762 | } |
753 | 763 | ||
754 | err = prom_getproperty(prom_node, "interrupts", | 764 | prop = of_find_property(dp, "interrupts", NULL); |
755 | (char *)&prom_irq, sizeof(prom_irq)); | 765 | if (!prop) { |
756 | if (err == 0 || err == -1) { | ||
757 | pdev->irq = 0; | 766 | pdev->irq = 0; |
758 | return; | 767 | return; |
759 | } | 768 | } |
769 | prom_irq = *(unsigned int *) prop->value; | ||
760 | 770 | ||
761 | if (tlb_type != hypervisor) { | 771 | if (tlb_type != hypervisor) { |
762 | /* Fully specified already? */ | 772 | /* Fully specified already? */ |
diff --git a/arch/sparc64/kernel/pci_impl.h b/arch/sparc64/kernel/pci_impl.h index 6c3205962544..971e2bea30b4 100644 --- a/arch/sparc64/kernel/pci_impl.h +++ b/arch/sparc64/kernel/pci_impl.h | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/types.h> | 10 | #include <linux/types.h> |
11 | #include <linux/spinlock.h> | 11 | #include <linux/spinlock.h> |
12 | #include <asm/io.h> | 12 | #include <asm/io.h> |
13 | #include <asm/prom.h> | ||
13 | 14 | ||
14 | extern struct pci_controller_info *pci_controller_root; | 15 | extern struct pci_controller_info *pci_controller_root; |
15 | 16 | ||
@@ -19,7 +20,7 @@ extern int pci_num_controllers; | |||
19 | extern void pci_fixup_host_bridge_self(struct pci_bus *pbus); | 20 | extern void pci_fixup_host_bridge_self(struct pci_bus *pbus); |
20 | extern void pci_fill_in_pbm_cookies(struct pci_bus *pbus, | 21 | extern void pci_fill_in_pbm_cookies(struct pci_bus *pbus, |
21 | struct pci_pbm_info *pbm, | 22 | struct pci_pbm_info *pbm, |
22 | int prom_node); | 23 | struct device_node *prom_node); |
23 | extern void pci_record_assignments(struct pci_pbm_info *pbm, | 24 | extern void pci_record_assignments(struct pci_pbm_info *pbm, |
24 | struct pci_bus *pbus); | 25 | struct pci_bus *pbus); |
25 | extern void pci_assign_unassigned(struct pci_pbm_info *pbm, | 26 | extern void pci_assign_unassigned(struct pci_pbm_info *pbm, |
diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 40c2b6819983..5b2261ebda6f 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c | |||
@@ -1104,7 +1104,7 @@ static void pbm_scan_bus(struct pci_controller_info *p, | |||
1104 | pci_fixup_host_bridge_self(pbm->pci_bus); | 1104 | pci_fixup_host_bridge_self(pbm->pci_bus); |
1105 | pbm->pci_bus->self->sysdata = cookie; | 1105 | pbm->pci_bus->self->sysdata = cookie; |
1106 | 1106 | ||
1107 | pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node->node); | 1107 | pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node); |
1108 | pci_record_assignments(pbm, pbm->pci_bus); | 1108 | pci_record_assignments(pbm, pbm->pci_bus); |
1109 | pci_assign_unassigned(pbm, pbm->pci_bus); | 1109 | pci_assign_unassigned(pbm, pbm->pci_bus); |
1110 | pci_fixup_irq(pbm, pbm->pci_bus); | 1110 | pci_fixup_irq(pbm, pbm->pci_bus); |
diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index 4ce7b4620c09..26f194ce4400 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c | |||
@@ -1161,7 +1161,7 @@ static void sabre_scan_bus(struct pci_controller_info *p) | |||
1161 | 1161 | ||
1162 | pbus->sysdata = pbm; | 1162 | pbus->sysdata = pbm; |
1163 | pbm->pci_bus = pbus; | 1163 | pbm->pci_bus = pbus; |
1164 | pci_fill_in_pbm_cookies(pbus, pbm, pbm->prom_node->node); | 1164 | pci_fill_in_pbm_cookies(pbus, pbm, pbm->prom_node); |
1165 | pci_record_assignments(pbm, pbus); | 1165 | pci_record_assignments(pbm, pbus); |
1166 | pci_assign_unassigned(pbm, pbus); | 1166 | pci_assign_unassigned(pbm, pbus); |
1167 | pci_fixup_irq(pbm, pbus); | 1167 | pci_fixup_irq(pbm, pbus); |
@@ -1174,7 +1174,7 @@ static void sabre_scan_bus(struct pci_controller_info *p) | |||
1174 | pbm = &p->pbm_A; | 1174 | pbm = &p->pbm_A; |
1175 | sabre_bus->sysdata = pbm; | 1175 | sabre_bus->sysdata = pbm; |
1176 | pbm->pci_bus = sabre_bus; | 1176 | pbm->pci_bus = sabre_bus; |
1177 | pci_fill_in_pbm_cookies(sabre_bus, pbm, pbm->prom_node->node); | 1177 | pci_fill_in_pbm_cookies(sabre_bus, pbm, pbm->prom_node); |
1178 | pci_record_assignments(pbm, sabre_bus); | 1178 | pci_record_assignments(pbm, sabre_bus); |
1179 | pci_assign_unassigned(pbm, sabre_bus); | 1179 | pci_assign_unassigned(pbm, sabre_bus); |
1180 | pci_fixup_irq(pbm, sabre_bus); | 1180 | pci_fixup_irq(pbm, sabre_bus); |
diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index d26820086843..f16449ccd7bc 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c | |||
@@ -1438,7 +1438,7 @@ static void pbm_scan_bus(struct pci_controller_info *p, | |||
1438 | pci_fixup_host_bridge_self(pbm->pci_bus); | 1438 | pci_fixup_host_bridge_self(pbm->pci_bus); |
1439 | pbm->pci_bus->self->sysdata = cookie; | 1439 | pbm->pci_bus->self->sysdata = cookie; |
1440 | 1440 | ||
1441 | pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node->node); | 1441 | pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node); |
1442 | pci_record_assignments(pbm, pbm->pci_bus); | 1442 | pci_record_assignments(pbm, pbm->pci_bus); |
1443 | pci_assign_unassigned(pbm, pbm->pci_bus); | 1443 | pci_assign_unassigned(pbm, pbm->pci_bus); |
1444 | pci_fixup_irq(pbm, pbm->pci_bus); | 1444 | pci_fixup_irq(pbm, pbm->pci_bus); |
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index b275c7df0186..b69e2270a721 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c | |||
@@ -814,8 +814,7 @@ static void pbm_scan_bus(struct pci_controller_info *p, | |||
814 | pci_fixup_host_bridge_self(pbm->pci_bus); | 814 | pci_fixup_host_bridge_self(pbm->pci_bus); |
815 | pbm->pci_bus->self->sysdata = cookie; | 815 | pbm->pci_bus->self->sysdata = cookie; |
816 | #endif | 816 | #endif |
817 | pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, | 817 | pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node); |
818 | pbm->prom_node->node); | ||
819 | pci_record_assignments(pbm, pbm->pci_bus); | 818 | pci_record_assignments(pbm, pbm->pci_bus); |
820 | pci_assign_unassigned(pbm, pbm->pci_bus); | 819 | pci_assign_unassigned(pbm, pbm->pci_bus); |
821 | pci_fixup_irq(pbm, pbm->pci_bus); | 820 | pci_fixup_irq(pbm, pbm->pci_bus); |
diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c index 0a32b1064dfb..fb112c3c0485 100644 --- a/arch/sparc64/kernel/prom.c +++ b/arch/sparc64/kernel/prom.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/string.h> | 20 | #include <linux/string.h> |
21 | #include <linux/mm.h> | 21 | #include <linux/mm.h> |
22 | #include <linux/bootmem.h> | 22 | #include <linux/bootmem.h> |
23 | #include <linux/module.h> | ||
23 | 24 | ||
24 | #include <asm/prom.h> | 25 | #include <asm/prom.h> |
25 | #include <asm/oplib.h> | 26 | #include <asm/oplib.h> |
@@ -63,6 +64,17 @@ struct device_node *of_find_node_by_path(const char *path) | |||
63 | return np; | 64 | return np; |
64 | } | 65 | } |
65 | 66 | ||
67 | struct device_node *of_find_node_by_phandle(phandle handle) | ||
68 | { | ||
69 | struct device_node *np; | ||
70 | |||
71 | for (np = allnodes; np != 0; np = np->allnext) | ||
72 | if (np->node == handle) | ||
73 | break; | ||
74 | |||
75 | return np; | ||
76 | } | ||
77 | |||
66 | struct device_node *of_find_node_by_name(struct device_node *from, | 78 | struct device_node *of_find_node_by_name(struct device_node *from, |
67 | const char *name) | 79 | const char *name) |
68 | { | 80 | { |
@@ -103,6 +115,18 @@ struct property *of_find_property(struct device_node *np, const char *name, | |||
103 | } | 115 | } |
104 | return pp; | 116 | return pp; |
105 | } | 117 | } |
118 | EXPORT_SYMBOL(of_find_property); | ||
119 | |||
120 | /* | ||
121 | * Find a property with a given name for a given node | ||
122 | * and return the value. | ||
123 | */ | ||
124 | void *of_get_property(struct device_node *np, const char *name, int *lenp) | ||
125 | { | ||
126 | struct property *pp = of_find_property(np,name,lenp); | ||
127 | return pp ? pp->value : NULL; | ||
128 | } | ||
129 | EXPORT_SYMBOL(of_get_property); | ||
106 | 130 | ||
107 | int of_getintprop_default(struct device_node *np, const char *name, int def) | 131 | int of_getintprop_default(struct device_node *np, const char *name, int def) |
108 | { | 132 | { |
@@ -115,6 +139,7 @@ int of_getintprop_default(struct device_node *np, const char *name, int def) | |||
115 | 139 | ||
116 | return *(int *) prop->value; | 140 | return *(int *) prop->value; |
117 | } | 141 | } |
142 | EXPORT_SYMBOL(of_getintprop_default); | ||
118 | 143 | ||
119 | static unsigned int prom_early_allocated; | 144 | static unsigned int prom_early_allocated; |
120 | 145 | ||