On Mon, Apr 11, 2022 at 06:47:44PM +0900, Wangseok Lee wrote: > >> Therefore, the dma_set_mask(32)(in dw_pcie_host_init()) > >> was modified to be performed only when > >> the dev-dma_mask is not set larger than 32 bits. > > > > So what sets dev->dma_mask to a larger than 32-bit value here? > > We need to find and fix that. > > At the code of of_dma_configure_id() of driver/of/device.c.. > In the 64bit system, if the dma start addr is used as 0x1'0000'0000 > and the size is used as 0xf'0000'0000, "u64 end" is 0xf'ffff'ffff. > And the dma_mask value is changed from 0xffff'ffff'ffff'ffff to > 0xf'ffff'ffffff due to the code below. That does look rather wrong to me, as any limitation should only be in the bus mask. Unless I'm missing something (and Robin should know the code much better than I do) we should do something like the patch below: diff --git a/drivers/of/device.c b/drivers/of/device.c index 874f031442dc7..b197861fcde08 100644 --- a/drivers/of/device.c +++ b/drivers/of/device.c @@ -113,8 +113,7 @@ int of_dma_configure_id(struct device *dev, struct device_node *np, { const struct iommu_ops *iommu; const struct bus_dma_region *map = NULL; - u64 dma_start = 0; - u64 mask, end, size = 0; + u64 dma_start = 0, size = 0; bool coherent; int ret; @@ -156,6 +155,9 @@ int of_dma_configure_id(struct device *dev, struct device_node *np, kfree(map); return -EINVAL; } + + dev->bus_dma_limit = dma_start + size - 1; + dev->dma_range_map = map; } /* @@ -169,25 +171,6 @@ int of_dma_configure_id(struct device *dev, struct device_node *np, dev->dma_mask = &dev->coherent_dma_mask; } - if (!size && dev->coherent_dma_mask) - size = max(dev->coherent_dma_mask, dev->coherent_dma_mask + 1); - else if (!size) - size = 1ULL << 32; - - /* - * Limit coherent and dma mask based on size and default mask - * set by the driver. - */ - end = dma_start + size - 1; - mask = DMA_BIT_MASK(ilog2(end) + 1); - dev->coherent_dma_mask &= mask; - *dev->dma_mask &= mask; - /* ...but only set bus limit and range map if we found valid dma-ranges earlier */ - if (!ret) { - dev->bus_dma_limit = end; - dev->dma_range_map = map; - } - coherent = of_dma_is_coherent(np); dev_dbg(dev, "device is%sdma coherent\n", coherent ? " " : " not ");