1 /* visorchannel_funcs.c
2  *
3  * Copyright (C) 2010 - 2015 UNISYS CORPORATION
4  * All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms and conditions of the GNU General Public License,
8  * version 2, as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
13  * NON INFRINGEMENT.  See the GNU General Public License for more
14  * details.
15  */
16 
17 /*
18  *  This provides Supervisor channel communication primitives, which are
19  *  independent of the mechanism used to access the channel data.
20  */
21 
22 #include <linux/uuid.h>
23 #include <linux/io.h>
24 
25 #include "version.h"
26 #include "visorbus.h"
27 #include "controlvmchannel.h"
28 
29 #define MYDRVNAME "visorchannel"
30 
31 #define SPAR_CONSOLEVIDEO_CHANNEL_PROTOCOL_GUID \
32 	UUID_LE(0x3cd6e705, 0xd6a2, 0x4aa5,           \
33 		0xad, 0x5c, 0x7b, 0x8, 0x88, 0x9d, 0xff, 0xe2)
34 static const uuid_le spar_video_guid = SPAR_CONSOLEVIDEO_CHANNEL_PROTOCOL_GUID;
35 
36 struct visorchannel {
37 	u64 physaddr;
38 	ulong nbytes;
39 	void *mapped;
40 	bool requested;
41 	struct channel_header chan_hdr;
42 	uuid_le guid;
43 	ulong size;
44 	bool needs_lock;	/* channel creator knows if more than one
45 				 * thread will be inserting or removing */
46 	spinlock_t insert_lock; /* protect head writes in chan_hdr */
47 	spinlock_t remove_lock;	/* protect tail writes in chan_hdr */
48 
49 	struct {
50 		struct signal_queue_header req_queue;
51 		struct signal_queue_header rsp_queue;
52 		struct signal_queue_header event_queue;
53 		struct signal_queue_header ack_queue;
54 	} safe_uis_queue;
55 	uuid_le type;
56 	uuid_le inst;
57 };
58 
59 /* Creates the struct visorchannel abstraction for a data area in memory,
60  * but does NOT modify this data area.
61  */
62 static struct visorchannel *
visorchannel_create_guts(u64 physaddr,unsigned long channel_bytes,gfp_t gfp,unsigned long off,uuid_le guid,bool needs_lock)63 visorchannel_create_guts(u64 physaddr, unsigned long channel_bytes,
64 			 gfp_t gfp, unsigned long off,
65 			 uuid_le guid, bool needs_lock)
66 {
67 	struct visorchannel *channel;
68 	int err;
69 	size_t size = sizeof(struct channel_header);
70 
71 	if (physaddr == 0)
72 		return NULL;
73 
74 	channel = kzalloc(sizeof(*channel), gfp);
75 	if (!channel)
76 		goto cleanup;
77 
78 	channel->needs_lock = needs_lock;
79 	spin_lock_init(&channel->insert_lock);
80 	spin_lock_init(&channel->remove_lock);
81 
82 	/* Video driver constains the efi framebuffer so it will get a
83 	 * conflict resource when requesting its full mem region. Since
84 	 * we are only using the efi framebuffer for video we can ignore
85 	 * this. Remember that we haven't requested it so we don't try to
86 	 * release later on.
87 	 */
88 	channel->requested = request_mem_region(physaddr, size, MYDRVNAME);
89 	if (!channel->requested) {
90 		if (uuid_le_cmp(guid, spar_video_guid)) {
91 			/* Not the video channel we care about this */
92 			goto cleanup;
93 		}
94 	}
95 
96 	channel->mapped = memremap(physaddr, size, MEMREMAP_WB);
97 	if (!channel->mapped) {
98 		release_mem_region(physaddr, size);
99 		goto cleanup;
100 	}
101 
102 	channel->physaddr = physaddr;
103 	channel->nbytes = size;
104 
105 	err = visorchannel_read(channel, 0, &channel->chan_hdr,
106 				sizeof(struct channel_header));
107 	if (err)
108 		goto cleanup;
109 
110 	/* we had better be a CLIENT of this channel */
111 	if (channel_bytes == 0)
112 		channel_bytes = (ulong)channel->chan_hdr.size;
113 	if (uuid_le_cmp(guid, NULL_UUID_LE) == 0)
114 		guid = channel->chan_hdr.chtype;
115 
116 	memunmap(channel->mapped);
117 	if (channel->requested)
118 		release_mem_region(channel->physaddr, channel->nbytes);
119 	channel->mapped = NULL;
120 	channel->requested = request_mem_region(channel->physaddr,
121 						channel_bytes, MYDRVNAME);
122 	if (!channel->requested) {
123 		if (uuid_le_cmp(guid, spar_video_guid)) {
124 			/* Different we care about this */
125 			goto cleanup;
126 		}
127 	}
128 
129 	channel->mapped = memremap(channel->physaddr, channel_bytes,
130 			MEMREMAP_WB);
131 	if (!channel->mapped) {
132 		release_mem_region(channel->physaddr, channel_bytes);
133 		goto cleanup;
134 	}
135 
136 	channel->nbytes = channel_bytes;
137 
138 	channel->size = channel_bytes;
139 	channel->guid = guid;
140 	return channel;
141 
142 cleanup:
143 	visorchannel_destroy(channel);
144 	return NULL;
145 }
146 
147 struct visorchannel *
visorchannel_create(u64 physaddr,unsigned long channel_bytes,gfp_t gfp,uuid_le guid)148 visorchannel_create(u64 physaddr, unsigned long channel_bytes,
149 		    gfp_t gfp, uuid_le guid)
150 {
151 	return visorchannel_create_guts(physaddr, channel_bytes, gfp, 0, guid,
152 					false);
153 }
154 EXPORT_SYMBOL_GPL(visorchannel_create);
155 
156 struct visorchannel *
visorchannel_create_with_lock(u64 physaddr,unsigned long channel_bytes,gfp_t gfp,uuid_le guid)157 visorchannel_create_with_lock(u64 physaddr, unsigned long channel_bytes,
158 			      gfp_t gfp, uuid_le guid)
159 {
160 	return visorchannel_create_guts(physaddr, channel_bytes, gfp, 0, guid,
161 					true);
162 }
163 EXPORT_SYMBOL_GPL(visorchannel_create_with_lock);
164 
165 void
visorchannel_destroy(struct visorchannel * channel)166 visorchannel_destroy(struct visorchannel *channel)
167 {
168 	if (!channel)
169 		return;
170 	if (channel->mapped) {
171 		memunmap(channel->mapped);
172 		if (channel->requested)
173 			release_mem_region(channel->physaddr, channel->nbytes);
174 	}
175 	kfree(channel);
176 }
177 EXPORT_SYMBOL_GPL(visorchannel_destroy);
178 
179 u64
visorchannel_get_physaddr(struct visorchannel * channel)180 visorchannel_get_physaddr(struct visorchannel *channel)
181 {
182 	return channel->physaddr;
183 }
184 EXPORT_SYMBOL_GPL(visorchannel_get_physaddr);
185 
186 ulong
visorchannel_get_nbytes(struct visorchannel * channel)187 visorchannel_get_nbytes(struct visorchannel *channel)
188 {
189 	return channel->size;
190 }
191 EXPORT_SYMBOL_GPL(visorchannel_get_nbytes);
192 
193 char *
visorchannel_uuid_id(uuid_le * guid,char * s)194 visorchannel_uuid_id(uuid_le *guid, char *s)
195 {
196 	sprintf(s, "%pUL", guid);
197 	return s;
198 }
199 EXPORT_SYMBOL_GPL(visorchannel_uuid_id);
200 
201 char *
visorchannel_id(struct visorchannel * channel,char * s)202 visorchannel_id(struct visorchannel *channel, char *s)
203 {
204 	return visorchannel_uuid_id(&channel->guid, s);
205 }
206 EXPORT_SYMBOL_GPL(visorchannel_id);
207 
208 char *
visorchannel_zoneid(struct visorchannel * channel,char * s)209 visorchannel_zoneid(struct visorchannel *channel, char *s)
210 {
211 	return visorchannel_uuid_id(&channel->chan_hdr.zone_uuid, s);
212 }
213 EXPORT_SYMBOL_GPL(visorchannel_zoneid);
214 
215 u64
visorchannel_get_clientpartition(struct visorchannel * channel)216 visorchannel_get_clientpartition(struct visorchannel *channel)
217 {
218 	return channel->chan_hdr.partition_handle;
219 }
220 EXPORT_SYMBOL_GPL(visorchannel_get_clientpartition);
221 
222 int
visorchannel_set_clientpartition(struct visorchannel * channel,u64 partition_handle)223 visorchannel_set_clientpartition(struct visorchannel *channel,
224 				 u64 partition_handle)
225 {
226 	channel->chan_hdr.partition_handle = partition_handle;
227 	return 0;
228 }
229 EXPORT_SYMBOL_GPL(visorchannel_set_clientpartition);
230 
231 uuid_le
visorchannel_get_uuid(struct visorchannel * channel)232 visorchannel_get_uuid(struct visorchannel *channel)
233 {
234 	return channel->guid;
235 }
236 EXPORT_SYMBOL_GPL(visorchannel_get_uuid);
237 
238 int
visorchannel_read(struct visorchannel * channel,ulong offset,void * local,ulong nbytes)239 visorchannel_read(struct visorchannel *channel, ulong offset,
240 		  void *local, ulong nbytes)
241 {
242 	if (offset + nbytes > channel->nbytes)
243 		return -EIO;
244 
245 	memcpy(local, channel->mapped + offset, nbytes);
246 
247 	return 0;
248 }
249 EXPORT_SYMBOL_GPL(visorchannel_read);
250 
251 int
visorchannel_write(struct visorchannel * channel,ulong offset,void * local,ulong nbytes)252 visorchannel_write(struct visorchannel *channel, ulong offset,
253 		   void *local, ulong nbytes)
254 {
255 	size_t chdr_size = sizeof(struct channel_header);
256 	size_t copy_size;
257 
258 	if (offset + nbytes > channel->nbytes)
259 		return -EIO;
260 
261 	if (offset < chdr_size) {
262 		copy_size = min(chdr_size - offset, nbytes);
263 		memcpy(((char *)(&channel->chan_hdr)) + offset,
264 		       local, copy_size);
265 	}
266 
267 	memcpy(channel->mapped + offset, local, nbytes);
268 
269 	return 0;
270 }
271 EXPORT_SYMBOL_GPL(visorchannel_write);
272 
273 int
visorchannel_clear(struct visorchannel * channel,ulong offset,u8 ch,ulong nbytes)274 visorchannel_clear(struct visorchannel *channel, ulong offset, u8 ch,
275 		   ulong nbytes)
276 {
277 	int err;
278 	int bufsize = PAGE_SIZE;
279 	int written = 0;
280 	u8 *buf;
281 
282 	buf = (u8 *)__get_free_page(GFP_KERNEL);
283 	if (!buf)
284 		return -ENOMEM;
285 
286 	memset(buf, ch, bufsize);
287 
288 	while (nbytes > 0) {
289 		int thisbytes = bufsize;
290 
291 		if (nbytes < thisbytes)
292 			thisbytes = nbytes;
293 		err = visorchannel_write(channel, offset + written,
294 					 buf, thisbytes);
295 		if (err)
296 			goto cleanup;
297 
298 		written += thisbytes;
299 		nbytes -= thisbytes;
300 	}
301 	err = 0;
302 
303 cleanup:
304 	free_page((unsigned long)buf);
305 	return err;
306 }
307 EXPORT_SYMBOL_GPL(visorchannel_clear);
308 
309 void __iomem  *
visorchannel_get_header(struct visorchannel * channel)310 visorchannel_get_header(struct visorchannel *channel)
311 {
312 	return (void __iomem *)&channel->chan_hdr;
313 }
314 EXPORT_SYMBOL_GPL(visorchannel_get_header);
315 
316 /** Return offset of a specific SIGNAL_QUEUE_HEADER from the beginning of a
317  *  channel header
318  */
319 #define SIG_QUEUE_OFFSET(chan_hdr, q) \
320 	((chan_hdr)->ch_space_offset + \
321 	 ((q) * sizeof(struct signal_queue_header)))
322 
323 /** Return offset of a specific queue entry (data) from the beginning of a
324  *  channel header
325  */
326 #define SIG_DATA_OFFSET(chan_hdr, q, sig_hdr, slot) \
327 	(SIG_QUEUE_OFFSET(chan_hdr, q) + (sig_hdr)->sig_base_offset + \
328 	    ((slot) * (sig_hdr)->signal_size))
329 
330 /** Write the contents of a specific field within a SIGNAL_QUEUE_HEADER back
331  *  into host memory
332  */
333 #define SIG_WRITE_FIELD(channel, queue, sig_hdr, FIELD)			 \
334 	(visorchannel_write(channel,					 \
335 			    SIG_QUEUE_OFFSET(&channel->chan_hdr, queue) +\
336 			    offsetof(struct signal_queue_header, FIELD), \
337 			    &((sig_hdr)->FIELD),			 \
338 			    sizeof((sig_hdr)->FIELD)) >= 0)
339 
340 static bool
sig_read_header(struct visorchannel * channel,u32 queue,struct signal_queue_header * sig_hdr)341 sig_read_header(struct visorchannel *channel, u32 queue,
342 		struct signal_queue_header *sig_hdr)
343 {
344 	int err;
345 
346 	if (channel->chan_hdr.ch_space_offset < sizeof(struct channel_header))
347 		return false;
348 
349 	/* Read the appropriate SIGNAL_QUEUE_HEADER into local memory. */
350 	err = visorchannel_read(channel,
351 				SIG_QUEUE_OFFSET(&channel->chan_hdr, queue),
352 				sig_hdr, sizeof(struct signal_queue_header));
353 	if (err)
354 		return false;
355 
356 	return true;
357 }
358 
359 static inline bool
sig_read_data(struct visorchannel * channel,u32 queue,struct signal_queue_header * sig_hdr,u32 slot,void * data)360 sig_read_data(struct visorchannel *channel, u32 queue,
361 	      struct signal_queue_header *sig_hdr, u32 slot, void *data)
362 {
363 	int err;
364 	int signal_data_offset = SIG_DATA_OFFSET(&channel->chan_hdr, queue,
365 						 sig_hdr, slot);
366 
367 	err = visorchannel_read(channel, signal_data_offset,
368 				data, sig_hdr->signal_size);
369 	if (err)
370 		return false;
371 
372 	return true;
373 }
374 
375 static inline bool
sig_write_data(struct visorchannel * channel,u32 queue,struct signal_queue_header * sig_hdr,u32 slot,void * data)376 sig_write_data(struct visorchannel *channel, u32 queue,
377 	       struct signal_queue_header *sig_hdr, u32 slot, void *data)
378 {
379 	int err;
380 	int signal_data_offset = SIG_DATA_OFFSET(&channel->chan_hdr, queue,
381 						 sig_hdr, slot);
382 
383 	err = visorchannel_write(channel, signal_data_offset,
384 				 data, sig_hdr->signal_size);
385 	if (err)
386 		return false;
387 
388 	return true;
389 }
390 
391 static bool
signalremove_inner(struct visorchannel * channel,u32 queue,void * msg)392 signalremove_inner(struct visorchannel *channel, u32 queue, void *msg)
393 {
394 	struct signal_queue_header sig_hdr;
395 
396 	if (!sig_read_header(channel, queue, &sig_hdr))
397 		return false;
398 	if (sig_hdr.head == sig_hdr.tail)
399 		return false;	/* no signals to remove */
400 
401 	sig_hdr.tail = (sig_hdr.tail + 1) % sig_hdr.max_slots;
402 	if (!sig_read_data(channel, queue, &sig_hdr, sig_hdr.tail, msg))
403 		return false;
404 	sig_hdr.num_received++;
405 
406 	/* For each data field in SIGNAL_QUEUE_HEADER that was modified,
407 	 * update host memory.
408 	 */
409 	mb(); /* required for channel synch */
410 	if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, tail))
411 		return false;
412 	if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_received))
413 		return false;
414 	return true;
415 }
416 
417 bool
visorchannel_signalremove(struct visorchannel * channel,u32 queue,void * msg)418 visorchannel_signalremove(struct visorchannel *channel, u32 queue, void *msg)
419 {
420 	bool rc;
421 	unsigned long flags;
422 
423 	if (channel->needs_lock) {
424 		spin_lock_irqsave(&channel->remove_lock, flags);
425 		rc = signalremove_inner(channel, queue, msg);
426 		spin_unlock_irqrestore(&channel->remove_lock, flags);
427 	} else {
428 		rc = signalremove_inner(channel, queue, msg);
429 	}
430 
431 	return rc;
432 }
433 EXPORT_SYMBOL_GPL(visorchannel_signalremove);
434 
435 bool
visorchannel_signalempty(struct visorchannel * channel,u32 queue)436 visorchannel_signalempty(struct visorchannel *channel, u32 queue)
437 {
438 	unsigned long flags = 0;
439 	struct signal_queue_header sig_hdr;
440 	bool rc = false;
441 
442 	if (channel->needs_lock)
443 		spin_lock_irqsave(&channel->remove_lock, flags);
444 
445 	if (!sig_read_header(channel, queue, &sig_hdr))
446 		rc = true;
447 	if (sig_hdr.head == sig_hdr.tail)
448 		rc = true;
449 	if (channel->needs_lock)
450 		spin_unlock_irqrestore(&channel->remove_lock, flags);
451 
452 	return rc;
453 }
454 EXPORT_SYMBOL_GPL(visorchannel_signalempty);
455 
456 static bool
signalinsert_inner(struct visorchannel * channel,u32 queue,void * msg)457 signalinsert_inner(struct visorchannel *channel, u32 queue, void *msg)
458 {
459 	struct signal_queue_header sig_hdr;
460 
461 	if (!sig_read_header(channel, queue, &sig_hdr))
462 		return false;
463 
464 	sig_hdr.head = ((sig_hdr.head + 1) % sig_hdr.max_slots);
465 	if (sig_hdr.head == sig_hdr.tail) {
466 		sig_hdr.num_overflows++;
467 		visorchannel_write(channel,
468 				   SIG_QUEUE_OFFSET(&channel->chan_hdr, queue) +
469 				   offsetof(struct signal_queue_header,
470 					    num_overflows),
471 				   &sig_hdr.num_overflows,
472 				   sizeof(sig_hdr.num_overflows));
473 		return false;
474 	}
475 
476 	if (!sig_write_data(channel, queue, &sig_hdr, sig_hdr.head, msg))
477 		return false;
478 
479 	sig_hdr.num_sent++;
480 
481 	/* For each data field in SIGNAL_QUEUE_HEADER that was modified,
482 	 * update host memory.
483 	 */
484 	mb(); /* required for channel synch */
485 	if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, head))
486 		return false;
487 	if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_sent))
488 		return false;
489 
490 	return true;
491 }
492 
493 bool
visorchannel_signalinsert(struct visorchannel * channel,u32 queue,void * msg)494 visorchannel_signalinsert(struct visorchannel *channel, u32 queue, void *msg)
495 {
496 	bool rc;
497 	unsigned long flags;
498 
499 	if (channel->needs_lock) {
500 		spin_lock_irqsave(&channel->insert_lock, flags);
501 		rc = signalinsert_inner(channel, queue, msg);
502 		spin_unlock_irqrestore(&channel->insert_lock, flags);
503 	} else {
504 		rc = signalinsert_inner(channel, queue, msg);
505 	}
506 
507 	return rc;
508 }
509 EXPORT_SYMBOL_GPL(visorchannel_signalinsert);
510 
511 int
visorchannel_signalqueue_slots_avail(struct visorchannel * channel,u32 queue)512 visorchannel_signalqueue_slots_avail(struct visorchannel *channel, u32 queue)
513 {
514 	struct signal_queue_header sig_hdr;
515 	u32 slots_avail, slots_used;
516 	u32 head, tail;
517 
518 	if (!sig_read_header(channel, queue, &sig_hdr))
519 		return 0;
520 	head = sig_hdr.head;
521 	tail = sig_hdr.tail;
522 	if (head < tail)
523 		head = head + sig_hdr.max_slots;
524 	slots_used = (head - tail);
525 	slots_avail = sig_hdr.max_signals - slots_used;
526 	return (int)slots_avail;
527 }
528 EXPORT_SYMBOL_GPL(visorchannel_signalqueue_slots_avail);
529 
530 int
visorchannel_signalqueue_max_slots(struct visorchannel * channel,u32 queue)531 visorchannel_signalqueue_max_slots(struct visorchannel *channel, u32 queue)
532 {
533 	struct signal_queue_header sig_hdr;
534 
535 	if (!sig_read_header(channel, queue, &sig_hdr))
536 		return 0;
537 	return (int)sig_hdr.max_signals;
538 }
539 EXPORT_SYMBOL_GPL(visorchannel_signalqueue_max_slots);
540 
541 static void
sigqueue_debug(struct signal_queue_header * q,int which,struct seq_file * seq)542 sigqueue_debug(struct signal_queue_header *q, int which, struct seq_file *seq)
543 {
544 	seq_printf(seq, "Signal Queue #%d\n", which);
545 	seq_printf(seq, "   VersionId          = %lu\n", (ulong)q->version);
546 	seq_printf(seq, "   Type               = %lu\n", (ulong)q->chtype);
547 	seq_printf(seq, "   oSignalBase        = %llu\n",
548 		   (long long)q->sig_base_offset);
549 	seq_printf(seq, "   SignalSize         = %lu\n", (ulong)q->signal_size);
550 	seq_printf(seq, "   MaxSignalSlots     = %lu\n",
551 		   (ulong)q->max_slots);
552 	seq_printf(seq, "   MaxSignals         = %lu\n", (ulong)q->max_signals);
553 	seq_printf(seq, "   FeatureFlags       = %-16.16Lx\n",
554 		   (long long)q->features);
555 	seq_printf(seq, "   NumSignalsSent     = %llu\n",
556 		   (long long)q->num_sent);
557 	seq_printf(seq, "   NumSignalsReceived = %llu\n",
558 		   (long long)q->num_received);
559 	seq_printf(seq, "   NumOverflows       = %llu\n",
560 		   (long long)q->num_overflows);
561 	seq_printf(seq, "   Head               = %lu\n", (ulong)q->head);
562 	seq_printf(seq, "   Tail               = %lu\n", (ulong)q->tail);
563 }
564 
565 void
visorchannel_debug(struct visorchannel * channel,int num_queues,struct seq_file * seq,u32 off)566 visorchannel_debug(struct visorchannel *channel, int num_queues,
567 		   struct seq_file *seq, u32 off)
568 {
569 	u64 addr = 0;
570 	ulong nbytes = 0, nbytes_region = 0;
571 	struct channel_header hdr;
572 	struct channel_header *phdr = &hdr;
573 	int i = 0;
574 	int errcode = 0;
575 
576 	if (!channel)
577 		return;
578 
579 	addr = visorchannel_get_physaddr(channel);
580 	nbytes_region = visorchannel_get_nbytes(channel);
581 	errcode = visorchannel_read(channel, off,
582 				    phdr, sizeof(struct channel_header));
583 	if (errcode < 0) {
584 		seq_printf(seq,
585 			   "Read of channel header failed with errcode=%d)\n",
586 			   errcode);
587 		if (off == 0) {
588 			phdr = &channel->chan_hdr;
589 			seq_puts(seq, "(following data may be stale)\n");
590 		} else {
591 			return;
592 		}
593 	}
594 	nbytes = (ulong)(phdr->size);
595 	seq_printf(seq, "--- Begin channel @0x%-16.16Lx for 0x%lx bytes (region=0x%lx bytes) ---\n",
596 		   addr + off, nbytes, nbytes_region);
597 	seq_printf(seq, "Type            = %pUL\n", &phdr->chtype);
598 	seq_printf(seq, "ZoneGuid        = %pUL\n", &phdr->zone_uuid);
599 	seq_printf(seq, "Signature       = 0x%-16.16Lx\n",
600 		   (long long)phdr->signature);
601 	seq_printf(seq, "LegacyState     = %lu\n", (ulong)phdr->legacy_state);
602 	seq_printf(seq, "SrvState        = %lu\n", (ulong)phdr->srv_state);
603 	seq_printf(seq, "CliStateBoot    = %lu\n", (ulong)phdr->cli_state_boot);
604 	seq_printf(seq, "CliStateOS      = %lu\n", (ulong)phdr->cli_state_os);
605 	seq_printf(seq, "HeaderSize      = %lu\n", (ulong)phdr->header_size);
606 	seq_printf(seq, "Size            = %llu\n", (long long)phdr->size);
607 	seq_printf(seq, "Features        = 0x%-16.16llx\n",
608 		   (long long)phdr->features);
609 	seq_printf(seq, "PartitionHandle = 0x%-16.16llx\n",
610 		   (long long)phdr->partition_handle);
611 	seq_printf(seq, "Handle          = 0x%-16.16llx\n",
612 		   (long long)phdr->handle);
613 	seq_printf(seq, "VersionId       = %lu\n", (ulong)phdr->version_id);
614 	seq_printf(seq, "oChannelSpace   = %llu\n",
615 		   (long long)phdr->ch_space_offset);
616 	if ((phdr->ch_space_offset == 0) || (errcode < 0))
617 		;
618 	else
619 		for (i = 0; i < num_queues; i++) {
620 			struct signal_queue_header q;
621 
622 			errcode = visorchannel_read(channel,
623 						    off +
624 						    phdr->ch_space_offset +
625 						    (i * sizeof(q)),
626 						    &q, sizeof(q));
627 			if (errcode < 0) {
628 				seq_printf(seq,
629 					   "failed to read signal queue #%d from channel @0x%-16.16Lx errcode=%d\n",
630 					   i, addr, errcode);
631 				continue;
632 			}
633 			sigqueue_debug(&q, i, seq);
634 		}
635 	seq_printf(seq, "--- End   channel @0x%-16.16Lx for 0x%lx bytes ---\n",
636 		   addr + off, nbytes);
637 }
638 EXPORT_SYMBOL_GPL(visorchannel_debug);
639