1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2010 - 2015 UNISYS CORPORATION
8 * This provides s-Par channel communication primitives, which are
9 * independent of the mechanism used to access the channel data.
12 #include <linux/uuid.h>
14 #include <linux/slab.h>
15 #include <linux/visorbus.h>
17 #include "visorbus_private.h"
18 #include "controlvmchannel.h"
20 #define VISOR_DRV_NAME "visorchannel"
22 #define VISOR_CONSOLEVIDEO_CHANNEL_GUID \
23 GUID_INIT(0x3cd6e705, 0xd6a2, 0x4aa5, \
24 0xad, 0x5c, 0x7b, 0x8, 0x88, 0x9d, 0xff, 0xe2)
26 static const guid_t visor_video_guid
= VISOR_CONSOLEVIDEO_CHANNEL_GUID
;
33 struct channel_header chan_hdr
;
36 * channel creator knows if more than one thread will be inserting or
40 /* protect head writes in chan_hdr */
41 spinlock_t insert_lock
;
42 /* protect tail writes in chan_hdr */
43 spinlock_t remove_lock
;
48 void visorchannel_destroy(struct visorchannel
*channel
)
53 if (channel
->mapped
) {
54 memunmap(channel
->mapped
);
55 if (channel
->requested
)
56 release_mem_region(channel
->physaddr
, channel
->nbytes
);
61 u64
visorchannel_get_physaddr(struct visorchannel
*channel
)
63 return channel
->physaddr
;
66 ulong
visorchannel_get_nbytes(struct visorchannel
*channel
)
68 return channel
->nbytes
;
71 char *visorchannel_guid_id(const guid_t
*guid
, char *s
)
73 sprintf(s
, "%pUL", guid
);
77 char *visorchannel_id(struct visorchannel
*channel
, char *s
)
79 return visorchannel_guid_id(&channel
->guid
, s
);
82 char *visorchannel_zoneid(struct visorchannel
*channel
, char *s
)
84 return visorchannel_guid_id(&channel
->chan_hdr
.zone_guid
, s
);
87 u64
visorchannel_get_clientpartition(struct visorchannel
*channel
)
89 return channel
->chan_hdr
.partition_handle
;
92 int visorchannel_set_clientpartition(struct visorchannel
*channel
,
95 channel
->chan_hdr
.partition_handle
= partition_handle
;
100 * visorchannel_get_guid() - queries the GUID of the designated channel
101 * @channel: the channel to query
103 * Return: the GUID of the provided channel
105 const guid_t
*visorchannel_get_guid(struct visorchannel
*channel
)
107 return &channel
->guid
;
109 EXPORT_SYMBOL_GPL(visorchannel_get_guid
);
111 int visorchannel_read(struct visorchannel
*channel
, ulong offset
, void *dest
,
114 if (offset
+ nbytes
> channel
->nbytes
)
117 memcpy(dest
, channel
->mapped
+ offset
, nbytes
);
121 int visorchannel_write(struct visorchannel
*channel
, ulong offset
, void *dest
,
124 size_t chdr_size
= sizeof(struct channel_header
);
127 if (offset
+ nbytes
> channel
->nbytes
)
130 if (offset
< chdr_size
) {
131 copy_size
= min(chdr_size
- offset
, nbytes
);
132 memcpy(((char *)(&channel
->chan_hdr
)) + offset
,
135 memcpy(channel
->mapped
+ offset
, dest
, nbytes
);
139 void *visorchannel_get_header(struct visorchannel
*channel
)
141 return &channel
->chan_hdr
;
145 * Return offset of a specific SIGNAL_QUEUE_HEADER from the beginning of a
148 static int sig_queue_offset(struct channel_header
*chan_hdr
, int q
)
150 return ((chan_hdr
)->ch_space_offset
+
151 ((q
) * sizeof(struct signal_queue_header
)));
155 * Return offset of a specific queue entry (data) from the beginning of a
158 static int sig_data_offset(struct channel_header
*chan_hdr
, int q
,
159 struct signal_queue_header
*sig_hdr
, int slot
)
161 return (sig_queue_offset(chan_hdr
, q
) + sig_hdr
->sig_base_offset
+
162 (slot
* sig_hdr
->signal_size
));
166 * Write the contents of a specific field within a SIGNAL_QUEUE_HEADER back into
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))
176 static int sig_read_header(struct visorchannel
*channel
, u32 queue
,
177 struct signal_queue_header
*sig_hdr
)
179 if (channel
->chan_hdr
.ch_space_offset
< sizeof(struct channel_header
))
182 /* Read the appropriate SIGNAL_QUEUE_HEADER into local memory. */
183 return visorchannel_read(channel
,
184 sig_queue_offset(&channel
->chan_hdr
, queue
),
185 sig_hdr
, sizeof(struct signal_queue_header
));
188 static int sig_read_data(struct visorchannel
*channel
, u32 queue
,
189 struct signal_queue_header
*sig_hdr
, u32 slot
,
192 int signal_data_offset
= sig_data_offset(&channel
->chan_hdr
, queue
,
195 return visorchannel_read(channel
, signal_data_offset
,
196 data
, sig_hdr
->signal_size
);
199 static int sig_write_data(struct visorchannel
*channel
, u32 queue
,
200 struct signal_queue_header
*sig_hdr
, u32 slot
,
203 int signal_data_offset
= sig_data_offset(&channel
->chan_hdr
, queue
,
206 return visorchannel_write(channel
, signal_data_offset
,
207 data
, sig_hdr
->signal_size
);
210 static int signalremove_inner(struct visorchannel
*channel
, u32 queue
,
213 struct signal_queue_header sig_hdr
;
216 error
= sig_read_header(channel
, queue
, &sig_hdr
);
219 /* No signals to remove; have caller try again. */
220 if (sig_hdr
.head
== sig_hdr
.tail
)
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
);
226 sig_hdr
.num_received
++;
228 * For each data field in SIGNAL_QUEUE_HEADER that was modified, update
229 * host memory. Required for channel sync.
232 error
= SIG_WRITE_FIELD(channel
, queue
, &sig_hdr
, tail
);
235 error
= SIG_WRITE_FIELD(channel
, queue
, &sig_hdr
, num_received
);
242 * visorchannel_signalremove() - removes a message from the designated
244 * @channel: the channel the message will be removed from
245 * @queue: the queue the message will be removed from
246 * @msg: the message to remove
248 * Return: integer error code indicating the status of the removal
250 int visorchannel_signalremove(struct visorchannel
*channel
, u32 queue
,
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
);
261 rc
= signalremove_inner(channel
, queue
, msg
);
266 EXPORT_SYMBOL_GPL(visorchannel_signalremove
);
268 static bool queue_empty(struct visorchannel
*channel
, u32 queue
)
270 struct signal_queue_header sig_hdr
;
272 if (sig_read_header(channel
, queue
, &sig_hdr
))
274 return (sig_hdr
.head
== sig_hdr
.tail
);
278 * visorchannel_signalempty() - checks if the designated channel/queue contains
280 * @channel: the channel to query
281 * @queue: the queue in the channel to query
283 * Return: boolean indicating whether any messages in the designated
284 * channel/queue are present
286 bool visorchannel_signalempty(struct visorchannel
*channel
, u32 queue
)
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
);
298 EXPORT_SYMBOL_GPL(visorchannel_signalempty
);
300 static int signalinsert_inner(struct visorchannel
*channel
, u32 queue
,
303 struct signal_queue_header sig_hdr
;
306 err
= sig_read_header(channel
, queue
, &sig_hdr
);
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
);
317 err
= sig_write_data(channel
, queue
, &sig_hdr
, sig_hdr
.head
, msg
);
322 * For each data field in SIGNAL_QUEUE_HEADER that was modified, update
323 * host memory. Required for channel sync.
326 err
= SIG_WRITE_FIELD(channel
, queue
, &sig_hdr
, head
);
329 err
= SIG_WRITE_FIELD(channel
, queue
, &sig_hdr
, num_sent
);
336 * visorchannel_create() - creates the struct visorchannel abstraction for a
337 * data area in memory, but does NOT modify this data
339 * @physaddr: physical address of start of channel
340 * @gfp: gfp_t to use when allocating memory for the data struct
341 * @guid: GUID that identifies channel type;
342 * @needs_lock: must specify true if you have multiple threads of execution
343 * that will be calling visorchannel methods of this
344 * visorchannel at the same time
346 * Return: pointer to visorchannel that was created if successful,
349 struct visorchannel
*visorchannel_create(u64 physaddr
, gfp_t gfp
,
350 const guid_t
*guid
, bool needs_lock
)
352 struct visorchannel
*channel
;
354 size_t size
= sizeof(struct channel_header
);
359 channel
= kzalloc(sizeof(*channel
), gfp
);
362 channel
->needs_lock
= needs_lock
;
363 spin_lock_init(&channel
->insert_lock
);
364 spin_lock_init(&channel
->remove_lock
);
366 * Video driver constains the efi framebuffer so it will get a conflict
367 * resource when requesting its full mem region. Since we are only
368 * using the efi framebuffer for video we can ignore this. Remember that
369 * we haven't requested it so we don't try to release later on.
371 channel
->requested
= request_mem_region(physaddr
, size
, VISOR_DRV_NAME
);
372 if (!channel
->requested
&& !guid_equal(guid
, &visor_video_guid
))
373 /* we only care about errors if this is not the video channel */
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
;
380 channel
->physaddr
= physaddr
;
381 channel
->nbytes
= size
;
382 err
= visorchannel_read(channel
, 0, &channel
->chan_hdr
, size
);
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
,
392 if (!channel
->requested
&& !guid_equal(guid
, &visor_video_guid
))
393 /* we only care about errors if this is not the video channel */
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
;
400 channel
->nbytes
= size
;
401 guid_copy(&channel
->guid
, guid
);
405 visorchannel_destroy(channel
);
410 * visorchannel_signalinsert() - inserts a message into the designated
412 * @channel: the channel the message will be added to
413 * @queue: the queue the message will be added to
414 * @msg: the message to insert
416 * Return: integer error code indicating the status of the insertion
418 int visorchannel_signalinsert(struct visorchannel
*channel
, u32 queue
,
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
);
429 rc
= signalinsert_inner(channel
, queue
, msg
);
434 EXPORT_SYMBOL_GPL(visorchannel_signalinsert
);