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