Skip to content

Commit 576882e

Browse files
cleechgregkh
authored andcommitted
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> Signed-off-by: Chris Leech <cleech@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Link: https://lore.kernel.org/r/20240205200137.138302-1-cleech@redhat.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 0e439ba commit 576882e

2 files changed

Lines changed: 60 additions & 0 deletions

File tree

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

@@ -759,6 +760,49 @@ static int uio_mmap_physical(struct vm_area_struct *vma)
759760
vma->vm_page_prot);
760761
}
761762

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

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)