blob: db4e6b28755b45066c73023fade02524d8a17765 [file] [log] [blame]
Benjamin Romerf6d0c1e2014-04-23 14:58:34 -04001/* Copyright (C) 2010 - 2013 UNISYS CORPORATION
Ken Coxe4238122014-03-04 07:58:06 -06002 * 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
Benjamin Romer1d2def92014-08-02 22:03:43 -040019#include <linux/types.h>
20#include <linux/io.h>
Benjamin Romer90addb02014-05-06 09:58:23 -040021#include <linux/uuid.h>
22
Ken Coxe4238122014-03-04 07:58:06 -060023/*
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
Masanari Iidafb90c602014-04-15 01:56:33 +090031 * files of similar abbreviated content
Ken Coxe4238122014-03-04 07:58:06 -060032 */
33#define __SUPERVISOR_CHANNEL_H__
34
David Kershner54bf4d42015-10-12 15:19:40 -040035#define SIGNATURE_16(A, B) ((A) | (B << 8))
Ken Coxe4238122014-03-04 07:58:06 -060036#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) \
Benjamin Romer5fc02292014-07-31 12:00:51 -040039 (SIGNATURE_32(A, B, C, D) | ((u64)(SIGNATURE_32(E, F, G, H)) << 32))
Ken Coxe4238122014-03-04 07:58:06 -060040
41#ifndef lengthof
42#define lengthof(TYPE, MEMBER) (sizeof(((TYPE *)0)->MEMBER))
43#endif
44#ifndef COVERQ
David Kershner54bf4d42015-10-12 15:19:40 -040045#define COVERQ(v, d) (((v) + (d) - 1) / (d))
Ken Coxe4238122014-03-04 07:58:06 -060046#endif
47#ifndef COVER
David Kershner54bf4d42015-10-12 15:19:40 -040048#define COVER(v, d) ((d) * COVERQ(v, d))
Ken Coxe4238122014-03-04 07:58:06 -060049#endif
50
Ken Coxe4238122014-03-04 07:58:06 -060051#define ULTRA_CHANNEL_PROTOCOL_SIGNATURE SIGNATURE_32('E', 'C', 'N', 'L')
52
Benjamin Romer1e73f4b2014-10-23 14:29:51 -040053enum channel_serverstate {
Ken Coxe4238122014-03-04 07:58:06 -060054 CHANNELSRV_UNINITIALIZED = 0, /* channel is in an undefined state */
55 CHANNELSRV_READY = 1 /* channel has been initialized by server */
Benjamin Romer1e73f4b2014-10-23 14:29:51 -040056};
Ken Coxe4238122014-03-04 07:58:06 -060057
Benjamin Romer9831a292014-10-23 14:29:52 -040058enum channel_clientstate {
Ken Coxe4238122014-03-04 07:58:06 -060059 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
Erik Arfvidson180e2762015-11-17 13:34:57 -050063 * < DETACHED)
64 */
Ken Coxe4238122014-03-04 07:58:06 -060065 CHANNELCLI_ATTACHING = 2, /* legacy EFI client request
Erik Arfvidson180e2762015-11-17 13:34:57 -050066 * for EFI server to attach
67 */
Ken Coxe4238122014-03-04 07:58:06 -060068 CHANNELCLI_ATTACHED = 3, /* idle, but client may want
Erik Arfvidson180e2762015-11-17 13:34:57 -050069 * to use channel any time
70 */
Ken Coxe4238122014-03-04 07:58:06 -060071 CHANNELCLI_BUSY = 4, /* client either wants to use or is
Erik Arfvidson180e2762015-11-17 13:34:57 -050072 * using channel
73 */
74 CHANNELCLI_OWNED = 5 /* "no worries" state - client can */
75 /* access channel anytime */
Benjamin Romer9831a292014-10-23 14:29:52 -040076};
Benjamin Romer09a50732014-10-23 14:29:53 -040077
Benjamin Romerc2422332014-07-29 15:09:40 -040078static inline const u8 *
Alexander Curtin85d83cd2016-03-23 22:15:53 -040079ULTRA_CHANNELCLI_STRING(u32 state)
Ken Coxe4238122014-03-04 07:58:06 -060080{
Alexander Curtin85d83cd2016-03-23 22:15:53 -040081 switch (state) {
Ken Coxe4238122014-03-04 07:58:06 -060082 case CHANNELCLI_DETACHED:
Benjamin Romer82d72be2014-10-23 14:29:54 -040083 return (const u8 *)("DETACHED");
Ken Coxe4238122014-03-04 07:58:06 -060084 case CHANNELCLI_DISABLED:
Benjamin Romer82d72be2014-10-23 14:29:54 -040085 return (const u8 *)("DISABLED");
Ken Coxe4238122014-03-04 07:58:06 -060086 case CHANNELCLI_ATTACHING:
Benjamin Romer82d72be2014-10-23 14:29:54 -040087 return (const u8 *)("ATTACHING");
Ken Coxe4238122014-03-04 07:58:06 -060088 case CHANNELCLI_ATTACHED:
Benjamin Romer82d72be2014-10-23 14:29:54 -040089 return (const u8 *)("ATTACHED");
Ken Coxe4238122014-03-04 07:58:06 -060090 case CHANNELCLI_BUSY:
Benjamin Romer82d72be2014-10-23 14:29:54 -040091 return (const u8 *)("BUSY");
Ken Coxe4238122014-03-04 07:58:06 -060092 case CHANNELCLI_OWNED:
Benjamin Romer82d72be2014-10-23 14:29:54 -040093 return (const u8 *)("OWNED");
Ken Coxe4238122014-03-04 07:58:06 -060094 default:
95 break;
96 }
Benjamin Romer82d72be2014-10-23 14:29:54 -040097 return (const u8 *)("?");
Ken Coxe4238122014-03-04 07:58:06 -060098}
99
Benjamin Romer10b133c2014-10-23 14:29:57 -0400100#define SPAR_CHANNEL_SERVER_READY(ch) \
101 (readl(&(ch)->srv_state) == CHANNELSRV_READY)
Ken Coxe4238122014-03-04 07:58:06 -0600102
103#define ULTRA_VALID_CHANNELCLI_TRANSITION(o, n) \
104 (((((o) == CHANNELCLI_DETACHED) && ((n) == CHANNELCLI_DISABLED)) || \
105 (((o) == CHANNELCLI_ATTACHING) && ((n) == CHANNELCLI_DISABLED)) || \
106 (((o) == CHANNELCLI_ATTACHED) && ((n) == CHANNELCLI_DISABLED)) || \
107 (((o) == CHANNELCLI_ATTACHING) && ((n) == CHANNELCLI_DETACHED)) || \
108 (((o) == CHANNELCLI_ATTACHED) && ((n) == CHANNELCLI_DETACHED)) || \
109 (((o) == CHANNELCLI_DETACHED) && ((n) == CHANNELCLI_ATTACHING)) || \
110 (((o) == CHANNELCLI_ATTACHING) && ((n) == CHANNELCLI_ATTACHED)) || \
111 (((o) == CHANNELCLI_DETACHED) && ((n) == CHANNELCLI_ATTACHED)) || \
112 (((o) == CHANNELCLI_BUSY) && ((n) == CHANNELCLI_ATTACHED)) || \
113 (((o) == CHANNELCLI_ATTACHED) && ((n) == CHANNELCLI_BUSY)) || \
114 (((o) == CHANNELCLI_DETACHED) && ((n) == CHANNELCLI_OWNED)) || \
115 (((o) == CHANNELCLI_DISABLED) && ((n) == CHANNELCLI_OWNED)) || \
116 (((o) == CHANNELCLI_ATTACHING) && ((n) == CHANNELCLI_OWNED)) || \
117 (((o) == CHANNELCLI_ATTACHED) && ((n) == CHANNELCLI_OWNED)) || \
118 (((o) == CHANNELCLI_BUSY) && ((n) == CHANNELCLI_OWNED)) || (0)) \
119 ? (1) : (0))
120
Ken Coxe4238122014-03-04 07:58:06 -0600121/* Values for ULTRA_CHANNEL_PROTOCOL.CliErrorBoot: */
122/* throttling invalid boot channel statetransition error due to client
Erik Arfvidson180e2762015-11-17 13:34:57 -0500123 * disabled
124 */
Ken Coxe4238122014-03-04 07:58:06 -0600125#define ULTRA_CLIERRORBOOT_THROTTLEMSG_DISABLED 0x01
126
127/* throttling invalid boot channel statetransition error due to client
Erik Arfvidson180e2762015-11-17 13:34:57 -0500128 * not attached
129 */
Ken Coxe4238122014-03-04 07:58:06 -0600130#define ULTRA_CLIERRORBOOT_THROTTLEMSG_NOTATTACHED 0x02
131
132/* throttling invalid boot channel statetransition error due to busy channel */
133#define ULTRA_CLIERRORBOOT_THROTTLEMSG_BUSY 0x04
134
135/* Values for ULTRA_CHANNEL_PROTOCOL.CliErrorOS: */
136/* throttling invalid guest OS channel statetransition error due to
Erik Arfvidson180e2762015-11-17 13:34:57 -0500137 * client disabled
138 */
Ken Coxe4238122014-03-04 07:58:06 -0600139#define ULTRA_CLIERROROS_THROTTLEMSG_DISABLED 0x01
140
141/* throttling invalid guest OS channel statetransition error due to
Erik Arfvidson180e2762015-11-17 13:34:57 -0500142 * client not attached
143 */
Ken Coxe4238122014-03-04 07:58:06 -0600144#define ULTRA_CLIERROROS_THROTTLEMSG_NOTATTACHED 0x02
145
146/* throttling invalid guest OS channel statetransition error due to
Erik Arfvidson180e2762015-11-17 13:34:57 -0500147 * busy channel
148 */
Ken Coxe4238122014-03-04 07:58:06 -0600149#define ULTRA_CLIERROROS_THROTTLEMSG_BUSY 0x04
150
151/* Values for ULTRA_CHANNEL_PROTOCOL.Features: This define exists so
Erik Arfvidson180e2762015-11-17 13:34:57 -0500152 * that windows guest can look at the FeatureFlags in the io channel,
153 * and configure the windows driver to use interrupts or not based on
154 * this setting. This flag is set in uislib after the
155 * ULTRA_VHBA_init_channel is called. All feature bits for all
156 * channels should be defined here. The io channel feature bits are
157 * defined right here
158 */
Ken Coxe4238122014-03-04 07:58:06 -0600159#define ULTRA_IO_DRIVER_ENABLES_INTS (0x1ULL << 1)
160#define ULTRA_IO_CHANNEL_IS_POLLING (0x1ULL << 3)
161#define ULTRA_IO_IOVM_IS_OK_WITH_DRIVER_DISABLING_INTS (0x1ULL << 4)
162#define ULTRA_IO_DRIVER_DISABLES_INTS (0x1ULL << 5)
163#define ULTRA_IO_DRIVER_SUPPORTS_ENHANCED_RCVBUF_CHECKING (0x1ULL << 6)
164
Ken Coxe4238122014-03-04 07:58:06 -0600165/* Common Channel Header */
Benjamin Romer9fd1b952014-10-23 14:29:55 -0400166struct channel_header {
Benjamin Romera8a31f62014-10-23 14:29:56 -0400167 u64 signature; /* Signature */
168 u32 legacy_state; /* DEPRECATED - being replaced by */
Erik Arfvidson180e2762015-11-17 13:34:57 -0500169 /* SrvState, CliStateBoot, and CliStateOS below */
Benjamin Romera8a31f62014-10-23 14:29:56 -0400170 u32 header_size; /* sizeof(struct channel_header) */
171 u64 size; /* Total size of this channel in bytes */
172 u64 features; /* Flags to modify behavior */
173 uuid_le chtype; /* Channel type: data, bus, control, etc. */
174 u64 partition_handle; /* ID of guest partition */
175 u64 handle; /* Device number of this channel in client */
176 u64 ch_space_offset; /* Offset in bytes to channel specific area */
177 u32 version_id; /* struct channel_header Version ID */
178 u32 partition_index; /* Index of guest partition */
179 uuid_le zone_uuid; /* Guid of Channel's zone */
180 u32 cli_str_offset; /* offset from channel header to
Ken Coxe4238122014-03-04 07:58:06 -0600181 * nul-terminated ClientString (0 if
Erik Arfvidson180e2762015-11-17 13:34:57 -0500182 * ClientString not present)
183 */
Benjamin Romera8a31f62014-10-23 14:29:56 -0400184 u32 cli_state_boot; /* CHANNEL_CLIENTSTATE of pre-boot
Erik Arfvidson180e2762015-11-17 13:34:57 -0500185 * EFI client of this channel
186 */
Benjamin Romera8a31f62014-10-23 14:29:56 -0400187 u32 cmd_state_cli; /* CHANNEL_COMMANDSTATE (overloaded in
Ken Coxe4238122014-03-04 07:58:06 -0600188 * Windows drivers, see ServerStateUp,
Erik Arfvidson180e2762015-11-17 13:34:57 -0500189 * ServerStateDown, etc)
190 */
Benjamin Romera8a31f62014-10-23 14:29:56 -0400191 u32 cli_state_os; /* CHANNEL_CLIENTSTATE of Guest OS
Erik Arfvidson180e2762015-11-17 13:34:57 -0500192 * client of this channel
193 */
Benjamin Romera8a31f62014-10-23 14:29:56 -0400194 u32 ch_characteristic; /* CHANNEL_CHARACTERISTIC_<xxx> */
195 u32 cmd_state_srv; /* CHANNEL_COMMANDSTATE (overloaded in
Ken Coxe4238122014-03-04 07:58:06 -0600196 * Windows drivers, see ServerStateUp,
Erik Arfvidson180e2762015-11-17 13:34:57 -0500197 * ServerStateDown, etc)
198 */
Benjamin Romera8a31f62014-10-23 14:29:56 -0400199 u32 srv_state; /* CHANNEL_SERVERSTATE */
200 u8 cli_error_boot; /* bits to indicate err states for
Ken Coxe4238122014-03-04 07:58:06 -0600201 * boot clients, so err messages can
Erik Arfvidson180e2762015-11-17 13:34:57 -0500202 * be throttled
203 */
Benjamin Romera8a31f62014-10-23 14:29:56 -0400204 u8 cli_error_os; /* bits to indicate err states for OS
Ken Coxe4238122014-03-04 07:58:06 -0600205 * clients, so err messages can be
Erik Arfvidson180e2762015-11-17 13:34:57 -0500206 * throttled
207 */
Benjamin Romera8a31f62014-10-23 14:29:56 -0400208 u8 filler[1]; /* Pad out to 128 byte cacheline */
Ken Coxe4238122014-03-04 07:58:06 -0600209 /* Please add all new single-byte values below here */
Benjamin Romera8a31f62014-10-23 14:29:56 -0400210 u8 recover_channel;
David Kershner9f00be72015-10-12 15:19:39 -0400211} __packed;
Ken Coxe4238122014-03-04 07:58:06 -0600212
213#define ULTRA_CHANNEL_ENABLE_INTS (0x1ULL << 0)
214
215/* Subheader for the Signal Type variation of the Common Channel */
Benjamin Romere0fed862014-10-23 14:30:03 -0400216struct signal_queue_header {
Ken Coxe4238122014-03-04 07:58:06 -0600217 /* 1st cache line */
Benjamin Romer153cf712014-10-23 14:30:04 -0400218 u32 version; /* SIGNAL_QUEUE_HEADER Version ID */
219 u32 chtype; /* Queue type: storage, network */
220 u64 size; /* Total size of this queue in bytes */
221 u64 sig_base_offset; /* Offset to signal queue area */
222 u64 features; /* Flags to modify behavior */
223 u64 num_sent; /* Total # of signals placed in this queue */
224 u64 num_overflows; /* Total # of inserts failed due to
Erik Arfvidson180e2762015-11-17 13:34:57 -0500225 * full queue
226 */
Benjamin Romer153cf712014-10-23 14:30:04 -0400227 u32 signal_size; /* Total size of a signal for this queue */
228 u32 max_slots; /* Max # of slots in queue, 1 slot is
Erik Arfvidson180e2762015-11-17 13:34:57 -0500229 * always empty
230 */
Benjamin Romer153cf712014-10-23 14:30:04 -0400231 u32 max_signals; /* Max # of signals in queue
Erik Arfvidson180e2762015-11-17 13:34:57 -0500232 * (MaxSignalSlots-1)
233 */
Benjamin Romer153cf712014-10-23 14:30:04 -0400234 u32 head; /* Queue head signal # */
Ken Coxe4238122014-03-04 07:58:06 -0600235 /* 2nd cache line */
Benjamin Romer153cf712014-10-23 14:30:04 -0400236 u64 num_received; /* Total # of signals removed from this queue */
Erik Arfvidson180e2762015-11-17 13:34:57 -0500237 u32 tail; /* Queue tail signal */
Benjamin Romer153cf712014-10-23 14:30:04 -0400238 u32 reserved1; /* Reserved field */
239 u64 reserved2; /* Reserved field */
240 u64 client_queue;
241 u64 num_irq_received; /* Total # of Interrupts received. This
Erik Arfvidson180e2762015-11-17 13:34:57 -0500242 * is incremented by the ISR in the
243 * guest windows driver
244 */
Benjamin Romer153cf712014-10-23 14:30:04 -0400245 u64 num_empty; /* Number of times that visor_signal_remove
Erik Arfvidson180e2762015-11-17 13:34:57 -0500246 * is called and returned Empty Status.
247 */
Benjamin Romer153cf712014-10-23 14:30:04 -0400248 u32 errorflags; /* Error bits set during SignalReinit
Ken Coxe4238122014-03-04 07:58:06 -0600249 * to denote trouble with client's
Erik Arfvidson180e2762015-11-17 13:34:57 -0500250 * fields
251 */
Benjamin Romer153cf712014-10-23 14:30:04 -0400252 u8 filler[12]; /* Pad out to 64 byte cacheline */
David Kershner9f00be72015-10-12 15:19:39 -0400253} __packed;
Ken Coxe4238122014-03-04 07:58:06 -0600254
Benjamin Romer29fe22b2014-10-23 14:30:09 -0400255#define spar_signal_init(chan, QHDRFLD, QDATAFLD, QDATATYPE, ver, typ) \
Ken Coxe4238122014-03-04 07:58:06 -0600256 do { \
Benjamin Romer30de72d2014-07-31 12:00:59 -0400257 memset(&chan->QHDRFLD, 0, sizeof(chan->QHDRFLD)); \
Benjamin Romer29fe22b2014-10-23 14:30:09 -0400258 chan->QHDRFLD.version = ver; \
259 chan->QHDRFLD.chtype = typ; \
260 chan->QHDRFLD.size = sizeof(chan->QDATAFLD); \
261 chan->QHDRFLD.signal_size = sizeof(QDATATYPE); \
David Kershner54bf4d42015-10-12 15:19:40 -0400262 chan->QHDRFLD.sig_base_offset = (u64)(chan->QDATAFLD) - \
Benjamin Romer90f3b502014-07-31 12:00:58 -0400263 (u64)(&chan->QHDRFLD); \
Benjamin Romer29fe22b2014-10-23 14:30:09 -0400264 chan->QHDRFLD.max_slots = \
David Kershner54bf4d42015-10-12 15:19:40 -0400265 sizeof(chan->QDATAFLD) / sizeof(QDATATYPE); \
266 chan->QHDRFLD.max_signals = chan->QHDRFLD.max_slots - 1;\
Ken Coxe4238122014-03-04 07:58:06 -0600267 } while (0)
268
269/* Generic function useful for validating any type of channel when it is
270 * received by the client that will be accessing the channel.
271 * Note that <logCtx> is only needed for callers in the EFI environment, and
272 * is used to pass the EFI_DIAG_CAPTURE_PROTOCOL needed to log messages.
273 */
274static inline int
Benjamin Romer93a84562014-10-23 14:30:05 -0400275spar_check_channel_client(void __iomem *ch,
276 uuid_le expected_uuid,
277 char *chname,
278 u64 expected_min_bytes,
279 u32 expected_version,
280 u64 expected_signature)
Ken Coxe4238122014-03-04 07:58:06 -0600281{
Benjamin Romer93a84562014-10-23 14:30:05 -0400282 if (uuid_le_cmp(expected_uuid, NULL_UUID_LE) != 0) {
Luke Hart635ecc52014-09-12 10:48:33 +0100283 uuid_le guid;
284
Benjamin Romer35b81172014-09-22 13:45:03 -0400285 memcpy_fromio(&guid,
Benjamin Romer93a84562014-10-23 14:30:05 -0400286 &((struct channel_header __iomem *)(ch))->chtype,
287 sizeof(guid));
Ken Coxe4238122014-03-04 07:58:06 -0600288 /* caller wants us to verify type GUID */
Benjamin Romer93a84562014-10-23 14:30:05 -0400289 if (uuid_le_cmp(guid, expected_uuid) != 0) {
Benjamin Romere2706692014-10-23 14:29:49 -0400290 pr_err("Channel mismatch on channel=%s(%pUL) field=type expected=%pUL actual=%pUL\n",
Benjamin Romer93a84562014-10-23 14:30:05 -0400291 chname, &expected_uuid,
292 &expected_uuid, &guid);
Ken Coxe4238122014-03-04 07:58:06 -0600293 return 0;
294 }
Luke Hart635ecc52014-09-12 10:48:33 +0100295 }
Erik Arfvidson180e2762015-11-17 13:34:57 -0500296 if (expected_min_bytes > 0) { /* verify channel size */
Benjamin Romer9fd1b952014-10-23 14:29:55 -0400297 unsigned long long bytes =
298 readq(&((struct channel_header __iomem *)
Benjamin Romer93a84562014-10-23 14:30:05 -0400299 (ch))->size);
300 if (bytes < expected_min_bytes) {
Benjamin Romere2706692014-10-23 14:29:49 -0400301 pr_err("Channel mismatch on channel=%s(%pUL) field=size expected=0x%-8.8Lx actual=0x%-8.8Lx\n",
Benjamin Romer93a84562014-10-23 14:30:05 -0400302 chname, &expected_uuid,
303 (unsigned long long)expected_min_bytes, bytes);
Ken Coxe4238122014-03-04 07:58:06 -0600304 return 0;
305 }
Benjamin Romere2706692014-10-23 14:29:49 -0400306 }
Erik Arfvidson180e2762015-11-17 13:34:57 -0500307 if (expected_version > 0) { /* verify channel version */
Benjamin Romer9fd1b952014-10-23 14:29:55 -0400308 unsigned long ver = readl(&((struct channel_header __iomem *)
Benjamin Romer93a84562014-10-23 14:30:05 -0400309 (ch))->version_id);
310 if (ver != expected_version) {
Benjamin Romere2706692014-10-23 14:29:49 -0400311 pr_err("Channel mismatch on channel=%s(%pUL) field=version expected=0x%-8.8lx actual=0x%-8.8lx\n",
Benjamin Romer93a84562014-10-23 14:30:05 -0400312 chname, &expected_uuid,
313 (unsigned long)expected_version, ver);
Ken Coxe4238122014-03-04 07:58:06 -0600314 return 0;
315 }
Benjamin Romere2706692014-10-23 14:29:49 -0400316 }
Erik Arfvidson180e2762015-11-17 13:34:57 -0500317 if (expected_signature > 0) { /* verify channel signature */
Benjamin Romer9fd1b952014-10-23 14:29:55 -0400318 unsigned long long sig =
319 readq(&((struct channel_header __iomem *)
Benjamin Romer93a84562014-10-23 14:30:05 -0400320 (ch))->signature);
321 if (sig != expected_signature) {
Benjamin Romere2706692014-10-23 14:29:49 -0400322 pr_err("Channel mismatch on channel=%s(%pUL) field=signature expected=0x%-8.8llx actual=0x%-8.8llx\n",
Benjamin Romer93a84562014-10-23 14:30:05 -0400323 chname, &expected_uuid,
324 expected_signature, sig);
Ken Coxe4238122014-03-04 07:58:06 -0600325 return 0;
326 }
Benjamin Romere2706692014-10-23 14:29:49 -0400327 }
Ken Coxe4238122014-03-04 07:58:06 -0600328 return 1;
329}
330
Benjamin Romer10c5ef62014-10-23 14:30:11 -0400331/* Generic function useful for validating any type of channel when it is about
332 * to be initialized by the server of the channel.
333 * Note that <logCtx> is only needed for callers in the EFI environment, and
334 * is used to pass the EFI_DIAG_CAPTURE_PROTOCOL needed to log messages.
335 */
336static inline int spar_check_channel_server(uuid_le typeuuid, char *name,
337 u64 expected_min_bytes,
338 u64 actual_bytes)
339{
Erik Arfvidson180e2762015-11-17 13:34:57 -0500340 if (expected_min_bytes > 0) /* verify channel size */
Benjamin Romer10c5ef62014-10-23 14:30:11 -0400341 if (actual_bytes < expected_min_bytes) {
342 pr_err("Channel mismatch on channel=%s(%pUL) field=size expected=0x%-8.8llx actual=0x%-8.8llx\n",
343 name, &typeuuid, expected_min_bytes,
344 actual_bytes);
345 return 0;
346 }
347 return 1;
348}
349
Ken Coxe4238122014-03-04 07:58:06 -0600350/* Given a file pathname <s> (with '/' or '\' separating directory nodes),
351 * returns a pointer to the beginning of a node within that pathname such
352 * that the number of nodes from that pointer to the end of the string is
353 * NOT more than <n>. Note that if the pathname has less than <n> nodes
354 * in it, the return pointer will be to the beginning of the string.
355 */
Benjamin Romerc2422332014-07-29 15:09:40 -0400356static inline u8 *
Benjamin Romer8800bfb2014-10-23 14:29:59 -0400357pathname_last_n_nodes(u8 *s, unsigned int n)
Ken Coxe4238122014-03-04 07:58:06 -0600358{
Benjamin Romerc2422332014-07-29 15:09:40 -0400359 u8 *p = s;
Ken Coxe4238122014-03-04 07:58:06 -0600360 unsigned int node_count = 0;
Melike Yurtogluaff6de02014-10-02 11:13:53 +0300361
Ken Coxe4238122014-03-04 07:58:06 -0600362 while (*p != '\0') {
363 if ((*p == '/') || (*p == '\\'))
364 node_count++;
365 p++;
366 }
367 if (node_count <= n)
368 return s;
369 while (n > 0) {
370 p--;
371 if (p == s)
372 break; /* should never happen, unless someone
373 * is changing the string while we are
Erik Arfvidson180e2762015-11-17 13:34:57 -0500374 * looking at it!!
375 */
Ken Coxe4238122014-03-04 07:58:06 -0600376 if ((*p == '/') || (*p == '\\'))
377 n--;
378 }
379 return p + 1;
380}
381
382static inline int
Benjamin Romer9f169302014-10-23 14:30:01 -0400383spar_channel_client_acquire_os(void __iomem *ch, u8 *id)
Ken Coxe4238122014-03-04 07:58:06 -0600384{
Benjamin Romer9f169302014-10-23 14:30:01 -0400385 struct channel_header __iomem *hdr = ch;
Ken Coxe4238122014-03-04 07:58:06 -0600386
Benjamin Romer9f169302014-10-23 14:30:01 -0400387 if (readl(&hdr->cli_state_os) == CHANNELCLI_DISABLED) {
388 if ((readb(&hdr->cli_error_os)
Ken Coxa8d7f212014-03-13 15:39:19 -0500389 & ULTRA_CLIERROROS_THROTTLEMSG_DISABLED) == 0) {
Ken Coxe4238122014-03-04 07:58:06 -0600390 /* we are NOT throttling this message */
Benjamin Romer9f169302014-10-23 14:30:01 -0400391 writeb(readb(&hdr->cli_error_os) |
Ken Coxa8d7f212014-03-13 15:39:19 -0500392 ULTRA_CLIERROROS_THROTTLEMSG_DISABLED,
Benjamin Romer9f169302014-10-23 14:30:01 -0400393 &hdr->cli_error_os);
Ken Coxe4238122014-03-04 07:58:06 -0600394 /* throttle until acquire successful */
395
Benjamin Romer9f169302014-10-23 14:30:01 -0400396 pr_info("%s Channel StateTransition INVALID! - acquire failed because OS client DISABLED\n",
397 id);
Ken Coxe4238122014-03-04 07:58:06 -0600398 }
399 return 0;
400 }
Benjamin Romerbac9e372014-10-23 14:30:08 -0400401 if ((readl(&hdr->cli_state_os) != CHANNELCLI_OWNED) &&
402 (readl(&hdr->cli_state_boot) == CHANNELCLI_DISABLED)) {
Ken Coxe4238122014-03-04 07:58:06 -0600403 /* Our competitor is DISABLED, so we can transition to OWNED */
Benjamin Romer9f169302014-10-23 14:30:01 -0400404 pr_info("%s Channel StateTransition (%s) %s(%d)-->%s(%d)\n",
405 id, "cli_state_os",
406 ULTRA_CHANNELCLI_STRING(readl(&hdr->cli_state_os)),
407 readl(&hdr->cli_state_os),
Benjamin Romerddb38ae2014-10-23 14:29:50 -0400408 ULTRA_CHANNELCLI_STRING(CHANNELCLI_OWNED),
Benjamin Romer9f169302014-10-23 14:30:01 -0400409 CHANNELCLI_OWNED);
410 writel(CHANNELCLI_OWNED, &hdr->cli_state_os);
Benjamin Romere87cfde2014-08-02 22:03:38 -0400411 mb(); /* required for channel synch */
Ken Coxe4238122014-03-04 07:58:06 -0600412 }
Benjamin Romer9f169302014-10-23 14:30:01 -0400413 if (readl(&hdr->cli_state_os) == CHANNELCLI_OWNED) {
Erik Arfvidson800aecc2016-03-24 09:18:09 -0400414 if (readb(&hdr->cli_error_os)) {
Ken Coxe4238122014-03-04 07:58:06 -0600415 /* we are in an error msg throttling state;
Erik Arfvidson180e2762015-11-17 13:34:57 -0500416 * come out of it
417 */
Benjamin Romer9f169302014-10-23 14:30:01 -0400418 pr_info("%s Channel OS client acquire now successful\n",
419 id);
420 writeb(0, &hdr->cli_error_os);
Ken Coxe4238122014-03-04 07:58:06 -0600421 }
422 return 1;
423 }
424
425 /* We have to do it the "hard way". We transition to BUSY,
Erik Arfvidson180e2762015-11-17 13:34:57 -0500426 * and can use the channel iff our competitor has not also
427 * transitioned to BUSY.
428 */
Benjamin Romer9f169302014-10-23 14:30:01 -0400429 if (readl(&hdr->cli_state_os) != CHANNELCLI_ATTACHED) {
430 if ((readb(&hdr->cli_error_os)
Ken Coxa8d7f212014-03-13 15:39:19 -0500431 & ULTRA_CLIERROROS_THROTTLEMSG_NOTATTACHED) == 0) {
Ken Coxe4238122014-03-04 07:58:06 -0600432 /* we are NOT throttling this message */
Benjamin Romer9f169302014-10-23 14:30:01 -0400433 writeb(readb(&hdr->cli_error_os) |
Ken Coxa8d7f212014-03-13 15:39:19 -0500434 ULTRA_CLIERROROS_THROTTLEMSG_NOTATTACHED,
Benjamin Romer9f169302014-10-23 14:30:01 -0400435 &hdr->cli_error_os);
Ken Coxe4238122014-03-04 07:58:06 -0600436 /* throttle until acquire successful */
Benjamin Romer9f169302014-10-23 14:30:01 -0400437 pr_info("%s Channel StateTransition INVALID! - acquire failed because OS client NOT ATTACHED (state=%s(%d))\n",
438 id, ULTRA_CHANNELCLI_STRING(
439 readl(&hdr->cli_state_os)),
440 readl(&hdr->cli_state_os));
Ken Coxe4238122014-03-04 07:58:06 -0600441 }
442 return 0;
443 }
Benjamin Romer9f169302014-10-23 14:30:01 -0400444 writel(CHANNELCLI_BUSY, &hdr->cli_state_os);
Benjamin Romere87cfde2014-08-02 22:03:38 -0400445 mb(); /* required for channel synch */
Benjamin Romer9f169302014-10-23 14:30:01 -0400446 if (readl(&hdr->cli_state_boot) == CHANNELCLI_BUSY) {
447 if ((readb(&hdr->cli_error_os)
Ken Coxa8d7f212014-03-13 15:39:19 -0500448 & ULTRA_CLIERROROS_THROTTLEMSG_BUSY) == 0) {
Ken Coxe4238122014-03-04 07:58:06 -0600449 /* we are NOT throttling this message */
Benjamin Romer9f169302014-10-23 14:30:01 -0400450 writeb(readb(&hdr->cli_error_os) |
Ken Coxa8d7f212014-03-13 15:39:19 -0500451 ULTRA_CLIERROROS_THROTTLEMSG_BUSY,
Benjamin Romer9f169302014-10-23 14:30:01 -0400452 &hdr->cli_error_os);
Ken Coxe4238122014-03-04 07:58:06 -0600453 /* throttle until acquire successful */
Benjamin Romer9f169302014-10-23 14:30:01 -0400454 pr_info("%s Channel StateTransition failed - host OS acquire failed because boot BUSY\n",
455 id);
Ken Coxe4238122014-03-04 07:58:06 -0600456 }
Ken Coxa8d7f212014-03-13 15:39:19 -0500457 /* reset busy */
Benjamin Romer9f169302014-10-23 14:30:01 -0400458 writel(CHANNELCLI_ATTACHED, &hdr->cli_state_os);
Benjamin Romere87cfde2014-08-02 22:03:38 -0400459 mb(); /* required for channel synch */
Ken Coxe4238122014-03-04 07:58:06 -0600460 return 0;
461 }
Erik Arfvidson800aecc2016-03-24 09:18:09 -0400462 if (readb(&hdr->cli_error_os)) {
Ken Coxe4238122014-03-04 07:58:06 -0600463 /* we are in an error msg throttling state; come out of it */
Benjamin Romer9f169302014-10-23 14:30:01 -0400464 pr_info("%s Channel OS client acquire now successful\n", id);
465 writeb(0, &hdr->cli_error_os);
Ken Coxe4238122014-03-04 07:58:06 -0600466 }
467 return 1;
468}
469
470static inline void
Benjamin Romer08598912014-10-23 14:30:02 -0400471spar_channel_client_release_os(void __iomem *ch, u8 *id)
Ken Coxe4238122014-03-04 07:58:06 -0600472{
Benjamin Romer08598912014-10-23 14:30:02 -0400473 struct channel_header __iomem *hdr = ch;
Melike Yurtogluaff6de02014-10-02 11:13:53 +0300474
Erik Arfvidson800aecc2016-03-24 09:18:09 -0400475 if (readb(&hdr->cli_error_os)) {
Ken Coxe4238122014-03-04 07:58:06 -0600476 /* we are in an error msg throttling state; come out of it */
Benjamin Romer08598912014-10-23 14:30:02 -0400477 pr_info("%s Channel OS client error state cleared\n", id);
478 writeb(0, &hdr->cli_error_os);
Ken Coxe4238122014-03-04 07:58:06 -0600479 }
Benjamin Romer08598912014-10-23 14:30:02 -0400480 if (readl(&hdr->cli_state_os) == CHANNELCLI_OWNED)
Ken Coxe4238122014-03-04 07:58:06 -0600481 return;
Benjamin Romer08598912014-10-23 14:30:02 -0400482 if (readl(&hdr->cli_state_os) != CHANNELCLI_BUSY) {
483 pr_info("%s Channel StateTransition INVALID! - release failed because OS client NOT BUSY (state=%s(%d))\n",
484 id, ULTRA_CHANNELCLI_STRING(
485 readl(&hdr->cli_state_os)),
486 readl(&hdr->cli_state_os));
Ken Coxe4238122014-03-04 07:58:06 -0600487 /* return; */
488 }
Benjamin Romer08598912014-10-23 14:30:02 -0400489 writel(CHANNELCLI_ATTACHED, &hdr->cli_state_os); /* release busy */
Ken Coxe4238122014-03-04 07:58:06 -0600490}
491
492/*
493* Routine Description:
494* Tries to insert the prebuilt signal pointed to by pSignal into the nth
495* Queue of the Channel pointed to by pChannel
496*
497* Parameters:
498* pChannel: (IN) points to the IO Channel
499* Queue: (IN) nth Queue of the IO Channel
500* pSignal: (IN) pointer to the signal
501*
502* Assumptions:
503* - pChannel, Queue and pSignal are valid.
504* - If insertion fails due to a full queue, the caller will determine the
505* retry policy (e.g. wait & try again, report an error, etc.).
506*
507* Return value: 1 if the insertion succeeds, 0 if the queue was
508* full.
509*/
510
Benjamin Romer93a84562014-10-23 14:30:05 -0400511unsigned char spar_signal_insert(struct channel_header __iomem *ch, u32 queue,
512 void *sig);
Ken Coxe4238122014-03-04 07:58:06 -0600513
514/*
515* Routine Description:
516* Removes one signal from Channel pChannel's nth Queue at the
517* time of the call and copies it into the memory pointed to by
518* pSignal.
519*
520* Parameters:
521* pChannel: (IN) points to the IO Channel
522* Queue: (IN) nth Queue of the IO Channel
523* pSignal: (IN) pointer to where the signals are to be copied
524*
525* Assumptions:
526* - pChannel and Queue are valid.
527* - pSignal points to a memory area large enough to hold queue's SignalSize
528*
529* Return value: 1 if the removal succeeds, 0 if the queue was
530* empty.
531*/
532
Benjamin Romer3f12c5f2014-10-23 14:30:06 -0400533unsigned char spar_signal_remove(struct channel_header __iomem *ch, u32 queue,
534 void *sig);
Ken Coxe4238122014-03-04 07:58:06 -0600535
536/*
537* Routine Description:
538* Removes all signals present in Channel pChannel's nth Queue at the
539* time of the call and copies them into the memory pointed to by
540* pSignal. Returns the # of signals copied as the value of the routine.
541*
542* Parameters:
543* pChannel: (IN) points to the IO Channel
544* Queue: (IN) nth Queue of the IO Channel
545* pSignal: (IN) pointer to where the signals are to be copied
546*
547* Assumptions:
548* - pChannel and Queue are valid.
549* - pSignal points to a memory area large enough to hold Queue's MaxSignals
550* # of signals, each of which is Queue's SignalSize.
551*
552* Return value:
553* # of signals copied.
554*/
Benjamin Romerc11cf5f2014-10-23 14:30:10 -0400555unsigned int spar_signal_remove_all(struct channel_header *ch, u32 queue,
556 void *sig);
Ken Coxe4238122014-03-04 07:58:06 -0600557
558/*
559* Routine Description:
560* Determine whether a signal queue is empty.
561*
562* Parameters:
563* pChannel: (IN) points to the IO Channel
564* Queue: (IN) nth Queue of the IO Channel
565*
566* Return value:
567* 1 if the signal queue is empty, 0 otherwise.
568*/
Benjamin Romera17f5b42014-10-23 14:30:07 -0400569unsigned char spar_signalqueue_empty(struct channel_header __iomem *ch,
570 u32 queue);
Ken Coxe4238122014-03-04 07:58:06 -0600571
572#endif