This source file includes following definitions.
- visorchannel_destroy
- visorchannel_get_physaddr
- visorchannel_get_nbytes
- visorchannel_guid_id
- visorchannel_id
- visorchannel_zoneid
- visorchannel_get_clientpartition
- visorchannel_set_clientpartition
- visorchannel_get_guid
- visorchannel_read
- visorchannel_write
- visorchannel_get_header
- sig_queue_offset
- sig_data_offset
- sig_read_header
- sig_read_data
- sig_write_data
- signalremove_inner
- visorchannel_signalremove
- queue_empty
- visorchannel_signalempty
- signalinsert_inner
- visorchannel_create
- visorchannel_signalinsert
1
2
3
4
5
6
7
8
9
10
11
12 #include <linux/uuid.h>
13 #include <linux/io.h>
14 #include <linux/slab.h>
15 #include <linux/visorbus.h>
16
17 #include "visorbus_private.h"
18 #include "controlvmchannel.h"
19
20 #define VISOR_DRV_NAME "visorchannel"
21
22 #define VISOR_CONSOLEVIDEO_CHANNEL_GUID \
23 GUID_INIT(0x3cd6e705, 0xd6a2, 0x4aa5, \
24 0xad, 0x5c, 0x7b, 0x8, 0x88, 0x9d, 0xff, 0xe2)
25
26 static const guid_t visor_video_guid = VISOR_CONSOLEVIDEO_CHANNEL_GUID;
27
28 struct visorchannel {
29 u64 physaddr;
30 ulong nbytes;
31 void *mapped;
32 bool requested;
33 struct channel_header chan_hdr;
34 guid_t guid;
35
36
37
38
39 bool needs_lock;
40
41 spinlock_t insert_lock;
42
43 spinlock_t remove_lock;
44 guid_t type;
45 guid_t inst;
46 };
47
48 void visorchannel_destroy(struct visorchannel *channel)
49 {
50 if (!channel)
51 return;
52
53 if (channel->mapped) {
54 memunmap(channel->mapped);
55 if (channel->requested)
56 release_mem_region(channel->physaddr, channel->nbytes);
57 }
58 kfree(channel);
59 }
60
61 u64 visorchannel_get_physaddr(struct visorchannel *channel)
62 {
63 return channel->physaddr;
64 }
65
66 ulong visorchannel_get_nbytes(struct visorchannel *channel)
67 {
68 return channel->nbytes;
69 }
70
71 char *visorchannel_guid_id(const guid_t *guid, char *s)
72 {
73 sprintf(s, "%pUL", guid);
74 return s;
75 }
76
77 char *visorchannel_id(struct visorchannel *channel, char *s)
78 {
79 return visorchannel_guid_id(&channel->guid, s);
80 }
81
82 char *visorchannel_zoneid(struct visorchannel *channel, char *s)
83 {
84 return visorchannel_guid_id(&channel->chan_hdr.zone_guid, s);
85 }
86
87 u64 visorchannel_get_clientpartition(struct visorchannel *channel)
88 {
89 return channel->chan_hdr.partition_handle;
90 }
91
92 int visorchannel_set_clientpartition(struct visorchannel *channel,
93 u64 partition_handle)
94 {
95 channel->chan_hdr.partition_handle = partition_handle;
96 return 0;
97 }
98
99
100
101
102
103
104
105 const guid_t *visorchannel_get_guid(struct visorchannel *channel)
106 {
107 return &channel->guid;
108 }
109 EXPORT_SYMBOL_GPL(visorchannel_get_guid);
110
111 int visorchannel_read(struct visorchannel *channel, ulong offset, void *dest,
112 ulong nbytes)
113 {
114 if (offset + nbytes > channel->nbytes)
115 return -EIO;
116
117 memcpy(dest, channel->mapped + offset, nbytes);
118 return 0;
119 }
120
121 int visorchannel_write(struct visorchannel *channel, ulong offset, void *dest,
122 ulong nbytes)
123 {
124 size_t chdr_size = sizeof(struct channel_header);
125 size_t copy_size;
126
127 if (offset + nbytes > channel->nbytes)
128 return -EIO;
129
130 if (offset < chdr_size) {
131 copy_size = min(chdr_size - offset, nbytes);
132 memcpy(((char *)(&channel->chan_hdr)) + offset,
133 dest, copy_size);
134 }
135 memcpy(channel->mapped + offset, dest, nbytes);
136 return 0;
137 }
138
139 void *visorchannel_get_header(struct visorchannel *channel)
140 {
141 return &channel->chan_hdr;
142 }
143
144
145
146
147
148 static int sig_queue_offset(struct channel_header *chan_hdr, int q)
149 {
150 return ((chan_hdr)->ch_space_offset +
151 ((q) * sizeof(struct signal_queue_header)));
152 }
153
154
155
156
157
158 static int sig_data_offset(struct channel_header *chan_hdr, int q,
159 struct signal_queue_header *sig_hdr, int slot)
160 {
161 return (sig_queue_offset(chan_hdr, q) + sig_hdr->sig_base_offset +
162 (slot * sig_hdr->signal_size));
163 }
164
165
166
167
168
169 #define SIG_WRITE_FIELD(channel, queue, sig_hdr, FIELD) \
170 visorchannel_write(channel, \
171 sig_queue_offset(&channel->chan_hdr, queue) + \
172 offsetof(struct signal_queue_header, FIELD), \
173 &((sig_hdr)->FIELD), \
174 sizeof((sig_hdr)->FIELD))
175
176 static int sig_read_header(struct visorchannel *channel, u32 queue,
177 struct signal_queue_header *sig_hdr)
178 {
179 if (channel->chan_hdr.ch_space_offset < sizeof(struct channel_header))
180 return -EINVAL;
181
182
183 return visorchannel_read(channel,
184 sig_queue_offset(&channel->chan_hdr, queue),
185 sig_hdr, sizeof(struct signal_queue_header));
186 }
187
188 static int sig_read_data(struct visorchannel *channel, u32 queue,
189 struct signal_queue_header *sig_hdr, u32 slot,
190 void *data)
191 {
192 int signal_data_offset = sig_data_offset(&channel->chan_hdr, queue,
193 sig_hdr, slot);
194
195 return visorchannel_read(channel, signal_data_offset,
196 data, sig_hdr->signal_size);
197 }
198
199 static int sig_write_data(struct visorchannel *channel, u32 queue,
200 struct signal_queue_header *sig_hdr, u32 slot,
201 void *data)
202 {
203 int signal_data_offset = sig_data_offset(&channel->chan_hdr, queue,
204 sig_hdr, slot);
205
206 return visorchannel_write(channel, signal_data_offset,
207 data, sig_hdr->signal_size);
208 }
209
210 static int signalremove_inner(struct visorchannel *channel, u32 queue,
211 void *msg)
212 {
213 struct signal_queue_header sig_hdr;
214 int error;
215
216 error = sig_read_header(channel, queue, &sig_hdr);
217 if (error)
218 return error;
219
220 if (sig_hdr.head == sig_hdr.tail)
221 return -EAGAIN;
222 sig_hdr.tail = (sig_hdr.tail + 1) % sig_hdr.max_slots;
223 error = sig_read_data(channel, queue, &sig_hdr, sig_hdr.tail, msg);
224 if (error)
225 return error;
226 sig_hdr.num_received++;
227
228
229
230
231 mb();
232 error = SIG_WRITE_FIELD(channel, queue, &sig_hdr, tail);
233 if (error)
234 return error;
235 error = SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_received);
236 if (error)
237 return error;
238 return 0;
239 }
240
241
242
243
244
245
246
247
248
249
250 int visorchannel_signalremove(struct visorchannel *channel, u32 queue,
251 void *msg)
252 {
253 int rc;
254 unsigned long flags;
255
256 if (channel->needs_lock) {
257 spin_lock_irqsave(&channel->remove_lock, flags);
258 rc = signalremove_inner(channel, queue, msg);
259 spin_unlock_irqrestore(&channel->remove_lock, flags);
260 } else {
261 rc = signalremove_inner(channel, queue, msg);
262 }
263
264 return rc;
265 }
266 EXPORT_SYMBOL_GPL(visorchannel_signalremove);
267
268 static bool queue_empty(struct visorchannel *channel, u32 queue)
269 {
270 struct signal_queue_header sig_hdr;
271
272 if (sig_read_header(channel, queue, &sig_hdr))
273 return true;
274 return (sig_hdr.head == sig_hdr.tail);
275 }
276
277
278
279
280
281
282
283
284
285
286 bool visorchannel_signalempty(struct visorchannel *channel, u32 queue)
287 {
288 bool rc;
289 unsigned long flags;
290
291 if (!channel->needs_lock)
292 return queue_empty(channel, queue);
293 spin_lock_irqsave(&channel->remove_lock, flags);
294 rc = queue_empty(channel, queue);
295 spin_unlock_irqrestore(&channel->remove_lock, flags);
296 return rc;
297 }
298 EXPORT_SYMBOL_GPL(visorchannel_signalempty);
299
300 static int signalinsert_inner(struct visorchannel *channel, u32 queue,
301 void *msg)
302 {
303 struct signal_queue_header sig_hdr;
304 int err;
305
306 err = sig_read_header(channel, queue, &sig_hdr);
307 if (err)
308 return err;
309 sig_hdr.head = (sig_hdr.head + 1) % sig_hdr.max_slots;
310 if (sig_hdr.head == sig_hdr.tail) {
311 sig_hdr.num_overflows++;
312 err = SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_overflows);
313 if (err)
314 return err;
315 return -EIO;
316 }
317 err = sig_write_data(channel, queue, &sig_hdr, sig_hdr.head, msg);
318 if (err)
319 return err;
320 sig_hdr.num_sent++;
321
322
323
324
325 mb();
326 err = SIG_WRITE_FIELD(channel, queue, &sig_hdr, head);
327 if (err)
328 return err;
329 err = SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_sent);
330 if (err)
331 return err;
332 return 0;
333 }
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349 struct visorchannel *visorchannel_create(u64 physaddr, gfp_t gfp,
350 const guid_t *guid, bool needs_lock)
351 {
352 struct visorchannel *channel;
353 int err;
354 size_t size = sizeof(struct channel_header);
355
356 if (physaddr == 0)
357 return NULL;
358
359 channel = kzalloc(sizeof(*channel), gfp);
360 if (!channel)
361 return NULL;
362 channel->needs_lock = needs_lock;
363 spin_lock_init(&channel->insert_lock);
364 spin_lock_init(&channel->remove_lock);
365
366
367
368
369
370
371 channel->requested = request_mem_region(physaddr, size, VISOR_DRV_NAME);
372 if (!channel->requested && !guid_equal(guid, &visor_video_guid))
373
374 goto err_destroy_channel;
375 channel->mapped = memremap(physaddr, size, MEMREMAP_WB);
376 if (!channel->mapped) {
377 release_mem_region(physaddr, size);
378 goto err_destroy_channel;
379 }
380 channel->physaddr = physaddr;
381 channel->nbytes = size;
382 err = visorchannel_read(channel, 0, &channel->chan_hdr, size);
383 if (err)
384 goto err_destroy_channel;
385 size = (ulong)channel->chan_hdr.size;
386 memunmap(channel->mapped);
387 if (channel->requested)
388 release_mem_region(channel->physaddr, channel->nbytes);
389 channel->mapped = NULL;
390 channel->requested = request_mem_region(channel->physaddr, size,
391 VISOR_DRV_NAME);
392 if (!channel->requested && !guid_equal(guid, &visor_video_guid))
393
394 goto err_destroy_channel;
395 channel->mapped = memremap(channel->physaddr, size, MEMREMAP_WB);
396 if (!channel->mapped) {
397 release_mem_region(channel->physaddr, size);
398 goto err_destroy_channel;
399 }
400 channel->nbytes = size;
401 guid_copy(&channel->guid, guid);
402 return channel;
403
404 err_destroy_channel:
405 visorchannel_destroy(channel);
406 return NULL;
407 }
408
409
410
411
412
413
414
415
416
417
418 int visorchannel_signalinsert(struct visorchannel *channel, u32 queue,
419 void *msg)
420 {
421 int rc;
422 unsigned long flags;
423
424 if (channel->needs_lock) {
425 spin_lock_irqsave(&channel->insert_lock, flags);
426 rc = signalinsert_inner(channel, queue, msg);
427 spin_unlock_irqrestore(&channel->insert_lock, flags);
428 } else {
429 rc = signalinsert_inner(channel, queue, msg);
430 }
431
432 return rc;
433 }
434 EXPORT_SYMBOL_GPL(visorchannel_signalinsert);