[1/2] uio: introduce UIO_MEM_DMA_COHERENT type
Commit Message
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
could 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>
---
drivers/uio/uio.c | 40 ++++++++++++++++++++++++++++++++++++++
include/linux/uio_driver.h | 3 +++
2 files changed, 43 insertions(+)
Comments
On Wed, Jan 31, 2024 at 11:17:31AM -0800, Chris Leech wrote:
> 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
> could be converted to use dma_mmap_coherent as well.
What other drivers could use this? Patches doing the conversion would
be welcome, otherwise, again, I am very loath to take this
one-off-change for just a single driver that shouldn't be doing this in
the first place :)
thanks,
greg k-h
On Wed, Jan 31, 2024 at 1:29 PM Greg Kroah-Hartman
<gregkh@linuxfoundation.org> wrote:
>
> On Wed, Jan 31, 2024 at 11:17:31AM -0800, Chris Leech wrote:
> > 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
> > could be converted to use dma_mmap_coherent as well.
>
> What other drivers could use this? Patches doing the conversion would
> be welcome, otherwise, again, I am very loath to take this
> one-off-change for just a single driver that shouldn't be doing this in
> the first place :)
uio_pruss and uio_dmem_genirq both appear to mmap dma_alloc_coherent
memory as UIO_MEM_PHYS. It might not be an issue on that platforms
where those are used, but I'd be happy to include untested patches to
convert them for better adherence to the DMA APIs.
(sorry for the double send on this Greg, missed the reply-all)
- Chris
On Wed, Jan 31, 2024 at 01:44:50PM -0800, Chris Leech wrote:
> On Wed, Jan 31, 2024 at 1:29 PM Greg Kroah-Hartman
> <gregkh@linuxfoundation.org> wrote:
> >
> > On Wed, Jan 31, 2024 at 11:17:31AM -0800, Chris Leech wrote:
> > > 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
> > > could be converted to use dma_mmap_coherent as well.
> >
> > What other drivers could use this? Patches doing the conversion would
> > be welcome, otherwise, again, I am very loath to take this
> > one-off-change for just a single driver that shouldn't be doing this in
> > the first place :)
>
> uio_pruss and uio_dmem_genirq both appear to mmap dma_alloc_coherent
> memory as UIO_MEM_PHYS. It might not be an issue on that platforms
> where those are used, but I'd be happy to include untested patches to
> convert them for better adherence to the DMA APIs.
Yes, they do need fixing.
As the least horrible way out this looks ok:
Reviewed-by: Christoph Hellwig <hch@lst.de>
Bt maybe you can add some commentary why this mem mode exists and
why no one should be using it in new code?
On Thu, Feb 01, 2024 at 05:46:37AM +0100, Christoph Hellwig wrote:
> As the least horrible way out this looks ok:
>
> Reviewed-by: Christoph Hellwig <hch@lst.de>
>
> Bt maybe you can add some commentary why this mem mode exists and
> why no one should be using it in new code?
>
Good idea, and perhaps a kernel log warning when this is used as well
just to prevent anyone new from ever considering it.
thanks,
greg k-h
@@ -24,6 +24,7 @@
#include <linux/kobject.h>
#include <linux/cdev.h>
#include <linux/uio_driver.h>
+#include <linux/dma-mapping.h>
#define UIO_MAX_DEVICES (1U << MINORBITS)
@@ -759,6 +760,42 @@ static int uio_mmap_physical(struct vm_area_struct *vma)
vma->vm_page_prot);
}
+static int uio_mmap_dma_coherent(struct vm_area_struct *vma)
+{
+ struct uio_device *idev = vma->vm_private_data;
+ struct uio_mem *mem;
+ void *addr;
+ int ret = 0;
+ int mi;
+
+ mi = uio_find_mem_index(vma);
+ if (mi < 0)
+ return -EINVAL;
+
+ mem = idev->info->mem + mi;
+
+ if (mem->dma_addr & ~PAGE_MASK)
+ return -ENODEV;
+ if (vma->vm_end - vma->vm_start > mem->size)
+ return -EINVAL;
+
+ /*
+ * UIO uses offset to index into the maps for a device.
+ * We need to clear vm_pgoff for dma_mmap_coherent.
+ */
+ vma->vm_pgoff = 0;
+
+ addr = (void *)mem->addr;
+ ret = dma_mmap_coherent(mem->dma_device,
+ vma,
+ addr,
+ mem->dma_addr,
+ vma->vm_end - vma->vm_start);
+ vma->vm_pgoff = mi;
+
+ return ret;
+}
+
static int uio_mmap(struct file *filep, struct vm_area_struct *vma)
{
struct uio_listener *listener = filep->private_data;
@@ -806,6 +843,9 @@ static int uio_mmap(struct file *filep, struct vm_area_struct *vma)
case UIO_MEM_VIRTUAL:
ret = uio_mmap_logical(vma);
break;
+ case UIO_MEM_DMA_COHERENT:
+ ret = uio_mmap_dma_coherent(vma);
+ break;
default:
ret = -EINVAL;
}
@@ -37,10 +37,12 @@ struct uio_map;
struct uio_mem {
const char *name;
phys_addr_t addr;
+ dma_addr_t dma_addr;
unsigned long offs;
resource_size_t size;
int memtype;
void __iomem *internal_addr;
+ struct device *dma_device;
struct uio_map *map;
};
@@ -158,6 +160,7 @@ extern int __must_check
#define UIO_MEM_LOGICAL 2
#define UIO_MEM_VIRTUAL 3
#define UIO_MEM_IOVA 4
+#define UIO_MEM_DMA_COHERENT 5
/* defines for uio_port->porttype */
#define UIO_PORT_NONE 0