The patch tries to implement a solution suggested by Russell King, 
http://lists.infradead.org/pipermail/linux-arm-kernel/2010-December/035264.html.
 
It is expected to solve video buffer allocation issues for at least a 
few soc_camera I/O memory less host interface drivers, designed around 
the videobuf_dma_contig layer, which allocates video buffers using 
dma_alloc_coherent().

Created against linux-2.6.37-rc5.

Tested on ARM OMAP1 based Amstrad Delta with a WIP OMAP1 camera patch, 
patterned upon two mach-mx3 machine types which already try to use the 
dma_declare_coherent_memory() method for reserving a region of system 
RAM preallocated with another dma_alloc_coherent(). Compile tested for 
all modified files except arch/sh/drivers/pci/fixups-dreamcast.c.

Signed-off-by: Janusz Krzysztofik <jkrzy...@tis.icnet.pl>
---
I intended to quote Russell in my commit message and even asked him for 
his permission, but since he didn't respond, I decided to include a link 
to his original message only.

 Documentation/DMA-API.txt                  |   18 +++++++----
 arch/arm/mach-mx3/mach-mx31moboard.c       |    2 -
 arch/arm/mach-mx3/mach-pcm037.c            |    2 -
 arch/sh/drivers/pci/fixups-dreamcast.c     |    6 +++
 drivers/base/dma-coherent.c                |   12 +------
 drivers/base/dma-mapping.c                 |    4 +-
 drivers/media/video/sh_mobile_ceu_camera.c |   20 +++++++++++-
 drivers/scsi/NCR_Q720.c                    |   15 +++++++--
 drivers/usb/gadget/langwell_udc.c          |   25 ++++++++++++----
 drivers/usb/gadget/langwell_udc.h          |    1
 drivers/usb/host/ohci-sm501.c              |   45 ++++++++++++++++++++---------
 drivers/usb/host/ohci-tmio.c               |   14 ++++++++-
 include/asm-generic/dma-coherent.h         |    2 -
 include/linux/dma-mapping.h                |    6 +--
 14 files changed, 122 insertions(+), 50 deletions(-)

--- linux-2.6.37-rc5/include/linux/dma-mapping.h.orig   2010-12-09 
23:09:05.000000000 +0100
+++ linux-2.6.37-rc5/include/linux/dma-mapping.h        2010-12-23 
18:32:24.000000000 +0100
@@ -164,7 +164,7 @@ static inline int dma_get_cache_alignmen
 
 #ifndef ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY
 static inline int
-dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
+dma_declare_coherent_memory(struct device *dev, void *virt_addr,
                            dma_addr_t device_addr, size_t size, int flags)
 {
        return 0;
@@ -195,13 +195,13 @@ extern void *dmam_alloc_noncoherent(stru
 extern void dmam_free_noncoherent(struct device *dev, size_t size, void *vaddr,
                                  dma_addr_t dma_handle);
 #ifdef ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY
-extern int dmam_declare_coherent_memory(struct device *dev, dma_addr_t 
bus_addr,
+extern int dmam_declare_coherent_memory(struct device *dev, void *virt_addr,
                                        dma_addr_t device_addr, size_t size,
                                        int flags);
 extern void dmam_release_declared_memory(struct device *dev);
 #else /* ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY */
 static inline int dmam_declare_coherent_memory(struct device *dev,
-                               dma_addr_t bus_addr, dma_addr_t device_addr,
+                               void *virt_addr, dma_addr_t device_addr,
                                size_t size, gfp_t gfp)
 {
        return 0;
--- linux-2.6.37-rc5/include/asm-generic/dma-coherent.h.orig    2010-12-09 
23:09:04.000000000 +0100
+++ linux-2.6.37-rc5/include/asm-generic/dma-coherent.h 2010-12-23 
18:32:24.000000000 +0100
@@ -15,7 +15,7 @@ int dma_release_from_coherent(struct dev
  */
 #define ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY
 extern int
-dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
+dma_declare_coherent_memory(struct device *dev, void *virt_addr,
                            dma_addr_t device_addr, size_t size, int flags);
 
 extern void
--- linux-2.6.37-rc5/Documentation/DMA-API.txt.orig     2010-12-09 
23:07:27.000000000 +0100
+++ linux-2.6.37-rc5/Documentation/DMA-API.txt  2010-12-23 18:32:24.000000000 
+0100
@@ -477,20 +477,25 @@ continuing on for size.  Again, you *mus
 boundaries when doing this.
 
 int
-dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
+dma_declare_coherent_memory(struct device *dev, void *virt_addr,
                            dma_addr_t device_addr, size_t size, int
                            flags)
 
 Declare region of memory to be handed out by dma_alloc_coherent when
 it's asked for coherent memory for this device.
 
-bus_addr is the physical address to which the memory is currently
-assigned in the bus responding region (this will be used by the
-platform to perform the mapping).
+virt_addr is the virtual address to which the pysical memory in the bus
+responding region is currently mapped (this will be handed out by
+dma_alloc_coherent() directly as its return value). Both a pointer to
+the ioremaped memory on the peripheral's bus, as well as a
+dma_alloc_coherent() obtained pointer to a host memory region can be
+cached.
 
 device_addr is the physical address the device needs to be programmed
 with actually to address this memory (this will be handed out as the
-dma_addr_t in dma_alloc_coherent()).
+dma_addr_t in dma_alloc_coherent()). Either the peripheral's memory
+physical address or a dma_alloc_coherent() obtained host memory region's
+dma handle is passed.
 
 size is the size of the area (must be multiples of PAGE_SIZE).
 
@@ -537,7 +542,8 @@ Remove the memory region previously decl
 API performs *no* in-use checking for this region and will return
 unconditionally having removed all the required structures.  It is the
 driver's job to ensure that no parts of this memory region are
-currently in use.
+currently in use. The driver should also revert any memory mapping done
+in preparation for dma_declare_coherent_memory().
 
 void *
 dma_mark_declared_memory_occupied(struct device *dev,
--- linux-2.6.37-rc5/arch/sh/drivers/pci/fixups-dreamcast.c.orig        
2010-12-09 23:07:50.000000000 +0100
+++ linux-2.6.37-rc5/arch/sh/drivers/pci/fixups-dreamcast.c     2010-12-23 
20:44:27.000000000 +0100
@@ -31,6 +31,7 @@
 static void __init gapspci_fixup_resources(struct pci_dev *dev)
 {
        struct pci_channel *p = dev->sysdata;
+       void __iomem *virt_base;
 
        printk(KERN_NOTICE "PCI: Fixing up device %s\n", pci_name(dev));
 
@@ -51,8 +52,11 @@ static void __init gapspci_fixup_resourc
                /*
                 * Redirect dma memory allocations to special memory window.
                 */
+               virt_base = ioremap(GAPSPCI_DMA_BASE, GAPSPCI_DMA_SIZE);
+               BUG_ON(!virt_base);
+
                BUG_ON(!dma_declare_coherent_memory(&dev->dev,
-                                               GAPSPCI_DMA_BASE,
+                                               virt_base,
                                                GAPSPCI_DMA_BASE,
                                                GAPSPCI_DMA_SIZE,
                                                DMA_MEMORY_MAP |
--- linux-2.6.37-rc5/arch/arm/mach-mx3/mach-pcm037.c.orig       2010-12-09 
23:07:34.000000000 +0100
+++ linux-2.6.37-rc5/arch/arm/mach-mx3/mach-pcm037.c    2010-12-23 
18:32:24.000000000 +0100
@@ -431,7 +431,7 @@ static int __init pcm037_camera_alloc_dm
        memset(buf, 0, buf_size);
 
        dma = dma_declare_coherent_memory(&mx3_camera.dev,
-                                       dma_handle, dma_handle, buf_size,
+                                       buf, dma_handle, buf_size,
                                        DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE);
 
        /* The way we call dma_declare_coherent_memory only a malloc can fail */
--- linux-2.6.37-rc5/arch/arm/mach-mx3/mach-mx31moboard.c.orig  2010-12-09 
23:07:34.000000000 +0100
+++ linux-2.6.37-rc5/arch/arm/mach-mx3/mach-mx31moboard.c       2010-12-23 
18:32:24.000000000 +0100
@@ -486,7 +486,7 @@ static int __init mx31moboard_cam_alloc_
        memset(buf, 0, buf_size);
 
        dma = dma_declare_coherent_memory(&mx3_camera.dev,
-                                       dma_handle, dma_handle, buf_size,
+                                       buf, dma_handle, buf_size,
                                        DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE);
 
        /* The way we call dma_declare_coherent_memory only a malloc can fail */
--- linux-2.6.37-rc5/drivers/base/dma-mapping.c.orig    2010-12-09 
23:08:03.000000000 +0100
+++ linux-2.6.37-rc5/drivers/base/dma-mapping.c 2010-12-23 18:32:24.000000000 
+0100
@@ -183,7 +183,7 @@ static void dmam_coherent_decl_release(s
  * RETURNS:
  * 0 on success, -errno on failure.
  */
-int dmam_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
+int dmam_declare_coherent_memory(struct device *dev, void *virt_addr,
                                 dma_addr_t device_addr, size_t size, int flags)
 {
        void *res;
@@ -193,7 +193,7 @@ int dmam_declare_coherent_memory(struct 
        if (!res)
                return -ENOMEM;
 
-       rc = dma_declare_coherent_memory(dev, bus_addr, device_addr, size,
+       rc = dma_declare_coherent_memory(dev, virt_addr, device_addr, size,
                                         flags);
        if (rc == 0)
                devres_add(dev, res);
--- linux-2.6.37-rc5/drivers/base/dma-coherent.c.orig   2010-12-09 
23:08:03.000000000 +0100
+++ linux-2.6.37-rc5/drivers/base/dma-coherent.c        2010-12-23 
18:32:24.000000000 +0100
@@ -14,10 +14,9 @@ struct dma_coherent_mem {
        unsigned long   *bitmap;
 };
 
-int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
+int dma_declare_coherent_memory(struct device *dev, void *virt_addr,
                                dma_addr_t device_addr, size_t size, int flags)
 {
-       void __iomem *mem_base = NULL;
        int pages = size >> PAGE_SHIFT;
        int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
 
@@ -30,10 +29,6 @@ int dma_declare_coherent_memory(struct d
 
        /* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */
 
-       mem_base = ioremap(bus_addr, size);
-       if (!mem_base)
-               goto out;
-
        dev->dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
        if (!dev->dma_mem)
                goto out;
@@ -41,7 +36,7 @@ int dma_declare_coherent_memory(struct d
        if (!dev->dma_mem->bitmap)
                goto free1_out;
 
-       dev->dma_mem->virt_base = mem_base;
+       dev->dma_mem->virt_base = virt_addr;
        dev->dma_mem->device_base = device_addr;
        dev->dma_mem->size = pages;
        dev->dma_mem->flags = flags;
@@ -54,8 +49,6 @@ int dma_declare_coherent_memory(struct d
  free1_out:
        kfree(dev->dma_mem);
  out:
-       if (mem_base)
-               iounmap(mem_base);
        return 0;
 }
 EXPORT_SYMBOL(dma_declare_coherent_memory);
@@ -67,7 +60,6 @@ void dma_release_declared_memory(struct 
        if (!mem)
                return;
        dev->dma_mem = NULL;
-       iounmap(mem->virt_base);
        kfree(mem->bitmap);
        kfree(mem);
 }
--- linux-2.6.37-rc5/drivers/usb/host/ohci-sm501.c.orig 2010-12-09 
23:08:51.000000000 +0100
+++ linux-2.6.37-rc5/drivers/usb/host/ohci-sm501.c      2010-12-23 
22:38:19.000000000 +0100
@@ -42,7 +42,8 @@ static int ohci_sm501_start(struct usb_h
 static const struct hc_driver ohci_sm501_hc_driver = {
        .description =          hcd_name,
        .product_desc =         "SM501 OHCI",
-       .hcd_priv_size =        sizeof(struct ohci_hcd),
+       .hcd_priv_size =        sizeof(struct ohci_hcd) +
+                                               sizeof(void __iomem *),
 
        /*
         * generic hardware linkage
@@ -89,6 +90,8 @@ static int ohci_hcd_sm501_drv_probe(stru
        const struct hc_driver *driver = &ohci_sm501_hc_driver;
        struct device *dev = &pdev->dev;
        struct resource *res, *mem;
+       void __iomem *mem_vaddr;
+       void __iomem **mem_vaddr_p;
        int retval, irq;
        struct usb_hcd *hcd = NULL;
 
@@ -124,14 +127,21 @@ static int ohci_hcd_sm501_drv_probe(stru
         * regular memory. The HCD_LOCAL_MEM flag does just that.
         */
 
-       if (!dma_declare_coherent_memory(dev, mem->start,
+       mem_vaddr = ioremap(mem->start, mem->end - mem->start + 1);
+       if (!mem_vaddr) {
+               dev_err(dev, "ioremap failed\n");
+               retval = -EIO;
+               goto err1;
+       }
+
+       if (!dma_declare_coherent_memory(dev, mem_vaddr,
                                         mem->start - mem->parent->start,
                                         (mem->end - mem->start) + 1,
                                         DMA_MEMORY_MAP |
                                         DMA_MEMORY_EXCLUSIVE)) {
                dev_err(dev, "cannot declare coherent memory\n");
                retval = -ENXIO;
-               goto err1;
+               goto err2;
        }
 
        /* allocate, reserve and remap resources for registers */
@@ -139,36 +149,39 @@ static int ohci_hcd_sm501_drv_probe(stru
        if (res == NULL) {
                dev_err(dev, "no resource definition for registers\n");
                retval = -ENOENT;
-               goto err2;
+               goto err3;
        }
 
        hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
        if (!hcd) {
                retval = -ENOMEM;
-               goto err2;
+               goto err3;
        }
 
+       mem_vaddr_p = (void __iomem **)(hcd_to_ohci(hcd) + 1);
+       *mem_vaddr_p = mem_vaddr;
+
        hcd->rsrc_start = res->start;
        hcd->rsrc_len = res->end - res->start + 1;
 
        if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, pdev->name)) {
                dev_err(dev, "request_mem_region failed\n");
                retval = -EBUSY;
-               goto err3;
+               goto err4;
        }
 
        hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
        if (hcd->regs == NULL) {
                dev_err(dev, "cannot remap registers\n");
                retval = -ENXIO;
-               goto err4;
+               goto err5;
        }
 
        ohci_hcd_init(hcd_to_ohci(hcd));
 
        retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
        if (retval)
-               goto err5;
+               goto err6;
 
        /* enable power and unmask interrupts */
 
@@ -176,14 +189,16 @@ static int ohci_hcd_sm501_drv_probe(stru
        sm501_modify_reg(dev->parent, SM501_IRQ_MASK, 1 << 6, 0);
 
        return 0;
-err5:
+err6:
        iounmap(hcd->regs);
-err4:
+err5:
        release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-err3:
+err4:
        usb_put_hcd(hcd);
-err2:
+err3:
        dma_release_declared_memory(dev);
+err2:
+       iounmap(mem_vaddr);
 err1:
        release_mem_region(mem->start, mem->end - mem->start + 1);
 err0:
@@ -193,6 +208,7 @@ err0:
 static int ohci_hcd_sm501_drv_remove(struct platform_device *pdev)
 {
        struct usb_hcd *hcd = platform_get_drvdata(pdev);
+       void __iomem **mem_vaddr_p;
        struct resource *mem;
 
        usb_remove_hcd(hcd);
@@ -200,8 +216,11 @@ static int ohci_hcd_sm501_drv_remove(str
        usb_put_hcd(hcd);
        dma_release_declared_memory(&pdev->dev);
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-       if (mem)
+       if (mem) {
+               mem_vaddr_p = (void __iomem **)(hcd_to_ohci(hcd) + 1);
+               iounmap(*mem_vaddr_p);
                release_mem_region(mem->start, mem->end - mem->start + 1);
+       }
 
        /* mask interrupts and disable power */
 
--- linux-2.6.37-rc5/drivers/usb/host/ohci-tmio.c.orig  2010-12-09 
23:08:51.000000000 +0100
+++ linux-2.6.37-rc5/drivers/usb/host/ohci-tmio.c       2010-12-23 
22:40:45.000000000 +0100
@@ -67,6 +67,7 @@
 
 struct tmio_hcd {
        void __iomem            *ccr;
+       void __iomem            *sram_vaddr;
        spinlock_t              lock; /* protects RMW cycles */
 };
 
@@ -226,7 +227,13 @@ static int __devinit ohci_hcd_tmio_drv_p
                goto err_ioremap_regs;
        }
 
-       if (!dma_declare_coherent_memory(&dev->dev, sram->start,
+       tmio->sram_vaddr = ioremap(sram->start, sram->end - sram->start + 1);
+       if (!tmio->sram_vaddr) {
+               ret = -EIO;
+               goto err_ioremap_sram;
+       }
+
+       if (!dma_declare_coherent_memory(&dev->dev, tmio->sram_vaddr,
                                sram->start,
                                sram->end - sram->start + 1,
                                DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE)) {
@@ -260,6 +267,8 @@ err_add_hcd:
 err_enable:
        dma_release_declared_memory(&dev->dev);
 err_dma_declare:
+       iounmap(tmio->sram_vaddr);
+err_ioremap_sram:
        iounmap(hcd->regs);
 err_ioremap_regs:
        iounmap(tmio->ccr);
@@ -275,12 +284,15 @@ static int __devexit ohci_hcd_tmio_drv_r
        struct usb_hcd *hcd = platform_get_drvdata(dev);
        struct tmio_hcd *tmio = hcd_to_tmio(hcd);
        struct mfd_cell *cell = dev->dev.platform_data;
+       struct resource *sram = platform_get_resource(dev, IORESOURCE_MEM, 2);
 
        usb_remove_hcd(hcd);
        tmio_stop_hc(dev);
        if (cell->disable)
                cell->disable(dev);
        dma_release_declared_memory(&dev->dev);
+       if (sram)
+               iounmap(tmio->sram_vaddr);
        iounmap(hcd->regs);
        iounmap(tmio->ccr);
        usb_put_hcd(hcd);
--- linux-2.6.37-rc5/drivers/usb/gadget/langwell_udc.c.orig     2010-12-09 
23:08:46.000000000 +0100
+++ linux-2.6.37-rc5/drivers/usb/gadget/langwell_udc.c  2010-12-23 
22:05:17.000000000 +0100
@@ -3024,14 +3024,26 @@ static void sram_init(struct langwell_ud
 
        if (pci_request_region(pdev, 1, kobject_name(&pdev->dev.kobj))) {
                dev_warn(&dev->pdev->dev, "SRAM request failed\n");
-               dev->got_sram = 0;
-       } else if (!dma_declare_coherent_memory(&pdev->dev, dev->sram_addr,
-                       dev->sram_addr, dev->sram_size, DMA_MEMORY_MAP)) {
-               dev_warn(&dev->pdev->dev, "SRAM DMA declare failed\n");
-               pci_release_region(pdev, 1);
-               dev->got_sram = 0;
+               goto out_no_sram;
        }
 
+       dev->sram_vaddr = ioremap(dev->sram_addr, dev->sram_size);
+       if (!dev->sram_vaddr) {
+               dev_warn(&dev->pdev->dev, "SRAM ioremap failed\n");
+               goto out_release;
+       }
+
+       if (dma_declare_coherent_memory(&pdev->dev, dev->sram_vaddr,
+                       dev->sram_addr, dev->sram_size, DMA_MEMORY_MAP))
+               goto out;
+       dev_warn(&dev->pdev->dev, "SRAM DMA declare failed\n");
+
+       iounmap(dev->sram_vaddr);
+out_release:
+       pci_release_region(pdev, 1);
+out_no_sram:
+       dev->got_sram = 0;
+out:
        dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
@@ -3044,6 +3056,7 @@ static void sram_deinit(struct langwell_
        dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
        dma_release_declared_memory(&pdev->dev);
+       iounmap(dev->sram_vaddr);
        pci_release_region(pdev, 1);
 
        dev->got_sram = 0;
--- linux-2.6.37-rc5/drivers/usb/gadget/langwell_udc.h.orig     2010-12-09 
23:08:46.000000000 +0100
+++ linux-2.6.37-rc5/drivers/usb/gadget/langwell_udc.h  2010-12-23 
22:03:56.000000000 +0100
@@ -226,6 +226,7 @@ struct langwell_udc {
        /* for private SRAM caching */
        unsigned int            sram_addr;
        unsigned int            sram_size;
+       void __iomem            *sram_vaddr;
 
        /* device status data for get_status request */
        u16                     dev_status;
--- linux-2.6.37-rc5/drivers/media/video/sh_mobile_ceu_camera.c.orig    
2010-12-09 23:08:15.000000000 +0100
+++ linux-2.6.37-rc5/drivers/media/video/sh_mobile_ceu_camera.c 2010-12-23 
22:21:25.000000000 +0100
@@ -97,6 +97,7 @@ struct sh_mobile_ceu_dev {
 
        unsigned int irq;
        void __iomem *base;
+       void __iomem *buf;
        unsigned long video_limit;
 
        /* lock used to protect videobuf */
@@ -1888,6 +1889,7 @@ static int __devinit sh_mobile_ceu_probe
        struct sh_mobile_ceu_dev *pcdev;
        struct resource *res;
        void __iomem *base;
+       void __iomem *buf = NULL;
        unsigned int irq;
        int err = 0;
        struct bus_wait wait = {
@@ -1934,7 +1936,14 @@ static int __devinit sh_mobile_ceu_probe
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
        if (res) {
-               err = dma_declare_coherent_memory(&pdev->dev, res->start,
+               buf = ioremap(res->start, resource_size(res));
+               if (!buf) {
+                       dev_err(&pdev->dev, "Unable to ioremap CEU memory.\n");
+                       err = -ENXIO;
+                       goto exit_iounmap_base;
+               }
+
+               err = dma_declare_coherent_memory(&pdev->dev, buf,
                                                  res->start,
                                                  resource_size(res),
                                                  DMA_MEMORY_MAP |
@@ -1945,6 +1954,7 @@ static int __devinit sh_mobile_ceu_probe
                        goto exit_iounmap;
                }
 
+               pcdev->buf = buf;
                pcdev->video_limit = resource_size(res);
        }
 
@@ -2021,6 +2031,9 @@ exit_release_mem:
        if (platform_get_resource(pdev, IORESOURCE_MEM, 1))
                dma_release_declared_memory(&pdev->dev);
 exit_iounmap:
+       if (buf)
+               iounmap(buf);
+exit_iounmap_base:
        iounmap(base);
 exit_kfree:
        kfree(pcdev);
@@ -2034,12 +2047,15 @@ static int __devexit sh_mobile_ceu_remov
        struct sh_mobile_ceu_dev *pcdev = container_of(soc_host,
                                        struct sh_mobile_ceu_dev, ici);
        struct device *csi2 = pcdev->pdata->csi2_dev;
+       struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 
        soc_camera_host_unregister(soc_host);
        pm_runtime_disable(&pdev->dev);
        free_irq(pcdev->irq, pcdev);
-       if (platform_get_resource(pdev, IORESOURCE_MEM, 1))
+       if (res) {
                dma_release_declared_memory(&pdev->dev);
+               iounmap(pcdev->buf);
+       }
        iounmap(pcdev->base);
        if (csi2 && csi2->driver)
                module_put(csi2->driver->owner);
--- linux-2.6.37-rc5/drivers/scsi/NCR_Q720.c.orig       2010-12-09 
23:08:35.000000000 +0100
+++ linux-2.6.37-rc5/drivers/scsi/NCR_Q720.c    2010-12-23 22:13:19.000000000 
+0100
@@ -147,7 +147,7 @@ NCR_Q720_probe(struct device *dev)
        __u8 pos2, pos4, asr2, asr9, asr10;
        __u16 io_base;
        __u32 base_addr, mem_size;
-       void __iomem *mem_base;
+       void __iomem *mem_base, *dma_mem_base;
 
        p = kzalloc(sizeof(*p), GFP_KERNEL);
        if (!p)
@@ -216,11 +216,17 @@ NCR_Q720_probe(struct device *dev)
                goto out_free;
        }
        
-       if (dma_declare_coherent_memory(dev, base_addr, base_addr,
+       dma_mem_base = ioremap(base_addr, mem_size);
+       if (!dma_mem_base) {
+               printk(KERN_ERR "NCR_Q720: ioremap DMA memory failed\n");
+               goto out_release_region;
+       }
+
+       if (dma_declare_coherent_memory(dev, dma_mem_base, base_addr,
                                        mem_size, DMA_MEMORY_MAP)
            != DMA_MEMORY_MAP) {
                printk(KERN_ERR "NCR_Q720: DMA declare memory failed\n");
-               goto out_release_region;
+               goto out_iounmap;
        }
 
        /* The first 1k of the memory buffer is a memory map of the registers
@@ -311,6 +317,8 @@ NCR_Q720_probe(struct device *dev)
 
  out_release:
        dma_release_declared_memory(dev);
+ out_iounmap:
+       iounmap(dma_mem_base);
  out_release_region:
        release_mem_region(base_addr, mem_size);
  out_free:
@@ -337,6 +345,7 @@ NCR_Q720_remove(struct device *dev)
                        NCR_Q720_remove_one(p->hosts[i]);
 
        dma_release_declared_memory(dev);
+       iounmap(p->mem_base);
        release_mem_region(p->phys_mem_base, p->mem_size);
        free_irq(p->irq, p);
        kfree(p);
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to