I am writing a PCIe driver and have trouble with setting the DMA mask.
The host is a zcu102 with a Quadcore ARM-Cortex A53. The PCIe device is a custom Device.
The kernel is v5.15.0-1023-xilinx-zynqmp with the Xilinx Ubuntu 22.04.3 LTS.
According to DMA API HOWTO I need to set the DMA mask using dma_set_mask_and_coherent()
My device supports a DMA mask of 24 bits.
Therefore I try the following:
status=dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(24));
This returns -5 => -EIO => I/O error.
I have tried the following:
When I try the same code with DMA_BIT_MASK(32)
it works. So it seems to be a problem with the 24 bits.
I looked at the kernel config gunzip -c /proc/config.gz | grep CONFIG_ZONE_DMA
:
CONFIG_ZONE_DMA=y
CONFIG_ZONE_DMA32=y
Which looks okay to me.
My current problem trace is:
dma_set_mask()
checks if dma_supported()(dev,mask) returns zero
For DMA_BIT_MASK(24) it returns 0 leading to failure. For DMA_BIT_MASK(32) it returns 1 leading to success.
dma_supported()
checks for a null pointer in get_dma_ops(dev)
get_dma_ops() implementation depends on CONFIG_DMA_OPS
gunzip -c /proc/config.gz | grep CONFIG_DMA_OPS
returns CONFIG_DMA_OPS=y
Since this is enabled: get_dma_ops()
checks for dev->dma_ops
pr_info("pdev->dev.dma_ops: %p\n", pdev->dev.dma_ops);
returns 0 so the check fails
That means dma_direct_supported()
is called.
Could you please help me answer the following questions:
With Ian Abbots Hint I took a look at dma_direct_supported()
and found
min_mask = min_t(u64, min_mask, DMA_BIT_MASK(zone_dma_bits));
zone_dma_bits
resolves to 32 for arm64 so the mask of 24 bits is too small.