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