Vikram Sethi wrote:
>>     retval = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
>>     if (retval) {
>>         dev_err(&pdev->dev, "failed to set DMA mask err %d\n", retval);
>>         goto err_res;
>>     }
How can you set the mask to 64 bits when the EMAC IP on FSM9900 and QDF2432 can 
only do 32 bit DMA?
The mask in that API is a bit mask describing which bits of an address your 
device supports.

Vikram, Shanker, and I discussed this offline, and came to a consensus.

The FSM9900 is a 32-bit platform, so the kernel will never create a DMA address above 4GB. Even if the driver sets the mask to 64 bits, it will technically work. However, the mask should be set to 32 because all address buses are 32 bits.

The QDF2432 is different. Although it's an ARM64 platform, we have the unfortunate situation that only 32 bits of that address is wired to the rest of the chip. So even though the Emac can handle 64-bit bus addresses, if it actually attempts to DMA above 4GB, the address will get truncated and corrupt memory. The mask needs to be set to 32.

There may or may not be other ARM64 chips from us that won't have this problem in the future, so these hypothetical chips would have a mask of 64.

So I think the solution is to create a device tree (and ACPI) property that holds the mask.

        dma-mask = <0 0xffffffff>;

or

        dma-mask = <0xffffffff 0xffffffff>;

The driver will then do this:

        u64 dma_mask;
        device_property_read_u64(&pdev->dev, "dma-mask", &dma_mask);
        dma_coerce_mask_and_coherent(&pdev->dev, dma_mask);

What I'm not sure yet is whether I should call dma_coerce_mask_and_coherent() or dma_set_coherent_mask().

--
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora
Forum, a Linux Foundation collaborative project.

Reply via email to