staging: unisys: fix visorchipset sysfs attribute functions
[deliverable/linux.git] / drivers / staging / unisys / visorutil / memregion_direct.c
CommitLineData
9d9baadd
KC
1/* memregion_direct.c
2 *
f6d0c1e6 3 * Copyright (C) 2010 - 2013 UNISYS CORPORATION
9d9baadd
KC
4 * All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or (at
9 * your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
14 * NON INFRINGEMENT. See the GNU General Public License for more
15 * details.
16 */
17
18/*
19 * This is an implementation of memory regions that can be used to read/write
20 * channel memory (in main memory of the host system) from code running in
21 * a virtual partition.
22 */
23#include "uniklog.h"
24#include "timskmod.h"
25#include "memregion.h"
26
27#define MYDRVNAME "memregion"
28
29struct MEMREGION_Tag {
30 HOSTADDRESS physaddr;
31 ulong nbytes;
3db5540d 32 void __iomem *mapped;
9d9baadd
KC
33 BOOL requested;
34 BOOL overlapped;
35};
36
37static BOOL mapit(MEMREGION *memregion);
38static void unmapit(MEMREGION *memregion);
39
40MEMREGION *
927c7927 41visor_memregion_create(HOSTADDRESS physaddr, ulong nbytes)
9d9baadd
KC
42{
43 MEMREGION *rc = NULL;
a3acc83a
S
44 MEMREGION *memregion = kzalloc(sizeof(MEMREGION),
45 GFP_KERNEL | __GFP_NORETRY);
9d9baadd 46 if (memregion == NULL) {
927c7927 47 ERRDRV("visor_memregion_create allocation failed");
9d9baadd
KC
48 return NULL;
49 }
9d9baadd
KC
50 memregion->physaddr = physaddr;
51 memregion->nbytes = nbytes;
52 memregion->overlapped = FALSE;
d9355f89
KC
53 if (!mapit(memregion)) {
54 rc = NULL;
55 goto Away;
56 }
57 rc = memregion;
9d9baadd
KC
58Away:
59 if (rc == NULL) {
60 if (memregion != NULL) {
927c7927 61 visor_memregion_destroy(memregion);
9d9baadd
KC
62 memregion = NULL;
63 }
64 }
65 return rc;
66}
927c7927 67EXPORT_SYMBOL_GPL(visor_memregion_create);
9d9baadd
KC
68
69MEMREGION *
927c7927 70visor_memregion_create_overlapped(MEMREGION *parent, ulong offset, ulong nbytes)
9d9baadd
KC
71{
72 MEMREGION *memregion = NULL;
73
74 if (parent == NULL) {
75 ERRDRV("%s parent is NULL", __func__);
76 return NULL;
77 }
78 if (parent->mapped == NULL) {
79 ERRDRV("%s parent is not mapped!", __func__);
80 return NULL;
81 }
82 if ((offset >= parent->nbytes) ||
83 ((offset + nbytes) >= parent->nbytes)) {
84 ERRDRV("%s range (%lu,%lu) out of parent range",
85 __func__, offset, nbytes);
86 return NULL;
87 }
97a84f12 88 memregion = kzalloc(sizeof(MEMREGION), GFP_KERNEL|__GFP_NORETRY);
9d9baadd
KC
89 if (memregion == NULL) {
90 ERRDRV("%s allocation failed", __func__);
91 return NULL;
92 }
97a84f12 93
9d9baadd
KC
94 memregion->physaddr = parent->physaddr + offset;
95 memregion->nbytes = nbytes;
3db5540d 96 memregion->mapped = ((u8 __iomem *) (parent->mapped)) + offset;
9d9baadd
KC
97 memregion->requested = FALSE;
98 memregion->overlapped = TRUE;
99 return memregion;
100}
927c7927 101EXPORT_SYMBOL_GPL(visor_memregion_create_overlapped);
9d9baadd
KC
102
103
104static BOOL
105mapit(MEMREGION *memregion)
106{
107 ulong physaddr = (ulong) (memregion->physaddr);
108 ulong nbytes = memregion->nbytes;
109
110 memregion->requested = FALSE;
111 if (!request_mem_region(physaddr, nbytes, MYDRVNAME))
112 ERRDRV("cannot reserve channel memory @0x%lx for 0x%lx-- no big deal", physaddr, nbytes);
113 else
114 memregion->requested = TRUE;
115 memregion->mapped = ioremap_cache(physaddr, nbytes);
116 if (memregion->mapped == NULL) {
117 ERRDRV("cannot ioremap_cache channel memory @0x%lx for 0x%lx",
118 physaddr, nbytes);
119 return FALSE;
120 }
121 return TRUE;
122}
123
124static void
125unmapit(MEMREGION *memregion)
126{
127 if (memregion->mapped != NULL) {
128 iounmap(memregion->mapped);
129 memregion->mapped = NULL;
130 }
131 if (memregion->requested) {
132 release_mem_region((ulong) (memregion->physaddr),
133 memregion->nbytes);
134 memregion->requested = FALSE;
135 }
136}
137
138HOSTADDRESS
927c7927 139visor_memregion_get_physaddr(MEMREGION *memregion)
9d9baadd
KC
140{
141 return memregion->physaddr;
142}
927c7927 143EXPORT_SYMBOL_GPL(visor_memregion_get_physaddr);
9d9baadd
KC
144
145ulong
927c7927 146visor_memregion_get_nbytes(MEMREGION *memregion)
9d9baadd
KC
147{
148 return memregion->nbytes;
149}
927c7927 150EXPORT_SYMBOL_GPL(visor_memregion_get_nbytes);
9d9baadd 151
3db5540d 152void __iomem *
927c7927 153visor_memregion_get_pointer(MEMREGION *memregion)
9d9baadd
KC
154{
155 return memregion->mapped;
156}
927c7927 157EXPORT_SYMBOL_GPL(visor_memregion_get_pointer);
9d9baadd
KC
158
159int
927c7927 160visor_memregion_resize(MEMREGION *memregion, ulong newsize)
9d9baadd
KC
161{
162 if (newsize == memregion->nbytes)
163 return 0;
164 if (memregion->overlapped)
165 /* no error check here - we no longer know the
166 * parent's range!
167 */
168 memregion->nbytes = newsize;
169 else {
170 unmapit(memregion);
171 memregion->nbytes = newsize;
172 if (!mapit(memregion))
173 return -1;
174 }
175 return 0;
176}
927c7927 177EXPORT_SYMBOL_GPL(visor_memregion_resize);
9d9baadd
KC
178
179
180static int
181memregion_readwrite(BOOL is_write,
182 MEMREGION *memregion, ulong offset,
183 void *local, ulong nbytes)
184{
185 if (offset + nbytes > memregion->nbytes) {
186 ERRDRV("memregion_readwrite offset out of range!!");
66e24b76 187 return -EIO;
9d9baadd
KC
188 }
189 if (is_write)
190 memcpy_toio(memregion->mapped + offset, local, nbytes);
191 else
192 memcpy_fromio(local, memregion->mapped + offset, nbytes);
193
194 return 0;
195}
196
197int
927c7927
KC
198visor_memregion_read(MEMREGION *memregion, ulong offset, void *dest,
199 ulong nbytes)
9d9baadd
KC
200{
201 return memregion_readwrite(FALSE, memregion, offset, dest, nbytes);
202}
927c7927 203EXPORT_SYMBOL_GPL(visor_memregion_read);
9d9baadd
KC
204
205int
927c7927
KC
206visor_memregion_write(MEMREGION *memregion, ulong offset, void *src,
207 ulong nbytes)
9d9baadd
KC
208{
209 return memregion_readwrite(TRUE, memregion, offset, src, nbytes);
210}
927c7927 211EXPORT_SYMBOL_GPL(visor_memregion_write);
9d9baadd
KC
212
213void
927c7927 214visor_memregion_destroy(MEMREGION *memregion)
9d9baadd
KC
215{
216 if (memregion == NULL)
217 return;
218 if (!memregion->overlapped)
219 unmapit(memregion);
220 kfree(memregion);
221}
927c7927 222EXPORT_SYMBOL_GPL(visor_memregion_destroy);
9d9baadd 223
This page took 0.155243 seconds and 5 git commands to generate.