Skip to content

Commit

Permalink
staging: comedi: comedi_buf: factor out common code to free the async…
Browse files Browse the repository at this point in the history
… 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 <hsweeten@visionengravers.com>
Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
H Hartley Sweeten authored and Greg Kroah-Hartman committed Jan 18, 2013
1 parent ea082fb commit 718c4d6
Showing 1 changed file with 43 additions and 63 deletions.
106 changes: 43 additions & 63 deletions drivers/staging/comedi/comedi_buf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 718c4d6

Please sign in to comment.