staging: unisys: visorchannel: visorchannel_create_overlap() is never used
[linux-drm-fsl-dcu.git] / drivers / staging / unisys / visorbus / visorchannel.c
1 /* visorchannel_funcs.c
2  *
3  * Copyright (C) 2010 - 2013 UNISYS CORPORATION
4  * All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or (at
9  * your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
14  * NON INFRINGEMENT.  See the GNU General Public License for more
15  * details.
16  */
17
18 /*
19  *  This provides Supervisor channel communication primitives, which are
20  *  independent of the mechanism used to access the channel data.  All channel
21  *  data is accessed using the memregion abstraction.  (memregion has both
22  *  a CM2 implementation and a direct memory implementation.)
23  */
24
25 #include "memregion.h"
26 #include "version.h"
27 #include "visorbus.h"
28 #include <linux/uuid.h>
29
30 #define MYDRVNAME "visorchannel"
31
32 struct visorchannel {
33         struct memregion *memregion;    /* from visor_memregion_create() */
34         struct channel_header chan_hdr;
35         uuid_le guid;
36         ulong size;
37         BOOL needs_lock;        /* channel creator knows if more than one
38                                  * thread will be inserting or removing */
39         spinlock_t insert_lock; /* protect head writes in chan_hdr */
40         spinlock_t remove_lock; /* protect tail writes in chan_hdr */
41
42         struct {
43                 struct signal_queue_header req_queue;
44                 struct signal_queue_header rsp_queue;
45                 struct signal_queue_header event_queue;
46                 struct signal_queue_header ack_queue;
47         } safe_uis_queue;
48 };
49
50 /* Creates the struct visorchannel abstraction for a data area in memory,
51  * but does NOT modify this data area.
52  */
53 static struct visorchannel *
54 visorchannel_create_guts(HOSTADDRESS physaddr, ulong channel_bytes,
55                          struct visorchannel *parent, ulong off, uuid_le guid,
56                          BOOL needs_lock)
57 {
58         struct visorchannel *channel;
59         int err;
60         size_t size = sizeof(struct channel_header);
61         struct memregion *memregion;
62
63         channel = kmalloc(sizeof(*channel), GFP_KERNEL|__GFP_NORETRY);
64         if (!channel)
65                 goto cleanup;
66
67         channel->memregion = NULL;
68         channel->needs_lock = needs_lock;
69         spin_lock_init(&channel->insert_lock);
70         spin_lock_init(&channel->remove_lock);
71
72         /* prepare chan_hdr (abstraction to read/write channel memory) */
73         if (!parent)
74                 memregion = visor_memregion_create(physaddr, size);
75         else
76                 memregion = visor_memregion_create_overlapped(parent->memregion,
77                                                               off, size);
78         if (!memregion)
79                 goto cleanup;
80         channel->memregion = memregion;
81
82         err = visor_memregion_read(channel->memregion, 0, &channel->chan_hdr,
83                                    sizeof(struct channel_header));
84         if (err)
85                 goto cleanup;
86
87         /* we had better be a CLIENT of this channel */
88         if (channel_bytes == 0)
89                 channel_bytes = (ulong)channel->chan_hdr.size;
90         if (uuid_le_cmp(guid, NULL_UUID_LE) == 0)
91                 guid = channel->chan_hdr.chtype;
92
93         err = visor_memregion_resize(channel->memregion, channel_bytes);
94         if (err)
95                 goto cleanup;
96
97         channel->size = channel_bytes;
98         channel->guid = guid;
99         return channel;
100
101 cleanup:
102         visorchannel_destroy(channel);
103         return NULL;
104 }
105
106 struct visorchannel *
107 visorchannel_create(HOSTADDRESS physaddr, ulong channel_bytes, uuid_le guid)
108 {
109         return visorchannel_create_guts(physaddr, channel_bytes, NULL, 0, guid,
110                                         FALSE);
111 }
112 EXPORT_SYMBOL_GPL(visorchannel_create);
113
114 struct visorchannel *
115 visorchannel_create_with_lock(HOSTADDRESS physaddr, ulong channel_bytes,
116                               uuid_le guid)
117 {
118         return visorchannel_create_guts(physaddr, channel_bytes, NULL, 0, guid,
119                                         TRUE);
120 }
121 EXPORT_SYMBOL_GPL(visorchannel_create_with_lock);
122
123 void
124 visorchannel_destroy(struct visorchannel *channel)
125 {
126         if (!channel)
127                 return;
128         visor_memregion_destroy(channel->memregion);
129         kfree(channel);
130 }
131 EXPORT_SYMBOL_GPL(visorchannel_destroy);
132
133 HOSTADDRESS
134 visorchannel_get_physaddr(struct visorchannel *channel)
135 {
136         return visor_memregion_get_physaddr(channel->memregion);
137 }
138 EXPORT_SYMBOL_GPL(visorchannel_get_physaddr);
139
140 ulong
141 visorchannel_get_nbytes(struct visorchannel *channel)
142 {
143         return channel->size;
144 }
145 EXPORT_SYMBOL_GPL(visorchannel_get_nbytes);
146
147 char *
148 visorchannel_uuid_id(uuid_le *guid, char *s)
149 {
150         sprintf(s, "%pUL", guid);
151         return s;
152 }
153 EXPORT_SYMBOL_GPL(visorchannel_uuid_id);
154
155 char *
156 visorchannel_id(struct visorchannel *channel, char *s)
157 {
158         return visorchannel_uuid_id(&channel->guid, s);
159 }
160 EXPORT_SYMBOL_GPL(visorchannel_id);
161
162 char *
163 visorchannel_zoneid(struct visorchannel *channel, char *s)
164 {
165         return visorchannel_uuid_id(&channel->chan_hdr.zone_uuid, s);
166 }
167 EXPORT_SYMBOL_GPL(visorchannel_zoneid);
168
169 HOSTADDRESS
170 visorchannel_get_clientpartition(struct visorchannel *channel)
171 {
172         return channel->chan_hdr.partition_handle;
173 }
174 EXPORT_SYMBOL_GPL(visorchannel_get_clientpartition);
175
176 uuid_le
177 visorchannel_get_uuid(struct visorchannel *channel)
178 {
179         return channel->guid;
180 }
181 EXPORT_SYMBOL_GPL(visorchannel_get_uuid);
182
183 struct memregion *
184 visorchannel_get_memregion(struct visorchannel *channel)
185 {
186         return channel->memregion;
187 }
188 EXPORT_SYMBOL_GPL(visorchannel_get_memregion);
189
190 int
191 visorchannel_read(struct visorchannel *channel, ulong offset,
192                   void *local, ulong nbytes)
193 {
194         int rc;
195         size_t size = sizeof(struct channel_header);
196
197         rc = visor_memregion_read(channel->memregion, offset, local, nbytes);
198         if (rc && !offset && (nbytes >= size))
199                 memcpy(&channel->chan_hdr, local, size);
200         return rc;
201 }
202 EXPORT_SYMBOL_GPL(visorchannel_read);
203
204 int
205 visorchannel_write(struct visorchannel *channel, ulong offset,
206                    void *local, ulong nbytes)
207 {
208         size_t size = sizeof(struct channel_header);
209
210         if (!offset && nbytes >= size)
211                 memcpy(&channel->chan_hdr, local, size);
212         return visor_memregion_write(channel->memregion, offset, local, nbytes);
213 }
214 EXPORT_SYMBOL_GPL(visorchannel_write);
215
216 int
217 visorchannel_clear(struct visorchannel *channel, ulong offset, u8 ch,
218                    ulong nbytes)
219 {
220         int err;
221         int bufsize = 65536;
222         int written = 0;
223         u8 *buf;
224
225         buf = vmalloc(bufsize);
226         if (!buf)
227                 return -ENOMEM;
228
229         memset(buf, ch, bufsize);
230         while (nbytes > 0) {
231                 ulong thisbytes = bufsize;
232
233                 if (nbytes < thisbytes)
234                         thisbytes = nbytes;
235                 err = visor_memregion_write(channel->memregion,
236                                             offset + written, buf, thisbytes);
237                 if (err)
238                         goto cleanup;
239
240                 written += thisbytes;
241                 nbytes -= thisbytes;
242         }
243         return 0;
244
245 cleanup:
246         vfree(buf);
247         return err;
248 }
249 EXPORT_SYMBOL_GPL(visorchannel_clear);
250
251 void __iomem  *
252 visorchannel_get_header(struct visorchannel *channel)
253 {
254         return (void __iomem *)&channel->chan_hdr;
255 }
256 EXPORT_SYMBOL_GPL(visorchannel_get_header);
257
258 /** Return offset of a specific SIGNAL_QUEUE_HEADER from the beginning of a
259  *  channel header
260  */
261 #define SIG_QUEUE_OFFSET(chan_hdr, q) \
262         ((chan_hdr)->ch_space_offset + \
263          ((q) * sizeof(struct signal_queue_header)))
264
265 /** Return offset of a specific queue entry (data) from the beginning of a
266  *  channel header
267  */
268 #define SIG_DATA_OFFSET(chan_hdr, q, sig_hdr, slot) \
269         (SIG_QUEUE_OFFSET(chan_hdr, q) + (sig_hdr)->sig_base_offset + \
270             ((slot) * (sig_hdr)->signal_size))
271
272 /** Write the contents of a specific field within a SIGNAL_QUEUE_HEADER back
273  *  into host memory
274  */
275 #define SIG_WRITE_FIELD(channel, queue, sig_hdr, FIELD)                 \
276         (visor_memregion_write(channel->memregion,                      \
277                                SIG_QUEUE_OFFSET(&channel->chan_hdr, queue)+ \
278                                offsetof(struct signal_queue_header, FIELD),\
279                                &((sig_hdr)->FIELD),                     \
280                                sizeof((sig_hdr)->FIELD)) >= 0)
281
282 static BOOL
283 sig_read_header(struct visorchannel *channel, u32 queue,
284                 struct signal_queue_header *sig_hdr)
285 {
286         int err;
287
288         if (channel->chan_hdr.ch_space_offset < sizeof(struct channel_header))
289                 return FALSE;
290
291         /* Read the appropriate SIGNAL_QUEUE_HEADER into local memory. */
292         err = visor_memregion_read(channel->memregion,
293                                    SIG_QUEUE_OFFSET(&channel->chan_hdr, queue),
294                                    sig_hdr, sizeof(struct signal_queue_header));
295         if (err)
296                 return FALSE;
297
298         return TRUE;
299 }
300
301 static inline BOOL
302 sig_read_data(struct visorchannel *channel, u32 queue,
303               struct signal_queue_header *sig_hdr, u32 slot, void *data)
304 {
305         int err;
306         int signal_data_offset = SIG_DATA_OFFSET(&channel->chan_hdr, queue,
307                                                  sig_hdr, slot);
308
309         err = visor_memregion_read(channel->memregion,
310                                    signal_data_offset,
311                                    data, sig_hdr->signal_size);
312         if (err)
313                 return FALSE;
314
315         return TRUE;
316 }
317
318 static inline BOOL
319 sig_write_data(struct visorchannel *channel, u32 queue,
320                struct signal_queue_header *sig_hdr, u32 slot, void *data)
321 {
322         int err;
323         int signal_data_offset = SIG_DATA_OFFSET(&channel->chan_hdr, queue,
324                                                  sig_hdr, slot);
325
326         err = visor_memregion_write(channel->memregion,
327                                     signal_data_offset,
328                                     data, sig_hdr->signal_size);
329         if (err)
330                 return FALSE;
331
332         return TRUE;
333 }
334
335 static BOOL
336 signalremove_inner(struct visorchannel *channel, u32 queue, void *msg)
337 {
338         struct signal_queue_header sig_hdr;
339
340         if (!sig_read_header(channel, queue, &sig_hdr))
341                 return FALSE;
342         if (sig_hdr.head == sig_hdr.tail)
343                 return FALSE;   /* no signals to remove */
344
345         sig_hdr.tail = (sig_hdr.tail + 1) % sig_hdr.max_slots;
346         if (!sig_read_data(channel, queue, &sig_hdr, sig_hdr.tail, msg))
347                 return FALSE;
348         sig_hdr.num_received++;
349
350         /* For each data field in SIGNAL_QUEUE_HEADER that was modified,
351          * update host memory.
352          */
353         mb(); /* required for channel synch */
354         if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, tail))
355                 return FALSE;
356         if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_received))
357                 return FALSE;
358         return TRUE;
359 }
360
361 BOOL
362 visorchannel_signalremove(struct visorchannel *channel, u32 queue, void *msg)
363 {
364         BOOL rc;
365
366         if (channel->needs_lock) {
367                 spin_lock(&channel->remove_lock);
368                 rc = signalremove_inner(channel, queue, msg);
369                 spin_unlock(&channel->remove_lock);
370         } else {
371                 rc = signalremove_inner(channel, queue, msg);
372         }
373
374         return rc;
375 }
376 EXPORT_SYMBOL_GPL(visorchannel_signalremove);
377
378 static BOOL
379 signalinsert_inner(struct visorchannel *channel, u32 queue, void *msg)
380 {
381         struct signal_queue_header sig_hdr;
382
383         if (!sig_read_header(channel, queue, &sig_hdr))
384                 return FALSE;
385
386         sig_hdr.head = ((sig_hdr.head + 1) % sig_hdr.max_slots);
387         if (sig_hdr.head == sig_hdr.tail) {
388                 sig_hdr.num_overflows++;
389                 visor_memregion_write(channel->memregion,
390                                       SIG_QUEUE_OFFSET(&channel->chan_hdr,
391                                                        queue) +
392                                       offsetof(struct signal_queue_header,
393                                                num_overflows),
394                                       &(sig_hdr.num_overflows),
395                                       sizeof(sig_hdr.num_overflows));
396                 return FALSE;
397         }
398
399         if (!sig_write_data(channel, queue, &sig_hdr, sig_hdr.head, msg))
400                 return FALSE;
401
402         sig_hdr.num_sent++;
403
404         /* For each data field in SIGNAL_QUEUE_HEADER that was modified,
405          * update host memory.
406          */
407         mb(); /* required for channel synch */
408         if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, head))
409                 return FALSE;
410         if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_sent))
411                 return FALSE;
412
413         return TRUE;
414 }
415
416 BOOL
417 visorchannel_signalinsert(struct visorchannel *channel, u32 queue, void *msg)
418 {
419         BOOL rc;
420
421         if (channel->needs_lock) {
422                 spin_lock(&channel->insert_lock);
423                 rc = signalinsert_inner(channel, queue, msg);
424                 spin_unlock(&channel->insert_lock);
425         } else {
426                 rc = signalinsert_inner(channel, queue, msg);
427         }
428
429         return rc;
430 }
431 EXPORT_SYMBOL_GPL(visorchannel_signalinsert);
432
433 int
434 visorchannel_signalqueue_slots_avail(struct visorchannel *channel, u32 queue)
435 {
436         struct signal_queue_header sig_hdr;
437         u32 slots_avail, slots_used;
438         u32 head, tail;
439
440         if (!sig_read_header(channel, queue, &sig_hdr))
441                 return 0;
442         head = sig_hdr.head;
443         tail = sig_hdr.tail;
444         if (head < tail)
445                 head = head + sig_hdr.max_slots;
446         slots_used = (head - tail);
447         slots_avail = sig_hdr.max_signals - slots_used;
448         return (int)slots_avail;
449 }
450 EXPORT_SYMBOL_GPL(visorchannel_signalqueue_slots_avail);
451
452 int
453 visorchannel_signalqueue_max_slots(struct visorchannel *channel, u32 queue)
454 {
455         struct signal_queue_header sig_hdr;
456
457         if (!sig_read_header(channel, queue, &sig_hdr))
458                 return 0;
459         return (int)sig_hdr.max_signals;
460 }
461 EXPORT_SYMBOL_GPL(visorchannel_signalqueue_max_slots);
462
463 static void
464 sigqueue_debug(struct signal_queue_header *q, int which, struct seq_file *seq)
465 {
466         seq_printf(seq, "Signal Queue #%d\n", which);
467         seq_printf(seq, "   VersionId          = %lu\n", (ulong)q->version);
468         seq_printf(seq, "   Type               = %lu\n", (ulong)q->chtype);
469         seq_printf(seq, "   oSignalBase        = %llu\n",
470                    (long long)q->sig_base_offset);
471         seq_printf(seq, "   SignalSize         = %lu\n", (ulong)q->signal_size);
472         seq_printf(seq, "   MaxSignalSlots     = %lu\n",
473                    (ulong)q->max_slots);
474         seq_printf(seq, "   MaxSignals         = %lu\n", (ulong)q->max_signals);
475         seq_printf(seq, "   FeatureFlags       = %-16.16Lx\n",
476                    (long long)q->features);
477         seq_printf(seq, "   NumSignalsSent     = %llu\n",
478                    (long long)q->num_sent);
479         seq_printf(seq, "   NumSignalsReceived = %llu\n",
480                    (long long)q->num_received);
481         seq_printf(seq, "   NumOverflows       = %llu\n",
482                    (long long)q->num_overflows);
483         seq_printf(seq, "   Head               = %lu\n", (ulong)q->head);
484         seq_printf(seq, "   Tail               = %lu\n", (ulong)q->tail);
485 }
486
487 void
488 visorchannel_debug(struct visorchannel *channel, int num_queues,
489                    struct seq_file *seq, u32 off)
490 {
491         HOSTADDRESS addr = 0;
492         ulong nbytes = 0, nbytes_region = 0;
493         struct memregion *memregion = NULL;
494         struct channel_header hdr;
495         struct channel_header *phdr = &hdr;
496         int i = 0;
497         int errcode = 0;
498
499         if (!channel)
500                 return;
501         memregion = channel->memregion;
502         if (!memregion)
503                 return;
504
505         addr = visor_memregion_get_physaddr(memregion);
506         nbytes_region = visor_memregion_get_nbytes(memregion);
507         errcode = visorchannel_read(channel, off,
508                                     phdr, sizeof(struct channel_header));
509         if (errcode < 0) {
510                 seq_printf(seq,
511                            "Read of channel header failed with errcode=%d)\n",
512                            errcode);
513                 if (off == 0) {
514                         phdr = &channel->chan_hdr;
515                         seq_puts(seq, "(following data may be stale)\n");
516                 } else {
517                         return;
518                 }
519         }
520         nbytes = (ulong)(phdr->size);
521         seq_printf(seq, "--- Begin channel @0x%-16.16Lx for 0x%lx bytes (region=0x%lx bytes) ---\n",
522                    addr + off, nbytes, nbytes_region);
523         seq_printf(seq, "Type            = %pUL\n", &phdr->chtype);
524         seq_printf(seq, "ZoneGuid        = %pUL\n", &phdr->zone_uuid);
525         seq_printf(seq, "Signature       = 0x%-16.16Lx\n",
526                    (long long)phdr->signature);
527         seq_printf(seq, "LegacyState     = %lu\n", (ulong)phdr->legacy_state);
528         seq_printf(seq, "SrvState        = %lu\n", (ulong)phdr->srv_state);
529         seq_printf(seq, "CliStateBoot    = %lu\n", (ulong)phdr->cli_state_boot);
530         seq_printf(seq, "CliStateOS      = %lu\n", (ulong)phdr->cli_state_os);
531         seq_printf(seq, "HeaderSize      = %lu\n", (ulong)phdr->header_size);
532         seq_printf(seq, "Size            = %llu\n", (long long)phdr->size);
533         seq_printf(seq, "Features        = 0x%-16.16llx\n",
534                    (long long)phdr->features);
535         seq_printf(seq, "PartitionHandle = 0x%-16.16llx\n",
536                    (long long)phdr->partition_handle);
537         seq_printf(seq, "Handle          = 0x%-16.16llx\n",
538                    (long long)phdr->handle);
539         seq_printf(seq, "VersionId       = %lu\n", (ulong)phdr->version_id);
540         seq_printf(seq, "oChannelSpace   = %llu\n",
541                    (long long)phdr->ch_space_offset);
542         if ((phdr->ch_space_offset == 0) || (errcode < 0))
543                 ;
544         else
545                 for (i = 0; i < num_queues; i++) {
546                         struct signal_queue_header q;
547
548                         errcode = visorchannel_read(channel,
549                                                     off +
550                                                     phdr->ch_space_offset +
551                                                     (i * sizeof(q)),
552                                                     &q, sizeof(q));
553                         if (errcode < 0) {
554                                 seq_printf(seq,
555                                            "failed to read signal queue #%d from channel @0x%-16.16Lx errcode=%d\n",
556                                            i, addr, errcode);
557                                 continue;
558                         }
559                         sigqueue_debug(&q, i, seq);
560                 }
561         seq_printf(seq, "--- End   channel @0x%-16.16Lx for 0x%lx bytes ---\n",
562                    addr + off, nbytes);
563 }
564 EXPORT_SYMBOL_GPL(visorchannel_debug);
565
566 void
567 visorchannel_dump_section(struct visorchannel *chan, char *s,
568                           int off, int len, struct seq_file *seq)
569 {
570         char *buf, *tbuf, *fmtbuf;
571         int fmtbufsize = 0;
572         int i;
573         int errcode = 0;
574
575         fmtbufsize = 100 * COVQ(len, 16);
576         buf = kmalloc(len, GFP_KERNEL|__GFP_NORETRY);
577         if (!buf)
578                 return;
579         fmtbuf = kmalloc(fmtbufsize, GFP_KERNEL|__GFP_NORETRY);
580         if (!fmtbuf)
581                 goto fmt_failed;
582
583         errcode = visorchannel_read(chan, off, buf, len);
584         if (errcode < 0)
585                 goto read_failed;
586         seq_printf(seq, "channel %s:\n", s);
587         tbuf = buf;
588         while (len > 0) {
589                 i = (len < 16) ? len : 16;
590                 hex_dump_to_buffer(tbuf, i, 16, 1, fmtbuf, fmtbufsize, TRUE);
591                 seq_printf(seq, "%s\n", fmtbuf);
592                 tbuf += 16;
593                 len -= 16;
594         }
595
596 read_failed:
597         kfree(fmtbuf);
598 fmt_failed:
599         kfree(buf);
600 }
601 EXPORT_SYMBOL_GPL(visorchannel_dump_section);