From 718c4d68d9491e8bc16a614d193b257efc41723e Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 9 Jan 2013 13:25:54 -0700 Subject: [PATCH] staging: comedi: comedi_buf: factor out common code to free the async buffer The function comedi_buf_alloc() uses two loops to free the async buffer's buf_page_list. The first one is used at the beginning to deallocate the current buffer. The second is used to cleanup if the new buffer allocation fails. Factor out the common code to a new function. Signed-off-by: H Hartley Sweeten Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_buf.c | 106 +++++++++++----------------- 1 file changed, 43 insertions(+), 63 deletions(-) diff --git a/drivers/staging/comedi/comedi_buf.c b/drivers/staging/comedi/comedi_buf.c index fe2dcae805b4..3f01b0badd0b 100644 --- a/drivers/staging/comedi/comedi_buf.c +++ b/drivers/staging/comedi/comedi_buf.c @@ -22,6 +22,43 @@ #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) { @@ -34,39 +71,9 @@ int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s, 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; @@ -114,36 +121,9 @@ int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s, } 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; -- 2.34.1