Commit 9bbd952e7f965757b5c913b6f98ad37a191137bd

Authored by David S. Miller
1 parent 91d1ed1a6d

[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>

Showing 1 changed file with 27 additions and 8 deletions Side-by-side Diff

arch/sparc64/kernel/prom.c
... ... @@ -539,23 +539,43 @@
539 539 ((ino & 0x20) ? (SABRE_ICLR_SCSI + (((ino) & 0x1f) << 3)) : \
540 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 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 566 if (parent_model &&
548 567 (!strcmp(parent_model, "SUNW,sabre") ||
549 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 573 if (parent_compat &&
554 574 (!strcmp(parent_compat, "pci108e,a000") ||
555 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 581 static unsigned int sabre_irq_build(struct device_node *dp,
... ... @@ -602,8 +622,7 @@
602 622 * is run.
603 623 */
604 624 regs = of_get_property(dp, "reg", NULL);
605   - if (regs &&
606   - !parent_is_sabre_or_simba(dp)) {
  625 + if (regs && sabre_device_needs_wsync(dp)) {
607 626 irq_install_pre_handler(virt_irq,
608 627 sabre_wsync_handler,
609 628 (void *) (long) regs->phys_hi,