add idl4k kernel firmware version 1.13.0.105

This commit is contained in:
Jaroslav Kysela
2015-03-26 17:22:37 +01:00
parent 5194d2792e
commit e9070cdc77
31064 changed files with 12769984 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
obj-$(CONFIG_SCSI_IBMVSCSI) += ibmvscsic.o
ibmvscsic-y += ibmvscsi.o
ibmvscsic-$(CONFIG_PPC_ISERIES) += iseries_vscsi.o
ibmvscsic-$(CONFIG_PPC_PSERIES) += rpa_vscsi.o
obj-$(CONFIG_SCSI_IBMVSCSIS) += ibmvstgt.o
obj-$(CONFIG_SCSI_IBMVFC) += ibmvfc.o

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,758 @@
/*
* ibmvfc.h -- driver for IBM Power Virtual Fibre Channel Adapter
*
* Written By: Brian King <brking@linux.vnet.ibm.com>, IBM Corporation
*
* Copyright (C) IBM Corporation, 2008
*
* 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. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef _IBMVFC_H
#define _IBMVFC_H
#include <linux/list.h>
#include <linux/types.h>
#include "viosrp.h"
#define IBMVFC_NAME "ibmvfc"
#define IBMVFC_DRIVER_VERSION "1.0.6"
#define IBMVFC_DRIVER_DATE "(May 28, 2009)"
#define IBMVFC_DEFAULT_TIMEOUT 60
#define IBMVFC_ADISC_CANCEL_TIMEOUT 45
#define IBMVFC_ADISC_TIMEOUT 15
#define IBMVFC_ADISC_PLUS_CANCEL_TIMEOUT \
(IBMVFC_ADISC_TIMEOUT + IBMVFC_ADISC_CANCEL_TIMEOUT)
#define IBMVFC_INIT_TIMEOUT 120
#define IBMVFC_ABORT_WAIT_TIMEOUT 40
#define IBMVFC_MAX_REQUESTS_DEFAULT 100
#define IBMVFC_DEBUG 0
#define IBMVFC_MAX_TARGETS 1024
#define IBMVFC_MAX_LUN 0xffffffff
#define IBMVFC_MAX_SECTORS 0xffffu
#define IBMVFC_MAX_DISC_THREADS 4
#define IBMVFC_TGT_MEMPOOL_SZ 64
#define IBMVFC_MAX_CMDS_PER_LUN 64
#define IBMVFC_MAX_HOST_INIT_RETRIES 6
#define IBMVFC_MAX_TGT_INIT_RETRIES 3
#define IBMVFC_DEV_LOSS_TMO (5 * 60)
#define IBMVFC_DEFAULT_LOG_LEVEL 2
#define IBMVFC_MAX_CDB_LEN 16
/*
* Ensure we have resources for ERP and initialization:
* 1 for ERP
* 1 for initialization
* 1 for NPIV Logout
* 2 for each discovery thread
*/
#define IBMVFC_NUM_INTERNAL_REQ (1 + 1 + 1 + (disc_threads * 2))
#define IBMVFC_MAD_SUCCESS 0x00
#define IBMVFC_MAD_NOT_SUPPORTED 0xF1
#define IBMVFC_MAD_FAILED 0xF7
#define IBMVFC_MAD_DRIVER_FAILED 0xEE
#define IBMVFC_MAD_CRQ_ERROR 0xEF
enum ibmvfc_crq_valid {
IBMVFC_CRQ_CMD_RSP = 0x80,
IBMVFC_CRQ_INIT_RSP = 0xC0,
IBMVFC_CRQ_XPORT_EVENT = 0xFF,
};
enum ibmvfc_crq_format {
IBMVFC_CRQ_INIT = 0x01,
IBMVFC_CRQ_INIT_COMPLETE = 0x02,
IBMVFC_PARTITION_MIGRATED = 0x06,
};
enum ibmvfc_cmd_status_flags {
IBMVFC_FABRIC_MAPPED = 0x0001,
IBMVFC_VIOS_FAILURE = 0x0002,
IBMVFC_FC_FAILURE = 0x0004,
IBMVFC_FC_SCSI_ERROR = 0x0008,
IBMVFC_HW_EVENT_LOGGED = 0x0010,
IBMVFC_VIOS_LOGGED = 0x0020,
};
enum ibmvfc_fabric_mapped_errors {
IBMVFC_UNABLE_TO_ESTABLISH = 0x0001,
IBMVFC_XPORT_FAULT = 0x0002,
IBMVFC_CMD_TIMEOUT = 0x0003,
IBMVFC_ENETDOWN = 0x0004,
IBMVFC_HW_FAILURE = 0x0005,
IBMVFC_LINK_DOWN_ERR = 0x0006,
IBMVFC_LINK_DEAD_ERR = 0x0007,
IBMVFC_UNABLE_TO_REGISTER = 0x0008,
IBMVFC_XPORT_BUSY = 0x000A,
IBMVFC_XPORT_DEAD = 0x000B,
IBMVFC_CONFIG_ERROR = 0x000C,
IBMVFC_NAME_SERVER_FAIL = 0x000D,
IBMVFC_LINK_HALTED = 0x000E,
IBMVFC_XPORT_GENERAL = 0x8000,
};
enum ibmvfc_vios_errors {
IBMVFC_CRQ_FAILURE = 0x0001,
IBMVFC_SW_FAILURE = 0x0002,
IBMVFC_INVALID_PARAMETER = 0x0003,
IBMVFC_MISSING_PARAMETER = 0x0004,
IBMVFC_HOST_IO_BUS = 0x0005,
IBMVFC_TRANS_CANCELLED = 0x0006,
IBMVFC_TRANS_CANCELLED_IMPLICIT = 0x0007,
IBMVFC_INSUFFICIENT_RESOURCE = 0x0008,
IBMVFC_PLOGI_REQUIRED = 0x0010,
IBMVFC_COMMAND_FAILED = 0x8000,
};
enum ibmvfc_mad_types {
IBMVFC_NPIV_LOGIN = 0x0001,
IBMVFC_DISC_TARGETS = 0x0002,
IBMVFC_PORT_LOGIN = 0x0004,
IBMVFC_PROCESS_LOGIN = 0x0008,
IBMVFC_QUERY_TARGET = 0x0010,
IBMVFC_IMPLICIT_LOGOUT = 0x0040,
IBMVFC_PASSTHRU = 0x0200,
IBMVFC_TMF_MAD = 0x0100,
IBMVFC_NPIV_LOGOUT = 0x0800,
};
struct ibmvfc_mad_common {
u32 version;
u32 reserved;
u32 opcode;
u16 status;
u16 length;
u64 tag;
}__attribute__((packed, aligned (8)));
struct ibmvfc_npiv_login_mad {
struct ibmvfc_mad_common common;
struct srp_direct_buf buffer;
}__attribute__((packed, aligned (8)));
struct ibmvfc_npiv_logout_mad {
struct ibmvfc_mad_common common;
}__attribute__((packed, aligned (8)));
#define IBMVFC_MAX_NAME 256
struct ibmvfc_npiv_login {
u32 ostype;
#define IBMVFC_OS_LINUX 0x02
u32 pad;
u64 max_dma_len;
u32 max_payload;
u32 max_response;
u32 partition_num;
u32 vfc_frame_version;
u16 fcp_version;
u16 flags;
#define IBMVFC_CLIENT_MIGRATED 0x01
#define IBMVFC_FLUSH_ON_HALT 0x02
u32 max_cmds;
u64 capabilities;
#define IBMVFC_CAN_MIGRATE 0x01
u64 node_name;
struct srp_direct_buf async;
u8 partition_name[IBMVFC_MAX_NAME];
u8 device_name[IBMVFC_MAX_NAME];
u8 drc_name[IBMVFC_MAX_NAME];
u64 reserved2[2];
}__attribute__((packed, aligned (8)));
struct ibmvfc_common_svc_parms {
u16 fcph_version;
u16 b2b_credit;
u16 features;
u16 bb_rcv_sz; /* upper nibble is BB_SC_N */
u32 ratov;
u32 edtov;
}__attribute__((packed, aligned (4)));
struct ibmvfc_service_parms {
struct ibmvfc_common_svc_parms common;
u8 port_name[8];
u8 node_name[8];
u32 class1_parms[4];
u32 class2_parms[4];
u32 class3_parms[4];
u32 obsolete[4];
u32 vendor_version[4];
u32 services_avail[2];
u32 ext_len;
u32 reserved[30];
u32 clk_sync_qos[2];
}__attribute__((packed, aligned (4)));
struct ibmvfc_npiv_login_resp {
u32 version;
u16 status;
u16 error;
u32 flags;
#define IBMVFC_NATIVE_FC 0x01
#define IBMVFC_CAN_FLUSH_ON_HALT 0x08
u32 reserved;
u64 capabilities;
#define IBMVFC_CAN_FLUSH_ON_HALT 0x08
u32 max_cmds;
u32 scsi_id_sz;
u64 max_dma_len;
u64 scsi_id;
u64 port_name;
u64 node_name;
u64 link_speed;
u8 partition_name[IBMVFC_MAX_NAME];
u8 device_name[IBMVFC_MAX_NAME];
u8 port_loc_code[IBMVFC_MAX_NAME];
u8 drc_name[IBMVFC_MAX_NAME];
struct ibmvfc_service_parms service_parms;
u64 reserved2;
}__attribute__((packed, aligned (8)));
union ibmvfc_npiv_login_data {
struct ibmvfc_npiv_login login;
struct ibmvfc_npiv_login_resp resp;
}__attribute__((packed, aligned (8)));
struct ibmvfc_discover_targets_buf {
u32 scsi_id[1];
#define IBMVFC_DISC_TGT_SCSI_ID_MASK 0x00ffffff
};
struct ibmvfc_discover_targets {
struct ibmvfc_mad_common common;
struct srp_direct_buf buffer;
u32 flags;
u16 status;
u16 error;
u32 bufflen;
u32 num_avail;
u32 num_written;
u64 reserved[2];
}__attribute__((packed, aligned (8)));
enum ibmvfc_fc_reason {
IBMVFC_INVALID_ELS_CMD_CODE = 0x01,
IBMVFC_INVALID_VERSION = 0x02,
IBMVFC_LOGICAL_ERROR = 0x03,
IBMVFC_INVALID_CT_IU_SIZE = 0x04,
IBMVFC_LOGICAL_BUSY = 0x05,
IBMVFC_PROTOCOL_ERROR = 0x07,
IBMVFC_UNABLE_TO_PERFORM_REQ = 0x09,
IBMVFC_CMD_NOT_SUPPORTED = 0x0B,
IBMVFC_SERVER_NOT_AVAIL = 0x0D,
IBMVFC_CMD_IN_PROGRESS = 0x0E,
IBMVFC_VENDOR_SPECIFIC = 0xFF,
};
enum ibmvfc_fc_type {
IBMVFC_FABRIC_REJECT = 0x01,
IBMVFC_PORT_REJECT = 0x02,
IBMVFC_LS_REJECT = 0x03,
IBMVFC_FABRIC_BUSY = 0x04,
IBMVFC_PORT_BUSY = 0x05,
IBMVFC_BASIC_REJECT = 0x06,
};
enum ibmvfc_gs_explain {
IBMVFC_PORT_NAME_NOT_REG = 0x02,
};
struct ibmvfc_port_login {
struct ibmvfc_mad_common common;
u64 scsi_id;
u16 reserved;
u16 fc_service_class;
u32 blksz;
u32 hdr_per_blk;
u16 status;
u16 error; /* also fc_reason */
u16 fc_explain;
u16 fc_type;
u32 reserved2;
struct ibmvfc_service_parms service_parms;
struct ibmvfc_service_parms service_parms_change;
u64 reserved3[2];
}__attribute__((packed, aligned (8)));
struct ibmvfc_prli_svc_parms {
u8 type;
#define IBMVFC_SCSI_FCP_TYPE 0x08
u8 type_ext;
u16 flags;
#define IBMVFC_PRLI_ORIG_PA_VALID 0x8000
#define IBMVFC_PRLI_RESP_PA_VALID 0x4000
#define IBMVFC_PRLI_EST_IMG_PAIR 0x2000
u32 orig_pa;
u32 resp_pa;
u32 service_parms;
#define IBMVFC_PRLI_TASK_RETRY 0x00000200
#define IBMVFC_PRLI_RETRY 0x00000100
#define IBMVFC_PRLI_DATA_OVERLAY 0x00000040
#define IBMVFC_PRLI_INITIATOR_FUNC 0x00000020
#define IBMVFC_PRLI_TARGET_FUNC 0x00000010
#define IBMVFC_PRLI_READ_FCP_XFER_RDY_DISABLED 0x00000002
#define IBMVFC_PRLI_WR_FCP_XFER_RDY_DISABLED 0x00000001
}__attribute__((packed, aligned (4)));
struct ibmvfc_process_login {
struct ibmvfc_mad_common common;
u64 scsi_id;
struct ibmvfc_prli_svc_parms parms;
u8 reserved[48];
u16 status;
u16 error; /* also fc_reason */
u32 reserved2;
u64 reserved3[2];
}__attribute__((packed, aligned (8)));
struct ibmvfc_query_tgt {
struct ibmvfc_mad_common common;
u64 wwpn;
u64 scsi_id;
u16 status;
u16 error;
u16 fc_explain;
u16 fc_type;
u64 reserved[2];
}__attribute__((packed, aligned (8)));
struct ibmvfc_implicit_logout {
struct ibmvfc_mad_common common;
u64 old_scsi_id;
u64 reserved[2];
}__attribute__((packed, aligned (8)));
struct ibmvfc_tmf {
struct ibmvfc_mad_common common;
u64 scsi_id;
struct scsi_lun lun;
u32 flags;
#define IBMVFC_TMF_ABORT_TASK 0x02
#define IBMVFC_TMF_ABORT_TASK_SET 0x04
#define IBMVFC_TMF_LUN_RESET 0x10
#define IBMVFC_TMF_TGT_RESET 0x20
#define IBMVFC_TMF_LUA_VALID 0x40
u32 cancel_key;
u32 my_cancel_key;
u32 pad;
u64 reserved[2];
}__attribute__((packed, aligned (8)));
enum ibmvfc_fcp_rsp_info_codes {
RSP_NO_FAILURE = 0x00,
RSP_TMF_REJECTED = 0x04,
RSP_TMF_FAILED = 0x05,
RSP_TMF_INVALID_LUN = 0x09,
};
struct ibmvfc_fcp_rsp_info {
u16 reserved;
u8 rsp_code;
u8 reserved2[4];
}__attribute__((packed, aligned (2)));
enum ibmvfc_fcp_rsp_flags {
FCP_BIDI_RSP = 0x80,
FCP_BIDI_READ_RESID_UNDER = 0x40,
FCP_BIDI_READ_RESID_OVER = 0x20,
FCP_CONF_REQ = 0x10,
FCP_RESID_UNDER = 0x08,
FCP_RESID_OVER = 0x04,
FCP_SNS_LEN_VALID = 0x02,
FCP_RSP_LEN_VALID = 0x01,
};
union ibmvfc_fcp_rsp_data {
struct ibmvfc_fcp_rsp_info info;
u8 sense[SCSI_SENSE_BUFFERSIZE + sizeof(struct ibmvfc_fcp_rsp_info)];
}__attribute__((packed, aligned (8)));
struct ibmvfc_fcp_rsp {
u64 reserved;
u16 retry_delay_timer;
u8 flags;
u8 scsi_status;
u32 fcp_resid;
u32 fcp_sense_len;
u32 fcp_rsp_len;
union ibmvfc_fcp_rsp_data data;
}__attribute__((packed, aligned (8)));
enum ibmvfc_cmd_flags {
IBMVFC_SCATTERLIST = 0x0001,
IBMVFC_NO_MEM_DESC = 0x0002,
IBMVFC_READ = 0x0004,
IBMVFC_WRITE = 0x0008,
IBMVFC_TMF = 0x0080,
IBMVFC_CLASS_3_ERR = 0x0100,
};
enum ibmvfc_fc_task_attr {
IBMVFC_SIMPLE_TASK = 0x00,
IBMVFC_HEAD_OF_QUEUE = 0x01,
IBMVFC_ORDERED_TASK = 0x02,
IBMVFC_ACA_TASK = 0x04,
};
enum ibmvfc_fc_tmf_flags {
IBMVFC_ABORT_TASK_SET = 0x02,
IBMVFC_LUN_RESET = 0x10,
IBMVFC_TARGET_RESET = 0x20,
};
struct ibmvfc_fcp_cmd_iu {
struct scsi_lun lun;
u8 crn;
u8 pri_task_attr;
u8 tmf_flags;
u8 add_cdb_len;
#define IBMVFC_RDDATA 0x02
#define IBMVFC_WRDATA 0x01
u8 cdb[IBMVFC_MAX_CDB_LEN];
u32 xfer_len;
}__attribute__((packed, aligned (4)));
struct ibmvfc_cmd {
u64 task_tag;
u32 frame_type;
u32 payload_len;
u32 resp_len;
u32 adapter_resid;
u16 status;
u16 error;
u16 flags;
u16 response_flags;
#define IBMVFC_ADAPTER_RESID_VALID 0x01
u32 cancel_key;
u32 exchange_id;
struct srp_direct_buf ext_func;
struct srp_direct_buf ioba;
struct srp_direct_buf resp;
u64 correlation;
u64 tgt_scsi_id;
u64 tag;
u64 reserved3[2];
struct ibmvfc_fcp_cmd_iu iu;
struct ibmvfc_fcp_rsp rsp;
}__attribute__((packed, aligned (8)));
struct ibmvfc_passthru_fc_iu {
u32 payload[7];
#define IBMVFC_ADISC 0x52000000
u32 response[7];
};
struct ibmvfc_passthru_iu {
u64 task_tag;
u32 cmd_len;
u32 rsp_len;
u16 status;
u16 error;
u32 flags;
#define IBMVFC_FC_ELS 0x01
u32 cancel_key;
u32 reserved;
struct srp_direct_buf cmd;
struct srp_direct_buf rsp;
u64 correlation;
u64 scsi_id;
u64 tag;
u64 reserved2[2];
}__attribute__((packed, aligned (8)));
struct ibmvfc_passthru_mad {
struct ibmvfc_mad_common common;
struct srp_direct_buf cmd_ioba;
struct ibmvfc_passthru_iu iu;
struct ibmvfc_passthru_fc_iu fc_iu;
}__attribute__((packed, aligned (8)));
struct ibmvfc_trace_start_entry {
u32 xfer_len;
}__attribute__((packed));
struct ibmvfc_trace_end_entry {
u16 status;
u16 error;
u8 fcp_rsp_flags;
u8 rsp_code;
u8 scsi_status;
u8 reserved;
}__attribute__((packed));
struct ibmvfc_trace_entry {
struct ibmvfc_event *evt;
u32 time;
u32 scsi_id;
u32 lun;
u8 fmt;
u8 op_code;
u8 tmf_flags;
u8 type;
#define IBMVFC_TRC_START 0x00
#define IBMVFC_TRC_END 0xff
union {
struct ibmvfc_trace_start_entry start;
struct ibmvfc_trace_end_entry end;
} u;
}__attribute__((packed, aligned (8)));
enum ibmvfc_crq_formats {
IBMVFC_CMD_FORMAT = 0x01,
IBMVFC_ASYNC_EVENT = 0x02,
IBMVFC_MAD_FORMAT = 0x04,
};
enum ibmvfc_async_event {
IBMVFC_AE_ELS_PLOGI = 0x0001,
IBMVFC_AE_ELS_LOGO = 0x0002,
IBMVFC_AE_ELS_PRLO = 0x0004,
IBMVFC_AE_SCN_NPORT = 0x0008,
IBMVFC_AE_SCN_GROUP = 0x0010,
IBMVFC_AE_SCN_DOMAIN = 0x0020,
IBMVFC_AE_SCN_FABRIC = 0x0040,
IBMVFC_AE_LINK_UP = 0x0080,
IBMVFC_AE_LINK_DOWN = 0x0100,
IBMVFC_AE_LINK_DEAD = 0x0200,
IBMVFC_AE_HALT = 0x0400,
IBMVFC_AE_RESUME = 0x0800,
IBMVFC_AE_ADAPTER_FAILED = 0x1000,
};
struct ibmvfc_crq {
volatile u8 valid;
volatile u8 format;
u8 reserved[6];
volatile u64 ioba;
}__attribute__((packed, aligned (8)));
struct ibmvfc_crq_queue {
struct ibmvfc_crq *msgs;
int size, cur;
dma_addr_t msg_token;
};
enum ibmvfc_ae_link_state {
IBMVFC_AE_LS_LINK_UP = 0x01,
IBMVFC_AE_LS_LINK_BOUNCED = 0x02,
IBMVFC_AE_LS_LINK_DOWN = 0x04,
IBMVFC_AE_LS_LINK_DEAD = 0x08,
};
struct ibmvfc_async_crq {
volatile u8 valid;
u8 link_state;
u8 pad[2];
u32 pad2;
volatile u64 event;
volatile u64 scsi_id;
volatile u64 wwpn;
volatile u64 node_name;
u64 reserved;
}__attribute__((packed, aligned (8)));
struct ibmvfc_async_crq_queue {
struct ibmvfc_async_crq *msgs;
int size, cur;
dma_addr_t msg_token;
};
union ibmvfc_iu {
struct ibmvfc_mad_common mad_common;
struct ibmvfc_npiv_login_mad npiv_login;
struct ibmvfc_npiv_logout_mad npiv_logout;
struct ibmvfc_discover_targets discover_targets;
struct ibmvfc_port_login plogi;
struct ibmvfc_process_login prli;
struct ibmvfc_query_tgt query_tgt;
struct ibmvfc_implicit_logout implicit_logout;
struct ibmvfc_tmf tmf;
struct ibmvfc_cmd cmd;
struct ibmvfc_passthru_mad passthru;
}__attribute__((packed, aligned (8)));
enum ibmvfc_target_action {
IBMVFC_TGT_ACTION_NONE = 0,
IBMVFC_TGT_ACTION_INIT,
IBMVFC_TGT_ACTION_INIT_WAIT,
IBMVFC_TGT_ACTION_DEL_RPORT,
};
struct ibmvfc_target {
struct list_head queue;
struct ibmvfc_host *vhost;
u64 scsi_id;
u64 new_scsi_id;
struct fc_rport *rport;
int target_id;
enum ibmvfc_target_action action;
int need_login;
int add_rport;
int init_retries;
int logo_rcvd;
u32 cancel_key;
struct ibmvfc_service_parms service_parms;
struct ibmvfc_service_parms service_parms_change;
struct fc_rport_identifiers ids;
void (*job_step) (struct ibmvfc_target *);
struct timer_list timer;
struct kref kref;
};
/* a unit of work for the hosting partition */
struct ibmvfc_event {
struct list_head queue;
struct ibmvfc_host *vhost;
struct ibmvfc_target *tgt;
struct scsi_cmnd *cmnd;
atomic_t free;
union ibmvfc_iu *xfer_iu;
void (*done) (struct ibmvfc_event *);
struct ibmvfc_crq crq;
union ibmvfc_iu iu;
union ibmvfc_iu *sync_iu;
struct srp_direct_buf *ext_list;
dma_addr_t ext_list_token;
struct completion comp;
struct completion *eh_comp;
struct timer_list timer;
};
/* a pool of event structs for use */
struct ibmvfc_event_pool {
struct ibmvfc_event *events;
u32 size;
union ibmvfc_iu *iu_storage;
dma_addr_t iu_token;
};
enum ibmvfc_host_action {
IBMVFC_HOST_ACTION_NONE = 0,
IBMVFC_HOST_ACTION_LOGO,
IBMVFC_HOST_ACTION_LOGO_WAIT,
IBMVFC_HOST_ACTION_INIT,
IBMVFC_HOST_ACTION_INIT_WAIT,
IBMVFC_HOST_ACTION_QUERY,
IBMVFC_HOST_ACTION_QUERY_TGTS,
IBMVFC_HOST_ACTION_TGT_DEL,
IBMVFC_HOST_ACTION_ALLOC_TGTS,
IBMVFC_HOST_ACTION_TGT_INIT,
IBMVFC_HOST_ACTION_TGT_DEL_FAILED,
};
enum ibmvfc_host_state {
IBMVFC_NO_CRQ = 0,
IBMVFC_INITIALIZING,
IBMVFC_ACTIVE,
IBMVFC_HALTED,
IBMVFC_LINK_DOWN,
IBMVFC_LINK_DEAD,
IBMVFC_HOST_OFFLINE,
};
struct ibmvfc_host {
char name[8];
struct list_head queue;
struct Scsi_Host *host;
enum ibmvfc_host_state state;
enum ibmvfc_host_action action;
#define IBMVFC_NUM_TRACE_INDEX_BITS 8
#define IBMVFC_NUM_TRACE_ENTRIES (1 << IBMVFC_NUM_TRACE_INDEX_BITS)
#define IBMVFC_TRACE_SIZE (sizeof(struct ibmvfc_trace_entry) * IBMVFC_NUM_TRACE_ENTRIES)
struct ibmvfc_trace_entry *trace;
u32 trace_index:IBMVFC_NUM_TRACE_INDEX_BITS;
int num_targets;
struct list_head targets;
struct list_head sent;
struct list_head free;
struct device *dev;
struct ibmvfc_event_pool pool;
struct dma_pool *sg_pool;
mempool_t *tgt_pool;
struct ibmvfc_crq_queue crq;
struct ibmvfc_async_crq_queue async_crq;
struct ibmvfc_npiv_login login_info;
union ibmvfc_npiv_login_data *login_buf;
dma_addr_t login_buf_dma;
int disc_buf_sz;
int log_level;
struct ibmvfc_discover_targets_buf *disc_buf;
int task_set;
int init_retries;
int discovery_threads;
int abort_threads;
int client_migrated;
int reinit;
int delay_init;
int scan_complete;
int logged_in;
int events_to_log;
#define IBMVFC_AE_LINKUP 0x0001
#define IBMVFC_AE_LINKDOWN 0x0002
#define IBMVFC_AE_RSCN 0x0004
dma_addr_t disc_buf_dma;
unsigned int partition_number;
char partition_name[97];
void (*job_step) (struct ibmvfc_host *);
struct task_struct *work_thread;
struct tasklet_struct tasklet;
struct work_struct rport_add_work_q;
wait_queue_head_t init_wait_q;
wait_queue_head_t work_wait_q;
};
#define DBG_CMD(CMD) do { if (ibmvfc_debug) CMD; } while (0)
#define tgt_dbg(t, fmt, ...) \
DBG_CMD(dev_info((t)->vhost->dev, "%llX: " fmt, (t)->scsi_id, ##__VA_ARGS__))
#define tgt_info(t, fmt, ...) \
dev_info((t)->vhost->dev, "%llX: " fmt, (t)->scsi_id, ##__VA_ARGS__)
#define tgt_err(t, fmt, ...) \
dev_err((t)->vhost->dev, "%llX: " fmt, (t)->scsi_id, ##__VA_ARGS__)
#define tgt_log(t, level, fmt, ...) \
do { \
if ((t)->vhost->log_level >= level) \
tgt_err(t, fmt, ##__VA_ARGS__); \
} while (0)
#define ibmvfc_dbg(vhost, ...) \
DBG_CMD(dev_info((vhost)->dev, ##__VA_ARGS__))
#define ibmvfc_log(vhost, level, ...) \
do { \
if ((vhost)->log_level >= level) \
dev_err((vhost)->dev, ##__VA_ARGS__); \
} while (0)
#define ENTER DBG_CMD(printk(KERN_INFO IBMVFC_NAME": Entering %s\n", __func__))
#define LEAVE DBG_CMD(printk(KERN_INFO IBMVFC_NAME": Leaving %s\n", __func__))
#ifdef CONFIG_SCSI_IBMVFC_TRACE
#define ibmvfc_create_trace_file(kobj, attr) sysfs_create_bin_file(kobj, attr)
#define ibmvfc_remove_trace_file(kobj, attr) sysfs_remove_bin_file(kobj, attr)
#else
#define ibmvfc_create_trace_file(kobj, attr) 0
#define ibmvfc_remove_trace_file(kobj, attr) do { } while (0)
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,128 @@
/* ------------------------------------------------------------
* ibmvscsi.h
* (C) Copyright IBM Corporation 1994, 2003
* Authors: Colin DeVilbiss (devilbis@us.ibm.com)
* Santiago Leon (santil@us.ibm.com)
* Dave Boutcher (sleddog@us.ibm.com)
*
* 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. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
* ------------------------------------------------------------
* Emulation of a SCSI host adapter for Virtual I/O devices
*
* This driver allows the Linux SCSI peripheral drivers to directly
* access devices in the hosting partition, either on an iSeries
* hypervisor system or a converged hypervisor system.
*/
#ifndef IBMVSCSI_H
#define IBMVSCSI_H
#include <linux/types.h>
#include <linux/list.h>
#include <linux/completion.h>
#include <linux/interrupt.h>
#include "viosrp.h"
struct scsi_cmnd;
struct Scsi_Host;
/* Number of indirect bufs...the list of these has to fit in the
* additional data of the srp_cmd struct along with the indirect
* descriptor
*/
#define MAX_INDIRECT_BUFS 10
#define IBMVSCSI_MAX_REQUESTS_DEFAULT 100
#define IBMVSCSI_CMDS_PER_LUN_DEFAULT 16
#define IBMVSCSI_MAX_SECTORS_DEFAULT 256 /* 32 * 8 = default max I/O 32 pages */
#define IBMVSCSI_MAX_CMDS_PER_LUN 64
/* ------------------------------------------------------------
* Data Structures
*/
/* an RPA command/response transport queue */
struct crq_queue {
struct viosrp_crq *msgs;
int size, cur;
dma_addr_t msg_token;
spinlock_t lock;
};
/* a unit of work for the hosting partition */
struct srp_event_struct {
union viosrp_iu *xfer_iu;
struct scsi_cmnd *cmnd;
struct list_head list;
void (*done) (struct srp_event_struct *);
struct viosrp_crq crq;
struct ibmvscsi_host_data *hostdata;
atomic_t free;
union viosrp_iu iu;
void (*cmnd_done) (struct scsi_cmnd *);
struct completion comp;
struct timer_list timer;
union viosrp_iu *sync_srp;
struct srp_direct_buf *ext_list;
dma_addr_t ext_list_token;
};
/* a pool of event structs for use */
struct event_pool {
struct srp_event_struct *events;
u32 size;
int next;
union viosrp_iu *iu_storage;
dma_addr_t iu_token;
};
/* all driver data associated with a host adapter */
struct ibmvscsi_host_data {
atomic_t request_limit;
int client_migrated;
struct device *dev;
struct event_pool pool;
struct crq_queue queue;
struct tasklet_struct srp_task;
struct list_head sent;
struct Scsi_Host *host;
struct mad_adapter_info_data madapter_info;
struct capabilities caps;
dma_addr_t caps_addr;
dma_addr_t adapter_info_addr;
};
/* routines for managing a command/response queue */
void ibmvscsi_handle_crq(struct viosrp_crq *crq,
struct ibmvscsi_host_data *hostdata);
struct ibmvscsi_ops {
int (*init_crq_queue)(struct crq_queue *queue,
struct ibmvscsi_host_data *hostdata,
int max_requests);
void (*release_crq_queue)(struct crq_queue *queue,
struct ibmvscsi_host_data *hostdata,
int max_requests);
int (*reset_crq_queue)(struct crq_queue *queue,
struct ibmvscsi_host_data *hostdata);
int (*reenable_crq_queue)(struct crq_queue *queue,
struct ibmvscsi_host_data *hostdata);
int (*send_crq)(struct ibmvscsi_host_data *hostdata,
u64 word1, u64 word2);
};
extern struct ibmvscsi_ops iseriesvscsi_ops;
extern struct ibmvscsi_ops rpavscsi_ops;
#endif /* IBMVSCSI_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,167 @@
/* ------------------------------------------------------------
* iSeries_vscsi.c
* (C) Copyright IBM Corporation 1994, 2003
* Authors: Colin DeVilbiss (devilbis@us.ibm.com)
* Santiago Leon (santil@us.ibm.com)
* Dave Boutcher (sleddog@us.ibm.com)
*
* 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. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
* ------------------------------------------------------------
* iSeries-specific functions of the SCSI host adapter for Virtual I/O devices
*
* This driver allows the Linux SCSI peripheral drivers to directly
* access devices in the hosting partition, either on an iSeries
* hypervisor system or a converged hypervisor system.
*/
#include <asm/iseries/vio.h>
#include <asm/iseries/hv_lp_event.h>
#include <asm/iseries/hv_types.h>
#include <asm/iseries/hv_lp_config.h>
#include <asm/vio.h>
#include <linux/device.h>
#include "ibmvscsi.h"
/* global variables */
static struct ibmvscsi_host_data *single_host_data;
/* ------------------------------------------------------------
* Routines for direct interpartition interaction
*/
struct srp_lp_event {
struct HvLpEvent lpevt; /* 0x00-0x17 */
u32 reserved1; /* 0x18-0x1B; unused */
u16 version; /* 0x1C-0x1D; unused */
u16 subtype_rc; /* 0x1E-0x1F; unused */
struct viosrp_crq crq; /* 0x20-0x3F */
};
/**
* standard interface for handling logical partition events.
*/
static void iseriesvscsi_handle_event(struct HvLpEvent *lpevt)
{
struct srp_lp_event *evt = (struct srp_lp_event *)lpevt;
if (!evt) {
printk(KERN_ERR "ibmvscsi: received null event\n");
return;
}
if (single_host_data == NULL) {
printk(KERN_ERR
"ibmvscsi: received event, no adapter present\n");
return;
}
ibmvscsi_handle_crq(&evt->crq, single_host_data);
}
/* ------------------------------------------------------------
* Routines for driver initialization
*/
static int iseriesvscsi_init_crq_queue(struct crq_queue *queue,
struct ibmvscsi_host_data *hostdata,
int max_requests)
{
int rc;
single_host_data = hostdata;
rc = viopath_open(viopath_hostLp, viomajorsubtype_scsi, max_requests);
if (rc < 0) {
printk("viopath_open failed with rc %d in open_event_path\n",
rc);
goto viopath_open_failed;
}
rc = vio_setHandler(viomajorsubtype_scsi, iseriesvscsi_handle_event);
if (rc < 0) {
printk("vio_setHandler failed with rc %d in open_event_path\n",
rc);
goto vio_setHandler_failed;
}
return 0;
vio_setHandler_failed:
viopath_close(viopath_hostLp, viomajorsubtype_scsi, max_requests);
viopath_open_failed:
return -1;
}
static void iseriesvscsi_release_crq_queue(struct crq_queue *queue,
struct ibmvscsi_host_data *hostdata,
int max_requests)
{
vio_clearHandler(viomajorsubtype_scsi);
viopath_close(viopath_hostLp, viomajorsubtype_scsi, max_requests);
}
/**
* reset_crq_queue: - resets a crq after a failure
* @queue: crq_queue to initialize and register
* @hostdata: ibmvscsi_host_data of host
*
* no-op for iSeries
*/
static int iseriesvscsi_reset_crq_queue(struct crq_queue *queue,
struct ibmvscsi_host_data *hostdata)
{
return 0;
}
/**
* reenable_crq_queue: - reenables a crq after a failure
* @queue: crq_queue to initialize and register
* @hostdata: ibmvscsi_host_data of host
*
* no-op for iSeries
*/
static int iseriesvscsi_reenable_crq_queue(struct crq_queue *queue,
struct ibmvscsi_host_data *hostdata)
{
return 0;
}
/**
* iseriesvscsi_send_crq: - Send a CRQ
* @hostdata: the adapter
* @word1: the first 64 bits of the data
* @word2: the second 64 bits of the data
*/
static int iseriesvscsi_send_crq(struct ibmvscsi_host_data *hostdata,
u64 word1, u64 word2)
{
single_host_data = hostdata;
return HvCallEvent_signalLpEventFast(viopath_hostLp,
HvLpEvent_Type_VirtualIo,
viomajorsubtype_scsi,
HvLpEvent_AckInd_NoAck,
HvLpEvent_AckType_ImmediateAck,
viopath_sourceinst(viopath_hostLp),
viopath_targetinst(viopath_hostLp),
0,
VIOVERSION << 16, word1, word2, 0,
0);
}
struct ibmvscsi_ops iseriesvscsi_ops = {
.init_crq_queue = iseriesvscsi_init_crq_queue,
.release_crq_queue = iseriesvscsi_release_crq_queue,
.reset_crq_queue = iseriesvscsi_reset_crq_queue,
.reenable_crq_queue = iseriesvscsi_reenable_crq_queue,
.send_crq = iseriesvscsi_send_crq,
};

View File

@@ -0,0 +1,343 @@
/* ------------------------------------------------------------
* rpa_vscsi.c
* (C) Copyright IBM Corporation 1994, 2003
* Authors: Colin DeVilbiss (devilbis@us.ibm.com)
* Santiago Leon (santil@us.ibm.com)
*
* 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. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
* ------------------------------------------------------------
* RPA-specific functions of the SCSI host adapter for Virtual I/O devices
*
* This driver allows the Linux SCSI peripheral drivers to directly
* access devices in the hosting partition, either on an iSeries
* hypervisor system or a converged hypervisor system.
*/
#include <asm/vio.h>
#include <asm/prom.h>
#include <asm/iommu.h>
#include <asm/hvcall.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include "ibmvscsi.h"
static char partition_name[97] = "UNKNOWN";
static unsigned int partition_number = -1;
/* ------------------------------------------------------------
* Routines for managing the command/response queue
*/
/**
* rpavscsi_handle_event: - Interrupt handler for crq events
* @irq: number of irq to handle, not used
* @dev_instance: ibmvscsi_host_data of host that received interrupt
*
* Disables interrupts and schedules srp_task
* Always returns IRQ_HANDLED
*/
static irqreturn_t rpavscsi_handle_event(int irq, void *dev_instance)
{
struct ibmvscsi_host_data *hostdata =
(struct ibmvscsi_host_data *)dev_instance;
vio_disable_interrupts(to_vio_dev(hostdata->dev));
tasklet_schedule(&hostdata->srp_task);
return IRQ_HANDLED;
}
/**
* release_crq_queue: - Deallocates data and unregisters CRQ
* @queue: crq_queue to initialize and register
* @host_data: ibmvscsi_host_data of host
*
* Frees irq, deallocates a page for messages, unmaps dma, and unregisters
* the crq with the hypervisor.
*/
static void rpavscsi_release_crq_queue(struct crq_queue *queue,
struct ibmvscsi_host_data *hostdata,
int max_requests)
{
long rc;
struct vio_dev *vdev = to_vio_dev(hostdata->dev);
free_irq(vdev->irq, (void *)hostdata);
tasklet_kill(&hostdata->srp_task);
do {
rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
} while ((rc == H_BUSY) || (H_IS_LONG_BUSY(rc)));
dma_unmap_single(hostdata->dev,
queue->msg_token,
queue->size * sizeof(*queue->msgs), DMA_BIDIRECTIONAL);
free_page((unsigned long)queue->msgs);
}
/**
* crq_queue_next_crq: - Returns the next entry in message queue
* @queue: crq_queue to use
*
* Returns pointer to next entry in queue, or NULL if there are no new
* entried in the CRQ.
*/
static struct viosrp_crq *crq_queue_next_crq(struct crq_queue *queue)
{
struct viosrp_crq *crq;
unsigned long flags;
spin_lock_irqsave(&queue->lock, flags);
crq = &queue->msgs[queue->cur];
if (crq->valid & 0x80) {
if (++queue->cur == queue->size)
queue->cur = 0;
} else
crq = NULL;
spin_unlock_irqrestore(&queue->lock, flags);
return crq;
}
/**
* rpavscsi_send_crq: - Send a CRQ
* @hostdata: the adapter
* @word1: the first 64 bits of the data
* @word2: the second 64 bits of the data
*/
static int rpavscsi_send_crq(struct ibmvscsi_host_data *hostdata,
u64 word1, u64 word2)
{
struct vio_dev *vdev = to_vio_dev(hostdata->dev);
return plpar_hcall_norets(H_SEND_CRQ, vdev->unit_address, word1, word2);
}
/**
* rpavscsi_task: - Process srps asynchronously
* @data: ibmvscsi_host_data of host
*/
static void rpavscsi_task(void *data)
{
struct ibmvscsi_host_data *hostdata = (struct ibmvscsi_host_data *)data;
struct vio_dev *vdev = to_vio_dev(hostdata->dev);
struct viosrp_crq *crq;
int done = 0;
while (!done) {
/* Pull all the valid messages off the CRQ */
while ((crq = crq_queue_next_crq(&hostdata->queue)) != NULL) {
ibmvscsi_handle_crq(crq, hostdata);
crq->valid = 0x00;
}
vio_enable_interrupts(vdev);
if ((crq = crq_queue_next_crq(&hostdata->queue)) != NULL) {
vio_disable_interrupts(vdev);
ibmvscsi_handle_crq(crq, hostdata);
crq->valid = 0x00;
} else {
done = 1;
}
}
}
static void gather_partition_info(void)
{
struct device_node *rootdn;
const char *ppartition_name;
const unsigned int *p_number_ptr;
/* Retrieve information about this partition */
rootdn = of_find_node_by_path("/");
if (!rootdn) {
return;
}
ppartition_name = of_get_property(rootdn, "ibm,partition-name", NULL);
if (ppartition_name)
strncpy(partition_name, ppartition_name,
sizeof(partition_name));
p_number_ptr = of_get_property(rootdn, "ibm,partition-no", NULL);
if (p_number_ptr)
partition_number = *p_number_ptr;
of_node_put(rootdn);
}
static void set_adapter_info(struct ibmvscsi_host_data *hostdata)
{
memset(&hostdata->madapter_info, 0x00,
sizeof(hostdata->madapter_info));
dev_info(hostdata->dev, "SRP_VERSION: %s\n", SRP_VERSION);
strcpy(hostdata->madapter_info.srp_version, SRP_VERSION);
strncpy(hostdata->madapter_info.partition_name, partition_name,
sizeof(hostdata->madapter_info.partition_name));
hostdata->madapter_info.partition_number = partition_number;
hostdata->madapter_info.mad_version = 1;
hostdata->madapter_info.os_type = 2;
}
/**
* reset_crq_queue: - resets a crq after a failure
* @queue: crq_queue to initialize and register
* @hostdata: ibmvscsi_host_data of host
*
*/
static int rpavscsi_reset_crq_queue(struct crq_queue *queue,
struct ibmvscsi_host_data *hostdata)
{
int rc;
struct vio_dev *vdev = to_vio_dev(hostdata->dev);
/* Close the CRQ */
do {
rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
} while ((rc == H_BUSY) || (H_IS_LONG_BUSY(rc)));
/* Clean out the queue */
memset(queue->msgs, 0x00, PAGE_SIZE);
queue->cur = 0;
set_adapter_info(hostdata);
/* And re-open it again */
rc = plpar_hcall_norets(H_REG_CRQ,
vdev->unit_address,
queue->msg_token, PAGE_SIZE);
if (rc == 2) {
/* Adapter is good, but other end is not ready */
dev_warn(hostdata->dev, "Partner adapter not ready\n");
} else if (rc != 0) {
dev_warn(hostdata->dev, "couldn't register crq--rc 0x%x\n", rc);
}
return rc;
}
/**
* initialize_crq_queue: - Initializes and registers CRQ with hypervisor
* @queue: crq_queue to initialize and register
* @hostdata: ibmvscsi_host_data of host
*
* Allocates a page for messages, maps it for dma, and registers
* the crq with the hypervisor.
* Returns zero on success.
*/
static int rpavscsi_init_crq_queue(struct crq_queue *queue,
struct ibmvscsi_host_data *hostdata,
int max_requests)
{
int rc;
int retrc;
struct vio_dev *vdev = to_vio_dev(hostdata->dev);
queue->msgs = (struct viosrp_crq *)get_zeroed_page(GFP_KERNEL);
if (!queue->msgs)
goto malloc_failed;
queue->size = PAGE_SIZE / sizeof(*queue->msgs);
queue->msg_token = dma_map_single(hostdata->dev, queue->msgs,
queue->size * sizeof(*queue->msgs),
DMA_BIDIRECTIONAL);
if (dma_mapping_error(hostdata->dev, queue->msg_token))
goto map_failed;
gather_partition_info();
set_adapter_info(hostdata);
retrc = rc = plpar_hcall_norets(H_REG_CRQ,
vdev->unit_address,
queue->msg_token, PAGE_SIZE);
if (rc == H_RESOURCE)
/* maybe kexecing and resource is busy. try a reset */
rc = rpavscsi_reset_crq_queue(queue,
hostdata);
if (rc == 2) {
/* Adapter is good, but other end is not ready */
dev_warn(hostdata->dev, "Partner adapter not ready\n");
retrc = 0;
} else if (rc != 0) {
dev_warn(hostdata->dev, "Error %d opening adapter\n", rc);
goto reg_crq_failed;
}
if (request_irq(vdev->irq,
rpavscsi_handle_event,
0, "ibmvscsi", (void *)hostdata) != 0) {
dev_err(hostdata->dev, "couldn't register irq 0x%x\n",
vdev->irq);
goto req_irq_failed;
}
rc = vio_enable_interrupts(vdev);
if (rc != 0) {
dev_err(hostdata->dev, "Error %d enabling interrupts!!!\n", rc);
goto req_irq_failed;
}
queue->cur = 0;
spin_lock_init(&queue->lock);
tasklet_init(&hostdata->srp_task, (void *)rpavscsi_task,
(unsigned long)hostdata);
return retrc;
req_irq_failed:
do {
rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
} while ((rc == H_BUSY) || (H_IS_LONG_BUSY(rc)));
reg_crq_failed:
dma_unmap_single(hostdata->dev,
queue->msg_token,
queue->size * sizeof(*queue->msgs), DMA_BIDIRECTIONAL);
map_failed:
free_page((unsigned long)queue->msgs);
malloc_failed:
return -1;
}
/**
* reenable_crq_queue: - reenables a crq after
* @queue: crq_queue to initialize and register
* @hostdata: ibmvscsi_host_data of host
*
*/
static int rpavscsi_reenable_crq_queue(struct crq_queue *queue,
struct ibmvscsi_host_data *hostdata)
{
int rc;
struct vio_dev *vdev = to_vio_dev(hostdata->dev);
/* Re-enable the CRQ */
do {
rc = plpar_hcall_norets(H_ENABLE_CRQ, vdev->unit_address);
} while ((rc == H_IN_PROGRESS) || (rc == H_BUSY) || (H_IS_LONG_BUSY(rc)));
if (rc)
dev_err(hostdata->dev, "Error %d enabling adapter\n", rc);
return rc;
}
struct ibmvscsi_ops rpavscsi_ops = {
.init_crq_queue = rpavscsi_init_crq_queue,
.release_crq_queue = rpavscsi_release_crq_queue,
.reset_crq_queue = rpavscsi_reset_crq_queue,
.reenable_crq_queue = rpavscsi_reenable_crq_queue,
.send_crq = rpavscsi_send_crq,
};

View File

@@ -0,0 +1,217 @@
/*****************************************************************************/
/* srp.h -- SCSI RDMA Protocol definitions */
/* */
/* Written By: Colin Devilbis, IBM Corporation */
/* */
/* Copyright (C) 2003 IBM Corporation */
/* */
/* 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. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program; if not, write to the Free Software */
/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* */
/* */
/* This file contains structures and definitions for IBM RPA (RS/6000 */
/* platform architecture) implementation of the SRP (SCSI RDMA Protocol) */
/* standard. SRP is used on IBM iSeries and pSeries platforms to send SCSI */
/* commands between logical partitions. */
/* */
/* SRP Information Units (IUs) are sent on a "Command/Response Queue" (CRQ) */
/* between partitions. The definitions in this file are architected, */
/* and cannot be changed without breaking compatibility with other versions */
/* of Linux and other operating systems (AIX, OS/400) that talk this protocol*/
/* between logical partitions */
/*****************************************************************************/
#ifndef VIOSRP_H
#define VIOSRP_H
#include <scsi/srp.h>
#define SRP_VERSION "16.a"
#define SRP_MAX_IU_LEN 256
#define SRP_MAX_LOC_LEN 32
union srp_iu {
struct srp_login_req login_req;
struct srp_login_rsp login_rsp;
struct srp_login_rej login_rej;
struct srp_i_logout i_logout;
struct srp_t_logout t_logout;
struct srp_tsk_mgmt tsk_mgmt;
struct srp_cmd cmd;
struct srp_rsp rsp;
u8 reserved[SRP_MAX_IU_LEN];
};
enum viosrp_crq_formats {
VIOSRP_SRP_FORMAT = 0x01,
VIOSRP_MAD_FORMAT = 0x02,
VIOSRP_OS400_FORMAT = 0x03,
VIOSRP_AIX_FORMAT = 0x04,
VIOSRP_LINUX_FORMAT = 0x06,
VIOSRP_INLINE_FORMAT = 0x07
};
enum viosrp_crq_status {
VIOSRP_OK = 0x0,
VIOSRP_NONRECOVERABLE_ERR = 0x1,
VIOSRP_VIOLATES_MAX_XFER = 0x2,
VIOSRP_PARTNER_PANIC = 0x3,
VIOSRP_DEVICE_BUSY = 0x8,
VIOSRP_ADAPTER_FAIL = 0x10,
VIOSRP_OK2 = 0x99,
};
struct viosrp_crq {
u8 valid; /* used by RPA */
u8 format; /* SCSI vs out-of-band */
u8 reserved;
u8 status; /* non-scsi failure? (e.g. DMA failure) */
u16 timeout; /* in seconds */
u16 IU_length; /* in bytes */
u64 IU_data_ptr; /* the TCE for transferring data */
};
/* MADs are Management requests above and beyond the IUs defined in the SRP
* standard.
*/
enum viosrp_mad_types {
VIOSRP_EMPTY_IU_TYPE = 0x01,
VIOSRP_ERROR_LOG_TYPE = 0x02,
VIOSRP_ADAPTER_INFO_TYPE = 0x03,
VIOSRP_HOST_CONFIG_TYPE = 0x04,
VIOSRP_CAPABILITIES_TYPE = 0x05,
VIOSRP_ENABLE_FAST_FAIL = 0x08,
};
enum viosrp_mad_status {
VIOSRP_MAD_SUCCESS = 0x00,
VIOSRP_MAD_NOT_SUPPORTED = 0xF1,
VIOSRP_MAD_FAILED = 0xF7,
};
enum viosrp_capability_type {
MIGRATION_CAPABILITIES = 0x01,
RESERVATION_CAPABILITIES = 0x02,
};
enum viosrp_capability_support {
SERVER_DOES_NOT_SUPPORTS_CAP = 0x0,
SERVER_SUPPORTS_CAP = 0x01,
SERVER_CAP_DATA = 0x02,
};
enum viosrp_reserve_type {
CLIENT_RESERVE_SCSI_2 = 0x01,
};
enum viosrp_capability_flag {
CLIENT_MIGRATED = 0x01,
CLIENT_RECONNECT = 0x02,
CAP_LIST_SUPPORTED = 0x04,
CAP_LIST_DATA = 0x08,
};
/*
* Common MAD header
*/
struct mad_common {
u32 type;
u16 status;
u16 length;
u64 tag;
};
/*
* All SRP (and MAD) requests normally flow from the
* client to the server. There is no way for the server to send
* an asynchronous message back to the client. The Empty IU is used
* to hang out a meaningless request to the server so that it can respond
* asynchrouously with something like a SCSI AER
*/
struct viosrp_empty_iu {
struct mad_common common;
u64 buffer;
u32 port;
};
struct viosrp_error_log {
struct mad_common common;
u64 buffer;
};
struct viosrp_adapter_info {
struct mad_common common;
u64 buffer;
};
struct viosrp_host_config {
struct mad_common common;
u64 buffer;
};
struct viosrp_fast_fail {
struct mad_common common;
};
struct viosrp_capabilities {
struct mad_common common;
u64 buffer;
};
struct mad_capability_common {
u32 cap_type;
u16 length;
u16 server_support;
};
struct mad_reserve_cap {
struct mad_capability_common common;
u32 type;
};
struct mad_migration_cap {
struct mad_capability_common common;
u32 ecl;
};
struct capabilities{
u32 flags;
char name[SRP_MAX_LOC_LEN];
char loc[SRP_MAX_LOC_LEN];
struct mad_migration_cap migration;
struct mad_reserve_cap reserve;
};
union mad_iu {
struct viosrp_empty_iu empty_iu;
struct viosrp_error_log error_log;
struct viosrp_adapter_info adapter_info;
struct viosrp_host_config host_config;
struct viosrp_fast_fail fast_fail;
struct viosrp_capabilities capabilities;
};
union viosrp_iu {
union srp_iu srp;
union mad_iu mad;
};
struct mad_adapter_info_data {
char srp_version[8];
char partition_name[96];
u32 partition_number;
u32 mad_version;
u32 os_type;
u32 port_max_txu[8]; /* per-port maximum transfer */
};
#endif