6d7ea8bf435d07dead922d807bfa59a39cb71662
[platform/kernel/linux-starfive.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                          ulong off, uuid_le guid, BOOL needs_lock)
56 {
57         struct visorchannel *channel;
58         int err;
59         size_t size = sizeof(struct channel_header);
60
61         channel = kzalloc(sizeof(*channel), GFP_KERNEL|__GFP_NORETRY);
62         if (!channel)
63                 goto cleanup;
64
65         channel->needs_lock = needs_lock;
66         spin_lock_init(&channel->insert_lock);
67         spin_lock_init(&channel->remove_lock);
68
69         if (!request_mem_region(physaddr, size, MYDRVNAME))
70                 goto cleanup;
71
72         channel->memregion.mapped = ioremap_cache(physaddr, size);
73         if (!channel->memregion.mapped) {
74                 release_mem_region(physaddr, size);
75                 goto cleanup;
76         }
77
78         channel->memregion.physaddr = physaddr;
79         channel->memregion.nbytes = size;
80
81         err = visorchannel_read(channel, 0, &channel->chan_hdr,
82                                 sizeof(struct channel_header));
83         if (err)
84                 goto cleanup;
85
86         /* we had better be a CLIENT of this channel */
87         if (channel_bytes == 0)
88                 channel_bytes = (ulong)channel->chan_hdr.size;
89         if (uuid_le_cmp(guid, NULL_UUID_LE) == 0)
90                 guid = channel->chan_hdr.chtype;
91
92         iounmap(channel->memregion.mapped);
93         release_mem_region(channel->memregion.physaddr,
94                            channel->memregion.nbytes);
95         channel->memregion.mapped = NULL;
96         if (!request_mem_region(channel->memregion.physaddr, channel_bytes,
97                                 MYDRVNAME))
98                 goto cleanup;
99
100         channel->memregion.mapped = ioremap_cache(channel->memregion.physaddr,
101                                                   channel_bytes);
102         if (!channel->memregion.mapped) {
103                 release_mem_region(channel->memregion.physaddr, channel_bytes);
104                 goto cleanup;
105         }
106
107         channel->memregion.nbytes = channel_bytes;
108
109         channel->size = channel_bytes;
110         channel->guid = guid;
111         return channel;
112
113 cleanup:
114         visorchannel_destroy(channel);
115         return NULL;
116 }
117
118 struct visorchannel *
119 visorchannel_create(HOSTADDRESS physaddr, ulong channel_bytes, uuid_le guid)
120 {
121         return visorchannel_create_guts(physaddr, channel_bytes, 0, guid,
122                                         FALSE);
123 }
124 EXPORT_SYMBOL_GPL(visorchannel_create);
125
126 struct visorchannel *
127 visorchannel_create_with_lock(HOSTADDRESS physaddr, ulong channel_bytes,
128                               uuid_le guid)
129 {
130         return visorchannel_create_guts(physaddr, channel_bytes, 0, guid,
131                                         TRUE);
132 }
133 EXPORT_SYMBOL_GPL(visorchannel_create_with_lock);
134
135 void
136 visorchannel_destroy(struct visorchannel *channel)
137 {
138         if (!channel)
139                 return;
140         if (channel->memregion.mapped) {
141                 iounmap(channel->memregion.mapped);
142                 release_mem_region(channel->memregion.physaddr,
143                                    channel->memregion.nbytes);
144         }
145         kfree(channel);
146 }
147 EXPORT_SYMBOL_GPL(visorchannel_destroy);
148
149 HOSTADDRESS
150 visorchannel_get_physaddr(struct visorchannel *channel)
151 {
152         return channel->memregion.physaddr;
153 }
154 EXPORT_SYMBOL_GPL(visorchannel_get_physaddr);
155
156 ulong
157 visorchannel_get_nbytes(struct visorchannel *channel)
158 {
159         return channel->size;
160 }
161 EXPORT_SYMBOL_GPL(visorchannel_get_nbytes);
162
163 char *
164 visorchannel_uuid_id(uuid_le *guid, char *s)
165 {
166         sprintf(s, "%pUL", guid);
167         return s;
168 }
169 EXPORT_SYMBOL_GPL(visorchannel_uuid_id);
170
171 char *
172 visorchannel_id(struct visorchannel *channel, char *s)
173 {
174         return visorchannel_uuid_id(&channel->guid, s);
175 }
176 EXPORT_SYMBOL_GPL(visorchannel_id);
177
178 char *
179 visorchannel_zoneid(struct visorchannel *channel, char *s)
180 {
181         return visorchannel_uuid_id(&channel->chan_hdr.zone_uuid, s);
182 }
183 EXPORT_SYMBOL_GPL(visorchannel_zoneid);
184
185 HOSTADDRESS
186 visorchannel_get_clientpartition(struct visorchannel *channel)
187 {
188         return channel->chan_hdr.partition_handle;
189 }
190 EXPORT_SYMBOL_GPL(visorchannel_get_clientpartition);
191
192 uuid_le
193 visorchannel_get_uuid(struct visorchannel *channel)
194 {
195         return channel->guid;
196 }
197 EXPORT_SYMBOL_GPL(visorchannel_get_uuid);
198
199 int
200 visorchannel_read(struct visorchannel *channel, ulong offset,
201                   void *local, ulong nbytes)
202 {
203         if (offset + nbytes > channel->memregion.nbytes)
204                 return -EIO;
205
206         memcpy_fromio(local, channel->memregion.mapped + offset, nbytes);
207
208         return 0;
209 }
210 EXPORT_SYMBOL_GPL(visorchannel_read);
211
212 int
213 visorchannel_write(struct visorchannel *channel, ulong offset,
214                    void *local, ulong nbytes)
215 {
216         size_t chdr_size = sizeof(struct channel_header);
217         size_t copy_size;
218
219         if (offset + nbytes > channel->memregion.nbytes)
220                 return -EIO;
221
222         if (offset < chdr_size) {
223                 copy_size = min(chdr_size, nbytes) - offset;
224                 memcpy(&channel->chan_hdr + offset, local, copy_size);
225         }
226
227         memcpy_toio(channel->memregion.mapped + offset, local, nbytes);
228
229         return 0;
230 }
231 EXPORT_SYMBOL_GPL(visorchannel_write);
232
233 int
234 visorchannel_clear(struct visorchannel *channel, ulong offset, u8 ch,
235                    ulong nbytes)
236 {
237         int err;
238         int bufsize = PAGE_SIZE;
239         int written = 0;
240         u8 *buf;
241
242         buf = (u8 *) __get_free_page(GFP_KERNEL);
243         if (!buf)
244                 return -ENOMEM;
245
246         memset(buf, ch, bufsize);
247
248         while (nbytes > 0) {
249                 int thisbytes = bufsize;
250
251                 if (nbytes < thisbytes)
252                         thisbytes = nbytes;
253                 err = visor_memregion_write(&channel->memregion,
254                                             offset + written, buf, thisbytes);
255                 if (err)
256                         goto cleanup;
257
258                 written += thisbytes;
259                 nbytes -= thisbytes;
260         }
261         err = 0;
262
263 cleanup:
264         free_page((unsigned long) buf);
265         return err;
266 }
267 EXPORT_SYMBOL_GPL(visorchannel_clear);
268
269 void __iomem  *
270 visorchannel_get_header(struct visorchannel *channel)
271 {
272         return (void __iomem *)&channel->chan_hdr;
273 }
274 EXPORT_SYMBOL_GPL(visorchannel_get_header);
275
276 /** Return offset of a specific SIGNAL_QUEUE_HEADER from the beginning of a
277  *  channel header
278  */
279 #define SIG_QUEUE_OFFSET(chan_hdr, q) \
280         ((chan_hdr)->ch_space_offset + \
281          ((q) * sizeof(struct signal_queue_header)))
282
283 /** Return offset of a specific queue entry (data) from the beginning of a
284  *  channel header
285  */
286 #define SIG_DATA_OFFSET(chan_hdr, q, sig_hdr, slot) \
287         (SIG_QUEUE_OFFSET(chan_hdr, q) + (sig_hdr)->sig_base_offset + \
288             ((slot) * (sig_hdr)->signal_size))
289
290 /** Write the contents of a specific field within a SIGNAL_QUEUE_HEADER back
291  *  into host memory
292  */
293 #define SIG_WRITE_FIELD(channel, queue, sig_hdr, FIELD)                 \
294         (visor_memregion_write(&channel->memregion,                     \
295                                SIG_QUEUE_OFFSET(&channel->chan_hdr, queue)+ \
296                                offsetof(struct signal_queue_header, FIELD),\
297                                &((sig_hdr)->FIELD),                     \
298                                sizeof((sig_hdr)->FIELD)) >= 0)
299
300 static BOOL
301 sig_read_header(struct visorchannel *channel, u32 queue,
302                 struct signal_queue_header *sig_hdr)
303 {
304         int err;
305
306         if (channel->chan_hdr.ch_space_offset < sizeof(struct channel_header))
307                 return FALSE;
308
309         /* Read the appropriate SIGNAL_QUEUE_HEADER into local memory. */
310         err = visor_memregion_read(&channel->memregion,
311                                    SIG_QUEUE_OFFSET(&channel->chan_hdr, queue),
312                                    sig_hdr, sizeof(struct signal_queue_header));
313         if (err)
314                 return FALSE;
315
316         return TRUE;
317 }
318
319 static inline BOOL
320 sig_read_data(struct visorchannel *channel, u32 queue,
321               struct signal_queue_header *sig_hdr, u32 slot, void *data)
322 {
323         int err;
324         int signal_data_offset = SIG_DATA_OFFSET(&channel->chan_hdr, queue,
325                                                  sig_hdr, slot);
326
327         err = visor_memregion_read(&channel->memregion,
328                                    signal_data_offset,
329                                    data, sig_hdr->signal_size);
330         if (err)
331                 return FALSE;
332
333         return TRUE;
334 }
335
336 static inline BOOL
337 sig_write_data(struct visorchannel *channel, u32 queue,
338                struct signal_queue_header *sig_hdr, u32 slot, void *data)
339 {
340         int err;
341         int signal_data_offset = SIG_DATA_OFFSET(&channel->chan_hdr, queue,
342                                                  sig_hdr, slot);
343
344         err = visor_memregion_write(&channel->memregion,
345                                     signal_data_offset,
346                                     data, sig_hdr->signal_size);
347         if (err)
348                 return FALSE;
349
350         return TRUE;
351 }
352
353 static BOOL
354 signalremove_inner(struct visorchannel *channel, u32 queue, void *msg)
355 {
356         struct signal_queue_header sig_hdr;
357
358         if (!sig_read_header(channel, queue, &sig_hdr))
359                 return FALSE;
360         if (sig_hdr.head == sig_hdr.tail)
361                 return FALSE;   /* no signals to remove */
362
363         sig_hdr.tail = (sig_hdr.tail + 1) % sig_hdr.max_slots;
364         if (!sig_read_data(channel, queue, &sig_hdr, sig_hdr.tail, msg))
365                 return FALSE;
366         sig_hdr.num_received++;
367
368         /* For each data field in SIGNAL_QUEUE_HEADER that was modified,
369          * update host memory.
370          */
371         mb(); /* required for channel synch */
372         if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, tail))
373                 return FALSE;
374         if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_received))
375                 return FALSE;
376         return TRUE;
377 }
378
379 BOOL
380 visorchannel_signalremove(struct visorchannel *channel, u32 queue, void *msg)
381 {
382         BOOL rc;
383
384         if (channel->needs_lock) {
385                 spin_lock(&channel->remove_lock);
386                 rc = signalremove_inner(channel, queue, msg);
387                 spin_unlock(&channel->remove_lock);
388         } else {
389                 rc = signalremove_inner(channel, queue, msg);
390         }
391
392         return rc;
393 }
394 EXPORT_SYMBOL_GPL(visorchannel_signalremove);
395
396 static BOOL
397 signalinsert_inner(struct visorchannel *channel, u32 queue, void *msg)
398 {
399         struct signal_queue_header sig_hdr;
400
401         if (!sig_read_header(channel, queue, &sig_hdr))
402                 return FALSE;
403
404         sig_hdr.head = ((sig_hdr.head + 1) % sig_hdr.max_slots);
405         if (sig_hdr.head == sig_hdr.tail) {
406                 sig_hdr.num_overflows++;
407                 visor_memregion_write(&channel->memregion,
408                                       SIG_QUEUE_OFFSET(&channel->chan_hdr,
409                                                        queue) +
410                                       offsetof(struct signal_queue_header,
411                                                num_overflows),
412                                       &(sig_hdr.num_overflows),
413                                       sizeof(sig_hdr.num_overflows));
414                 return FALSE;
415         }
416
417         if (!sig_write_data(channel, queue, &sig_hdr, sig_hdr.head, msg))
418                 return FALSE;
419
420         sig_hdr.num_sent++;
421
422         /* For each data field in SIGNAL_QUEUE_HEADER that was modified,
423          * update host memory.
424          */
425         mb(); /* required for channel synch */
426         if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, head))
427                 return FALSE;
428         if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_sent))
429                 return FALSE;
430
431         return TRUE;
432 }
433
434 BOOL
435 visorchannel_signalinsert(struct visorchannel *channel, u32 queue, void *msg)
436 {
437         BOOL rc;
438
439         if (channel->needs_lock) {
440                 spin_lock(&channel->insert_lock);
441                 rc = signalinsert_inner(channel, queue, msg);
442                 spin_unlock(&channel->insert_lock);
443         } else {
444                 rc = signalinsert_inner(channel, queue, msg);
445         }
446
447         return rc;
448 }
449 EXPORT_SYMBOL_GPL(visorchannel_signalinsert);
450
451 int
452 visorchannel_signalqueue_slots_avail(struct visorchannel *channel, u32 queue)
453 {
454         struct signal_queue_header sig_hdr;
455         u32 slots_avail, slots_used;
456         u32 head, tail;
457
458         if (!sig_read_header(channel, queue, &sig_hdr))
459                 return 0;
460         head = sig_hdr.head;
461         tail = sig_hdr.tail;
462         if (head < tail)
463                 head = head + sig_hdr.max_slots;
464         slots_used = (head - tail);
465         slots_avail = sig_hdr.max_signals - slots_used;
466         return (int)slots_avail;
467 }
468 EXPORT_SYMBOL_GPL(visorchannel_signalqueue_slots_avail);
469
470 int
471 visorchannel_signalqueue_max_slots(struct visorchannel *channel, u32 queue)
472 {
473         struct signal_queue_header sig_hdr;
474
475         if (!sig_read_header(channel, queue, &sig_hdr))
476                 return 0;
477         return (int)sig_hdr.max_signals;
478 }
479 EXPORT_SYMBOL_GPL(visorchannel_signalqueue_max_slots);
480
481 static void
482 sigqueue_debug(struct signal_queue_header *q, int which, struct seq_file *seq)
483 {
484         seq_printf(seq, "Signal Queue #%d\n", which);
485         seq_printf(seq, "   VersionId          = %lu\n", (ulong)q->version);
486         seq_printf(seq, "   Type               = %lu\n", (ulong)q->chtype);
487         seq_printf(seq, "   oSignalBase        = %llu\n",
488                    (long long)q->sig_base_offset);
489         seq_printf(seq, "   SignalSize         = %lu\n", (ulong)q->signal_size);
490         seq_printf(seq, "   MaxSignalSlots     = %lu\n",
491                    (ulong)q->max_slots);
492         seq_printf(seq, "   MaxSignals         = %lu\n", (ulong)q->max_signals);
493         seq_printf(seq, "   FeatureFlags       = %-16.16Lx\n",
494                    (long long)q->features);
495         seq_printf(seq, "   NumSignalsSent     = %llu\n",
496                    (long long)q->num_sent);
497         seq_printf(seq, "   NumSignalsReceived = %llu\n",
498                    (long long)q->num_received);
499         seq_printf(seq, "   NumOverflows       = %llu\n",
500                    (long long)q->num_overflows);
501         seq_printf(seq, "   Head               = %lu\n", (ulong)q->head);
502         seq_printf(seq, "   Tail               = %lu\n", (ulong)q->tail);
503 }
504
505 void
506 visorchannel_debug(struct visorchannel *channel, int num_queues,
507                    struct seq_file *seq, u32 off)
508 {
509         HOSTADDRESS addr = 0;
510         ulong nbytes = 0, nbytes_region = 0;
511         struct channel_header hdr;
512         struct channel_header *phdr = &hdr;
513         int i = 0;
514         int errcode = 0;
515
516         if (!channel)
517                 return;
518
519         addr = visorchannel_get_physaddr(channel);
520         nbytes_region = visorchannel_get_nbytes(channel);
521         errcode = visorchannel_read(channel, off,
522                                     phdr, sizeof(struct channel_header));
523         if (errcode < 0) {
524                 seq_printf(seq,
525                            "Read of channel header failed with errcode=%d)\n",
526                            errcode);
527                 if (off == 0) {
528                         phdr = &channel->chan_hdr;
529                         seq_puts(seq, "(following data may be stale)\n");
530                 } else {
531                         return;
532                 }
533         }
534         nbytes = (ulong)(phdr->size);
535         seq_printf(seq, "--- Begin channel @0x%-16.16Lx for 0x%lx bytes (region=0x%lx bytes) ---\n",
536                    addr + off, nbytes, nbytes_region);
537         seq_printf(seq, "Type            = %pUL\n", &phdr->chtype);
538         seq_printf(seq, "ZoneGuid        = %pUL\n", &phdr->zone_uuid);
539         seq_printf(seq, "Signature       = 0x%-16.16Lx\n",
540                    (long long)phdr->signature);
541         seq_printf(seq, "LegacyState     = %lu\n", (ulong)phdr->legacy_state);
542         seq_printf(seq, "SrvState        = %lu\n", (ulong)phdr->srv_state);
543         seq_printf(seq, "CliStateBoot    = %lu\n", (ulong)phdr->cli_state_boot);
544         seq_printf(seq, "CliStateOS      = %lu\n", (ulong)phdr->cli_state_os);
545         seq_printf(seq, "HeaderSize      = %lu\n", (ulong)phdr->header_size);
546         seq_printf(seq, "Size            = %llu\n", (long long)phdr->size);
547         seq_printf(seq, "Features        = 0x%-16.16llx\n",
548                    (long long)phdr->features);
549         seq_printf(seq, "PartitionHandle = 0x%-16.16llx\n",
550                    (long long)phdr->partition_handle);
551         seq_printf(seq, "Handle          = 0x%-16.16llx\n",
552                    (long long)phdr->handle);
553         seq_printf(seq, "VersionId       = %lu\n", (ulong)phdr->version_id);
554         seq_printf(seq, "oChannelSpace   = %llu\n",
555                    (long long)phdr->ch_space_offset);
556         if ((phdr->ch_space_offset == 0) || (errcode < 0))
557                 ;
558         else
559                 for (i = 0; i < num_queues; i++) {
560                         struct signal_queue_header q;
561
562                         errcode = visorchannel_read(channel,
563                                                     off +
564                                                     phdr->ch_space_offset +
565                                                     (i * sizeof(q)),
566                                                     &q, sizeof(q));
567                         if (errcode < 0) {
568                                 seq_printf(seq,
569                                            "failed to read signal queue #%d from channel @0x%-16.16Lx errcode=%d\n",
570                                            i, addr, errcode);
571                                 continue;
572                         }
573                         sigqueue_debug(&q, i, seq);
574                 }
575         seq_printf(seq, "--- End   channel @0x%-16.16Lx for 0x%lx bytes ---\n",
576                    addr + off, nbytes);
577 }
578 EXPORT_SYMBOL_GPL(visorchannel_debug);