#define MYDRVNAME "memregion"
-struct memregion {
- HOSTADDRESS physaddr;
- ulong nbytes;
- void __iomem *mapped;
- BOOL requested;
- BOOL overlapped;
-};
-
-static BOOL mapit(struct memregion *memregion);
+static int mapit(struct memregion *memregion);
static void unmapit(struct memregion *memregion);
struct memregion *
-visor_memregion_create(HOSTADDRESS physaddr, ulong nbytes)
+visor_memregion_create(struct memregion *memregion,
+ HOSTADDRESS physaddr, ulong nbytes)
{
struct memregion *rc = NULL;
- struct memregion *memregion;
-
- memregion = kzalloc(sizeof(*memregion), GFP_KERNEL | __GFP_NORETRY);
- if (memregion == NULL)
- return NULL;
memregion->physaddr = physaddr;
memregion->nbytes = nbytes;
- memregion->overlapped = FALSE;
- if (!mapit(memregion)) {
+ if (mapit(memregion)) {
rc = NULL;
goto cleanup;
}
}
EXPORT_SYMBOL_GPL(visor_memregion_create);
-struct memregion *
-visor_memregion_create_overlapped(struct memregion *parent, ulong offset,
- ulong nbytes)
-{
- struct memregion *memregion = NULL;
-
- if (parent == NULL)
- return NULL;
-
- if (parent->mapped == NULL)
- return NULL;
-
- if ((offset >= parent->nbytes) ||
- ((offset + nbytes) >= parent->nbytes))
- return NULL;
-
- memregion = kzalloc(sizeof(*memregion), GFP_KERNEL|__GFP_NORETRY);
- if (memregion == NULL)
- return NULL;
-
- memregion->physaddr = parent->physaddr + offset;
- memregion->nbytes = nbytes;
- memregion->mapped = ((u8 __iomem *)(parent->mapped)) + offset;
- memregion->requested = FALSE;
- memregion->overlapped = TRUE;
- return memregion;
-}
-EXPORT_SYMBOL_GPL(visor_memregion_create_overlapped);
-
-static BOOL
+static int
mapit(struct memregion *memregion)
{
ulong physaddr = (ulong)(memregion->physaddr);
ulong nbytes = memregion->nbytes;
- memregion->requested = FALSE;
- if (request_mem_region(physaddr, nbytes, MYDRVNAME))
- memregion->requested = TRUE;
+ if (!request_mem_region(physaddr, nbytes, MYDRVNAME))
+ return -EBUSY;
+
memregion->mapped = ioremap_cache(physaddr, nbytes);
if (!memregion->mapped)
- return FALSE;
- return TRUE;
+ return -EFAULT;
+
+ return 0;
}
static void
unmapit(struct memregion *memregion)
{
- if (memregion->mapped != NULL) {
+ if (memregion->mapped) {
iounmap(memregion->mapped);
memregion->mapped = NULL;
- }
- if (memregion->requested) {
- release_mem_region((ulong)(memregion->physaddr),
+ release_mem_region((unsigned long)memregion->physaddr,
memregion->nbytes);
- memregion->requested = FALSE;
}
}
int
visor_memregion_resize(struct memregion *memregion, ulong newsize)
{
+ int rc;
+
if (newsize == memregion->nbytes)
return 0;
- if (memregion->overlapped)
- /* no error check here - we no longer know the
- * parent's range!
- */
- memregion->nbytes = newsize;
- else {
- unmapit(memregion);
- memregion->nbytes = newsize;
- if (!mapit(memregion))
- return -1;
- }
- return 0;
-}
-EXPORT_SYMBOL_GPL(visor_memregion_resize);
-
-static int
-memregion_readwrite(BOOL is_write,
- struct memregion *memregion, ulong offset,
- void *local, ulong nbytes)
-{
- if (offset + nbytes > memregion->nbytes)
- return -EIO;
- if (is_write)
- memcpy_toio(memregion->mapped + offset, local, nbytes);
- else
- memcpy_fromio(local, memregion->mapped + offset, nbytes);
+ unmapit(memregion);
+ memregion->nbytes = newsize;
+ rc = mapit(memregion);
- return 0;
+ return rc;
}
+EXPORT_SYMBOL_GPL(visor_memregion_resize);
int
visor_memregion_read(struct memregion *memregion, ulong offset, void *dest,
ulong nbytes)
{
- return memregion_readwrite(FALSE, memregion, offset, dest, nbytes);
+ if (offset + nbytes > memregion->nbytes)
+ return -EIO;
+
+ memcpy_fromio(dest, memregion->mapped + offset, nbytes);
+ return 0;
}
EXPORT_SYMBOL_GPL(visor_memregion_read);
visor_memregion_write(struct memregion *memregion, ulong offset, void *src,
ulong nbytes)
{
- return memregion_readwrite(TRUE, memregion, offset, src, nbytes);
+ if (offset + nbytes > memregion->nbytes)
+ return -EIO;
+
+ memcpy_toio(memregion->mapped + offset, src, nbytes);
+ return 0;
}
EXPORT_SYMBOL_GPL(visor_memregion_write);
void
visor_memregion_destroy(struct memregion *memregion)
{
- if (memregion == NULL)
+ if (!memregion)
return;
- if (!memregion->overlapped)
- unmapit(memregion);
- kfree(memregion);
+ unmapit(memregion);
}
EXPORT_SYMBOL_GPL(visor_memregion_destroy);
-