From: David S. Miller Date: Thu, 13 Jul 2006 04:16:07 +0000 (-0700) Subject: [SPARC64]: Refine Sabre wsync logic. X-Git-Tag: v2.6.18-rc2~90^2~1 X-Git-Url: http://pilppa.com/gitweb/?a=commitdiff_plain;h=9bbd952e7f965757b5c913b6f98ad37a191137bd;p=linux-2.6-omap-h63xx.git [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 --- diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c index 86cdbd4dbad..c86007a2aa3 100644 --- a/arch/sparc64/kernel/prom.c +++ b/arch/sparc64/kernel/prom.c @@ -539,23 +539,43 @@ static unsigned long __sabre_onboard_imap_off[] = { ((ino & 0x20) ? (SABRE_ICLR_SCSI + (((ino) & 0x1f) << 3)) : \ (SABRE_ICLR_A_SLOT0 + (((ino) & 0x1f)<<3))) -static int parent_is_sabre_or_simba(struct device_node *dp) +static int sabre_device_needs_wsync(struct device_node *dp) { + struct device_node *parent = dp->parent; char *parent_model, *parent_compat; - parent_model = of_get_property(dp->parent, "model", NULL); + /* This traversal up towards the root is meant to + * handle two cases: + * + * 1) non-PCI bus sitting under PCI, such as 'ebus' + * 2) the PCI controller interrupts themselves, which + * will use the sabre_irq_build but do not need + * the DMA synchronization handling + */ + while (parent) { + if (!strcmp(parent->type, "pci")) + break; + parent = parent->parent; + } + + if (!parent) + return 0; + + parent_model = of_get_property(parent, + "model", NULL); if (parent_model && (!strcmp(parent_model, "SUNW,sabre") || !strcmp(parent_model, "SUNW,simba"))) - return 1; + return 0; - parent_compat = of_get_property(dp->parent, "compatible", NULL); + parent_compat = of_get_property(parent, + "compatible", NULL); if (parent_compat && (!strcmp(parent_compat, "pci108e,a000") || !strcmp(parent_compat, "pci108e,a001"))) - return 1; + return 0; - return 0; + return 1; } static unsigned int sabre_irq_build(struct device_node *dp, @@ -602,8 +622,7 @@ static unsigned int sabre_irq_build(struct device_node *dp, * is run. */ regs = of_get_property(dp, "reg", NULL); - if (regs && - !parent_is_sabre_or_simba(dp)) { + if (regs && sabre_device_needs_wsync(dp)) { irq_install_pre_handler(virt_irq, sabre_wsync_handler, (void *) (long) regs->phys_hi,