[PATCH v1 1/1] ARM: Select DMA_DIRECT_REMAP to fix restricted DMA

Robin Murphy robin.murphy at arm.com
Mon Oct 2 08:08:32 PDT 2023


On 02/10/2023 1:33 pm, Jim Quinlan wrote:
> On Thu, Sep 28, 2023 at 11:47 AM Robin Murphy <robin.murphy at arm.com> wrote:
>>
>> On 28/09/2023 1:07 pm, Jim Quinlan wrote:
>>> On Wed, Sep 27, 2023 at 7:10 PM Linus Walleij <linus.walleij at linaro.org> wrote:
>>>>
>>>> Hi Jim,
>>>>
>>>> thanks for your patch!
>>>>
>>>> On Tue, Sep 26, 2023 at 7:52 PM Jim Quinlan <james.quinlan at broadcom.com> wrote:
>>>>
>>>>> Without this commit, the use of dma_alloc_coherent() while
>>>>> using CONFIG_DMA_RESTRICTED_POOL=y breaks devices from working.
>>>>> For example, the common Wifi 7260 chip (iwlwifi) works fine
>>>>> on arm64 with restricted memory but not on arm, unless this
>>>>> commit is applied.
>>>>>
>>>>> Signed-off-by: Jim Quinlan <james.quinlan at broadcom.com>
>>>>
>>>> (...)
>>>>> +       select DMA_DIRECT_REMAP
>>>>
>>>> Christoph invented that symbol so he can certainly
>>>> explain what is missing to use this on ARM.
>>>>
>>>> This looks weird to me, because:
>>>>> git grep atomic_pool_init
>>>> arch/arm/mm/dma-mapping.c:static int __init atomic_pool_init(void)
>>>> kernel/dma/pool.c:static int __init dma_atomic_pool_init(void)
>>>>
>>>> Now you have two atomic DMA pools in the kernel,
>>>> and a lot more than that is duplicated. I'm amazed that it
>>>> compiles at all.
>>>>
>>>> Clearly if you want to do this, surely the ARM-specific
>>>> arch/arm/mm/dma-mapping.c and arch/arm/mm/dma-mapping-nommu.c
>>>> needs to be removed at the same time?
>>>>
>>>> However I don't think it's that simple, because Christoph would surely
>>>> had done this a long time ago if it was that simple.
>>>
>>> Hello Linus,
>>>
>>> Yes, this is the reason I used "RFC" as the fix looked too easy to be viable :-)
>>> I debugged it enough to see that the host driver's
>>> writes to the dma_alloc_coherent() region  were not appearing in
>>> memory, and that
>>> led me to DMA_DIRECT_REMAP.
>>
>> Oh, another thing - the restricted-dma-pool is really only for streaming
>> DMA - IIRC there can be cases where the emergency fallback of trying to
>> allocate out of the bounce buffer won't work properly. Are you also
>> using an additional shared-dma-pool carveout to satisfy the coherent
>> allocations, per the DT binding?
> 
> Hello Robin,
> Sorry for the delay.  We use "restricted DMA" as a poor person's IOMMU; we can
> restrict the DMA memory of a device to a narrow region, and our memory
> bus HW has
> "checkers' to enforce said region for a specific memory client, e.g. PCIe.
> 
> We can confirm the assignment of restricted DMA in the bootlog when the device
> is probed:
> 
>          iwlwifi 0001:01:00.0: assigned reserved memory node pcieSR1 at 4a000000
>          iwlwifi 0001:01:00.0: enabling device (0000 -> 0002)
> 
> As far as your other question, why don't I  just post our relevant DT [1].

OK, I spent a while reminding myself of the restricted DMA code, and I'm 
at least 95% confident that I now recall the relevant details...

Restricted DMA has never actually been supported on ARM, or various 
other platforms which the config doesn't do a great job of reflecting. 
ARM does not fully use dma-direct, and its arch_dma_alloc() 
implementation doesn't understand how to call the swiotlb_alloc() 
fallback path. TBH I'm now rather puzzled that you get any semblance of 
working at all, since AFAICS what ARM's arch_dma_alloc() should end up 
doing is giving you a non-cacheable remap as expected, but of some 
regular kernel memory outside the restricted address range, which 
oughtn't to work at all if something is actually restricting device 
accesses.

Secondly, the case I was half-remembering above is that the 
aforementioned fallback path fundamentally *only* works for non-coherent 
devices where dma_alloc_coherent() calls are in non-blocking context. 
The only way to make atomic coherent allocations come from the 
restricted range is to set up part of it as a per-device coherent pool, 
via an additional reserved-memory region as mentioned.

Thanks,
Robin.

> 
> Regards,
> Jim Quinlan
> Broardcom STB/CM
> 
> [1]
> memory {
>          device_type = "memory";
>          reg = <0x0 0x40000000 0x1 0x0>;
> };
> 
> reserved-memory {
>          #address-cells = <0x2>;
>          #size-cells = <0x2>;
>          ranges;
>          /* ... */
> 
>          pcieSR1 at 4a000000 {
>                  linux,phandle = <0x2a>;
>                  phandle = <0x2a>;
>                  compatible = "restricted-dma-pool";
>                  reserved-names = "pcieSR1";
>                  reg = <0x0 0x4a000000 0x0 0x2400000>;
>          };
> };
> pcie at 8b20000 {
>          /* ... */
>          pci at 0,0 {
>                  /* ... */
>                  pci-ep at 0,0 {
>                          memory-region = <0x2a>;
>                          reg = <0x10000 0x0 0x0 0x0 0x0>;
>                  };
>          };
> };
> 
> 
> 
> 
>>
>> Thanks,
>> Robin.



More information about the linux-arm-kernel mailing list