diff options
author | Yunhong Jiang <yunhong.jiang@intel.com> | 2015-08-04 12:17:53 -0700 |
---|---|---|
committer | Yunhong Jiang <yunhong.jiang@intel.com> | 2015-08-04 15:44:42 -0700 |
commit | 9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00 (patch) | |
tree | 1c9cafbcd35f783a87880a10f85d1a060db1a563 /kernel/drivers/staging/unisys/visorutil/memregion_direct.c | |
parent | 98260f3884f4a202f9ca5eabed40b1354c489b29 (diff) |
Add the rt linux 4.1.3-rt3 as base
Import the rt linux 4.1.3-rt3 as OPNFV kvm base.
It's from git://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-rt-devel.git linux-4.1.y-rt and
the base is:
commit 0917f823c59692d751951bf5ea699a2d1e2f26a2
Author: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Date: Sat Jul 25 12:13:34 2015 +0200
Prepare v4.1.3-rt3
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
We lose all the git history this way and it's not good. We
should apply another opnfv project repo in future.
Change-Id: I87543d81c9df70d99c5001fbdf646b202c19f423
Signed-off-by: Yunhong Jiang <yunhong.jiang@intel.com>
Diffstat (limited to 'kernel/drivers/staging/unisys/visorutil/memregion_direct.c')
-rw-r--r-- | kernel/drivers/staging/unisys/visorutil/memregion_direct.c | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/kernel/drivers/staging/unisys/visorutil/memregion_direct.c b/kernel/drivers/staging/unisys/visorutil/memregion_direct.c new file mode 100644 index 000000000..eb7422fbe --- /dev/null +++ b/kernel/drivers/staging/unisys/visorutil/memregion_direct.c @@ -0,0 +1,207 @@ +/* memregion_direct.c + * + * Copyright (C) 2010 - 2013 UNISYS CORPORATION + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for more + * details. + */ + +/* + * This is an implementation of memory regions that can be used to read/write + * channel memory (in main memory of the host system) from code running in + * a virtual partition. + */ +#include "timskmod.h" +#include "memregion.h" + +#define MYDRVNAME "memregion" + +struct memregion { + HOSTADDRESS physaddr; + ulong nbytes; + void __iomem *mapped; + BOOL requested; + BOOL overlapped; +}; + +static BOOL mapit(struct memregion *memregion); +static void unmapit(struct memregion *memregion); + +struct memregion * +visor_memregion_create(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)) { + rc = NULL; + goto cleanup; + } + rc = memregion; +cleanup: + if (rc == NULL) { + visor_memregion_destroy(memregion); + memregion = NULL; + } + return rc; +} +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 +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; + memregion->mapped = ioremap_cache(physaddr, nbytes); + if (!memregion->mapped) + return FALSE; + return TRUE; +} + +static void +unmapit(struct memregion *memregion) +{ + if (memregion->mapped != NULL) { + iounmap(memregion->mapped); + memregion->mapped = NULL; + } + if (memregion->requested) { + release_mem_region((ulong)(memregion->physaddr), + memregion->nbytes); + memregion->requested = FALSE; + } +} + +HOSTADDRESS +visor_memregion_get_physaddr(struct memregion *memregion) +{ + return memregion->physaddr; +} +EXPORT_SYMBOL_GPL(visor_memregion_get_physaddr); + +ulong +visor_memregion_get_nbytes(struct memregion *memregion) +{ + return memregion->nbytes; +} +EXPORT_SYMBOL_GPL(visor_memregion_get_nbytes); + +void __iomem * +visor_memregion_get_pointer(struct memregion *memregion) +{ + return memregion->mapped; +} +EXPORT_SYMBOL_GPL(visor_memregion_get_pointer); + +int +visor_memregion_resize(struct memregion *memregion, ulong newsize) +{ + 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); + + return 0; +} + +int +visor_memregion_read(struct memregion *memregion, ulong offset, void *dest, + ulong nbytes) +{ + return memregion_readwrite(FALSE, memregion, offset, dest, nbytes); +} +EXPORT_SYMBOL_GPL(visor_memregion_read); + +int +visor_memregion_write(struct memregion *memregion, ulong offset, void *src, + ulong nbytes) +{ + return memregion_readwrite(TRUE, memregion, offset, src, nbytes); +} +EXPORT_SYMBOL_GPL(visor_memregion_write); + +void +visor_memregion_destroy(struct memregion *memregion) +{ + if (memregion == NULL) + return; + if (!memregion->overlapped) + unmapit(memregion); + kfree(memregion); +} +EXPORT_SYMBOL_GPL(visor_memregion_destroy); + |