Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+56
+56
drivers/parisc/lba_pci.c
··· 613 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 664 #else 617 665 #define truncate_pat_collision(r,n) (0) 618 666 #endif ··· 1042 994 case PAT_LMMIO: 1043 995 /* used to fix up pre-initialized MEM BARs */ 1044 996 if (!lba_dev->hba.lmmio_space.flags) { 997 + unsigned long lba_len; 998 + 999 + lba_len = ~READ_REG32(lba_dev->hba.base_addr 1000 + + LBA_LMMIO_MASK); 1001 + if ((p->end - p->start) != lba_len) 1002 + p->end = extend_lmmio_len(p->start, 1003 + p->end, lba_len); 1004 + 1045 1005 sprintf(lba_dev->hba.lmmio_name, 1046 1006 "PCI%02x LMMIO", 1047 1007 (int)lba_dev->hba.bus_num.start);