diff options
Diffstat (limited to 'arch/sparc64/kernel/pci_common.c')
-rw-r--r-- | arch/sparc64/kernel/pci_common.c | 196 |
1 files changed, 103 insertions, 93 deletions
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? */ |