aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2006-07-13 00:16:07 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-07-13 04:50:13 -0400
commit9bbd952e7f965757b5c913b6f98ad37a191137bd (patch)
tree134f38166dd1829c14739fcecd453f0bf2c1136d /arch
parent91d1ed1a6d225e3cf4bd8ede6235b1be65f7651a (diff)
[SPARC64]: Refine Sabre wsync logic.
It is only needed when there is a PCI-PCI bridge sitting between the device and the PCI host controller which is not a Simba APB bridge. Add logic to handle two special cases: 1) device behind EBUS, which sits on PCI 2) PCI controller interrupts Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch')
-rw-r--r--arch/sparc64/kernel/prom.c35
1 files changed, 27 insertions, 8 deletions
diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c
index 86cdbd4dbad5..c86007a2aa3f 100644
--- a/arch/sparc64/kernel/prom.c
+++ b/arch/sparc64/kernel/prom.c
@@ -539,23 +539,43 @@ 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 parent_is_sabre_or_simba(struct device_node *dp) 542static int sabre_device_needs_wsync(struct device_node *dp)
543{ 543{
544 struct device_node *parent = dp->parent;
544 char *parent_model, *parent_compat; 545 char *parent_model, *parent_compat;
545 546
546 parent_model = of_get_property(dp->parent, "model", NULL); 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);
547 if (parent_model && 566 if (parent_model &&
548 (!strcmp(parent_model, "SUNW,sabre") || 567 (!strcmp(parent_model, "SUNW,sabre") ||
549 !strcmp(parent_model, "SUNW,simba"))) 568 !strcmp(parent_model, "SUNW,simba")))
550 return 1; 569 return 0;
551 570
552 parent_compat = of_get_property(dp->parent, "compatible", NULL); 571 parent_compat = of_get_property(parent,
572 "compatible", NULL);
553 if (parent_compat && 573 if (parent_compat &&
554 (!strcmp(parent_compat, "pci108e,a000") || 574 (!strcmp(parent_compat, "pci108e,a000") ||
555 !strcmp(parent_compat, "pci108e,a001"))) 575 !strcmp(parent_compat, "pci108e,a001")))
556 return 1; 576 return 0;
557 577
558 return 0; 578 return 1;
559} 579}
560 580
561static unsigned int sabre_irq_build(struct device_node *dp, 581static unsigned int sabre_irq_build(struct device_node *dp,
@@ -602,8 +622,7 @@ static unsigned int sabre_irq_build(struct device_node *dp,
602 * is run. 622 * is run.
603 */ 623 */
604 regs = of_get_property(dp, "reg", NULL); 624 regs = of_get_property(dp, "reg", NULL);
605 if (regs && 625 if (regs && sabre_device_needs_wsync(dp)) {
606 !parent_is_sabre_or_simba(dp)) {
607 irq_install_pre_handler(virt_irq, 626 irq_install_pre_handler(virt_irq,
608 sabre_wsync_handler, 627 sabre_wsync_handler,
609 (void *) (long) regs->phys_hi, 628 (void *) (long) regs->phys_hi,