linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / arch / arm / common / dmabounce.c
index 028bdc9..ad6c89a 100644 (file)
@@ -5,7 +5,7 @@
  *  limited DMA windows. These functions utilize bounce buffers to
  *  copy data to/from buffers located outside the DMA region. This
  *  only works for systems in which DMA memory is at the bottom of
- *  RAM, the remainder of memory is at the top and the DMA memory
+ *  RAM and the remainder of memory is at the top an the DMA memory
  *  can be marked as ZONE_DMA. Anything beyond that such as discontigous
  *  DMA windows will require custom implementations that reserve memory
  *  areas at early bootup.
@@ -77,8 +77,6 @@ struct dmabounce_device_info {
 #endif
        struct dmabounce_pool   small;
        struct dmabounce_pool   large;
-
-       rwlock_t lock;
 };
 
 static LIST_HEAD(dmabounce_devs);
@@ -118,7 +116,6 @@ 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);
@@ -166,12 +163,8 @@ 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;
 }
 
@@ -179,34 +172,22 @@ alloc_safe_buffer(struct dmabounce_device_info *device_info, void *ptr,
 static inline struct safe_buffer *
 find_safe_buffer(struct dmabounce_device_info *device_info, dma_addr_t safe_dma_addr)
 {
-       struct safe_buffer *b, *rb = NULL;
-       unsigned long flags;
-
-       read_lock_irqsave(&device_info->lock, flags);
+       struct safe_buffer *b;
 
        list_for_each_entry(b, &device_info->safe_buffers, node)
-               if (b->safe_dma_addr == safe_dma_addr) {
-                       rb = b;
-                       break;
-               }
+               if (b->safe_dma_addr == safe_dma_addr)
+                       return b;
 
-       read_unlock_irqrestore(&device_info->lock, flags);
-       return rb;
+       return NULL;
 }
 
 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
@@ -415,6 +396,7 @@ 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",
@@ -422,8 +404,12 @@ dma_map_single(struct device *dev, void *ptr, size_t size,
 
        BUG_ON(dir == DMA_NONE);
 
+       local_irq_save(flags);
+
        dma_addr = map_single(dev, ptr, size, dir);
 
+       local_irq_restore(flags);
+
        return dma_addr;
 }
 
@@ -438,18 +424,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",
@@ -457,6 +450,8 @@ dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
 
        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;
@@ -467,6 +462,8 @@ dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
                        map_single(dev, ptr, length, dir);
        }
 
+       local_irq_restore(flags);
+
        return nents;
 }
 
@@ -474,6 +471,7 @@ 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",
@@ -481,38 +479,55 @@ dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
 
        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",
@@ -520,18 +535,23 @@ dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nents,
 
        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",
@@ -539,12 +559,16 @@ dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents,
 
        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
@@ -598,7 +622,6 @@ 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;