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.
Unified · Split
| @@ -56,13 +56,7 @@ static void __comedi_buf_free(struct comedi_device *dev, · 55 unmodified lines | |||
| 56 | struct comedi_buf_map *bm; | 56 | struct comedi_buf_map *bm; |
| 57 | unsigned long flags; | 57 | unsigned long flags; |
| 58 | 58 | ||
| 59 | if (async->prealloc_buf) { | 59 | async->prealloc_bufsz = 0; |
| 60 | if (s->async_dma_dir == DMA_NONE) | ||
| 61 | vunmap(async->prealloc_buf); | ||
| 62 | async->prealloc_buf = NULL; | ||
| 63 | async->prealloc_bufsz = 0; | ||
| 64 | } | ||
| 65 | |||
| 66 | spin_lock_irqsave(&s->spin_lock, flags); | 60 | spin_lock_irqsave(&s->spin_lock, flags); |
| 67 | bm = async->buf_map; | 61 | bm = async->buf_map; |
| 68 | async->buf_map = NULL; | 62 | async->buf_map = NULL; |
| @@ -141,11 +135,8 @@ static void __comedi_buf_alloc(struct comedi_device *dev, · 72 unmodified lines | |||
| 141 | unsigned int n_pages) | 135 | unsigned int n_pages) |
| 142 | { | 136 | { |
| 143 | struct comedi_async *async = s->async; | 137 | struct comedi_async *async = s->async; |
| 144 | struct page **pages = NULL; | ||
| 145 | struct comedi_buf_map *bm; | 138 | struct comedi_buf_map *bm; |
| 146 | struct comedi_buf_page *buf; | ||
| 147 | unsigned long flags; | 139 | unsigned long flags; |
| 148 | unsigned int i; | ||
| 149 | 140 | ||
| 150 | if (!IS_ENABLED(CONFIG_HAS_DMA) && s->async_dma_dir != DMA_NONE) { | 141 | if (!IS_ENABLED(CONFIG_HAS_DMA) && s->async_dma_dir != DMA_NONE) { |
| 151 | dev_err(dev->class_dev, | 142 | dev_err(dev->class_dev, |
| @@ -160,30 +151,7 @@ static void __comedi_buf_alloc(struct comedi_device *dev, · 8 unmodified lines | |||
| 160 | spin_lock_irqsave(&s->spin_lock, flags); | 151 | spin_lock_irqsave(&s->spin_lock, flags); |
| 161 | async->buf_map = bm; | 152 | async->buf_map = bm; |
| 162 | spin_unlock_irqrestore(&s->spin_lock, flags); | 153 | spin_unlock_irqrestore(&s->spin_lock, flags); |
| 163 | 154 | async->prealloc_bufsz = n_pages << PAGE_SHIFT; | |
| 164 | if (bm->dma_dir != DMA_NONE) { | ||
| 165 | /* | ||
| 166 | * DMA buffer was allocated as a single block. | ||
| 167 | * Address is in page_list[0]. | ||
| 168 | */ | ||
| 169 | buf = &bm->page_list[0]; | ||
| 170 | async->prealloc_buf = buf->virt_addr; | ||
| 171 | } else { | ||
| 172 | pages = vmalloc(sizeof(struct page *) * n_pages); | ||
| 173 | if (!pages) | ||
| 174 | return; | ||
| 175 | |||
| 176 | for (i = 0; i < n_pages; i++) { | ||
| 177 | buf = &bm->page_list[i]; | ||
| 178 | pages[i] = virt_to_page(buf->virt_addr); | ||
| 179 | } | ||
| 180 | |||
| 181 | /* vmap the pages to prealloc_buf */ | ||
| 182 | async->prealloc_buf = vmap(pages, n_pages, VM_MAP, | ||
| 183 | COMEDI_PAGE_PROTECTION); | ||
| 184 | |||
| 185 | vfree(pages); | ||
| 186 | } | ||
| 187 | } | 155 | } |
| 188 | 156 | ||
| 189 | void comedi_buf_map_get(struct comedi_buf_map *bm) | 157 | 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, · 74 unmodified lines | |||
| 264 | new_size = (new_size + PAGE_SIZE - 1) & PAGE_MASK; | 232 | new_size = (new_size + PAGE_SIZE - 1) & PAGE_MASK; |
| 265 | 233 | ||
| 266 | /* if no change is required, do nothing */ | 234 | /* if no change is required, do nothing */ |
| 267 | if (async->prealloc_buf && async->prealloc_bufsz == new_size) | 235 | if (async->prealloc_bufsz == new_size) |
| 268 | return 0; | 236 | return 0; |
| 269 | 237 | ||
| 270 | /* deallocate old buffer */ | 238 | /* deallocate old buffer */ |
| @@ -275,14 +243,9 @@ int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s, · 4 unmodified lines | |||
| 275 | unsigned int n_pages = new_size >> PAGE_SHIFT; | 243 | unsigned int n_pages = new_size >> PAGE_SHIFT; |
| 276 | 244 | ||
| 277 | __comedi_buf_alloc(dev, s, n_pages); | 245 | __comedi_buf_alloc(dev, s, n_pages); |
| 278 | 246 | if (!async->prealloc_bufsz) | |
| 279 | if (!async->prealloc_buf) { | ||
| 280 | /* allocation failed */ | ||
| 281 | __comedi_buf_free(dev, s); | ||
| 282 | return -ENOMEM; | 247 | return -ENOMEM; |
| 283 | } | ||
| 284 | } | 248 | } |
| 285 | async->prealloc_bufsz = new_size; | ||
| 286 | 249 | ||
| 287 | return 0; | 250 | return 0; |
| 288 | } | 251 | } |
| @@ -234,16 +234,12 @@ struct comedi_buf_page { · 233 unmodified lines | |||
| 234 | * | 234 | * |
| 235 | * A COMEDI data buffer is allocated as individual pages, either in | 235 | * A COMEDI data buffer is allocated as individual pages, either in |
| 236 | * conventional memory or DMA coherent memory, depending on the attached, | 236 | * conventional memory or DMA coherent memory, depending on the attached, |
| 237 | * low-level hardware device. (The buffer pages also get mapped into the | 237 | * low-level hardware device. |
| 238 | * kernel's contiguous virtual address space pointed to by the 'prealloc_buf' | ||
| 239 | * member of &struct comedi_async.) | ||
| 240 | * | 238 | * |
| 241 | * The buffer is normally freed when the COMEDI device is detached from the | 239 | * The buffer is normally freed when the COMEDI device is detached from the |
| 242 | * low-level driver (which may happen due to device removal), but if it happens | 240 | * low-level driver (which may happen due to device removal), but if it happens |
| 243 | * to be mmapped at the time, the pages cannot be freed until the buffer has | 241 | * to be mmapped at the time, the pages cannot be freed until the buffer has |
| 244 | * been munmapped. That is what the reference counter is for. (The virtual | 242 | * been munmapped. That is what the reference counter is for. |
| 245 | * address space pointed by 'prealloc_buf' is freed when the COMEDI device is | ||
| 246 | * detached.) | ||
| 247 | */ | 243 | */ |
| 248 | struct comedi_buf_map { | 244 | struct comedi_buf_map { |
| 249 | struct device *dma_hw_dev; | 245 | struct device *dma_hw_dev; |
| @@ -255,7 +251,6 @@ struct comedi_buf_map { · 5 unmodified lines | |||
| 255 | 251 | ||
| 256 | /** | 252 | /** |
| 257 | * struct comedi_async - Control data for asynchronous COMEDI commands | 253 | * struct comedi_async - Control data for asynchronous COMEDI commands |
| 258 | * @prealloc_buf: Kernel virtual address of allocated acquisition buffer. | ||
| 259 | * @prealloc_bufsz: Buffer size (in bytes). | 254 | * @prealloc_bufsz: Buffer size (in bytes). |
| 260 | * @buf_map: Map of buffer pages. | 255 | * @buf_map: Map of buffer pages. |
| 261 | * @max_bufsize: Maximum allowed buffer size (in bytes). | 256 | * @max_bufsize: Maximum allowed buffer size (in bytes). |
| @@ -344,7 +339,6 @@ struct comedi_buf_map { · 82 unmodified lines | |||
| 344 | * less than or equal to UINT_MAX). | 339 | * less than or equal to UINT_MAX). |
| 345 | */ | 340 | */ |
| 346 | struct comedi_async { | 341 | struct comedi_async { |
| 347 | void *prealloc_buf; | ||
| 348 | unsigned int prealloc_bufsz; | 342 | unsigned int prealloc_bufsz; |
| 349 | struct comedi_buf_map *buf_map; | 343 | struct comedi_buf_map *buf_map; |
| 350 | unsigned int max_bufsize; | 344 | unsigned int max_bufsize; |