GNU Linux-libre 4.14.290-gnu1
[releases.git] / drivers / staging / unisys / visorbus / visorchannel.c
1 /*
2  * Copyright (C) 2010 - 2015 UNISYS CORPORATION
3  * All rights reserved.
4  *
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.
8  *
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
13  * details.
14  */
15
16 /*
17  *  This provides s-Par channel communication primitives, which are
18  *  independent of the mechanism used to access the channel data.
19  */
20
21 #include <linux/uuid.h>
22 #include <linux/io.h>
23
24 #include "visorbus.h"
25 #include "visorbus_private.h"
26 #include "controlvmchannel.h"
27
28 #define VISOR_DRV_NAME "visorchannel"
29
30 #define VISOR_CONSOLEVIDEO_CHANNEL_GUID \
31         GUID_INIT(0x3cd6e705, 0xd6a2, 0x4aa5, \
32                   0xad, 0x5c, 0x7b, 0x8, 0x88, 0x9d, 0xff, 0xe2)
33
34 static const guid_t visor_video_guid = VISOR_CONSOLEVIDEO_CHANNEL_GUID;
35
36 struct visorchannel {
37         u64 physaddr;
38         ulong nbytes;
39         void *mapped;
40         bool requested;
41         struct channel_header chan_hdr;
42         guid_t guid;
43         /*
44          * channel creator knows if more than one
45          * thread will be inserting or removing
46          */
47         bool needs_lock;
48         /* protect head writes in chan_hdr */
49         spinlock_t insert_lock;
50         /* protect tail writes in chan_hdr */
51         spinlock_t remove_lock;
52         guid_t type;
53         guid_t inst;
54 };
55
56 void visorchannel_destroy(struct visorchannel *channel)
57 {
58         if (!channel)
59                 return;
60         if (channel->mapped) {
61                 memunmap(channel->mapped);
62                 if (channel->requested)
63                         release_mem_region(channel->physaddr, channel->nbytes);
64         }
65         kfree(channel);
66 }
67
68 u64 visorchannel_get_physaddr(struct visorchannel *channel)
69 {
70         return channel->physaddr;
71 }
72
73 ulong visorchannel_get_nbytes(struct visorchannel *channel)
74 {
75         return channel->nbytes;
76 }
77
78 char *visorchannel_guid_id(const guid_t *guid, char *s)
79 {
80         sprintf(s, "%pUL", guid);
81         return s;
82 }
83
84 char *visorchannel_id(struct visorchannel *channel, char *s)
85 {
86         return visorchannel_guid_id(&channel->guid, s);
87 }
88
89 char *visorchannel_zoneid(struct visorchannel *channel, char *s)
90 {
91         return visorchannel_guid_id(&channel->chan_hdr.zone_guid, s);
92 }
93
94 u64 visorchannel_get_clientpartition(struct visorchannel *channel)
95 {
96         return channel->chan_hdr.partition_handle;
97 }
98
99 int visorchannel_set_clientpartition(struct visorchannel *channel,
100                                      u64 partition_handle)
101 {
102         channel->chan_hdr.partition_handle = partition_handle;
103         return 0;
104 }
105
106 /**
107  * visorchannel_get_guid() - queries the GUID of the designated channel
108  * @channel: the channel to query
109  *
110  * Return: the GUID of the provided channel
111  */
112 const guid_t *visorchannel_get_guid(struct visorchannel *channel)
113 {
114         return &channel->guid;
115 }
116 EXPORT_SYMBOL_GPL(visorchannel_get_guid);
117
118 int visorchannel_read(struct visorchannel *channel, ulong offset, void *dest,
119                       ulong nbytes)
120 {
121         if (offset + nbytes > channel->nbytes)
122                 return -EIO;
123
124         memcpy(dest, channel->mapped + offset, nbytes);
125
126         return 0;
127 }
128
129 int visorchannel_write(struct visorchannel *channel, ulong offset, void *dest,
130                        ulong nbytes)
131 {
132         size_t chdr_size = sizeof(struct channel_header);
133         size_t copy_size;
134
135         if (offset + nbytes > channel->nbytes)
136                 return -EIO;
137
138         if (offset < chdr_size) {
139                 copy_size = min(chdr_size - offset, nbytes);
140                 memcpy(((char *)(&channel->chan_hdr)) + offset,
141                        dest, copy_size);
142         }
143
144         memcpy(channel->mapped + offset, dest, nbytes);
145
146         return 0;
147 }
148
149 void *visorchannel_get_header(struct visorchannel *channel)
150 {
151         return &channel->chan_hdr;
152 }
153
154 /*
155  * Return offset of a specific SIGNAL_QUEUE_HEADER from the beginning of a
156  * channel header
157  */
158 static int sig_queue_offset(struct channel_header *chan_hdr, int q)
159 {
160         return ((chan_hdr)->ch_space_offset +
161                ((q) * sizeof(struct signal_queue_header)));
162 }
163
164 /*
165  * Return offset of a specific queue entry (data) from the beginning of a
166  * channel header
167  */
168 static int sig_data_offset(struct channel_header *chan_hdr, int q,
169                            struct signal_queue_header *sig_hdr, int slot)
170 {
171         return (sig_queue_offset(chan_hdr, q) + sig_hdr->sig_base_offset +
172                (slot * sig_hdr->signal_size));
173 }
174
175 /*
176  * Write the contents of a specific field within a SIGNAL_QUEUE_HEADER back
177  * into host memory
178  */
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))
185
186 static int sig_read_header(struct visorchannel *channel, u32 queue,
187                            struct signal_queue_header *sig_hdr)
188 {
189         if (channel->chan_hdr.ch_space_offset < sizeof(struct channel_header))
190                 return -EINVAL;
191
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));
196 }
197
198 static int sig_read_data(struct visorchannel *channel, u32 queue,
199                          struct signal_queue_header *sig_hdr, u32 slot,
200                          void *data)
201 {
202         int signal_data_offset = sig_data_offset(&channel->chan_hdr, queue,
203                                                  sig_hdr, slot);
204
205         return visorchannel_read(channel, signal_data_offset,
206                                  data, sig_hdr->signal_size);
207 }
208
209 static int sig_write_data(struct visorchannel *channel, u32 queue,
210                           struct signal_queue_header *sig_hdr, u32 slot,
211                           void *data)
212 {
213         int signal_data_offset = sig_data_offset(&channel->chan_hdr, queue,
214                                                  sig_hdr, slot);
215
216         return visorchannel_write(channel, signal_data_offset,
217                                   data, sig_hdr->signal_size);
218 }
219
220 static int signalremove_inner(struct visorchannel *channel, u32 queue,
221                               void *msg)
222 {
223         struct signal_queue_header sig_hdr;
224         int error;
225
226         error = sig_read_header(channel, queue, &sig_hdr);
227         if (error)
228                 return error;
229
230         /* No signals to remove; have caller try again. */
231         if (sig_hdr.head == sig_hdr.tail)
232                 return -EAGAIN;
233
234         sig_hdr.tail = (sig_hdr.tail + 1) % sig_hdr.max_slots;
235
236         error = sig_read_data(channel, queue, &sig_hdr, sig_hdr.tail, msg);
237         if (error)
238                 return error;
239
240         sig_hdr.num_received++;
241
242         /*
243          * For each data field in SIGNAL_QUEUE_HEADER that was modified,
244          * update host memory. Required for channel sync.
245          */
246         mb();
247
248         error = SIG_WRITE_FIELD(channel, queue, &sig_hdr, tail);
249         if (error)
250                 return error;
251         error = SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_received);
252         if (error)
253                 return error;
254
255         return 0;
256 }
257
258 /**
259  * visorchannel_signalremove() - removes a message from the designated
260  *                               channel/queue
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
264  *
265  * Return: integer error code indicating the status of the removal
266  */
267 int visorchannel_signalremove(struct visorchannel *channel, u32 queue,
268                               void *msg)
269 {
270         int rc;
271         unsigned long flags;
272
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);
277         } else {
278                 rc = signalremove_inner(channel, queue, msg);
279         }
280
281         return rc;
282 }
283 EXPORT_SYMBOL_GPL(visorchannel_signalremove);
284
285 static bool queue_empty(struct visorchannel *channel, u32 queue)
286 {
287         struct signal_queue_header sig_hdr;
288
289         if (sig_read_header(channel, queue, &sig_hdr))
290                 return true;
291
292         return (sig_hdr.head == sig_hdr.tail);
293 }
294
295 /**
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
300  *
301  * Return: boolean indicating whether any messages in the designated
302  *         channel/queue are present
303  */
304 bool visorchannel_signalempty(struct visorchannel *channel, u32 queue)
305 {
306         bool rc;
307         unsigned long flags;
308
309         if (!channel->needs_lock)
310                 return queue_empty(channel, queue);
311
312         spin_lock_irqsave(&channel->remove_lock, flags);
313         rc = queue_empty(channel, queue);
314         spin_unlock_irqrestore(&channel->remove_lock, flags);
315
316         return rc;
317 }
318 EXPORT_SYMBOL_GPL(visorchannel_signalempty);
319
320 static int signalinsert_inner(struct visorchannel *channel, u32 queue,
321                               void *msg)
322 {
323         struct signal_queue_header sig_hdr;
324         int err;
325
326         err = sig_read_header(channel, queue, &sig_hdr);
327         if (err)
328                 return err;
329
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);
334                 if (err)
335                         return err;
336                 return -EIO;
337         }
338
339         err = sig_write_data(channel, queue, &sig_hdr, sig_hdr.head, msg);
340         if (err)
341                 return err;
342
343         sig_hdr.num_sent++;
344
345         /*
346          * For each data field in SIGNAL_QUEUE_HEADER that was modified,
347          * update host memory. Required for channel sync.
348          */
349         mb();
350
351         err = SIG_WRITE_FIELD(channel, queue, &sig_hdr, head);
352         if (err)
353                 return err;
354         err = SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_sent);
355         if (err)
356                 return err;
357
358         return 0;
359 }
360
361 /*
362  * visorchannel_create_guts() - creates the struct visorchannel abstraction
363  *                              for a data area in memory, but does NOT modify
364  *                              this data area
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
371  *
372  * Return: pointer to visorchannel that was created if successful,
373  *         otherwise NULL
374  */
375 static struct visorchannel *visorchannel_create_guts(u64 physaddr, gfp_t gfp,
376                                                      const guid_t *guid,
377                                                      bool needs_lock)
378 {
379         struct visorchannel *channel;
380         int err;
381         size_t size = sizeof(struct channel_header);
382
383         if (physaddr == 0)
384                 return NULL;
385
386         channel = kzalloc(sizeof(*channel), gfp);
387         if (!channel)
388                 return NULL;
389
390         channel->needs_lock = needs_lock;
391         spin_lock_init(&channel->insert_lock);
392         spin_lock_init(&channel->remove_lock);
393
394         /*
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
399          * release later on.
400          */
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;
405
406         channel->mapped = memremap(physaddr, size, MEMREMAP_WB);
407         if (!channel->mapped) {
408                 release_mem_region(physaddr, size);
409                 goto err_destroy_channel;
410         }
411
412         channel->physaddr = physaddr;
413         channel->nbytes = size;
414
415         err = visorchannel_read(channel, 0, &channel->chan_hdr, size);
416         if (err)
417                 goto err_destroy_channel;
418         size = (ulong)channel->chan_hdr.size;
419
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,
425                                                 VISOR_DRV_NAME);
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;
429
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;
434         }
435
436         channel->nbytes = size;
437         guid_copy(&channel->guid, guid);
438         return channel;
439
440 err_destroy_channel:
441         visorchannel_destroy(channel);
442         return NULL;
443 }
444
445 struct visorchannel *visorchannel_create(u64 physaddr, gfp_t gfp,
446                                          const guid_t *guid)
447 {
448         return visorchannel_create_guts(physaddr, gfp, guid, false);
449 }
450
451 struct visorchannel *visorchannel_create_with_lock(u64 physaddr, gfp_t gfp,
452                                                    const guid_t *guid)
453 {
454         return visorchannel_create_guts(physaddr, gfp, guid, true);
455 }
456
457 /**
458  * visorchannel_signalinsert() - inserts a message into the designated
459  *                               channel/queue
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
463  *
464  * Return: integer error code indicating the status of the insertion
465  */
466 int visorchannel_signalinsert(struct visorchannel *channel, u32 queue,
467                               void *msg)
468 {
469         int rc;
470         unsigned long flags;
471
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);
476         } else {
477                 rc = signalinsert_inner(channel, queue, msg);
478         }
479
480         return rc;
481 }
482 EXPORT_SYMBOL_GPL(visorchannel_signalinsert);