comedi: remove the mapping of the Comedi buffer in vmalloc address space
authorIan Abbott <abbotti@mev.co.uk>
Tue, 15 Apr 2025 11:35:58 +0000 (12:35 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 25 Apr 2025 13:53:19 +0000 (15:53 +0200)
Now that all the code that accesses the Comedi buffer data does so
page-by-page, using the `virt_addr` member of `struct comedi_buf_page`
to point to the data of each page, do not linearly map the buffer into
vmalloc address space (pointed to by the `prealloc_buf` member of
`struct comedi_async`).  That was only done for convenience, but was not
done for those drivers that need a DMA coherent buffer, which is
allocated in a single chunk.  Remove the `prealloc_buf` member as it is
no longer used.

Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
Link: https://lore.kernel.org/r/20250415114008.5977-4-abbotti@mev.co.uk
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/comedi/comedi_buf.c
include/linux/comedi/comedidev.h

index 0d956dd40a2b36a55cdf639d5263addf5ab16bf1..5807007bb3dd95ce90a1ce6c2b9479ba68fea0dd 100644 (file)
@@ -56,13 +56,7 @@ static void __comedi_buf_free(struct comedi_device *dev,
        struct comedi_buf_map *bm;
        unsigned long flags;
 
-       if (async->prealloc_buf) {
-               if (s->async_dma_dir == DMA_NONE)
-                       vunmap(async->prealloc_buf);
-               async->prealloc_buf = NULL;
-               async->prealloc_bufsz = 0;
-       }
-
+       async->prealloc_bufsz = 0;
        spin_lock_irqsave(&s->spin_lock, flags);
        bm = async->buf_map;
        async->buf_map = NULL;
@@ -141,11 +135,8 @@ static void __comedi_buf_alloc(struct comedi_device *dev,
                               unsigned int n_pages)
 {
        struct comedi_async *async = s->async;
-       struct page **pages = NULL;
        struct comedi_buf_map *bm;
-       struct comedi_buf_page *buf;
        unsigned long flags;
-       unsigned int i;
 
        if (!IS_ENABLED(CONFIG_HAS_DMA) && s->async_dma_dir != DMA_NONE) {
                dev_err(dev->class_dev,
@@ -160,30 +151,7 @@ static void __comedi_buf_alloc(struct comedi_device *dev,
        spin_lock_irqsave(&s->spin_lock, flags);
        async->buf_map = bm;
        spin_unlock_irqrestore(&s->spin_lock, flags);
-
-       if (bm->dma_dir != DMA_NONE) {
-               /*
-                * DMA buffer was allocated as a single block.
-                * Address is in page_list[0].
-                */
-               buf = &bm->page_list[0];
-               async->prealloc_buf = buf->virt_addr;
-       } else {
-               pages = vmalloc(sizeof(struct page *) * n_pages);
-               if (!pages)
-                       return;
-
-               for (i = 0; i < n_pages; i++) {
-                       buf = &bm->page_list[i];
-                       pages[i] = virt_to_page(buf->virt_addr);
-               }
-
-               /* vmap the pages to prealloc_buf */
-               async->prealloc_buf = vmap(pages, n_pages, VM_MAP,
-                                          COMEDI_PAGE_PROTECTION);
-
-               vfree(pages);
-       }
+       async->prealloc_bufsz = n_pages << PAGE_SHIFT;
 }
 
 void comedi_buf_map_get(struct comedi_buf_map *bm)
@@ -264,7 +232,7 @@ int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s,
        new_size = (new_size + PAGE_SIZE - 1) & PAGE_MASK;
 
        /* if no change is required, do nothing */
-       if (async->prealloc_buf && async->prealloc_bufsz == new_size)
+       if (async->prealloc_bufsz == new_size)
                return 0;
 
        /* deallocate old buffer */
@@ -275,14 +243,9 @@ int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s,
                unsigned int n_pages = new_size >> PAGE_SHIFT;
 
                __comedi_buf_alloc(dev, s, n_pages);
-
-               if (!async->prealloc_buf) {
-                       /* allocation failed */
-                       __comedi_buf_free(dev, s);
+               if (!async->prealloc_bufsz)
                        return -ENOMEM;
-               }
        }
-       async->prealloc_bufsz = new_size;
 
        return 0;
 }
index c08416a7364bc4ef12ebe3c704a7b1d794e86d16..4cb0400ad616de14ff35741c6c819ab3a30c0298 100644 (file)
@@ -234,16 +234,12 @@ struct comedi_buf_page {
  *
  * A COMEDI data buffer is allocated as individual pages, either in
  * conventional memory or DMA coherent memory, depending on the attached,
- * low-level hardware device.  (The buffer pages also get mapped into the
- * kernel's contiguous virtual address space pointed to by the 'prealloc_buf'
- * member of &struct comedi_async.)
+ * low-level hardware device.
  *
  * The buffer is normally freed when the COMEDI device is detached from the
  * low-level driver (which may happen due to device removal), but if it happens
  * to be mmapped at the time, the pages cannot be freed until the buffer has
- * been munmapped.  That is what the reference counter is for.  (The virtual
- * address space pointed by 'prealloc_buf' is freed when the COMEDI device is
- * detached.)
+ * been munmapped.  That is what the reference counter is for.
  */
 struct comedi_buf_map {
        struct device *dma_hw_dev;
@@ -255,7 +251,6 @@ struct comedi_buf_map {
 
 /**
  * struct comedi_async - Control data for asynchronous COMEDI commands
- * @prealloc_buf: Kernel virtual address of allocated acquisition buffer.
  * @prealloc_bufsz: Buffer size (in bytes).
  * @buf_map: Map of buffer pages.
  * @max_bufsize: Maximum allowed buffer size (in bytes).
@@ -344,7 +339,6 @@ struct comedi_buf_map {
  * less than or equal to UINT_MAX).
  */
 struct comedi_async {
-       void *prealloc_buf;
        unsigned int prealloc_bufsz;
        struct comedi_buf_map *buf_map;
        unsigned int max_bufsize;