Subject: Unable to map uncached buffer for PCI DMA to userspace on Cortex-A53

From: Mike Campin <[email-masked]>
Date: Mon, 7 Oct 2019 08:26:22 -0700

I've been trying for several days to map an uncached buffer for PCI DMA in
userspace without luck. The only way I can get the DMA transfer to work is
to wrap it with __builtin___clear_cache().

Details.
  - 96boards SC2A11 with Cortex-A53 with my device plugged into a PCIe slot.
  - Kernel 5.2.13-200.fc30.aarch64 (Fedora 30).
  - /proc/cmdline 
      BOOT_IMAGE=(hd1,gpt2)/vmlinuz-5.2.13-200.fc30.aarch64 root=/dev/mapper/fedora-root ro rd.lvm.lv=fedora/root rd.lvm.lv=fedora/swap
  - Simplified code:
      init_dma_attrs(&attrs);
      dma_set_attr(DMA_ATTR_FORCE_CONTIGUOUS,  &attrs);
      dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs);
      dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
      vaddr = dma_alloc_attrs(dev, size, &iaddr, GFP_KERNEL | __GFP_ZERO, &attrs);
 
      vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
      dma_mmap_attrs(dev, vma, vaddr, iaddr, size, &attrs);

I've tried several permutations. Here's a few examples:
  - vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
  - vma->vm_flags |= VM_IO;
  - With and without DMA_ATTR_NO_KERNEL_MAPPING.
  - remap_pfn_range(vma, vma->vm_start, iaddr >> PAGE_SHIFT, size, vma->vm_page_prot);
  - dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
  - Even tried using get_arch_dma_ops() to get a pointer to arm_dma_ops.

-- 
Mike Campin
arm at timequake dot net

_______________________________________________
linux-arm-kernel mailing list
[email-masked]
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel