#include "comedidev.h"
 #include "comedi_internal.h"
 
+static void __comedi_buf_free(struct comedi_device *dev,
+                             struct comedi_subdevice *s,
+                             unsigned n_pages)
+{
+       struct comedi_async *async = s->async;
+       struct comedi_buf_page *buf;
+       unsigned i;
+
+       if (async->prealloc_buf) {
+               vunmap(async->prealloc_buf);
+               async->prealloc_buf = NULL;
+               async->prealloc_bufsz = 0;
+       }
+
+       if (!async->buf_page_list)
+               return;
+
+       for (i = 0; i < n_pages; ++i) {
+               buf = &async->buf_page_list[i];
+               if (buf->virt_addr) {
+                       clear_bit(PG_reserved,
+                                 &(virt_to_page(buf->virt_addr)->flags));
+                       if (s->async_dma_dir != DMA_NONE) {
+                               dma_free_coherent(dev->hw_dev,
+                                                 PAGE_SIZE,
+                                                 buf->virt_addr,
+                                                 buf->dma_addr);
+                       } else {
+                               free_page((unsigned long)buf->virt_addr);
+                       }
+               }
+       }
+       vfree(async->buf_page_list);
+       async->buf_page_list = NULL;
+       async->n_buf_pages = 0;
+}
+
 int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s,
                     unsigned long new_size)
 {
        if (async->prealloc_buf && async->prealloc_bufsz == new_size)
                return 0;
 
-       /*  deallocate old buffer */
-       if (async->prealloc_buf) {
-               vunmap(async->prealloc_buf);
-               async->prealloc_buf = NULL;
-               async->prealloc_bufsz = 0;
-       }
-       if (async->buf_page_list) {
-               unsigned i;
-               for (i = 0; i < async->n_buf_pages; ++i) {
-                       if (async->buf_page_list[i].virt_addr) {
-                               clear_bit(PG_reserved,
-                                       &(virt_to_page(async->buf_page_list[i].
-                                                       virt_addr)->flags));
-                               if (s->async_dma_dir != DMA_NONE) {
-                                       dma_free_coherent(dev->hw_dev,
-                                                         PAGE_SIZE,
-                                                         async->
-                                                         buf_page_list
-                                                         [i].virt_addr,
-                                                         async->
-                                                         buf_page_list
-                                                         [i].dma_addr);
-                               } else {
-                                       free_page((unsigned long)
-                                                 async->buf_page_list[i].
-                                                 virt_addr);
-                               }
-                       }
-               }
-               vfree(async->buf_page_list);
-               async->buf_page_list = NULL;
-               async->n_buf_pages = 0;
-       }
+       /* deallocate old buffer */
+       __comedi_buf_free(dev, s, async->n_buf_pages);
+
        /*  allocate new buffer */
        if (new_size) {
                unsigned i = 0;
                }
                vfree(pages);
 
-               if (async->prealloc_buf == NULL) {
-                       /* Some allocation failed above. */
-                       if (async->buf_page_list) {
-                               for (i = 0; i < n_pages; i++) {
-                                       if (async->buf_page_list[i].virt_addr ==
-                                           NULL) {
-                                               break;
-                                       }
-                                       clear_bit(PG_reserved,
-                                               &(virt_to_page(async->
-                                                       buf_page_list[i].
-                                                       virt_addr)->flags));
-                                       if (s->async_dma_dir != DMA_NONE) {
-                                               dma_free_coherent(dev->hw_dev,
-                                                                 PAGE_SIZE,
-                                                                 async->
-                                                                 buf_page_list
-                                                                 [i].virt_addr,
-                                                                 async->
-                                                                 buf_page_list
-                                                                 [i].dma_addr);
-                                       } else {
-                                               free_page((unsigned long)
-                                                         async->buf_page_list
-                                                         [i].virt_addr);
-                                       }
-                               }
-                               vfree(async->buf_page_list);
-                               async->buf_page_list = NULL;
-                       }
+               if (!async->prealloc_buf) {
+                       /* Some allocation failed above */
+                       __comedi_buf_free(dev, s, n_pages);
                        return -ENOMEM;
                }
                async->n_buf_pages = n_pages;