Skip to content

Commit ba126da

Browse files
committed
uio: introduce UIO_MEM_DMA_COHERENT type
JIRA: https://issues.redhat.com/browse/RHEL-26081 Upstream Status: Posted https://lore.kernel.org/all/20240201233400.3394996-1-cleech@redhat.com/ Author: Chris Leech <cleech@redhat.com> Date: Mon Feb 5 12:01:37 2024 -0800 uio: introduce UIO_MEM_DMA_COHERENT type Add a UIO memtype specifically for sharing dma_alloc_coherent memory with userspace, backed by dma_mmap_coherent. This is mainly for the bnx2/bnx2x/bnx2i "cnic" interface, although there are a few other uio drivers which map dma_alloc_coherent memory and will be converted to use dma_mmap_coherent as well. Signed-off-by: Nilesh Javali <njavali@marvell.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Chris Leech <cleech@redhat.com> Signed-off-by: Chris Leech <cleech@redhat.com>
1 parent 3e2dc04 commit ba126da

File tree

2 files changed

+60
-0
lines changed

2 files changed

+60
-0
lines changed

drivers/uio/uio.c

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <linux/kobject.h>
2525
#include <linux/cdev.h>
2626
#include <linux/uio_driver.h>
27+
#include <linux/dma-mapping.h>
2728

2829
#define UIO_MAX_DEVICES (1U << MINORBITS)
2930

@@ -757,6 +758,49 @@ static int uio_mmap_physical(struct vm_area_struct *vma)
757758
vma->vm_page_prot);
758759
}
759760

761+
static int uio_mmap_dma_coherent(struct vm_area_struct *vma)
762+
{
763+
struct uio_device *idev = vma->vm_private_data;
764+
struct uio_mem *mem;
765+
void *addr;
766+
int ret = 0;
767+
int mi;
768+
769+
mi = uio_find_mem_index(vma);
770+
if (mi < 0)
771+
return -EINVAL;
772+
773+
mem = idev->info->mem + mi;
774+
775+
if (mem->addr & ~PAGE_MASK)
776+
return -ENODEV;
777+
if (mem->dma_addr & ~PAGE_MASK)
778+
return -ENODEV;
779+
if (!mem->dma_device)
780+
return -ENODEV;
781+
if (vma->vm_end - vma->vm_start > mem->size)
782+
return -EINVAL;
783+
784+
dev_warn(mem->dma_device,
785+
"use of UIO_MEM_DMA_COHERENT is highly discouraged");
786+
787+
/*
788+
* UIO uses offset to index into the maps for a device.
789+
* We need to clear vm_pgoff for dma_mmap_coherent.
790+
*/
791+
vma->vm_pgoff = 0;
792+
793+
addr = (void *)mem->addr;
794+
ret = dma_mmap_coherent(mem->dma_device,
795+
vma,
796+
addr,
797+
mem->dma_addr,
798+
vma->vm_end - vma->vm_start);
799+
vma->vm_pgoff = mi;
800+
801+
return ret;
802+
}
803+
760804
static int uio_mmap(struct file *filep, struct vm_area_struct *vma)
761805
{
762806
struct uio_listener *listener = filep->private_data;
@@ -804,6 +848,9 @@ static int uio_mmap(struct file *filep, struct vm_area_struct *vma)
804848
case UIO_MEM_VIRTUAL:
805849
ret = uio_mmap_logical(vma);
806850
break;
851+
case UIO_MEM_DMA_COHERENT:
852+
ret = uio_mmap_dma_coherent(vma);
853+
break;
807854
default:
808855
ret = -EINVAL;
809856
}

include/linux/uio_driver.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,26 @@ struct uio_map;
2828
* logical, virtual, or physical & phys_addr_t
2929
* should always be large enough to handle any of
3030
* the address types)
31+
* @dma_addr: DMA handle set by dma_alloc_coherent, used with
32+
* UIO_MEM_DMA_COHERENT only (@addr should be the
33+
* void * returned from the same dma_alloc_coherent call)
3134
* @offs: offset of device memory within the page
3235
* @size: size of IO (multiple of page size)
3336
* @memtype: type of memory addr points to
3437
* @internal_addr: ioremap-ped version of addr, for driver internal use
38+
* @dma_device: device struct that was passed to dma_alloc_coherent,
39+
* used with UIO_MEM_DMA_COHERENT only
3540
* @map: for use by the UIO core only.
3641
*/
3742
struct uio_mem {
3843
const char *name;
3944
phys_addr_t addr;
45+
dma_addr_t dma_addr;
4046
unsigned long offs;
4147
resource_size_t size;
4248
int memtype;
4349
void __iomem *internal_addr;
50+
struct device *dma_device;
4451
struct uio_map *map;
4552
};
4653

@@ -158,6 +165,12 @@ extern int __must_check
158165
#define UIO_MEM_LOGICAL 2
159166
#define UIO_MEM_VIRTUAL 3
160167
#define UIO_MEM_IOVA 4
168+
/*
169+
* UIO_MEM_DMA_COHERENT exists for legacy drivers that had been getting by with
170+
* improperly mapping DMA coherent allocations through the other modes.
171+
* Do not use in new drivers.
172+
*/
173+
#define UIO_MEM_DMA_COHERENT 5
161174

162175
/* defines for uio_port->porttype */
163176
#define UIO_PORT_NONE 0

0 commit comments

Comments
 (0)