Release 4.11 drivers/staging/unisys/include/iochannel.h
/* 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/dma-direction.h>
#include "channel.h"
#define ULTRA_VHBA_CHANNEL_PROTOCOL_SIGNATURE ULTRA_CHANNEL_PROTOCOL_SIGNATURE
#define ULTRA_VNIC_CHANNEL_PROTOCOL_SIGNATURE ULTRA_CHANNEL_PROTOCOL_SIGNATURE
#define ULTRA_VSWITCH_CHANNEL_PROTOCOL_SIGNATURE \
ULTRA_CHANNEL_PROTOCOL_SIGNATURE
/*
* 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 ULTRA_VHBA_CHANNEL_PROTOCOL_VERSIONID 2
#define ULTRA_VNIC_CHANNEL_PROTOCOL_VERSIONID 2
#define ULTRA_VSWITCH_CHANNEL_PROTOCOL_VERSIONID 1
#define SPAR_VHBA_CHANNEL_OK_CLIENT(ch) \
(spar_check_channel_client(ch, spar_vhba_channel_protocol_uuid, \
"vhba", MIN_IO_CHANNEL_SIZE, \
ULTRA_VHBA_CHANNEL_PROTOCOL_VERSIONID, \
ULTRA_VHBA_CHANNEL_PROTOCOL_SIGNATURE))
#define SPAR_VNIC_CHANNEL_OK_CLIENT(ch) \
(spar_check_channel_client(ch, spar_vnic_channel_protocol_uuid, \
"vnic", MIN_IO_CHANNEL_SIZE, \
ULTRA_VNIC_CHANNEL_PROTOCOL_VERSIONID, \
ULTRA_VNIC_CHANNEL_PROTOCOL_SIGNATURE))
/*
* Everything necessary to handle SCSI & NIC traffic between Guest Partition and
* IO Partition is defined below.
*/
/* Defines and enums. */
#define MINNUM(a, b) (((a) < (b)) ? (a) : (b))
#define MAXNUM(a, b) (((a) > (b)) ? (a) : (b))
/* Define the two queues per data channel between iopart and ioguestparts. */
/* Used by ioguestpart to 'insert' signals to iopart. */
#define IOCHAN_TO_IOPART 0
/* Used by ioguestpart to 'remove' signals from iopart, same previous queue. */
#define IOCHAN_FROM_IOPART 1
/* Size of cdb - i.e., SCSI cmnd */
#define MAX_CMND_SIZE 16
#define MAX_SENSE_SIZE 64
#define MAX_PHYS_INFO 64
/* Various types of network packets that can be sent in cmdrsp. */
enum net_types {
NET_RCV_POST = 0, /*
* Submit buffer to hold receiving
* incoming packet
*/
/* visornic -> uisnic */
NET_RCV, /* incoming packet received */
/* uisnic -> virtpci */
NET_XMIT, /* for outgoing net packets */
/* visornic -> uisnic */
NET_XMIT_DONE, /* outgoing packet xmitted */
/* uisnic -> virtpci */
NET_RCV_ENBDIS, /* enable/disable packet reception */
/* visornic -> uisnic */
NET_RCV_ENBDIS_ACK, /* acknowledge enable/disable packet */
/* reception */
/* uisnic -> visornic */
NET_RCV_PROMISC, /* enable/disable promiscuous mode */
/* visornic -> uisnic */
NET_CONNECT_STATUS, /*
* indicate the loss or restoration of a network
* connection
*/
/* uisnic -> visornic */
NET_MACADDR, /*
* Indicates the client has requested to update
* it's MAC address
*/
NET_MACADDR_ACK, /* MAC address acknowledge */
};
#define ETH_MIN_DATA_SIZE 46
/* minimum eth data size */
#define ETH_MIN_PACKET_SIZE (ETH_HLEN + ETH_MIN_DATA_SIZE)
#define VISOR_ETH_MAX_MTU 16384
/* maximum data size */
#ifndef MAX_MACADDR_LEN
#define MAX_MACADDR_LEN 6
/* number of bytes in MAC address */
#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;
#define GPI_ENTRIES_PER_PAGE (PAGE_SIZE / sizeof(struct guest_phys_info))
struct uisscsi_dest {
u32 channel; /* channel == bus number */
u32 id; /* id == target number */
u32 lun; /* lun == logical unit number */
}
__packed;
struct vhba_wwnn {
u32 wwnn1;
u32 wwnn2;
}
__packed;
/*
* WARNING: Values stired in this structure must contain maximum counts (not
* maximum values).
*/
struct vhba_config_max {/* 20 bytes */
u32 max_channel;/* maximum channel for devices attached to this bus */
u32 max_id; /* maximum SCSI ID for devices attached to bus */
u32 max_lun; /* maximum SCSI LUN for devices attached to bus */
u32 cmd_per_lun;/* maximum number of outstanding commands per LUN */
u32 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 */
}
__packed;
struct uiscmdrsp_scsi {
u64 handle; /* the handle to the cmd that was received */
/* send it back as is in the rsp packet. */
u8 cmnd[MAX_CMND_SIZE]; /* the cdb for the command */
u32 bufflen; /* length of data to be transferred out or in */
u16 guest_phys_entries; /* Number of entries in scatter-gather list */
struct guest_phys_info gpi_list[MAX_PHYS_INFO]; /* physical address
* information for each
* fragment
*/
enum dma_data_direction data_dir; /* direction of the data, if any */
struct uisscsi_dest vdest; /* identifies the virtual hba, id, */
/* channel, lun to which cmd was sent */
/* Needed to queue the rsp back to cmd originator. */
int linuxstat; /* original Linux status used by Linux vdisk */
u8 scsistat; /* the scsi status */
u8 addlstat; /* non-scsi status */
#define ADDL_SEL_TIMEOUT 4
/* The following fields are need to determine the result of command. */
u8 sensebuf[MAX_SENSE_SIZE]; /* sense info in case cmd failed; */
/* sensebuf holds the sense_data struct; */
/* See sense_data struct for more details. */
void *vdisk; /* Pointer to the vdisk to clean up when IO completes. */
int 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.
*/
}
__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.
*/
#define DEV_NOT_CAPABLE 0x7f
/*
* peripheral qualifier of 0x3
* peripheral type of 0x1f
* specifies no device but target present
*/
#define DEV_DISK_CAPABLE_NOT_PRESENT 0x20
/* peripheral qualifier of 0x1
* peripheral type of 0 - disk
* Specifies device capable, but
* not present
*/
#define DEV_HISUPPORT 0x10
/*
* HiSup = 1; shows support for report luns
* must be returned for lun 0.
*/
/*
* 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
#define MIN_INQUIRY_RESULT_LEN 5
/* 5 bytes minimum for inquiry result */
/* SCSI device version for no disk inquiry result */
#define SCSI_SPC2_VER 4
/* indicates SCSI SPC2 (SPC3 is 5) */
/* 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 {
int len; /* full length of data in the packet */
int num_frags; /* number of fragments in frags containing data */
struct phys_info frags[MAX_PHYS_INFO]; /* physical page information */
char ethhdr[ETH_HLEN]; /* the ethernet header */
struct {
/* These are needed for csum at uisnic end */
u8 valid; /* 1 = struct is valid - else ignore */
u8 hrawoffv; /* 1 = hwrafoff is valid */
u8 nhrawoffv; /* 1 = nhwrafoff is valid */
u16 protocol; /* specifies packet protocol */
u32 csum; /* value used to set skb->csum at IOPart */
u32 hrawoff; /* value used to set skb->h.raw at IOPart */
/* hrawoff points to the start of the TRANSPORT LAYER HEADER */
u32 nhrawoff; /* value used to set skb->nh.raw at IOPart */
/* nhrawoff points to the start of the NETWORK LAYER HEADER */
}
lincsum;
/*
* 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.
*/
}
__packed;
struct net_pkt_xmtdone {
u32 xmt_done_result; /* result of NET_XMIT */
}
__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;
/*
* 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; /* length of received data */
/*
* numrcvbufs: contain the incoming data; guest side MUST chain these
* together.
*/
u8 numrcvbufs;
void *rcvbuf[MAX_NET_RCV_CHAIN]; /* list of chained rcvbufs */
/* Each entry is a receive buffer provided by NET_RCV_POST. */
/* NOTE: first rcvbuf in the chain will also be provided in net.buf. */
u64 unique_num;
u32 rcvs_dropped_delta;
}
__packed;
struct net_pkt_enbdis {
void *context;
u16 enable; /* 1 = enable, 0 = disable */
}
__packed;
struct net_pkt_macaddr {
void *context;
u8 macaddr[MAX_MACADDR_LEN]; /* 6 bytes */
}
__packed;
/* cmd rsp packet used for VNIC network traffic */
struct uiscmdrsp_net {
enum net_types type;
void *buf;
union {
struct net_pkt_xmt xmt; /* used for NET_XMIT */
struct net_pkt_xmtdone xmtdone; /* used for NET_XMIT_DONE */
struct net_pkt_rcvpost rcvpost; /* used for NET_RCV_POST */
struct net_pkt_rcv rcv; /* used for NET_RCV */
struct net_pkt_enbdis enbdis; /* used for NET_RCV_ENBDIS, */
/* NET_RCV_ENBDIS_ACK, */
/* NET_RCV_PROMSIC, */
/* and NET_CONNECT_STATUS */
struct net_pkt_macaddr macaddr;
};
}
__packed;
struct uiscmdrsp_scsitaskmgmt {
/* The type of task. */
enum task_mgmt_types tasktype;
/* The vdisk for which this task mgmt is generated. */
struct uisscsi_dest vdest;
/*
* 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.
*/
u64 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.
*/
u64 notify_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 in
* the task mgmt rsp.
*/
u64 notifyresult_handle;
/* Result of taskmgmt command - set by IOPart - values are: */
char result;
#define TASK_MGMT_FAILED 0
}
__packed;
/* Used by uissd to send disk add/remove notifications to Guest. */
/* Note that the vHba pointer is not used by the Client/Guest side. */
struct uiscmdrsp_disknotify {
u8 add; /* 0-remove, 1-add */
void *v_hba; /* channel info to route msg */
u32 channel, id, lun; /* SCSI Path of Disk to added or removed */
}
__packed;
/*
* The following is used by virthba/vSCSI to send the Acquire/Release commands
* to the IOVM.
*/
struct uiscmdrsp_vdiskmgmt {
/* The type of task */
enum vdisk_mgmt_types vdisktype;
/* The vdisk for which this task mgmt is generated */
struct uisscsi_dest vdest;
/*
* This is a handle that the guest has saved off for its own use. It's
* value is preserved by iopart and returned as in the task mgmt rsp.
*/
u64 handle;
/*
* For Linux guests, this is a pointer to wait_queue_head that a
* thread is waiting on to see if the tskmgmt 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.
*/
u64 notify_handle;
/*
* Handle to the location in 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 in
* the task mgmt rsp.
*/
u64 notifyresult_handle;
/* Result of taskmgmt command - set by IOPart - values are: */
char result;
}
__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
#define CMD_VDISKMGMT_TYPE 5
union {
struct uiscmdrsp_scsi scsi;
struct uiscmdrsp_net net;
struct uiscmdrsp_scsitaskmgmt scsitaskmgmt;
struct uiscmdrsp_disknotify disknotify;
struct uiscmdrsp_vdiskmgmt vdiskmgmt;
};
/* Send the response when the cmd is done (scsi and scsittaskmgmt). */
void *private_data;
struct uiscmdrsp *next; /* General Purpose Queue Link */
struct uiscmdrsp *activeQ_next; /* Pointer to the nextactive commands */
struct uiscmdrsp *activeQ_prev; /* Pointer to the prevactive commands */
}
__packed;
struct iochannel_vhba {
struct vhba_wwnn wwnn; /* 8 bytes */
struct vhba_config_max max; /* 20 bytes */
}
__packed;
/* total = 28 bytes */
struct iochannel_vnic {
u8 macaddr[6]; /* 6 bytes */
u32 num_rcv_bufs; /* 4 bytes */
u32 mtu; /* 4 bytes */
uuid_le zone_uuid; /* 16 bytes */
}
__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 spar_io_channel_protocol {
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 (COVER(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
/* Returns next non-zero index on success or 0 on failure (i.e. out of room). */
static inline u16
add_physinfo_entries(u64 inp_pfn, u16 inp_off, u32 inp_len, u16 index,
u16 max_pi_arr_entries, struct phys_info pi_arr[])
{
u32 len;
u16 i, firstlen;
firstlen = PI_PAGE_SIZE - inp_off;
if (inp_len <= firstlen) {
/* The input entry spans only one page - add as is. */
if (index >= max_pi_arr_entries)
return 0;
pi_arr[index].pi_pfn = inp_pfn;
pi_arr[index].pi_off = (u16)inp_off;
pi_arr[index].pi_len = (u16)inp_len;
return index + 1;
}
/* This entry spans multiple pages. */
for (len = inp_len, i = 0; len;
len -= pi_arr[index + i].pi_len, i++) {
if (index + i >= max_pi_arr_entries)
return 0;
pi_arr[index + i].pi_pfn = inp_pfn + i;
if (i == 0) {
pi_arr[index].pi_off = inp_off;
pi_arr[index].pi_len = firstlen;
} else {
pi_arr[index + i].pi_off = 0;
pi_arr[index + i].pi_len =
(u16)MINNUM(len, (u32)PI_PAGE_SIZE);
}
}
return index + i;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Ken Cox | 202 | 93.09% | 1 | 16.67% |
Benjamin Romer | 12 | 5.53% | 3 | 50.00% |
Erik Arfvidson | 2 | 0.92% | 1 | 16.67% |
David Kershner | 1 | 0.46% | 1 | 16.67% |
Total | 217 | 100.00% | 6 | 100.00% |
#endif /* __IOCHANNEL_H__ */
Overall Contributors
Person | Tokens | Prop | Commits | CommitProp |
Ken Cox | 898 | 75.15% | 2 | 6.90% |
Benjamin Romer | 110 | 9.21% | 17 | 58.62% |
Erik Arfvidson | 99 | 8.28% | 3 | 10.34% |
David Kershner | 83 | 6.95% | 5 | 17.24% |
Jarod Wilson | 4 | 0.33% | 1 | 3.45% |
Yeliz Taneroglu | 1 | 0.08% | 1 | 3.45% |
Total | 1195 | 100.00% | 29 | 100.00% |
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.