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

Configure Feed

Select the types of activity you want to include in your feed.

powerpc/pseries/iommu: create DDW for devices with DMA mask less than 64-bits

Starting with PAPR level 2.13, platform supports placing PHB in limited
address mode. Devices that support DMA masks less that 64-bit but greater
than 32-bits are placed in limited address mode. In this mode, the
starting DMA address returned by the DDW is 4GB.

When the device driver calls dma_supported, with mask less then 64-bit, the
PowerPC IOMMU driver places PHB in the Limited Addressing Mode before
creating DDW.

Signed-off-by: Gaurav Batra <gbatra@linux.ibm.com>
Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com>
Link: https://patch.msgid.link/20250108164814.73250-1-gbatra@linux.ibm.com

authored by

Gaurav Batra and committed by
Madhavan Srinivasan
67dfc119 ddcb883f

+94 -16
+94 -16
arch/powerpc/platforms/pseries/iommu.c
··· 52 52 enum { 53 53 DDW_EXT_SIZE = 0, 54 54 DDW_EXT_RESET_DMA_WIN = 1, 55 - DDW_EXT_QUERY_OUT_SIZE = 2 55 + DDW_EXT_QUERY_OUT_SIZE = 2, 56 + DDW_EXT_LIMITED_ADDR_MODE = 3 56 57 }; 57 58 58 59 static struct iommu_table *iommu_pseries_alloc_table(int node) ··· 1332 1331 ret); 1333 1332 } 1334 1333 1334 + /* 1335 + * Platforms support placing PHB in limited address mode starting with LoPAR 1336 + * level 2.13 implement. In this mode, the DMA address returned by DDW is over 1337 + * 4GB but, less than 64-bits. This benefits IO adapters that don't support 1338 + * 64-bits for DMA addresses. 1339 + */ 1340 + static int limited_dma_window(struct pci_dev *dev, struct device_node *par_dn) 1341 + { 1342 + int ret; 1343 + u32 cfg_addr, reset_dma_win, las_supported; 1344 + u64 buid; 1345 + struct device_node *dn; 1346 + struct pci_dn *pdn; 1347 + 1348 + ret = ddw_read_ext(par_dn, DDW_EXT_RESET_DMA_WIN, &reset_dma_win); 1349 + if (ret) 1350 + goto out; 1351 + 1352 + ret = ddw_read_ext(par_dn, DDW_EXT_LIMITED_ADDR_MODE, &las_supported); 1353 + 1354 + /* Limited Address Space extension available on the platform but DDW in 1355 + * limited addressing mode not supported 1356 + */ 1357 + if (!ret && !las_supported) 1358 + ret = -EPROTO; 1359 + 1360 + if (ret) { 1361 + dev_info(&dev->dev, "Limited Address Space for DDW not Supported, err: %d", ret); 1362 + goto out; 1363 + } 1364 + 1365 + dn = pci_device_to_OF_node(dev); 1366 + pdn = PCI_DN(dn); 1367 + buid = pdn->phb->buid; 1368 + cfg_addr = (pdn->busno << 16) | (pdn->devfn << 8); 1369 + 1370 + ret = rtas_call(reset_dma_win, 4, 1, NULL, cfg_addr, BUID_HI(buid), 1371 + BUID_LO(buid), 1); 1372 + if (ret) 1373 + dev_info(&dev->dev, 1374 + "ibm,reset-pe-dma-windows(%x) for Limited Addr Support: %x %x %x returned %d ", 1375 + reset_dma_win, cfg_addr, BUID_HI(buid), BUID_LO(buid), 1376 + ret); 1377 + 1378 + out: 1379 + return ret; 1380 + } 1381 + 1335 1382 /* Return largest page shift based on "IO Page Sizes" output of ibm,query-pe-dma-window. */ 1336 1383 static int iommu_get_page_shift(u32 query_page_size) 1337 1384 { ··· 1447 1398 * 1448 1399 * returns true if can map all pages (direct mapping), false otherwise.. 1449 1400 */ 1450 - static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn) 1401 + static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn, u64 dma_mask) 1451 1402 { 1452 1403 int len = 0, ret; 1453 1404 int max_ram_len = order_base_2(ddw_memory_hotplug_max()); ··· 1466 1417 bool pmem_present; 1467 1418 struct pci_dn *pci = PCI_DN(pdn); 1468 1419 struct property *default_win = NULL; 1420 + bool limited_addr_req = false, limited_addr_enabled = false; 1421 + int dev_max_ddw; 1422 + int ddw_sz; 1469 1423 1470 1424 dn = of_find_node_by_type(NULL, "ibm,pmemory"); 1471 1425 pmem_present = dn != NULL; ··· 1495 1443 * the ibm,ddw-applicable property holds the tokens for: 1496 1444 * ibm,query-pe-dma-window 1497 1445 * ibm,create-pe-dma-window 1498 - * ibm,remove-pe-dma-window 1499 1446 * for the given node in that order. 1500 1447 * the property is actually in the parent, not the PE 1501 1448 */ ··· 1513 1462 ret = query_ddw(dev, ddw_avail, &query, pdn); 1514 1463 if (ret != 0) 1515 1464 goto out_failed; 1465 + 1466 + /* DMA Limited Addressing required? This is when the driver has 1467 + * requested to create DDW but supports mask which is less than 64-bits 1468 + */ 1469 + limited_addr_req = (dma_mask != DMA_BIT_MASK(64)); 1470 + 1471 + /* place the PHB in Limited Addressing mode */ 1472 + if (limited_addr_req) { 1473 + if (limited_dma_window(dev, pdn)) 1474 + goto out_failed; 1475 + 1476 + /* PHB is in Limited address mode */ 1477 + limited_addr_enabled = true; 1478 + } 1516 1479 1517 1480 /* 1518 1481 * If there is no window available, remove the default DMA window, ··· 1574 1509 goto out_failed; 1575 1510 } 1576 1511 1512 + /* Maximum DMA window size that the device can address (in log2) */ 1513 + dev_max_ddw = fls64(dma_mask); 1514 + 1515 + /* If the device DMA mask is less than 64-bits, make sure the DMA window 1516 + * size is not bigger than what the device can access 1517 + */ 1518 + ddw_sz = min(order_base_2(query.largest_available_block << page_shift), 1519 + dev_max_ddw); 1520 + 1577 1521 /* 1578 1522 * The "ibm,pmemory" can appear anywhere in the address space. 1579 1523 * Assuming it is still backed by page structs, try MAX_PHYSMEM_BITS ··· 1591 1517 */ 1592 1518 len = max_ram_len; 1593 1519 if (pmem_present) { 1594 - if (query.largest_available_block >= 1595 - (1ULL << (MAX_PHYSMEM_BITS - page_shift))) 1520 + if (ddw_sz >= MAX_PHYSMEM_BITS) 1596 1521 len = MAX_PHYSMEM_BITS; 1597 1522 else 1598 1523 dev_info(&dev->dev, "Skipping ibm,pmemory"); 1599 1524 } 1600 1525 1601 1526 /* check if the available block * number of ptes will map everything */ 1602 - if (query.largest_available_block < (1ULL << (len - page_shift))) { 1527 + if (ddw_sz < len) { 1603 1528 dev_dbg(&dev->dev, 1604 1529 "can't map partition max 0x%llx with %llu %llu-sized pages\n", 1605 1530 1ULL << len, 1606 1531 query.largest_available_block, 1607 1532 1ULL << page_shift); 1608 1533 1609 - len = order_base_2(query.largest_available_block << page_shift); 1610 - 1534 + len = ddw_sz; 1611 1535 dynamic_mapping = true; 1612 1536 } else { 1613 1537 direct_mapping = !default_win_removed || ··· 1619 1547 */ 1620 1548 if (default_win_removed && pmem_present && !direct_mapping) { 1621 1549 /* DDW is big enough to be split */ 1622 - if ((query.largest_available_block << page_shift) >= 1623 - MIN_DDW_VPMEM_DMA_WINDOW + (1ULL << max_ram_len)) { 1550 + if ((1ULL << ddw_sz) >= 1551 + MIN_DDW_VPMEM_DMA_WINDOW + (1ULL << max_ram_len)) { 1552 + 1624 1553 direct_mapping = true; 1625 1554 1626 1555 /* offset of the Dynamic part of DDW */ ··· 1632 1559 dynamic_mapping = true; 1633 1560 1634 1561 /* create max size DDW possible */ 1635 - len = order_base_2(query.largest_available_block 1636 - << page_shift); 1562 + len = ddw_sz; 1637 1563 } 1638 1564 } 1639 1565 ··· 1761 1689 __remove_dma_window(pdn, ddw_avail, create.liobn); 1762 1690 1763 1691 out_failed: 1764 - if (default_win_removed) 1692 + if (default_win_removed || limited_addr_enabled) 1765 1693 reset_dma_window(dev, pdn); 1766 1694 1767 1695 fpdn = kzalloc(sizeof(*fpdn), GFP_KERNEL); ··· 1779 1707 if (pmem_present && direct_mapping && len != MAX_PHYSMEM_BITS) 1780 1708 dev->dev.bus_dma_limit = dev->dev.archdata.dma_offset + 1781 1709 (1ULL << max_ram_len); 1710 + 1711 + dev_info(&dev->dev, "lsa_required: %x, lsa_enabled: %x, direct mapping: %x\n", 1712 + limited_addr_req, limited_addr_enabled, direct_mapping); 1782 1713 1783 1714 return direct_mapping; 1784 1715 } ··· 1908 1833 { 1909 1834 struct device_node *dn = pci_device_to_OF_node(pdev), *pdn; 1910 1835 1911 - /* only attempt to use a new window if 64-bit DMA is requested */ 1912 - if (dma_mask < DMA_BIT_MASK(64)) 1836 + /* For DDW, DMA mask should be more than 32-bits. For mask more then 1837 + * 32-bits but less then 64-bits, DMA addressing is supported in 1838 + * Limited Addressing mode. 1839 + */ 1840 + if (dma_mask <= DMA_BIT_MASK(32)) 1913 1841 return false; 1914 1842 1915 1843 dev_dbg(&pdev->dev, "node is %pOF\n", dn); ··· 1925 1847 */ 1926 1848 pdn = pci_dma_find(dn, NULL); 1927 1849 if (pdn && PCI_DN(pdn)) 1928 - return enable_ddw(pdev, pdn); 1850 + return enable_ddw(pdev, pdn, dma_mask); 1929 1851 1930 1852 return false; 1931 1853 }