5ba5e566be9afcc70e2f74f1dd537cdfe683b870
[pandora-kernel.git] / drivers / staging / unisys / common-spar / include / channels / channel.h
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 *
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
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                 ioread8_rep(&((CHANNEL_HEADER __iomem *)(pChannel))->Type,
354                         &guid, sizeof(guid));
355                 /* caller wants us to verify type GUID */
356                 if (uuid_le_cmp(guid, expectedTypeGuid) != 0) {
357                         CHANNEL_GUID_MISMATCH(expectedTypeGuid, channelName,
358                                               "type", expectedTypeGuid,
359                                               ((CHANNEL_HEADER __iomem *)
360                                                (pChannel))->Type, 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
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 *
433 PathName_Last_N_Nodes(u8 *s, unsigned int n)
434 {
435         u8 *p = s;
436         unsigned int node_count = 0;
437         while (*p != '\0') {
438                 if ((*p == '/') || (*p == '\\'))
439                         node_count++;
440                 p++;
441         }
442         if (node_count <= n)
443                 return s;
444         while (n > 0) {
445                 p--;
446                 if (p == s)
447                         break;  /* should never happen, unless someone
448                                  * is changing the string while we are
449                                  * looking at it!! */
450                 if ((*p == '/') || (*p == '\\'))
451                         n--;
452         }
453         return p + 1;
454 }
455
456 static inline int
457 ULTRA_channel_client_acquire_os(void __iomem *pChannel, u8 *chanId,
458                                 void *logCtx, char *file, int line, char *func)
459 {
460         CHANNEL_HEADER __iomem *pChan = pChannel;
461
462         if (readl(&pChan->CliStateOS) == CHANNELCLI_DISABLED) {
463                 if ((readb(&pChan->CliErrorOS)
464                      & ULTRA_CLIERROROS_THROTTLEMSG_DISABLED) == 0) {
465                         /* we are NOT throttling this message */
466                         writeb(readb(&pChan->CliErrorOS) |
467                                ULTRA_CLIERROROS_THROTTLEMSG_DISABLED,
468                                &pChan->CliErrorOS);
469                         /* throttle until acquire successful */
470
471                         UltraLogEvent(logCtx,
472                                       CHANNELSTATE_DIAG_EVENTID_TRANSITERR,
473                                       CHANNELSTATE_DIAG_SEVERITY,
474                                       CHANNELSTATE_DIAG_SUBSYS, func, line,
475                                       "%s Channel StateTransition INVALID! - acquire failed because OS client DISABLED @%s:%d\n",
476                                       chanId, PathName_Last_N_Nodes(
477                                               (u8 *) file, 4), line);
478                 }
479                 return 0;
480         }
481         if ((readl(&pChan->CliStateOS) != CHANNELCLI_OWNED)
482             && (readl(&pChan->CliStateBoot) == CHANNELCLI_DISABLED)) {
483                 /* Our competitor is DISABLED, so we can transition to OWNED */
484                 UltraLogEvent(logCtx, CHANNELSTATE_DIAG_EVENTID_TRANSITOK,
485                               CHANNELSTATE_DIAG_SEVERITY,
486                               CHANNELSTATE_DIAG_SUBSYS, func, line,
487                               "%s Channel StateTransition (%s) %s(%d)-->%s(%d) @%s:%d\n",
488                               chanId, "CliStateOS",
489                               ULTRA_CHANNELCLI_STRING(
490                                       readl(&pChan->CliStateOS)),
491                               readl(&pChan->CliStateOS),
492                               ULTRA_CHANNELCLI_STRING(CHANNELCLI_OWNED),
493                               CHANNELCLI_OWNED,
494                               PathName_Last_N_Nodes((u8 *) file, 4), line);
495                 writel(CHANNELCLI_OWNED, &pChan->CliStateOS);
496                 mb(); /* required for channel synch */
497         }
498         if (readl(&pChan->CliStateOS) == CHANNELCLI_OWNED) {
499                 if (readb(&pChan->CliErrorOS) != 0) {
500                         /* we are in an error msg throttling state;
501                          * come out of it */
502                         UltraLogEvent(logCtx,
503                                       CHANNELSTATE_DIAG_EVENTID_TRANSITOK,
504                                       CHANNELSTATE_DIAG_SEVERITY,
505                                       CHANNELSTATE_DIAG_SUBSYS, func, line,
506                                       "%s Channel OS client acquire now successful @%s:%d\n",
507                                       chanId, PathName_Last_N_Nodes((u8 *) file,
508                                                                     4), line);
509                         writeb(0, &pChan->CliErrorOS);
510                 }
511                 return 1;
512         }
513
514         /* We have to do it the "hard way".  We transition to BUSY,
515         * and can use the channel iff our competitor has not also
516         * transitioned to BUSY. */
517         if (readl(&pChan->CliStateOS) != CHANNELCLI_ATTACHED) {
518                 if ((readb(&pChan->CliErrorOS)
519                      & ULTRA_CLIERROROS_THROTTLEMSG_NOTATTACHED) == 0) {
520                         /* we are NOT throttling this message */
521                         writeb(readb(&pChan->CliErrorOS) |
522                                ULTRA_CLIERROROS_THROTTLEMSG_NOTATTACHED,
523                                &pChan->CliErrorOS);
524                         /* throttle until acquire successful */
525                         UltraLogEvent(logCtx,
526                                       CHANNELSTATE_DIAG_EVENTID_TRANSITERR,
527                                       CHANNELSTATE_DIAG_SEVERITY,
528                                       CHANNELSTATE_DIAG_SUBSYS, func, line,
529                                       "%s Channel StateTransition INVALID! - acquire failed because OS client NOT ATTACHED (state=%s(%d)) @%s:%d\n",
530                                       chanId,
531                                       ULTRA_CHANNELCLI_STRING(
532                                               readl(&pChan->CliStateOS)),
533                                       readl(&pChan->CliStateOS),
534                                       PathName_Last_N_Nodes((u8 *) file, 4),
535                                       line);
536                 }
537                 return 0;
538         }
539         writel(CHANNELCLI_BUSY, &pChan->CliStateOS);
540         mb(); /* required for channel synch */
541         if (readl(&pChan->CliStateBoot) == CHANNELCLI_BUSY) {
542                 if ((readb(&pChan->CliErrorOS)
543                      & ULTRA_CLIERROROS_THROTTLEMSG_BUSY) == 0) {
544                         /* we are NOT throttling this message */
545                         writeb(readb(&pChan->CliErrorOS) |
546                                ULTRA_CLIERROROS_THROTTLEMSG_BUSY,
547                                &pChan->CliErrorOS);
548                         /* throttle until acquire successful */
549                         UltraLogEvent(logCtx,
550                                       CHANNELSTATE_DIAG_EVENTID_TRANSITBUSY,
551                                       CHANNELSTATE_DIAG_SEVERITY,
552                                       CHANNELSTATE_DIAG_SUBSYS, func, line,
553                                       "%s Channel StateTransition failed - host OS acquire failed because boot BUSY @%s:%d\n",
554                                       chanId, PathName_Last_N_Nodes((u8 *) file,
555                                                                     4), line);
556                 }
557                 /* reset busy */
558                 writel(CHANNELCLI_ATTACHED, &pChan->CliStateOS);
559                 mb(); /* required for channel synch */
560                 return 0;
561         }
562         if (readb(&pChan->CliErrorOS) != 0) {
563                 /* we are in an error msg throttling state; come out of it */
564                 UltraLogEvent(logCtx, CHANNELSTATE_DIAG_EVENTID_TRANSITOK,
565                               CHANNELSTATE_DIAG_SEVERITY,
566                               CHANNELSTATE_DIAG_SUBSYS, func, line,
567                               "%s Channel OS client acquire now successful @%s:%d\n",
568                               chanId, PathName_Last_N_Nodes((u8 *) file, 4),
569                               line);
570                 writeb(0, &pChan->CliErrorOS);
571         }
572         return 1;
573 }
574
575 static inline void
576 ULTRA_channel_client_release_os(void __iomem *pChannel, u8 *chanId,
577                                 void *logCtx, char *file, int line, char *func)
578 {
579         CHANNEL_HEADER __iomem *pChan = pChannel;
580         if (readb(&pChan->CliErrorOS) != 0) {
581                 /* we are in an error msg throttling state; come out of it */
582                 UltraLogEvent(logCtx, CHANNELSTATE_DIAG_EVENTID_TRANSITOK,
583                               CHANNELSTATE_DIAG_SEVERITY,
584                               CHANNELSTATE_DIAG_SUBSYS, func, line,
585                               "%s Channel OS client error state cleared @%s:%d\n",
586                               chanId, PathName_Last_N_Nodes((u8 *) file, 4),
587                               line);
588                 writeb(0, &pChan->CliErrorOS);
589         }
590         if (readl(&pChan->CliStateOS) == CHANNELCLI_OWNED)
591                 return;
592         if (readl(&pChan->CliStateOS) != CHANNELCLI_BUSY) {
593                 UltraLogEvent(logCtx, CHANNELSTATE_DIAG_EVENTID_TRANSITERR,
594                               CHANNELSTATE_DIAG_SEVERITY,
595                               CHANNELSTATE_DIAG_SUBSYS, func, line,
596                               "%s Channel StateTransition INVALID! - release failed because OS client NOT BUSY (state=%s(%d)) @%s:%d\n",
597                               chanId,
598                               ULTRA_CHANNELCLI_STRING(
599                                       readl(&pChan->CliStateOS)),
600                               readl(&pChan->CliStateOS),
601                               PathName_Last_N_Nodes((u8 *) file, 4), line);
602                 /* return; */
603         }
604         writel(CHANNELCLI_ATTACHED, &pChan->CliStateOS); /* release busy */
605 }
606
607 /*
608 * Routine Description:
609 * Tries to insert the prebuilt signal pointed to by pSignal into the nth
610 * Queue of the Channel pointed to by pChannel
611 *
612 * Parameters:
613 * pChannel: (IN) points to the IO Channel
614 * Queue: (IN) nth Queue of the IO Channel
615 * pSignal: (IN) pointer to the signal
616 *
617 * Assumptions:
618 * - pChannel, Queue and pSignal are valid.
619 * - If insertion fails due to a full queue, the caller will determine the
620 * retry policy (e.g. wait & try again, report an error, etc.).
621 *
622 * Return value: 1 if the insertion succeeds, 0 if the queue was
623 * full.
624 */
625
626 unsigned char visor_signal_insert(CHANNEL_HEADER __iomem *pChannel, u32 Queue,
627                                   void *pSignal);
628
629 /*
630 * Routine Description:
631 * Removes one signal from Channel pChannel's nth Queue at the
632 * time of the call and copies it into the memory pointed to by
633 * pSignal.
634 *
635 * Parameters:
636 * pChannel: (IN) points to the IO Channel
637 * Queue: (IN) nth Queue of the IO Channel
638 * pSignal: (IN) pointer to where the signals are to be copied
639 *
640 * Assumptions:
641 * - pChannel and Queue are valid.
642 * - pSignal points to a memory area large enough to hold queue's SignalSize
643 *
644 * Return value: 1 if the removal succeeds, 0 if the queue was
645 * empty.
646 */
647
648 unsigned char visor_signal_remove(CHANNEL_HEADER __iomem *pChannel, u32 Queue,
649                                   void *pSignal);
650
651 /*
652 * Routine Description:
653 * Removes all signals present in Channel pChannel's nth Queue at the
654 * time of the call and copies them into the memory pointed to by
655 * pSignal.  Returns the # of signals copied as the value of the routine.
656 *
657 * Parameters:
658 * pChannel: (IN) points to the IO Channel
659 * Queue: (IN) nth Queue of the IO Channel
660 * pSignal: (IN) pointer to where the signals are to be copied
661 *
662 * Assumptions:
663 * - pChannel and Queue are valid.
664 * - pSignal points to a memory area large enough to hold Queue's MaxSignals
665 * # of signals, each of which is Queue's SignalSize.
666 *
667 * Return value:
668 * # of signals copied.
669 */
670 unsigned int SignalRemoveAll(pCHANNEL_HEADER pChannel, u32 Queue,
671                              void *pSignal);
672
673 /*
674 * Routine Description:
675 * Determine whether a signal queue is empty.
676 *
677 * Parameters:
678 * pChannel: (IN) points to the IO Channel
679 * Queue: (IN) nth Queue of the IO Channel
680 *
681 * Return value:
682 * 1 if the signal queue is empty, 0 otherwise.
683 */
684 unsigned char visor_signalqueue_empty(CHANNEL_HEADER __iomem *pChannel,
685                                       u32 Queue);
686
687 #endif