AnsweredAssumed Answered

32 bits PCI device DMA problem on T1042 platform Linux 64 bits

Question asked by Antoine Durand on Jun 15, 2018
Latest reply on Jul 2, 2018 by Yiping Wang


Hi,

 

on a T1042 platform,
with Linux kernel 4.1.8 from NXP QorIQ SDK 2.0,
I'm writing a PCI driver for a PCI 32 bit device.

 

I need to setup a DMA_FROM_DEVICE page (one page = 4KB) with dma_map_single() ... and it fails.

 

the buffer i want to dma_map_single() is "kalloced" with GFP_KERNEL | GFP_DMA, the corresponding Physical address, is everytime above 0xF0000000. the pci device's dma mask is set by dma_set_mask(dev, DMA_BIT_MASK(32)).

 

dma_map_single() is defined as dma_map_single_attrs() [include/asm-generic/dma-mapping-common.h] which call the corresponding dma_ops of swiotlb : swiotlb_map_page() [lib/swiotlb.c].
swiotlb_map_page() test for the given buffer's physical address to check if it is dma_capable() [include/asm-generic/dma-mapping.h] directly.
as it is not, it try to map_single() [lib/swiotlb.c] again, test again the new physical address returned and it is still not dma_capable().

 

dma_capable() check if physical address is below dev->archdata.max_direct_dma_addr.
dev->archdata.max_direct_dma_addr is set in pci_dma_dev_setup_swiotlb() [arch/powerpc/kernel/dma-swiotlb.c] based on the pci controller dma_window_base_cur and dma_window_size.
those values were been set to 0x0 and 0xc0000000 in setup_pci_atmu() [arch/powerpc/sysdev/fsl_pci.c] based on the device tree ranges.
what i understood of the inbound/outbound window setup is :
    the inbound window set up in setup_pci_atmu() start from 0x0 to the low address of the pci Memory outbound window,
    that is, all remaining adress space between zero and the beginning of outbound windows
    is that correct and normal ?

 

I don't known if dev->archdata.max_direct_dma_addr (= 0xc0000000) is wrong
or if map_single() [lib/swiotlb.c] is wrong and must return a physical address value below 0xc0000000 ?

 

Does someone see what's wrong ?

 

My DRAM is located from 0x00000000 to 0x200000000 (8 GB) physical address
an d here is my device tree  for pci nodes :

 

Thank you for any help,

 

------------------------------------

 

    pci0: pcie@ffe240000 {
        reg = <0xf 0xfe240000 0 0x10000>;
             /* 32 bits non-prefetchable memmory region beginning on PCI address [0xC0000000..0xFFFFFFFF] of 1GB mapped onto CPU physical address [0xC00000000..0xC3FFFFFFF] */
        ranges = <0x02000000 0 0xc0000000 0xc 0x00000000 0x0 0x40000000
             /* I/O region beginning on PCI address 0x0 of 64 KB mapped onto CPU address 0xff8000000 */
              0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>;
        pcie@0 {
            ranges = <0x02000000 0 0xc0000000
                  0x02000000 0 0xc0000000
                  0 0x40000000

 

                  0x01000000 0 0x00000000
                  0x01000000 0 0x00000000
                  0 0x00010000>;
        };
    };

 

    pci1: pcie@ffe250000 {
        reg = <0xf 0xfe250000 0 0x10000>;
             /* 32 bits non-prefetchable memmory region beginning on PCI address [0xC0000000..0xDFFFFFFF] of 512 MB mapped onto CPU physical address [0xC40000000..0xC5FFFFFFF] */
        ranges = <0x02000000 0x0 0xc0000000 0xc 0x40000000 0x0 0x20000000
              0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>;
        pcie@0 {
            ranges = <0x02000000 0 0xc0000000
                  0x02000000 0 0xc0000000
                  0 0x10000000

 

                  0x01000000 0 0x00000000
                  0x01000000 0 0x00000000
                  0 0x00010000>;
        };
    };

Outcomes