aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/parisc
diff options
context:
space:
mode:
authorHelge Deller <deller@gmx.de>2013-06-18 17:21:25 -0400
committerHelge Deller <deller@gmx.de>2013-07-09 16:09:16 -0400
commitdac76f1be5beaea4af9afe85fb475c73de0b8731 (patch)
tree83112c5476a2c021a76818c172545107ac93fd03 /drivers/parisc
parentd2b4a646717153a1a180b64d4a8464054dbd700e (diff)
parisc: fix LMMIO mismatch between PAT length and MASK register
The LMMIO length reported by PAT and the length given by the LBA MASK register are not consistent. This leads e.g. to a not-working ATI FireGL card with the radeon DRM driver since the memory can't be mapped. Fix this by correctly adjusting the resource sizes. Signed-off-by: Helge Deller <deller@gmx.de> Cc: <stable@vger.kernel.org> # 3.10
Diffstat (limited to 'drivers/parisc')
-rw-r--r--drivers/parisc/lba_pci.c56
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 */
622static unsigned long
623extend_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);