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 | 56 | struct comedi_buf_map *bm; |
| 57 | 57 | unsigned long flags; |
| 58 | 58 | |
| 59 | − if (async->prealloc_buf) { | |
| 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 | − | |
| 59 | + async->prealloc_bufsz = 0; | |
| 66 | 60 | spin_lock_irqsave(&s->spin_lock, flags); |
| 67 | 61 | bm = async->buf_map; |
| 68 | 62 | async->buf_map = NULL; |
| @@ -141,11 +135,8 @@ static void __comedi_buf_alloc(struct comedi_device *dev, · 72 unmodified lines | ||
| 141 | 135 | unsigned int n_pages) |
| 142 | 136 | { |
| 143 | 137 | struct comedi_async *async = s->async; |
| 144 | − struct page **pages = NULL; | |
| 145 | 138 | struct comedi_buf_map *bm; |
| 146 | − struct comedi_buf_page *buf; | |
| 147 | 139 | unsigned long flags; |
| 148 | − unsigned int i; | |
| 149 | 140 | |
| 150 | 141 | if (!IS_ENABLED(CONFIG_HAS_DMA) && s->async_dma_dir != DMA_NONE) { |
| 151 | 142 | dev_err(dev->class_dev, |
| @@ -160,30 +151,7 @@ static void __comedi_buf_alloc(struct comedi_device *dev, · 8 unmodified lines | ||
| 160 | 151 | spin_lock_irqsave(&s->spin_lock, flags); |
| 161 | 152 | async->buf_map = bm; |
| 162 | 153 | spin_unlock_irqrestore(&s->spin_lock, flags); |
| 163 | − | |
| 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 | − } | |
| 154 | + async->prealloc_bufsz = n_pages << PAGE_SHIFT; | |
| 187 | 155 | } |
| 188 | 156 | |
| 189 | 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 | 232 | new_size = (new_size + PAGE_SIZE - 1) & PAGE_MASK; |
| 265 | 233 | |
| 266 | 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 | 236 | return 0; |
| 269 | 237 | |
| 270 | 238 | /* deallocate old buffer */ |
| @@ -275,14 +243,9 @@ int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s, · 4 unmodified lines | ||
| 275 | 243 | unsigned int n_pages = new_size >> PAGE_SHIFT; |
| 276 | 244 | |
| 277 | 245 | __comedi_buf_alloc(dev, s, n_pages); |
| 278 | − | |
| 279 | − if (!async->prealloc_buf) { | |
| 280 | − /* allocation failed */ | |
| 281 | − __comedi_buf_free(dev, s); | |
| 246 | + if (!async->prealloc_bufsz) | |
| 282 | 247 | return -ENOMEM; |
| 283 | − } | |
| 284 | 248 | } |
| 285 | − async->prealloc_bufsz = new_size; | |
| 286 | 249 | |
| 287 | 250 | return 0; |
| 288 | 251 | } |
| @@ -234,16 +234,12 @@ struct comedi_buf_page { · 233 unmodified lines | ||
| 234 | 234 | * |
| 235 | 235 | * A COMEDI data buffer is allocated as individual pages, either in |
| 236 | 236 | * conventional memory or DMA coherent memory, depending on the attached, |
| 237 | − * low-level hardware device. (The buffer pages also get mapped into the | |
| 238 | − * kernel's contiguous virtual address space pointed to by the 'prealloc_buf' | |
| 239 | − * member of &struct comedi_async.) | |
| 237 | + * low-level hardware device. | |
| 240 | 238 | * |
| 241 | 239 | * The buffer is normally freed when the COMEDI device is detached from the |
| 242 | 240 | * low-level driver (which may happen due to device removal), but if it happens |
| 243 | 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 | |
| 245 | − * address space pointed by 'prealloc_buf' is freed when the COMEDI device is | |
| 246 | − * detached.) | |
| 242 | + * been munmapped. That is what the reference counter is for. | |
| 247 | 243 | */ |
| 248 | 244 | struct comedi_buf_map { |
| 249 | 245 | struct device *dma_hw_dev; |
| @@ -255,7 +251,6 @@ struct comedi_buf_map { · 5 unmodified lines | ||
| 255 | 251 | |
| 256 | 252 | /** |
| 257 | 253 | * struct comedi_async - Control data for asynchronous COMEDI commands |
| 258 | − * @prealloc_buf: Kernel virtual address of allocated acquisition buffer. | |
| 259 | 254 | * @prealloc_bufsz: Buffer size (in bytes). |
| 260 | 255 | * @buf_map: Map of buffer pages. |
| 261 | 256 | * @max_bufsize: Maximum allowed buffer size (in bytes). |
| @@ -344,7 +339,6 @@ struct comedi_buf_map { · 82 unmodified lines | ||
| 344 | 339 | * less than or equal to UINT_MAX). |
| 345 | 340 | */ |
| 346 | 341 | struct comedi_async { |
| 347 | − void *prealloc_buf; | |
| 348 | 342 | unsigned int prealloc_bufsz; |
| 349 | 343 | struct comedi_buf_map *buf_map; |
| 350 | 344 | unsigned int max_bufsize; |