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