[PATCH 03/11] staging: comedi: comedi_buf: factor out common code to free the buf_page_list

H Hartley Sweeten hsweeten at visionengravers.com
Fri Dec 21 16:37:46 UTC 2012


The function comedi_buf_alloc() uses two loops to free the buf_page_list.
The first one is used at the beginning as part of deallocating any old
buffer. The second is used to cleanup the buffer if the new allocation
fails.

Factor out the common code to a new function.

Signed-off-by: H Hartley Sweeten <hsweeten at visionengravers.com>
Cc: Ian Abbott <abbobbi at mev.co.uk>
Cc: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 drivers/staging/comedi/comedi_buf.c | 88 ++++++++++++++-----------------------
 1 file changed, 33 insertions(+), 55 deletions(-)

diff --git a/drivers/staging/comedi/comedi_buf.c b/drivers/staging/comedi/comedi_buf.c
index 838f089..37656d9 100644
--- a/drivers/staging/comedi/comedi_buf.c
+++ b/drivers/staging/comedi/comedi_buf.c
@@ -22,6 +22,34 @@
 #include "comedidev.h"
 #include "comedi_internal.h"
 
+static void comedi_buf_free_page_list(struct comedi_device *dev,
+				      struct comedi_subdevice *s,
+				      unsigned n_pages)
+{
+	struct comedi_async *async = s->async;
+	struct comedi_buf_page *buf;
+	unsigned i;
+
+	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)
 {
@@ -40,33 +68,9 @@ int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s,
 		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;
-	}
+	if (async->buf_page_list)
+		comedi_buf_free_page_list(dev, s, async->n_buf_pages);
+
 	/*  allocate new buffer */
 	if (new_size) {
 		unsigned i = 0;
@@ -116,34 +120,8 @@ int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s,
 
 		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->buf_page_list)
+				comedi_buf_free_page_list(dev, s, n_pages);
 			return -ENOMEM;
 		}
 		async->n_buf_pages = n_pages;
-- 
1.8.0




More information about the devel mailing list