aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/prom.c
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2006-07-17 09:25:26 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2006-07-17 09:25:26 -0400
commit4bf311ddfbffe12d41ad1a3c311ab727db6f72cb (patch)
tree9d19a2774e83637d86dc876f3af22af1dacf0bec /arch/sparc64/kernel/prom.c
parent597d0cae0f99f62501e229bed50e8149604015bb (diff)
parent82d6897fefca6206bca7153805b4c5359ce97fc4 (diff)
Merge branch 'master'
Diffstat (limited to 'arch/sparc64/kernel/prom.c')
-rw-r--r--arch/sparc64/kernel/prom.c51
1 files changed, 46 insertions, 5 deletions
diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c
index 99daeee4209d..c86007a2aa3f 100644
--- a/arch/sparc64/kernel/prom.c
+++ b/arch/sparc64/kernel/prom.c
@@ -539,6 +539,45 @@ static unsigned long __sabre_onboard_imap_off[] = {
539 ((ino & 0x20) ? (SABRE_ICLR_SCSI + (((ino) & 0x1f) << 3)) : \ 539 ((ino & 0x20) ? (SABRE_ICLR_SCSI + (((ino) & 0x1f) << 3)) : \
540 (SABRE_ICLR_A_SLOT0 + (((ino) & 0x1f)<<3))) 540 (SABRE_ICLR_A_SLOT0 + (((ino) & 0x1f)<<3)))
541 541
542static int sabre_device_needs_wsync(struct device_node *dp)
543{
544 struct device_node *parent = dp->parent;
545 char *parent_model, *parent_compat;
546
547 /* This traversal up towards the root is meant to
548 * handle two cases:
549 *
550 * 1) non-PCI bus sitting under PCI, such as 'ebus'
551 * 2) the PCI controller interrupts themselves, which
552 * will use the sabre_irq_build but do not need
553 * the DMA synchronization handling
554 */
555 while (parent) {
556 if (!strcmp(parent->type, "pci"))
557 break;
558 parent = parent->parent;
559 }
560
561 if (!parent)
562 return 0;
563
564 parent_model = of_get_property(parent,
565 "model", NULL);
566 if (parent_model &&
567 (!strcmp(parent_model, "SUNW,sabre") ||
568 !strcmp(parent_model, "SUNW,simba")))
569 return 0;
570
571 parent_compat = of_get_property(parent,
572 "compatible", NULL);
573 if (parent_compat &&
574 (!strcmp(parent_compat, "pci108e,a000") ||
575 !strcmp(parent_compat, "pci108e,a001")))
576 return 0;
577
578 return 1;
579}
580
542static unsigned int sabre_irq_build(struct device_node *dp, 581static unsigned int sabre_irq_build(struct device_node *dp,
543 unsigned int ino, 582 unsigned int ino,
544 void *_data) 583 void *_data)
@@ -577,15 +616,17 @@ static unsigned int sabre_irq_build(struct device_node *dp,
577 616
578 virt_irq = build_irq(inofixup, iclr, imap); 617 virt_irq = build_irq(inofixup, iclr, imap);
579 618
619 /* If the parent device is a PCI<->PCI bridge other than
620 * APB, we have to install a pre-handler to ensure that
621 * all pending DMA is drained before the interrupt handler
622 * is run.
623 */
580 regs = of_get_property(dp, "reg", NULL); 624 regs = of_get_property(dp, "reg", NULL);
581 if (regs && 625 if (regs && sabre_device_needs_wsync(dp)) {
582 ((regs->phys_hi >> 16) & 0xff) != irq_data->pci_first_busno) {
583 irq_install_pre_handler(virt_irq, 626 irq_install_pre_handler(virt_irq,
584 sabre_wsync_handler, 627 sabre_wsync_handler,
585 (void *) (long) regs->phys_hi, 628 (void *) (long) regs->phys_hi,
586 (void *) 629 (void *) irq_data);
587 controller_regs +
588 SABRE_WRSYNC);
589 } 630 }
590 631
591 return virt_irq; 632 return virt_irq;