GNU Linux-libre 4.9.304-gnu1
[releases.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 s-Par channel communication primitives, which are
19  *  independent of the mechanism used to access the channel data.
20  */
21
22 #include <linux/uuid.h>
23 #include <linux/io.h>
24
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 *mapped;
39         bool requested;
40         struct channel_header chan_hdr;
41         uuid_le guid;
42         bool needs_lock;        /* channel creator knows if more than one */
43                                 /* thread will be inserting or removing */
44         spinlock_t insert_lock; /* protect head writes in chan_hdr */
45         spinlock_t remove_lock; /* protect tail writes in chan_hdr */
46
47         struct {
48                 struct signal_queue_header req_queue;
49                 struct signal_queue_header rsp_queue;
50                 struct signal_queue_header event_queue;
51                 struct signal_queue_header ack_queue;
52         } safe_uis_queue;
53         uuid_le type;
54         uuid_le inst;
55 };
56
57 void
58 visorchannel_destroy(struct visorchannel *channel)
59 {
60         if (!channel)
61                 return;
62         if (channel->mapped) {
63                 memunmap(channel->mapped);
64                 if (channel->requested)
65                         release_mem_region(channel->physaddr, channel->nbytes);
66         }
67         kfree(channel);
68 }
69
70 u64
71 visorchannel_get_physaddr(struct visorchannel *channel)
72 {
73         return channel->physaddr;
74 }
75
76 ulong
77 visorchannel_get_nbytes(struct visorchannel *channel)
78 {
79         return channel->nbytes;
80 }
81
82 char *
83 visorchannel_uuid_id(uuid_le *guid, char *s)
84 {
85         sprintf(s, "%pUL", guid);
86         return s;
87 }
88
89 char *
90 visorchannel_id(struct visorchannel *channel, char *s)
91 {
92         return visorchannel_uuid_id(&channel->guid, s);
93 }
94
95 char *
96 visorchannel_zoneid(struct visorchannel *channel, char *s)
97 {
98         return visorchannel_uuid_id(&channel->chan_hdr.zone_uuid, s);
99 }
100
101 u64
102 visorchannel_get_clientpartition(struct visorchannel *channel)
103 {
104         return channel->chan_hdr.partition_handle;
105 }
106
107 int
108 visorchannel_set_clientpartition(struct visorchannel *channel,
109                                  u64 partition_handle)
110 {
111         channel->chan_hdr.partition_handle = partition_handle;
112         return 0;
113 }
114
115 /**
116  * visorchannel_get_uuid() - queries the UUID of the designated channel
117  * @channel: the channel to query
118  *
119  * Return: the UUID of the provided channel
120  */
121 uuid_le
122 visorchannel_get_uuid(struct visorchannel *channel)
123 {
124         return channel->guid;
125 }
126 EXPORT_SYMBOL_GPL(visorchannel_get_uuid);
127
128 int
129 visorchannel_read(struct visorchannel *channel, ulong offset,
130                   void *local, ulong nbytes)
131 {
132         if (offset + nbytes > channel->nbytes)
133                 return -EIO;
134
135         memcpy(local, channel->mapped + offset, nbytes);
136
137         return 0;
138 }
139
140 int
141 visorchannel_write(struct visorchannel *channel, ulong offset,
142                    void *local, ulong nbytes)
143 {
144         size_t chdr_size = sizeof(struct channel_header);
145         size_t copy_size;
146
147         if (offset + nbytes > channel->nbytes)
148                 return -EIO;
149
150         if (offset < chdr_size) {
151                 copy_size = min(chdr_size - offset, nbytes);
152                 memcpy(((char *)(&channel->chan_hdr)) + offset,
153                        local, copy_size);
154         }
155
156         memcpy(channel->mapped + offset, local, nbytes);
157
158         return 0;
159 }
160
161 void __iomem  *
162 visorchannel_get_header(struct visorchannel *channel)
163 {
164         return (void __iomem *)&channel->chan_hdr;
165 }
166
167 /*
168  * Return offset of a specific SIGNAL_QUEUE_HEADER from the beginning of a
169  * channel header
170  */
171 #define SIG_QUEUE_OFFSET(chan_hdr, q) \
172         ((chan_hdr)->ch_space_offset + \
173          ((q) * sizeof(struct signal_queue_header)))
174
175 /*
176  * Return offset of a specific queue entry (data) from the beginning of a
177  * channel header
178  */
179 #define SIG_DATA_OFFSET(chan_hdr, q, sig_hdr, slot) \
180         (SIG_QUEUE_OFFSET(chan_hdr, q) + (sig_hdr)->sig_base_offset + \
181             ((slot) * (sig_hdr)->signal_size))
182
183 /*
184  * Write the contents of a specific field within a SIGNAL_QUEUE_HEADER back
185  * into host memory
186  */
187 #define SIG_WRITE_FIELD(channel, queue, sig_hdr, FIELD)                  \
188         visorchannel_write(channel,                                      \
189                            SIG_QUEUE_OFFSET(&channel->chan_hdr, queue) +\
190                            offsetof(struct signal_queue_header, FIELD), \
191                            &((sig_hdr)->FIELD),                  \
192                            sizeof((sig_hdr)->FIELD))
193
194 static int
195 sig_read_header(struct visorchannel *channel, u32 queue,
196                 struct signal_queue_header *sig_hdr)
197 {
198         if (channel->chan_hdr.ch_space_offset < sizeof(struct channel_header))
199                 return -EINVAL;
200
201         /* Read the appropriate SIGNAL_QUEUE_HEADER into local memory. */
202         return visorchannel_read(channel,
203                                  SIG_QUEUE_OFFSET(&channel->chan_hdr, queue),
204                                  sig_hdr, sizeof(struct signal_queue_header));
205 }
206
207 static inline int
208 sig_read_data(struct visorchannel *channel, u32 queue,
209               struct signal_queue_header *sig_hdr, u32 slot, void *data)
210 {
211         int signal_data_offset = SIG_DATA_OFFSET(&channel->chan_hdr, queue,
212                                                  sig_hdr, slot);
213
214         return visorchannel_read(channel, signal_data_offset,
215                                  data, sig_hdr->signal_size);
216 }
217
218 static inline int
219 sig_write_data(struct visorchannel *channel, u32 queue,
220                struct signal_queue_header *sig_hdr, u32 slot, void *data)
221 {
222         int signal_data_offset = SIG_DATA_OFFSET(&channel->chan_hdr, queue,
223                                                  sig_hdr, slot);
224
225         return visorchannel_write(channel, signal_data_offset,
226                                   data, sig_hdr->signal_size);
227 }
228
229 static int
230 signalremove_inner(struct visorchannel *channel, u32 queue, void *msg)
231 {
232         struct signal_queue_header sig_hdr;
233         int error;
234
235         error = sig_read_header(channel, queue, &sig_hdr);
236         if (error)
237                 return error;
238
239         if (sig_hdr.head == sig_hdr.tail)
240                 return -EIO;    /* no signals to remove */
241
242         sig_hdr.tail = (sig_hdr.tail + 1) % sig_hdr.max_slots;
243
244         error = sig_read_data(channel, queue, &sig_hdr, sig_hdr.tail, msg);
245         if (error)
246                 return error;
247
248         sig_hdr.num_received++;
249
250         /*
251          * For each data field in SIGNAL_QUEUE_HEADER that was modified,
252          * update host memory.
253          */
254         mb(); /* required for channel synch */
255
256         error = SIG_WRITE_FIELD(channel, queue, &sig_hdr, tail);
257         if (error)
258                 return error;
259         error = SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_received);
260         if (error)
261                 return error;
262
263         return 0;
264 }
265
266 /**
267  * visorchannel_signalremove() - removes a message from the designated
268  *                               channel/queue
269  * @channel: the channel the message will be removed from
270  * @queue:   the queue the message will be removed from
271  * @msg:     the message to remove
272  *
273  * Return: integer error code indicating the status of the removal
274  */
275 int
276 visorchannel_signalremove(struct visorchannel *channel, u32 queue, void *msg)
277 {
278         int rc;
279         unsigned long flags;
280
281         if (channel->needs_lock) {
282                 spin_lock_irqsave(&channel->remove_lock, flags);
283                 rc = signalremove_inner(channel, queue, msg);
284                 spin_unlock_irqrestore(&channel->remove_lock, flags);
285         } else {
286                 rc = signalremove_inner(channel, queue, msg);
287         }
288
289         return rc;
290 }
291 EXPORT_SYMBOL_GPL(visorchannel_signalremove);
292
293 /**
294  * visorchannel_signalempty() - checks if the designated channel/queue
295  *                              contains any messages
296  * @channel: the channel to query
297  * @queue:   the queue in the channel to query
298  *
299  * Return: boolean indicating whether any messages in the designated
300  *         channel/queue are present
301  */
302 bool
303 visorchannel_signalempty(struct visorchannel *channel, u32 queue)
304 {
305         unsigned long flags = 0;
306         struct signal_queue_header sig_hdr;
307         bool rc = false;
308
309         if (channel->needs_lock)
310                 spin_lock_irqsave(&channel->remove_lock, flags);
311
312         if (sig_read_header(channel, queue, &sig_hdr))
313                 rc = true;
314         if (sig_hdr.head == sig_hdr.tail)
315                 rc = true;
316         if (channel->needs_lock)
317                 spin_unlock_irqrestore(&channel->remove_lock, flags);
318
319         return rc;
320 }
321 EXPORT_SYMBOL_GPL(visorchannel_signalempty);
322
323 static int
324 signalinsert_inner(struct visorchannel *channel, u32 queue, void *msg)
325 {
326         struct signal_queue_header sig_hdr;
327         int error;
328
329         error = sig_read_header(channel, queue, &sig_hdr);
330         if (error)
331                 return error;
332
333         sig_hdr.head = (sig_hdr.head + 1) % sig_hdr.max_slots;
334         if (sig_hdr.head == sig_hdr.tail) {
335                 sig_hdr.num_overflows++;
336                 visorchannel_write(channel,
337                                    SIG_QUEUE_OFFSET(&channel->chan_hdr, queue) +
338                                    offsetof(struct signal_queue_header,
339                                             num_overflows),
340                                    &sig_hdr.num_overflows,
341                                    sizeof(sig_hdr.num_overflows));
342                 return -EIO;
343         }
344
345         error = sig_write_data(channel, queue, &sig_hdr, sig_hdr.head, msg);
346         if (error)
347                 return error;
348
349         sig_hdr.num_sent++;
350
351         /*
352          * For each data field in SIGNAL_QUEUE_HEADER that was modified,
353          * update host memory.
354          */
355         mb(); /* required for channel synch */
356
357         error = SIG_WRITE_FIELD(channel, queue, &sig_hdr, head);
358         if (error)
359                 return error;
360         error = SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_sent);
361         if (error)
362                 return error;
363
364         return 0;
365 }
366
367 /**
368  * visorchannel_create_guts() - creates the struct visorchannel abstraction
369  *                              for a data area in memory, but does NOT modify
370  *                              this data area
371  * @physaddr:      physical address of start of channel
372  * @channel_bytes: size of the channel in bytes; this may 0 if the channel has
373  *                 already been initialized in memory (which is true for all
374  *                 channels provided to guest environments by the s-Par
375  *                 back-end), in which case the actual channel size will be
376  *                 read from the channel header in memory
377  * @gfp:           gfp_t to use when allocating memory for the data struct
378  * @guid:          uuid that identifies channel type; this may 0 if the channel
379  *                 has already been initialized in memory (which is true for all
380  *                 channels provided to guest environments by the s-Par
381  *                 back-end), in which case the actual channel guid will be
382  *                 read from the channel header in memory
383  * @needs_lock:    must specify true if you have multiple threads of execution
384  *                 that will be calling visorchannel methods of this
385  *                 visorchannel at the same time
386  *
387  * Return: pointer to visorchannel that was created if successful,
388  *         otherwise NULL
389  */
390 static struct visorchannel *
391 visorchannel_create_guts(u64 physaddr, unsigned long channel_bytes,
392                          gfp_t gfp, uuid_le guid, bool needs_lock)
393 {
394         struct visorchannel *channel;
395         int err;
396         size_t size = sizeof(struct channel_header);
397
398         if (physaddr == 0)
399                 return NULL;
400
401         channel = kzalloc(sizeof(*channel), gfp);
402         if (!channel)
403                 return NULL;
404
405         channel->needs_lock = needs_lock;
406         spin_lock_init(&channel->insert_lock);
407         spin_lock_init(&channel->remove_lock);
408
409         /*
410          * Video driver constains the efi framebuffer so it will get a
411          * conflict resource when requesting its full mem region. Since
412          * we are only using the efi framebuffer for video we can ignore
413          * this. Remember that we haven't requested it so we don't try to
414          * release later on.
415          */
416         channel->requested = request_mem_region(physaddr, size, MYDRVNAME);
417         if (!channel->requested) {
418                 if (uuid_le_cmp(guid, spar_video_guid)) {
419                         /* Not the video channel we care about this */
420                         goto err_destroy_channel;
421                 }
422         }
423
424         channel->mapped = memremap(physaddr, size, MEMREMAP_WB);
425         if (!channel->mapped) {
426                 release_mem_region(physaddr, size);
427                 goto err_destroy_channel;
428         }
429
430         channel->physaddr = physaddr;
431         channel->nbytes = size;
432
433         err = visorchannel_read(channel, 0, &channel->chan_hdr,
434                                 sizeof(struct channel_header));
435         if (err)
436                 goto err_destroy_channel;
437
438         /* we had better be a CLIENT of this channel */
439         if (channel_bytes == 0)
440                 channel_bytes = (ulong)channel->chan_hdr.size;
441         if (uuid_le_cmp(guid, NULL_UUID_LE) == 0)
442                 guid = channel->chan_hdr.chtype;
443
444         memunmap(channel->mapped);
445         if (channel->requested)
446                 release_mem_region(channel->physaddr, channel->nbytes);
447         channel->mapped = NULL;
448         channel->requested = request_mem_region(channel->physaddr,
449                                                 channel_bytes, MYDRVNAME);
450         if (!channel->requested) {
451                 if (uuid_le_cmp(guid, spar_video_guid)) {
452                         /* Different we care about this */
453                         goto err_destroy_channel;
454                 }
455         }
456
457         channel->mapped = memremap(channel->physaddr, channel_bytes,
458                         MEMREMAP_WB);
459         if (!channel->mapped) {
460                 release_mem_region(channel->physaddr, channel_bytes);
461                 goto err_destroy_channel;
462         }
463
464         channel->nbytes = channel_bytes;
465         channel->guid = guid;
466         return channel;
467
468 err_destroy_channel:
469         visorchannel_destroy(channel);
470         return NULL;
471 }
472
473 struct visorchannel *
474 visorchannel_create(u64 physaddr, unsigned long channel_bytes,
475                     gfp_t gfp, uuid_le guid)
476 {
477         return visorchannel_create_guts(physaddr, channel_bytes, gfp, guid,
478                                         false);
479 }
480
481 struct visorchannel *
482 visorchannel_create_with_lock(u64 physaddr, unsigned long channel_bytes,
483                               gfp_t gfp, uuid_le guid)
484 {
485         return visorchannel_create_guts(physaddr, channel_bytes, gfp, guid,
486                                         true);
487 }
488
489 /**
490  * visorchannel_signalinsert() - inserts a message into the designated
491  *                               channel/queue
492  * @channel: the channel the message will be added to
493  * @queue:   the queue the message will be added to
494  * @msg:     the message to insert
495  *
496  * Return: integer error code indicating the status of the insertion
497  */
498 int
499 visorchannel_signalinsert(struct visorchannel *channel, u32 queue, void *msg)
500 {
501         int rc;
502         unsigned long flags;
503
504         if (channel->needs_lock) {
505                 spin_lock_irqsave(&channel->insert_lock, flags);
506                 rc = signalinsert_inner(channel, queue, msg);
507                 spin_unlock_irqrestore(&channel->insert_lock, flags);
508         } else {
509                 rc = signalinsert_inner(channel, queue, msg);
510         }
511
512         return rc;
513 }
514 EXPORT_SYMBOL_GPL(visorchannel_signalinsert);