From: David Kershner Date: Wed, 13 May 2015 17:22:04 +0000 (-0400) Subject: staging: unisys: Move channel.h to include. Controvlm to visorbus X-Git-Url: http://drtracing.org/?a=commitdiff_plain;h=63b0179c397b70029dc28d166211354697fb1382;p=deliverable%2Flinux.git staging: unisys: Move channel.h to include. Controvlm to visorbus Channel.h is used by all channels, it needs to be in include. Controlvm Channel is only used by visorbus, it needs to just be there. Signed-off-by: David Kershner Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/staging/unisys/common-spar/include/channels/channel.h b/drivers/staging/unisys/common-spar/include/channels/channel.h deleted file mode 100644 index 6fb6e5b3ddaf..000000000000 --- a/drivers/staging/unisys/common-spar/include/channels/channel.h +++ /dev/null @@ -1,590 +0,0 @@ -/* Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -#ifndef __CHANNEL_H__ -#define __CHANNEL_H__ - -#include -#include -#include - -/* -* Whenever this file is changed a corresponding change must be made in -* the Console/ServicePart/visordiag_early/supervisor_channel.h file -* which is needed for Linux kernel compiles. These two files must be -* in sync. -*/ - -/* define the following to prevent include nesting in kernel header - * files of similar abbreviated content - */ -#define __SUPERVISOR_CHANNEL_H__ - -#define SIGNATURE_16(A, B) ((A) | (B<<8)) -#define SIGNATURE_32(A, B, C, D) \ - (SIGNATURE_16(A, B) | (SIGNATURE_16(C, D) << 16)) -#define SIGNATURE_64(A, B, C, D, E, F, G, H) \ - (SIGNATURE_32(A, B, C, D) | ((u64)(SIGNATURE_32(E, F, G, H)) << 32)) - -#ifndef lengthof -#define lengthof(TYPE, MEMBER) (sizeof(((TYPE *)0)->MEMBER)) -#endif -#ifndef COVERQ -#define COVERQ(v, d) (((v)+(d)-1) / (d)) -#endif -#ifndef COVER -#define COVER(v, d) ((d)*COVERQ(v, d)) -#endif - -#define ULTRA_CHANNEL_PROTOCOL_SIGNATURE SIGNATURE_32('E', 'C', 'N', 'L') - -enum channel_serverstate { - CHANNELSRV_UNINITIALIZED = 0, /* channel is in an undefined state */ - CHANNELSRV_READY = 1 /* channel has been initialized by server */ -}; - -enum channel_clientstate { - CHANNELCLI_DETACHED = 0, - CHANNELCLI_DISABLED = 1, /* client can see channel but is NOT - * allowed to use it unless given TBD - * explicit request (should actually be - * < DETACHED) */ - CHANNELCLI_ATTACHING = 2, /* legacy EFI client request - * for EFI server to attach */ - CHANNELCLI_ATTACHED = 3, /* idle, but client may want - * to use channel any time */ - CHANNELCLI_BUSY = 4, /* client either wants to use or is - * using channel */ - CHANNELCLI_OWNED = 5 /* "no worries" state - client can - * access channel anytime */ -}; - -static inline const u8 * -ULTRA_CHANNELCLI_STRING(u32 v) -{ - switch (v) { - case CHANNELCLI_DETACHED: - return (const u8 *)("DETACHED"); - case CHANNELCLI_DISABLED: - return (const u8 *)("DISABLED"); - case CHANNELCLI_ATTACHING: - return (const u8 *)("ATTACHING"); - case CHANNELCLI_ATTACHED: - return (const u8 *)("ATTACHED"); - case CHANNELCLI_BUSY: - return (const u8 *)("BUSY"); - case CHANNELCLI_OWNED: - return (const u8 *)("OWNED"); - default: - break; - } - return (const u8 *)("?"); -} - -#define SPAR_CHANNEL_SERVER_READY(ch) \ - (readl(&(ch)->srv_state) == CHANNELSRV_READY) - -#define ULTRA_VALID_CHANNELCLI_TRANSITION(o, n) \ - (((((o) == CHANNELCLI_DETACHED) && ((n) == CHANNELCLI_DISABLED)) || \ - (((o) == CHANNELCLI_ATTACHING) && ((n) == CHANNELCLI_DISABLED)) || \ - (((o) == CHANNELCLI_ATTACHED) && ((n) == CHANNELCLI_DISABLED)) || \ - (((o) == CHANNELCLI_ATTACHING) && ((n) == CHANNELCLI_DETACHED)) || \ - (((o) == CHANNELCLI_ATTACHED) && ((n) == CHANNELCLI_DETACHED)) || \ - (((o) == CHANNELCLI_DETACHED) && ((n) == CHANNELCLI_ATTACHING)) || \ - (((o) == CHANNELCLI_ATTACHING) && ((n) == CHANNELCLI_ATTACHED)) || \ - (((o) == CHANNELCLI_DETACHED) && ((n) == CHANNELCLI_ATTACHED)) || \ - (((o) == CHANNELCLI_BUSY) && ((n) == CHANNELCLI_ATTACHED)) || \ - (((o) == CHANNELCLI_ATTACHED) && ((n) == CHANNELCLI_BUSY)) || \ - (((o) == CHANNELCLI_DETACHED) && ((n) == CHANNELCLI_OWNED)) || \ - (((o) == CHANNELCLI_DISABLED) && ((n) == CHANNELCLI_OWNED)) || \ - (((o) == CHANNELCLI_ATTACHING) && ((n) == CHANNELCLI_OWNED)) || \ - (((o) == CHANNELCLI_ATTACHED) && ((n) == CHANNELCLI_OWNED)) || \ - (((o) == CHANNELCLI_BUSY) && ((n) == CHANNELCLI_OWNED)) || (0)) \ - ? (1) : (0)) - -#define SPAR_CHANNEL_CLIENT_CHK_TRANSITION(old, new, id, log, \ - file, line) \ - do { \ - if (!ULTRA_VALID_CHANNELCLI_TRANSITION(old, new)) \ - pr_info("%s Channel StateTransition INVALID! (%s) %s(%d)-->%s(%d) @%s:%d\n", \ - id, "CliState", \ - ULTRA_CHANNELCLI_STRING(old), \ - old, \ - ULTRA_CHANNELCLI_STRING(new), \ - new, \ - pathname_last_n_nodes((u8 *)file, 4), \ - line); \ - } while (0) - -#define SPAR_CHANNEL_CLIENT_TRANSITION(ch, id, newstate, log) \ - do { \ - SPAR_CHANNEL_CLIENT_CHK_TRANSITION( \ - readl(&(((struct channel_header __iomem *)\ - (ch))->cli_state_os)), \ - newstate, id, log, __FILE__, __LINE__); \ - pr_info("%s Channel StateTransition (%s) %s(%d)-->%s(%d) @%s:%d\n", \ - id, "CliStateOS", \ - ULTRA_CHANNELCLI_STRING( \ - readl(&((struct channel_header __iomem *)\ - (ch))->cli_state_os)), \ - readl(&((struct channel_header __iomem *)\ - (ch))->cli_state_os), \ - ULTRA_CHANNELCLI_STRING(newstate), \ - newstate, \ - pathname_last_n_nodes(__FILE__, 4), __LINE__); \ - writel(newstate, &((struct channel_header __iomem *)\ - (ch))->cli_state_os); \ - mb(); /* required for channel synch */ \ - } while (0) - -/* Values for ULTRA_CHANNEL_PROTOCOL.CliErrorBoot: */ -/* throttling invalid boot channel statetransition error due to client - * disabled */ -#define ULTRA_CLIERRORBOOT_THROTTLEMSG_DISABLED 0x01 - -/* throttling invalid boot channel statetransition error due to client - * not attached */ -#define ULTRA_CLIERRORBOOT_THROTTLEMSG_NOTATTACHED 0x02 - -/* throttling invalid boot channel statetransition error due to busy channel */ -#define ULTRA_CLIERRORBOOT_THROTTLEMSG_BUSY 0x04 - -/* Values for ULTRA_CHANNEL_PROTOCOL.CliErrorOS: */ -/* throttling invalid guest OS channel statetransition error due to - * client disabled */ -#define ULTRA_CLIERROROS_THROTTLEMSG_DISABLED 0x01 - -/* throttling invalid guest OS channel statetransition error due to - * client not attached */ -#define ULTRA_CLIERROROS_THROTTLEMSG_NOTATTACHED 0x02 - -/* throttling invalid guest OS channel statetransition error due to - * busy channel */ -#define ULTRA_CLIERROROS_THROTTLEMSG_BUSY 0x04 - -/* Values for ULTRA_CHANNEL_PROTOCOL.Features: This define exists so -* that windows guest can look at the FeatureFlags in the io channel, -* and configure the windows driver to use interrupts or not based on -* this setting. This flag is set in uislib after the -* ULTRA_VHBA_init_channel is called. All feature bits for all -* channels should be defined here. The io channel feature bits are -* defined right here */ -#define ULTRA_IO_DRIVER_ENABLES_INTS (0x1ULL << 1) -#define ULTRA_IO_CHANNEL_IS_POLLING (0x1ULL << 3) -#define ULTRA_IO_IOVM_IS_OK_WITH_DRIVER_DISABLING_INTS (0x1ULL << 4) -#define ULTRA_IO_DRIVER_DISABLES_INTS (0x1ULL << 5) -#define ULTRA_IO_DRIVER_SUPPORTS_ENHANCED_RCVBUF_CHECKING (0x1ULL << 6) - -#pragma pack(push, 1) /* both GCC and VC now allow this pragma */ -/* Common Channel Header */ -struct channel_header { - u64 signature; /* Signature */ - u32 legacy_state; /* DEPRECATED - being replaced by */ - /* / SrvState, CliStateBoot, and CliStateOS below */ - u32 header_size; /* sizeof(struct channel_header) */ - u64 size; /* Total size of this channel in bytes */ - u64 features; /* Flags to modify behavior */ - uuid_le chtype; /* Channel type: data, bus, control, etc. */ - u64 partition_handle; /* ID of guest partition */ - u64 handle; /* Device number of this channel in client */ - u64 ch_space_offset; /* Offset in bytes to channel specific area */ - u32 version_id; /* struct channel_header Version ID */ - u32 partition_index; /* Index of guest partition */ - uuid_le zone_uuid; /* Guid of Channel's zone */ - u32 cli_str_offset; /* offset from channel header to - * nul-terminated ClientString (0 if - * ClientString not present) */ - u32 cli_state_boot; /* CHANNEL_CLIENTSTATE of pre-boot - * EFI client of this channel */ - u32 cmd_state_cli; /* CHANNEL_COMMANDSTATE (overloaded in - * Windows drivers, see ServerStateUp, - * ServerStateDown, etc) */ - u32 cli_state_os; /* CHANNEL_CLIENTSTATE of Guest OS - * client of this channel */ - u32 ch_characteristic; /* CHANNEL_CHARACTERISTIC_ */ - u32 cmd_state_srv; /* CHANNEL_COMMANDSTATE (overloaded in - * Windows drivers, see ServerStateUp, - * ServerStateDown, etc) */ - u32 srv_state; /* CHANNEL_SERVERSTATE */ - u8 cli_error_boot; /* bits to indicate err states for - * boot clients, so err messages can - * be throttled */ - u8 cli_error_os; /* bits to indicate err states for OS - * clients, so err messages can be - * throttled */ - u8 filler[1]; /* Pad out to 128 byte cacheline */ - /* Please add all new single-byte values below here */ - u8 recover_channel; -}; - -#define ULTRA_CHANNEL_ENABLE_INTS (0x1ULL << 0) - -/* Subheader for the Signal Type variation of the Common Channel */ -struct signal_queue_header { - /* 1st cache line */ - u32 version; /* SIGNAL_QUEUE_HEADER Version ID */ - u32 chtype; /* Queue type: storage, network */ - u64 size; /* Total size of this queue in bytes */ - u64 sig_base_offset; /* Offset to signal queue area */ - u64 features; /* Flags to modify behavior */ - u64 num_sent; /* Total # of signals placed in this queue */ - u64 num_overflows; /* Total # of inserts failed due to - * full queue */ - u32 signal_size; /* Total size of a signal for this queue */ - u32 max_slots; /* Max # of slots in queue, 1 slot is - * always empty */ - u32 max_signals; /* Max # of signals in queue - * (MaxSignalSlots-1) */ - u32 head; /* Queue head signal # */ - /* 2nd cache line */ - u64 num_received; /* Total # of signals removed from this queue */ - u32 tail; /* Queue tail signal # (on separate - * cache line) */ - u32 reserved1; /* Reserved field */ - u64 reserved2; /* Reserved field */ - u64 client_queue; - u64 num_irq_received; /* Total # of Interrupts received. This - * is incremented by the ISR in the - * guest windows driver */ - u64 num_empty; /* Number of times that visor_signal_remove - * is called and returned Empty - * Status. */ - u32 errorflags; /* Error bits set during SignalReinit - * to denote trouble with client's - * fields */ - u8 filler[12]; /* Pad out to 64 byte cacheline */ -}; - -#pragma pack(pop) - -#define spar_signal_init(chan, QHDRFLD, QDATAFLD, QDATATYPE, ver, typ) \ - do { \ - memset(&chan->QHDRFLD, 0, sizeof(chan->QHDRFLD)); \ - chan->QHDRFLD.version = ver; \ - chan->QHDRFLD.chtype = typ; \ - chan->QHDRFLD.size = sizeof(chan->QDATAFLD); \ - chan->QHDRFLD.signal_size = sizeof(QDATATYPE); \ - chan->QHDRFLD.sig_base_offset = (u64)(chan->QDATAFLD)- \ - (u64)(&chan->QHDRFLD); \ - chan->QHDRFLD.max_slots = \ - sizeof(chan->QDATAFLD)/sizeof(QDATATYPE); \ - chan->QHDRFLD.max_signals = chan->QHDRFLD.max_slots-1; \ - } while (0) - -/* Generic function useful for validating any type of channel when it is - * received by the client that will be accessing the channel. - * Note that is only needed for callers in the EFI environment, and - * is used to pass the EFI_DIAG_CAPTURE_PROTOCOL needed to log messages. - */ -static inline int -spar_check_channel_client(void __iomem *ch, - uuid_le expected_uuid, - char *chname, - u64 expected_min_bytes, - u32 expected_version, - u64 expected_signature) -{ - if (uuid_le_cmp(expected_uuid, NULL_UUID_LE) != 0) { - uuid_le guid; - - memcpy_fromio(&guid, - &((struct channel_header __iomem *)(ch))->chtype, - sizeof(guid)); - /* caller wants us to verify type GUID */ - if (uuid_le_cmp(guid, expected_uuid) != 0) { - pr_err("Channel mismatch on channel=%s(%pUL) field=type expected=%pUL actual=%pUL\n", - chname, &expected_uuid, - &expected_uuid, &guid); - return 0; - } - } - if (expected_min_bytes > 0) { /* caller wants us to verify - * channel size */ - unsigned long long bytes = - readq(&((struct channel_header __iomem *) - (ch))->size); - if (bytes < expected_min_bytes) { - pr_err("Channel mismatch on channel=%s(%pUL) field=size expected=0x%-8.8Lx actual=0x%-8.8Lx\n", - chname, &expected_uuid, - (unsigned long long)expected_min_bytes, bytes); - return 0; - } - } - if (expected_version > 0) { /* caller wants us to verify - * channel version */ - unsigned long ver = readl(&((struct channel_header __iomem *) - (ch))->version_id); - if (ver != expected_version) { - pr_err("Channel mismatch on channel=%s(%pUL) field=version expected=0x%-8.8lx actual=0x%-8.8lx\n", - chname, &expected_uuid, - (unsigned long)expected_version, ver); - return 0; - } - } - if (expected_signature > 0) { /* caller wants us to verify - * channel signature */ - unsigned long long sig = - readq(&((struct channel_header __iomem *) - (ch))->signature); - if (sig != expected_signature) { - pr_err("Channel mismatch on channel=%s(%pUL) field=signature expected=0x%-8.8llx actual=0x%-8.8llx\n", - chname, &expected_uuid, - expected_signature, sig); - return 0; - } - } - return 1; -} - -/* Generic function useful for validating any type of channel when it is about - * to be initialized by the server of the channel. - * Note that is only needed for callers in the EFI environment, and - * is used to pass the EFI_DIAG_CAPTURE_PROTOCOL needed to log messages. - */ -static inline int spar_check_channel_server(uuid_le typeuuid, char *name, - u64 expected_min_bytes, - u64 actual_bytes) -{ - if (expected_min_bytes > 0) /* caller wants us to verify - * channel size */ - if (actual_bytes < expected_min_bytes) { - pr_err("Channel mismatch on channel=%s(%pUL) field=size expected=0x%-8.8llx actual=0x%-8.8llx\n", - name, &typeuuid, expected_min_bytes, - actual_bytes); - return 0; - } - return 1; -} - -/* Given a file pathname (with '/' or '\' separating directory nodes), - * returns a pointer to the beginning of a node within that pathname such - * that the number of nodes from that pointer to the end of the string is - * NOT more than . Note that if the pathname has less than nodes - * in it, the return pointer will be to the beginning of the string. - */ -static inline u8 * -pathname_last_n_nodes(u8 *s, unsigned int n) -{ - u8 *p = s; - unsigned int node_count = 0; - - while (*p != '\0') { - if ((*p == '/') || (*p == '\\')) - node_count++; - p++; - } - if (node_count <= n) - return s; - while (n > 0) { - p--; - if (p == s) - break; /* should never happen, unless someone - * is changing the string while we are - * looking at it!! */ - if ((*p == '/') || (*p == '\\')) - n--; - } - return p + 1; -} - -static inline int -spar_channel_client_acquire_os(void __iomem *ch, u8 *id) -{ - struct channel_header __iomem *hdr = ch; - - if (readl(&hdr->cli_state_os) == CHANNELCLI_DISABLED) { - if ((readb(&hdr->cli_error_os) - & ULTRA_CLIERROROS_THROTTLEMSG_DISABLED) == 0) { - /* we are NOT throttling this message */ - writeb(readb(&hdr->cli_error_os) | - ULTRA_CLIERROROS_THROTTLEMSG_DISABLED, - &hdr->cli_error_os); - /* throttle until acquire successful */ - - pr_info("%s Channel StateTransition INVALID! - acquire failed because OS client DISABLED\n", - id); - } - return 0; - } - if ((readl(&hdr->cli_state_os) != CHANNELCLI_OWNED) && - (readl(&hdr->cli_state_boot) == CHANNELCLI_DISABLED)) { - /* Our competitor is DISABLED, so we can transition to OWNED */ - pr_info("%s Channel StateTransition (%s) %s(%d)-->%s(%d)\n", - id, "cli_state_os", - ULTRA_CHANNELCLI_STRING(readl(&hdr->cli_state_os)), - readl(&hdr->cli_state_os), - ULTRA_CHANNELCLI_STRING(CHANNELCLI_OWNED), - CHANNELCLI_OWNED); - writel(CHANNELCLI_OWNED, &hdr->cli_state_os); - mb(); /* required for channel synch */ - } - if (readl(&hdr->cli_state_os) == CHANNELCLI_OWNED) { - if (readb(&hdr->cli_error_os) != 0) { - /* we are in an error msg throttling state; - * come out of it */ - pr_info("%s Channel OS client acquire now successful\n", - id); - writeb(0, &hdr->cli_error_os); - } - return 1; - } - - /* We have to do it the "hard way". We transition to BUSY, - * and can use the channel iff our competitor has not also - * transitioned to BUSY. */ - if (readl(&hdr->cli_state_os) != CHANNELCLI_ATTACHED) { - if ((readb(&hdr->cli_error_os) - & ULTRA_CLIERROROS_THROTTLEMSG_NOTATTACHED) == 0) { - /* we are NOT throttling this message */ - writeb(readb(&hdr->cli_error_os) | - ULTRA_CLIERROROS_THROTTLEMSG_NOTATTACHED, - &hdr->cli_error_os); - /* throttle until acquire successful */ - pr_info("%s Channel StateTransition INVALID! - acquire failed because OS client NOT ATTACHED (state=%s(%d))\n", - id, ULTRA_CHANNELCLI_STRING( - readl(&hdr->cli_state_os)), - readl(&hdr->cli_state_os)); - } - return 0; - } - writel(CHANNELCLI_BUSY, &hdr->cli_state_os); - mb(); /* required for channel synch */ - if (readl(&hdr->cli_state_boot) == CHANNELCLI_BUSY) { - if ((readb(&hdr->cli_error_os) - & ULTRA_CLIERROROS_THROTTLEMSG_BUSY) == 0) { - /* we are NOT throttling this message */ - writeb(readb(&hdr->cli_error_os) | - ULTRA_CLIERROROS_THROTTLEMSG_BUSY, - &hdr->cli_error_os); - /* throttle until acquire successful */ - pr_info("%s Channel StateTransition failed - host OS acquire failed because boot BUSY\n", - id); - } - /* reset busy */ - writel(CHANNELCLI_ATTACHED, &hdr->cli_state_os); - mb(); /* required for channel synch */ - return 0; - } - if (readb(&hdr->cli_error_os) != 0) { - /* we are in an error msg throttling state; come out of it */ - pr_info("%s Channel OS client acquire now successful\n", id); - writeb(0, &hdr->cli_error_os); - } - return 1; -} - -static inline void -spar_channel_client_release_os(void __iomem *ch, u8 *id) -{ - struct channel_header __iomem *hdr = ch; - - if (readb(&hdr->cli_error_os) != 0) { - /* we are in an error msg throttling state; come out of it */ - pr_info("%s Channel OS client error state cleared\n", id); - writeb(0, &hdr->cli_error_os); - } - if (readl(&hdr->cli_state_os) == CHANNELCLI_OWNED) - return; - if (readl(&hdr->cli_state_os) != CHANNELCLI_BUSY) { - pr_info("%s Channel StateTransition INVALID! - release failed because OS client NOT BUSY (state=%s(%d))\n", - id, ULTRA_CHANNELCLI_STRING( - readl(&hdr->cli_state_os)), - readl(&hdr->cli_state_os)); - /* return; */ - } - writel(CHANNELCLI_ATTACHED, &hdr->cli_state_os); /* release busy */ -} - -/* -* Routine Description: -* Tries to insert the prebuilt signal pointed to by pSignal into the nth -* Queue of the Channel pointed to by pChannel -* -* Parameters: -* pChannel: (IN) points to the IO Channel -* Queue: (IN) nth Queue of the IO Channel -* pSignal: (IN) pointer to the signal -* -* Assumptions: -* - pChannel, Queue and pSignal are valid. -* - If insertion fails due to a full queue, the caller will determine the -* retry policy (e.g. wait & try again, report an error, etc.). -* -* Return value: 1 if the insertion succeeds, 0 if the queue was -* full. -*/ - -unsigned char spar_signal_insert(struct channel_header __iomem *ch, u32 queue, - void *sig); - -/* -* Routine Description: -* Removes one signal from Channel pChannel's nth Queue at the -* time of the call and copies it into the memory pointed to by -* pSignal. -* -* Parameters: -* pChannel: (IN) points to the IO Channel -* Queue: (IN) nth Queue of the IO Channel -* pSignal: (IN) pointer to where the signals are to be copied -* -* Assumptions: -* - pChannel and Queue are valid. -* - pSignal points to a memory area large enough to hold queue's SignalSize -* -* Return value: 1 if the removal succeeds, 0 if the queue was -* empty. -*/ - -unsigned char spar_signal_remove(struct channel_header __iomem *ch, u32 queue, - void *sig); - -/* -* Routine Description: -* Removes all signals present in Channel pChannel's nth Queue at the -* time of the call and copies them into the memory pointed to by -* pSignal. Returns the # of signals copied as the value of the routine. -* -* Parameters: -* pChannel: (IN) points to the IO Channel -* Queue: (IN) nth Queue of the IO Channel -* pSignal: (IN) pointer to where the signals are to be copied -* -* Assumptions: -* - pChannel and Queue are valid. -* - pSignal points to a memory area large enough to hold Queue's MaxSignals -* # of signals, each of which is Queue's SignalSize. -* -* Return value: -* # of signals copied. -*/ -unsigned int spar_signal_remove_all(struct channel_header *ch, u32 queue, - void *sig); - -/* -* Routine Description: -* Determine whether a signal queue is empty. -* -* Parameters: -* pChannel: (IN) points to the IO Channel -* Queue: (IN) nth Queue of the IO Channel -* -* Return value: -* 1 if the signal queue is empty, 0 otherwise. -*/ -unsigned char spar_signalqueue_empty(struct channel_header __iomem *ch, - u32 queue); - -#endif diff --git a/drivers/staging/unisys/common-spar/include/channels/channel_guid.h b/drivers/staging/unisys/common-spar/include/channels/channel_guid.h deleted file mode 100644 index 706363fc3e9a..000000000000 --- a/drivers/staging/unisys/common-spar/include/channels/channel_guid.h +++ /dev/null @@ -1,61 +0,0 @@ -/* Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -/* - * CHANNEL Guids - */ - -/* Used in IOChannel - * {414815ed-c58c-11da-95a9-00e08161165f} - */ -#define SPAR_VHBA_CHANNEL_PROTOCOL_UUID \ - UUID_LE(0x414815ed, 0xc58c, 0x11da, \ - 0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f) -static const uuid_le spar_vhba_channel_protocol_uuid = - SPAR_VHBA_CHANNEL_PROTOCOL_UUID; - -/* Used in IOChannel - * {8cd5994d-c58e-11da-95a9-00e08161165f} - */ -#define SPAR_VNIC_CHANNEL_PROTOCOL_UUID \ - UUID_LE(0x8cd5994d, 0xc58e, 0x11da, \ - 0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f) -static const uuid_le spar_vnic_channel_protocol_uuid = - SPAR_VNIC_CHANNEL_PROTOCOL_UUID; - -/* Used in IOChannel - * {72120008-4AAB-11DC-8530-444553544200} - */ -#define SPAR_SIOVM_UUID \ - UUID_LE(0x72120008, 0x4AAB, 0x11DC, \ - 0x85, 0x30, 0x44, 0x45, 0x53, 0x54, 0x42, 0x00) -static const uuid_le spar_siovm_uuid = SPAR_SIOVM_UUID; - -/* Used in visornoop/visornoop_main.c - * {5b52c5ac-e5f5-4d42-8dff-429eaecd221f} - */ -#define SPAR_CONTROLDIRECTOR_CHANNEL_PROTOCOL_UUID \ - UUID_LE(0x5b52c5ac, 0xe5f5, 0x4d42, \ - 0x8d, 0xff, 0x42, 0x9e, 0xae, 0xcd, 0x22, 0x1f) - -static const uuid_le spar_controldirector_channel_protocol_uuid = - SPAR_CONTROLDIRECTOR_CHANNEL_PROTOCOL_UUID; - -/* Used in visorchipset/visorchipset_main.c - * {B4E79625-AEDE-4EAA-9E11-D3EDDCD4504C} - */ -#define SPAR_DIAG_POOL_CHANNEL_PROTOCOL_UUID \ - UUID_LE(0xb4e79625, 0xaede, 0x4eaa, \ - 0x9e, 0x11, 0xd3, 0xed, 0xdc, 0xd4, 0x50, 0x4c) diff --git a/drivers/staging/unisys/common-spar/include/channels/controlvmchannel.h b/drivers/staging/unisys/common-spar/include/channels/controlvmchannel.h deleted file mode 100644 index a50d9cf4bed7..000000000000 --- a/drivers/staging/unisys/common-spar/include/channels/controlvmchannel.h +++ /dev/null @@ -1,485 +0,0 @@ -/* Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -#ifndef __CONTROLVMCHANNEL_H__ -#define __CONTROLVMCHANNEL_H__ - -#include -#include "channel.h" - -/* {2B3C2D10-7EF5-4ad8-B966-3448B7386B3D} */ -#define SPAR_CONTROLVM_CHANNEL_PROTOCOL_UUID \ - UUID_LE(0x2b3c2d10, 0x7ef5, 0x4ad8, \ - 0xb9, 0x66, 0x34, 0x48, 0xb7, 0x38, 0x6b, 0x3d) - -#define ULTRA_CONTROLVM_CHANNEL_PROTOCOL_SIGNATURE \ - ULTRA_CHANNEL_PROTOCOL_SIGNATURE -#define CONTROLVM_MESSAGE_MAX 64 - -/* Must increment this whenever you insert or delete fields within - * this channel struct. Also increment whenever you change the meaning - * of fields within this channel struct so as to break pre-existing - * software. Note that you can usually add fields to the END of the - * channel struct withOUT needing to increment this. - */ -#define ULTRA_CONTROLVM_CHANNEL_PROTOCOL_VERSIONID 1 - -#define SPAR_CONTROLVM_CHANNEL_OK_CLIENT(ch) \ - spar_check_channel_client(ch, \ - SPAR_CONTROLVM_CHANNEL_PROTOCOL_UUID, \ - "controlvm", \ - sizeof(struct spar_controlvm_channel_protocol), \ - ULTRA_CONTROLVM_CHANNEL_PROTOCOL_VERSIONID, \ - ULTRA_CONTROLVM_CHANNEL_PROTOCOL_SIGNATURE) - -#define MAX_SERIAL_NUM 32 - -/* Defines for various channel queues */ -#define CONTROLVM_QUEUE_REQUEST 0 -#define CONTROLVM_QUEUE_RESPONSE 1 -#define CONTROLVM_QUEUE_EVENT 2 -#define CONTROLVM_QUEUE_ACK 3 - -/* Max num of messages stored during IOVM creation to be reused after crash */ -#define CONTROLVM_CRASHMSG_MAX 2 - -struct spar_segment_state { - u16 enabled:1; /* Bit 0: May enter other states */ - u16 active:1; /* Bit 1: Assigned to active partition */ - u16 alive:1; /* Bit 2: Configure message sent to - * service/server */ - u16 revoked:1; /* Bit 3: similar to partition state - * ShuttingDown */ - u16 allocated:1; /* Bit 4: memory (device/port number) - * has been selected by Command */ - u16 known:1; /* Bit 5: has been introduced to the - * service/guest partition */ - u16 ready:1; /* Bit 6: service/Guest partition has - * responded to introduction */ - u16 operating:1; /* Bit 7: resource is configured and - * operating */ - /* Note: don't use high bit unless we need to switch to ushort - * which is non-compliant */ -}; - -static const struct spar_segment_state segment_state_running = { - 1, 1, 1, 0, 1, 1, 1, 1 -}; - -static const struct spar_segment_state segment_state_paused = { - 1, 1, 1, 0, 1, 1, 1, 0 -}; - -static const struct spar_segment_state segment_state_standby = { - 1, 1, 0, 0, 1, 1, 1, 0 -}; - -/* Ids for commands that may appear in either queue of a ControlVm channel. - * - * Commands that are initiated by the command partition (CP), by an IO or - * console service partition (SP), or by a guest partition (GP)are: - * - issued on the RequestQueue queue (q #0) in the ControlVm channel - * - responded to on the ResponseQueue queue (q #1) in the ControlVm channel - * - * Events that are initiated by an IO or console service partition (SP) or - * by a guest partition (GP) are: - * - issued on the EventQueue queue (q #2) in the ControlVm channel - * - responded to on the EventAckQueue queue (q #3) in the ControlVm channel - */ -enum controlvm_id { - CONTROLVM_INVALID = 0, - /* SWITCH commands required Parameter: SwitchNumber */ - /* BUS commands required Parameter: BusNumber */ - CONTROLVM_BUS_CREATE = 0x101, /* CP --> SP, GP */ - CONTROLVM_BUS_DESTROY = 0x102, /* CP --> SP, GP */ - CONTROLVM_BUS_CONFIGURE = 0x104, /* CP --> SP */ - CONTROLVM_BUS_CHANGESTATE = 0x105, /* CP --> SP, GP */ - CONTROLVM_BUS_CHANGESTATE_EVENT = 0x106, /* SP, GP --> CP */ -/* DEVICE commands required Parameter: BusNumber, DeviceNumber */ - - CONTROLVM_DEVICE_CREATE = 0x201, /* CP --> SP, GP */ - CONTROLVM_DEVICE_DESTROY = 0x202, /* CP --> SP, GP */ - CONTROLVM_DEVICE_CONFIGURE = 0x203, /* CP --> SP */ - CONTROLVM_DEVICE_CHANGESTATE = 0x204, /* CP --> SP, GP */ - CONTROLVM_DEVICE_CHANGESTATE_EVENT = 0x205, /* SP, GP --> CP */ - CONTROLVM_DEVICE_RECONFIGURE = 0x206, /* CP --> Boot */ -/* CHIPSET commands */ - CONTROLVM_CHIPSET_INIT = 0x301, /* CP --> SP, GP */ - CONTROLVM_CHIPSET_STOP = 0x302, /* CP --> SP, GP */ - CONTROLVM_CHIPSET_READY = 0x304, /* CP --> SP */ - CONTROLVM_CHIPSET_SELFTEST = 0x305, /* CP --> SP */ - -}; - -struct irq_info { - u64 reserved1; - - /* specifies interrupt handle. It is used to retrieve the - * corresponding interrupt pin from Monitor; and the - * interrupt pin is used to connect to the corresponding - * interrupt. Used by IOPart-GP only. - */ - u64 recv_irq_handle; - - /* specifies interrupt vector. It, interrupt pin, and shared are - * used to connect to the corresponding interrupt. Used by - * IOPart-GP only. - */ - u32 recv_irq_vector; - - /* specifies if the recvInterrupt is shared. It, interrupt pin - * and vector are used to connect to 0 = not shared; 1 = shared. - * the corresponding interrupt. Used by IOPart-GP only. - */ - u8 recv_irq_shared; - u8 reserved[3]; /* Natural alignment purposes */ -}; - -struct pci_id { - u16 domain; - u8 bus; - u8 slot; - u8 func; - u8 reserved[3]; /* Natural alignment purposes */ -}; - -struct efi_spar_indication { - u64 boot_to_fw_ui:1; /* Bit 0: Stop in uefi ui */ - u64 clear_nvram:1; /* Bit 1: Clear NVRAM */ - u64 clear_cmos:1; /* Bit 2: Clear CMOS */ - u64 boot_to_tool:1; /* Bit 3: Run install tool */ - /* remaining bits are available */ -}; - -enum ultra_chipset_feature { - ULTRA_CHIPSET_FEATURE_REPLY = 0x00000001, - ULTRA_CHIPSET_FEATURE_PARA_HOTPLUG = 0x00000002, -}; - -/* This is the common structure that is at the beginning of every - * ControlVm message (both commands and responses) in any ControlVm - * queue. Commands are easily distinguished from responses by - * looking at the flags.response field. - */ -struct controlvm_message_header { - u32 id; /* See CONTROLVM_ID. */ - /* For requests, indicates the message type. */ - /* For responses, indicates the type of message we are responding to. */ - - u32 message_size; /* Includes size of this struct + size - * of message */ - u32 segment_index; /* Index of segment containing Vm - * message/information */ - u32 completion_status; /* Error status code or result of - * message completion */ - struct { - u32 failed:1; /* =1 in a response to * signify - * failure */ - u32 response_expected:1; /* =1 in all messages that expect a - * response (Control ignores this - * bit) */ - u32 server:1; /* =1 in all bus & device-related - * messages where the message - * receiver is to act as the bus or - * device server */ - u32 test_message:1; /* =1 for testing use only - * (Control and Command ignore this - * bit) */ - u32 partial_completion:1; /* =1 if there are forthcoming - * responses/acks associated - * with this message */ - u32 preserve:1; /* =1 this is to let us know to - * preserve channel contents - * (for running guests)*/ - u32 writer_in_diag:1; /* =1 the DiagWriter is active in the - * Diagnostic Partition*/ - } flags; - u32 reserved; /* Natural alignment */ - u64 message_handle; /* Identifies the particular message instance, - * and is used to match particular */ - /* request instances with the corresponding response instance. */ - u64 payload_vm_offset; /* Offset of payload area from start of this - * instance of ControlVm segment */ - u32 payload_max_bytes; /* Maximum bytes allocated in payload - * area of ControlVm segment */ - u32 payload_bytes; /* Actual number of bytes of payload - * area to copy between IO/Command; */ - /* if non-zero, there is a payload to copy. */ -}; - -struct controlvm_packet_device_create { - u32 bus_no; /* bus # (0..n-1) from the msg receiver's end */ - u32 dev_no; /* bus-relative (0..n-1) device number */ - u64 channel_addr; /* Guest physical address of the channel, which - * can be dereferenced by the receiver of this - * ControlVm command */ - u64 channel_bytes; /* specifies size of the channel in bytes */ - uuid_le data_type_uuid; /* specifies format of data in channel */ - uuid_le dev_inst_uuid; /* instance guid for the device */ - struct irq_info intr; /* specifies interrupt information */ -}; /* for CONTROLVM_DEVICE_CREATE */ - -struct controlvm_packet_device_configure { - u32 bus_no; /* bus # (0..n-1) from the msg - * receiver's perspective */ - /* Control uses header SegmentIndex field to access bus number... */ - u32 dev_no; /* bus-relative (0..n-1) device number */ -} ; /* for CONTROLVM_DEVICE_CONFIGURE */ - -struct controlvm_message_device_create { - struct controlvm_message_header header; - struct controlvm_packet_device_create packet; -}; /* total 128 bytes */ - -struct controlvm_message_device_configure { - struct controlvm_message_header header; - struct controlvm_packet_device_configure packet; -}; /* total 56 bytes */ - -/* This is the format for a message in any ControlVm queue. */ -struct controlvm_message_packet { - union { - struct { - u32 bus_no; /* bus # (0..n-1) from the msg - * receiver's perspective */ - u32 dev_count; /* indicates the max number of - * devices on this bus */ - u64 channel_addr; /* Guest physical address of - * the channel, which can be - * dereferenced by the receiver - * of this ControlVm command */ - u64 channel_bytes; /* size of the channel */ - uuid_le bus_data_type_uuid; /* indicates format of - * data in bus channel*/ - uuid_le bus_inst_uuid; /* instance uuid for the bus */ - } create_bus; /* for CONTROLVM_BUS_CREATE */ - struct { - u32 bus_no; /* bus # (0..n-1) from the msg - * receiver's perspective */ - u32 reserved; /* Natural alignment purposes */ - } destroy_bus; /* for CONTROLVM_BUS_DESTROY */ - struct { - u32 bus_no; /* bus # (0..n-1) from the receiver's - * perspective */ - u32 reserved1; /* for alignment purposes */ - u64 guest_handle; /* This is used to convert - * guest physical address to - * physical address */ - u64 recv_bus_irq_handle; - /* specifies interrupt info. It is used by SP - * to register to receive interrupts from the - * CP. This interrupt is used for bus level - * notifications. The corresponding - * sendBusInterruptHandle is kept in CP. */ - } configure_bus; /* for CONTROLVM_BUS_CONFIGURE */ - /* for CONTROLVM_DEVICE_CREATE */ - struct controlvm_packet_device_create create_device; - struct { - u32 bus_no; /* bus # (0..n-1) from the msg - * receiver's perspective */ - u32 dev_no; /* bus-relative (0..n-1) device # */ - } destroy_device; /* for CONTROLVM_DEVICE_DESTROY */ - /* for CONTROLVM_DEVICE_CONFIGURE */ - struct controlvm_packet_device_configure configure_device; - struct { - u32 bus_no; /* bus # (0..n-1) from the msg - * receiver's perspective */ - u32 dev_no; /* bus-relative (0..n-1) device # */ - } reconfigure_device; /* for CONTROLVM_DEVICE_RECONFIGURE */ - struct { - u32 bus_no; - struct spar_segment_state state; - u8 reserved[2]; /* Natural alignment purposes */ - } bus_change_state; /* for CONTROLVM_BUS_CHANGESTATE */ - struct { - u32 bus_no; - u32 dev_no; - struct spar_segment_state state; - struct { - u32 phys_device:1; /* =1 if message is for - * a physical device */ - } flags; - u8 reserved[2]; /* Natural alignment purposes */ - } device_change_state; /* for CONTROLVM_DEVICE_CHANGESTATE */ - struct { - u32 bus_no; - u32 dev_no; - struct spar_segment_state state; - u8 reserved[6]; /* Natural alignment purposes */ - } device_change_state_event; - /* for CONTROLVM_DEVICE_CHANGESTATE_EVENT */ - struct { - u32 bus_count; /* indicates the max number of busses */ - u32 switch_count; /* indicates the max number of - * switches if a service partition */ - enum ultra_chipset_feature features; - u32 platform_number; /* Platform Number */ - } init_chipset; /* for CONTROLVM_CHIPSET_INIT */ - struct { - u32 options; /* reserved */ - u32 test; /* bit 0 set to run embedded selftest */ - } chipset_selftest; /* for CONTROLVM_CHIPSET_SELFTEST */ - u64 addr; /* a physical address of something, that can be - * dereferenced by the receiver of this - * ControlVm command (depends on command id) */ - u64 handle; /* a handle of something (depends on command - * id) */ - }; -}; - -/* All messages in any ControlVm queue have this layout. */ -struct controlvm_message { - struct controlvm_message_header hdr; - struct controlvm_message_packet cmd; -}; - -struct spar_controlvm_channel_protocol { - struct channel_header header; - u64 gp_controlvm; /* guest phys addr of this channel */ - u64 gp_partition_tables;/* guest phys addr of partition tables */ - u64 gp_diag_guest; /* guest phys addr of diagnostic channel */ - u64 gp_boot_romdisk;/* guest phys addr of (read* only) Boot ROM disk */ - u64 gp_boot_ramdisk;/* guest phys addr of writable Boot RAM disk */ - u64 gp_acpi_table; /* guest phys addr of acpi table */ - u64 gp_control_channel;/* guest phys addr of control channel */ - u64 gp_diag_romdisk;/* guest phys addr of diagnostic ROM disk */ - u64 gp_nvram; /* guest phys addr of NVRAM channel */ - u64 request_payload_offset; /* Offset to request payload area */ - u64 event_payload_offset; /* Offset to event payload area */ - u32 request_payload_bytes; /* Bytes available in request payload - * area */ - u32 event_payload_bytes;/* Bytes available in event payload area */ - u32 control_channel_bytes; - u32 nvram_channel_bytes; /* Bytes in PartitionNvram segment */ - u32 message_bytes; /* sizeof(CONTROLVM_MESSAGE) */ - u32 message_count; /* CONTROLVM_MESSAGE_MAX */ - u64 gp_smbios_table; /* guest phys addr of SMBIOS tables */ - u64 gp_physical_smbios_table; /* guest phys addr of SMBIOS table */ - /* ULTRA_MAX_GUESTS_PER_SERVICE */ - char gp_reserved[2688]; - - /* guest physical address of EFI firmware image base */ - u64 virtual_guest_firmware_image_base; - - /* guest physical address of EFI firmware entry point */ - u64 virtual_guest_firmware_entry_point; - - /* guest EFI firmware image size */ - u64 virtual_guest_firmware_image_size; - - /* GPA = 1MB where EFI firmware image is copied to */ - u64 virtual_guest_firmware_boot_base; - u64 virtual_guest_image_base; - u64 virtual_guest_image_size; - u64 prototype_control_channel_offset; - u64 virtual_guest_partition_handle; - - u16 restore_action; /* Restore Action field to restore the guest - * partition */ - u16 dump_action; /* For Windows guests it shows if the visordisk - * is running in dump mode */ - u16 nvram_fail_count; - u16 saved_crash_message_count; /* = CONTROLVM_CRASHMSG_MAX */ - u32 saved_crash_message_offset; /* Offset to request payload area needed - * for crash dump */ - u32 installation_error; /* Type of error encountered during - * installation */ - u32 installation_text_id; /* Id of string to display */ - u16 installation_remaining_steps;/* Number of remaining installation - * steps (for progress bars) */ - u8 tool_action; /* ULTRA_TOOL_ACTIONS Installation Action - * field */ - u8 reserved; /* alignment */ - struct efi_spar_indication efi_spar_ind; - struct efi_spar_indication efi_spar_ind_supported; - u32 sp_reserved; - u8 reserved2[28]; /* Force signals to begin on 128-byte cache - * line */ - struct signal_queue_header request_queue;/* Service or guest partition - * uses this queue to send - * requests to Control */ - struct signal_queue_header response_queue;/* Control uses this queue to - * respond to service or guest - * partition requests */ - struct signal_queue_header event_queue; /* Control uses this queue to - * send events to service or - * guest partition */ - struct signal_queue_header event_ack_queue;/* Service or guest partition - * uses this queue to ack - * Control events */ - - /* Request fixed-size message pool - does not include payload */ - struct controlvm_message request_msg[CONTROLVM_MESSAGE_MAX]; - - /* Response fixed-size message pool - does not include payload */ - struct controlvm_message response_msg[CONTROLVM_MESSAGE_MAX]; - - /* Event fixed-size message pool - does not include payload */ - struct controlvm_message event_msg[CONTROLVM_MESSAGE_MAX]; - - /* Ack fixed-size message pool - does not include payload */ - struct controlvm_message event_ack_msg[CONTROLVM_MESSAGE_MAX]; - - /* Message stored during IOVM creation to be reused after crash */ - struct controlvm_message saved_crash_msg[CONTROLVM_CRASHMSG_MAX]; -}; - -/* Offsets for VM channel attributes */ -#define VM_CH_REQ_QUEUE_OFFSET \ - offsetof(struct spar_controlvm_channel_protocol, request_queue) -#define VM_CH_RESP_QUEUE_OFFSET \ - offsetof(struct spar_controlvm_channel_protocol, response_queue) -#define VM_CH_EVENT_QUEUE_OFFSET \ - offsetof(struct spar_controlvm_channel_protocol, event_queue) -#define VM_CH_ACK_QUEUE_OFFSET \ - offsetof(struct spar_controlvm_channel_protocol, event_ack_queue) -#define VM_CH_REQ_MSG_OFFSET \ - offsetof(struct spar_controlvm_channel_protocol, request_msg) -#define VM_CH_RESP_MSG_OFFSET \ - offsetof(struct spar_controlvm_channel_protocol, response_msg) -#define VM_CH_EVENT_MSG_OFFSET \ - offsetof(struct spar_controlvm_channel_protocol, event_msg) -#define VM_CH_ACK_MSG_OFFSET \ - offsetof(struct spar_controlvm_channel_protocol, event_ack_msg) -#define VM_CH_CRASH_MSG_OFFSET \ - offsetof(struct spar_controlvm_channel_protocol, saved_crash_msg) - -/* The following header will be located at the beginning of PayloadVmOffset for - * various ControlVm commands. The receiver of a ControlVm command with a - * PayloadVmOffset will dereference this address and then use connection_offset, - * initiator_offset, and target_offset to get the location of UTF-8 formatted - * strings that can be parsed to obtain command-specific information. The value - * of total_length should equal PayloadBytes. The format of the strings at - * PayloadVmOffset will take different forms depending on the message. - */ -struct spar_controlvm_parameters_header { - u32 total_length; - u32 header_length; - u32 connection_offset; - u32 connection_length; - u32 initiator_offset; - u32 initiator_length; - u32 target_offset; - u32 target_length; - u32 client_offset; - u32 client_length; - u32 name_offset; - u32 name_length; - uuid_le id; - u32 revision; - u32 reserved; /* Natural alignment */ -}; - -#endif /* __CONTROLVMCHANNEL_H__ */ diff --git a/drivers/staging/unisys/include/channel.h b/drivers/staging/unisys/include/channel.h new file mode 100644 index 000000000000..da0b5387f884 --- /dev/null +++ b/drivers/staging/unisys/include/channel.h @@ -0,0 +1,555 @@ +/* Copyright (C) 2010 - 2013 UNISYS CORPORATION + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for more + * details. + */ + +#ifndef __CHANNEL_H__ +#define __CHANNEL_H__ + +#include +#include +#include + +/* +* Whenever this file is changed a corresponding change must be made in +* the Console/ServicePart/visordiag_early/supervisor_channel.h file +* which is needed for Linux kernel compiles. These two files must be +* in sync. +*/ + +/* define the following to prevent include nesting in kernel header + * files of similar abbreviated content + */ +#define __SUPERVISOR_CHANNEL_H__ + +#define SIGNATURE_16(A, B) ((A) | (B<<8)) +#define SIGNATURE_32(A, B, C, D) \ + (SIGNATURE_16(A, B) | (SIGNATURE_16(C, D) << 16)) +#define SIGNATURE_64(A, B, C, D, E, F, G, H) \ + (SIGNATURE_32(A, B, C, D) | ((u64)(SIGNATURE_32(E, F, G, H)) << 32)) + +#ifndef lengthof +#define lengthof(TYPE, MEMBER) (sizeof(((TYPE *)0)->MEMBER)) +#endif +#ifndef COVERQ +#define COVERQ(v, d) (((v)+(d)-1) / (d)) +#endif +#ifndef COVER +#define COVER(v, d) ((d)*COVERQ(v, d)) +#endif + +#define ULTRA_CHANNEL_PROTOCOL_SIGNATURE SIGNATURE_32('E', 'C', 'N', 'L') + +enum channel_serverstate { + CHANNELSRV_UNINITIALIZED = 0, /* channel is in an undefined state */ + CHANNELSRV_READY = 1 /* channel has been initialized by server */ +}; + +enum channel_clientstate { + CHANNELCLI_DETACHED = 0, + CHANNELCLI_DISABLED = 1, /* client can see channel but is NOT + * allowed to use it unless given TBD + * explicit request (should actually be + * < DETACHED) */ + CHANNELCLI_ATTACHING = 2, /* legacy EFI client request + * for EFI server to attach */ + CHANNELCLI_ATTACHED = 3, /* idle, but client may want + * to use channel any time */ + CHANNELCLI_BUSY = 4, /* client either wants to use or is + * using channel */ + CHANNELCLI_OWNED = 5 /* "no worries" state - client can + * access channel anytime */ +}; + +static inline const u8 * +ULTRA_CHANNELCLI_STRING(u32 v) +{ + switch (v) { + case CHANNELCLI_DETACHED: + return (const u8 *)("DETACHED"); + case CHANNELCLI_DISABLED: + return (const u8 *)("DISABLED"); + case CHANNELCLI_ATTACHING: + return (const u8 *)("ATTACHING"); + case CHANNELCLI_ATTACHED: + return (const u8 *)("ATTACHED"); + case CHANNELCLI_BUSY: + return (const u8 *)("BUSY"); + case CHANNELCLI_OWNED: + return (const u8 *)("OWNED"); + default: + break; + } + return (const u8 *)("?"); +} + +#define SPAR_CHANNEL_SERVER_READY(ch) \ + (readl(&(ch)->srv_state) == CHANNELSRV_READY) + +#define ULTRA_VALID_CHANNELCLI_TRANSITION(o, n) \ + (((((o) == CHANNELCLI_DETACHED) && ((n) == CHANNELCLI_DISABLED)) || \ + (((o) == CHANNELCLI_ATTACHING) && ((n) == CHANNELCLI_DISABLED)) || \ + (((o) == CHANNELCLI_ATTACHED) && ((n) == CHANNELCLI_DISABLED)) || \ + (((o) == CHANNELCLI_ATTACHING) && ((n) == CHANNELCLI_DETACHED)) || \ + (((o) == CHANNELCLI_ATTACHED) && ((n) == CHANNELCLI_DETACHED)) || \ + (((o) == CHANNELCLI_DETACHED) && ((n) == CHANNELCLI_ATTACHING)) || \ + (((o) == CHANNELCLI_ATTACHING) && ((n) == CHANNELCLI_ATTACHED)) || \ + (((o) == CHANNELCLI_DETACHED) && ((n) == CHANNELCLI_ATTACHED)) || \ + (((o) == CHANNELCLI_BUSY) && ((n) == CHANNELCLI_ATTACHED)) || \ + (((o) == CHANNELCLI_ATTACHED) && ((n) == CHANNELCLI_BUSY)) || \ + (((o) == CHANNELCLI_DETACHED) && ((n) == CHANNELCLI_OWNED)) || \ + (((o) == CHANNELCLI_DISABLED) && ((n) == CHANNELCLI_OWNED)) || \ + (((o) == CHANNELCLI_ATTACHING) && ((n) == CHANNELCLI_OWNED)) || \ + (((o) == CHANNELCLI_ATTACHED) && ((n) == CHANNELCLI_OWNED)) || \ + (((o) == CHANNELCLI_BUSY) && ((n) == CHANNELCLI_OWNED)) || (0)) \ + ? (1) : (0)) + +/* Values for ULTRA_CHANNEL_PROTOCOL.CliErrorBoot: */ +/* throttling invalid boot channel statetransition error due to client + * disabled */ +#define ULTRA_CLIERRORBOOT_THROTTLEMSG_DISABLED 0x01 + +/* throttling invalid boot channel statetransition error due to client + * not attached */ +#define ULTRA_CLIERRORBOOT_THROTTLEMSG_NOTATTACHED 0x02 + +/* throttling invalid boot channel statetransition error due to busy channel */ +#define ULTRA_CLIERRORBOOT_THROTTLEMSG_BUSY 0x04 + +/* Values for ULTRA_CHANNEL_PROTOCOL.CliErrorOS: */ +/* throttling invalid guest OS channel statetransition error due to + * client disabled */ +#define ULTRA_CLIERROROS_THROTTLEMSG_DISABLED 0x01 + +/* throttling invalid guest OS channel statetransition error due to + * client not attached */ +#define ULTRA_CLIERROROS_THROTTLEMSG_NOTATTACHED 0x02 + +/* throttling invalid guest OS channel statetransition error due to + * busy channel */ +#define ULTRA_CLIERROROS_THROTTLEMSG_BUSY 0x04 + +/* Values for ULTRA_CHANNEL_PROTOCOL.Features: This define exists so +* that windows guest can look at the FeatureFlags in the io channel, +* and configure the windows driver to use interrupts or not based on +* this setting. This flag is set in uislib after the +* ULTRA_VHBA_init_channel is called. All feature bits for all +* channels should be defined here. The io channel feature bits are +* defined right here */ +#define ULTRA_IO_DRIVER_ENABLES_INTS (0x1ULL << 1) +#define ULTRA_IO_CHANNEL_IS_POLLING (0x1ULL << 3) +#define ULTRA_IO_IOVM_IS_OK_WITH_DRIVER_DISABLING_INTS (0x1ULL << 4) +#define ULTRA_IO_DRIVER_DISABLES_INTS (0x1ULL << 5) +#define ULTRA_IO_DRIVER_SUPPORTS_ENHANCED_RCVBUF_CHECKING (0x1ULL << 6) + +#pragma pack(push, 1) /* both GCC and VC now allow this pragma */ +/* Common Channel Header */ +struct channel_header { + u64 signature; /* Signature */ + u32 legacy_state; /* DEPRECATED - being replaced by */ + /* / SrvState, CliStateBoot, and CliStateOS below */ + u32 header_size; /* sizeof(struct channel_header) */ + u64 size; /* Total size of this channel in bytes */ + u64 features; /* Flags to modify behavior */ + uuid_le chtype; /* Channel type: data, bus, control, etc. */ + u64 partition_handle; /* ID of guest partition */ + u64 handle; /* Device number of this channel in client */ + u64 ch_space_offset; /* Offset in bytes to channel specific area */ + u32 version_id; /* struct channel_header Version ID */ + u32 partition_index; /* Index of guest partition */ + uuid_le zone_uuid; /* Guid of Channel's zone */ + u32 cli_str_offset; /* offset from channel header to + * nul-terminated ClientString (0 if + * ClientString not present) */ + u32 cli_state_boot; /* CHANNEL_CLIENTSTATE of pre-boot + * EFI client of this channel */ + u32 cmd_state_cli; /* CHANNEL_COMMANDSTATE (overloaded in + * Windows drivers, see ServerStateUp, + * ServerStateDown, etc) */ + u32 cli_state_os; /* CHANNEL_CLIENTSTATE of Guest OS + * client of this channel */ + u32 ch_characteristic; /* CHANNEL_CHARACTERISTIC_ */ + u32 cmd_state_srv; /* CHANNEL_COMMANDSTATE (overloaded in + * Windows drivers, see ServerStateUp, + * ServerStateDown, etc) */ + u32 srv_state; /* CHANNEL_SERVERSTATE */ + u8 cli_error_boot; /* bits to indicate err states for + * boot clients, so err messages can + * be throttled */ + u8 cli_error_os; /* bits to indicate err states for OS + * clients, so err messages can be + * throttled */ + u8 filler[1]; /* Pad out to 128 byte cacheline */ + /* Please add all new single-byte values below here */ + u8 recover_channel; +}; + +#define ULTRA_CHANNEL_ENABLE_INTS (0x1ULL << 0) + +/* Subheader for the Signal Type variation of the Common Channel */ +struct signal_queue_header { + /* 1st cache line */ + u32 version; /* SIGNAL_QUEUE_HEADER Version ID */ + u32 chtype; /* Queue type: storage, network */ + u64 size; /* Total size of this queue in bytes */ + u64 sig_base_offset; /* Offset to signal queue area */ + u64 features; /* Flags to modify behavior */ + u64 num_sent; /* Total # of signals placed in this queue */ + u64 num_overflows; /* Total # of inserts failed due to + * full queue */ + u32 signal_size; /* Total size of a signal for this queue */ + u32 max_slots; /* Max # of slots in queue, 1 slot is + * always empty */ + u32 max_signals; /* Max # of signals in queue + * (MaxSignalSlots-1) */ + u32 head; /* Queue head signal # */ + /* 2nd cache line */ + u64 num_received; /* Total # of signals removed from this queue */ + u32 tail; /* Queue tail signal # (on separate + * cache line) */ + u32 reserved1; /* Reserved field */ + u64 reserved2; /* Reserved field */ + u64 client_queue; + u64 num_irq_received; /* Total # of Interrupts received. This + * is incremented by the ISR in the + * guest windows driver */ + u64 num_empty; /* Number of times that visor_signal_remove + * is called and returned Empty + * Status. */ + u32 errorflags; /* Error bits set during SignalReinit + * to denote trouble with client's + * fields */ + u8 filler[12]; /* Pad out to 64 byte cacheline */ +}; + +#pragma pack(pop) + +#define spar_signal_init(chan, QHDRFLD, QDATAFLD, QDATATYPE, ver, typ) \ + do { \ + memset(&chan->QHDRFLD, 0, sizeof(chan->QHDRFLD)); \ + chan->QHDRFLD.version = ver; \ + chan->QHDRFLD.chtype = typ; \ + chan->QHDRFLD.size = sizeof(chan->QDATAFLD); \ + chan->QHDRFLD.signal_size = sizeof(QDATATYPE); \ + chan->QHDRFLD.sig_base_offset = (u64)(chan->QDATAFLD)- \ + (u64)(&chan->QHDRFLD); \ + chan->QHDRFLD.max_slots = \ + sizeof(chan->QDATAFLD)/sizeof(QDATATYPE); \ + chan->QHDRFLD.max_signals = chan->QHDRFLD.max_slots-1; \ + } while (0) + +/* Generic function useful for validating any type of channel when it is + * received by the client that will be accessing the channel. + * Note that is only needed for callers in the EFI environment, and + * is used to pass the EFI_DIAG_CAPTURE_PROTOCOL needed to log messages. + */ +static inline int +spar_check_channel_client(void __iomem *ch, + uuid_le expected_uuid, + char *chname, + u64 expected_min_bytes, + u32 expected_version, + u64 expected_signature) +{ + if (uuid_le_cmp(expected_uuid, NULL_UUID_LE) != 0) { + uuid_le guid; + + memcpy_fromio(&guid, + &((struct channel_header __iomem *)(ch))->chtype, + sizeof(guid)); + /* caller wants us to verify type GUID */ + if (uuid_le_cmp(guid, expected_uuid) != 0) { + pr_err("Channel mismatch on channel=%s(%pUL) field=type expected=%pUL actual=%pUL\n", + chname, &expected_uuid, + &expected_uuid, &guid); + return 0; + } + } + if (expected_min_bytes > 0) { /* caller wants us to verify + * channel size */ + unsigned long long bytes = + readq(&((struct channel_header __iomem *) + (ch))->size); + if (bytes < expected_min_bytes) { + pr_err("Channel mismatch on channel=%s(%pUL) field=size expected=0x%-8.8Lx actual=0x%-8.8Lx\n", + chname, &expected_uuid, + (unsigned long long)expected_min_bytes, bytes); + return 0; + } + } + if (expected_version > 0) { /* caller wants us to verify + * channel version */ + unsigned long ver = readl(&((struct channel_header __iomem *) + (ch))->version_id); + if (ver != expected_version) { + pr_err("Channel mismatch on channel=%s(%pUL) field=version expected=0x%-8.8lx actual=0x%-8.8lx\n", + chname, &expected_uuid, + (unsigned long)expected_version, ver); + return 0; + } + } + if (expected_signature > 0) { /* caller wants us to verify + * channel signature */ + unsigned long long sig = + readq(&((struct channel_header __iomem *) + (ch))->signature); + if (sig != expected_signature) { + pr_err("Channel mismatch on channel=%s(%pUL) field=signature expected=0x%-8.8llx actual=0x%-8.8llx\n", + chname, &expected_uuid, + expected_signature, sig); + return 0; + } + } + return 1; +} + +/* Generic function useful for validating any type of channel when it is about + * to be initialized by the server of the channel. + * Note that is only needed for callers in the EFI environment, and + * is used to pass the EFI_DIAG_CAPTURE_PROTOCOL needed to log messages. + */ +static inline int spar_check_channel_server(uuid_le typeuuid, char *name, + u64 expected_min_bytes, + u64 actual_bytes) +{ + if (expected_min_bytes > 0) /* caller wants us to verify + * channel size */ + if (actual_bytes < expected_min_bytes) { + pr_err("Channel mismatch on channel=%s(%pUL) field=size expected=0x%-8.8llx actual=0x%-8.8llx\n", + name, &typeuuid, expected_min_bytes, + actual_bytes); + return 0; + } + return 1; +} + +/* Given a file pathname (with '/' or '\' separating directory nodes), + * returns a pointer to the beginning of a node within that pathname such + * that the number of nodes from that pointer to the end of the string is + * NOT more than . Note that if the pathname has less than nodes + * in it, the return pointer will be to the beginning of the string. + */ +static inline u8 * +pathname_last_n_nodes(u8 *s, unsigned int n) +{ + u8 *p = s; + unsigned int node_count = 0; + + while (*p != '\0') { + if ((*p == '/') || (*p == '\\')) + node_count++; + p++; + } + if (node_count <= n) + return s; + while (n > 0) { + p--; + if (p == s) + break; /* should never happen, unless someone + * is changing the string while we are + * looking at it!! */ + if ((*p == '/') || (*p == '\\')) + n--; + } + return p + 1; +} + +static inline int +spar_channel_client_acquire_os(void __iomem *ch, u8 *id) +{ + struct channel_header __iomem *hdr = ch; + + if (readl(&hdr->cli_state_os) == CHANNELCLI_DISABLED) { + if ((readb(&hdr->cli_error_os) + & ULTRA_CLIERROROS_THROTTLEMSG_DISABLED) == 0) { + /* we are NOT throttling this message */ + writeb(readb(&hdr->cli_error_os) | + ULTRA_CLIERROROS_THROTTLEMSG_DISABLED, + &hdr->cli_error_os); + /* throttle until acquire successful */ + + pr_info("%s Channel StateTransition INVALID! - acquire failed because OS client DISABLED\n", + id); + } + return 0; + } + if ((readl(&hdr->cli_state_os) != CHANNELCLI_OWNED) && + (readl(&hdr->cli_state_boot) == CHANNELCLI_DISABLED)) { + /* Our competitor is DISABLED, so we can transition to OWNED */ + pr_info("%s Channel StateTransition (%s) %s(%d)-->%s(%d)\n", + id, "cli_state_os", + ULTRA_CHANNELCLI_STRING(readl(&hdr->cli_state_os)), + readl(&hdr->cli_state_os), + ULTRA_CHANNELCLI_STRING(CHANNELCLI_OWNED), + CHANNELCLI_OWNED); + writel(CHANNELCLI_OWNED, &hdr->cli_state_os); + mb(); /* required for channel synch */ + } + if (readl(&hdr->cli_state_os) == CHANNELCLI_OWNED) { + if (readb(&hdr->cli_error_os) != 0) { + /* we are in an error msg throttling state; + * come out of it */ + pr_info("%s Channel OS client acquire now successful\n", + id); + writeb(0, &hdr->cli_error_os); + } + return 1; + } + + /* We have to do it the "hard way". We transition to BUSY, + * and can use the channel iff our competitor has not also + * transitioned to BUSY. */ + if (readl(&hdr->cli_state_os) != CHANNELCLI_ATTACHED) { + if ((readb(&hdr->cli_error_os) + & ULTRA_CLIERROROS_THROTTLEMSG_NOTATTACHED) == 0) { + /* we are NOT throttling this message */ + writeb(readb(&hdr->cli_error_os) | + ULTRA_CLIERROROS_THROTTLEMSG_NOTATTACHED, + &hdr->cli_error_os); + /* throttle until acquire successful */ + pr_info("%s Channel StateTransition INVALID! - acquire failed because OS client NOT ATTACHED (state=%s(%d))\n", + id, ULTRA_CHANNELCLI_STRING( + readl(&hdr->cli_state_os)), + readl(&hdr->cli_state_os)); + } + return 0; + } + writel(CHANNELCLI_BUSY, &hdr->cli_state_os); + mb(); /* required for channel synch */ + if (readl(&hdr->cli_state_boot) == CHANNELCLI_BUSY) { + if ((readb(&hdr->cli_error_os) + & ULTRA_CLIERROROS_THROTTLEMSG_BUSY) == 0) { + /* we are NOT throttling this message */ + writeb(readb(&hdr->cli_error_os) | + ULTRA_CLIERROROS_THROTTLEMSG_BUSY, + &hdr->cli_error_os); + /* throttle until acquire successful */ + pr_info("%s Channel StateTransition failed - host OS acquire failed because boot BUSY\n", + id); + } + /* reset busy */ + writel(CHANNELCLI_ATTACHED, &hdr->cli_state_os); + mb(); /* required for channel synch */ + return 0; + } + if (readb(&hdr->cli_error_os) != 0) { + /* we are in an error msg throttling state; come out of it */ + pr_info("%s Channel OS client acquire now successful\n", id); + writeb(0, &hdr->cli_error_os); + } + return 1; +} + +static inline void +spar_channel_client_release_os(void __iomem *ch, u8 *id) +{ + struct channel_header __iomem *hdr = ch; + + if (readb(&hdr->cli_error_os) != 0) { + /* we are in an error msg throttling state; come out of it */ + pr_info("%s Channel OS client error state cleared\n", id); + writeb(0, &hdr->cli_error_os); + } + if (readl(&hdr->cli_state_os) == CHANNELCLI_OWNED) + return; + if (readl(&hdr->cli_state_os) != CHANNELCLI_BUSY) { + pr_info("%s Channel StateTransition INVALID! - release failed because OS client NOT BUSY (state=%s(%d))\n", + id, ULTRA_CHANNELCLI_STRING( + readl(&hdr->cli_state_os)), + readl(&hdr->cli_state_os)); + /* return; */ + } + writel(CHANNELCLI_ATTACHED, &hdr->cli_state_os); /* release busy */ +} + +/* +* Routine Description: +* Tries to insert the prebuilt signal pointed to by pSignal into the nth +* Queue of the Channel pointed to by pChannel +* +* Parameters: +* pChannel: (IN) points to the IO Channel +* Queue: (IN) nth Queue of the IO Channel +* pSignal: (IN) pointer to the signal +* +* Assumptions: +* - pChannel, Queue and pSignal are valid. +* - If insertion fails due to a full queue, the caller will determine the +* retry policy (e.g. wait & try again, report an error, etc.). +* +* Return value: 1 if the insertion succeeds, 0 if the queue was +* full. +*/ + +unsigned char spar_signal_insert(struct channel_header __iomem *ch, u32 queue, + void *sig); + +/* +* Routine Description: +* Removes one signal from Channel pChannel's nth Queue at the +* time of the call and copies it into the memory pointed to by +* pSignal. +* +* Parameters: +* pChannel: (IN) points to the IO Channel +* Queue: (IN) nth Queue of the IO Channel +* pSignal: (IN) pointer to where the signals are to be copied +* +* Assumptions: +* - pChannel and Queue are valid. +* - pSignal points to a memory area large enough to hold queue's SignalSize +* +* Return value: 1 if the removal succeeds, 0 if the queue was +* empty. +*/ + +unsigned char spar_signal_remove(struct channel_header __iomem *ch, u32 queue, + void *sig); + +/* +* Routine Description: +* Removes all signals present in Channel pChannel's nth Queue at the +* time of the call and copies them into the memory pointed to by +* pSignal. Returns the # of signals copied as the value of the routine. +* +* Parameters: +* pChannel: (IN) points to the IO Channel +* Queue: (IN) nth Queue of the IO Channel +* pSignal: (IN) pointer to where the signals are to be copied +* +* Assumptions: +* - pChannel and Queue are valid. +* - pSignal points to a memory area large enough to hold Queue's MaxSignals +* # of signals, each of which is Queue's SignalSize. +* +* Return value: +* # of signals copied. +*/ +unsigned int spar_signal_remove_all(struct channel_header *ch, u32 queue, + void *sig); + +/* +* Routine Description: +* Determine whether a signal queue is empty. +* +* Parameters: +* pChannel: (IN) points to the IO Channel +* Queue: (IN) nth Queue of the IO Channel +* +* Return value: +* 1 if the signal queue is empty, 0 otherwise. +*/ +unsigned char spar_signalqueue_empty(struct channel_header __iomem *ch, + u32 queue); + +#endif diff --git a/drivers/staging/unisys/include/channel_guid.h b/drivers/staging/unisys/include/channel_guid.h new file mode 100644 index 000000000000..706363fc3e9a --- /dev/null +++ b/drivers/staging/unisys/include/channel_guid.h @@ -0,0 +1,61 @@ +/* Copyright (C) 2010 - 2013 UNISYS CORPORATION + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for more + * details. + */ + +/* + * CHANNEL Guids + */ + +/* Used in IOChannel + * {414815ed-c58c-11da-95a9-00e08161165f} + */ +#define SPAR_VHBA_CHANNEL_PROTOCOL_UUID \ + UUID_LE(0x414815ed, 0xc58c, 0x11da, \ + 0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f) +static const uuid_le spar_vhba_channel_protocol_uuid = + SPAR_VHBA_CHANNEL_PROTOCOL_UUID; + +/* Used in IOChannel + * {8cd5994d-c58e-11da-95a9-00e08161165f} + */ +#define SPAR_VNIC_CHANNEL_PROTOCOL_UUID \ + UUID_LE(0x8cd5994d, 0xc58e, 0x11da, \ + 0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f) +static const uuid_le spar_vnic_channel_protocol_uuid = + SPAR_VNIC_CHANNEL_PROTOCOL_UUID; + +/* Used in IOChannel + * {72120008-4AAB-11DC-8530-444553544200} + */ +#define SPAR_SIOVM_UUID \ + UUID_LE(0x72120008, 0x4AAB, 0x11DC, \ + 0x85, 0x30, 0x44, 0x45, 0x53, 0x54, 0x42, 0x00) +static const uuid_le spar_siovm_uuid = SPAR_SIOVM_UUID; + +/* Used in visornoop/visornoop_main.c + * {5b52c5ac-e5f5-4d42-8dff-429eaecd221f} + */ +#define SPAR_CONTROLDIRECTOR_CHANNEL_PROTOCOL_UUID \ + UUID_LE(0x5b52c5ac, 0xe5f5, 0x4d42, \ + 0x8d, 0xff, 0x42, 0x9e, 0xae, 0xcd, 0x22, 0x1f) + +static const uuid_le spar_controldirector_channel_protocol_uuid = + SPAR_CONTROLDIRECTOR_CHANNEL_PROTOCOL_UUID; + +/* Used in visorchipset/visorchipset_main.c + * {B4E79625-AEDE-4EAA-9E11-D3EDDCD4504C} + */ +#define SPAR_DIAG_POOL_CHANNEL_PROTOCOL_UUID \ + UUID_LE(0xb4e79625, 0xaede, 0x4eaa, \ + 0x9e, 0x11, 0xd3, 0xed, 0xdc, 0xd4, 0x50, 0x4c) diff --git a/drivers/staging/unisys/visorbus/controlvmchannel.h b/drivers/staging/unisys/visorbus/controlvmchannel.h new file mode 100644 index 000000000000..a50d9cf4bed7 --- /dev/null +++ b/drivers/staging/unisys/visorbus/controlvmchannel.h @@ -0,0 +1,485 @@ +/* Copyright (C) 2010 - 2013 UNISYS CORPORATION + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for more + * details. + */ + +#ifndef __CONTROLVMCHANNEL_H__ +#define __CONTROLVMCHANNEL_H__ + +#include +#include "channel.h" + +/* {2B3C2D10-7EF5-4ad8-B966-3448B7386B3D} */ +#define SPAR_CONTROLVM_CHANNEL_PROTOCOL_UUID \ + UUID_LE(0x2b3c2d10, 0x7ef5, 0x4ad8, \ + 0xb9, 0x66, 0x34, 0x48, 0xb7, 0x38, 0x6b, 0x3d) + +#define ULTRA_CONTROLVM_CHANNEL_PROTOCOL_SIGNATURE \ + ULTRA_CHANNEL_PROTOCOL_SIGNATURE +#define CONTROLVM_MESSAGE_MAX 64 + +/* Must increment this whenever you insert or delete fields within + * this channel struct. Also increment whenever you change the meaning + * of fields within this channel struct so as to break pre-existing + * software. Note that you can usually add fields to the END of the + * channel struct withOUT needing to increment this. + */ +#define ULTRA_CONTROLVM_CHANNEL_PROTOCOL_VERSIONID 1 + +#define SPAR_CONTROLVM_CHANNEL_OK_CLIENT(ch) \ + spar_check_channel_client(ch, \ + SPAR_CONTROLVM_CHANNEL_PROTOCOL_UUID, \ + "controlvm", \ + sizeof(struct spar_controlvm_channel_protocol), \ + ULTRA_CONTROLVM_CHANNEL_PROTOCOL_VERSIONID, \ + ULTRA_CONTROLVM_CHANNEL_PROTOCOL_SIGNATURE) + +#define MAX_SERIAL_NUM 32 + +/* Defines for various channel queues */ +#define CONTROLVM_QUEUE_REQUEST 0 +#define CONTROLVM_QUEUE_RESPONSE 1 +#define CONTROLVM_QUEUE_EVENT 2 +#define CONTROLVM_QUEUE_ACK 3 + +/* Max num of messages stored during IOVM creation to be reused after crash */ +#define CONTROLVM_CRASHMSG_MAX 2 + +struct spar_segment_state { + u16 enabled:1; /* Bit 0: May enter other states */ + u16 active:1; /* Bit 1: Assigned to active partition */ + u16 alive:1; /* Bit 2: Configure message sent to + * service/server */ + u16 revoked:1; /* Bit 3: similar to partition state + * ShuttingDown */ + u16 allocated:1; /* Bit 4: memory (device/port number) + * has been selected by Command */ + u16 known:1; /* Bit 5: has been introduced to the + * service/guest partition */ + u16 ready:1; /* Bit 6: service/Guest partition has + * responded to introduction */ + u16 operating:1; /* Bit 7: resource is configured and + * operating */ + /* Note: don't use high bit unless we need to switch to ushort + * which is non-compliant */ +}; + +static const struct spar_segment_state segment_state_running = { + 1, 1, 1, 0, 1, 1, 1, 1 +}; + +static const struct spar_segment_state segment_state_paused = { + 1, 1, 1, 0, 1, 1, 1, 0 +}; + +static const struct spar_segment_state segment_state_standby = { + 1, 1, 0, 0, 1, 1, 1, 0 +}; + +/* Ids for commands that may appear in either queue of a ControlVm channel. + * + * Commands that are initiated by the command partition (CP), by an IO or + * console service partition (SP), or by a guest partition (GP)are: + * - issued on the RequestQueue queue (q #0) in the ControlVm channel + * - responded to on the ResponseQueue queue (q #1) in the ControlVm channel + * + * Events that are initiated by an IO or console service partition (SP) or + * by a guest partition (GP) are: + * - issued on the EventQueue queue (q #2) in the ControlVm channel + * - responded to on the EventAckQueue queue (q #3) in the ControlVm channel + */ +enum controlvm_id { + CONTROLVM_INVALID = 0, + /* SWITCH commands required Parameter: SwitchNumber */ + /* BUS commands required Parameter: BusNumber */ + CONTROLVM_BUS_CREATE = 0x101, /* CP --> SP, GP */ + CONTROLVM_BUS_DESTROY = 0x102, /* CP --> SP, GP */ + CONTROLVM_BUS_CONFIGURE = 0x104, /* CP --> SP */ + CONTROLVM_BUS_CHANGESTATE = 0x105, /* CP --> SP, GP */ + CONTROLVM_BUS_CHANGESTATE_EVENT = 0x106, /* SP, GP --> CP */ +/* DEVICE commands required Parameter: BusNumber, DeviceNumber */ + + CONTROLVM_DEVICE_CREATE = 0x201, /* CP --> SP, GP */ + CONTROLVM_DEVICE_DESTROY = 0x202, /* CP --> SP, GP */ + CONTROLVM_DEVICE_CONFIGURE = 0x203, /* CP --> SP */ + CONTROLVM_DEVICE_CHANGESTATE = 0x204, /* CP --> SP, GP */ + CONTROLVM_DEVICE_CHANGESTATE_EVENT = 0x205, /* SP, GP --> CP */ + CONTROLVM_DEVICE_RECONFIGURE = 0x206, /* CP --> Boot */ +/* CHIPSET commands */ + CONTROLVM_CHIPSET_INIT = 0x301, /* CP --> SP, GP */ + CONTROLVM_CHIPSET_STOP = 0x302, /* CP --> SP, GP */ + CONTROLVM_CHIPSET_READY = 0x304, /* CP --> SP */ + CONTROLVM_CHIPSET_SELFTEST = 0x305, /* CP --> SP */ + +}; + +struct irq_info { + u64 reserved1; + + /* specifies interrupt handle. It is used to retrieve the + * corresponding interrupt pin from Monitor; and the + * interrupt pin is used to connect to the corresponding + * interrupt. Used by IOPart-GP only. + */ + u64 recv_irq_handle; + + /* specifies interrupt vector. It, interrupt pin, and shared are + * used to connect to the corresponding interrupt. Used by + * IOPart-GP only. + */ + u32 recv_irq_vector; + + /* specifies if the recvInterrupt is shared. It, interrupt pin + * and vector are used to connect to 0 = not shared; 1 = shared. + * the corresponding interrupt. Used by IOPart-GP only. + */ + u8 recv_irq_shared; + u8 reserved[3]; /* Natural alignment purposes */ +}; + +struct pci_id { + u16 domain; + u8 bus; + u8 slot; + u8 func; + u8 reserved[3]; /* Natural alignment purposes */ +}; + +struct efi_spar_indication { + u64 boot_to_fw_ui:1; /* Bit 0: Stop in uefi ui */ + u64 clear_nvram:1; /* Bit 1: Clear NVRAM */ + u64 clear_cmos:1; /* Bit 2: Clear CMOS */ + u64 boot_to_tool:1; /* Bit 3: Run install tool */ + /* remaining bits are available */ +}; + +enum ultra_chipset_feature { + ULTRA_CHIPSET_FEATURE_REPLY = 0x00000001, + ULTRA_CHIPSET_FEATURE_PARA_HOTPLUG = 0x00000002, +}; + +/* This is the common structure that is at the beginning of every + * ControlVm message (both commands and responses) in any ControlVm + * queue. Commands are easily distinguished from responses by + * looking at the flags.response field. + */ +struct controlvm_message_header { + u32 id; /* See CONTROLVM_ID. */ + /* For requests, indicates the message type. */ + /* For responses, indicates the type of message we are responding to. */ + + u32 message_size; /* Includes size of this struct + size + * of message */ + u32 segment_index; /* Index of segment containing Vm + * message/information */ + u32 completion_status; /* Error status code or result of + * message completion */ + struct { + u32 failed:1; /* =1 in a response to * signify + * failure */ + u32 response_expected:1; /* =1 in all messages that expect a + * response (Control ignores this + * bit) */ + u32 server:1; /* =1 in all bus & device-related + * messages where the message + * receiver is to act as the bus or + * device server */ + u32 test_message:1; /* =1 for testing use only + * (Control and Command ignore this + * bit) */ + u32 partial_completion:1; /* =1 if there are forthcoming + * responses/acks associated + * with this message */ + u32 preserve:1; /* =1 this is to let us know to + * preserve channel contents + * (for running guests)*/ + u32 writer_in_diag:1; /* =1 the DiagWriter is active in the + * Diagnostic Partition*/ + } flags; + u32 reserved; /* Natural alignment */ + u64 message_handle; /* Identifies the particular message instance, + * and is used to match particular */ + /* request instances with the corresponding response instance. */ + u64 payload_vm_offset; /* Offset of payload area from start of this + * instance of ControlVm segment */ + u32 payload_max_bytes; /* Maximum bytes allocated in payload + * area of ControlVm segment */ + u32 payload_bytes; /* Actual number of bytes of payload + * area to copy between IO/Command; */ + /* if non-zero, there is a payload to copy. */ +}; + +struct controlvm_packet_device_create { + u32 bus_no; /* bus # (0..n-1) from the msg receiver's end */ + u32 dev_no; /* bus-relative (0..n-1) device number */ + u64 channel_addr; /* Guest physical address of the channel, which + * can be dereferenced by the receiver of this + * ControlVm command */ + u64 channel_bytes; /* specifies size of the channel in bytes */ + uuid_le data_type_uuid; /* specifies format of data in channel */ + uuid_le dev_inst_uuid; /* instance guid for the device */ + struct irq_info intr; /* specifies interrupt information */ +}; /* for CONTROLVM_DEVICE_CREATE */ + +struct controlvm_packet_device_configure { + u32 bus_no; /* bus # (0..n-1) from the msg + * receiver's perspective */ + /* Control uses header SegmentIndex field to access bus number... */ + u32 dev_no; /* bus-relative (0..n-1) device number */ +} ; /* for CONTROLVM_DEVICE_CONFIGURE */ + +struct controlvm_message_device_create { + struct controlvm_message_header header; + struct controlvm_packet_device_create packet; +}; /* total 128 bytes */ + +struct controlvm_message_device_configure { + struct controlvm_message_header header; + struct controlvm_packet_device_configure packet; +}; /* total 56 bytes */ + +/* This is the format for a message in any ControlVm queue. */ +struct controlvm_message_packet { + union { + struct { + u32 bus_no; /* bus # (0..n-1) from the msg + * receiver's perspective */ + u32 dev_count; /* indicates the max number of + * devices on this bus */ + u64 channel_addr; /* Guest physical address of + * the channel, which can be + * dereferenced by the receiver + * of this ControlVm command */ + u64 channel_bytes; /* size of the channel */ + uuid_le bus_data_type_uuid; /* indicates format of + * data in bus channel*/ + uuid_le bus_inst_uuid; /* instance uuid for the bus */ + } create_bus; /* for CONTROLVM_BUS_CREATE */ + struct { + u32 bus_no; /* bus # (0..n-1) from the msg + * receiver's perspective */ + u32 reserved; /* Natural alignment purposes */ + } destroy_bus; /* for CONTROLVM_BUS_DESTROY */ + struct { + u32 bus_no; /* bus # (0..n-1) from the receiver's + * perspective */ + u32 reserved1; /* for alignment purposes */ + u64 guest_handle; /* This is used to convert + * guest physical address to + * physical address */ + u64 recv_bus_irq_handle; + /* specifies interrupt info. It is used by SP + * to register to receive interrupts from the + * CP. This interrupt is used for bus level + * notifications. The corresponding + * sendBusInterruptHandle is kept in CP. */ + } configure_bus; /* for CONTROLVM_BUS_CONFIGURE */ + /* for CONTROLVM_DEVICE_CREATE */ + struct controlvm_packet_device_create create_device; + struct { + u32 bus_no; /* bus # (0..n-1) from the msg + * receiver's perspective */ + u32 dev_no; /* bus-relative (0..n-1) device # */ + } destroy_device; /* for CONTROLVM_DEVICE_DESTROY */ + /* for CONTROLVM_DEVICE_CONFIGURE */ + struct controlvm_packet_device_configure configure_device; + struct { + u32 bus_no; /* bus # (0..n-1) from the msg + * receiver's perspective */ + u32 dev_no; /* bus-relative (0..n-1) device # */ + } reconfigure_device; /* for CONTROLVM_DEVICE_RECONFIGURE */ + struct { + u32 bus_no; + struct spar_segment_state state; + u8 reserved[2]; /* Natural alignment purposes */ + } bus_change_state; /* for CONTROLVM_BUS_CHANGESTATE */ + struct { + u32 bus_no; + u32 dev_no; + struct spar_segment_state state; + struct { + u32 phys_device:1; /* =1 if message is for + * a physical device */ + } flags; + u8 reserved[2]; /* Natural alignment purposes */ + } device_change_state; /* for CONTROLVM_DEVICE_CHANGESTATE */ + struct { + u32 bus_no; + u32 dev_no; + struct spar_segment_state state; + u8 reserved[6]; /* Natural alignment purposes */ + } device_change_state_event; + /* for CONTROLVM_DEVICE_CHANGESTATE_EVENT */ + struct { + u32 bus_count; /* indicates the max number of busses */ + u32 switch_count; /* indicates the max number of + * switches if a service partition */ + enum ultra_chipset_feature features; + u32 platform_number; /* Platform Number */ + } init_chipset; /* for CONTROLVM_CHIPSET_INIT */ + struct { + u32 options; /* reserved */ + u32 test; /* bit 0 set to run embedded selftest */ + } chipset_selftest; /* for CONTROLVM_CHIPSET_SELFTEST */ + u64 addr; /* a physical address of something, that can be + * dereferenced by the receiver of this + * ControlVm command (depends on command id) */ + u64 handle; /* a handle of something (depends on command + * id) */ + }; +}; + +/* All messages in any ControlVm queue have this layout. */ +struct controlvm_message { + struct controlvm_message_header hdr; + struct controlvm_message_packet cmd; +}; + +struct spar_controlvm_channel_protocol { + struct channel_header header; + u64 gp_controlvm; /* guest phys addr of this channel */ + u64 gp_partition_tables;/* guest phys addr of partition tables */ + u64 gp_diag_guest; /* guest phys addr of diagnostic channel */ + u64 gp_boot_romdisk;/* guest phys addr of (read* only) Boot ROM disk */ + u64 gp_boot_ramdisk;/* guest phys addr of writable Boot RAM disk */ + u64 gp_acpi_table; /* guest phys addr of acpi table */ + u64 gp_control_channel;/* guest phys addr of control channel */ + u64 gp_diag_romdisk;/* guest phys addr of diagnostic ROM disk */ + u64 gp_nvram; /* guest phys addr of NVRAM channel */ + u64 request_payload_offset; /* Offset to request payload area */ + u64 event_payload_offset; /* Offset to event payload area */ + u32 request_payload_bytes; /* Bytes available in request payload + * area */ + u32 event_payload_bytes;/* Bytes available in event payload area */ + u32 control_channel_bytes; + u32 nvram_channel_bytes; /* Bytes in PartitionNvram segment */ + u32 message_bytes; /* sizeof(CONTROLVM_MESSAGE) */ + u32 message_count; /* CONTROLVM_MESSAGE_MAX */ + u64 gp_smbios_table; /* guest phys addr of SMBIOS tables */ + u64 gp_physical_smbios_table; /* guest phys addr of SMBIOS table */ + /* ULTRA_MAX_GUESTS_PER_SERVICE */ + char gp_reserved[2688]; + + /* guest physical address of EFI firmware image base */ + u64 virtual_guest_firmware_image_base; + + /* guest physical address of EFI firmware entry point */ + u64 virtual_guest_firmware_entry_point; + + /* guest EFI firmware image size */ + u64 virtual_guest_firmware_image_size; + + /* GPA = 1MB where EFI firmware image is copied to */ + u64 virtual_guest_firmware_boot_base; + u64 virtual_guest_image_base; + u64 virtual_guest_image_size; + u64 prototype_control_channel_offset; + u64 virtual_guest_partition_handle; + + u16 restore_action; /* Restore Action field to restore the guest + * partition */ + u16 dump_action; /* For Windows guests it shows if the visordisk + * is running in dump mode */ + u16 nvram_fail_count; + u16 saved_crash_message_count; /* = CONTROLVM_CRASHMSG_MAX */ + u32 saved_crash_message_offset; /* Offset to request payload area needed + * for crash dump */ + u32 installation_error; /* Type of error encountered during + * installation */ + u32 installation_text_id; /* Id of string to display */ + u16 installation_remaining_steps;/* Number of remaining installation + * steps (for progress bars) */ + u8 tool_action; /* ULTRA_TOOL_ACTIONS Installation Action + * field */ + u8 reserved; /* alignment */ + struct efi_spar_indication efi_spar_ind; + struct efi_spar_indication efi_spar_ind_supported; + u32 sp_reserved; + u8 reserved2[28]; /* Force signals to begin on 128-byte cache + * line */ + struct signal_queue_header request_queue;/* Service or guest partition + * uses this queue to send + * requests to Control */ + struct signal_queue_header response_queue;/* Control uses this queue to + * respond to service or guest + * partition requests */ + struct signal_queue_header event_queue; /* Control uses this queue to + * send events to service or + * guest partition */ + struct signal_queue_header event_ack_queue;/* Service or guest partition + * uses this queue to ack + * Control events */ + + /* Request fixed-size message pool - does not include payload */ + struct controlvm_message request_msg[CONTROLVM_MESSAGE_MAX]; + + /* Response fixed-size message pool - does not include payload */ + struct controlvm_message response_msg[CONTROLVM_MESSAGE_MAX]; + + /* Event fixed-size message pool - does not include payload */ + struct controlvm_message event_msg[CONTROLVM_MESSAGE_MAX]; + + /* Ack fixed-size message pool - does not include payload */ + struct controlvm_message event_ack_msg[CONTROLVM_MESSAGE_MAX]; + + /* Message stored during IOVM creation to be reused after crash */ + struct controlvm_message saved_crash_msg[CONTROLVM_CRASHMSG_MAX]; +}; + +/* Offsets for VM channel attributes */ +#define VM_CH_REQ_QUEUE_OFFSET \ + offsetof(struct spar_controlvm_channel_protocol, request_queue) +#define VM_CH_RESP_QUEUE_OFFSET \ + offsetof(struct spar_controlvm_channel_protocol, response_queue) +#define VM_CH_EVENT_QUEUE_OFFSET \ + offsetof(struct spar_controlvm_channel_protocol, event_queue) +#define VM_CH_ACK_QUEUE_OFFSET \ + offsetof(struct spar_controlvm_channel_protocol, event_ack_queue) +#define VM_CH_REQ_MSG_OFFSET \ + offsetof(struct spar_controlvm_channel_protocol, request_msg) +#define VM_CH_RESP_MSG_OFFSET \ + offsetof(struct spar_controlvm_channel_protocol, response_msg) +#define VM_CH_EVENT_MSG_OFFSET \ + offsetof(struct spar_controlvm_channel_protocol, event_msg) +#define VM_CH_ACK_MSG_OFFSET \ + offsetof(struct spar_controlvm_channel_protocol, event_ack_msg) +#define VM_CH_CRASH_MSG_OFFSET \ + offsetof(struct spar_controlvm_channel_protocol, saved_crash_msg) + +/* The following header will be located at the beginning of PayloadVmOffset for + * various ControlVm commands. The receiver of a ControlVm command with a + * PayloadVmOffset will dereference this address and then use connection_offset, + * initiator_offset, and target_offset to get the location of UTF-8 formatted + * strings that can be parsed to obtain command-specific information. The value + * of total_length should equal PayloadBytes. The format of the strings at + * PayloadVmOffset will take different forms depending on the message. + */ +struct spar_controlvm_parameters_header { + u32 total_length; + u32 header_length; + u32 connection_offset; + u32 connection_length; + u32 initiator_offset; + u32 initiator_length; + u32 target_offset; + u32 target_length; + u32 client_offset; + u32 client_length; + u32 name_offset; + u32 name_length; + uuid_le id; + u32 revision; + u32 reserved; /* Natural alignment */ +}; + +#endif /* __CONTROLVMCHANNEL_H__ */