• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #define CHANNEL_GUID_MISMATCH(chType, chName, field, expected, actual, fil, \
54 			      lin, logCtx)				\
55 	do {								\
56 		pr_err("Channel mismatch on channel=%s(%pUL) field=%s expected=%pUL actual=%pUL @%s:%d\n", \
57 		       chName, &chType, field,	\
58 		       &expected, &actual, \
59 		       fil, lin);					\
60 	} while (0)
61 #define CHANNEL_U32_MISMATCH(chType, chName, field, expected, actual, fil, \
62 			     lin, logCtx)				\
63 	do {								\
64 		pr_err("Channel mismatch on channel=%s(%pUL) field=%s expected=0x%-8.8lx actual=0x%-8.8lx @%s:%d\n", \
65 		       chName, &chType, field,	\
66 		       (unsigned long)expected, (unsigned long)actual,	\
67 		       fil, lin);					\
68 	} while (0)
69 
70 #define CHANNEL_U64_MISMATCH(chType, chName, field, expected, actual, fil, \
71 			     lin, logCtx)				\
72 	do {								\
73 		pr_err("Channel mismatch on channel=%s(%pUL) field=%s expected=0x%-8.8Lx actual=0x%-8.8Lx @%s:%d\n", \
74 		       chName, &chType, field,	\
75 		       (unsigned long long)expected,			\
76 		       (unsigned long long)actual,			\
77 		       fil, lin);					\
78 	} while (0)
79 
80 #define UltraLogEvent(logCtx, EventId, Severity, SubsystemMask, pFunctionName, \
81 		      LineNumber, Str, args...)				\
82 	pr_info(Str, ## args)
83 
84 typedef enum {
85 	CHANNELSRV_UNINITIALIZED = 0,	/* channel is in an undefined state */
86 	CHANNELSRV_READY = 1	/* channel has been initialized by server */
87 } CHANNEL_SERVERSTATE;
88 
89 typedef enum {
90 	CHANNELCLI_DETACHED = 0,
91 	CHANNELCLI_DISABLED = 1,	/* client can see channel but is NOT
92 					 * allowed to use it unless given TBD
93 					 * explicit request (should actually be
94 					 * < DETACHED) */
95 	CHANNELCLI_ATTACHING = 2,	/* legacy EFI client request
96 					 * for EFI server to attach */
97 	CHANNELCLI_ATTACHED = 3,	/* idle, but client may want
98 					 * to use channel any time */
99 	CHANNELCLI_BUSY = 4,	/* client either wants to use or is
100 				 * using channel */
101 	CHANNELCLI_OWNED = 5	/* "no worries" state - client can
102 				 * access channel anytime */
103 } CHANNEL_CLIENTSTATE;
104 static inline const u8 *
ULTRA_CHANNELCLI_STRING(u32 v)105 ULTRA_CHANNELCLI_STRING(u32 v)
106 {
107 	switch (v) {
108 	case CHANNELCLI_DETACHED:
109 		return (const u8 *) ("DETACHED");
110 	case CHANNELCLI_DISABLED:
111 		return (const u8 *) ("DISABLED");
112 	case CHANNELCLI_ATTACHING:
113 		return (const u8 *) ("ATTACHING");
114 	case CHANNELCLI_ATTACHED:
115 		return (const u8 *) ("ATTACHED");
116 	case CHANNELCLI_BUSY:
117 		return (const u8 *) ("BUSY");
118 	case CHANNELCLI_OWNED:
119 		return (const u8 *) ("OWNED");
120 	default:
121 		break;
122 	}
123 	return (const u8 *) ("?");
124 }
125 
126 #define ULTRA_CHANNELSRV_IS_READY(x)     ((x) == CHANNELSRV_READY)
127 #define ULTRA_CHANNEL_SERVER_READY(pChannel) \
128 	(ULTRA_CHANNELSRV_IS_READY(readl(&(pChannel)->SrvState)))
129 
130 #define ULTRA_VALID_CHANNELCLI_TRANSITION(o, n)				\
131 	(((((o) == CHANNELCLI_DETACHED) && ((n) == CHANNELCLI_DISABLED)) || \
132 	  (((o) == CHANNELCLI_ATTACHING) && ((n) == CHANNELCLI_DISABLED)) || \
133 	  (((o) == CHANNELCLI_ATTACHED) && ((n) == CHANNELCLI_DISABLED)) || \
134 	  (((o) == CHANNELCLI_ATTACHING) && ((n) == CHANNELCLI_DETACHED)) || \
135 	  (((o) == CHANNELCLI_ATTACHED) && ((n) == CHANNELCLI_DETACHED)) || \
136 	  (((o) == CHANNELCLI_DETACHED) && ((n) == CHANNELCLI_ATTACHING)) || \
137 	  (((o) == CHANNELCLI_ATTACHING) && ((n) == CHANNELCLI_ATTACHED)) || \
138 	  (((o) == CHANNELCLI_DETACHED) && ((n) == CHANNELCLI_ATTACHED)) || \
139 	  (((o) == CHANNELCLI_BUSY) && ((n) == CHANNELCLI_ATTACHED)) ||	\
140 	  (((o) == CHANNELCLI_ATTACHED) && ((n) == CHANNELCLI_BUSY)) ||	\
141 	  (((o) == CHANNELCLI_DETACHED) && ((n) == CHANNELCLI_OWNED)) || \
142 	  (((o) == CHANNELCLI_DISABLED) && ((n) == CHANNELCLI_OWNED)) || \
143 	  (((o) == CHANNELCLI_ATTACHING) && ((n) == CHANNELCLI_OWNED)) || \
144 	  (((o) == CHANNELCLI_ATTACHED) && ((n) == CHANNELCLI_OWNED)) || \
145 	  (((o) == CHANNELCLI_BUSY) && ((n) == CHANNELCLI_OWNED)) || (0)) \
146 	 ? (1) : (0))
147 
148 #define ULTRA_CHANNEL_CLIENT_CHK_TRANSITION(old, new, chanId, logCtx,	\
149 					    file, line)			\
150 	do {								\
151 		if (!ULTRA_VALID_CHANNELCLI_TRANSITION(old, new))	\
152 			UltraLogEvent(logCtx,				\
153 				      CHANNELSTATE_DIAG_EVENTID_TRANSITERR, \
154 				      CHANNELSTATE_DIAG_SEVERITY, \
155 				      CHANNELSTATE_DIAG_SUBSYS,		\
156 				      __func__, __LINE__,		\
157 				      "%s Channel StateTransition INVALID! (%s) %s(%d)-->%s(%d) @%s:%d\n", \
158 				      chanId, "CliState<x>",		\
159 				      ULTRA_CHANNELCLI_STRING(old),	\
160 				      old,				\
161 				      ULTRA_CHANNELCLI_STRING(new),	\
162 				      new,				\
163 				      PathName_Last_N_Nodes((u8 *)file, 4), \
164 				      line);				\
165 	} while (0)
166 
167 #define ULTRA_CHANNEL_CLIENT_TRANSITION(pChan, chanId,			\
168 					newstate, logCtx)		\
169 	do {								\
170 		ULTRA_CHANNEL_CLIENT_CHK_TRANSITION(			\
171 			readl(&(((CHANNEL_HEADER __iomem *) \
172 				 (pChan))->CliStateOS)),		\
173 			newstate,					\
174 			chanId, logCtx, __FILE__, __LINE__);		\
175 		UltraLogEvent(logCtx, CHANNELSTATE_DIAG_EVENTID_TRANSITOK, \
176 			CHANNELSTATE_DIAG_SEVERITY, \
177 			      CHANNELSTATE_DIAG_SUBSYS,			\
178 			      __func__, __LINE__,			\
179 			      "%s Channel StateTransition (%s) %s(%d)-->%s(%d) @%s:%d\n", \
180 			      chanId, "CliStateOS",			\
181 			      ULTRA_CHANNELCLI_STRING( \
182 				      readl(&((CHANNEL_HEADER __iomem *) \
183 					      (pChan))->CliStateOS)),	\
184 			      readl(&((CHANNEL_HEADER __iomem *) \
185 				      (pChan))->CliStateOS),		\
186 			      ULTRA_CHANNELCLI_STRING(newstate),	\
187 			      newstate,					\
188 			      PathName_Last_N_Nodes(__FILE__, 4), __LINE__); \
189 		writel(newstate, &((CHANNEL_HEADER __iomem *) \
190 				   (pChan))->CliStateOS);		\
191 		mb(); /* required for channel synch */			\
192 	} while (0)
193 
194 #define ULTRA_CHANNEL_CLIENT_ACQUIRE_OS(pChan, chanId, logCtx)	\
195 	ULTRA_channel_client_acquire_os(pChan, chanId, logCtx,		\
196 					(char *)__FILE__, __LINE__,	\
197 					(char *)__func__)
198 #define ULTRA_CHANNEL_CLIENT_RELEASE_OS(pChan, chanId, logCtx)	\
199 	ULTRA_channel_client_release_os(pChan, chanId, logCtx,	\
200 		(char *)__FILE__, __LINE__, (char *)__func__)
201 
202 /* Values for ULTRA_CHANNEL_PROTOCOL.CliErrorBoot: */
203 /* throttling invalid boot channel statetransition error due to client
204  * disabled */
205 #define ULTRA_CLIERRORBOOT_THROTTLEMSG_DISABLED    0x01
206 
207 /* throttling invalid boot channel statetransition error due to client
208  * not attached */
209 #define ULTRA_CLIERRORBOOT_THROTTLEMSG_NOTATTACHED 0x02
210 
211 /* throttling invalid boot channel statetransition error due to busy channel */
212 #define ULTRA_CLIERRORBOOT_THROTTLEMSG_BUSY        0x04
213 
214 /* Values for ULTRA_CHANNEL_PROTOCOL.CliErrorOS: */
215 /* throttling invalid guest OS channel statetransition error due to
216  * client disabled */
217 #define ULTRA_CLIERROROS_THROTTLEMSG_DISABLED      0x01
218 
219 /* throttling invalid guest OS channel statetransition error due to
220  * client not attached */
221 #define ULTRA_CLIERROROS_THROTTLEMSG_NOTATTACHED   0x02
222 
223 /* throttling invalid guest OS channel statetransition error due to
224  * busy channel */
225 #define ULTRA_CLIERROROS_THROTTLEMSG_BUSY          0x04
226 
227 /* Values for ULTRA_CHANNEL_PROTOCOL.Features: This define exists so
228 * that windows guest can look at the FeatureFlags in the io channel,
229 * and configure the windows driver to use interrupts or not based on
230 * this setting.  This flag is set in uislib after the
231 * ULTRA_VHBA_init_channel is called.  All feature bits for all
232 * channels should be defined here.  The io channel feature bits are
233 * defined right here */
234 #define ULTRA_IO_DRIVER_ENABLES_INTS (0x1ULL << 1)
235 #define ULTRA_IO_CHANNEL_IS_POLLING (0x1ULL << 3)
236 #define ULTRA_IO_IOVM_IS_OK_WITH_DRIVER_DISABLING_INTS (0x1ULL << 4)
237 #define ULTRA_IO_DRIVER_DISABLES_INTS (0x1ULL << 5)
238 #define ULTRA_IO_DRIVER_SUPPORTS_ENHANCED_RCVBUF_CHECKING (0x1ULL << 6)
239 
240 #pragma pack(push, 1)		/* both GCC and VC now allow this pragma */
241 /* Common Channel Header */
242 typedef struct _CHANNEL_HEADER {
243 	u64 Signature;		/* Signature */
244 	u32 LegacyState;	/* DEPRECATED - being replaced by */
245 	/* /              SrvState, CliStateBoot, and CliStateOS below */
246 	u32 HeaderSize;		/* sizeof(CHANNEL_HEADER) */
247 	u64 Size;		/* Total size of this channel in bytes */
248 	u64 Features;		/* Flags to modify behavior */
249 	uuid_le Type;		/* Channel type: data, bus, control, etc. */
250 	u64 PartitionHandle;	/* ID of guest partition */
251 	u64 Handle;		/* Device number of this channel in client */
252 	u64 oChannelSpace;	/* Offset in bytes to channel specific area */
253 	u32 VersionId;		/* CHANNEL_HEADER Version ID */
254 	u32 PartitionIndex;	/* Index of guest partition */
255 	uuid_le ZoneGuid;		/* Guid of Channel's zone */
256 	u32 oClientString;	/* offset from channel header to
257 				 * nul-terminated ClientString (0 if
258 				 * ClientString not present) */
259 	u32 CliStateBoot;	/* CHANNEL_CLIENTSTATE of pre-boot
260 				 * EFI client of this channel */
261 	u32 CmdStateCli;	/* CHANNEL_COMMANDSTATE (overloaded in
262 				 * Windows drivers, see ServerStateUp,
263 				 * ServerStateDown, etc) */
264 	u32 CliStateOS;		/* CHANNEL_CLIENTSTATE of Guest OS
265 				 * client of this channel */
266 	u32 ChannelCharacteristics;	/* CHANNEL_CHARACTERISTIC_<xxx> */
267 	u32 CmdStateSrv;	/* CHANNEL_COMMANDSTATE (overloaded in
268 				 * Windows drivers, see ServerStateUp,
269 				 * ServerStateDown, etc) */
270 	u32 SrvState;		/* CHANNEL_SERVERSTATE */
271 	u8 CliErrorBoot;	/* bits to indicate err states for
272 				 * boot clients, so err messages can
273 				 * be throttled */
274 	u8 CliErrorOS;		/* bits to indicate err states for OS
275 				 * clients, so err messages can be
276 				 * throttled */
277 	u8 Filler[1];		/* Pad out to 128 byte cacheline */
278 	/* Please add all new single-byte values below here */
279 	u8 RecoverChannel;
280 } CHANNEL_HEADER, *pCHANNEL_HEADER, ULTRA_CHANNEL_PROTOCOL;
281 
282 #define ULTRA_CHANNEL_ENABLE_INTS (0x1ULL << 0)
283 
284 /* Subheader for the Signal Type variation of the Common Channel */
285 typedef struct _SIGNAL_QUEUE_HEADER {
286 	/* 1st cache line */
287 	u32 VersionId;		/* SIGNAL_QUEUE_HEADER Version ID */
288 	u32 Type;		/* Queue type: storage, network */
289 	u64 Size;		/* Total size of this queue in bytes */
290 	u64 oSignalBase;	/* Offset to signal queue area */
291 	u64 FeatureFlags;	/* Flags to modify behavior */
292 	u64 NumSignalsSent;	/* Total # of signals placed in this queue */
293 	u64 NumOverflows;	/* Total # of inserts failed due to
294 				 * full queue */
295 	u32 SignalSize;		/* Total size of a signal for this queue */
296 	u32 MaxSignalSlots;	/* Max # of slots in queue, 1 slot is
297 				 * always empty */
298 	u32 MaxSignals;		/* Max # of signals in queue
299 				 * (MaxSignalSlots-1) */
300 	u32 Head;		/* Queue head signal # */
301 	/* 2nd cache line */
302 	u64 NumSignalsReceived;	/* Total # of signals removed from this queue */
303 	u32 Tail;		/* Queue tail signal # (on separate
304 				 * cache line) */
305 	u32 Reserved1;		/* Reserved field */
306 	u64 Reserved2;		/* Resrved field */
307 	u64 ClientQueue;
308 	u64 NumInterruptsReceived;	/* Total # of Interrupts received.  This
309 					 * is incremented by the ISR in the
310 					 * guest windows driver */
311 	u64 NumEmptyCnt;	/* Number of times that visor_signal_remove
312 				 * is called and returned Empty
313 				 * Status. */
314 	u32 ErrorFlags;		/* Error bits set during SignalReinit
315 				 * to denote trouble with client's
316 				 * fields */
317 	u8 Filler[12];		/* Pad out to 64 byte cacheline */
318 } SIGNAL_QUEUE_HEADER, *pSIGNAL_QUEUE_HEADER;
319 
320 #pragma pack(pop)
321 
322 #define SignalInit(chan, QHDRFLD, QDATAFLD, QDATATYPE, ver, typ)	\
323 	do {								\
324 		memset(&chan->QHDRFLD, 0, sizeof(chan->QHDRFLD));	\
325 		chan->QHDRFLD.VersionId = ver;				\
326 		chan->QHDRFLD.Type = typ;				\
327 		chan->QHDRFLD.Size = sizeof(chan->QDATAFLD);		\
328 		chan->QHDRFLD.SignalSize = sizeof(QDATATYPE);		\
329 		chan->QHDRFLD.oSignalBase = (u64)(chan->QDATAFLD)-	\
330 			(u64)(&chan->QHDRFLD);				\
331 		chan->QHDRFLD.MaxSignalSlots =				\
332 			sizeof(chan->QDATAFLD)/sizeof(QDATATYPE);	\
333 		chan->QHDRFLD.MaxSignals = chan->QHDRFLD.MaxSignalSlots-1; \
334 	} while (0)
335 
336 /* Generic function useful for validating any type of channel when it is
337  * received by the client that will be accessing the channel.
338  * Note that <logCtx> is only needed for callers in the EFI environment, and
339  * is used to pass the EFI_DIAG_CAPTURE_PROTOCOL needed to log messages.
340  */
341 static inline int
ULTRA_check_channel_client(void __iomem * pChannel,uuid_le expectedTypeGuid,char * channelName,u64 expectedMinBytes,u32 expectedVersionId,u64 expectedSignature,char * fileName,int lineNumber,void * logCtx)342 ULTRA_check_channel_client(void __iomem *pChannel,
343 			   uuid_le expectedTypeGuid,
344 			   char *channelName,
345 			   u64 expectedMinBytes,
346 			   u32 expectedVersionId,
347 			   u64 expectedSignature,
348 			   char *fileName, int lineNumber, void *logCtx)
349 {
350 	if (uuid_le_cmp(expectedTypeGuid, NULL_UUID_LE) != 0) {
351 		uuid_le guid;
352 
353 		memcpy_fromio(&guid,
354 			      &((CHANNEL_HEADER __iomem *)(pChannel))->Type,
355 			      sizeof(guid));
356 		/* caller wants us to verify type GUID */
357 		if (uuid_le_cmp(guid, expectedTypeGuid) != 0) {
358 			CHANNEL_GUID_MISMATCH(expectedTypeGuid, channelName,
359 					      "type", expectedTypeGuid,
360 					      guid, fileName,
361 					      lineNumber, logCtx);
362 			return 0;
363 		}
364 	}
365 	if (expectedMinBytes > 0)	/* caller wants us to verify
366 					 * channel size */
367 		if (readq(&((CHANNEL_HEADER __iomem *)
368 			   (pChannel))->Size) < expectedMinBytes) {
369 			CHANNEL_U64_MISMATCH(expectedTypeGuid, channelName,
370 					     "size", expectedMinBytes,
371 					     readq(&((CHANNEL_HEADER __iomem *)
372 						     (pChannel))->Size),
373 					     fileName,
374 					     lineNumber, logCtx);
375 			return 0;
376 		}
377 	if (expectedVersionId > 0)	/* caller wants us to verify
378 					 * channel version */
379 		if (readl(&((CHANNEL_HEADER __iomem *) (pChannel))->VersionId)
380 		    != expectedVersionId) {
381 			CHANNEL_U32_MISMATCH(expectedTypeGuid, channelName,
382 					     "version", expectedVersionId,
383 					     readl(&((CHANNEL_HEADER __iomem *)
384 						     (pChannel))->VersionId),
385 					     fileName, lineNumber, logCtx);
386 			return 0;
387 		}
388 	if (expectedSignature > 0)	/* caller wants us to verify
389 					 * channel signature */
390 		if (readq(&((CHANNEL_HEADER __iomem *) (pChannel))->Signature)
391 		    != expectedSignature) {
392 			CHANNEL_U64_MISMATCH(expectedTypeGuid, channelName,
393 					     "signature", expectedSignature,
394 					     readq(&((CHANNEL_HEADER __iomem *)
395 						     (pChannel))->Signature),
396 					     fileName,
397 					     lineNumber, logCtx);
398 			return 0;
399 		}
400 	return 1;
401 }
402 
403 /* Generic function useful for validating any type of channel when it is about
404  * to be initialized by the server of the channel.
405  * Note that <logCtx> is only needed for callers in the EFI environment, and
406  * is used to pass the EFI_DIAG_CAPTURE_PROTOCOL needed to log messages.
407  */
408 static inline int
ULTRA_check_channel_server(uuid_le typeGuid,char * channelName,u64 expectedMinBytes,u64 actualBytes,char * fileName,int lineNumber,void * logCtx)409 ULTRA_check_channel_server(uuid_le typeGuid,
410 			   char *channelName,
411 			   u64 expectedMinBytes,
412 			   u64 actualBytes,
413 			   char *fileName, int lineNumber, void *logCtx)
414 {
415 	if (expectedMinBytes > 0)	/* caller wants us to verify
416 					 * channel size */
417 		if (actualBytes < expectedMinBytes) {
418 			CHANNEL_U64_MISMATCH(typeGuid, channelName, "size",
419 					     expectedMinBytes, actualBytes,
420 					     fileName, lineNumber, logCtx);
421 			return 0;
422 		}
423 	return 1;
424 }
425 
426 /* Given a file pathname <s> (with '/' or '\' separating directory nodes),
427  * returns a pointer to the beginning of a node within that pathname such
428  * that the number of nodes from that pointer to the end of the string is
429  * NOT more than <n>.  Note that if the pathname has less than <n> nodes
430  * in it, the return pointer will be to the beginning of the string.
431  */
432 static inline u8 *
PathName_Last_N_Nodes(u8 * s,unsigned int n)433 PathName_Last_N_Nodes(u8 *s, unsigned int n)
434 {
435 	u8 *p = s;
436 	unsigned int node_count = 0;
437 
438 	while (*p != '\0') {
439 		if ((*p == '/') || (*p == '\\'))
440 			node_count++;
441 		p++;
442 	}
443 	if (node_count <= n)
444 		return s;
445 	while (n > 0) {
446 		p--;
447 		if (p == s)
448 			break;	/* should never happen, unless someone
449 				 * is changing the string while we are
450 				 * looking at it!! */
451 		if ((*p == '/') || (*p == '\\'))
452 			n--;
453 	}
454 	return p + 1;
455 }
456 
457 static inline int
ULTRA_channel_client_acquire_os(void __iomem * pChannel,u8 * chanId,void * logCtx,char * file,int line,char * func)458 ULTRA_channel_client_acquire_os(void __iomem *pChannel, u8 *chanId,
459 				void *logCtx, char *file, int line, char *func)
460 {
461 	CHANNEL_HEADER __iomem *pChan = pChannel;
462 
463 	if (readl(&pChan->CliStateOS) == CHANNELCLI_DISABLED) {
464 		if ((readb(&pChan->CliErrorOS)
465 		     & ULTRA_CLIERROROS_THROTTLEMSG_DISABLED) == 0) {
466 			/* we are NOT throttling this message */
467 			writeb(readb(&pChan->CliErrorOS) |
468 			       ULTRA_CLIERROROS_THROTTLEMSG_DISABLED,
469 			       &pChan->CliErrorOS);
470 			/* throttle until acquire successful */
471 
472 			UltraLogEvent(logCtx,
473 				      CHANNELSTATE_DIAG_EVENTID_TRANSITERR,
474 				      CHANNELSTATE_DIAG_SEVERITY,
475 				      CHANNELSTATE_DIAG_SUBSYS, func, line,
476 				      "%s Channel StateTransition INVALID! - acquire failed because OS client DISABLED @%s:%d\n",
477 				      chanId, PathName_Last_N_Nodes(
478 					      (u8 *) file, 4), line);
479 		}
480 		return 0;
481 	}
482 	if ((readl(&pChan->CliStateOS) != CHANNELCLI_OWNED)
483 	    && (readl(&pChan->CliStateBoot) == CHANNELCLI_DISABLED)) {
484 		/* Our competitor is DISABLED, so we can transition to OWNED */
485 		UltraLogEvent(logCtx, CHANNELSTATE_DIAG_EVENTID_TRANSITOK,
486 			      CHANNELSTATE_DIAG_SEVERITY,
487 			      CHANNELSTATE_DIAG_SUBSYS, func, line,
488 			      "%s Channel StateTransition (%s) %s(%d)-->%s(%d) @%s:%d\n",
489 			      chanId, "CliStateOS",
490 			      ULTRA_CHANNELCLI_STRING(
491 				      readl(&pChan->CliStateOS)),
492 			      readl(&pChan->CliStateOS),
493 			      ULTRA_CHANNELCLI_STRING(CHANNELCLI_OWNED),
494 			      CHANNELCLI_OWNED,
495 			      PathName_Last_N_Nodes((u8 *) file, 4), line);
496 		writel(CHANNELCLI_OWNED, &pChan->CliStateOS);
497 		mb(); /* required for channel synch */
498 	}
499 	if (readl(&pChan->CliStateOS) == CHANNELCLI_OWNED) {
500 		if (readb(&pChan->CliErrorOS) != 0) {
501 			/* we are in an error msg throttling state;
502 			 * come out of it */
503 			UltraLogEvent(logCtx,
504 				      CHANNELSTATE_DIAG_EVENTID_TRANSITOK,
505 				      CHANNELSTATE_DIAG_SEVERITY,
506 				      CHANNELSTATE_DIAG_SUBSYS, func, line,
507 				      "%s Channel OS client acquire now successful @%s:%d\n",
508 				      chanId, PathName_Last_N_Nodes((u8 *) file,
509 								    4), line);
510 			writeb(0, &pChan->CliErrorOS);
511 		}
512 		return 1;
513 	}
514 
515 	/* We have to do it the "hard way".  We transition to BUSY,
516 	* and can use the channel iff our competitor has not also
517 	* transitioned to BUSY. */
518 	if (readl(&pChan->CliStateOS) != CHANNELCLI_ATTACHED) {
519 		if ((readb(&pChan->CliErrorOS)
520 		     & ULTRA_CLIERROROS_THROTTLEMSG_NOTATTACHED) == 0) {
521 			/* we are NOT throttling this message */
522 			writeb(readb(&pChan->CliErrorOS) |
523 			       ULTRA_CLIERROROS_THROTTLEMSG_NOTATTACHED,
524 			       &pChan->CliErrorOS);
525 			/* throttle until acquire successful */
526 			UltraLogEvent(logCtx,
527 				      CHANNELSTATE_DIAG_EVENTID_TRANSITERR,
528 				      CHANNELSTATE_DIAG_SEVERITY,
529 				      CHANNELSTATE_DIAG_SUBSYS, func, line,
530 				      "%s Channel StateTransition INVALID! - acquire failed because OS client NOT ATTACHED (state=%s(%d)) @%s:%d\n",
531 				      chanId,
532 				      ULTRA_CHANNELCLI_STRING(
533 					      readl(&pChan->CliStateOS)),
534 				      readl(&pChan->CliStateOS),
535 				      PathName_Last_N_Nodes((u8 *) file, 4),
536 				      line);
537 		}
538 		return 0;
539 	}
540 	writel(CHANNELCLI_BUSY, &pChan->CliStateOS);
541 	mb(); /* required for channel synch */
542 	if (readl(&pChan->CliStateBoot) == CHANNELCLI_BUSY) {
543 		if ((readb(&pChan->CliErrorOS)
544 		     & ULTRA_CLIERROROS_THROTTLEMSG_BUSY) == 0) {
545 			/* we are NOT throttling this message */
546 			writeb(readb(&pChan->CliErrorOS) |
547 			       ULTRA_CLIERROROS_THROTTLEMSG_BUSY,
548 			       &pChan->CliErrorOS);
549 			/* throttle until acquire successful */
550 			UltraLogEvent(logCtx,
551 				      CHANNELSTATE_DIAG_EVENTID_TRANSITBUSY,
552 				      CHANNELSTATE_DIAG_SEVERITY,
553 				      CHANNELSTATE_DIAG_SUBSYS, func, line,
554 				      "%s Channel StateTransition failed - host OS acquire failed because boot BUSY @%s:%d\n",
555 				      chanId, PathName_Last_N_Nodes((u8 *) file,
556 								    4), line);
557 		}
558 		/* reset busy */
559 		writel(CHANNELCLI_ATTACHED, &pChan->CliStateOS);
560 		mb(); /* required for channel synch */
561 		return 0;
562 	}
563 	if (readb(&pChan->CliErrorOS) != 0) {
564 		/* we are in an error msg throttling state; come out of it */
565 		UltraLogEvent(logCtx, CHANNELSTATE_DIAG_EVENTID_TRANSITOK,
566 			      CHANNELSTATE_DIAG_SEVERITY,
567 			      CHANNELSTATE_DIAG_SUBSYS, func, line,
568 			      "%s Channel OS client acquire now successful @%s:%d\n",
569 			      chanId, PathName_Last_N_Nodes((u8 *) file, 4),
570 			      line);
571 		writeb(0, &pChan->CliErrorOS);
572 	}
573 	return 1;
574 }
575 
576 static inline void
ULTRA_channel_client_release_os(void __iomem * pChannel,u8 * chanId,void * logCtx,char * file,int line,char * func)577 ULTRA_channel_client_release_os(void __iomem *pChannel, u8 *chanId,
578 				void *logCtx, char *file, int line, char *func)
579 {
580 	CHANNEL_HEADER __iomem *pChan = pChannel;
581 
582 	if (readb(&pChan->CliErrorOS) != 0) {
583 		/* we are in an error msg throttling state; come out of it */
584 		UltraLogEvent(logCtx, CHANNELSTATE_DIAG_EVENTID_TRANSITOK,
585 			      CHANNELSTATE_DIAG_SEVERITY,
586 			      CHANNELSTATE_DIAG_SUBSYS, func, line,
587 			      "%s Channel OS client error state cleared @%s:%d\n",
588 			      chanId, PathName_Last_N_Nodes((u8 *) file, 4),
589 			      line);
590 		writeb(0, &pChan->CliErrorOS);
591 	}
592 	if (readl(&pChan->CliStateOS) == CHANNELCLI_OWNED)
593 		return;
594 	if (readl(&pChan->CliStateOS) != CHANNELCLI_BUSY) {
595 		UltraLogEvent(logCtx, CHANNELSTATE_DIAG_EVENTID_TRANSITERR,
596 			      CHANNELSTATE_DIAG_SEVERITY,
597 			      CHANNELSTATE_DIAG_SUBSYS, func, line,
598 			      "%s Channel StateTransition INVALID! - release failed because OS client NOT BUSY (state=%s(%d)) @%s:%d\n",
599 			      chanId,
600 			      ULTRA_CHANNELCLI_STRING(
601 				      readl(&pChan->CliStateOS)),
602 			      readl(&pChan->CliStateOS),
603 			      PathName_Last_N_Nodes((u8 *) file, 4), line);
604 		/* return; */
605 	}
606 	writel(CHANNELCLI_ATTACHED, &pChan->CliStateOS); /* release busy */
607 }
608 
609 /*
610 * Routine Description:
611 * Tries to insert the prebuilt signal pointed to by pSignal into the nth
612 * Queue of the Channel pointed to by pChannel
613 *
614 * Parameters:
615 * pChannel: (IN) points to the IO Channel
616 * Queue: (IN) nth Queue of the IO Channel
617 * pSignal: (IN) pointer to the signal
618 *
619 * Assumptions:
620 * - pChannel, Queue and pSignal are valid.
621 * - If insertion fails due to a full queue, the caller will determine the
622 * retry policy (e.g. wait & try again, report an error, etc.).
623 *
624 * Return value: 1 if the insertion succeeds, 0 if the queue was
625 * full.
626 */
627 
628 unsigned char visor_signal_insert(CHANNEL_HEADER __iomem *pChannel, u32 Queue,
629 				  void *pSignal);
630 
631 /*
632 * Routine Description:
633 * Removes one signal from Channel pChannel's nth Queue at the
634 * time of the call and copies it into the memory pointed to by
635 * pSignal.
636 *
637 * Parameters:
638 * pChannel: (IN) points to the IO Channel
639 * Queue: (IN) nth Queue of the IO Channel
640 * pSignal: (IN) pointer to where the signals are to be copied
641 *
642 * Assumptions:
643 * - pChannel and Queue are valid.
644 * - pSignal points to a memory area large enough to hold queue's SignalSize
645 *
646 * Return value: 1 if the removal succeeds, 0 if the queue was
647 * empty.
648 */
649 
650 unsigned char visor_signal_remove(CHANNEL_HEADER __iomem *pChannel, u32 Queue,
651 				  void *pSignal);
652 
653 /*
654 * Routine Description:
655 * Removes all signals present in Channel pChannel's nth Queue at the
656 * time of the call and copies them into the memory pointed to by
657 * pSignal.  Returns the # of signals copied as the value of the routine.
658 *
659 * Parameters:
660 * pChannel: (IN) points to the IO Channel
661 * Queue: (IN) nth Queue of the IO Channel
662 * pSignal: (IN) pointer to where the signals are to be copied
663 *
664 * Assumptions:
665 * - pChannel and Queue are valid.
666 * - pSignal points to a memory area large enough to hold Queue's MaxSignals
667 * # of signals, each of which is Queue's SignalSize.
668 *
669 * Return value:
670 * # of signals copied.
671 */
672 unsigned int SignalRemoveAll(pCHANNEL_HEADER pChannel, u32 Queue,
673 			     void *pSignal);
674 
675 /*
676 * Routine Description:
677 * Determine whether a signal queue is empty.
678 *
679 * Parameters:
680 * pChannel: (IN) points to the IO Channel
681 * Queue: (IN) nth Queue of the IO Channel
682 *
683 * Return value:
684 * 1 if the signal queue is empty, 0 otherwise.
685 */
686 unsigned char visor_signalqueue_empty(CHANNEL_HEADER __iomem *pChannel,
687 				      u32 Queue);
688 
689 #endif
690