[PATCH] dma_declare_coherent_memory: push ioremap() up to caller

From: Janusz Krzysztofik
Date: Thu Dec 23 2010 - 18:22:44 EST


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 <jkrzyszt@xxxxxxxxxxxx>
---
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-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/