Re: [PATCH 1/2] [v4] net: emac: emac gigabit ethernet controller driver

Timur Tabi
2016-04-14T23:35:10Z

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.