2 * Copyright (C) 2010 - 2015 UNISYS CORPORATION
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
12 * NON INFRINGEMENT. See the GNU General Public License for more
17 * This provides s-Par channel communication primitives, which are
18 * independent of the mechanism used to access the channel data.
21 #include <linux/uuid.h>
25 #include "visorbus_private.h"
26 #include "controlvmchannel.h"
28 #define VISOR_DRV_NAME "visorchannel"
30 #define VISOR_CONSOLEVIDEO_CHANNEL_GUID \
31 GUID_INIT(0x3cd6e705, 0xd6a2, 0x4aa5, \
32 0xad, 0x5c, 0x7b, 0x8, 0x88, 0x9d, 0xff, 0xe2)
34 static const guid_t visor_video_guid = VISOR_CONSOLEVIDEO_CHANNEL_GUID;
41 struct channel_header chan_hdr;
44 * channel creator knows if more than one
45 * thread will be inserting or removing
48 /* protect head writes in chan_hdr */
49 spinlock_t insert_lock;
50 /* protect tail writes in chan_hdr */
51 spinlock_t remove_lock;
56 void visorchannel_destroy(struct visorchannel *channel)
60 if (channel->mapped) {
61 memunmap(channel->mapped);
62 if (channel->requested)
63 release_mem_region(channel->physaddr, channel->nbytes);
68 u64 visorchannel_get_physaddr(struct visorchannel *channel)
70 return channel->physaddr;
73 ulong visorchannel_get_nbytes(struct visorchannel *channel)
75 return channel->nbytes;
78 char *visorchannel_guid_id(const guid_t *guid, char *s)
80 sprintf(s, "%pUL", guid);
84 char *visorchannel_id(struct visorchannel *channel, char *s)
86 return visorchannel_guid_id(&channel->guid, s);
89 char *visorchannel_zoneid(struct visorchannel *channel, char *s)
91 return visorchannel_guid_id(&channel->chan_hdr.zone_guid, s);
94 u64 visorchannel_get_clientpartition(struct visorchannel *channel)
96 return channel->chan_hdr.partition_handle;
99 int visorchannel_set_clientpartition(struct visorchannel *channel,
100 u64 partition_handle)
102 channel->chan_hdr.partition_handle = partition_handle;
107 * visorchannel_get_guid() - queries the GUID of the designated channel
108 * @channel: the channel to query
110 * Return: the GUID of the provided channel
112 const guid_t *visorchannel_get_guid(struct visorchannel *channel)
114 return &channel->guid;
116 EXPORT_SYMBOL_GPL(visorchannel_get_guid);
118 int visorchannel_read(struct visorchannel *channel, ulong offset, void *dest,
121 if (offset + nbytes > channel->nbytes)
124 memcpy(dest, channel->mapped + offset, nbytes);
129 int visorchannel_write(struct visorchannel *channel, ulong offset, void *dest,
132 size_t chdr_size = sizeof(struct channel_header);
135 if (offset + nbytes > channel->nbytes)
138 if (offset < chdr_size) {
139 copy_size = min(chdr_size - offset, nbytes);
140 memcpy(((char *)(&channel->chan_hdr)) + offset,
144 memcpy(channel->mapped + offset, dest, nbytes);
149 void *visorchannel_get_header(struct visorchannel *channel)
151 return &channel->chan_hdr;
155 * Return offset of a specific SIGNAL_QUEUE_HEADER from the beginning of a
158 static int sig_queue_offset(struct channel_header *chan_hdr, int q)
160 return ((chan_hdr)->ch_space_offset +
161 ((q) * sizeof(struct signal_queue_header)));
165 * Return offset of a specific queue entry (data) from the beginning of a
168 static int sig_data_offset(struct channel_header *chan_hdr, int q,
169 struct signal_queue_header *sig_hdr, int slot)
171 return (sig_queue_offset(chan_hdr, q) + sig_hdr->sig_base_offset +
172 (slot * sig_hdr->signal_size));
176 * Write the contents of a specific field within a SIGNAL_QUEUE_HEADER back
179 #define SIG_WRITE_FIELD(channel, queue, sig_hdr, FIELD) \
180 visorchannel_write(channel, \
181 sig_queue_offset(&channel->chan_hdr, queue) + \
182 offsetof(struct signal_queue_header, FIELD), \
183 &((sig_hdr)->FIELD), \
184 sizeof((sig_hdr)->FIELD))
186 static int sig_read_header(struct visorchannel *channel, u32 queue,
187 struct signal_queue_header *sig_hdr)
189 if (channel->chan_hdr.ch_space_offset < sizeof(struct channel_header))
192 /* Read the appropriate SIGNAL_QUEUE_HEADER into local memory. */
193 return visorchannel_read(channel,
194 sig_queue_offset(&channel->chan_hdr, queue),
195 sig_hdr, sizeof(struct signal_queue_header));
198 static int sig_read_data(struct visorchannel *channel, u32 queue,
199 struct signal_queue_header *sig_hdr, u32 slot,
202 int signal_data_offset = sig_data_offset(&channel->chan_hdr, queue,
205 return visorchannel_read(channel, signal_data_offset,
206 data, sig_hdr->signal_size);
209 static int sig_write_data(struct visorchannel *channel, u32 queue,
210 struct signal_queue_header *sig_hdr, u32 slot,
213 int signal_data_offset = sig_data_offset(&channel->chan_hdr, queue,
216 return visorchannel_write(channel, signal_data_offset,
217 data, sig_hdr->signal_size);
220 static int signalremove_inner(struct visorchannel *channel, u32 queue,
223 struct signal_queue_header sig_hdr;
226 error = sig_read_header(channel, queue, &sig_hdr);
230 /* No signals to remove; have caller try again. */
231 if (sig_hdr.head == sig_hdr.tail)
234 sig_hdr.tail = (sig_hdr.tail + 1) % sig_hdr.max_slots;
236 error = sig_read_data(channel, queue, &sig_hdr, sig_hdr.tail, msg);
240 sig_hdr.num_received++;
243 * For each data field in SIGNAL_QUEUE_HEADER that was modified,
244 * update host memory. Required for channel sync.
248 error = SIG_WRITE_FIELD(channel, queue, &sig_hdr, tail);
251 error = SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_received);
259 * visorchannel_signalremove() - removes a message from the designated
261 * @channel: the channel the message will be removed from
262 * @queue: the queue the message will be removed from
263 * @msg: the message to remove
265 * Return: integer error code indicating the status of the removal
267 int visorchannel_signalremove(struct visorchannel *channel, u32 queue,
273 if (channel->needs_lock) {
274 spin_lock_irqsave(&channel->remove_lock, flags);
275 rc = signalremove_inner(channel, queue, msg);
276 spin_unlock_irqrestore(&channel->remove_lock, flags);
278 rc = signalremove_inner(channel, queue, msg);
283 EXPORT_SYMBOL_GPL(visorchannel_signalremove);
285 static bool queue_empty(struct visorchannel *channel, u32 queue)
287 struct signal_queue_header sig_hdr;
289 if (sig_read_header(channel, queue, &sig_hdr))
292 return (sig_hdr.head == sig_hdr.tail);
296 * visorchannel_signalempty() - checks if the designated channel/queue
297 * contains any messages
298 * @channel: the channel to query
299 * @queue: the queue in the channel to query
301 * Return: boolean indicating whether any messages in the designated
302 * channel/queue are present
304 bool visorchannel_signalempty(struct visorchannel *channel, u32 queue)
309 if (!channel->needs_lock)
310 return queue_empty(channel, queue);
312 spin_lock_irqsave(&channel->remove_lock, flags);
313 rc = queue_empty(channel, queue);
314 spin_unlock_irqrestore(&channel->remove_lock, flags);
318 EXPORT_SYMBOL_GPL(visorchannel_signalempty);
320 static int signalinsert_inner(struct visorchannel *channel, u32 queue,
323 struct signal_queue_header sig_hdr;
326 err = sig_read_header(channel, queue, &sig_hdr);
330 sig_hdr.head = (sig_hdr.head + 1) % sig_hdr.max_slots;
331 if (sig_hdr.head == sig_hdr.tail) {
332 sig_hdr.num_overflows++;
333 err = SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_overflows);
339 err = sig_write_data(channel, queue, &sig_hdr, sig_hdr.head, msg);
346 * For each data field in SIGNAL_QUEUE_HEADER that was modified,
347 * update host memory. Required for channel sync.
351 err = SIG_WRITE_FIELD(channel, queue, &sig_hdr, head);
354 err = SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_sent);
362 * visorchannel_create_guts() - creates the struct visorchannel abstraction
363 * for a data area in memory, but does NOT modify
365 * @physaddr: physical address of start of channel
366 * @gfp: gfp_t to use when allocating memory for the data struct
367 * @guid: GUID that identifies channel type;
368 * @needs_lock: must specify true if you have multiple threads of execution
369 * that will be calling visorchannel methods of this
370 * visorchannel at the same time
372 * Return: pointer to visorchannel that was created if successful,
375 static struct visorchannel *visorchannel_create_guts(u64 physaddr, gfp_t gfp,
379 struct visorchannel *channel;
381 size_t size = sizeof(struct channel_header);
386 channel = kzalloc(sizeof(*channel), gfp);
390 channel->needs_lock = needs_lock;
391 spin_lock_init(&channel->insert_lock);
392 spin_lock_init(&channel->remove_lock);
395 * Video driver constains the efi framebuffer so it will get a
396 * conflict resource when requesting its full mem region. Since
397 * we are only using the efi framebuffer for video we can ignore
398 * this. Remember that we haven't requested it so we don't try to
401 channel->requested = request_mem_region(physaddr, size, VISOR_DRV_NAME);
402 if (!channel->requested && !guid_equal(guid, &visor_video_guid))
403 /* we only care about errors if this is not the video channel */
404 goto err_destroy_channel;
406 channel->mapped = memremap(physaddr, size, MEMREMAP_WB);
407 if (!channel->mapped) {
408 release_mem_region(physaddr, size);
409 goto err_destroy_channel;
412 channel->physaddr = physaddr;
413 channel->nbytes = size;
415 err = visorchannel_read(channel, 0, &channel->chan_hdr, size);
417 goto err_destroy_channel;
418 size = (ulong)channel->chan_hdr.size;
420 memunmap(channel->mapped);
421 if (channel->requested)
422 release_mem_region(channel->physaddr, channel->nbytes);
423 channel->mapped = NULL;
424 channel->requested = request_mem_region(channel->physaddr, size,
426 if (!channel->requested && !guid_equal(guid, &visor_video_guid))
427 /* we only care about errors if this is not the video channel */
428 goto err_destroy_channel;
430 channel->mapped = memremap(channel->physaddr, size, MEMREMAP_WB);
431 if (!channel->mapped) {
432 release_mem_region(channel->physaddr, size);
433 goto err_destroy_channel;
436 channel->nbytes = size;
437 guid_copy(&channel->guid, guid);
441 visorchannel_destroy(channel);
445 struct visorchannel *visorchannel_create(u64 physaddr, gfp_t gfp,
448 return visorchannel_create_guts(physaddr, gfp, guid, false);
451 struct visorchannel *visorchannel_create_with_lock(u64 physaddr, gfp_t gfp,
454 return visorchannel_create_guts(physaddr, gfp, guid, true);
458 * visorchannel_signalinsert() - inserts a message into the designated
460 * @channel: the channel the message will be added to
461 * @queue: the queue the message will be added to
462 * @msg: the message to insert
464 * Return: integer error code indicating the status of the insertion
466 int visorchannel_signalinsert(struct visorchannel *channel, u32 queue,
472 if (channel->needs_lock) {
473 spin_lock_irqsave(&channel->insert_lock, flags);
474 rc = signalinsert_inner(channel, queue, msg);
475 spin_unlock_irqrestore(&channel->insert_lock, flags);
477 rc = signalinsert_inner(channel, queue, msg);
482 EXPORT_SYMBOL_GPL(visorchannel_signalinsert);