1 /* Copyright (C) 2010 - 2013 UNISYS CORPORATION
2  * All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or (at
7  * your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
12  * NON INFRINGEMENT.  See the GNU General Public License for more
13  * details.
14  */
15 
16 #ifndef __CHANNEL_H__
17 #define __CHANNEL_H__
18 
19 #include <linux/types.h>
20 #include <linux/io.h>
21 #include <linux/uuid.h>
22 
23 /*
24 * Whenever this file is changed a corresponding change must be made in
25 * the Console/ServicePart/visordiag_early/supervisor_channel.h file
26 * which is needed for Linux kernel compiles. These two files must be
27 * in sync.
28 */
29 
30 /* define the following to prevent include nesting in kernel header
31  * files of similar abbreviated content
32  */
33 #define __SUPERVISOR_CHANNEL_H__
34 
35 #define SIGNATURE_16(A, B) ((A) | (B<<8))
36 #define SIGNATURE_32(A, B, C, D) \
37 	(SIGNATURE_16(A, B) | (SIGNATURE_16(C, D) << 16))
38 #define SIGNATURE_64(A, B, C, D, E, F, G, H) \
39 	(SIGNATURE_32(A, B, C, D) | ((u64)(SIGNATURE_32(E, F, G, H)) << 32))
40 
41 #ifndef lengthof
42 #define lengthof(TYPE, MEMBER) (sizeof(((TYPE *)0)->MEMBER))
43 #endif
44 #ifndef COVERQ
45 #define COVERQ(v, d)  (((v)+(d)-1) / (d))
46 #endif
47 #ifndef COVER
48 #define COVER(v, d)   ((d)*COVERQ(v, d))
49 #endif
50 
51 #define ULTRA_CHANNEL_PROTOCOL_SIGNATURE  SIGNATURE_32('E', 'C', 'N', 'L')
52 
53 enum channel_serverstate {
54 	CHANNELSRV_UNINITIALIZED = 0,	/* channel is in an undefined state */
55 	CHANNELSRV_READY = 1	/* channel has been initialized by server */
56 };
57 
58 enum channel_clientstate {
59 	CHANNELCLI_DETACHED = 0,
60 	CHANNELCLI_DISABLED = 1,	/* client can see channel but is NOT
61 					 * allowed to use it unless given TBD
62 					 * explicit request (should actually be
63 					 * < DETACHED) */
64 	CHANNELCLI_ATTACHING = 2,	/* legacy EFI client request
65 					 * for EFI server to attach */
66 	CHANNELCLI_ATTACHED = 3,	/* idle, but client may want
67 					 * to use channel any time */
68 	CHANNELCLI_BUSY = 4,	/* client either wants to use or is
69 				 * using channel */
70 	CHANNELCLI_OWNED = 5	/* "no worries" state - client can
71 				 * access channel anytime */
72 };
73 
74 static inline const u8 *
ULTRA_CHANNELCLI_STRING(u32 v)75 ULTRA_CHANNELCLI_STRING(u32 v)
76 {
77 	switch (v) {
78 	case CHANNELCLI_DETACHED:
79 		return (const u8 *)("DETACHED");
80 	case CHANNELCLI_DISABLED:
81 		return (const u8 *)("DISABLED");
82 	case CHANNELCLI_ATTACHING:
83 		return (const u8 *)("ATTACHING");
84 	case CHANNELCLI_ATTACHED:
85 		return (const u8 *)("ATTACHED");
86 	case CHANNELCLI_BUSY:
87 		return (const u8 *)("BUSY");
88 	case CHANNELCLI_OWNED:
89 		return (const u8 *)("OWNED");
90 	default:
91 		break;
92 	}
93 	return (const u8 *)("?");
94 }
95 
96 #define SPAR_CHANNEL_SERVER_READY(ch) \
97 	(readl(&(ch)->srv_state) == CHANNELSRV_READY)
98 
99 #define ULTRA_VALID_CHANNELCLI_TRANSITION(o, n)				\
100 	(((((o) == CHANNELCLI_DETACHED) && ((n) == CHANNELCLI_DISABLED)) || \
101 	  (((o) == CHANNELCLI_ATTACHING) && ((n) == CHANNELCLI_DISABLED)) || \
102 	  (((o) == CHANNELCLI_ATTACHED) && ((n) == CHANNELCLI_DISABLED)) || \
103 	  (((o) == CHANNELCLI_ATTACHING) && ((n) == CHANNELCLI_DETACHED)) || \
104 	  (((o) == CHANNELCLI_ATTACHED) && ((n) == CHANNELCLI_DETACHED)) || \
105 	  (((o) == CHANNELCLI_DETACHED) && ((n) == CHANNELCLI_ATTACHING)) || \
106 	  (((o) == CHANNELCLI_ATTACHING) && ((n) == CHANNELCLI_ATTACHED)) || \
107 	  (((o) == CHANNELCLI_DETACHED) && ((n) == CHANNELCLI_ATTACHED)) || \
108 	  (((o) == CHANNELCLI_BUSY) && ((n) == CHANNELCLI_ATTACHED)) ||	\
109 	  (((o) == CHANNELCLI_ATTACHED) && ((n) == CHANNELCLI_BUSY)) ||	\
110 	  (((o) == CHANNELCLI_DETACHED) && ((n) == CHANNELCLI_OWNED)) || \
111 	  (((o) == CHANNELCLI_DISABLED) && ((n) == CHANNELCLI_OWNED)) || \
112 	  (((o) == CHANNELCLI_ATTACHING) && ((n) == CHANNELCLI_OWNED)) || \
113 	  (((o) == CHANNELCLI_ATTACHED) && ((n) == CHANNELCLI_OWNED)) || \
114 	  (((o) == CHANNELCLI_BUSY) && ((n) == CHANNELCLI_OWNED)) || (0)) \
115 	 ? (1) : (0))
116 
117 #define SPAR_CHANNEL_CLIENT_CHK_TRANSITION(old, new, id, log,	\
118 					    file, line)			\
119 	do {								\
120 		if (!ULTRA_VALID_CHANNELCLI_TRANSITION(old, new))	\
121 			pr_info("%s Channel StateTransition INVALID! (%s) %s(%d)-->%s(%d) @%s:%d\n", \
122 				id, "CliState<x>",		\
123 				ULTRA_CHANNELCLI_STRING(old),	\
124 				old,				\
125 				ULTRA_CHANNELCLI_STRING(new),	\
126 				new,				\
127 				pathname_last_n_nodes((u8 *)file, 4), \
128 				line);				\
129 	} while (0)
130 
131 #define SPAR_CHANNEL_CLIENT_TRANSITION(ch, id, newstate, log)		\
132 	do {								\
133 		SPAR_CHANNEL_CLIENT_CHK_TRANSITION(			\
134 			readl(&(((struct channel_header __iomem *)\
135 				 (ch))->cli_state_os)),		\
136 			newstate, id, log, __FILE__, __LINE__);		\
137 			pr_info("%s Channel StateTransition (%s) %s(%d)-->%s(%d) @%s:%d\n", \
138 				id, "CliStateOS",			\
139 				ULTRA_CHANNELCLI_STRING( \
140 				      readl(&((struct channel_header __iomem *)\
141 					      (ch))->cli_state_os)),	\
142 				readl(&((struct channel_header __iomem *)\
143 				      (ch))->cli_state_os),		\
144 				ULTRA_CHANNELCLI_STRING(newstate),	\
145 				newstate,				\
146 				pathname_last_n_nodes(__FILE__, 4), __LINE__); \
147 		writel(newstate, &((struct channel_header __iomem *)\
148 				   (ch))->cli_state_os);		\
149 		mb(); /* required for channel synch */			\
150 	} while (0)
151 
152 /* Values for ULTRA_CHANNEL_PROTOCOL.CliErrorBoot: */
153 /* throttling invalid boot channel statetransition error due to client
154  * disabled */
155 #define ULTRA_CLIERRORBOOT_THROTTLEMSG_DISABLED    0x01
156 
157 /* throttling invalid boot channel statetransition error due to client
158  * not attached */
159 #define ULTRA_CLIERRORBOOT_THROTTLEMSG_NOTATTACHED 0x02
160 
161 /* throttling invalid boot channel statetransition error due to busy channel */
162 #define ULTRA_CLIERRORBOOT_THROTTLEMSG_BUSY        0x04
163 
164 /* Values for ULTRA_CHANNEL_PROTOCOL.CliErrorOS: */
165 /* throttling invalid guest OS channel statetransition error due to
166  * client disabled */
167 #define ULTRA_CLIERROROS_THROTTLEMSG_DISABLED      0x01
168 
169 /* throttling invalid guest OS channel statetransition error due to
170  * client not attached */
171 #define ULTRA_CLIERROROS_THROTTLEMSG_NOTATTACHED   0x02
172 
173 /* throttling invalid guest OS channel statetransition error due to
174  * busy channel */
175 #define ULTRA_CLIERROROS_THROTTLEMSG_BUSY          0x04
176 
177 /* Values for ULTRA_CHANNEL_PROTOCOL.Features: This define exists so
178 * that windows guest can look at the FeatureFlags in the io channel,
179 * and configure the windows driver to use interrupts or not based on
180 * this setting.  This flag is set in uislib after the
181 * ULTRA_VHBA_init_channel is called.  All feature bits for all
182 * channels should be defined here.  The io channel feature bits are
183 * defined right here */
184 #define ULTRA_IO_DRIVER_ENABLES_INTS (0x1ULL << 1)
185 #define ULTRA_IO_CHANNEL_IS_POLLING (0x1ULL << 3)
186 #define ULTRA_IO_IOVM_IS_OK_WITH_DRIVER_DISABLING_INTS (0x1ULL << 4)
187 #define ULTRA_IO_DRIVER_DISABLES_INTS (0x1ULL << 5)
188 #define ULTRA_IO_DRIVER_SUPPORTS_ENHANCED_RCVBUF_CHECKING (0x1ULL << 6)
189 
190 #pragma pack(push, 1)		/* both GCC and VC now allow this pragma */
191 /* Common Channel Header */
192 struct channel_header {
193 	u64 signature;		/* Signature */
194 	u32 legacy_state;	/* DEPRECATED - being replaced by */
195 	/* /              SrvState, CliStateBoot, and CliStateOS below */
196 	u32 header_size;	/* sizeof(struct channel_header) */
197 	u64 size;		/* Total size of this channel in bytes */
198 	u64 features;		/* Flags to modify behavior */
199 	uuid_le chtype;		/* Channel type: data, bus, control, etc. */
200 	u64 partition_handle;	/* ID of guest partition */
201 	u64 handle;		/* Device number of this channel in client */
202 	u64 ch_space_offset;	/* Offset in bytes to channel specific area */
203 	u32 version_id;		/* struct channel_header Version ID */
204 	u32 partition_index;	/* Index of guest partition */
205 	uuid_le zone_uuid;	/* Guid of Channel's zone */
206 	u32 cli_str_offset;	/* offset from channel header to
207 				 * nul-terminated ClientString (0 if
208 				 * ClientString not present) */
209 	u32 cli_state_boot;	/* CHANNEL_CLIENTSTATE of pre-boot
210 				 * EFI client of this channel */
211 	u32 cmd_state_cli;	/* CHANNEL_COMMANDSTATE (overloaded in
212 				 * Windows drivers, see ServerStateUp,
213 				 * ServerStateDown, etc) */
214 	u32 cli_state_os;	/* CHANNEL_CLIENTSTATE of Guest OS
215 				 * client of this channel */
216 	u32 ch_characteristic;	/* CHANNEL_CHARACTERISTIC_<xxx> */
217 	u32 cmd_state_srv;	/* CHANNEL_COMMANDSTATE (overloaded in
218 				 * Windows drivers, see ServerStateUp,
219 				 * ServerStateDown, etc) */
220 	u32 srv_state;		/* CHANNEL_SERVERSTATE */
221 	u8 cli_error_boot;	/* bits to indicate err states for
222 				 * boot clients, so err messages can
223 				 * be throttled */
224 	u8 cli_error_os;	/* bits to indicate err states for OS
225 				 * clients, so err messages can be
226 				 * throttled */
227 	u8 filler[1];		/* Pad out to 128 byte cacheline */
228 	/* Please add all new single-byte values below here */
229 	u8 recover_channel;
230 };
231 
232 #define ULTRA_CHANNEL_ENABLE_INTS (0x1ULL << 0)
233 
234 /* Subheader for the Signal Type variation of the Common Channel */
235 struct signal_queue_header {
236 	/* 1st cache line */
237 	u32 version;		/* SIGNAL_QUEUE_HEADER Version ID */
238 	u32 chtype;		/* Queue type: storage, network */
239 	u64 size;		/* Total size of this queue in bytes */
240 	u64 sig_base_offset;	/* Offset to signal queue area */
241 	u64 features;		/* Flags to modify behavior */
242 	u64 num_sent;		/* Total # of signals placed in this queue */
243 	u64 num_overflows;	/* Total # of inserts failed due to
244 				 * full queue */
245 	u32 signal_size;	/* Total size of a signal for this queue */
246 	u32 max_slots;		/* Max # of slots in queue, 1 slot is
247 				 * always empty */
248 	u32 max_signals;	/* Max # of signals in queue
249 				 * (MaxSignalSlots-1) */
250 	u32 head;		/* Queue head signal # */
251 	/* 2nd cache line */
252 	u64 num_received;	/* Total # of signals removed from this queue */
253 	u32 tail;		/* Queue tail signal # (on separate
254 				 * cache line) */
255 	u32 reserved1;		/* Reserved field */
256 	u64 reserved2;		/* Reserved field */
257 	u64 client_queue;
258 	u64 num_irq_received;	/* Total # of Interrupts received.  This
259 					 * is incremented by the ISR in the
260 					 * guest windows driver */
261 	u64 num_empty;		/* Number of times that visor_signal_remove
262 				 * is called and returned Empty
263 				 * Status. */
264 	u32 errorflags;		/* Error bits set during SignalReinit
265 				 * to denote trouble with client's
266 				 * fields */
267 	u8 filler[12];		/* Pad out to 64 byte cacheline */
268 };
269 
270 #pragma pack(pop)
271 
272 #define spar_signal_init(chan, QHDRFLD, QDATAFLD, QDATATYPE, ver, typ)	\
273 	do {								\
274 		memset(&chan->QHDRFLD, 0, sizeof(chan->QHDRFLD));	\
275 		chan->QHDRFLD.version = ver;				\
276 		chan->QHDRFLD.chtype = typ;				\
277 		chan->QHDRFLD.size = sizeof(chan->QDATAFLD);		\
278 		chan->QHDRFLD.signal_size = sizeof(QDATATYPE);		\
279 		chan->QHDRFLD.sig_base_offset = (u64)(chan->QDATAFLD)-	\
280 			(u64)(&chan->QHDRFLD);				\
281 		chan->QHDRFLD.max_slots =				\
282 			sizeof(chan->QDATAFLD)/sizeof(QDATATYPE);	\
283 		chan->QHDRFLD.max_signals = chan->QHDRFLD.max_slots-1;	\
284 	} while (0)
285 
286 /* Generic function useful for validating any type of channel when it is
287  * received by the client that will be accessing the channel.
288  * Note that <logCtx> is only needed for callers in the EFI environment, and
289  * is used to pass the EFI_DIAG_CAPTURE_PROTOCOL needed to log messages.
290  */
291 static inline int
spar_check_channel_client(void __iomem * ch,uuid_le expected_uuid,char * chname,u64 expected_min_bytes,u32 expected_version,u64 expected_signature)292 spar_check_channel_client(void __iomem *ch,
293 			  uuid_le expected_uuid,
294 			  char *chname,
295 			  u64 expected_min_bytes,
296 			  u32 expected_version,
297 			  u64 expected_signature)
298 {
299 	if (uuid_le_cmp(expected_uuid, NULL_UUID_LE) != 0) {
300 		uuid_le guid;
301 
302 		memcpy_fromio(&guid,
303 			      &((struct channel_header __iomem *)(ch))->chtype,
304 			      sizeof(guid));
305 		/* caller wants us to verify type GUID */
306 		if (uuid_le_cmp(guid, expected_uuid) != 0) {
307 			pr_err("Channel mismatch on channel=%s(%pUL) field=type expected=%pUL actual=%pUL\n",
308 			       chname, &expected_uuid,
309 			       &expected_uuid, &guid);
310 			return 0;
311 		}
312 	}
313 	if (expected_min_bytes > 0) {	/* caller wants us to verify
314 					 * channel size */
315 		unsigned long long bytes =
316 				readq(&((struct channel_header __iomem *)
317 					(ch))->size);
318 		if (bytes < expected_min_bytes) {
319 			pr_err("Channel mismatch on channel=%s(%pUL) field=size expected=0x%-8.8Lx actual=0x%-8.8Lx\n",
320 			       chname, &expected_uuid,
321 			       (unsigned long long)expected_min_bytes, bytes);
322 			return 0;
323 		}
324 	}
325 	if (expected_version > 0) {	/* caller wants us to verify
326 					 * channel version */
327 		unsigned long ver = readl(&((struct channel_header __iomem *)
328 				    (ch))->version_id);
329 		if (ver != expected_version) {
330 			pr_err("Channel mismatch on channel=%s(%pUL) field=version expected=0x%-8.8lx actual=0x%-8.8lx\n",
331 			       chname, &expected_uuid,
332 			       (unsigned long)expected_version, ver);
333 			return 0;
334 		}
335 	}
336 	if (expected_signature > 0) {	/* caller wants us to verify
337 					 * channel signature */
338 		unsigned long long sig =
339 				readq(&((struct channel_header __iomem *)
340 					(ch))->signature);
341 		if (sig != expected_signature) {
342 			pr_err("Channel mismatch on channel=%s(%pUL) field=signature expected=0x%-8.8llx actual=0x%-8.8llx\n",
343 			       chname, &expected_uuid,
344 			       expected_signature, sig);
345 			return 0;
346 		}
347 	}
348 	return 1;
349 }
350 
351 /* Generic function useful for validating any type of channel when it is about
352  * to be initialized by the server of the channel.
353  * Note that <logCtx> is only needed for callers in the EFI environment, and
354  * is used to pass the EFI_DIAG_CAPTURE_PROTOCOL needed to log messages.
355  */
spar_check_channel_server(uuid_le typeuuid,char * name,u64 expected_min_bytes,u64 actual_bytes)356 static inline int spar_check_channel_server(uuid_le typeuuid, char *name,
357 					    u64 expected_min_bytes,
358 					    u64 actual_bytes)
359 {
360 	if (expected_min_bytes > 0)	/* caller wants us to verify
361 					 * channel size */
362 		if (actual_bytes < expected_min_bytes) {
363 			pr_err("Channel mismatch on channel=%s(%pUL) field=size expected=0x%-8.8llx actual=0x%-8.8llx\n",
364 			       name, &typeuuid, expected_min_bytes,
365 			       actual_bytes);
366 			return 0;
367 		}
368 	return 1;
369 }
370 
371 /* Given a file pathname <s> (with '/' or '\' separating directory nodes),
372  * returns a pointer to the beginning of a node within that pathname such
373  * that the number of nodes from that pointer to the end of the string is
374  * NOT more than <n>.  Note that if the pathname has less than <n> nodes
375  * in it, the return pointer will be to the beginning of the string.
376  */
377 static inline u8 *
pathname_last_n_nodes(u8 * s,unsigned int n)378 pathname_last_n_nodes(u8 *s, unsigned int n)
379 {
380 	u8 *p = s;
381 	unsigned int node_count = 0;
382 
383 	while (*p != '\0') {
384 		if ((*p == '/') || (*p == '\\'))
385 			node_count++;
386 		p++;
387 	}
388 	if (node_count <= n)
389 		return s;
390 	while (n > 0) {
391 		p--;
392 		if (p == s)
393 			break;	/* should never happen, unless someone
394 				 * is changing the string while we are
395 				 * looking at it!! */
396 		if ((*p == '/') || (*p == '\\'))
397 			n--;
398 	}
399 	return p + 1;
400 }
401 
402 static inline int
spar_channel_client_acquire_os(void __iomem * ch,u8 * id)403 spar_channel_client_acquire_os(void __iomem *ch, u8 *id)
404 {
405 	struct channel_header __iomem *hdr = ch;
406 
407 	if (readl(&hdr->cli_state_os) == CHANNELCLI_DISABLED) {
408 		if ((readb(&hdr->cli_error_os)
409 		     & ULTRA_CLIERROROS_THROTTLEMSG_DISABLED) == 0) {
410 			/* we are NOT throttling this message */
411 			writeb(readb(&hdr->cli_error_os) |
412 			       ULTRA_CLIERROROS_THROTTLEMSG_DISABLED,
413 			       &hdr->cli_error_os);
414 			/* throttle until acquire successful */
415 
416 			pr_info("%s Channel StateTransition INVALID! - acquire failed because OS client DISABLED\n",
417 				id);
418 		}
419 		return 0;
420 	}
421 	if ((readl(&hdr->cli_state_os) != CHANNELCLI_OWNED) &&
422 	    (readl(&hdr->cli_state_boot) == CHANNELCLI_DISABLED)) {
423 		/* Our competitor is DISABLED, so we can transition to OWNED */
424 		pr_info("%s Channel StateTransition (%s) %s(%d)-->%s(%d)\n",
425 			id, "cli_state_os",
426 			ULTRA_CHANNELCLI_STRING(readl(&hdr->cli_state_os)),
427 			readl(&hdr->cli_state_os),
428 			ULTRA_CHANNELCLI_STRING(CHANNELCLI_OWNED),
429 			CHANNELCLI_OWNED);
430 		writel(CHANNELCLI_OWNED, &hdr->cli_state_os);
431 		mb(); /* required for channel synch */
432 	}
433 	if (readl(&hdr->cli_state_os) == CHANNELCLI_OWNED) {
434 		if (readb(&hdr->cli_error_os) != 0) {
435 			/* we are in an error msg throttling state;
436 			 * come out of it */
437 			pr_info("%s Channel OS client acquire now successful\n",
438 				id);
439 			writeb(0, &hdr->cli_error_os);
440 		}
441 		return 1;
442 	}
443 
444 	/* We have to do it the "hard way".  We transition to BUSY,
445 	* and can use the channel iff our competitor has not also
446 	* transitioned to BUSY. */
447 	if (readl(&hdr->cli_state_os) != CHANNELCLI_ATTACHED) {
448 		if ((readb(&hdr->cli_error_os)
449 		     & ULTRA_CLIERROROS_THROTTLEMSG_NOTATTACHED) == 0) {
450 			/* we are NOT throttling this message */
451 			writeb(readb(&hdr->cli_error_os) |
452 			       ULTRA_CLIERROROS_THROTTLEMSG_NOTATTACHED,
453 			       &hdr->cli_error_os);
454 			/* throttle until acquire successful */
455 			pr_info("%s Channel StateTransition INVALID! - acquire failed because OS client NOT ATTACHED (state=%s(%d))\n",
456 				id, ULTRA_CHANNELCLI_STRING(
457 						readl(&hdr->cli_state_os)),
458 				readl(&hdr->cli_state_os));
459 		}
460 		return 0;
461 	}
462 	writel(CHANNELCLI_BUSY, &hdr->cli_state_os);
463 	mb(); /* required for channel synch */
464 	if (readl(&hdr->cli_state_boot) == CHANNELCLI_BUSY) {
465 		if ((readb(&hdr->cli_error_os)
466 		     & ULTRA_CLIERROROS_THROTTLEMSG_BUSY) == 0) {
467 			/* we are NOT throttling this message */
468 			writeb(readb(&hdr->cli_error_os) |
469 			       ULTRA_CLIERROROS_THROTTLEMSG_BUSY,
470 			       &hdr->cli_error_os);
471 			/* throttle until acquire successful */
472 			pr_info("%s Channel StateTransition failed - host OS acquire failed because boot BUSY\n",
473 				id);
474 		}
475 		/* reset busy */
476 		writel(CHANNELCLI_ATTACHED, &hdr->cli_state_os);
477 		mb(); /* required for channel synch */
478 		return 0;
479 	}
480 	if (readb(&hdr->cli_error_os) != 0) {
481 		/* we are in an error msg throttling state; come out of it */
482 		pr_info("%s Channel OS client acquire now successful\n", id);
483 		writeb(0, &hdr->cli_error_os);
484 	}
485 	return 1;
486 }
487 
488 static inline void
spar_channel_client_release_os(void __iomem * ch,u8 * id)489 spar_channel_client_release_os(void __iomem *ch, u8 *id)
490 {
491 	struct channel_header __iomem *hdr = ch;
492 
493 	if (readb(&hdr->cli_error_os) != 0) {
494 		/* we are in an error msg throttling state; come out of it */
495 		pr_info("%s Channel OS client error state cleared\n", id);
496 		writeb(0, &hdr->cli_error_os);
497 	}
498 	if (readl(&hdr->cli_state_os) == CHANNELCLI_OWNED)
499 		return;
500 	if (readl(&hdr->cli_state_os) != CHANNELCLI_BUSY) {
501 		pr_info("%s Channel StateTransition INVALID! - release failed because OS client NOT BUSY (state=%s(%d))\n",
502 			id, ULTRA_CHANNELCLI_STRING(
503 					readl(&hdr->cli_state_os)),
504 			readl(&hdr->cli_state_os));
505 		/* return; */
506 	}
507 	writel(CHANNELCLI_ATTACHED, &hdr->cli_state_os); /* release busy */
508 }
509 
510 /*
511 * Routine Description:
512 * Tries to insert the prebuilt signal pointed to by pSignal into the nth
513 * Queue of the Channel pointed to by pChannel
514 *
515 * Parameters:
516 * pChannel: (IN) points to the IO Channel
517 * Queue: (IN) nth Queue of the IO Channel
518 * pSignal: (IN) pointer to the signal
519 *
520 * Assumptions:
521 * - pChannel, Queue and pSignal are valid.
522 * - If insertion fails due to a full queue, the caller will determine the
523 * retry policy (e.g. wait & try again, report an error, etc.).
524 *
525 * Return value: 1 if the insertion succeeds, 0 if the queue was
526 * full.
527 */
528 
529 unsigned char spar_signal_insert(struct channel_header __iomem *ch, u32 queue,
530 				 void *sig);
531 
532 /*
533 * Routine Description:
534 * Removes one signal from Channel pChannel's nth Queue at the
535 * time of the call and copies it into the memory pointed to by
536 * pSignal.
537 *
538 * Parameters:
539 * pChannel: (IN) points to the IO Channel
540 * Queue: (IN) nth Queue of the IO Channel
541 * pSignal: (IN) pointer to where the signals are to be copied
542 *
543 * Assumptions:
544 * - pChannel and Queue are valid.
545 * - pSignal points to a memory area large enough to hold queue's SignalSize
546 *
547 * Return value: 1 if the removal succeeds, 0 if the queue was
548 * empty.
549 */
550 
551 unsigned char spar_signal_remove(struct channel_header __iomem *ch, u32 queue,
552 				 void *sig);
553 
554 /*
555 * Routine Description:
556 * Removes all signals present in Channel pChannel's nth Queue at the
557 * time of the call and copies them into the memory pointed to by
558 * pSignal.  Returns the # of signals copied as the value of the routine.
559 *
560 * Parameters:
561 * pChannel: (IN) points to the IO Channel
562 * Queue: (IN) nth Queue of the IO Channel
563 * pSignal: (IN) pointer to where the signals are to be copied
564 *
565 * Assumptions:
566 * - pChannel and Queue are valid.
567 * - pSignal points to a memory area large enough to hold Queue's MaxSignals
568 * # of signals, each of which is Queue's SignalSize.
569 *
570 * Return value:
571 * # of signals copied.
572 */
573 unsigned int spar_signal_remove_all(struct channel_header *ch, u32 queue,
574 				    void *sig);
575 
576 /*
577 * Routine Description:
578 * Determine whether a signal queue is empty.
579 *
580 * Parameters:
581 * pChannel: (IN) points to the IO Channel
582 * Queue: (IN) nth Queue of the IO Channel
583 *
584 * Return value:
585 * 1 if the signal queue is empty, 0 otherwise.
586 */
587 unsigned char spar_signalqueue_empty(struct channel_header __iomem *ch,
588 				     u32 queue);
589 
590 #endif
591