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

powerpc/pci: Support per-aperture memory offset

The PCI core supports an offset per aperture nowadays but our arch
code still has a single offset per host bridge representing the
difference betwen CPU memory addresses and PCI MMIO addresses.

This is a problem as new machines and hypervisor versions are
coming out where the 64-bit windows will have a different offset
(basically mapped 1:1) from the 32-bit windows.

This fixes it by using separate offsets. In the long run, we probably
want to get rid of that intermediary struct pci_controller and have
those directly stored into the pci_host_bridge as they are parsed
but this will be a more invasive change.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

+54 -104
+1 -5
arch/powerpc/include/asm/pci-bridge.h
··· 39 39 resource_size_t io_base_phys; 40 40 resource_size_t pci_io_size; 41 41 42 - /* Some machines (PReP) have a non 1:1 mapping of 43 - * the PCI memory space in the CPU bus space 44 - */ 45 - resource_size_t pci_mem_offset; 46 - 47 42 /* Some machines have a special region to forward the ISA 48 43 * "memory" cycles such as VGA memory regions. Left to 0 49 44 * if unsupported ··· 81 86 */ 82 87 struct resource io_resource; 83 88 struct resource mem_resources[3]; 89 + resource_size_t mem_offset[3]; 84 90 int global_number; /* PCI domain number */ 85 91 86 92 resource_size_t dma_window_base_cur;
+28 -69
arch/powerpc/kernel/pci-common.c
··· 786 786 hose->isa_mem_size = size; 787 787 } 788 788 789 - /* We get the PCI/Mem offset from the first range or 790 - * the, current one if the offset came from an ISA 791 - * hole. If they don't match, bugger. 792 - */ 793 - if (memno == 0 || 794 - (isa_hole >= 0 && pci_addr != 0 && 795 - hose->pci_mem_offset == isa_mb)) 796 - hose->pci_mem_offset = cpu_addr - pci_addr; 797 - else if (pci_addr != 0 && 798 - hose->pci_mem_offset != cpu_addr - pci_addr) { 799 - printk(KERN_INFO 800 - " \\--> Skipped (offset mismatch) !\n"); 801 - continue; 802 - } 803 - 804 789 /* Build resource */ 790 + hose->mem_offset[memno] = cpu_addr - pci_addr; 805 791 res = &hose->mem_resources[memno++]; 806 792 res->flags = IORESOURCE_MEM; 807 793 if (pci_space & 0x40000000) ··· 802 816 res->sibling = NULL; 803 817 res->child = NULL; 804 818 } 805 - } 806 - 807 - /* If there's an ISA hole and the pci_mem_offset is -not- matching 808 - * the ISA hole offset, then we need to remove the ISA hole from 809 - * the resource list for that brige 810 - */ 811 - if (isa_hole >= 0 && hose->pci_mem_offset != isa_mb) { 812 - unsigned int next = isa_hole + 1; 813 - printk(KERN_INFO " Removing ISA hole at 0x%016llx\n", isa_mb); 814 - if (next < memno) 815 - memmove(&hose->mem_resources[isa_hole], 816 - &hose->mem_resources[next], 817 - sizeof(struct resource) * (memno - next)); 818 - hose->mem_resources[--memno].flags = 0; 819 819 } 820 820 } 821 821 ··· 888 916 struct pci_controller *hose = pci_bus_to_host(bus); 889 917 struct pci_dev *dev = bus->self; 890 918 resource_size_t offset; 919 + struct pci_bus_region region; 891 920 u16 command; 892 921 int i; 893 922 ··· 898 925 899 926 /* Job is a bit different between memory and IO */ 900 927 if (res->flags & IORESOURCE_MEM) { 901 - /* If the BAR is non-0 (res != pci_mem_offset) then it's probably been 902 - * initialized by somebody 903 - */ 904 - if (res->start != hose->pci_mem_offset) 928 + pcibios_resource_to_bus(dev, &region, res); 929 + 930 + /* If the BAR is non-0 then it's probably been initialized */ 931 + if (region.start != 0) 905 932 return 0; 906 933 907 934 /* The BAR is 0, let's check if memory decoding is enabled on ··· 913 940 914 941 /* Memory decoding is enabled and the BAR is 0. If any of the bridge 915 942 * resources covers that starting address (0 then it's good enough for 916 - * us for memory 943 + * us for memory space) 917 944 */ 918 945 for (i = 0; i < 3; i++) { 919 946 if ((hose->mem_resources[i].flags & IORESOURCE_MEM) && 920 - hose->mem_resources[i].start == hose->pci_mem_offset) 947 + hose->mem_resources[i].start == hose->mem_offset[i]) 921 948 return 0; 922 949 } 923 950 ··· 1354 1381 1355 1382 no_io: 1356 1383 /* Check for memory */ 1357 - offset = hose->pci_mem_offset; 1358 - pr_debug("hose mem offset: %016llx\n", (unsigned long long)offset); 1359 1384 for (i = 0; i < 3; i++) { 1360 1385 pres = &hose->mem_resources[i]; 1386 + offset = hose->mem_offset[i]; 1361 1387 if (!(pres->flags & IORESOURCE_MEM)) 1362 1388 continue; 1363 1389 pr_debug("hose mem res: %pR\n", pres); ··· 1496 1524 struct list_head *resources) 1497 1525 { 1498 1526 struct resource *res; 1527 + resource_size_t offset; 1499 1528 int i; 1500 1529 1501 1530 /* Hookup PHB IO resource */ ··· 1506 1533 printk(KERN_WARNING "PCI: I/O resource not set for host" 1507 1534 " bridge %s (domain %d)\n", 1508 1535 hose->dn->full_name, hose->global_number); 1509 - #ifdef CONFIG_PPC32 1510 - /* Workaround for lack of IO resource only on 32-bit */ 1511 - res->start = (unsigned long)hose->io_base_virt - isa_io_base; 1512 - res->end = res->start + IO_SPACE_LIMIT; 1513 - res->flags = IORESOURCE_IO; 1514 - #endif /* CONFIG_PPC32 */ 1515 - } 1516 - if (res->flags) { 1517 - pr_debug("PCI: PHB IO resource = %016llx-%016llx [%lx]\n", 1536 + } else { 1537 + offset = pcibios_io_space_offset(hose); 1538 + 1539 + pr_debug("PCI: PHB IO resource = %08llx-%08llx [%lx] off 0x%08llx\n", 1518 1540 (unsigned long long)res->start, 1519 1541 (unsigned long long)res->end, 1520 - (unsigned long)res->flags); 1521 - pci_add_resource_offset(resources, res, pcibios_io_space_offset(hose)); 1522 - 1523 - pr_debug("PCI: PHB IO offset = %08lx\n", 1524 - (unsigned long)hose->io_base_virt - _IO_BASE); 1542 + (unsigned long)res->flags, 1543 + (unsigned long long)offset); 1544 + pci_add_resource_offset(resources, res, offset); 1525 1545 } 1526 1546 1527 1547 /* Hookup PHB Memory resources */ 1528 1548 for (i = 0; i < 3; ++i) { 1529 1549 res = &hose->mem_resources[i]; 1530 1550 if (!res->flags) { 1531 - if (i > 0) 1532 - continue; 1533 1551 printk(KERN_ERR "PCI: Memory resource 0 not set for " 1534 1552 "host bridge %s (domain %d)\n", 1535 1553 hose->dn->full_name, hose->global_number); 1536 - #ifdef CONFIG_PPC32 1537 - /* Workaround for lack of MEM resource only on 32-bit */ 1538 - res->start = hose->pci_mem_offset; 1539 - res->end = (resource_size_t)-1LL; 1540 - res->flags = IORESOURCE_MEM; 1541 - #endif /* CONFIG_PPC32 */ 1554 + continue; 1542 1555 } 1543 - if (res->flags) { 1544 - pr_debug("PCI: PHB MEM resource %d = %016llx-%016llx [%lx]\n", i, 1545 - (unsigned long long)res->start, 1546 - (unsigned long long)res->end, 1547 - (unsigned long)res->flags); 1548 - pci_add_resource_offset(resources, res, hose->pci_mem_offset); 1549 - } 1550 - } 1556 + offset = hose->mem_offset[i]; 1551 1557 1552 - pr_debug("PCI: PHB MEM offset = %016llx\n", 1553 - (unsigned long long)hose->pci_mem_offset); 1558 + 1559 + pr_debug("PCI: PHB MEM resource %d = %08llx-%08llx [%lx] off 0x%08llx\n", i, 1560 + (unsigned long long)res->start, 1561 + (unsigned long long)res->end, 1562 + (unsigned long)res->flags, 1563 + (unsigned long long)offset); 1564 + 1565 + pci_add_resource_offset(resources, res, offset); 1566 + } 1554 1567 } 1555 1568 1556 1569 /*
+1 -1
arch/powerpc/kernel/pci_32.c
··· 295 295 case IOBASE_BRIDGE_NUMBER: 296 296 return (long)hose->first_busno; 297 297 case IOBASE_MEMORY: 298 - return (long)hose->pci_mem_offset; 298 + return (long)hose->mem_offset[0]; 299 299 case IOBASE_IO: 300 300 return (long)hose->io_base_phys; 301 301 case IOBASE_ISA_IO:
+1 -1
arch/powerpc/kernel/pci_64.c
··· 246 246 case IOBASE_BRIDGE_NUMBER: 247 247 return (long)hose->first_busno; 248 248 case IOBASE_MEMORY: 249 - return (long)hose->pci_mem_offset; 249 + return (long)hose->mem_offset[0]; 250 250 case IOBASE_IO: 251 251 return (long)hose->io_base_phys; 252 252 case IOBASE_ISA_IO:
-11
arch/powerpc/platforms/embedded6xx/mpc10x.h
··· 81 81 #define MPC10X_MAPB_PCI_MEM_OFFSET (MPC10X_MAPB_ISA_MEM_BASE - \ 82 82 MPC10X_MAPB_PCI_MEM_START) 83 83 84 - /* Set hose members to values appropriate for the mem map used */ 85 - #define MPC10X_SETUP_HOSE(hose, map) { \ 86 - (hose)->pci_mem_offset = MPC10X_MAP##map##_PCI_MEM_OFFSET; \ 87 - (hose)->io_space.start = MPC10X_MAP##map##_PCI_IO_START; \ 88 - (hose)->io_space.end = MPC10X_MAP##map##_PCI_IO_END; \ 89 - (hose)->mem_space.start = MPC10X_MAP##map##_PCI_MEM_START; \ 90 - (hose)->mem_space.end = MPC10X_MAP##map##_PCI_MEM_END; \ 91 - (hose)->io_base_virt = (void *)MPC10X_MAP##map##_ISA_IO_BASE; \ 92 - } 93 - 94 - 95 84 /* Miscellaneous Configuration register offsets */ 96 85 #define MPC10X_CFG_PIR_REG 0x09 97 86 #define MPC10X_CFG_PIR_HOST_BRIDGE 0x00
+1 -1
arch/powerpc/platforms/powermac/pci.c
··· 824 824 hose->mem_resources[cur].name = hose->dn->full_name; 825 825 hose->mem_resources[cur].start = base; 826 826 hose->mem_resources[cur].end = end; 827 + hose->mem_offset[cur] = 0; 827 828 DBG(" %d: 0x%08lx-0x%08lx\n", cur, base, end); 828 829 } else { 829 830 DBG(" : -0x%08lx\n", end); ··· 867 866 hose->io_resource.start = 0; 868 867 hose->io_resource.end = 0x003fffff; 869 868 hose->io_resource.flags = IORESOURCE_IO; 870 - hose->pci_mem_offset = 0; 871 869 hose->first_busno = 0; 872 870 hose->last_busno = 0xef; 873 871
+6 -4
arch/powerpc/platforms/powernv/pci-ioda.c
··· 915 915 index++; 916 916 } 917 917 } else if (res->flags & IORESOURCE_MEM) { 918 + /* WARNING: Assumes M32 is mem region 0 in PHB. We need to 919 + * harden that algorithm when we start supporting M64 920 + */ 918 921 region.start = res->start - 919 - hose->pci_mem_offset - 922 + hose->mem_offset[0] - 920 923 phb->ioda.m32_pci_base; 921 924 region.end = res->end - 922 - hose->pci_mem_offset - 925 + hose->mem_offset[0] - 923 926 phb->ioda.m32_pci_base; 924 927 index = region.start / phb->ioda.m32_segsize; 925 928 ··· 1118 1115 phb->ioda.m32_size += 0x10000; 1119 1116 1120 1117 phb->ioda.m32_segsize = phb->ioda.m32_size / phb->ioda.total_pe; 1121 - phb->ioda.m32_pci_base = hose->mem_resources[0].start - 1122 - hose->pci_mem_offset; 1118 + phb->ioda.m32_pci_base = hose->mem_resources[0].start - hose->mem_offset[0]; 1123 1119 phb->ioda.io_size = hose->pci_io_size; 1124 1120 phb->ioda.io_segsize = phb->ioda.io_size / phb->ioda.total_pe; 1125 1121 phb->ioda.io_pci_base = 0; /* XXX calculate this ? */
+1 -1
arch/powerpc/platforms/wsp/wsp_pci.c
··· 502 502 (~(hose->mem_resources[0].end - 503 503 hose->mem_resources[0].start)) & 0x3ffffff0000ul); 504 504 out_be64(hose->cfg_data + PCIE_REG_M32A_START_ADDR, 505 - (hose->mem_resources[0].start - hose->pci_mem_offset) | 1); 505 + (hose->mem_resources[0].start - hose->mem_offset[0]) | 1); 506 506 507 507 /* Clear all TVT entries 508 508 *
+6 -5
arch/powerpc/sysdev/fsl_pci.c
··· 178 178 struct ccsr_pci __iomem *pci = hose->private_data; 179 179 int i, j, n, mem_log, win_idx = 3, start_idx = 1, end_idx = 4; 180 180 u64 mem, sz, paddr_hi = 0; 181 - u64 paddr_lo = ULLONG_MAX; 181 + u64 offset = 0, paddr_lo = ULLONG_MAX; 182 182 u32 pcicsrbar = 0, pcicsrbar_sz; 183 183 u32 piwar = PIWAR_EN | PIWAR_PF | PIWAR_TGI_LOCAL | 184 184 PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP; ··· 208 208 paddr_lo = min(paddr_lo, (u64)hose->mem_resources[i].start); 209 209 paddr_hi = max(paddr_hi, (u64)hose->mem_resources[i].end); 210 210 211 - n = setup_one_atmu(pci, j, &hose->mem_resources[i], 212 - hose->pci_mem_offset); 211 + /* We assume all memory resources have the same offset */ 212 + offset = hose->mem_offset[i]; 213 + n = setup_one_atmu(pci, j, &hose->mem_resources[i], offset); 213 214 214 215 if (n < 0 || j >= 5) { 215 216 pr_err("Ran out of outbound PCI ATMUs for resource %d!\n", i); ··· 240 239 } 241 240 242 241 /* convert to pci address space */ 243 - paddr_hi -= hose->pci_mem_offset; 244 - paddr_lo -= hose->pci_mem_offset; 242 + paddr_hi -= offset; 243 + paddr_lo -= offset; 245 244 246 245 if (paddr_hi == paddr_lo) { 247 246 pr_err("%s: No outbound window space\n", name);
+9 -6
arch/powerpc/sysdev/ppc4xx_pci.c
··· 257 257 /* Setup outbound memory windows */ 258 258 for (i = j = 0; i < 3; i++) { 259 259 struct resource *res = &hose->mem_resources[i]; 260 + resource_size_t offset = hose->mem_offset[i]; 260 261 261 262 /* we only care about memory windows */ 262 263 if (!(res->flags & IORESOURCE_MEM)) ··· 271 270 /* Configure the resource */ 272 271 if (ppc4xx_setup_one_pci_PMM(hose, reg, 273 272 res->start, 274 - res->start - hose->pci_mem_offset, 273 + res->start - offset, 275 274 resource_size(res), 276 275 res->flags, 277 276 j) == 0) { ··· 280 279 /* If the resource PCI address is 0 then we have our 281 280 * ISA memory hole 282 281 */ 283 - if (res->start == hose->pci_mem_offset) 282 + if (res->start == offset) 284 283 found_isa_hole = 1; 285 284 } 286 285 } ··· 458 457 /* Setup outbound memory windows */ 459 458 for (i = j = 0; i < 3; i++) { 460 459 struct resource *res = &hose->mem_resources[i]; 460 + resource_size_t offset = hose->mem_offset[i]; 461 461 462 462 /* we only care about memory windows */ 463 463 if (!(res->flags & IORESOURCE_MEM)) ··· 472 470 /* Configure the resource */ 473 471 if (ppc4xx_setup_one_pcix_POM(hose, reg, 474 472 res->start, 475 - res->start - hose->pci_mem_offset, 473 + res->start - offset, 476 474 resource_size(res), 477 475 res->flags, 478 476 j) == 0) { ··· 481 479 /* If the resource PCI address is 0 then we have our 482 480 * ISA memory hole 483 481 */ 484 - if (res->start == hose->pci_mem_offset) 482 + if (res->start == offset) 485 483 found_isa_hole = 1; 486 484 } 487 485 } ··· 1794 1792 /* Setup outbound memory windows */ 1795 1793 for (i = j = 0; i < 3; i++) { 1796 1794 struct resource *res = &hose->mem_resources[i]; 1795 + resource_size_t offset = hose->mem_offset[i]; 1797 1796 1798 1797 /* we only care about memory windows */ 1799 1798 if (!(res->flags & IORESOURCE_MEM)) ··· 1808 1805 /* Configure the resource */ 1809 1806 if (ppc4xx_setup_one_pciex_POM(port, hose, mbase, 1810 1807 res->start, 1811 - res->start - hose->pci_mem_offset, 1808 + res->start - offset, 1812 1809 resource_size(res), 1813 1810 res->flags, 1814 1811 j) == 0) { ··· 1817 1814 /* If the resource PCI address is 0 then we have our 1818 1815 * ISA memory hole 1819 1816 */ 1820 - if (res->start == hose->pci_mem_offset) 1817 + if (res->start == offset) 1821 1818 found_isa_hole = 1; 1822 1819 } 1823 1820 }