diff options
-rw-r--r-- | drivers/parisc/lba_pci.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index 1f05913ae677..19f6f70c67d3 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c | |||
@@ -613,6 +613,54 @@ truncate_pat_collision(struct resource *root, struct resource *new) | |||
613 | return 0; /* truncation successful */ | 613 | return 0; /* truncation successful */ |
614 | } | 614 | } |
615 | 615 | ||
616 | /* | ||
617 | * extend_lmmio_len: extend lmmio range to maximum length | ||
618 | * | ||
619 | * This is needed at least on C8000 systems to get the ATI FireGL card | ||
620 | * working. On other systems we will currently not extend the lmmio space. | ||
621 | */ | ||
622 | static unsigned long | ||
623 | extend_lmmio_len(unsigned long start, unsigned long end, unsigned long lba_len) | ||
624 | { | ||
625 | struct resource *tmp; | ||
626 | |||
627 | pr_debug("LMMIO mismatch: PAT length = 0x%lx, MASK register = 0x%lx\n", | ||
628 | end - start, lba_len); | ||
629 | |||
630 | lba_len = min(lba_len+1, 256UL*1024*1024); /* limit to 256 MB */ | ||
631 | |||
632 | pr_debug("LBA: lmmio_space [0x%lx-0x%lx] - original\n", start, end); | ||
633 | |||
634 | if (boot_cpu_data.cpu_type < mako) { | ||
635 | pr_info("LBA: Not a C8000 system - not extending LMMIO range.\n"); | ||
636 | return end; | ||
637 | } | ||
638 | |||
639 | end += lba_len; | ||
640 | if (end < start) /* fix overflow */ | ||
641 | end = -1ULL; | ||
642 | |||
643 | pr_debug("LBA: lmmio_space [0x%lx-0x%lx] - current\n", start, end); | ||
644 | |||
645 | /* first overlap */ | ||
646 | for (tmp = iomem_resource.child; tmp; tmp = tmp->sibling) { | ||
647 | pr_debug("LBA: testing %pR\n", tmp); | ||
648 | if (tmp->start == start) | ||
649 | continue; /* ignore ourself */ | ||
650 | if (tmp->end < start) | ||
651 | continue; | ||
652 | if (tmp->start > end) | ||
653 | continue; | ||
654 | if (end >= tmp->start) | ||
655 | end = tmp->start - 1; | ||
656 | } | ||
657 | |||
658 | pr_info("LBA: lmmio_space [0x%lx-0x%lx] - new\n", start, end); | ||
659 | |||
660 | /* return new end */ | ||
661 | return end; | ||
662 | } | ||
663 | |||
616 | #else | 664 | #else |
617 | #define truncate_pat_collision(r,n) (0) | 665 | #define truncate_pat_collision(r,n) (0) |
618 | #endif | 666 | #endif |
@@ -994,6 +1042,14 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) | |||
994 | case PAT_LMMIO: | 1042 | case PAT_LMMIO: |
995 | /* used to fix up pre-initialized MEM BARs */ | 1043 | /* used to fix up pre-initialized MEM BARs */ |
996 | if (!lba_dev->hba.lmmio_space.flags) { | 1044 | if (!lba_dev->hba.lmmio_space.flags) { |
1045 | unsigned long lba_len; | ||
1046 | |||
1047 | lba_len = ~READ_REG32(lba_dev->hba.base_addr | ||
1048 | + LBA_LMMIO_MASK); | ||
1049 | if ((p->end - p->start) != lba_len) | ||
1050 | p->end = extend_lmmio_len(p->start, | ||
1051 | p->end, lba_len); | ||
1052 | |||
997 | sprintf(lba_dev->hba.lmmio_name, | 1053 | sprintf(lba_dev->hba.lmmio_name, |
998 | "PCI%02x LMMIO", | 1054 | "PCI%02x LMMIO", |
999 | (int)lba_dev->hba.bus_num.start); | 1055 | (int)lba_dev->hba.bus_num.start); |