Skip to content

Commit

Permalink
[ARM] 3537/1: Rework DMA-bounce locking for finer granularity
Browse files Browse the repository at this point in the history
Patch from Kevin Hilman

This time with IRQ versions of locks.

Rework also enables compatability with realtime-preemption patch.
With the current locking via interrupt disabling, under RT,
potentially sleeping functions can be called with interrupts
disabled.

Signed-off-by: Kevin Hilman <khilman@mvista.com>
Signed-off-by: Deepak Saxena <dsaxena@plexity.net>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
  • Loading branch information
Kevin Hilman authored and Russell King committed Jun 22, 2006
1 parent fa3e686 commit 823588c
Showing 1 changed file with 21 additions and 46 deletions.
67 changes: 21 additions & 46 deletions arch/arm/common/dmabounce.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ struct dmabounce_device_info {
#endif
struct dmabounce_pool small;
struct dmabounce_pool large;

rwlock_t lock;
};

static LIST_HEAD(dmabounce_devs);
Expand Down Expand Up @@ -116,6 +118,7 @@ alloc_safe_buffer(struct dmabounce_device_info *device_info, void *ptr,
struct safe_buffer *buf;
struct dmabounce_pool *pool;
struct device *dev = device_info->dev;
unsigned long flags;

dev_dbg(dev, "%s(ptr=%p, size=%d, dir=%d)\n",
__func__, ptr, size, dir);
Expand Down Expand Up @@ -163,31 +166,45 @@ alloc_safe_buffer(struct dmabounce_device_info *device_info, void *ptr,
print_alloc_stats(device_info);
#endif

write_lock_irqsave(&device_info->lock, flags);

list_add(&buf->node, &device_info->safe_buffers);

write_unlock_irqrestore(&device_info->lock, flags);

return buf;
}

/* determine if a buffer is from our "safe" pool */
static inline struct safe_buffer *
find_safe_buffer(struct dmabounce_device_info *device_info, dma_addr_t safe_dma_addr)
{
struct safe_buffer *b;
struct safe_buffer *b = NULL;
unsigned long flags;

read_lock_irqsave(&device_info->lock, flags);

list_for_each_entry(b, &device_info->safe_buffers, node)
if (b->safe_dma_addr == safe_dma_addr)
return b;
break;

return NULL;
read_unlock_irqrestore(&device_info->lock, flags);
return b;
}

static inline void
free_safe_buffer(struct dmabounce_device_info *device_info, struct safe_buffer *buf)
{
unsigned long flags;

dev_dbg(device_info->dev, "%s(buf=%p)\n", __func__, buf);

write_lock_irqsave(&device_info->lock, flags);

list_del(&buf->node);

write_unlock_irqrestore(&device_info->lock, flags);

if (buf->pool)
dma_pool_free(buf->pool->pool, buf->safe, buf->safe_dma_addr);
else
Expand Down Expand Up @@ -396,20 +413,15 @@ dma_addr_t
dma_map_single(struct device *dev, void *ptr, size_t size,
enum dma_data_direction dir)
{
unsigned long flags;
dma_addr_t dma_addr;

dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
__func__, ptr, size, dir);

BUG_ON(dir == DMA_NONE);

local_irq_save(flags);

dma_addr = map_single(dev, ptr, size, dir);

local_irq_restore(flags);

return dma_addr;
}

Expand All @@ -424,34 +436,25 @@ void
dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
enum dma_data_direction dir)
{
unsigned long flags;

dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
__func__, (void *) dma_addr, size, dir);

BUG_ON(dir == DMA_NONE);

local_irq_save(flags);

unmap_single(dev, dma_addr, size, dir);

local_irq_restore(flags);
}

int
dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
enum dma_data_direction dir)
{
unsigned long flags;
int i;

dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n",
__func__, sg, nents, dir);

BUG_ON(dir == DMA_NONE);

local_irq_save(flags);

for (i = 0; i < nents; i++, sg++) {
struct page *page = sg->page;
unsigned int offset = sg->offset;
Expand All @@ -462,113 +465,84 @@ dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
map_single(dev, ptr, length, dir);
}

local_irq_restore(flags);

return nents;
}

void
dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
enum dma_data_direction dir)
{
unsigned long flags;
int i;

dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n",
__func__, sg, nents, dir);

BUG_ON(dir == DMA_NONE);

local_irq_save(flags);

for (i = 0; i < nents; i++, sg++) {
dma_addr_t dma_addr = sg->dma_address;
unsigned int length = sg->length;

unmap_single(dev, dma_addr, length, dir);
}

local_irq_restore(flags);
}

void
dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_addr, size_t size,
enum dma_data_direction dir)
{
unsigned long flags;

dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
__func__, (void *) dma_addr, size, dir);

local_irq_save(flags);

sync_single(dev, dma_addr, size, dir);

local_irq_restore(flags);
}

void
dma_sync_single_for_device(struct device *dev, dma_addr_t dma_addr, size_t size,
enum dma_data_direction dir)
{
unsigned long flags;

dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
__func__, (void *) dma_addr, size, dir);

local_irq_save(flags);

sync_single(dev, dma_addr, size, dir);

local_irq_restore(flags);
}

void
dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nents,
enum dma_data_direction dir)
{
unsigned long flags;
int i;

dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n",
__func__, sg, nents, dir);

BUG_ON(dir == DMA_NONE);

local_irq_save(flags);

for (i = 0; i < nents; i++, sg++) {
dma_addr_t dma_addr = sg->dma_address;
unsigned int length = sg->length;

sync_single(dev, dma_addr, length, dir);
}

local_irq_restore(flags);
}

void
dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents,
enum dma_data_direction dir)
{
unsigned long flags;
int i;

dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n",
__func__, sg, nents, dir);

BUG_ON(dir == DMA_NONE);

local_irq_save(flags);

for (i = 0; i < nents; i++, sg++) {
dma_addr_t dma_addr = sg->dma_address;
unsigned int length = sg->length;

sync_single(dev, dma_addr, length, dir);
}

local_irq_restore(flags);
}

static int
Expand Down Expand Up @@ -622,6 +596,7 @@ dmabounce_register_dev(struct device *dev, unsigned long small_buffer_size,

device_info->dev = dev;
INIT_LIST_HEAD(&device_info->safe_buffers);
rwlock_init(&device_info->lock);

#ifdef STATS
device_info->total_allocs = 0;
Expand Down

0 comments on commit 823588c

Please sign in to comment.