aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/of_device.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2006-07-17 01:10:44 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-07-21 17:17:52 -0400
commit46ba6d7d8b0486e9d565729880ddfb2b84d3af31 (patch)
tree53f6eb1eb20d9adb45af5a78b440ae7ae3257990 /arch/sparc64/kernel/of_device.c
parent00ab956f2fefd3673edc16df55beed21834b7bdd (diff)
[SPARC64]: Fix more of_device layer IRQ bugs, and correct PROMREG_MAX.
Sabre and Psycho PCI controllers can have partial interrupt-map properties, meaning that on-board devices don't match up to any entries. Instead, they are fully specified from the beginning and we should pass them directly to the IRQ translator as-is. Also, fill in the necessary translator slots for the "graphics" and "expansion UPA" interrupts on Sabre, Psycho, and SYSIO SBUS. Increase PROMREG_MAX to 24, as seen on SUNW,ffb devices. Finally, prevent accidentally writing past the end of the of_device struct resource[] and irqs[] arrays. Spit out a log message when we ignore some entries because there are too many of them. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64/kernel/of_device.c')
-rw-r--r--arch/sparc64/kernel/of_device.c34
1 files changed, 32 insertions, 2 deletions
diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c
index 7064cee290ae..238bbf6de07d 100644
--- a/arch/sparc64/kernel/of_device.c
+++ b/arch/sparc64/kernel/of_device.c
@@ -542,9 +542,17 @@ static void __init build_device_resources(struct of_device *op,
542 /* Convert to num-cells. */ 542 /* Convert to num-cells. */
543 num_reg /= 4; 543 num_reg /= 4;
544 544
545 /* Conver to num-entries. */ 545 /* Convert to num-entries. */
546 num_reg /= na + ns; 546 num_reg /= na + ns;
547 547
548 /* Prevent overruning the op->resources[] array. */
549 if (num_reg > PROMREG_MAX) {
550 printk(KERN_WARNING "%s: Too many regs (%d), "
551 "limiting to %d.\n",
552 op->node->full_name, num_reg, PROMREG_MAX);
553 num_reg = PROMREG_MAX;
554 }
555
548 for (index = 0; index < num_reg; index++) { 556 for (index = 0; index < num_reg; index++) {
549 struct resource *r = &op->resource[index]; 557 struct resource *r = &op->resource[index];
550 u32 addr[OF_MAX_ADDR_CELLS]; 558 u32 addr[OF_MAX_ADDR_CELLS];
@@ -650,8 +658,22 @@ apply_interrupt_map(struct device_node *dp, struct device_node *pp,
650 next: 658 next:
651 imap += (na + 3); 659 imap += (na + 3);
652 } 660 }
653 if (i == imlen) 661 if (i == imlen) {
662 /* Psycho and Sabre PCI controllers can have 'interrupt-map'
663 * properties that do not include the on-board device
664 * interrupts. Instead, the device's 'interrupts' property
665 * is already a fully specified INO value.
666 *
667 * Handle this by deciding that, if we didn't get a
668 * match in the parent's 'interrupt-map', and the
669 * parent is an IRQ translater, then use the parent as
670 * our IRQ controller.
671 */
672 if (pp->irq_trans)
673 return pp;
674
654 return NULL; 675 return NULL;
676 }
655 677
656 *irq_p = irq; 678 *irq_p = irq;
657 cp = of_find_node_by_phandle(handle); 679 cp = of_find_node_by_phandle(handle);
@@ -803,6 +825,14 @@ static struct of_device * __init scan_one_device(struct device_node *dp,
803 op->num_irqs = 0; 825 op->num_irqs = 0;
804 } 826 }
805 827
828 /* Prevent overruning the op->irqs[] array. */
829 if (op->num_irqs > PROMINTR_MAX) {
830 printk(KERN_WARNING "%s: Too many irqs (%d), "
831 "limiting to %d.\n",
832 dp->full_name, op->num_irqs, PROMINTR_MAX);
833 op->num_irqs = PROMINTR_MAX;
834 }
835
806 build_device_resources(op, parent); 836 build_device_resources(op, parent);
807 for (i = 0; i < op->num_irqs; i++) 837 for (i = 0; i < op->num_irqs; i++)
808 op->irqs[i] = build_one_device_irq(op, parent, op->irqs[i]); 838 op->irqs[i] = build_one_device_irq(op, parent, op->irqs[i]);