]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/staging/unisys/visorbus/visorchannel.c
Merge branch 'x86-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[mirror_ubuntu-bionic-kernel.git] / drivers / staging / unisys / visorbus / visorchannel.c
1 /* visorchannel_funcs.c
2 *
3 * Copyright (C) 2010 - 2015 UNISYS CORPORATION
4 * All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
13 * NON INFRINGEMENT. See the GNU General Public License for more
14 * details.
15 */
16
17 /*
18 * This provides Supervisor channel communication primitives, which are
19 * independent of the mechanism used to access the channel data.
20 */
21
22 #include <linux/uuid.h>
23
24 #include "version.h"
25 #include "visorbus.h"
26 #include "controlvmchannel.h"
27
28 #define MYDRVNAME "visorchannel"
29
30 #define SPAR_CONSOLEVIDEO_CHANNEL_PROTOCOL_GUID \
31 UUID_LE(0x3cd6e705, 0xd6a2, 0x4aa5, \
32 0xad, 0x5c, 0x7b, 0x8, 0x88, 0x9d, 0xff, 0xe2)
33 static const uuid_le spar_video_guid = SPAR_CONSOLEVIDEO_CHANNEL_PROTOCOL_GUID;
34
35 struct visorchannel {
36 u64 physaddr;
37 ulong nbytes;
38 void __iomem *mapped;
39 bool requested;
40 struct channel_header chan_hdr;
41 uuid_le guid;
42 ulong size;
43 bool needs_lock; /* channel creator knows if more than one
44 * thread will be inserting or removing */
45 spinlock_t insert_lock; /* protect head writes in chan_hdr */
46 spinlock_t remove_lock; /* protect tail writes in chan_hdr */
47
48 struct {
49 struct signal_queue_header req_queue;
50 struct signal_queue_header rsp_queue;
51 struct signal_queue_header event_queue;
52 struct signal_queue_header ack_queue;
53 } safe_uis_queue;
54 uuid_le type;
55 uuid_le inst;
56 };
57
58 /* Creates the struct visorchannel abstraction for a data area in memory,
59 * but does NOT modify this data area.
60 */
61 static struct visorchannel *
62 visorchannel_create_guts(u64 physaddr, unsigned long channel_bytes,
63 gfp_t gfp, unsigned long off,
64 uuid_le guid, bool needs_lock)
65 {
66 struct visorchannel *channel;
67 int err;
68 size_t size = sizeof(struct channel_header);
69
70 if (physaddr == 0)
71 return NULL;
72
73 channel = kzalloc(sizeof(*channel), gfp);
74 if (!channel)
75 goto cleanup;
76
77 channel->needs_lock = needs_lock;
78 spin_lock_init(&channel->insert_lock);
79 spin_lock_init(&channel->remove_lock);
80
81 /* Video driver constains the efi framebuffer so it will get a
82 * conflict resource when requesting its full mem region. Since
83 * we are only using the efi framebuffer for video we can ignore
84 * this. Remember that we haven't requested it so we don't try to
85 * release later on.
86 */
87 channel->requested = request_mem_region(physaddr, size, MYDRVNAME);
88 if (!channel->requested) {
89 if (uuid_le_cmp(guid, spar_video_guid)) {
90 /* Not the video channel we care about this */
91 goto cleanup;
92 }
93 }
94
95 channel->mapped = ioremap_cache(physaddr, size);
96 if (!channel->mapped) {
97 release_mem_region(physaddr, size);
98 goto cleanup;
99 }
100
101 channel->physaddr = physaddr;
102 channel->nbytes = size;
103
104 err = visorchannel_read(channel, 0, &channel->chan_hdr,
105 sizeof(struct channel_header));
106 if (err)
107 goto cleanup;
108
109 /* we had better be a CLIENT of this channel */
110 if (channel_bytes == 0)
111 channel_bytes = (ulong)channel->chan_hdr.size;
112 if (uuid_le_cmp(guid, NULL_UUID_LE) == 0)
113 guid = channel->chan_hdr.chtype;
114
115 iounmap(channel->mapped);
116 if (channel->requested)
117 release_mem_region(channel->physaddr, channel->nbytes);
118 channel->mapped = NULL;
119 channel->requested = request_mem_region(channel->physaddr,
120 channel_bytes, MYDRVNAME);
121 if (!channel->requested) {
122 if (uuid_le_cmp(guid, spar_video_guid)) {
123 /* Different we care about this */
124 goto cleanup;
125 }
126 }
127
128 channel->mapped = ioremap_cache(channel->physaddr, channel_bytes);
129 if (!channel->mapped) {
130 release_mem_region(channel->physaddr, channel_bytes);
131 goto cleanup;
132 }
133
134 channel->nbytes = channel_bytes;
135
136 channel->size = channel_bytes;
137 channel->guid = guid;
138 return channel;
139
140 cleanup:
141 visorchannel_destroy(channel);
142 return NULL;
143 }
144
145 struct visorchannel *
146 visorchannel_create(u64 physaddr, unsigned long channel_bytes,
147 gfp_t gfp, uuid_le guid)
148 {
149 return visorchannel_create_guts(physaddr, channel_bytes, gfp, 0, guid,
150 false);
151 }
152 EXPORT_SYMBOL_GPL(visorchannel_create);
153
154 struct visorchannel *
155 visorchannel_create_with_lock(u64 physaddr, unsigned long channel_bytes,
156 gfp_t gfp, uuid_le guid)
157 {
158 return visorchannel_create_guts(physaddr, channel_bytes, gfp, 0, guid,
159 true);
160 }
161 EXPORT_SYMBOL_GPL(visorchannel_create_with_lock);
162
163 void
164 visorchannel_destroy(struct visorchannel *channel)
165 {
166 if (!channel)
167 return;
168 if (channel->mapped) {
169 iounmap(channel->mapped);
170 if (channel->requested)
171 release_mem_region(channel->physaddr, channel->nbytes);
172 }
173 kfree(channel);
174 }
175 EXPORT_SYMBOL_GPL(visorchannel_destroy);
176
177 u64
178 visorchannel_get_physaddr(struct visorchannel *channel)
179 {
180 return channel->physaddr;
181 }
182 EXPORT_SYMBOL_GPL(visorchannel_get_physaddr);
183
184 ulong
185 visorchannel_get_nbytes(struct visorchannel *channel)
186 {
187 return channel->size;
188 }
189 EXPORT_SYMBOL_GPL(visorchannel_get_nbytes);
190
191 char *
192 visorchannel_uuid_id(uuid_le *guid, char *s)
193 {
194 sprintf(s, "%pUL", guid);
195 return s;
196 }
197 EXPORT_SYMBOL_GPL(visorchannel_uuid_id);
198
199 char *
200 visorchannel_id(struct visorchannel *channel, char *s)
201 {
202 return visorchannel_uuid_id(&channel->guid, s);
203 }
204 EXPORT_SYMBOL_GPL(visorchannel_id);
205
206 char *
207 visorchannel_zoneid(struct visorchannel *channel, char *s)
208 {
209 return visorchannel_uuid_id(&channel->chan_hdr.zone_uuid, s);
210 }
211 EXPORT_SYMBOL_GPL(visorchannel_zoneid);
212
213 u64
214 visorchannel_get_clientpartition(struct visorchannel *channel)
215 {
216 return channel->chan_hdr.partition_handle;
217 }
218 EXPORT_SYMBOL_GPL(visorchannel_get_clientpartition);
219
220 int
221 visorchannel_set_clientpartition(struct visorchannel *channel,
222 u64 partition_handle)
223 {
224 channel->chan_hdr.partition_handle = partition_handle;
225 return 0;
226 }
227 EXPORT_SYMBOL_GPL(visorchannel_set_clientpartition);
228
229 uuid_le
230 visorchannel_get_uuid(struct visorchannel *channel)
231 {
232 return channel->guid;
233 }
234 EXPORT_SYMBOL_GPL(visorchannel_get_uuid);
235
236 int
237 visorchannel_read(struct visorchannel *channel, ulong offset,
238 void *local, ulong nbytes)
239 {
240 if (offset + nbytes > channel->nbytes)
241 return -EIO;
242
243 memcpy_fromio(local, channel->mapped + offset, nbytes);
244
245 return 0;
246 }
247 EXPORT_SYMBOL_GPL(visorchannel_read);
248
249 int
250 visorchannel_write(struct visorchannel *channel, ulong offset,
251 void *local, ulong nbytes)
252 {
253 size_t chdr_size = sizeof(struct channel_header);
254 size_t copy_size;
255
256 if (offset + nbytes > channel->nbytes)
257 return -EIO;
258
259 if (offset < chdr_size) {
260 copy_size = min(chdr_size - offset, nbytes);
261 memcpy(((char *)(&channel->chan_hdr)) + offset,
262 local, copy_size);
263 }
264
265 memcpy_toio(channel->mapped + offset, local, nbytes);
266
267 return 0;
268 }
269 EXPORT_SYMBOL_GPL(visorchannel_write);
270
271 int
272 visorchannel_clear(struct visorchannel *channel, ulong offset, u8 ch,
273 ulong nbytes)
274 {
275 int err;
276 int bufsize = PAGE_SIZE;
277 int written = 0;
278 u8 *buf;
279
280 buf = (u8 *) __get_free_page(GFP_KERNEL);
281 if (!buf)
282 return -ENOMEM;
283
284 memset(buf, ch, bufsize);
285
286 while (nbytes > 0) {
287 int thisbytes = bufsize;
288
289 if (nbytes < thisbytes)
290 thisbytes = nbytes;
291 err = visorchannel_write(channel, offset + written,
292 buf, thisbytes);
293 if (err)
294 goto cleanup;
295
296 written += thisbytes;
297 nbytes -= thisbytes;
298 }
299 err = 0;
300
301 cleanup:
302 free_page((unsigned long) buf);
303 return err;
304 }
305 EXPORT_SYMBOL_GPL(visorchannel_clear);
306
307 void __iomem *
308 visorchannel_get_header(struct visorchannel *channel)
309 {
310 return (void __iomem *)&channel->chan_hdr;
311 }
312 EXPORT_SYMBOL_GPL(visorchannel_get_header);
313
314 /** Return offset of a specific SIGNAL_QUEUE_HEADER from the beginning of a
315 * channel header
316 */
317 #define SIG_QUEUE_OFFSET(chan_hdr, q) \
318 ((chan_hdr)->ch_space_offset + \
319 ((q) * sizeof(struct signal_queue_header)))
320
321 /** Return offset of a specific queue entry (data) from the beginning of a
322 * channel header
323 */
324 #define SIG_DATA_OFFSET(chan_hdr, q, sig_hdr, slot) \
325 (SIG_QUEUE_OFFSET(chan_hdr, q) + (sig_hdr)->sig_base_offset + \
326 ((slot) * (sig_hdr)->signal_size))
327
328 /** Write the contents of a specific field within a SIGNAL_QUEUE_HEADER back
329 * into host memory
330 */
331 #define SIG_WRITE_FIELD(channel, queue, sig_hdr, FIELD) \
332 (visorchannel_write(channel, \
333 SIG_QUEUE_OFFSET(&channel->chan_hdr, queue)+ \
334 offsetof(struct signal_queue_header, FIELD), \
335 &((sig_hdr)->FIELD), \
336 sizeof((sig_hdr)->FIELD)) >= 0)
337
338 static bool
339 sig_read_header(struct visorchannel *channel, u32 queue,
340 struct signal_queue_header *sig_hdr)
341 {
342 int err;
343
344 if (channel->chan_hdr.ch_space_offset < sizeof(struct channel_header))
345 return false;
346
347 /* Read the appropriate SIGNAL_QUEUE_HEADER into local memory. */
348 err = visorchannel_read(channel,
349 SIG_QUEUE_OFFSET(&channel->chan_hdr, queue),
350 sig_hdr, sizeof(struct signal_queue_header));
351 if (err)
352 return false;
353
354 return true;
355 }
356
357 static inline bool
358 sig_read_data(struct visorchannel *channel, u32 queue,
359 struct signal_queue_header *sig_hdr, u32 slot, void *data)
360 {
361 int err;
362 int signal_data_offset = SIG_DATA_OFFSET(&channel->chan_hdr, queue,
363 sig_hdr, slot);
364
365 err = visorchannel_read(channel, signal_data_offset,
366 data, sig_hdr->signal_size);
367 if (err)
368 return false;
369
370 return true;
371 }
372
373 static inline bool
374 sig_write_data(struct visorchannel *channel, u32 queue,
375 struct signal_queue_header *sig_hdr, u32 slot, void *data)
376 {
377 int err;
378 int signal_data_offset = SIG_DATA_OFFSET(&channel->chan_hdr, queue,
379 sig_hdr, slot);
380
381 err = visorchannel_write(channel, signal_data_offset,
382 data, sig_hdr->signal_size);
383 if (err)
384 return false;
385
386 return true;
387 }
388
389 static bool
390 signalremove_inner(struct visorchannel *channel, u32 queue, void *msg)
391 {
392 struct signal_queue_header sig_hdr;
393
394 if (!sig_read_header(channel, queue, &sig_hdr))
395 return false;
396 if (sig_hdr.head == sig_hdr.tail)
397 return false; /* no signals to remove */
398
399 sig_hdr.tail = (sig_hdr.tail + 1) % sig_hdr.max_slots;
400 if (!sig_read_data(channel, queue, &sig_hdr, sig_hdr.tail, msg))
401 return false;
402 sig_hdr.num_received++;
403
404 /* For each data field in SIGNAL_QUEUE_HEADER that was modified,
405 * update host memory.
406 */
407 mb(); /* required for channel synch */
408 if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, tail))
409 return false;
410 if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_received))
411 return false;
412 return true;
413 }
414
415 bool
416 visorchannel_signalremove(struct visorchannel *channel, u32 queue, void *msg)
417 {
418 bool rc;
419 unsigned long flags;
420
421 if (channel->needs_lock) {
422 spin_lock_irqsave(&channel->remove_lock, flags);
423 rc = signalremove_inner(channel, queue, msg);
424 spin_unlock_irqrestore(&channel->remove_lock, flags);
425 } else {
426 rc = signalremove_inner(channel, queue, msg);
427 }
428
429 return rc;
430 }
431 EXPORT_SYMBOL_GPL(visorchannel_signalremove);
432
433 bool
434 visorchannel_signalempty(struct visorchannel *channel, u32 queue)
435 {
436 unsigned long flags = 0;
437 struct signal_queue_header sig_hdr;
438 bool rc = false;
439
440 if (channel->needs_lock)
441 spin_lock_irqsave(&channel->remove_lock, flags);
442
443 if (!sig_read_header(channel, queue, &sig_hdr))
444 rc = true;
445 if (sig_hdr.head == sig_hdr.tail)
446 rc = true;
447 if (channel->needs_lock)
448 spin_unlock_irqrestore(&channel->remove_lock, flags);
449
450 return rc;
451 }
452 EXPORT_SYMBOL_GPL(visorchannel_signalempty);
453
454 static bool
455 signalinsert_inner(struct visorchannel *channel, u32 queue, void *msg)
456 {
457 struct signal_queue_header sig_hdr;
458
459 if (!sig_read_header(channel, queue, &sig_hdr))
460 return false;
461
462 sig_hdr.head = ((sig_hdr.head + 1) % sig_hdr.max_slots);
463 if (sig_hdr.head == sig_hdr.tail) {
464 sig_hdr.num_overflows++;
465 visorchannel_write(channel,
466 SIG_QUEUE_OFFSET(&channel->chan_hdr, queue) +
467 offsetof(struct signal_queue_header,
468 num_overflows),
469 &(sig_hdr.num_overflows),
470 sizeof(sig_hdr.num_overflows));
471 return false;
472 }
473
474 if (!sig_write_data(channel, queue, &sig_hdr, sig_hdr.head, msg))
475 return false;
476
477 sig_hdr.num_sent++;
478
479 /* For each data field in SIGNAL_QUEUE_HEADER that was modified,
480 * update host memory.
481 */
482 mb(); /* required for channel synch */
483 if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, head))
484 return false;
485 if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_sent))
486 return false;
487
488 return true;
489 }
490
491 bool
492 visorchannel_signalinsert(struct visorchannel *channel, u32 queue, void *msg)
493 {
494 bool rc;
495 unsigned long flags;
496
497 if (channel->needs_lock) {
498 spin_lock_irqsave(&channel->insert_lock, flags);
499 rc = signalinsert_inner(channel, queue, msg);
500 spin_unlock_irqrestore(&channel->insert_lock, flags);
501 } else {
502 rc = signalinsert_inner(channel, queue, msg);
503 }
504
505 return rc;
506 }
507 EXPORT_SYMBOL_GPL(visorchannel_signalinsert);
508
509 int
510 visorchannel_signalqueue_slots_avail(struct visorchannel *channel, u32 queue)
511 {
512 struct signal_queue_header sig_hdr;
513 u32 slots_avail, slots_used;
514 u32 head, tail;
515
516 if (!sig_read_header(channel, queue, &sig_hdr))
517 return 0;
518 head = sig_hdr.head;
519 tail = sig_hdr.tail;
520 if (head < tail)
521 head = head + sig_hdr.max_slots;
522 slots_used = (head - tail);
523 slots_avail = sig_hdr.max_signals - slots_used;
524 return (int)slots_avail;
525 }
526 EXPORT_SYMBOL_GPL(visorchannel_signalqueue_slots_avail);
527
528 int
529 visorchannel_signalqueue_max_slots(struct visorchannel *channel, u32 queue)
530 {
531 struct signal_queue_header sig_hdr;
532
533 if (!sig_read_header(channel, queue, &sig_hdr))
534 return 0;
535 return (int)sig_hdr.max_signals;
536 }
537 EXPORT_SYMBOL_GPL(visorchannel_signalqueue_max_slots);
538
539 static void
540 sigqueue_debug(struct signal_queue_header *q, int which, struct seq_file *seq)
541 {
542 seq_printf(seq, "Signal Queue #%d\n", which);
543 seq_printf(seq, " VersionId = %lu\n", (ulong)q->version);
544 seq_printf(seq, " Type = %lu\n", (ulong)q->chtype);
545 seq_printf(seq, " oSignalBase = %llu\n",
546 (long long)q->sig_base_offset);
547 seq_printf(seq, " SignalSize = %lu\n", (ulong)q->signal_size);
548 seq_printf(seq, " MaxSignalSlots = %lu\n",
549 (ulong)q->max_slots);
550 seq_printf(seq, " MaxSignals = %lu\n", (ulong)q->max_signals);
551 seq_printf(seq, " FeatureFlags = %-16.16Lx\n",
552 (long long)q->features);
553 seq_printf(seq, " NumSignalsSent = %llu\n",
554 (long long)q->num_sent);
555 seq_printf(seq, " NumSignalsReceived = %llu\n",
556 (long long)q->num_received);
557 seq_printf(seq, " NumOverflows = %llu\n",
558 (long long)q->num_overflows);
559 seq_printf(seq, " Head = %lu\n", (ulong)q->head);
560 seq_printf(seq, " Tail = %lu\n", (ulong)q->tail);
561 }
562
563 void
564 visorchannel_debug(struct visorchannel *channel, int num_queues,
565 struct seq_file *seq, u32 off)
566 {
567 u64 addr = 0;
568 ulong nbytes = 0, nbytes_region = 0;
569 struct channel_header hdr;
570 struct channel_header *phdr = &hdr;
571 int i = 0;
572 int errcode = 0;
573
574 if (!channel)
575 return;
576
577 addr = visorchannel_get_physaddr(channel);
578 nbytes_region = visorchannel_get_nbytes(channel);
579 errcode = visorchannel_read(channel, off,
580 phdr, sizeof(struct channel_header));
581 if (errcode < 0) {
582 seq_printf(seq,
583 "Read of channel header failed with errcode=%d)\n",
584 errcode);
585 if (off == 0) {
586 phdr = &channel->chan_hdr;
587 seq_puts(seq, "(following data may be stale)\n");
588 } else {
589 return;
590 }
591 }
592 nbytes = (ulong)(phdr->size);
593 seq_printf(seq, "--- Begin channel @0x%-16.16Lx for 0x%lx bytes (region=0x%lx bytes) ---\n",
594 addr + off, nbytes, nbytes_region);
595 seq_printf(seq, "Type = %pUL\n", &phdr->chtype);
596 seq_printf(seq, "ZoneGuid = %pUL\n", &phdr->zone_uuid);
597 seq_printf(seq, "Signature = 0x%-16.16Lx\n",
598 (long long)phdr->signature);
599 seq_printf(seq, "LegacyState = %lu\n", (ulong)phdr->legacy_state);
600 seq_printf(seq, "SrvState = %lu\n", (ulong)phdr->srv_state);
601 seq_printf(seq, "CliStateBoot = %lu\n", (ulong)phdr->cli_state_boot);
602 seq_printf(seq, "CliStateOS = %lu\n", (ulong)phdr->cli_state_os);
603 seq_printf(seq, "HeaderSize = %lu\n", (ulong)phdr->header_size);
604 seq_printf(seq, "Size = %llu\n", (long long)phdr->size);
605 seq_printf(seq, "Features = 0x%-16.16llx\n",
606 (long long)phdr->features);
607 seq_printf(seq, "PartitionHandle = 0x%-16.16llx\n",
608 (long long)phdr->partition_handle);
609 seq_printf(seq, "Handle = 0x%-16.16llx\n",
610 (long long)phdr->handle);
611 seq_printf(seq, "VersionId = %lu\n", (ulong)phdr->version_id);
612 seq_printf(seq, "oChannelSpace = %llu\n",
613 (long long)phdr->ch_space_offset);
614 if ((phdr->ch_space_offset == 0) || (errcode < 0))
615 ;
616 else
617 for (i = 0; i < num_queues; i++) {
618 struct signal_queue_header q;
619
620 errcode = visorchannel_read(channel,
621 off +
622 phdr->ch_space_offset +
623 (i * sizeof(q)),
624 &q, sizeof(q));
625 if (errcode < 0) {
626 seq_printf(seq,
627 "failed to read signal queue #%d from channel @0x%-16.16Lx errcode=%d\n",
628 i, addr, errcode);
629 continue;
630 }
631 sigqueue_debug(&q, i, seq);
632 }
633 seq_printf(seq, "--- End channel @0x%-16.16Lx for 0x%lx bytes ---\n",
634 addr + off, nbytes);
635 }
636 EXPORT_SYMBOL_GPL(visorchannel_debug);