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