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

[ Upstream commit 67dfc11982f7e3c37f0977e74671da2391b29181 ]

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
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Gaurav Batra
2025-01-08 10:48:14 -06:00
committed by Greg Kroah-Hartman
parent 9aeaf1956e
commit c2e02e2b21

View File

@@ -52,7 +52,8 @@ enum {
enum {
DDW_EXT_SIZE = 0,
DDW_EXT_RESET_DMA_WIN = 1,
DDW_EXT_QUERY_OUT_SIZE = 2
DDW_EXT_QUERY_OUT_SIZE = 2,
DDW_EXT_LIMITED_ADDR_MODE = 3
};
static struct iommu_table *iommu_pseries_alloc_table(int node)
@@ -1327,6 +1328,54 @@ static void reset_dma_window(struct pci_dev *dev, struct device_node *par_dn)
ret);
}
/*
* Platforms support placing PHB in limited address mode starting with LoPAR
* level 2.13 implement. In this mode, the DMA address returned by DDW is over
* 4GB but, less than 64-bits. This benefits IO adapters that don't support
* 64-bits for DMA addresses.
*/
static int limited_dma_window(struct pci_dev *dev, struct device_node *par_dn)
{
int ret;
u32 cfg_addr, reset_dma_win, las_supported;
u64 buid;
struct device_node *dn;
struct pci_dn *pdn;
ret = ddw_read_ext(par_dn, DDW_EXT_RESET_DMA_WIN, &reset_dma_win);
if (ret)
goto out;
ret = ddw_read_ext(par_dn, DDW_EXT_LIMITED_ADDR_MODE, &las_supported);
/* Limited Address Space extension available on the platform but DDW in
* limited addressing mode not supported
*/
if (!ret && !las_supported)
ret = -EPROTO;
if (ret) {
dev_info(&dev->dev, "Limited Address Space for DDW not Supported, err: %d", ret);
goto out;
}
dn = pci_device_to_OF_node(dev);
pdn = PCI_DN(dn);
buid = pdn->phb->buid;
cfg_addr = (pdn->busno << 16) | (pdn->devfn << 8);
ret = rtas_call(reset_dma_win, 4, 1, NULL, cfg_addr, BUID_HI(buid),
BUID_LO(buid), 1);
if (ret)
dev_info(&dev->dev,
"ibm,reset-pe-dma-windows(%x) for Limited Addr Support: %x %x %x returned %d ",
reset_dma_win, cfg_addr, BUID_HI(buid), BUID_LO(buid),
ret);
out:
return ret;
}
/* Return largest page shift based on "IO Page Sizes" output of ibm,query-pe-dma-window. */
static int iommu_get_page_shift(u32 query_page_size)
{
@@ -1394,7 +1443,7 @@ static struct property *ddw_property_create(const char *propname, u32 liobn, u64
*
* returns true if can map all pages (direct mapping), false otherwise..
*/
static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn)
static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn, u64 dma_mask)
{
int len = 0, ret;
int max_ram_len = order_base_2(ddw_memory_hotplug_max());
@@ -1413,6 +1462,9 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn)
bool pmem_present;
struct pci_dn *pci = PCI_DN(pdn);
struct property *default_win = NULL;
bool limited_addr_req = false, limited_addr_enabled = false;
int dev_max_ddw;
int ddw_sz;
dn = of_find_node_by_type(NULL, "ibm,pmemory");
pmem_present = dn != NULL;
@@ -1439,7 +1491,6 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn)
* the ibm,ddw-applicable property holds the tokens for:
* ibm,query-pe-dma-window
* ibm,create-pe-dma-window
* ibm,remove-pe-dma-window
* for the given node in that order.
* the property is actually in the parent, not the PE
*/
@@ -1459,6 +1510,20 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn)
if (ret != 0)
goto out_failed;
/* DMA Limited Addressing required? This is when the driver has
* requested to create DDW but supports mask which is less than 64-bits
*/
limited_addr_req = (dma_mask != DMA_BIT_MASK(64));
/* place the PHB in Limited Addressing mode */
if (limited_addr_req) {
if (limited_dma_window(dev, pdn))
goto out_failed;
/* PHB is in Limited address mode */
limited_addr_enabled = true;
}
/*
* If there is no window available, remove the default DMA window,
* if it's present. This will make all the resources available to the
@@ -1505,6 +1570,15 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn)
goto out_failed;
}
/* Maximum DMA window size that the device can address (in log2) */
dev_max_ddw = fls64(dma_mask);
/* If the device DMA mask is less than 64-bits, make sure the DMA window
* size is not bigger than what the device can access
*/
ddw_sz = min(order_base_2(query.largest_available_block << page_shift),
dev_max_ddw);
/*
* The "ibm,pmemory" can appear anywhere in the address space.
* Assuming it is still backed by page structs, try MAX_PHYSMEM_BITS
@@ -1513,23 +1587,21 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn)
*/
len = max_ram_len;
if (pmem_present) {
if (query.largest_available_block >=
(1ULL << (MAX_PHYSMEM_BITS - page_shift)))
if (ddw_sz >= MAX_PHYSMEM_BITS)
len = MAX_PHYSMEM_BITS;
else
dev_info(&dev->dev, "Skipping ibm,pmemory");
}
/* check if the available block * number of ptes will map everything */
if (query.largest_available_block < (1ULL << (len - page_shift))) {
if (ddw_sz < len) {
dev_dbg(&dev->dev,
"can't map partition max 0x%llx with %llu %llu-sized pages\n",
1ULL << len,
query.largest_available_block,
1ULL << page_shift);
len = order_base_2(query.largest_available_block << page_shift);
len = ddw_sz;
dynamic_mapping = true;
} else {
direct_mapping = !default_win_removed ||
@@ -1543,8 +1615,9 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn)
*/
if (default_win_removed && pmem_present && !direct_mapping) {
/* DDW is big enough to be split */
if ((query.largest_available_block << page_shift) >=
MIN_DDW_VPMEM_DMA_WINDOW + (1ULL << max_ram_len)) {
if ((1ULL << ddw_sz) >=
MIN_DDW_VPMEM_DMA_WINDOW + (1ULL << max_ram_len)) {
direct_mapping = true;
/* offset of the Dynamic part of DDW */
@@ -1555,8 +1628,7 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn)
dynamic_mapping = true;
/* create max size DDW possible */
len = order_base_2(query.largest_available_block
<< page_shift);
len = ddw_sz;
}
}
@@ -1685,7 +1757,7 @@ out_remove_win:
__remove_dma_window(pdn, ddw_avail, create.liobn);
out_failed:
if (default_win_removed)
if (default_win_removed || limited_addr_enabled)
reset_dma_window(dev, pdn);
fpdn = kzalloc(sizeof(*fpdn), GFP_KERNEL);
@@ -1704,6 +1776,9 @@ out_unlock:
dev->dev.bus_dma_limit = dev->dev.archdata.dma_offset +
(1ULL << max_ram_len);
dev_info(&dev->dev, "lsa_required: %x, lsa_enabled: %x, direct mapping: %x\n",
limited_addr_req, limited_addr_enabled, direct_mapping);
return direct_mapping;
}
@@ -1829,8 +1904,11 @@ static bool iommu_bypass_supported_pSeriesLP(struct pci_dev *pdev, u64 dma_mask)
{
struct device_node *dn = pci_device_to_OF_node(pdev), *pdn;
/* only attempt to use a new window if 64-bit DMA is requested */
if (dma_mask < DMA_BIT_MASK(64))
/* For DDW, DMA mask should be more than 32-bits. For mask more then
* 32-bits but less then 64-bits, DMA addressing is supported in
* Limited Addressing mode.
*/
if (dma_mask <= DMA_BIT_MASK(32))
return false;
dev_dbg(&pdev->dev, "node is %pOF\n", dn);
@@ -1843,7 +1921,7 @@ static bool iommu_bypass_supported_pSeriesLP(struct pci_dev *pdev, u64 dma_mask)
*/
pdn = pci_dma_find(dn, NULL);
if (pdn && PCI_DN(pdn))
return enable_ddw(pdev, pdn);
return enable_ddw(pdev, pdn, dma_mask);
return false;
}