diff options
author | David S. Miller <davem@sunset.davemloft.net> | 2006-07-13 00:16:07 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-07-13 04:50:13 -0400 |
commit | 9bbd952e7f965757b5c913b6f98ad37a191137bd (patch) | |
tree | 134f38166dd1829c14739fcecd453f0bf2c1136d /arch | |
parent | 91d1ed1a6d225e3cf4bd8ede6235b1be65f7651a (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.c | 35 |
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 | ||
542 | static int parent_is_sabre_or_simba(struct device_node *dp) | 542 | static 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 | ||
561 | static unsigned int sabre_irq_build(struct device_node *dp, | 581 | static 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, |