staging: unisys: memregion: Eliminate visor_memregion_get_*() functions
[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 = visor_memregion_read(&channel->memregion, 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         int rc;
204         size_t size = sizeof(struct channel_header);
205
206         rc = visor_memregion_read(&channel->memregion, offset, local, nbytes);
207         if (rc && !offset && (nbytes >= size))
208                 memcpy(&channel->chan_hdr, local, size);
209         return rc;
210 }
211 EXPORT_SYMBOL_GPL(visorchannel_read);
212
213 int
214 visorchannel_write(struct visorchannel *channel, ulong offset,
215                    void *local, ulong nbytes)
216 {
217         size_t size = sizeof(struct channel_header);
218
219         if (!offset && nbytes >= size)
220                 memcpy(&channel->chan_hdr, local, size);
221         return visor_memregion_write(&channel->memregion,
222                                      offset, local, nbytes);
223 }
224 EXPORT_SYMBOL_GPL(visorchannel_write);
225
226 int
227 visorchannel_clear(struct visorchannel *channel, ulong offset, u8 ch,
228                    ulong nbytes)
229 {
230         int err;
231         int bufsize = PAGE_SIZE;
232         int written = 0;
233         u8 *buf;
234
235         buf = (u8 *) __get_free_page(GFP_KERNEL);
236         if (!buf)
237                 return -ENOMEM;
238
239         memset(buf, ch, bufsize);
240
241         while (nbytes > 0) {
242                 int thisbytes = bufsize;
243
244                 if (nbytes < thisbytes)
245                         thisbytes = nbytes;
246                 err = visor_memregion_write(&channel->memregion,
247                                             offset + written, buf, thisbytes);
248                 if (err)
249                         goto cleanup;
250
251                 written += thisbytes;
252                 nbytes -= thisbytes;
253         }
254         err = 0;
255
256 cleanup:
257         free_page((unsigned long) buf);
258         return err;
259 }
260 EXPORT_SYMBOL_GPL(visorchannel_clear);
261
262 void __iomem  *
263 visorchannel_get_header(struct visorchannel *channel)
264 {
265         return (void __iomem *)&channel->chan_hdr;
266 }
267 EXPORT_SYMBOL_GPL(visorchannel_get_header);
268
269 /** Return offset of a specific SIGNAL_QUEUE_HEADER from the beginning of a
270  *  channel header
271  */
272 #define SIG_QUEUE_OFFSET(chan_hdr, q) \
273         ((chan_hdr)->ch_space_offset + \
274          ((q) * sizeof(struct signal_queue_header)))
275
276 /** Return offset of a specific queue entry (data) from the beginning of a
277  *  channel header
278  */
279 #define SIG_DATA_OFFSET(chan_hdr, q, sig_hdr, slot) \
280         (SIG_QUEUE_OFFSET(chan_hdr, q) + (sig_hdr)->sig_base_offset + \
281             ((slot) * (sig_hdr)->signal_size))
282
283 /** Write the contents of a specific field within a SIGNAL_QUEUE_HEADER back
284  *  into host memory
285  */
286 #define SIG_WRITE_FIELD(channel, queue, sig_hdr, FIELD)                 \
287         (visor_memregion_write(&channel->memregion,                     \
288                                SIG_QUEUE_OFFSET(&channel->chan_hdr, queue)+ \
289                                offsetof(struct signal_queue_header, FIELD),\
290                                &((sig_hdr)->FIELD),                     \
291                                sizeof((sig_hdr)->FIELD)) >= 0)
292
293 static BOOL
294 sig_read_header(struct visorchannel *channel, u32 queue,
295                 struct signal_queue_header *sig_hdr)
296 {
297         int err;
298
299         if (channel->chan_hdr.ch_space_offset < sizeof(struct channel_header))
300                 return FALSE;
301
302         /* Read the appropriate SIGNAL_QUEUE_HEADER into local memory. */
303         err = visor_memregion_read(&channel->memregion,
304                                    SIG_QUEUE_OFFSET(&channel->chan_hdr, queue),
305                                    sig_hdr, sizeof(struct signal_queue_header));
306         if (err)
307                 return FALSE;
308
309         return TRUE;
310 }
311
312 static inline BOOL
313 sig_read_data(struct visorchannel *channel, u32 queue,
314               struct signal_queue_header *sig_hdr, u32 slot, void *data)
315 {
316         int err;
317         int signal_data_offset = SIG_DATA_OFFSET(&channel->chan_hdr, queue,
318                                                  sig_hdr, slot);
319
320         err = visor_memregion_read(&channel->memregion,
321                                    signal_data_offset,
322                                    data, sig_hdr->signal_size);
323         if (err)
324                 return FALSE;
325
326         return TRUE;
327 }
328
329 static inline BOOL
330 sig_write_data(struct visorchannel *channel, u32 queue,
331                struct signal_queue_header *sig_hdr, u32 slot, void *data)
332 {
333         int err;
334         int signal_data_offset = SIG_DATA_OFFSET(&channel->chan_hdr, queue,
335                                                  sig_hdr, slot);
336
337         err = visor_memregion_write(&channel->memregion,
338                                     signal_data_offset,
339                                     data, sig_hdr->signal_size);
340         if (err)
341                 return FALSE;
342
343         return TRUE;
344 }
345
346 static BOOL
347 signalremove_inner(struct visorchannel *channel, u32 queue, void *msg)
348 {
349         struct signal_queue_header sig_hdr;
350
351         if (!sig_read_header(channel, queue, &sig_hdr))
352                 return FALSE;
353         if (sig_hdr.head == sig_hdr.tail)
354                 return FALSE;   /* no signals to remove */
355
356         sig_hdr.tail = (sig_hdr.tail + 1) % sig_hdr.max_slots;
357         if (!sig_read_data(channel, queue, &sig_hdr, sig_hdr.tail, msg))
358                 return FALSE;
359         sig_hdr.num_received++;
360
361         /* For each data field in SIGNAL_QUEUE_HEADER that was modified,
362          * update host memory.
363          */
364         mb(); /* required for channel synch */
365         if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, tail))
366                 return FALSE;
367         if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_received))
368                 return FALSE;
369         return TRUE;
370 }
371
372 BOOL
373 visorchannel_signalremove(struct visorchannel *channel, u32 queue, void *msg)
374 {
375         BOOL rc;
376
377         if (channel->needs_lock) {
378                 spin_lock(&channel->remove_lock);
379                 rc = signalremove_inner(channel, queue, msg);
380                 spin_unlock(&channel->remove_lock);
381         } else {
382                 rc = signalremove_inner(channel, queue, msg);
383         }
384
385         return rc;
386 }
387 EXPORT_SYMBOL_GPL(visorchannel_signalremove);
388
389 static BOOL
390 signalinsert_inner(struct visorchannel *channel, u32 queue, void *msg)
391 {
392         struct signal_queue_header sig_hdr;
393
394         if (!sig_read_header(channel, queue, &sig_hdr))
395                 return FALSE;
396
397         sig_hdr.head = ((sig_hdr.head + 1) % sig_hdr.max_slots);
398         if (sig_hdr.head == sig_hdr.tail) {
399                 sig_hdr.num_overflows++;
400                 visor_memregion_write(&channel->memregion,
401                                       SIG_QUEUE_OFFSET(&channel->chan_hdr,
402                                                        queue) +
403                                       offsetof(struct signal_queue_header,
404                                                num_overflows),
405                                       &(sig_hdr.num_overflows),
406                                       sizeof(sig_hdr.num_overflows));
407                 return FALSE;
408         }
409
410         if (!sig_write_data(channel, queue, &sig_hdr, sig_hdr.head, msg))
411                 return FALSE;
412
413         sig_hdr.num_sent++;
414
415         /* For each data field in SIGNAL_QUEUE_HEADER that was modified,
416          * update host memory.
417          */
418         mb(); /* required for channel synch */
419         if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, head))
420                 return FALSE;
421         if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_sent))
422                 return FALSE;
423
424         return TRUE;
425 }
426
427 BOOL
428 visorchannel_signalinsert(struct visorchannel *channel, u32 queue, void *msg)
429 {
430         BOOL rc;
431
432         if (channel->needs_lock) {
433                 spin_lock(&channel->insert_lock);
434                 rc = signalinsert_inner(channel, queue, msg);
435                 spin_unlock(&channel->insert_lock);
436         } else {
437                 rc = signalinsert_inner(channel, queue, msg);
438         }
439
440         return rc;
441 }
442 EXPORT_SYMBOL_GPL(visorchannel_signalinsert);
443
444 int
445 visorchannel_signalqueue_slots_avail(struct visorchannel *channel, u32 queue)
446 {
447         struct signal_queue_header sig_hdr;
448         u32 slots_avail, slots_used;
449         u32 head, tail;
450
451         if (!sig_read_header(channel, queue, &sig_hdr))
452                 return 0;
453         head = sig_hdr.head;
454         tail = sig_hdr.tail;
455         if (head < tail)
456                 head = head + sig_hdr.max_slots;
457         slots_used = (head - tail);
458         slots_avail = sig_hdr.max_signals - slots_used;
459         return (int)slots_avail;
460 }
461 EXPORT_SYMBOL_GPL(visorchannel_signalqueue_slots_avail);
462
463 int
464 visorchannel_signalqueue_max_slots(struct visorchannel *channel, u32 queue)
465 {
466         struct signal_queue_header sig_hdr;
467
468         if (!sig_read_header(channel, queue, &sig_hdr))
469                 return 0;
470         return (int)sig_hdr.max_signals;
471 }
472 EXPORT_SYMBOL_GPL(visorchannel_signalqueue_max_slots);
473
474 static void
475 sigqueue_debug(struct signal_queue_header *q, int which, struct seq_file *seq)
476 {
477         seq_printf(seq, "Signal Queue #%d\n", which);
478         seq_printf(seq, "   VersionId          = %lu\n", (ulong)q->version);
479         seq_printf(seq, "   Type               = %lu\n", (ulong)q->chtype);
480         seq_printf(seq, "   oSignalBase        = %llu\n",
481                    (long long)q->sig_base_offset);
482         seq_printf(seq, "   SignalSize         = %lu\n", (ulong)q->signal_size);
483         seq_printf(seq, "   MaxSignalSlots     = %lu\n",
484                    (ulong)q->max_slots);
485         seq_printf(seq, "   MaxSignals         = %lu\n", (ulong)q->max_signals);
486         seq_printf(seq, "   FeatureFlags       = %-16.16Lx\n",
487                    (long long)q->features);
488         seq_printf(seq, "   NumSignalsSent     = %llu\n",
489                    (long long)q->num_sent);
490         seq_printf(seq, "   NumSignalsReceived = %llu\n",
491                    (long long)q->num_received);
492         seq_printf(seq, "   NumOverflows       = %llu\n",
493                    (long long)q->num_overflows);
494         seq_printf(seq, "   Head               = %lu\n", (ulong)q->head);
495         seq_printf(seq, "   Tail               = %lu\n", (ulong)q->tail);
496 }
497
498 void
499 visorchannel_debug(struct visorchannel *channel, int num_queues,
500                    struct seq_file *seq, u32 off)
501 {
502         HOSTADDRESS addr = 0;
503         ulong nbytes = 0, nbytes_region = 0;
504         struct channel_header hdr;
505         struct channel_header *phdr = &hdr;
506         int i = 0;
507         int errcode = 0;
508
509         if (!channel)
510                 return;
511
512         addr = visorchannel_get_physaddr(channel);
513         nbytes_region = visorchannel_get_nbytes(channel);
514         errcode = visorchannel_read(channel, off,
515                                     phdr, sizeof(struct channel_header));
516         if (errcode < 0) {
517                 seq_printf(seq,
518                            "Read of channel header failed with errcode=%d)\n",
519                            errcode);
520                 if (off == 0) {
521                         phdr = &channel->chan_hdr;
522                         seq_puts(seq, "(following data may be stale)\n");
523                 } else {
524                         return;
525                 }
526         }
527         nbytes = (ulong)(phdr->size);
528         seq_printf(seq, "--- Begin channel @0x%-16.16Lx for 0x%lx bytes (region=0x%lx bytes) ---\n",
529                    addr + off, nbytes, nbytes_region);
530         seq_printf(seq, "Type            = %pUL\n", &phdr->chtype);
531         seq_printf(seq, "ZoneGuid        = %pUL\n", &phdr->zone_uuid);
532         seq_printf(seq, "Signature       = 0x%-16.16Lx\n",
533                    (long long)phdr->signature);
534         seq_printf(seq, "LegacyState     = %lu\n", (ulong)phdr->legacy_state);
535         seq_printf(seq, "SrvState        = %lu\n", (ulong)phdr->srv_state);
536         seq_printf(seq, "CliStateBoot    = %lu\n", (ulong)phdr->cli_state_boot);
537         seq_printf(seq, "CliStateOS      = %lu\n", (ulong)phdr->cli_state_os);
538         seq_printf(seq, "HeaderSize      = %lu\n", (ulong)phdr->header_size);
539         seq_printf(seq, "Size            = %llu\n", (long long)phdr->size);
540         seq_printf(seq, "Features        = 0x%-16.16llx\n",
541                    (long long)phdr->features);
542         seq_printf(seq, "PartitionHandle = 0x%-16.16llx\n",
543                    (long long)phdr->partition_handle);
544         seq_printf(seq, "Handle          = 0x%-16.16llx\n",
545                    (long long)phdr->handle);
546         seq_printf(seq, "VersionId       = %lu\n", (ulong)phdr->version_id);
547         seq_printf(seq, "oChannelSpace   = %llu\n",
548                    (long long)phdr->ch_space_offset);
549         if ((phdr->ch_space_offset == 0) || (errcode < 0))
550                 ;
551         else
552                 for (i = 0; i < num_queues; i++) {
553                         struct signal_queue_header q;
554
555                         errcode = visorchannel_read(channel,
556                                                     off +
557                                                     phdr->ch_space_offset +
558                                                     (i * sizeof(q)),
559                                                     &q, sizeof(q));
560                         if (errcode < 0) {
561                                 seq_printf(seq,
562                                            "failed to read signal queue #%d from channel @0x%-16.16Lx errcode=%d\n",
563                                            i, addr, errcode);
564                                 continue;
565                         }
566                         sigqueue_debug(&q, i, seq);
567                 }
568         seq_printf(seq, "--- End   channel @0x%-16.16Lx for 0x%lx bytes ---\n",
569                    addr + off, nbytes);
570 }
571 EXPORT_SYMBOL_GPL(visorchannel_debug);