1 /* visorchannel_funcs.c
3 * Copyright (C) 2010 - 2015 UNISYS CORPORATION
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.
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
18 * This provides Supervisor channel communication primitives, which are
19 * independent of the mechanism used to access the channel data.
22 #include <linux/uuid.h>
26 #include "controlvmchannel.h"
28 #define MYDRVNAME "visorchannel"
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
;
40 struct channel_header chan_hdr
;
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 */
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
;
58 /* Creates the struct visorchannel abstraction for a data area in memory,
59 * but does NOT modify this data area.
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
)
66 struct visorchannel
*channel
;
68 size_t size
= sizeof(struct channel_header
);
73 channel
= kzalloc(sizeof(*channel
), gfp
);
77 channel
->needs_lock
= needs_lock
;
78 spin_lock_init(&channel
->insert_lock
);
79 spin_lock_init(&channel
->remove_lock
);
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
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 */
95 channel
->mapped
= ioremap_cache(physaddr
, size
);
96 if (!channel
->mapped
) {
97 release_mem_region(physaddr
, size
);
101 channel
->physaddr
= physaddr
;
102 channel
->nbytes
= size
;
104 err
= visorchannel_read(channel
, 0, &channel
->chan_hdr
,
105 sizeof(struct channel_header
));
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
;
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 */
128 channel
->mapped
= ioremap_cache(channel
->physaddr
, channel_bytes
);
129 if (!channel
->mapped
) {
130 release_mem_region(channel
->physaddr
, channel_bytes
);
134 channel
->nbytes
= channel_bytes
;
136 channel
->size
= channel_bytes
;
137 channel
->guid
= guid
;
141 visorchannel_destroy(channel
);
145 struct visorchannel
*
146 visorchannel_create(u64 physaddr
, unsigned long channel_bytes
,
147 gfp_t gfp
, uuid_le guid
)
149 return visorchannel_create_guts(physaddr
, channel_bytes
, gfp
, 0, guid
,
152 EXPORT_SYMBOL_GPL(visorchannel_create
);
154 struct visorchannel
*
155 visorchannel_create_with_lock(u64 physaddr
, unsigned long channel_bytes
,
156 gfp_t gfp
, uuid_le guid
)
158 return visorchannel_create_guts(physaddr
, channel_bytes
, gfp
, 0, guid
,
161 EXPORT_SYMBOL_GPL(visorchannel_create_with_lock
);
164 visorchannel_destroy(struct visorchannel
*channel
)
168 if (channel
->mapped
) {
169 iounmap(channel
->mapped
);
170 if (channel
->requested
)
171 release_mem_region(channel
->physaddr
, channel
->nbytes
);
175 EXPORT_SYMBOL_GPL(visorchannel_destroy
);
178 visorchannel_get_physaddr(struct visorchannel
*channel
)
180 return channel
->physaddr
;
182 EXPORT_SYMBOL_GPL(visorchannel_get_physaddr
);
185 visorchannel_get_nbytes(struct visorchannel
*channel
)
187 return channel
->size
;
189 EXPORT_SYMBOL_GPL(visorchannel_get_nbytes
);
192 visorchannel_uuid_id(uuid_le
*guid
, char *s
)
194 sprintf(s
, "%pUL", guid
);
197 EXPORT_SYMBOL_GPL(visorchannel_uuid_id
);
200 visorchannel_id(struct visorchannel
*channel
, char *s
)
202 return visorchannel_uuid_id(&channel
->guid
, s
);
204 EXPORT_SYMBOL_GPL(visorchannel_id
);
207 visorchannel_zoneid(struct visorchannel
*channel
, char *s
)
209 return visorchannel_uuid_id(&channel
->chan_hdr
.zone_uuid
, s
);
211 EXPORT_SYMBOL_GPL(visorchannel_zoneid
);
214 visorchannel_get_clientpartition(struct visorchannel
*channel
)
216 return channel
->chan_hdr
.partition_handle
;
218 EXPORT_SYMBOL_GPL(visorchannel_get_clientpartition
);
221 visorchannel_set_clientpartition(struct visorchannel
*channel
,
222 u64 partition_handle
)
224 channel
->chan_hdr
.partition_handle
= partition_handle
;
227 EXPORT_SYMBOL_GPL(visorchannel_set_clientpartition
);
230 visorchannel_get_uuid(struct visorchannel
*channel
)
232 return channel
->guid
;
234 EXPORT_SYMBOL_GPL(visorchannel_get_uuid
);
237 visorchannel_read(struct visorchannel
*channel
, ulong offset
,
238 void *local
, ulong nbytes
)
240 if (offset
+ nbytes
> channel
->nbytes
)
243 memcpy_fromio(local
, channel
->mapped
+ offset
, nbytes
);
247 EXPORT_SYMBOL_GPL(visorchannel_read
);
250 visorchannel_write(struct visorchannel
*channel
, ulong offset
,
251 void *local
, ulong nbytes
)
253 size_t chdr_size
= sizeof(struct channel_header
);
256 if (offset
+ nbytes
> channel
->nbytes
)
259 if (offset
< chdr_size
) {
260 copy_size
= min(chdr_size
- offset
, nbytes
);
261 memcpy(((char *)(&channel
->chan_hdr
)) + offset
,
265 memcpy_toio(channel
->mapped
+ offset
, local
, nbytes
);
269 EXPORT_SYMBOL_GPL(visorchannel_write
);
272 visorchannel_clear(struct visorchannel
*channel
, ulong offset
, u8 ch
,
276 int bufsize
= PAGE_SIZE
;
280 buf
= (u8
*) __get_free_page(GFP_KERNEL
);
284 memset(buf
, ch
, bufsize
);
287 int thisbytes
= bufsize
;
289 if (nbytes
< thisbytes
)
291 err
= visorchannel_write(channel
, offset
+ written
,
296 written
+= thisbytes
;
302 free_page((unsigned long) buf
);
305 EXPORT_SYMBOL_GPL(visorchannel_clear
);
308 visorchannel_get_header(struct visorchannel
*channel
)
310 return (void __iomem
*)&channel
->chan_hdr
;
312 EXPORT_SYMBOL_GPL(visorchannel_get_header
);
314 /** Return offset of a specific SIGNAL_QUEUE_HEADER from the beginning of a
317 #define SIG_QUEUE_OFFSET(chan_hdr, q) \
318 ((chan_hdr)->ch_space_offset + \
319 ((q) * sizeof(struct signal_queue_header)))
321 /** Return offset of a specific queue entry (data) from the beginning of a
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))
328 /** Write the contents of a specific field within a SIGNAL_QUEUE_HEADER back
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)
339 sig_read_header(struct visorchannel
*channel
, u32 queue
,
340 struct signal_queue_header
*sig_hdr
)
344 if (channel
->chan_hdr
.ch_space_offset
< sizeof(struct channel_header
))
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
));
358 sig_read_data(struct visorchannel
*channel
, u32 queue
,
359 struct signal_queue_header
*sig_hdr
, u32 slot
, void *data
)
362 int signal_data_offset
= SIG_DATA_OFFSET(&channel
->chan_hdr
, queue
,
365 err
= visorchannel_read(channel
, signal_data_offset
,
366 data
, sig_hdr
->signal_size
);
374 sig_write_data(struct visorchannel
*channel
, u32 queue
,
375 struct signal_queue_header
*sig_hdr
, u32 slot
, void *data
)
378 int signal_data_offset
= SIG_DATA_OFFSET(&channel
->chan_hdr
, queue
,
381 err
= visorchannel_write(channel
, signal_data_offset
,
382 data
, sig_hdr
->signal_size
);
390 signalremove_inner(struct visorchannel
*channel
, u32 queue
, void *msg
)
392 struct signal_queue_header sig_hdr
;
394 if (!sig_read_header(channel
, queue
, &sig_hdr
))
396 if (sig_hdr
.head
== sig_hdr
.tail
)
397 return false; /* no signals to remove */
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
))
402 sig_hdr
.num_received
++;
404 /* For each data field in SIGNAL_QUEUE_HEADER that was modified,
405 * update host memory.
407 mb(); /* required for channel synch */
408 if (!SIG_WRITE_FIELD(channel
, queue
, &sig_hdr
, tail
))
410 if (!SIG_WRITE_FIELD(channel
, queue
, &sig_hdr
, num_received
))
416 visorchannel_signalremove(struct visorchannel
*channel
, u32 queue
, void *msg
)
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
);
426 rc
= signalremove_inner(channel
, queue
, msg
);
431 EXPORT_SYMBOL_GPL(visorchannel_signalremove
);
434 visorchannel_signalempty(struct visorchannel
*channel
, u32 queue
)
436 unsigned long flags
= 0;
437 struct signal_queue_header sig_hdr
;
440 if (channel
->needs_lock
)
441 spin_lock_irqsave(&channel
->remove_lock
, flags
);
443 if (!sig_read_header(channel
, queue
, &sig_hdr
))
445 if (sig_hdr
.head
== sig_hdr
.tail
)
447 if (channel
->needs_lock
)
448 spin_unlock_irqrestore(&channel
->remove_lock
, flags
);
452 EXPORT_SYMBOL_GPL(visorchannel_signalempty
);
455 signalinsert_inner(struct visorchannel
*channel
, u32 queue
, void *msg
)
457 struct signal_queue_header sig_hdr
;
459 if (!sig_read_header(channel
, queue
, &sig_hdr
))
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
,
469 &(sig_hdr
.num_overflows
),
470 sizeof(sig_hdr
.num_overflows
));
474 if (!sig_write_data(channel
, queue
, &sig_hdr
, sig_hdr
.head
, msg
))
479 /* For each data field in SIGNAL_QUEUE_HEADER that was modified,
480 * update host memory.
482 mb(); /* required for channel synch */
483 if (!SIG_WRITE_FIELD(channel
, queue
, &sig_hdr
, head
))
485 if (!SIG_WRITE_FIELD(channel
, queue
, &sig_hdr
, num_sent
))
492 visorchannel_signalinsert(struct visorchannel
*channel
, u32 queue
, void *msg
)
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
);
502 rc
= signalinsert_inner(channel
, queue
, msg
);
507 EXPORT_SYMBOL_GPL(visorchannel_signalinsert
);
510 visorchannel_signalqueue_slots_avail(struct visorchannel
*channel
, u32 queue
)
512 struct signal_queue_header sig_hdr
;
513 u32 slots_avail
, slots_used
;
516 if (!sig_read_header(channel
, queue
, &sig_hdr
))
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
;
526 EXPORT_SYMBOL_GPL(visorchannel_signalqueue_slots_avail
);
529 visorchannel_signalqueue_max_slots(struct visorchannel
*channel
, u32 queue
)
531 struct signal_queue_header sig_hdr
;
533 if (!sig_read_header(channel
, queue
, &sig_hdr
))
535 return (int)sig_hdr
.max_signals
;
537 EXPORT_SYMBOL_GPL(visorchannel_signalqueue_max_slots
);
540 sigqueue_debug(struct signal_queue_header
*q
, int which
, struct seq_file
*seq
)
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
);
564 visorchannel_debug(struct visorchannel
*channel
, int num_queues
,
565 struct seq_file
*seq
, u32 off
)
568 ulong nbytes
= 0, nbytes_region
= 0;
569 struct channel_header hdr
;
570 struct channel_header
*phdr
= &hdr
;
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
));
583 "Read of channel header failed with errcode=%d)\n",
586 phdr
= &channel
->chan_hdr
;
587 seq_puts(seq
, "(following data may be stale)\n");
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))
617 for (i
= 0; i
< num_queues
; i
++) {
618 struct signal_queue_header q
;
620 errcode
= visorchannel_read(channel
,
622 phdr
->ch_space_offset
+
627 "failed to read signal queue #%d from channel @0x%-16.16Lx errcode=%d\n",
631 sigqueue_debug(&q
, i
, seq
);
633 seq_printf(seq
, "--- End channel @0x%-16.16Lx for 0x%lx bytes ---\n",
636 EXPORT_SYMBOL_GPL(visorchannel_debug
);