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