/* SPDX-License-Identifier: GPL-2.0+ */
|
/*
|
* Copyright (C) 2010 - 2016 UNISYS CORPORATION
|
* All rights reserved.
|
*/
|
|
#ifndef __IOCHANNEL_H__
|
#define __IOCHANNEL_H__
|
|
/*
|
* Everything needed for IOPart-GuestPart communication is define in
|
* this file. Note: Everything is OS-independent because this file is
|
* used by Windows, Linux and possible EFI drivers.
|
*
|
* Communication flow between the IOPart and GuestPart uses the channel headers
|
* channel state. The following states are currently being used:
|
* UNINIT(All Zeroes), CHANNEL_ATTACHING, CHANNEL_ATTACHED, CHANNEL_OPENED
|
*
|
* Additional states will be used later. No locking is needed to switch between
|
* states due to the following rules:
|
*
|
* 1. IOPart is only the only partition allowed to change from UNIT
|
* 2. IOPart is only the only partition allowed to change from
|
* CHANNEL_ATTACHING
|
* 3. GuestPart is only the only partition allowed to change from
|
* CHANNEL_ATTACHED
|
*
|
* The state changes are the following: IOPart sees the channel is in UNINIT,
|
* UNINIT -> CHANNEL_ATTACHING (performed only by IOPart)
|
* CHANNEL_ATTACHING -> CHANNEL_ATTACHED (performed only by IOPart)
|
* CHANNEL_ATTACHED -> CHANNEL_OPENED (performed only by GuestPart)
|
*/
|
|
#include <linux/uuid.h>
|
#include <linux/skbuff.h>
|
#include <linux/visorbus.h>
|
|
/*
|
* Must increment these 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 VISOR_VHBA_CHANNEL_VERSIONID 2
|
#define VISOR_VNIC_CHANNEL_VERSIONID 2
|
|
/*
|
* Everything necessary to handle SCSI & NIC traffic between Guest Partition and
|
* IO Partition is defined below.
|
*/
|
|
/*
|
* Define the two queues per data channel between iopart and ioguestparts.
|
* IOCHAN_TO_IOPART -- used by guest to 'insert' signals to iopart.
|
* IOCHAN_FROM_IOPART -- used by guest to 'remove' signals from IO part.
|
*/
|
#define IOCHAN_TO_IOPART 0
|
#define IOCHAN_FROM_IOPART 1
|
|
/* Size of cdb - i.e., SCSI cmnd */
|
#define MAX_CMND_SIZE 16
|
|
/* Unisys-specific DMA direction values */
|
enum uis_dma_data_direction {
|
UIS_DMA_BIDIRECTIONAL = 0,
|
UIS_DMA_TO_DEVICE = 1,
|
UIS_DMA_FROM_DEVICE = 2,
|
UIS_DMA_NONE = 3
|
};
|
|
#define MAX_SENSE_SIZE 64
|
#define MAX_PHYS_INFO 64
|
|
/*
|
* enum net_types - Various types of network packets that can be sent in cmdrsp.
|
* @NET_RCV_POST: Submit buffer to hold receiving incoming packet.
|
* @NET_RCV: visornic -> uisnic. Incoming packet received.
|
* @NET_XMIT: uisnic -> visornic. For outgoing packet.
|
* @NET_XMIT_DONE: visornic -> uisnic. Outgoing packet xmitted.
|
* @NET_RCV_ENBDIS: uisnic -> visornic. Enable/Disable packet reception.
|
* @NET_RCV_ENBDIS_ACK: visornic -> uisnic. Acknowledge enable/disable packet.
|
* @NET_RCV_PROMISC: uisnic -> visornic. Enable/Disable promiscuous mode.
|
* @NET_CONNECT_STATUS: visornic -> uisnic. Indicate the loss or restoration of
|
* a network connection.
|
* @NET_MACADDR: uisnic -> visornic. Indicates the client has requested
|
* to update it's MAC address.
|
* @NET_MACADDR_ACK: MAC address acknowledge.
|
*/
|
enum net_types {
|
NET_RCV_POST = 0,
|
NET_RCV,
|
NET_XMIT,
|
NET_XMIT_DONE,
|
NET_RCV_ENBDIS,
|
NET_RCV_ENBDIS_ACK,
|
/* Reception */
|
NET_RCV_PROMISC,
|
NET_CONNECT_STATUS,
|
NET_MACADDR,
|
NET_MACADDR_ACK,
|
};
|
|
/* Minimum eth data size */
|
#define ETH_MIN_DATA_SIZE 46
|
#define ETH_MIN_PACKET_SIZE (ETH_HLEN + ETH_MIN_DATA_SIZE)
|
|
/* Maximum data size */
|
#define VISOR_ETH_MAX_MTU 16384
|
|
#ifndef MAX_MACADDR_LEN
|
/* Number of bytes in MAC address */
|
#define MAX_MACADDR_LEN 6
|
#endif
|
|
/* Various types of scsi task mgmt commands. */
|
enum task_mgmt_types {
|
TASK_MGMT_ABORT_TASK = 1,
|
TASK_MGMT_BUS_RESET,
|
TASK_MGMT_LUN_RESET,
|
TASK_MGMT_TARGET_RESET,
|
};
|
|
/* Various types of vdisk mgmt commands. */
|
enum vdisk_mgmt_types {
|
VDISK_MGMT_ACQUIRE = 1,
|
VDISK_MGMT_RELEASE,
|
};
|
|
struct phys_info {
|
u64 pi_pfn;
|
u16 pi_off;
|
u16 pi_len;
|
} __packed;
|
|
#define MIN_NUMSIGNALS 64
|
|
/* Structs with pragma pack. */
|
|
struct guest_phys_info {
|
u64 address;
|
u64 length;
|
} __packed;
|
|
/*
|
* struct uisscsi_dest
|
* @channel: Bus number.
|
* @id: Target number.
|
* @lun: Logical unit number.
|
*/
|
struct uisscsi_dest {
|
u32 channel;
|
u32 id;
|
u32 lun;
|
} __packed;
|
|
struct vhba_wwnn {
|
u32 wwnn1;
|
u32 wwnn2;
|
} __packed;
|
|
/*
|
* struct vhba_config_max
|
* @max_channel: Maximum channel for devices attached to this bus.
|
* @max_id: Maximum SCSI ID for devices attached to bus.
|
* @max_lun: Maximum SCSI LUN for devices attached to bus.
|
* @cmd_per_lun: Maximum number of outstanding commands per LUN.
|
* @max_io_size: Maximum io size for devices attached to this bus. Max io size
|
* is often determined by the resource of the hba.
|
* e.g Max scatter gather list length * page size / sector size.
|
*
|
* WARNING: Values stored in this structure must contain maximum counts (not
|
* maximum values).
|
*
|
* 20 bytes
|
*/
|
struct vhba_config_max {
|
u32 max_channel;
|
u32 max_id;
|
u32 max_lun;
|
u32 cmd_per_lun;
|
u32 max_io_size;
|
} __packed;
|
|
/*
|
* struct uiscmdrsp_scsi
|
*
|
* @handle: The handle to the cmd that was received. Send it back as
|
* is in the rsp packet.
|
* @cmnd: The cdb for the command.
|
* @bufflen: Length of data to be transferred out or in.
|
* @guest_phys_entries: Number of entries in scatter-gather list.
|
* @struct gpi_list: Physical address information for each fragment.
|
* @data_dir: Direction of the data, if any.
|
* @struct vdest: Identifies the virtual hba, id, channel, lun to which
|
* cmd was sent.
|
* @linuxstat: Original Linux status used by Linux vdisk.
|
* @scsistat: The scsi status.
|
* @addlstat: Non-scsi status.
|
* @sensebuf: Sense info in case cmd failed. sensebuf holds the
|
* sense_data struct. See sense_data struct for more
|
* details.
|
* @*vdisk: Pointer to the vdisk to clean up when IO completes.
|
* @no_disk_result: Used to return no disk inquiry result when
|
* no_disk_result is set to 1
|
* scsi.scsistat is SAM_STAT_GOOD
|
* scsi.addlstat is 0
|
* scsi.linuxstat is SAM_STAT_GOOD
|
* That is, there is NO error.
|
*/
|
struct uiscmdrsp_scsi {
|
u64 handle;
|
u8 cmnd[MAX_CMND_SIZE];
|
u32 bufflen;
|
u16 guest_phys_entries;
|
struct guest_phys_info gpi_list[MAX_PHYS_INFO];
|
u32 data_dir;
|
struct uisscsi_dest vdest;
|
/* Needed to queue the rsp back to cmd originator. */
|
int linuxstat;
|
u8 scsistat;
|
u8 addlstat;
|
#define ADDL_SEL_TIMEOUT 4
|
/* The following fields are need to determine the result of command. */
|
u8 sensebuf[MAX_SENSE_SIZE];
|
void *vdisk;
|
int no_disk_result;
|
} __packed;
|
|
/*
|
* Defines to support sending correct inquiry result when no disk is
|
* configured.
|
*
|
* From SCSI SPC2 -
|
*
|
* If the target is not capable of supporting a device on this logical unit, the
|
* device server shall set this field to 7Fh (PERIPHERAL QUALIFIER set to 011b
|
* and PERIPHERAL DEVICE TYPE set to 1Fh).
|
*
|
* The device server is capable of supporting the specified peripheral device
|
* type on this logical unit. However, the physical device is not currently
|
* connected to this logical unit.
|
*/
|
|
/*
|
* Peripheral qualifier of 0x3
|
* Peripheral type of 0x1f
|
* Specifies no device but target present
|
*/
|
#define DEV_NOT_CAPABLE 0x7f
|
/*
|
* Peripheral qualifier of 0x1
|
* Peripheral type of 0 - disk
|
* Specifies device capable, but not present
|
*/
|
#define DEV_DISK_CAPABLE_NOT_PRESENT 0x20
|
/* HiSup = 1; shows support for report luns must be returned for lun 0. */
|
#define DEV_HISUPPORT 0x10
|
|
/*
|
* Peripheral qualifier of 0x3
|
* Peripheral type of 0x1f
|
* Specifies no device but target present
|
*/
|
#define DEV_NOT_CAPABLE 0x7f
|
/*
|
* Peripheral qualifier of 0x1
|
* Peripheral type of 0 - disk
|
* Specifies device capable, but not present
|
*/
|
#define DEV_DISK_CAPABLE_NOT_PRESENT 0x20
|
/* HiSup = 1; shows support for report luns must be returned for lun 0. */
|
#define DEV_HISUPPORT 0x10
|
|
/*
|
* NOTE: Linux code assumes inquiry contains 36 bytes. Without checking length
|
* in buf[4] some Linux code accesses bytes beyond 5 to retrieve vendor, product
|
* and revision. Yikes! So let us always send back 36 bytes, the minimum for
|
* inquiry result.
|
*/
|
#define NO_DISK_INQUIRY_RESULT_LEN 36
|
/* 5 bytes minimum for inquiry result */
|
#define MIN_INQUIRY_RESULT_LEN 5
|
|
/* SCSI device version for no disk inquiry result */
|
/* indicates SCSI SPC2 (SPC3 is 5) */
|
#define SCSI_SPC2_VER 4
|
|
/* Struct and Defines to support sense information. */
|
|
/*
|
* The following struct is returned in sensebuf field in uiscmdrsp_scsi. It is
|
* initialized in exactly the manner that is recommended in Windows (hence the
|
* odd values).
|
* When set, these fields will have the following values:
|
* ErrorCode = 0x70 indicates current error
|
* Valid = 1 indicates sense info is valid
|
* SenseKey contains sense key as defined by SCSI specs.
|
* AdditionalSenseCode contains sense key as defined by SCSI specs.
|
* AdditionalSenseCodeQualifier contains qualifier to sense code as defined by
|
* scsi docs.
|
* AdditionalSenseLength contains will be sizeof(sense_data)-8=10.
|
*/
|
struct sense_data {
|
u8 errorcode:7;
|
u8 valid:1;
|
u8 segment_number;
|
u8 sense_key:4;
|
u8 reserved:1;
|
u8 incorrect_length:1;
|
u8 end_of_media:1;
|
u8 file_mark:1;
|
u8 information[4];
|
u8 additional_sense_length;
|
u8 command_specific_information[4];
|
u8 additional_sense_code;
|
u8 additional_sense_code_qualifier;
|
u8 fru_code;
|
u8 sense_key_specific[3];
|
} __packed;
|
|
/*
|
* struct net_pkt_xmt
|
* @len: Full length of data in the packet.
|
* @num_frags: Number of fragments in frags containing data.
|
* @struct phys_info frags: Physical page information.
|
* @ethhdr: The ethernet header.
|
* @struct lincsum: These are needed for csum at uisnic end.
|
* @valid: 1 = struct is valid - else ignore.
|
* @hrawoffv: 1 = hwrafoff is valid.
|
* @nhrawoffv: 1 = nhwrafoff is valid.
|
* @protocol: Specifies packet protocol.
|
* @csum: Value used to set skb->csum at IOPart.
|
* @hrawoff: Value used to set skb->h.raw at IOPart. hrawoff points to
|
* the start of the TRANSPORT LAYER HEADER.
|
* @nhrawoff: Value used to set skb->nh.raw at IOPart. nhrawoff points to
|
* the start of the NETWORK LAYER HEADER.
|
*
|
* NOTE:
|
* The full packet is described in frags but the ethernet header is separately
|
* kept in ethhdr so that uisnic doesn't have "MAP" the guest memory to get to
|
* the header. uisnic needs ethhdr to determine how to route the packet.
|
*/
|
struct net_pkt_xmt {
|
int len;
|
int num_frags;
|
struct phys_info frags[MAX_PHYS_INFO];
|
char ethhdr[ETH_HLEN];
|
struct {
|
u8 valid;
|
u8 hrawoffv;
|
u8 nhrawoffv;
|
__be16 protocol;
|
__wsum csum;
|
u32 hrawoff;
|
u32 nhrawoff;
|
} lincsum;
|
} __packed;
|
|
struct net_pkt_xmtdone {
|
/* Result of NET_XMIT */
|
u32 xmt_done_result;
|
} __packed;
|
|
/*
|
* RCVPOST_BUF_SIZE must be at most page_size(4096) - cache_line_size (64) The
|
* reason is because dev_skb_alloc which is used to generate RCV_POST skbs in
|
* visornic requires that there is "overhead" in the buffer, and pads 16 bytes.
|
* Use 1 full cache line size for "overhead" so that transfers are optimized.
|
* IOVM requires that a buffer be represented by 1 phys_info structure
|
* which can only cover page_size.
|
*/
|
#define RCVPOST_BUF_SIZE 4032
|
#define MAX_NET_RCV_CHAIN \
|
((VISOR_ETH_MAX_MTU + ETH_HLEN + RCVPOST_BUF_SIZE - 1) \
|
/ RCVPOST_BUF_SIZE)
|
|
/* rcv buf size must be large enough to include ethernet data len + ethernet
|
* header len - we are choosing 2K because it is guaranteed to be describable.
|
*/
|
struct net_pkt_rcvpost {
|
/* Physical page information for the single fragment 2K rcv buf */
|
struct phys_info frag;
|
/*
|
* Ensures that receive posts are returned to the adapter which we sent
|
* them from originally.
|
*/
|
u64 unique_num;
|
|
} __packed;
|
|
/*
|
* struct net_pkt_rcv
|
* @rcv_done_len: Length of the received data.
|
* @numrcvbufs: Contains the incoming data. Guest side MUST chain these
|
* together.
|
* @*rcvbuf: List of chained rcvbufa. Each entry is a receive buffer
|
* provided by NET_RCV_POST. NOTE: First rcvbuf in the
|
* chain will also be provided in net.buf.
|
* @unique_num:
|
* @rcvs_dropped_delta:
|
*
|
* The number of rcvbuf that can be chained is based on max mtu and size of each
|
* rcvbuf.
|
*/
|
struct net_pkt_rcv {
|
u32 rcv_done_len;
|
u8 numrcvbufs;
|
void *rcvbuf[MAX_NET_RCV_CHAIN];
|
u64 unique_num;
|
u32 rcvs_dropped_delta;
|
} __packed;
|
|
struct net_pkt_enbdis {
|
void *context;
|
/* 1 = enable, 0 = disable */
|
u16 enable;
|
} __packed;
|
|
struct net_pkt_macaddr {
|
void *context;
|
/* 6 bytes */
|
u8 macaddr[MAX_MACADDR_LEN];
|
} __packed;
|
|
/*
|
* struct uiscmdrsp_net - cmd rsp packet used for VNIC network traffic.
|
* @enum type:
|
* @*buf:
|
* @union:
|
* @struct xmt: Used for NET_XMIT.
|
* @struct xmtdone: Used for NET_XMIT_DONE.
|
* @struct rcvpost: Used for NET_RCV_POST.
|
* @struct rcv: Used for NET_RCV.
|
* @struct enbdis: Used for NET_RCV_ENBDIS, NET_RCV_ENBDIS_ACK,
|
* NET_RCV_PROMSIC, and NET_CONNECT_STATUS.
|
* @struct macaddr:
|
*/
|
struct uiscmdrsp_net {
|
enum net_types type;
|
void *buf;
|
union {
|
struct net_pkt_xmt xmt;
|
struct net_pkt_xmtdone xmtdone;
|
struct net_pkt_rcvpost rcvpost;
|
struct net_pkt_rcv rcv;
|
struct net_pkt_enbdis enbdis;
|
struct net_pkt_macaddr macaddr;
|
};
|
} __packed;
|
|
/*
|
* struct uiscmdrsp_scsitaskmgmt
|
* @enum tasktype: The type of task.
|
* @struct vdest: The vdisk for which this task mgmt is generated.
|
* @handle: This is a handle that the guest has saved off for its
|
* own use. The handle value is preserved by iopart and
|
* returned as in task mgmt rsp.
|
* @notify_handle: For Linux guests, this is a pointer to wait_queue_head
|
* that a thread is waiting on to see if the taskmgmt
|
* command has completed. When the rsp is received by
|
* guest, the thread receiving the response uses this to
|
* notify the thread waiting for taskmgmt command
|
* completion. It's value is preserved by iopart and
|
* returned as in the task mgmt rsp.
|
* @notifyresult_handle: This is a handle to the location in the guest where
|
* the result of the taskmgmt command (result field) is
|
* saved to when the response is handled. It's value is
|
* preserved by iopart and returned as is in the task mgmt
|
* rsp.
|
* @result: Result of taskmgmt command - set by IOPart.
|
*/
|
struct uiscmdrsp_scsitaskmgmt {
|
enum task_mgmt_types tasktype;
|
struct uisscsi_dest vdest;
|
u64 handle;
|
u64 notify_handle;
|
u64 notifyresult_handle;
|
char result;
|
|
#define TASK_MGMT_FAILED 0
|
} __packed;
|
|
/*
|
* struct uiscmdrsp_disknotify - Used by uissd to send disk add/remove
|
* notifications to Guest.
|
* @add: 0-remove, 1-add.
|
* @*v_hba: Channel info to route msg.
|
* @channel: SCSI Path of Disk to added or removed.
|
* @id: SCSI Path of Disk to added or removed.
|
* @lun: SCSI Path of Disk to added or removed.
|
*
|
* Note that the vHba pointer is not used by the Client/Guest side.
|
*/
|
struct uiscmdrsp_disknotify {
|
u8 add;
|
void *v_hba;
|
u32 channel, id, lun;
|
} __packed;
|
|
/* Keeping cmd and rsp info in one structure for now cmd rsp packet for SCSI */
|
struct uiscmdrsp {
|
char cmdtype;
|
/* Describes what type of information is in the struct */
|
#define CMD_SCSI_TYPE 1
|
#define CMD_NET_TYPE 2
|
#define CMD_SCSITASKMGMT_TYPE 3
|
#define CMD_NOTIFYGUEST_TYPE 4
|
union {
|
struct uiscmdrsp_scsi scsi;
|
struct uiscmdrsp_net net;
|
struct uiscmdrsp_scsitaskmgmt scsitaskmgmt;
|
struct uiscmdrsp_disknotify disknotify;
|
};
|
/* Send the response when the cmd is done (scsi and scsittaskmgmt). */
|
void *private_data;
|
/* General Purpose Queue Link */
|
struct uiscmdrsp *next;
|
/* Pointer to the nextactive commands */
|
struct uiscmdrsp *activeQ_next;
|
/* Pointer to the prevactive commands */
|
struct uiscmdrsp *activeQ_prev;
|
} __packed;
|
|
/* total = 28 bytes */
|
struct iochannel_vhba {
|
/* 8 bytes */
|
struct vhba_wwnn wwnn;
|
/* 20 bytes */
|
struct vhba_config_max max;
|
} __packed;
|
|
struct iochannel_vnic {
|
/* 6 bytes */
|
u8 macaddr[6];
|
/* 4 bytes */
|
u32 num_rcv_bufs;
|
/* 4 bytes */
|
u32 mtu;
|
/* 16 bytes */
|
guid_t zone_guid;
|
} __packed;
|
|
/*
|
* This is just the header of the IO channel. It is assumed that directly after
|
* this header there is a large region of memory which contains the command and
|
* response queues as specified in cmd_q and rsp_q SIGNAL_QUEUE_HEADERS.
|
*/
|
struct visor_io_channel {
|
struct channel_header channel_header;
|
struct signal_queue_header cmd_q;
|
struct signal_queue_header rsp_q;
|
union {
|
struct iochannel_vhba vhba;
|
struct iochannel_vnic vnic;
|
} __packed;
|
|
#define MAX_CLIENTSTRING_LEN 1024
|
/* client_string is NULL termimated so holds max-1 bytes */
|
u8 client_string[MAX_CLIENTSTRING_LEN];
|
} __packed;
|
|
/* INLINE functions for initializing and accessing I/O data channels. */
|
#define SIZEOF_CMDRSP (64 * DIV_ROUND_UP(sizeof(struct uiscmdrsp), 64))
|
|
/* Use 4K page sizes when passing page info between Guest and IOPartition. */
|
#define PI_PAGE_SIZE 0x1000
|
#define PI_PAGE_MASK 0x0FFF
|
|
/* __IOCHANNEL_H__ */
|
#endif
|