Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 84bc227d authored by Rolf Eike Beer's avatar Rolf Eike Beer Committed by Linus Torvalds
Browse files

mm/dmapool.c: take lock only once in dma_pool_free()



dma_pool_free() scans for the page to free in the pool list holding the
pool lock.  Then it releases the lock basically to acquire it immediately
again.  Modify the code to only take the lock once.

This will do some additional loops and computations with the lock held in
if memory debugging is activated.  If it is not activated the only new
operations with this lock is one if and one substraction.

Signed-off-by: default avatarRolf Eike Beer <eike-kernel@sf-tec.de>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 43506fad
Loading
Loading
Loading
Loading
+6 −8
Original line number Diff line number Diff line
@@ -355,21 +355,16 @@ EXPORT_SYMBOL(dma_pool_alloc);

static struct dma_page *pool_find_page(struct dma_pool *pool, dma_addr_t dma)
{
	unsigned long flags;
	struct dma_page *page;

	spin_lock_irqsave(&pool->lock, flags);
	list_for_each_entry(page, &pool->page_list, page_list) {
		if (dma < page->dma)
			continue;
		if (dma < (page->dma + pool->allocation))
			goto done;
	}
	page = NULL;
 done:
	spin_unlock_irqrestore(&pool->lock, flags);
			return page;
	}
	return NULL;
}

/**
 * dma_pool_free - put block back into dma pool
@@ -386,8 +381,10 @@ void dma_pool_free(struct dma_pool *pool, void *vaddr, dma_addr_t dma)
	unsigned long flags;
	unsigned int offset;

	spin_lock_irqsave(&pool->lock, flags);
	page = pool_find_page(pool, dma);
	if (!page) {
		spin_unlock_irqrestore(&pool->lock, flags);
		if (pool->dev)
			dev_err(pool->dev,
				"dma_pool_free %s, %p/%lx (bad dma)\n",
@@ -401,6 +398,7 @@ void dma_pool_free(struct dma_pool *pool, void *vaddr, dma_addr_t dma)
	offset = vaddr - page->vaddr;
#ifdef	DMAPOOL_DEBUG
	if ((dma - page->dma) != offset) {
		spin_unlock_irqrestore(&pool->lock, flags);
		if (pool->dev)
			dev_err(pool->dev,
				"dma_pool_free %s, %p (bad vaddr)/%Lx\n",
@@ -418,6 +416,7 @@ void dma_pool_free(struct dma_pool *pool, void *vaddr, dma_addr_t dma)
				chain = *(int *)(page->vaddr + chain);
				continue;
			}
			spin_unlock_irqrestore(&pool->lock, flags);
			if (pool->dev)
				dev_err(pool->dev, "dma_pool_free %s, dma %Lx "
					"already free\n", pool->name,
@@ -432,7 +431,6 @@ void dma_pool_free(struct dma_pool *pool, void *vaddr, dma_addr_t dma)
	memset(vaddr, POOL_POISON_FREED, pool->size);
#endif

	spin_lock_irqsave(&pool->lock, flags);
	page->in_use--;
	*(int *)vaddr = page->offset;
	page->offset = offset;