diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2008-12-31 23:05:57 +1030 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2008-12-31 23:05:57 +1030 |
commit | 2ca1a615835d9f4990f42102ab1f2ef434e7e89c (patch) | |
tree | 726cf3d5f29a6c66c44e4bd68e7ebed2fd83d059 /include/scsi | |
parent | e12f0102ac81d660c9f801d0a0e10ccf4537a9de (diff) | |
parent | 6a94cb73064c952255336cc57731904174b2c58f (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Conflicts:
arch/x86/kernel/io_apic.c
Diffstat (limited to 'include/scsi')
-rw-r--r-- | include/scsi/fc/fc_els.h | 816 | ||||
-rw-r--r-- | include/scsi/fc/fc_encaps.h | 138 | ||||
-rw-r--r-- | include/scsi/fc/fc_fc2.h | 124 | ||||
-rw-r--r-- | include/scsi/fc/fc_fcoe.h | 114 | ||||
-rw-r--r-- | include/scsi/fc/fc_fcp.h | 199 | ||||
-rw-r--r-- | include/scsi/fc/fc_fs.h | 340 | ||||
-rw-r--r-- | include/scsi/fc/fc_gs.h | 93 | ||||
-rw-r--r-- | include/scsi/fc/fc_ns.h | 159 | ||||
-rw-r--r-- | include/scsi/fc_encode.h | 309 | ||||
-rw-r--r-- | include/scsi/fc_frame.h | 242 | ||||
-rw-r--r-- | include/scsi/fc_transport_fcoe.h | 54 | ||||
-rw-r--r-- | include/scsi/iscsi_if.h | 7 | ||||
-rw-r--r-- | include/scsi/libfc.h | 938 | ||||
-rw-r--r-- | include/scsi/libfcoe.h | 176 | ||||
-rw-r--r-- | include/scsi/libiscsi.h | 39 | ||||
-rw-r--r-- | include/scsi/libiscsi_tcp.h | 132 | ||||
-rw-r--r-- | include/scsi/scsi_device.h | 7 | ||||
-rw-r--r-- | include/scsi/scsi_transport_iscsi.h | 12 |
18 files changed, 3882 insertions, 17 deletions
diff --git a/include/scsi/fc/fc_els.h b/include/scsi/fc/fc_els.h new file mode 100644 index 00000000000..195ca014d3c --- /dev/null +++ b/include/scsi/fc/fc_els.h @@ -0,0 +1,816 @@ +/* + * Copyright(c) 2007 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + * Maintained at www.Open-FCoE.org + */ + +#ifndef _FC_ELS_H_ +#define _FC_ELS_H_ + +/* + * Fibre Channel Switch - Enhanced Link Services definitions. + * From T11 FC-LS Rev 1.2 June 7, 2005. + */ + +/* + * ELS Command codes - byte 0 of the frame payload + */ +enum fc_els_cmd { + ELS_LS_RJT = 0x01, /* ESL reject */ + ELS_LS_ACC = 0x02, /* ESL Accept */ + ELS_PLOGI = 0x03, /* N_Port login */ + ELS_FLOGI = 0x04, /* F_Port login */ + ELS_LOGO = 0x05, /* Logout */ + ELS_ABTX = 0x06, /* Abort exchange - obsolete */ + ELS_RCS = 0x07, /* read connection status */ + ELS_RES = 0x08, /* read exchange status block */ + ELS_RSS = 0x09, /* read sequence status block */ + ELS_RSI = 0x0a, /* read sequence initiative */ + ELS_ESTS = 0x0b, /* establish streaming */ + ELS_ESTC = 0x0c, /* estimate credit */ + ELS_ADVC = 0x0d, /* advise credit */ + ELS_RTV = 0x0e, /* read timeout value */ + ELS_RLS = 0x0f, /* read link error status block */ + ELS_ECHO = 0x10, /* echo */ + ELS_TEST = 0x11, /* test */ + ELS_RRQ = 0x12, /* reinstate recovery qualifier */ + ELS_REC = 0x13, /* read exchange concise */ + ELS_SRR = 0x14, /* sequence retransmission request */ + ELS_PRLI = 0x20, /* process login */ + ELS_PRLO = 0x21, /* process logout */ + ELS_SCN = 0x22, /* state change notification */ + ELS_TPLS = 0x23, /* test process login state */ + ELS_TPRLO = 0x24, /* third party process logout */ + ELS_LCLM = 0x25, /* login control list mgmt (obs) */ + ELS_GAID = 0x30, /* get alias_ID */ + ELS_FACT = 0x31, /* fabric activate alias_id */ + ELS_FDACDT = 0x32, /* fabric deactivate alias_id */ + ELS_NACT = 0x33, /* N-port activate alias_id */ + ELS_NDACT = 0x34, /* N-port deactivate alias_id */ + ELS_QOSR = 0x40, /* quality of service request */ + ELS_RVCS = 0x41, /* read virtual circuit status */ + ELS_PDISC = 0x50, /* discover N_port service params */ + ELS_FDISC = 0x51, /* discover F_port service params */ + ELS_ADISC = 0x52, /* discover address */ + ELS_RNC = 0x53, /* report node cap (obs) */ + ELS_FARP_REQ = 0x54, /* FC ARP request */ + ELS_FARP_REPL = 0x55, /* FC ARP reply */ + ELS_RPS = 0x56, /* read port status block */ + ELS_RPL = 0x57, /* read port list */ + ELS_RPBC = 0x58, /* read port buffer condition */ + ELS_FAN = 0x60, /* fabric address notification */ + ELS_RSCN = 0x61, /* registered state change notification */ + ELS_SCR = 0x62, /* state change registration */ + ELS_RNFT = 0x63, /* report node FC-4 types */ + ELS_CSR = 0x68, /* clock synch. request */ + ELS_CSU = 0x69, /* clock synch. update */ + ELS_LINIT = 0x70, /* loop initialize */ + ELS_LSTS = 0x72, /* loop status */ + ELS_RNID = 0x78, /* request node ID data */ + ELS_RLIR = 0x79, /* registered link incident report */ + ELS_LIRR = 0x7a, /* link incident record registration */ + ELS_SRL = 0x7b, /* scan remote loop */ + ELS_SBRP = 0x7c, /* set bit-error reporting params */ + ELS_RPSC = 0x7d, /* report speed capabilities */ + ELS_QSA = 0x7e, /* query security attributes */ + ELS_EVFP = 0x7f, /* exchange virt. fabrics params */ + ELS_LKA = 0x80, /* link keep-alive */ + ELS_AUTH_ELS = 0x90, /* authentication ELS */ +}; + +/* + * Initializer useful for decoding table. + * Please keep this in sync with the above definitions. + */ +#define FC_ELS_CMDS_INIT { \ + [ELS_LS_RJT] = "LS_RJT", \ + [ELS_LS_ACC] = "LS_ACC", \ + [ELS_PLOGI] = "PLOGI", \ + [ELS_FLOGI] = "FLOGI", \ + [ELS_LOGO] = "LOGO", \ + [ELS_ABTX] = "ABTX", \ + [ELS_RCS] = "RCS", \ + [ELS_RES] = "RES", \ + [ELS_RSS] = "RSS", \ + [ELS_RSI] = "RSI", \ + [ELS_ESTS] = "ESTS", \ + [ELS_ESTC] = "ESTC", \ + [ELS_ADVC] = "ADVC", \ + [ELS_RTV] = "RTV", \ + [ELS_RLS] = "RLS", \ + [ELS_ECHO] = "ECHO", \ + [ELS_TEST] = "TEST", \ + [ELS_RRQ] = "RRQ", \ + [ELS_REC] = "REC", \ + [ELS_SRR] = "SRR", \ + [ELS_PRLI] = "PRLI", \ + [ELS_PRLO] = "PRLO", \ + [ELS_SCN] = "SCN", \ + [ELS_TPLS] = "TPLS", \ + [ELS_TPRLO] = "TPRLO", \ + [ELS_LCLM] = "LCLM", \ + [ELS_GAID] = "GAID", \ + [ELS_FACT] = "FACT", \ + [ELS_FDACDT] = "FDACDT", \ + [ELS_NACT] = "NACT", \ + [ELS_NDACT] = "NDACT", \ + [ELS_QOSR] = "QOSR", \ + [ELS_RVCS] = "RVCS", \ + [ELS_PDISC] = "PDISC", \ + [ELS_FDISC] = "FDISC", \ + [ELS_ADISC] = "ADISC", \ + [ELS_RNC] = "RNC", \ + [ELS_FARP_REQ] = "FARP_REQ", \ + [ELS_FARP_REPL] = "FARP_REPL", \ + [ELS_RPS] = "RPS", \ + [ELS_RPL] = "RPL", \ + [ELS_RPBC] = "RPBC", \ + [ELS_FAN] = "FAN", \ + [ELS_RSCN] = "RSCN", \ + [ELS_SCR] = "SCR", \ + [ELS_RNFT] = "RNFT", \ + [ELS_CSR] = "CSR", \ + [ELS_CSU] = "CSU", \ + [ELS_LINIT] = "LINIT", \ + [ELS_LSTS] = "LSTS", \ + [ELS_RNID] = "RNID", \ + [ELS_RLIR] = "RLIR", \ + [ELS_LIRR] = "LIRR", \ + [ELS_SRL] = "SRL", \ + [ELS_SBRP] = "SBRP", \ + [ELS_RPSC] = "RPSC", \ + [ELS_QSA] = "QSA", \ + [ELS_EVFP] = "EVFP", \ + [ELS_LKA] = "LKA", \ + [ELS_AUTH_ELS] = "AUTH_ELS", \ +} + +/* + * LS_ACC payload. + */ +struct fc_els_ls_acc { + __u8 la_cmd; /* command code ELS_LS_ACC */ + __u8 la_resv[3]; /* reserved */ +}; + +/* + * ELS reject payload. + */ +struct fc_els_ls_rjt { + __u8 er_cmd; /* command code ELS_LS_RJT */ + __u8 er_resv[4]; /* reserved must be zero */ + __u8 er_reason; /* reason (enum fc_els_rjt_reason below) */ + __u8 er_explan; /* explanation (enum fc_els_rjt_explan below) */ + __u8 er_vendor; /* vendor specific code */ +}; + +/* + * ELS reject reason codes (er_reason). + */ +enum fc_els_rjt_reason { + ELS_RJT_NONE = 0, /* no reject - not to be sent */ + ELS_RJT_INVAL = 0x01, /* invalid ELS command code */ + ELS_RJT_LOGIC = 0x03, /* logical error */ + ELS_RJT_BUSY = 0x05, /* logical busy */ + ELS_RJT_PROT = 0x07, /* protocol error */ + ELS_RJT_UNAB = 0x09, /* unable to perform command request */ + ELS_RJT_UNSUP = 0x0b, /* command not supported */ + ELS_RJT_INPROG = 0x0e, /* command already in progress */ + ELS_RJT_VENDOR = 0xff, /* vendor specific error */ +}; + + +/* + * reason code explanation (er_explan). + */ +enum fc_els_rjt_explan { + ELS_EXPL_NONE = 0x00, /* No additional explanation */ + ELS_EXPL_SPP_OPT_ERR = 0x01, /* service parameter error - options */ + ELS_EXPL_SPP_ICTL_ERR = 0x03, /* service parm error - initiator ctl */ + ELS_EXPL_AH = 0x11, /* invalid association header */ + ELS_EXPL_AH_REQ = 0x13, /* association_header required */ + ELS_EXPL_SID = 0x15, /* invalid originator S_ID */ + ELS_EXPL_OXID_RXID = 0x17, /* invalid OX_ID-RX_ID combination */ + ELS_EXPL_INPROG = 0x19, /* Request already in progress */ + ELS_EXPL_PLOGI_REQD = 0x1e, /* N_Port login required */ + ELS_EXPL_INSUF_RES = 0x29, /* insufficient resources */ + ELS_EXPL_UNAB_DATA = 0x2a, /* unable to supply requested data */ + ELS_EXPL_UNSUPR = 0x2c, /* Request not supported */ + ELS_EXPL_INV_LEN = 0x2d, /* Invalid payload length */ + /* TBD - above definitions incomplete */ +}; + +/* + * Common service parameters (N ports). + */ +struct fc_els_csp { + __u8 sp_hi_ver; /* highest version supported (obs.) */ + __u8 sp_lo_ver; /* highest version supported (obs.) */ + __be16 sp_bb_cred; /* buffer-to-buffer credits */ + __be16 sp_features; /* common feature flags */ + __be16 sp_bb_data; /* b-b state number and data field sz */ + union { + struct { + __be16 _sp_tot_seq; /* total concurrent sequences */ + __be16 _sp_rel_off; /* rel. offset by info cat */ + } sp_plogi; + struct { + __be32 _sp_r_a_tov; /* resource alloc. timeout msec */ + } sp_flogi_acc; + } sp_u; + __be32 sp_e_d_tov; /* error detect timeout value */ +}; +#define sp_tot_seq sp_u.sp_plogi._sp_tot_seq +#define sp_rel_off sp_u.sp_plogi._sp_rel_off +#define sp_r_a_tov sp_u.sp_flogi_acc._sp_r_a_tov + +#define FC_SP_BB_DATA_MASK 0xfff /* mask for data field size in sp_bb_data */ + +/* + * Minimum and maximum values for max data field size in service parameters. + */ +#define FC_SP_MIN_MAX_PAYLOAD FC_MIN_MAX_PAYLOAD +#define FC_SP_MAX_MAX_PAYLOAD FC_MAX_PAYLOAD + +/* + * sp_features + */ +#define FC_SP_FT_CIRO 0x8000 /* continuously increasing rel. off. */ +#define FC_SP_FT_CLAD 0x8000 /* clean address (in FLOGI LS_ACC) */ +#define FC_SP_FT_RAND 0x4000 /* random relative offset */ +#define FC_SP_FT_VAL 0x2000 /* valid vendor version level */ +#define FC_SP_FT_FPORT 0x1000 /* F port (1) vs. N port (0) */ +#define FC_SP_FT_ABB 0x0800 /* alternate BB_credit management */ +#define FC_SP_FT_EDTR 0x0400 /* E_D_TOV Resolution is nanoseconds */ +#define FC_SP_FT_MCAST 0x0200 /* multicast */ +#define FC_SP_FT_BCAST 0x0100 /* broadcast */ +#define FC_SP_FT_HUNT 0x0080 /* hunt group */ +#define FC_SP_FT_SIMP 0x0040 /* dedicated simplex */ +#define FC_SP_FT_SEC 0x0020 /* reserved for security */ +#define FC_SP_FT_CSYN 0x0010 /* clock synch. supported */ +#define FC_SP_FT_RTTOV 0x0008 /* R_T_TOV value 100 uS, else 100 mS */ +#define FC_SP_FT_HALF 0x0004 /* dynamic half duplex */ +#define FC_SP_FT_SEQC 0x0002 /* SEQ_CNT */ +#define FC_SP_FT_PAYL 0x0001 /* FLOGI payload length 256, else 116 */ + +/* + * Class-specific service parameters. + */ +struct fc_els_cssp { + __be16 cp_class; /* class flags */ + __be16 cp_init; /* initiator flags */ + __be16 cp_recip; /* recipient flags */ + __be16 cp_rdfs; /* receive data field size */ + __be16 cp_con_seq; /* concurrent sequences */ + __be16 cp_ee_cred; /* N-port end-to-end credit */ + __u8 cp_resv1; /* reserved */ + __u8 cp_open_seq; /* open sequences per exchange */ + __u8 _cp_resv2[2]; /* reserved */ +}; + +/* + * cp_class flags. + */ +#define FC_CPC_VALID 0x8000 /* class valid */ +#define FC_CPC_IMIX 0x4000 /* intermix mode */ +#define FC_CPC_SEQ 0x0800 /* sequential delivery */ +#define FC_CPC_CAMP 0x0200 /* camp-on */ +#define FC_CPC_PRI 0x0080 /* priority */ + +/* + * cp_init flags. + * (TBD: not all flags defined here). + */ +#define FC_CPI_CSYN 0x0010 /* clock synch. capable */ + +/* + * cp_recip flags. + */ +#define FC_CPR_CSYN 0x0008 /* clock synch. capable */ + +/* + * NFC_ELS_FLOGI: Fabric login request. + * NFC_ELS_PLOGI: Port login request (same format). + */ +struct fc_els_flogi { + __u8 fl_cmd; /* command */ + __u8 _fl_resvd[3]; /* must be zero */ + struct fc_els_csp fl_csp; /* common service parameters */ + __be64 fl_wwpn; /* port name */ + __be64 fl_wwnn; /* node name */ + struct fc_els_cssp fl_cssp[4]; /* class 1-4 service parameters */ + __u8 fl_vend[16]; /* vendor version level */ +} __attribute__((__packed__)); + +/* + * Process login service parameter page. + */ +struct fc_els_spp { + __u8 spp_type; /* type code or common service params */ + __u8 spp_type_ext; /* type code extension */ + __u8 spp_flags; + __u8 _spp_resvd; + __be32 spp_orig_pa; /* originator process associator */ + __be32 spp_resp_pa; /* responder process associator */ + __be32 spp_params; /* service parameters */ +}; + +/* + * spp_flags. + */ +#define FC_SPP_OPA_VAL 0x80 /* originator proc. assoc. valid */ +#define FC_SPP_RPA_VAL 0x40 /* responder proc. assoc. valid */ +#define FC_SPP_EST_IMG_PAIR 0x20 /* establish image pair */ +#define FC_SPP_RESP_MASK 0x0f /* mask for response code (below) */ + +/* + * SPP response code in spp_flags - lower 4 bits. + */ +enum fc_els_spp_resp { + FC_SPP_RESP_ACK = 1, /* request executed */ + FC_SPP_RESP_RES = 2, /* unable due to lack of resources */ + FC_SPP_RESP_INIT = 3, /* initialization not complete */ + FC_SPP_RESP_NO_PA = 4, /* unknown process associator */ + FC_SPP_RESP_CONF = 5, /* configuration precludes image pair */ + FC_SPP_RESP_COND = 6, /* request completed conditionally */ + FC_SPP_RESP_MULT = 7, /* unable to handle multiple SPPs */ + FC_SPP_RESP_INVL = 8, /* SPP is invalid */ +}; + +/* + * ELS_RRQ - Reinstate Recovery Qualifier + */ +struct fc_els_rrq { + __u8 rrq_cmd; /* command (0x12) */ + __u8 rrq_zero[3]; /* specified as zero - part of cmd */ + __u8 rrq_resvd; /* reserved */ + __u8 rrq_s_id[3]; /* originator FID */ + __be16 rrq_ox_id; /* originator exchange ID */ + __be16 rrq_rx_id; /* responders exchange ID */ +}; + +/* + * ELS_REC - Read exchange concise. + */ +struct fc_els_rec { + __u8 rec_cmd; /* command (0x13) */ + __u8 rec_zero[3]; /* specified as zero - part of cmd */ + __u8 rec_resvd; /* reserved */ + __u8 rec_s_id[3]; /* originator FID */ + __be16 rec_ox_id; /* originator exchange ID */ + __be16 rec_rx_id; /* responders exchange ID */ +}; + +/* + * ELS_REC LS_ACC payload. + */ +struct fc_els_rec_acc { + __u8 reca_cmd; /* accept (0x02) */ + __u8 reca_zero[3]; /* specified as zero - part of cmd */ + __be16 reca_ox_id; /* originator exchange ID */ + __be16 reca_rx_id; /* responders exchange ID */ + __u8 reca_resvd1; /* reserved */ + __u8 reca_ofid[3]; /* originator FID */ + __u8 reca_resvd2; /* reserved */ + __u8 reca_rfid[3]; /* responder FID */ + __be32 reca_fc4value; /* FC4 value */ + __be32 reca_e_stat; /* ESB (exchange status block) status */ +}; + +/* + * ELS_PRLI - Process login request and response. + */ +struct fc_els_prli { + __u8 prli_cmd; /* command */ + __u8 prli_spp_len; /* length of each serv. parm. page */ + __be16 prli_len; /* length of entire payload */ + /* service parameter pages follow */ +}; + +/* + * ELS_ADISC payload + */ +struct fc_els_adisc { + __u8 adisc_cmd; + __u8 adisc_resv[3]; + __u8 adisc_resv1; + __u8 adisc_hard_addr[3]; + __be64 adisc_wwpn; + __be64 adisc_wwnn; + __u8 adisc_resv2; + __u8 adisc_port_id[3]; +} __attribute__((__packed__)); + +/* + * ELS_LOGO - process or fabric logout. + */ +struct fc_els_logo { + __u8 fl_cmd; /* command code */ + __u8 fl_zero[3]; /* specified as zero - part of cmd */ + __u8 fl_resvd; /* reserved */ + __u8 fl_n_port_id[3];/* N port ID */ + __be64 fl_n_port_wwn; /* port name */ +}; + +/* + * ELS_RTV - read timeout value. + */ +struct fc_els_rtv { + __u8 rtv_cmd; /* command code 0x0e */ + __u8 rtv_zero[3]; /* specified as zero - part of cmd */ +}; + +/* + * LS_ACC for ELS_RTV - read timeout value. + */ +struct fc_els_rtv_acc { + __u8 rtv_cmd; /* command code 0x02 */ + __u8 rtv_zero[3]; /* specified as zero - part of cmd */ + __be32 rtv_r_a_tov; /* resource allocation timeout value */ + __be32 rtv_e_d_tov; /* error detection timeout value */ + __be32 rtv_toq; /* timeout qualifier (see below) */ +}; + +/* + * rtv_toq bits. + */ +#define FC_ELS_RTV_EDRES (1 << 26) /* E_D_TOV resolution is nS else mS */ +#define FC_ELS_RTV_RTTOV (1 << 19) /* R_T_TOV is 100 uS else 100 mS */ + +/* + * ELS_SCR - state change registration payload. + */ +struct fc_els_scr { + __u8 scr_cmd; /* command code */ + __u8 scr_resv[6]; /* reserved */ + __u8 scr_reg_func; /* registration function (see below) */ +}; + +enum fc_els_scr_func { + ELS_SCRF_FAB = 1, /* fabric-detected registration */ + ELS_SCRF_NPORT = 2, /* Nx_Port-detected registration */ + ELS_SCRF_FULL = 3, /* full registration */ + ELS_SCRF_CLEAR = 255, /* remove any current registrations */ +}; + +/* + * ELS_RSCN - registered state change notification payload. + */ +struct fc_els_rscn { + __u8 rscn_cmd; /* RSCN opcode (0x61) */ + __u8 rscn_page_len; /* page length (4) */ + __be16 rscn_plen; /* payload length including this word */ + + /* followed by 4-byte generic affected Port_ID pages */ +}; + +struct fc_els_rscn_page { + __u8 rscn_page_flags; /* event and address format */ + __u8 rscn_fid[3]; /* fabric ID */ +}; + +#define ELS_RSCN_EV_QUAL_BIT 2 /* shift count for event qualifier */ +#define ELS_RSCN_EV_QUAL_MASK 0xf /* mask for event qualifier */ +#define ELS_RSCN_ADDR_FMT_BIT 0 /* shift count for address format */ +#define ELS_RSCN_ADDR_FMT_MASK 0x3 /* mask for address format */ + +enum fc_els_rscn_ev_qual { + ELS_EV_QUAL_NONE = 0, /* unspecified */ + ELS_EV_QUAL_NS_OBJ = 1, /* changed name server object */ + ELS_EV_QUAL_PORT_ATTR = 2, /* changed port attribute */ + ELS_EV_QUAL_SERV_OBJ = 3, /* changed service object */ + ELS_EV_QUAL_SW_CONFIG = 4, /* changed switch configuration */ + ELS_EV_QUAL_REM_OBJ = 5, /* removed object */ +}; + +enum fc_els_rscn_addr_fmt { + ELS_ADDR_FMT_PORT = 0, /* rscn_fid is a port address */ + ELS_ADDR_FMT_AREA = 1, /* rscn_fid is a area address */ + ELS_ADDR_FMT_DOM = 2, /* rscn_fid is a domain address */ + ELS_ADDR_FMT_FAB = 3, /* anything on fabric may have changed */ +}; + +/* + * ELS_RNID - request Node ID. + */ +struct fc_els_rnid { + __u8 rnid_cmd; /* RNID opcode (0x78) */ + __u8 rnid_resv[3]; /* reserved */ + __u8 rnid_fmt; /* data format */ + __u8 rnid_resv2[3]; /* reserved */ +}; + +/* + * Node Identification Data formats (rnid_fmt) + */ +enum fc_els_rnid_fmt { + ELS_RNIDF_NONE = 0, /* no specific identification data */ + ELS_RNIDF_GEN = 0xdf, /* general topology discovery format */ +}; + +/* + * ELS_RNID response. + */ +struct fc_els_rnid_resp { + __u8 rnid_cmd; /* response code (LS_ACC) */ + __u8 rnid_resv[3]; /* reserved */ + __u8 rnid_fmt; /* data format */ + __u8 rnid_cid_len; /* common ID data length */ + __u8 rnid_resv2; /* reserved */ + __u8 rnid_sid_len; /* specific ID data length */ +}; + +struct fc_els_rnid_cid { + __be64 rnid_wwpn; /* N port name */ + __be64 rnid_wwnn; /* node name */ +}; + +struct fc_els_rnid_gen { + __u8 rnid_vend_id[16]; /* vendor-unique ID */ + __be32 rnid_atype; /* associated type (see below) */ + __be32 rnid_phys_port; /* physical port number */ + __be32 rnid_att_nodes; /* number of attached nodes */ + __u8 rnid_node_mgmt; /* node management (see below) */ + __u8 rnid_ip_ver; /* IP version (see below) */ + __be16 rnid_prot_port; /* UDP / TCP port number */ + __be32 rnid_ip_addr[4]; /* IP address */ + __u8 rnid_resvd[2]; /* reserved */ + __be16 rnid_vend_spec; /* vendor-specific field */ +}; + +enum fc_els_rnid_atype { + ELS_RNIDA_UNK = 0x01, /* unknown */ + ELS_RNIDA_OTHER = 0x02, /* none of the following */ + ELS_RNIDA_HUB = 0x03, + ELS_RNIDA_SWITCH = 0x04, + ELS_RNIDA_GATEWAY = 0x05, + ELS_RNIDA_CONV = 0x06, /* Obsolete, do not use this value */ + ELS_RNIDA_HBA = 0x07, /* Obsolete, do not use this value */ + ELS_RNIDA_PROXY = 0x08, /* Obsolete, do not use this value */ + ELS_RNIDA_STORAGE = 0x09, + ELS_RNIDA_HOST = 0x0a, + ELS_RNIDA_SUBSYS = 0x0b, /* storage subsystem (e.g., RAID) */ + ELS_RNIDA_ACCESS = 0x0e, /* access device (e.g. media changer) */ + ELS_RNIDA_NAS = 0x11, /* NAS server */ + ELS_RNIDA_BRIDGE = 0x12, /* bridge */ + ELS_RNIDA_VIRT = 0x13, /* virtualization device */ + ELS_RNIDA_MF = 0xff, /* multifunction device (bits below) */ + ELS_RNIDA_MF_HUB = 1UL << 31, /* hub */ + ELS_RNIDA_MF_SW = 1UL << 30, /* switch */ + ELS_RNIDA_MF_GW = 1UL << 29, /* gateway */ + ELS_RNIDA_MF_ST = 1UL << 28, /* storage */ + ELS_RNIDA_MF_HOST = 1UL << 27, /* host */ + ELS_RNIDA_MF_SUB = 1UL << 26, /* storage subsystem */ + ELS_RNIDA_MF_ACC = 1UL << 25, /* storage access dev */ + ELS_RNIDA_MF_WDM = 1UL << 24, /* wavelength division mux */ + ELS_RNIDA_MF_NAS = 1UL << 23, /* NAS server */ + ELS_RNIDA_MF_BR = 1UL << 22, /* bridge */ + ELS_RNIDA_MF_VIRT = 1UL << 21, /* virtualization device */ +}; + +enum fc_els_rnid_mgmt { + ELS_RNIDM_SNMP = 0, + ELS_RNIDM_TELNET = 1, + ELS_RNIDM_HTTP = 2, + ELS_RNIDM_HTTPS = 3, + ELS_RNIDM_XML = 4, /* HTTP + XML */ +}; + +enum fc_els_rnid_ipver { + ELS_RNIDIP_NONE = 0, /* no IP support or node mgmt. */ + ELS_RNIDIP_V4 = 1, /* IPv4 */ + ELS_RNIDIP_V6 = 2, /* IPv6 */ +}; + +/* + * ELS RPL - Read Port List. + */ +struct fc_els_rpl { + __u8 rpl_cmd; /* command */ + __u8 rpl_resv[5]; /* reserved - must be zero */ + __be16 rpl_max_size; /* maximum response size or zero */ + __u8 rpl_resv1; /* reserved - must be zero */ + __u8 rpl_index[3]; /* starting index */ +}; + +/* + * Port number block in RPL response. + */ +struct fc_els_pnb { + __be32 pnb_phys_pn; /* physical port number */ + __u8 pnb_resv; /* reserved */ + __u8 pnb_port_id[3]; /* port ID */ + __be64 pnb_wwpn; /* port name */ +}; + +/* + * RPL LS_ACC response. + */ +struct fc_els_rpl_resp { + __u8 rpl_cmd; /* ELS_LS_ACC */ + __u8 rpl_resv1; /* reserved - must be zero */ + __be16 rpl_plen; /* payload length */ + __u8 rpl_resv2; /* reserved - must be zero */ + __u8 rpl_llen[3]; /* list length */ + __u8 rpl_resv3; /* reserved - must be zero */ + __u8 rpl_index[3]; /* starting index */ + struct fc_els_pnb rpl_pnb[1]; /* variable number of PNBs */ +}; + +/* + * Link Error Status Block. + */ +struct fc_els_lesb { + __be32 lesb_link_fail; /* link failure count */ + __be32 lesb_sync_loss; /* loss of synchronization count */ + __be32 lesb_sig_loss; /* loss of signal count */ + __be32 lesb_prim_err; /* primitive sequence error count */ + __be32 lesb_inv_word; /* invalid transmission word count */ + __be32 lesb_inv_crc; /* invalid CRC count */ +}; + +/* + * ELS RPS - Read Port Status Block request. + */ +struct fc_els_rps { + __u8 rps_cmd; /* command */ + __u8 rps_resv[2]; /* reserved - must be zero */ + __u8 rps_flag; /* flag - see below */ + __be64 rps_port_spec; /* port selection */ +}; + +enum fc_els_rps_flag { + FC_ELS_RPS_DID = 0x00, /* port identified by D_ID of req. */ + FC_ELS_RPS_PPN = 0x01, /* port_spec is physical port number */ + FC_ELS_RPS_WWPN = 0x02, /* port_spec is port WWN */ +}; + +/* + * ELS RPS LS_ACC response. + */ +struct fc_els_rps_resp { + __u8 rps_cmd; /* command - LS_ACC */ + __u8 rps_resv[2]; /* reserved - must be zero */ + __u8 rps_flag; /* flag - see below */ + __u8 rps_resv2[2]; /* reserved */ + __be16 rps_status; /* port status - see below */ + struct fc_els_lesb rps_lesb; /* link error status block */ +}; + +enum fc_els_rps_resp_flag { + FC_ELS_RPS_LPEV = 0x01, /* L_port extension valid */ +}; + +enum fc_els_rps_resp_status { + FC_ELS_RPS_PTP = 1 << 5, /* point-to-point connection */ + FC_ELS_RPS_LOOP = 1 << 4, /* loop mode */ + FC_ELS_RPS_FAB = 1 << 3, /* fabric present */ + FC_ELS_RPS_NO_SIG = 1 << 2, /* loss of signal */ + FC_ELS_RPS_NO_SYNC = 1 << 1, /* loss of synchronization */ + FC_ELS_RPS_RESET = 1 << 0, /* in link reset protocol */ +}; + +/* + * ELS LIRR - Link Incident Record Registration request. + */ +struct fc_els_lirr { + __u8 lirr_cmd; /* command */ + __u8 lirr_resv[3]; /* reserved - must be zero */ + __u8 lirr_func; /* registration function */ + __u8 lirr_fmt; /* FC-4 type of RLIR requested */ + __u8 lirr_resv2[2]; /* reserved - must be zero */ +}; + +enum fc_els_lirr_func { + ELS_LIRR_SET_COND = 0x01, /* set - conditionally receive */ + ELS_LIRR_SET_UNCOND = 0x02, /* set - unconditionally receive */ + ELS_LIRR_CLEAR = 0xff /* clear registration */ +}; + +/* + * ELS SRL - Scan Remote Loop request. + */ +struct fc_els_srl { + __u8 srl_cmd; /* command */ + __u8 srl_resv[3]; /* reserved - must be zero */ + __u8 srl_flag; /* flag - see below */ + __u8 srl_flag_param[3]; /* flag parameter */ +}; + +enum fc_els_srl_flag { + FC_ELS_SRL_ALL = 0x00, /* scan all FL ports */ + FC_ELS_SRL_ONE = 0x01, /* scan specified loop */ + FC_ELS_SRL_EN_PER = 0x02, /* enable periodic scanning (param) */ + FC_ELS_SRL_DIS_PER = 0x03, /* disable periodic scanning */ +}; + +/* + * ELS RLS - Read Link Error Status Block request. + */ +struct fc_els_rls { + __u8 rls_cmd; /* command */ + __u8 rls_resv[4]; /* reserved - must be zero */ + __u8 rls_port_id[3]; /* port ID */ +}; + +/* + * ELS RLS LS_ACC Response. + */ +struct fc_els_rls_resp { + __u8 rls_cmd; /* ELS_LS_ACC */ + __u8 rls_resv[3]; /* reserved - must be zero */ + struct fc_els_lesb rls_lesb; /* link error status block */ +}; + +/* + * ELS RLIR - Registered Link Incident Report. + * This is followed by the CLIR and the CLID, described below. + */ +struct fc_els_rlir { + __u8 rlir_cmd; /* command */ + __u8 rlir_resv[3]; /* reserved - must be zero */ + __u8 rlir_fmt; /* format (FC4-type if type specific) */ + __u8 rlir_clr_len; /* common link incident record length */ + __u8 rlir_cld_len; /* common link incident desc. length */ + __u8 rlir_slr_len; /* spec. link incident record length */ +}; + +/* + * CLIR - Common Link Incident Record Data. - Sent via RLIR. + */ +struct fc_els_clir { + __be64 clir_wwpn; /* incident port name */ + __be64 clir_wwnn; /* incident port node name */ + __u8 clir_port_type; /* incident port type */ + __u8 clir_port_id[3]; /* incident port ID */ + + __be64 clir_conn_wwpn; /* connected port name */ + __be64 clir_conn_wwnn; /* connected node name */ + __be64 clir_fab_name; /* fabric name */ + __be32 clir_phys_port; /* physical port number */ + __be32 clir_trans_id; /* transaction ID */ + __u8 clir_resv[3]; /* reserved */ + __u8 clir_ts_fmt; /* time stamp format */ + __be64 clir_timestamp; /* time stamp */ +}; + +/* + * CLIR clir_ts_fmt - time stamp format values. + */ +enum fc_els_clir_ts_fmt { + ELS_CLIR_TS_UNKNOWN = 0, /* time stamp field unknown */ + ELS_CLIR_TS_SEC_FRAC = 1, /* time in seconds and fractions */ + ELS_CLIR_TS_CSU = 2, /* time in clock synch update format */ +}; + +/* + * Common Link Incident Descriptor - sent via RLIR. + */ +struct fc_els_clid { + __u8 clid_iq; /* incident qualifier flags */ + __u8 clid_ic; /* incident code */ + __be16 clid_epai; /* domain/area of ISL */ +}; + +/* + * CLID incident qualifier flags. + */ +enum fc_els_clid_iq { + ELS_CLID_SWITCH = 0x20, /* incident port is a switch node */ + ELS_CLID_E_PORT = 0x10, /* incident is an ISL (E) port */ + ELS_CLID_SEV_MASK = 0x0c, /* severity 2-bit field mask */ + ELS_CLID_SEV_INFO = 0x00, /* report is informational */ + ELS_CLID_SEV_INOP = 0x08, /* link not operational */ + ELS_CLID_SEV_DEG = 0x04, /* link degraded but operational */ + ELS_CLID_LASER = 0x02, /* subassembly is a laser */ + ELS_CLID_FRU = 0x01, /* format can identify a FRU */ +}; + +/* + * CLID incident code. + */ +enum fc_els_clid_ic { + ELS_CLID_IC_IMPL = 1, /* implicit incident */ + ELS_CLID_IC_BER = 2, /* bit-error-rate threshold exceeded */ + ELS_CLID_IC_LOS = 3, /* loss of synch or signal */ + ELS_CLID_IC_NOS = 4, /* non-operational primitive sequence */ + ELS_CLID_IC_PST = 5, /* primitive sequence timeout */ + ELS_CLID_IC_INVAL = 6, /* invalid primitive sequence */ + ELS_CLID_IC_LOOP_TO = 7, /* loop initialization time out */ + ELS_CLID_IC_LIP = 8, /* receiving LIP */ +}; + +#endif /* _FC_ELS_H_ */ diff --git a/include/scsi/fc/fc_encaps.h b/include/scsi/fc/fc_encaps.h new file mode 100644 index 00000000000..f180c3e1622 --- /dev/null +++ b/include/scsi/fc/fc_encaps.h @@ -0,0 +1,138 @@ +/* + * Copyright(c) 2007 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + * Maintained at www.Open-FCoE.org + */ +#ifndef _FC_ENCAPS_H_ +#define _FC_ENCAPS_H_ + +/* + * Protocol definitions from RFC 3643 - Fibre Channel Frame Encapsulation. + * + * Note: The frame length field is the number of 32-bit words in + * the encapsulation including the fcip_encaps_header, CRC and EOF words. + * The minimum frame length value in bytes is (32 + 24 + 4 + 4) * 4 = 64. + * The maximum frame length value in bytes is (32 + 24 + 2112 + 4 + 4) = 2172. + */ +#define FC_ENCAPS_MIN_FRAME_LEN 64 /* min frame len (bytes) (see above) */ +#define FC_ENCAPS_MAX_FRAME_LEN (FC_ENCAPS_MIN_FRAME_LEN + FC_MAX_PAYLOAD) + +#define FC_ENCAPS_VER 1 /* current version number */ + +struct fc_encaps_hdr { + __u8 fc_proto; /* protocol number */ + __u8 fc_ver; /* version of encapsulation */ + __u8 fc_proto_n; /* ones complement of protocol */ + __u8 fc_ver_n; /* ones complement of version */ + + unsigned char fc_proto_data[8]; /* protocol specific data */ + + __be16 fc_len_flags; /* 10-bit length/4 w/ 6 flag bits */ + __be16 fc_len_flags_n; /* ones complement of length / flags */ + + /* + * Offset 0x10 + */ + __be32 fc_time[2]; /* time stamp: seconds and fraction */ + __be32 fc_crc; /* CRC */ + __be32 fc_sof; /* start of frame (see FC_SOF below) */ + + /* 0x20 - FC frame content followed by EOF word */ +}; + +#define FCIP_ENCAPS_HDR_LEN 0x20 /* expected length for asserts */ + +/* + * Macro's for making redundant copies of EOF and SOF. + */ +#define FC_XY(x, y) ((((x) & 0xff) << 8) | ((y) & 0xff)) +#define FC_XYXY(x, y) ((FCIP_XY(x, y) << 16) | FCIP_XY(x, y)) +#define FC_XYNN(x, y) (FCIP_XYXY(x, y) ^ 0xffff) + +#define FC_SOF_ENCODE(n) FC_XYNN(n, n) +#define FC_EOF_ENCODE(n) FC_XYNN(n, n) + +/* + * SOF / EOF bytes. + */ +enum fc_sof { + FC_SOF_F = 0x28, /* fabric */ + FC_SOF_I4 = 0x29, /* initiate class 4 */ + FC_SOF_I2 = 0x2d, /* initiate class 2 */ + FC_SOF_I3 = 0x2e, /* initiate class 3 */ + FC_SOF_N4 = 0x31, /* normal class 4 */ + FC_SOF_N2 = 0x35, /* normal class 2 */ + FC_SOF_N3 = 0x36, /* normal class 3 */ + FC_SOF_C4 = 0x39, /* activate class 4 */ +} __attribute__((packed)); + +enum fc_eof { + FC_EOF_N = 0x41, /* normal (not last frame of seq) */ + FC_EOF_T = 0x42, /* terminate (last frame of sequence) */ + FC_EOF_RT = 0x44, + FC_EOF_DT = 0x46, /* disconnect-terminate class-1 */ + FC_EOF_NI = 0x49, /* normal-invalid */ + FC_EOF_DTI = 0x4e, /* disconnect-terminate-invalid */ + FC_EOF_RTI = 0x4f, + FC_EOF_A = 0x50, /* abort */ +} __attribute__((packed)); + +#define FC_SOF_CLASS_MASK 0x06 /* mask for class of service in SOF */ + +/* + * Define classes in terms of the SOF code (initial). + */ +enum fc_class { + FC_CLASS_NONE = 0, /* software value indicating no class */ + FC_CLASS_2 = FC_SOF_I2, + FC_CLASS_3 = FC_SOF_I3, + FC_CLASS_4 = FC_SOF_I4, + FC_CLASS_F = FC_SOF_F, +}; + +/* + * Determine whether SOF code indicates the need for a BLS ACK. + */ +static inline int fc_sof_needs_ack(enum fc_sof sof) +{ + return (~sof) & 0x02; /* true for class 1, 2, 4, 6, or F */ +} + +/* + * Given an fc_class, return the normal (non-initial) SOF value. + */ +static inline enum fc_sof fc_sof_normal(enum fc_class class) +{ + return class + FC_SOF_N3 - FC_SOF_I3; /* diff is always 8 */ +} + +/* + * Compute class from SOF value. + */ +static inline enum fc_class fc_sof_class(enum fc_sof sof) +{ + return (sof & 0x7) | FC_SOF_F; +} + +/* + * Determine whether SOF is for the initial frame of a sequence. + */ +static inline int fc_sof_is_init(enum fc_sof sof) +{ + return sof < 0x30; +} + +#endif /* _FC_ENCAPS_H_ */ diff --git a/include/scsi/fc/fc_fc2.h b/include/scsi/fc/fc_fc2.h new file mode 100644 index 00000000000..cff8a8c22f5 --- /dev/null +++ b/include/scsi/fc/fc_fc2.h @@ -0,0 +1,124 @@ +/* + * Copyright(c) 2007 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + * Maintained at www.Open-FCoE.org + */ + +#ifndef _FC_FC2_H_ +#define _FC_FC2_H_ + +/* + * Fibre Channel Exchanges and Sequences. + */ +#ifndef PACKED +#define PACKED __attribute__ ((__packed__)) +#endif /* PACKED */ + + +/* + * Sequence Status Block. + * This format is set by the FC-FS standard and is sent over the wire. + * Note that the fields aren't all naturally aligned. + */ +struct fc_ssb { + __u8 ssb_seq_id; /* sequence ID */ + __u8 _ssb_resvd; + __be16 ssb_low_seq_cnt; /* lowest SEQ_CNT */ + + __be16 ssb_high_seq_cnt; /* highest SEQ_CNT */ + __be16 ssb_s_stat; /* sequence status flags */ + + __be16 ssb_err_seq_cnt; /* error SEQ_CNT */ + __u8 ssb_fh_cs_ctl; /* frame header CS_CTL */ + __be16 ssb_fh_ox_id; /* frame header OX_ID */ + __be16 ssb_rx_id; /* responder's exchange ID */ + __u8 _ssb_resvd2[2]; +} PACKED; + +/* + * The SSB should be 17 bytes. Since it's layout is somewhat strange, + * we define the size here so that code can ASSERT that the size comes out + * correct. + */ +#define FC_SSB_SIZE 17 /* length of fc_ssb for assert */ + +/* + * ssb_s_stat - flags from FC-FS-2 T11/1619-D Rev 0.90. + */ +#define SSB_ST_RESP (1 << 15) /* sequence responder */ +#define SSB_ST_ACTIVE (1 << 14) /* sequence is active */ +#define SSB_ST_ABNORMAL (1 << 12) /* abnormal ending condition */ + +#define SSB_ST_REQ_MASK (3 << 10) /* ACK, abort sequence condition */ +#define SSB_ST_REQ_CONT (0 << 10) +#define SSB_ST_REQ_ABORT (1 << 10) +#define SSB_ST_REQ_STOP (2 << 10) +#define SSB_ST_REQ_RETRANS (3 << 10) + +#define SSB_ST_ABTS (1 << 9) /* ABTS protocol completed */ +#define SSB_ST_RETRANS (1 << 8) /* retransmission completed */ +#define SSB_ST_TIMEOUT (1 << 7) /* sequence timed out by recipient */ +#define SSB_ST_P_RJT (1 << 6) /* P_RJT transmitted */ + +#define SSB_ST_CLASS_BIT 4 /* class of service field LSB */ +#define SSB_ST_CLASS_MASK 3 /* class of service mask */ +#define SSB_ST_ACK (1 << 3) /* ACK (EOFt or EOFdt) transmitted */ + +/* + * Exchange Status Block. + * This format is set by the FC-FS standard and is sent over the wire. + * Note that the fields aren't all naturally aligned. + */ +struct fc_esb { + __u8 esb_cs_ctl; /* CS_CTL for frame header */ + __be16 esb_ox_id; /* originator exchange ID */ + __be16 esb_rx_id; /* responder exchange ID */ + __be32 esb_orig_fid; /* fabric ID of originator */ + __be32 esb_resp_fid; /* fabric ID of responder */ + __be32 esb_e_stat; /* status */ + __u8 _esb_resvd[4]; + __u8 esb_service_params[112]; /* TBD */ + __u8 esb_seq_status[8]; /* sequence statuses, 8 bytes each */ +} __attribute__((packed));; + + +/* + * Define expected size for ASSERTs. + * See comments on FC_SSB_SIZE. + */ +#define FC_ESB_SIZE (1 + 5*4 + 112 + 8) /* expected size */ + +/* + * esb_e_stat - flags from FC-FS-2 T11/1619-D Rev 0.90. + */ +#define ESB_ST_RESP (1 << 31) /* responder to exchange */ +#define ESB_ST_SEQ_INIT (1 << 30) /* port holds sequence initiaive */ +#define ESB_ST_COMPLETE (1 << 29) /* exchange is complete */ +#define ESB_ST_ABNORMAL (1 << 28) /* abnormal ending condition */ +#define ESB_ST_REC_QUAL (1 << 26) /* recovery qualifier active */ + +#define ESB_ST_ERRP_BIT 24 /* LSB for error policy */ +#define ESB_ST_ERRP_MASK (3 << 24) /* mask for error policy */ +#define ESB_ST_ERRP_MULT (0 << 24) /* abort, discard multiple sequences */ +#define ESB_ST_ERRP_SING (1 << 24) /* abort, discard single sequence */ +#define ESB_ST_ERRP_INF (2 << 24) /* process with infinite buffers */ +#define ESB_ST_ERRP_IMM (3 << 24) /* discard mult. with immed. retran. */ + +#define ESB_ST_OX_ID_INVL (1 << 23) /* originator XID invalid */ +#define ESB_ST_RX_ID_INVL (1 << 22) /* responder XID invalid */ +#define ESB_ST_PRI_INUSE (1 << 21) /* priority / preemption in use */ + +#endif /* _FC_FC2_H_ */ diff --git a/include/scsi/fc/fc_fcoe.h b/include/scsi/fc/fc_fcoe.h new file mode 100644 index 00000000000..57aaa8f0d61 --- /dev/null +++ b/include/scsi/fc/fc_fcoe.h @@ -0,0 +1,114 @@ +/* + * Copyright(c) 2007 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + * Maintained at www.Open-FCoE.org + */ + +#ifndef _FC_FCOE_H_ +#define _FC_FCOE_H_ + +/* + * FCoE - Fibre Channel over Ethernet. + */ + +/* + * The FCoE ethertype eventually goes in net/if_ether.h. + */ +#ifndef ETH_P_FCOE +#define ETH_P_FCOE 0x8906 /* FCOE ether type */ +#endif + +#ifndef ETH_P_8021Q +#define ETH_P_8021Q 0x8100 +#endif + +/* + * FC_FCOE_OUI hasn't been standardized yet. XXX TBD. + */ +#ifndef FC_FCOE_OUI +#define FC_FCOE_OUI 0x0efc00 /* upper 24 bits of FCOE dest MAC TBD */ +#endif + +/* + * The destination MAC address for the fabric login may get a different OUI. + * This isn't standardized yet. + */ +#ifndef FC_FCOE_FLOGI_MAC +/* gateway MAC - TBD */ +#define FC_FCOE_FLOGI_MAC { 0x0e, 0xfc, 0x00, 0xff, 0xff, 0xfe } +#endif + +#define FC_FCOE_VER 0 /* version */ + +/* + * Ethernet Addresses based on FC S_ID and D_ID. + * Generated by FC_FCOE_OUI | S_ID/D_ID + */ +#define FC_FCOE_ENCAPS_ID(n) (((u64) FC_FCOE_OUI << 24) | (n)) +#define FC_FCOE_DECAPS_ID(n) ((n) >> 24) + +/* + * FCoE frame header - 14 bytes + * + * This is the August 2007 version of the FCoE header as defined by T11. + * This follows the VLAN header, which includes the ethertype. + */ +struct fcoe_hdr { + __u8 fcoe_ver; /* version field - upper 4 bits */ + __u8 fcoe_resvd[12]; /* reserved - send zero and ignore */ + __u8 fcoe_sof; /* start of frame per RFC 3643 */ +}; + +#define FC_FCOE_DECAPS_VER(hp) ((hp)->fcoe_ver >> 4) +#define FC_FCOE_ENCAPS_VER(hp, ver) ((hp)->fcoe_ver = (ver) << 4) + +/* + * FCoE CRC & EOF - 8 bytes. + */ +struct fcoe_crc_eof { + __le32 fcoe_crc32; /* CRC for FC packet */ + __u8 fcoe_eof; /* EOF from RFC 3643 */ + __u8 fcoe_resvd[3]; /* reserved - send zero and ignore */ +} __attribute__((packed)); + +/* + * Minimum FCoE + FC header length + * 14 bytes FCoE header + 24 byte FC header = 38 bytes + */ +#define FCOE_HEADER_LEN 38 + +/* + * Minimum FCoE frame size + * 14 bytes FCoE header + 24 byte FC header + 8 byte FCoE trailer = 46 bytes + */ +#define FCOE_MIN_FRAME 46 + +/* + * fc_fcoe_set_mac - Store OUI + DID into MAC address field. + * @mac: mac address to be set + * @did: fc dest id to use + */ +static inline void fc_fcoe_set_mac(u8 *mac, u8 *did) +{ + mac[0] = (u8) (FC_FCOE_OUI >> 16); + mac[1] = (u8) (FC_FCOE_OUI >> 8); + mac[2] = (u8) FC_FCOE_OUI; + mac[3] = did[0]; + mac[4] = did[1]; + mac[5] = did[2]; +} + +#endif /* _FC_FCOE_H_ */ diff --git a/include/scsi/fc/fc_fcp.h b/include/scsi/fc/fc_fcp.h new file mode 100644 index 00000000000..5d38f1989f3 --- /dev/null +++ b/include/scsi/fc/fc_fcp.h @@ -0,0 +1,199 @@ +/* + * Copyright(c) 2007 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + * Maintained at www.Open-FCoE.org + */ + +#ifndef _FC_FCP_H_ +#define _FC_FCP_H_ + +/* + * Fibre Channel Protocol for SCSI. + * From T10 FCP-3, T10 project 1560-D Rev 4, Sept. 13, 2005. + */ + +/* + * fc/fs.h defines FC_TYPE_FCP. + */ + +/* + * Service parameter page parameters (word 3 bits) for Process Login. + */ +#define FCP_SPPF_TASK_RETRY_ID 0x0200 /* task retry ID requested */ +#define FCP_SPPF_RETRY 0x0100 /* retry supported */ +#define FCP_SPPF_CONF_COMPL 0x0080 /* confirmed completion allowed */ +#define FCP_SPPF_OVLY_ALLOW 0x0040 /* data overlay allowed */ +#define FCP_SPPF_INIT_FCN 0x0020 /* initiator function */ +#define FCP_SPPF_TARG_FCN 0x0010 /* target function */ +#define FCP_SPPF_RD_XRDY_DIS 0x0002 /* disable XFER_RDY for reads */ +#define FCP_SPPF_WR_XRDY_DIS 0x0001 /* disable XFER_RDY for writes */ + +/* + * FCP_CMND IU Payload. + */ +struct fcp_cmnd { + __u8 fc_lun[8]; /* logical unit number */ + __u8 fc_cmdref; /* commmand reference number */ + __u8 fc_pri_ta; /* priority and task attribute */ + __u8 fc_tm_flags; /* task management flags */ + __u8 fc_flags; /* additional len & flags */ + __u8 fc_cdb[16]; /* base CDB */ + __be32 fc_dl; /* data length (must follow fc_cdb) */ +}; + +#define FCP_CMND_LEN 32 /* expected length of structure */ + +struct fcp_cmnd32 { + __u8 fc_lun[8]; /* logical unit number */ + __u8 fc_cmdref; /* commmand reference number */ + __u8 fc_pri_ta; /* priority and task attribute */ + __u8 fc_tm_flags; /* task management flags */ + __u8 fc_flags; /* additional len & flags */ + __u8 fc_cdb[32]; /* base CDB */ + __be32 fc_dl; /* data length (must follow fc_cdb) */ +}; + +#define FCP_CMND32_LEN 48 /* expected length of structure */ +#define FCP_CMND32_ADD_LEN (16 / 4) /* Additional cdb length */ + +/* + * fc_pri_ta. + */ +#define FCP_PTA_SIMPLE 0 /* simple task attribute */ +#define FCP_PTA_HEADQ 1 /* head of queue task attribute */ +#define FCP_PTA_ORDERED 2 /* ordered task attribute */ +#define FCP_PTA_ACA 4 /* auto. contigent allegiance */ +#define FCP_PRI_SHIFT 3 /* priority field starts in bit 3 */ +#define FCP_PRI_RESVD_MASK 0x80 /* reserved bits in priority field */ + +/* + * fc_tm_flags - task management flags field. + */ +#define FCP_TMF_CLR_ACA 0x40 /* clear ACA condition */ +#define FCP_TMF_LUN_RESET 0x10 /* logical unit reset task management */ +#define FCP_TMF_CLR_TASK_SET 0x04 /* clear task set */ +#define FCP_TMF_ABT_TASK_SET 0x02 /* abort task set */ + +/* + * fc_flags. + * Bits 7:2 are the additional FCP_CDB length / 4. + */ +#define FCP_CFL_LEN_MASK 0xfc /* mask for additional length */ +#define FCP_CFL_LEN_SHIFT 2 /* shift bits for additional length */ +#define FCP_CFL_RDDATA 0x02 /* read data */ +#define FCP_CFL_WRDATA 0x01 /* write data */ + +/* + * FCP_TXRDY IU - transfer ready payload. + */ +struct fcp_txrdy { + __be32 ft_data_ro; /* data relative offset */ + __be32 ft_burst_len; /* burst length */ + __u8 _ft_resvd[4]; /* reserved */ +}; + +#define FCP_TXRDY_LEN 12 /* expected length of structure */ + +/* + * FCP_RESP IU - response payload. + * + * The response payload comes in three parts: the flags/status, the + * sense/response lengths and the sense data/response info section. + * + * From FCP3r04, note 6 of section 9.5.13: + * + * Some early implementations presented the FCP_RSP IU without the FCP_RESID, + * FCP_SNS_LEN, and FCP_RSP_LEN fields if the FCP_RESID_UNDER, FCP_RESID_OVER, + * FCP_SNS_LEN_VALID, and FCP_RSP_LEN_VALID bits were all set to zero. This + * non-standard behavior should be tolerated. + * + * All response frames will always contain the fcp_resp template. Some + * will also include the fcp_resp_len template. + */ +struct fcp_resp { + __u8 _fr_resvd[8]; /* reserved */ + __be16 fr_retry_delay; /* retry delay timer */ + __u8 fr_flags; /* flags */ + __u8 fr_status; /* SCSI status code */ +}; + +#define FCP_RESP_LEN 12 /* expected length of structure */ + +struct fcp_resp_ext { + __be32 fr_resid; /* Residual value */ + __be32 fr_sns_len; /* SCSI Sense length */ + __be32 fr_rsp_len; /* Response Info length */ + + /* + * Optionally followed by RSP info and/or SNS info and/or + * bidirectional read residual length, if any. + */ +}; + +#define FCP_RESP_EXT_LEN 12 /* expected length of the structure */ + +struct fcp_resp_rsp_info { + __u8 _fr_resvd[3]; /* reserved */ + __u8 rsp_code; /* Response Info Code */ + __u8 _fr_resvd2[4]; /* reserved */ +}; + +struct fcp_resp_with_ext { + struct fcp_resp resp; + struct fcp_resp_ext ext; +}; + +#define FCP_RESP_WITH_EXT (FCP_RESP_LEN + FCP_RESP_EXT_LEN) + +/* + * fr_flags. + */ +#define FCP_BIDI_RSP 0x80 /* bidirectional read response */ +#define FCP_BIDI_READ_UNDER 0x40 /* bidir. read less than requested */ +#define FCP_BIDI_READ_OVER 0x20 /* DL insufficient for full transfer */ +#define FCP_CONF_REQ 0x10 /* confirmation requested */ +#define FCP_RESID_UNDER 0x08 /* transfer shorter than expected */ +#define FCP_RESID_OVER 0x04 /* DL insufficient for full transfer */ +#define FCP_SNS_LEN_VAL 0x02 /* SNS_LEN field is valid */ +#define FCP_RSP_LEN_VAL 0x01 /* RSP_LEN field is valid */ + +/* + * rsp_codes + */ +enum fcp_resp_rsp_codes { + FCP_TMF_CMPL = 0, + FCP_DATA_LEN_INVALID = 1, + FCP_CMND_FIELDS_INVALID = 2, + FCP_DATA_PARAM_MISMATCH = 3, + FCP_TMF_REJECTED = 4, + FCP_TMF_FAILED = 5, + FCP_TMF_INVALID_LUN = 9, +}; + +/* + * FCP SRR Link Service request - Sequence Retransmission Request. + */ +struct fcp_srr { + __u8 srr_op; /* opcode ELS_SRR */ + __u8 srr_resvd[3]; /* opcode / reserved - must be zero */ + __be16 srr_ox_id; /* OX_ID of failed command */ + __be16 srr_rx_id; /* RX_ID of failed command */ + __be32 srr_rel_off; /* relative offset */ + __u8 srr_r_ctl; /* r_ctl for the information unit */ + __u8 srr_resvd2[3]; /* reserved */ +}; + +#endif /* _FC_FCP_H_ */ diff --git a/include/scsi/fc/fc_fs.h b/include/scsi/fc/fc_fs.h new file mode 100644 index 00000000000..3e4801d2bdb --- /dev/null +++ b/include/scsi/fc/fc_fs.h @@ -0,0 +1,340 @@ +/* + * Copyright(c) 2007 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + * Maintained at www.Open-FCoE.org + */ + +#ifndef _FC_FS_H_ +#define _FC_FS_H_ + +/* + * Fibre Channel Framing and Signalling definitions. + * From T11 FC-FS-2 Rev 0.90 - 9 August 2005. + */ + +/* + * Frame header + */ +struct fc_frame_header { + __u8 fh_r_ctl; /* routing control */ + __u8 fh_d_id[3]; /* Destination ID */ + + __u8 fh_cs_ctl; /* class of service control / pri */ + __u8 fh_s_id[3]; /* Source ID */ + + __u8 fh_type; /* see enum fc_fh_type below */ + __u8 fh_f_ctl[3]; /* frame control */ + + __u8 fh_seq_id; /* sequence ID */ + __u8 fh_df_ctl; /* data field control */ + __be16 fh_seq_cnt; /* sequence count */ + + __be16 fh_ox_id; /* originator exchange ID */ + __be16 fh_rx_id; /* responder exchange ID */ + __be32 fh_parm_offset; /* parameter or relative offset */ +}; + +#define FC_FRAME_HEADER_LEN 24 /* expected length of structure */ + +#define FC_MAX_PAYLOAD 2112U /* max payload length in bytes */ +#define FC_MIN_MAX_PAYLOAD 256U /* lower limit on max payload */ + +#define FC_MAX_FRAME (FC_MAX_PAYLOAD + FC_FRAME_HEADER_LEN) +#define FC_MIN_MAX_FRAME (FC_MIN_MAX_PAYLOAD + FC_FRAME_HEADER_LEN) + +/* + * fh_r_ctl - Routing control definitions. + */ + /* + * FC-4 device_data. + */ +enum fc_rctl { + FC_RCTL_DD_UNCAT = 0x00, /* uncategorized information */ + FC_RCTL_DD_SOL_DATA = 0x01, /* solicited data */ + FC_RCTL_DD_UNSOL_CTL = 0x02, /* unsolicited control */ + FC_RCTL_DD_SOL_CTL = 0x03, /* solicited control or reply */ + FC_RCTL_DD_UNSOL_DATA = 0x04, /* unsolicited data */ + FC_RCTL_DD_DATA_DESC = 0x05, /* data descriptor */ + FC_RCTL_DD_UNSOL_CMD = 0x06, /* unsolicited command */ + FC_RCTL_DD_CMD_STATUS = 0x07, /* command status */ + +#define FC_RCTL_ILS_REQ FC_RCTL_DD_UNSOL_CTL /* ILS request */ +#define FC_RCTL_ILS_REP FC_RCTL_DD_SOL_CTL /* ILS reply */ + + /* + * Extended Link_Data + */ + FC_RCTL_ELS_REQ = 0x22, /* extended link services request */ + FC_RCTL_ELS_REP = 0x23, /* extended link services reply */ + FC_RCTL_ELS4_REQ = 0x32, /* FC-4 ELS request */ + FC_RCTL_ELS4_REP = 0x33, /* FC-4 ELS reply */ + /* + * Optional Extended Headers + */ + FC_RCTL_VFTH = 0x50, /* virtual fabric tagging header */ + FC_RCTL_IFRH = 0x51, /* inter-fabric routing header */ + FC_RCTL_ENCH = 0x52, /* encapsulation header */ + /* + * Basic Link Services fh_r_ctl values. + */ + FC_RCTL_BA_NOP = 0x80, /* basic link service NOP */ + FC_RCTL_BA_ABTS = 0x81, /* basic link service abort */ + FC_RCTL_BA_RMC = 0x82, /* remove connection */ + FC_RCTL_BA_ACC = 0x84, /* basic accept */ + FC_RCTL_BA_RJT = 0x85, /* basic reject */ + FC_RCTL_BA_PRMT = 0x86, /* dedicated connection preempted */ + /* + * Link Control Information. + */ + FC_RCTL_ACK_1 = 0xc0, /* acknowledge_1 */ + FC_RCTL_ACK_0 = 0xc1, /* acknowledge_0 */ + FC_RCTL_P_RJT = 0xc2, /* port reject */ + FC_RCTL_F_RJT = 0xc3, /* fabric reject */ + FC_RCTL_P_BSY = 0xc4, /* port busy */ + FC_RCTL_F_BSY = 0xc5, /* fabric busy to data frame */ + FC_RCTL_F_BSYL = 0xc6, /* fabric busy to link control frame */ + FC_RCTL_LCR = 0xc7, /* link credit reset */ + FC_RCTL_END = 0xc9, /* end */ +}; + /* incomplete list of definitions */ + +/* + * R_CTL names initializer. + * Please keep this matching the above definitions. + */ +#define FC_RCTL_NAMES_INIT { \ + [FC_RCTL_DD_UNCAT] = "uncat", \ + [FC_RCTL_DD_SOL_DATA] = "sol data", \ + [FC_RCTL_DD_UNSOL_CTL] = "unsol ctl", \ + [FC_RCTL_DD_SOL_CTL] = "sol ctl/reply", \ + [FC_RCTL_DD_UNSOL_DATA] = "unsol data", \ + [FC_RCTL_DD_DATA_DESC] = "data desc", \ + [FC_RCTL_DD_UNSOL_CMD] = "unsol cmd", \ + [FC_RCTL_DD_CMD_STATUS] = "cmd status", \ + [FC_RCTL_ELS_REQ] = "ELS req", \ + [FC_RCTL_ELS_REP] = "ELS rep", \ + [FC_RCTL_ELS4_REQ] = "FC-4 ELS req", \ + [FC_RCTL_ELS4_REP] = "FC-4 ELS rep", \ + [FC_RCTL_BA_NOP] = "BLS NOP", \ + [FC_RCTL_BA_ABTS] = "BLS abort", \ + [FC_RCTL_BA_RMC] = "BLS remove connection", \ + [FC_RCTL_BA_ACC] = "BLS accept", \ + [FC_RCTL_BA_RJT] = "BLS reject", \ + [FC_RCTL_BA_PRMT] = "BLS dedicated connection preempted", \ + [FC_RCTL_ACK_1] = "LC ACK_1", \ + [FC_RCTL_ACK_0] = "LC ACK_0", \ + [FC_RCTL_P_RJT] = "LC port reject", \ + [FC_RCTL_F_RJT] = "LC fabric reject", \ + [FC_RCTL_P_BSY] = "LC port busy", \ + [FC_RCTL_F_BSY] = "LC fabric busy to data frame", \ + [FC_RCTL_F_BSYL] = "LC fabric busy to link control frame",\ + [FC_RCTL_LCR] = "LC link credit reset", \ + [FC_RCTL_END] = "LC end", \ +} + +/* + * Well-known fabric addresses. + */ +enum fc_well_known_fid { + FC_FID_BCAST = 0xffffff, /* broadcast */ + FC_FID_FLOGI = 0xfffffe, /* fabric login */ + FC_FID_FCTRL = 0xfffffd, /* fabric controller */ + FC_FID_DIR_SERV = 0xfffffc, /* directory server */ + FC_FID_TIME_SERV = 0xfffffb, /* time server */ + FC_FID_MGMT_SERV = 0xfffffa, /* management server */ + FC_FID_QOS = 0xfffff9, /* QoS Facilitator */ + FC_FID_ALIASES = 0xfffff8, /* alias server (FC-PH2) */ + FC_FID_SEC_KEY = 0xfffff7, /* Security key dist. server */ + FC_FID_CLOCK = 0xfffff6, /* clock synch server */ + FC_FID_MCAST_SERV = 0xfffff5, /* multicast server */ +}; + +#define FC_FID_WELL_KNOWN_MAX 0xffffff /* highest well-known fabric ID */ +#define FC_FID_WELL_KNOWN_BASE 0xfffff5 /* start of well-known fabric ID */ + +/* + * Other well-known addresses, outside the above contiguous range. + */ +#define FC_FID_DOM_MGR 0xfffc00 /* domain manager base */ + +/* + * Fabric ID bytes. + */ +#define FC_FID_DOMAIN 0 +#define FC_FID_PORT 1 +#define FC_FID_LINK 2 + +/* + * fh_type codes + */ +enum fc_fh_type { + FC_TYPE_BLS = 0x00, /* basic link service */ + FC_TYPE_ELS = 0x01, /* extended link service */ + FC_TYPE_IP = 0x05, /* IP over FC, RFC 4338 */ + FC_TYPE_FCP = 0x08, /* SCSI FCP */ + FC_TYPE_CT = 0x20, /* Fibre Channel Services (FC-CT) */ + FC_TYPE_ILS = 0x22, /* internal link service */ +}; + +/* + * FC_TYPE names initializer. + * Please keep this matching the above definitions. + */ +#define FC_TYPE_NAMES_INIT { \ + [FC_TYPE_BLS] = "BLS", \ + [FC_TYPE_ELS] = "ELS", \ + [FC_TYPE_IP] = "IP", \ + [FC_TYPE_FCP] = "FCP", \ + [FC_TYPE_CT] = "CT", \ + [FC_TYPE_ILS] = "ILS", \ +} + +/* + * Exchange IDs. + */ +#define FC_XID_UNKNOWN 0xffff /* unknown exchange ID */ +#define FC_XID_MIN 0x0 /* supported min exchange ID */ +#define FC_XID_MAX 0xfffe /* supported max exchange ID */ + +/* + * fh_f_ctl - Frame control flags. + */ +#define FC_FC_EX_CTX (1 << 23) /* sent by responder to exchange */ +#define FC_FC_SEQ_CTX (1 << 22) /* sent by responder to sequence */ +#define FC_FC_FIRST_SEQ (1 << 21) /* first sequence of this exchange */ +#define FC_FC_LAST_SEQ (1 << 20) /* last sequence of this exchange */ +#define FC_FC_END_SEQ (1 << 19) /* last frame of sequence */ +#define FC_FC_END_CONN (1 << 18) /* end of class 1 connection pending */ +#define FC_FC_RES_B17 (1 << 17) /* reserved */ +#define FC_FC_SEQ_INIT (1 << 16) /* transfer of sequence initiative */ +#define FC_FC_X_ID_REASS (1 << 15) /* exchange ID has been changed */ +#define FC_FC_X_ID_INVAL (1 << 14) /* exchange ID invalidated */ + +#define FC_FC_ACK_1 (1 << 12) /* 13:12 = 1: ACK_1 expected */ +#define FC_FC_ACK_N (2 << 12) /* 13:12 = 2: ACK_N expected */ +#define FC_FC_ACK_0 (3 << 12) /* 13:12 = 3: ACK_0 expected */ + +#define FC_FC_RES_B11 (1 << 11) /* reserved */ +#define FC_FC_RES_B10 (1 << 10) /* reserved */ +#define FC_FC_RETX_SEQ (1 << 9) /* retransmitted sequence */ +#define FC_FC_UNI_TX (1 << 8) /* unidirectional transmit (class 1) */ +#define FC_FC_CONT_SEQ(i) ((i) << 6) +#define FC_FC_ABT_SEQ(i) ((i) << 4) +#define FC_FC_REL_OFF (1 << 3) /* parameter is relative offset */ +#define FC_FC_RES2 (1 << 2) /* reserved */ +#define FC_FC_FILL(i) ((i) & 3) /* 1:0: bytes of trailing fill */ + +/* + * BA_ACC payload. + */ +struct fc_ba_acc { + __u8 ba_seq_id_val; /* SEQ_ID validity */ +#define FC_BA_SEQ_ID_VAL 0x80 + __u8 ba_seq_id; /* SEQ_ID of seq last deliverable */ + __u8 ba_resvd[2]; /* reserved */ + __be16 ba_ox_id; /* OX_ID for aborted seq or exch */ + __be16 ba_rx_id; /* RX_ID for aborted seq or exch */ + __be16 ba_low_seq_cnt; /* low SEQ_CNT of aborted seq */ + __be16 ba_high_seq_cnt; /* high SEQ_CNT of aborted seq */ +}; + +/* + * BA_RJT: Basic Reject payload. + */ +struct fc_ba_rjt { + __u8 br_resvd; /* reserved */ + __u8 br_reason; /* reason code */ + __u8 br_explan; /* reason explanation */ + __u8 br_vendor; /* vendor unique code */ +}; + +/* + * BA_RJT reason codes. + * From FS-2. + */ +enum fc_ba_rjt_reason { + FC_BA_RJT_NONE = 0, /* in software this means no reject */ + FC_BA_RJT_INVL_CMD = 0x01, /* invalid command code */ + FC_BA_RJT_LOG_ERR = 0x03, /* logical error */ + FC_BA_RJT_LOG_BUSY = 0x05, /* logical busy */ + FC_BA_RJT_PROTO_ERR = 0x07, /* protocol error */ + FC_BA_RJT_UNABLE = 0x09, /* unable to perform request */ + FC_BA_RJT_VENDOR = 0xff, /* vendor-specific (see br_vendor) */ +}; + +/* + * BA_RJT reason code explanations. + */ +enum fc_ba_rjt_explan { + FC_BA_RJT_EXP_NONE = 0x00, /* no additional expanation */ + FC_BA_RJT_INV_XID = 0x03, /* invalid OX_ID-RX_ID combination */ + FC_BA_RJT_ABT = 0x05, /* sequence aborted, no seq info */ +}; + +/* + * P_RJT or F_RJT: Port Reject or Fabric Reject parameter field. + */ +struct fc_pf_rjt { + __u8 rj_action; /* reserved */ + __u8 rj_reason; /* reason code */ + __u8 rj_resvd; /* reserved */ + __u8 rj_vendor; /* vendor unique code */ +}; + +/* + * P_RJT and F_RJT reject reason codes. + */ +enum fc_pf_rjt_reason { + FC_RJT_NONE = 0, /* non-reject (reserved by standard) */ + FC_RJT_INVL_DID = 0x01, /* invalid destination ID */ + FC_RJT_INVL_SID = 0x02, /* invalid source ID */ + FC_RJT_P_UNAV_T = 0x03, /* port unavailable, temporary */ + FC_RJT_P_UNAV = 0x04, /* port unavailable, permanent */ + FC_RJT_CLS_UNSUP = 0x05, /* class not supported */ + FC_RJT_DEL_USAGE = 0x06, /* delimiter usage error */ + FC_RJT_TYPE_UNSUP = 0x07, /* type not supported */ + FC_RJT_LINK_CTL = 0x08, /* invalid link control */ + FC_RJT_R_CTL = 0x09, /* invalid R_CTL field */ + FC_RJT_F_CTL = 0x0a, /* invalid F_CTL field */ + FC_RJT_OX_ID = 0x0b, /* invalid originator exchange ID */ + FC_RJT_RX_ID = 0x0c, /* invalid responder exchange ID */ + FC_RJT_SEQ_ID = 0x0d, /* invalid sequence ID */ + FC_RJT_DF_CTL = 0x0e, /* invalid DF_CTL field */ + FC_RJT_SEQ_CNT = 0x0f, /* invalid SEQ_CNT field */ + FC_RJT_PARAM = 0x10, /* invalid parameter field */ + FC_RJT_EXCH_ERR = 0x11, /* exchange error */ + FC_RJT_PROTO = 0x12, /* protocol error */ + FC_RJT_LEN = 0x13, /* incorrect length */ + FC_RJT_UNEXP_ACK = 0x14, /* unexpected ACK */ + FC_RJT_FAB_CLASS = 0x15, /* class unsupported by fabric entity */ + FC_RJT_LOGI_REQ = 0x16, /* login required */ + FC_RJT_SEQ_XS = 0x17, /* excessive sequences attempted */ + FC_RJT_EXCH_EST = 0x18, /* unable to establish exchange */ + FC_RJT_FAB_UNAV = 0x1a, /* fabric unavailable */ + FC_RJT_VC_ID = 0x1b, /* invalid VC_ID (class 4) */ + FC_RJT_CS_CTL = 0x1c, /* invalid CS_CTL field */ + FC_RJT_INSUF_RES = 0x1d, /* insuff. resources for VC (Class 4) */ + FC_RJT_INVL_CLS = 0x1f, /* invalid class of service */ + FC_RJT_PREEMT_RJT = 0x20, /* preemption request rejected */ + FC_RJT_PREEMT_DIS = 0x21, /* preemption not enabled */ + FC_RJT_MCAST_ERR = 0x22, /* multicast error */ + FC_RJT_MCAST_ET = 0x23, /* multicast error terminate */ + FC_RJT_PRLI_REQ = 0x24, /* process login required */ + FC_RJT_INVL_ATT = 0x25, /* invalid attachment */ + FC_RJT_VENDOR = 0xff, /* vendor specific reject */ +}; + +#endif /* _FC_FS_H_ */ diff --git a/include/scsi/fc/fc_gs.h b/include/scsi/fc/fc_gs.h new file mode 100644 index 00000000000..ffab0272c65 --- /dev/null +++ b/include/scsi/fc/fc_gs.h @@ -0,0 +1,93 @@ +/* + * Copyright(c) 2007 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + * Maintained at www.Open-FCoE.org + */ + +#ifndef _FC_GS_H_ +#define _FC_GS_H_ + +/* + * Fibre Channel Services - Common Transport. + * From T11.org FC-GS-2 Rev 5.3 November 1998. + */ + +struct fc_ct_hdr { + __u8 ct_rev; /* revision */ + __u8 ct_in_id[3]; /* N_Port ID of original requestor */ + __u8 ct_fs_type; /* type of fibre channel service */ + __u8 ct_fs_subtype; /* subtype */ + __u8 ct_options; + __u8 _ct_resvd1; + __be16 ct_cmd; /* command / response code */ + __be16 ct_mr_size; /* maximum / residual size */ + __u8 _ct_resvd2; + __u8 ct_reason; /* reject reason */ + __u8 ct_explan; /* reason code explanation */ + __u8 ct_vendor; /* vendor unique data */ +}; + +#define FC_CT_HDR_LEN 16 /* expected sizeof (struct fc_ct_hdr) */ + +enum fc_ct_rev { + FC_CT_REV = 1 /* common transport revision */ +}; + +/* + * ct_fs_type values. + */ +enum fc_ct_fs_type { + FC_FST_ALIAS = 0xf8, /* alias service */ + FC_FST_MGMT = 0xfa, /* management service */ + FC_FST_TIME = 0xfb, /* time service */ + FC_FST_DIR = 0xfc, /* directory service */ +}; + +/* + * ct_cmd: Command / response codes + */ +enum fc_ct_cmd { + FC_FS_RJT = 0x8001, /* reject */ + FC_FS_ACC = 0x8002, /* accept */ +}; + +/* + * FS_RJT reason codes. + */ +enum fc_ct_reason { + FC_FS_RJT_CMD = 0x01, /* invalid command code */ + FC_FS_RJT_VER = 0x02, /* invalid version level */ + FC_FS_RJT_LOG = 0x03, /* logical error */ + FC_FS_RJT_IUSIZ = 0x04, /* invalid IU size */ + FC_FS_RJT_BSY = 0x05, /* logical busy */ + FC_FS_RJT_PROTO = 0x07, /* protocol error */ + FC_FS_RJT_UNABL = 0x09, /* unable to perform command request */ + FC_FS_RJT_UNSUP = 0x0b, /* command not supported */ +}; + +/* + * FS_RJT reason code explanations. + */ +enum fc_ct_explan { + FC_FS_EXP_NONE = 0x00, /* no additional explanation */ + FC_FS_EXP_PID = 0x01, /* port ID not registered */ + FC_FS_EXP_PNAM = 0x02, /* port name not registered */ + FC_FS_EXP_NNAM = 0x03, /* node name not registered */ + FC_FS_EXP_COS = 0x04, /* class of service not registered */ + /* definitions not complete */ +}; + +#endif /* _FC_GS_H_ */ diff --git a/include/scsi/fc/fc_ns.h b/include/scsi/fc/fc_ns.h new file mode 100644 index 00000000000..790d7b97d4b --- /dev/null +++ b/include/scsi/fc/fc_ns.h @@ -0,0 +1,159 @@ +/* + * Copyright(c) 2007 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + * Maintained at www.Open-FCoE.org + */ + +#ifndef _FC_NS_H_ +#define _FC_NS_H_ + +/* + * Fibre Channel Services - Name Service (dNS) + * From T11.org FC-GS-2 Rev 5.3 November 1998. + */ + +/* + * Common-transport sub-type for Name Server. + */ +#define FC_NS_SUBTYPE 2 /* fs_ct_hdr.ct_fs_subtype */ + +/* + * Name server Requests. + * Note: this is an incomplete list, some unused requests are omitted. + */ +enum fc_ns_req { + FC_NS_GA_NXT = 0x0100, /* get all next */ + FC_NS_GI_A = 0x0101, /* get identifiers - scope */ + FC_NS_GPN_ID = 0x0112, /* get port name by ID */ + FC_NS_GNN_ID = 0x0113, /* get node name by ID */ + FC_NS_GID_PN = 0x0121, /* get ID for port name */ + FC_NS_GID_NN = 0x0131, /* get IDs for node name */ + FC_NS_GID_FT = 0x0171, /* get IDs by FC4 type */ + FC_NS_GPN_FT = 0x0172, /* get port names by FC4 type */ + FC_NS_GID_PT = 0x01a1, /* get IDs by port type */ + FC_NS_RFT_ID = 0x0217, /* reg FC4 type for ID */ + FC_NS_RPN_ID = 0x0212, /* reg port name for ID */ + FC_NS_RNN_ID = 0x0213, /* reg node name for ID */ +}; + +/* + * Port type values. + */ +enum fc_ns_pt { + FC_NS_UNID_PORT = 0x00, /* unidentified */ + FC_NS_N_PORT = 0x01, /* N port */ + FC_NS_NL_PORT = 0x02, /* NL port */ + FC_NS_FNL_PORT = 0x03, /* F/NL port */ + FC_NS_NX_PORT = 0x7f, /* Nx port */ + FC_NS_F_PORT = 0x81, /* F port */ + FC_NS_FL_PORT = 0x82, /* FL port */ + FC_NS_E_PORT = 0x84, /* E port */ + FC_NS_B_PORT = 0x85, /* B port */ +}; + +/* + * Port type object. + */ +struct fc_ns_pt_obj { + __u8 pt_type; +}; + +/* + * Port ID object + */ +struct fc_ns_fid { + __u8 fp_flags; /* flags for responses only */ + __u8 fp_fid[3]; +}; + +/* + * fp_flags in port ID object, for responses only. + */ +#define FC_NS_FID_LAST 0x80 /* last object */ + +/* + * FC4-types object. + */ +#define FC_NS_TYPES 256 /* number of possible FC-4 types */ +#define FC_NS_BPW 32 /* bits per word in bitmap */ + +struct fc_ns_fts { + __be32 ff_type_map[FC_NS_TYPES / FC_NS_BPW]; /* bitmap of FC-4 types */ +}; + +/* + * GID_PT request. + */ +struct fc_ns_gid_pt { + __u8 fn_pt_type; + __u8 fn_domain_id_scope; + __u8 fn_area_id_scope; + __u8 fn_resvd; +}; + +/* + * GID_FT or GPN_FT request. + */ +struct fc_ns_gid_ft { + __u8 fn_resvd; + __u8 fn_domain_id_scope; + __u8 fn_area_id_scope; + __u8 fn_fc4_type; +}; + +/* + * GPN_FT response. + */ +struct fc_gpn_ft_resp { + __u8 fp_flags; /* see fp_flags definitions above */ + __u8 fp_fid[3]; /* port ID */ + __be32 fp_resvd; + __be64 fp_wwpn; /* port name */ +}; + +/* + * GID_PN request + */ +struct fc_ns_gid_pn { + __be64 fn_wwpn; /* port name */ +}; + +/* + * GID_PN response + */ +struct fc_gid_pn_resp { + __u8 fp_resvd; + __u8 fp_fid[3]; /* port ID */ +}; + +/* + * RFT_ID request - register FC-4 types for ID. + */ +struct fc_ns_rft_id { + struct fc_ns_fid fr_fid; /* port ID object */ + struct fc_ns_fts fr_fts; /* FC-4 types object */ +}; + +/* + * RPN_ID request - register port name for ID. + * RNN_ID request - register node name for ID. + */ +struct fc_ns_rn_id { + struct fc_ns_fid fr_fid; /* port ID object */ + __be64 fr_wwn; /* node name or port name */ +} __attribute__((__packed__)); + +#endif /* _FC_NS_H_ */ diff --git a/include/scsi/fc_encode.h b/include/scsi/fc_encode.h new file mode 100644 index 00000000000..6300f556bce --- /dev/null +++ b/include/scsi/fc_encode.h @@ -0,0 +1,309 @@ +/* + * Copyright(c) 2008 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + * Maintained at www.Open-FCoE.org + */ + +#ifndef _FC_ENCODE_H_ +#define _FC_ENCODE_H_ +#include <asm/unaligned.h> + +struct fc_ns_rft { + struct fc_ns_fid fid; /* port ID object */ + struct fc_ns_fts fts; /* FC4-types object */ +}; + +struct fc_ct_req { + struct fc_ct_hdr hdr; + union { + struct fc_ns_gid_ft gid; + struct fc_ns_rn_id rn; + struct fc_ns_rft rft; + } payload; +}; + +/** + * fill FC header fields in specified fc_frame + */ +static inline void fc_fill_fc_hdr(struct fc_frame *fp, enum fc_rctl r_ctl, + u32 did, u32 sid, enum fc_fh_type type, + u32 f_ctl, u32 parm_offset) +{ + struct fc_frame_header *fh; + + fh = fc_frame_header_get(fp); + WARN_ON(r_ctl == 0); + fh->fh_r_ctl = r_ctl; + hton24(fh->fh_d_id, did); + hton24(fh->fh_s_id, sid); + fh->fh_type = type; + hton24(fh->fh_f_ctl, f_ctl); + fh->fh_cs_ctl = 0; + fh->fh_df_ctl = 0; + fh->fh_parm_offset = htonl(parm_offset); +} + +/** + * fc_ct_hdr_fill- fills ct header and reset ct payload + * returns pointer to ct request. + */ +static inline struct fc_ct_req *fc_ct_hdr_fill(const struct fc_frame *fp, + unsigned int op, size_t req_size) +{ + struct fc_ct_req *ct; + size_t ct_plen; + + ct_plen = sizeof(struct fc_ct_hdr) + req_size; + ct = fc_frame_payload_get(fp, ct_plen); + memset(ct, 0, ct_plen); + ct->hdr.ct_rev = FC_CT_REV; + ct->hdr.ct_fs_type = FC_FST_DIR; + ct->hdr.ct_fs_subtype = FC_NS_SUBTYPE; + ct->hdr.ct_cmd = htons((u16) op); + return ct; +} + +/** + * fc_ct_fill - Fill in a name service request frame + */ +static inline int fc_ct_fill(struct fc_lport *lport, struct fc_frame *fp, + unsigned int op, enum fc_rctl *r_ctl, u32 *did, + enum fc_fh_type *fh_type) +{ + struct fc_ct_req *ct; + + switch (op) { + case FC_NS_GPN_FT: + ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_gid_ft)); + ct->payload.gid.fn_fc4_type = FC_TYPE_FCP; + break; + + case FC_NS_RFT_ID: + ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rft)); + hton24(ct->payload.rft.fid.fp_fid, + fc_host_port_id(lport->host)); + ct->payload.rft.fts = lport->fcts; + break; + + case FC_NS_RPN_ID: + ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rn_id)); + hton24(ct->payload.rn.fr_fid.fp_fid, + fc_host_port_id(lport->host)); + ct->payload.rft.fts = lport->fcts; + put_unaligned_be64(lport->wwpn, &ct->payload.rn.fr_wwn); + break; + + default: + FC_DBG("Invalid op code %x \n", op); + return -EINVAL; + } + *r_ctl = FC_RCTL_DD_UNSOL_CTL; + *did = FC_FID_DIR_SERV; + *fh_type = FC_TYPE_CT; + return 0; +} + +/** + * fc_plogi_fill - Fill in plogi request frame + */ +static inline void fc_plogi_fill(struct fc_lport *lport, struct fc_frame *fp, + unsigned int op) +{ + struct fc_els_flogi *plogi; + struct fc_els_csp *csp; + struct fc_els_cssp *cp; + + plogi = fc_frame_payload_get(fp, sizeof(*plogi)); + memset(plogi, 0, sizeof(*plogi)); + plogi->fl_cmd = (u8) op; + put_unaligned_be64(lport->wwpn, &plogi->fl_wwpn); + put_unaligned_be64(lport->wwnn, &plogi->fl_wwnn); + + csp = &plogi->fl_csp; + csp->sp_hi_ver = 0x20; + csp->sp_lo_ver = 0x20; + csp->sp_bb_cred = htons(10); /* this gets set by gateway */ + csp->sp_bb_data = htons((u16) lport->mfs); + cp = &plogi->fl_cssp[3 - 1]; /* class 3 parameters */ + cp->cp_class = htons(FC_CPC_VALID | FC_CPC_SEQ); + csp->sp_features = htons(FC_SP_FT_CIRO); + csp->sp_tot_seq = htons(255); /* seq. we accept */ + csp->sp_rel_off = htons(0x1f); + csp->sp_e_d_tov = htonl(lport->e_d_tov); + + cp->cp_rdfs = htons((u16) lport->mfs); + cp->cp_con_seq = htons(255); + cp->cp_open_seq = 1; +} + +/** + * fc_flogi_fill - Fill in a flogi request frame. + */ +static inline void fc_flogi_fill(struct fc_lport *lport, struct fc_frame *fp) +{ + struct fc_els_csp *sp; + struct fc_els_cssp *cp; + struct fc_els_flogi *flogi; + + flogi = fc_frame_payload_get(fp, sizeof(*flogi)); + memset(flogi, 0, sizeof(*flogi)); + flogi->fl_cmd = (u8) ELS_FLOGI; + put_unaligned_be64(lport->wwpn, &flogi->fl_wwpn); + put_unaligned_be64(lport->wwnn, &flogi->fl_wwnn); + sp = &flogi->fl_csp; + sp->sp_hi_ver = 0x20; + sp->sp_lo_ver = 0x20; + sp->sp_bb_cred = htons(10); /* this gets set by gateway */ + sp->sp_bb_data = htons((u16) lport->mfs); + cp = &flogi->fl_cssp[3 - 1]; /* class 3 parameters */ + cp->cp_class = htons(FC_CPC_VALID | FC_CPC_SEQ); +} + +/** + * fc_logo_fill - Fill in a logo request frame. + */ +static inline void fc_logo_fill(struct fc_lport *lport, struct fc_frame *fp) +{ + struct fc_els_logo *logo; + + logo = fc_frame_payload_get(fp, sizeof(*logo)); + memset(logo, 0, sizeof(*logo)); + logo->fl_cmd = ELS_LOGO; + hton24(logo->fl_n_port_id, fc_host_port_id(lport->host)); + logo->fl_n_port_wwn = htonll(lport->wwpn); +} + +/** + * fc_rtv_fill - Fill in RTV (read timeout value) request frame. + */ +static inline void fc_rtv_fill(struct fc_lport *lport, struct fc_frame *fp) +{ + struct fc_els_rtv *rtv; + + rtv = fc_frame_payload_get(fp, sizeof(*rtv)); + memset(rtv, 0, sizeof(*rtv)); + rtv->rtv_cmd = ELS_RTV; +} + +/** + * fc_rec_fill - Fill in rec request frame + */ +static inline void fc_rec_fill(struct fc_lport *lport, struct fc_frame *fp) +{ + struct fc_els_rec *rec; + struct fc_exch *ep = fc_seq_exch(fr_seq(fp)); + + rec = fc_frame_payload_get(fp, sizeof(*rec)); + memset(rec, 0, sizeof(*rec)); + rec->rec_cmd = ELS_REC; + hton24(rec->rec_s_id, fc_host_port_id(lport->host)); + rec->rec_ox_id = htons(ep->oxid); + rec->rec_rx_id = htons(ep->rxid); +} + +/** + * fc_prli_fill - Fill in prli request frame + */ +static inline void fc_prli_fill(struct fc_lport *lport, struct fc_frame *fp) +{ + struct { + struct fc_els_prli prli; + struct fc_els_spp spp; + } *pp; + + pp = fc_frame_payload_get(fp, sizeof(*pp)); + memset(pp, 0, sizeof(*pp)); + pp->prli.prli_cmd = ELS_PRLI; + pp->prli.prli_spp_len = sizeof(struct fc_els_spp); + pp->prli.prli_len = htons(sizeof(*pp)); + pp->spp.spp_type = FC_TYPE_FCP; + pp->spp.spp_flags = FC_SPP_EST_IMG_PAIR; + pp->spp.spp_params = htonl(lport->service_params); +} + +/** + * fc_scr_fill - Fill in a scr request frame. + */ +static inline void fc_scr_fill(struct fc_lport *lport, struct fc_frame *fp) +{ + struct fc_els_scr *scr; + + scr = fc_frame_payload_get(fp, sizeof(*scr)); + memset(scr, 0, sizeof(*scr)); + scr->scr_cmd = ELS_SCR; + scr->scr_reg_func = ELS_SCRF_FULL; +} + +/** + * fc_els_fill - Fill in an ELS request frame + */ +static inline int fc_els_fill(struct fc_lport *lport, struct fc_rport *rport, + struct fc_frame *fp, unsigned int op, + enum fc_rctl *r_ctl, u32 *did, enum fc_fh_type *fh_type) +{ + switch (op) { + case ELS_PLOGI: + fc_plogi_fill(lport, fp, ELS_PLOGI); + *did = rport->port_id; + break; + + case ELS_FLOGI: + fc_flogi_fill(lport, fp); + *did = FC_FID_FLOGI; + break; + + case ELS_LOGO: + fc_logo_fill(lport, fp); + *did = FC_FID_FLOGI; + /* + * if rport is valid then it + * is port logo, therefore + * set did to rport id. + */ + if (rport) + *did = rport->port_id; + break; + + case ELS_RTV: + fc_rtv_fill(lport, fp); + *did = rport->port_id; + break; + + case ELS_REC: + fc_rec_fill(lport, fp); + *did = rport->port_id; + break; + + case ELS_PRLI: + fc_prli_fill(lport, fp); + *did = rport->port_id; + break; + + case ELS_SCR: + fc_scr_fill(lport, fp); + *did = FC_FID_FCTRL; + break; + + default: + FC_DBG("Invalid op code %x \n", op); + return -EINVAL; + } + + *r_ctl = FC_RCTL_ELS_REQ; + *fh_type = FC_TYPE_ELS; + return 0; +} +#endif /* _FC_ENCODE_H_ */ diff --git a/include/scsi/fc_frame.h b/include/scsi/fc_frame.h new file mode 100644 index 00000000000..04d34a71355 --- /dev/null +++ b/include/scsi/fc_frame.h @@ -0,0 +1,242 @@ +/* + * Copyright(c) 2007 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + * Maintained at www.Open-FCoE.org + */ + +#ifndef _FC_FRAME_H_ +#define _FC_FRAME_H_ + +#include <linux/scatterlist.h> +#include <linux/skbuff.h> +#include <scsi/scsi_cmnd.h> + +#include <scsi/fc/fc_fs.h> +#include <scsi/fc/fc_fcp.h> +#include <scsi/fc/fc_encaps.h> + +/* + * The fc_frame interface is used to pass frame data between functions. + * The frame includes the data buffer, length, and SOF / EOF delimiter types. + * A pointer to the port structure of the receiving port is also includeded. + */ + +#define FC_FRAME_HEADROOM 32 /* headroom for VLAN + FCoE headers */ +#define FC_FRAME_TAILROOM 8 /* trailer space for FCoE */ + +/* + * Information about an individual fibre channel frame received or to be sent. + * The buffer may be in up to 4 additional non-contiguous sections, + * but the linear section must hold the frame header. + */ +#define FC_FRAME_SG_LEN 4 /* scatter/gather list maximum length */ + +#define fp_skb(fp) (&((fp)->skb)) +#define fr_hdr(fp) ((fp)->skb.data) +#define fr_len(fp) ((fp)->skb.len) +#define fr_cb(fp) ((struct fcoe_rcv_info *)&((fp)->skb.cb[0])) +#define fr_dev(fp) (fr_cb(fp)->fr_dev) +#define fr_seq(fp) (fr_cb(fp)->fr_seq) +#define fr_sof(fp) (fr_cb(fp)->fr_sof) +#define fr_eof(fp) (fr_cb(fp)->fr_eof) +#define fr_flags(fp) (fr_cb(fp)->fr_flags) +#define fr_max_payload(fp) (fr_cb(fp)->fr_max_payload) +#define fr_cmd(fp) (fr_cb(fp)->fr_cmd) +#define fr_dir(fp) (fr_cmd(fp)->sc_data_direction) +#define fr_crc(fp) (fr_cb(fp)->fr_crc) + +struct fc_frame { + struct sk_buff skb; +}; + +struct fcoe_rcv_info { + struct packet_type *ptype; + struct fc_lport *fr_dev; /* transport layer private pointer */ + struct fc_seq *fr_seq; /* for use with exchange manager */ + struct scsi_cmnd *fr_cmd; /* for use of scsi command */ + u32 fr_crc; + u16 fr_max_payload; /* max FC payload */ + enum fc_sof fr_sof; /* start of frame delimiter */ + enum fc_eof fr_eof; /* end of frame delimiter */ + u8 fr_flags; /* flags - see below */ +}; + + +/* + * Get fc_frame pointer for an skb that's already been imported. + */ +static inline struct fcoe_rcv_info *fcoe_dev_from_skb(const struct sk_buff *skb) +{ + BUILD_BUG_ON(sizeof(struct fcoe_rcv_info) > sizeof(skb->cb)); + return (struct fcoe_rcv_info *) skb->cb; +} + +/* + * fr_flags. + */ +#define FCPHF_CRC_UNCHECKED 0x01 /* CRC not computed, still appended */ + +/* + * Initialize a frame. + * We don't do a complete memset here for performance reasons. + * The caller must set fr_free, fr_hdr, fr_len, fr_sof, and fr_eof eventually. + */ +static inline void fc_frame_init(struct fc_frame *fp) +{ + fr_dev(fp) = NULL; + fr_seq(fp) = NULL; + fr_flags(fp) = 0; +} + +struct fc_frame *fc_frame_alloc_fill(struct fc_lport *, size_t payload_len); + +struct fc_frame *__fc_frame_alloc(size_t payload_len); + +/* + * Get frame for sending via port. + */ +static inline struct fc_frame *_fc_frame_alloc(struct fc_lport *dev, + size_t payload_len) +{ + return __fc_frame_alloc(payload_len); +} + +/* + * Allocate fc_frame structure and buffer. Set the initial length to + * payload_size + sizeof (struct fc_frame_header). + */ +static inline struct fc_frame *fc_frame_alloc(struct fc_lport *dev, size_t len) +{ + struct fc_frame *fp; + + /* + * Note: Since len will often be a constant multiple of 4, + * this check will usually be evaluated and eliminated at compile time. + */ + if ((len % 4) != 0) + fp = fc_frame_alloc_fill(dev, len); + else + fp = _fc_frame_alloc(dev, len); + return fp; +} + +/* + * Free the fc_frame structure and buffer. + */ +static inline void fc_frame_free(struct fc_frame *fp) +{ + kfree_skb(fp_skb(fp)); +} + +static inline int fc_frame_is_linear(struct fc_frame *fp) +{ + return !skb_is_nonlinear(fp_skb(fp)); +} + +/* + * Get frame header from message in fc_frame structure. + * This hides a cast and provides a place to add some checking. + */ +static inline +struct fc_frame_header *fc_frame_header_get(const struct fc_frame *fp) +{ + WARN_ON(fr_len(fp) < sizeof(struct fc_frame_header)); + return (struct fc_frame_header *) fr_hdr(fp); +} + +/* + * Get frame payload from message in fc_frame structure. + * This hides a cast and provides a place to add some checking. + * The len parameter is the minimum length for the payload portion. + * Returns NULL if the frame is too short. + * + * This assumes the interesting part of the payload is in the first part + * of the buffer for received data. This may not be appropriate to use for + * buffers being transmitted. + */ +static inline void *fc_frame_payload_get(const struct fc_frame *fp, + size_t len) +{ + void *pp = NULL; + + if (fr_len(fp) >= sizeof(struct fc_frame_header) + len) + pp = fc_frame_header_get(fp) + 1; + return pp; +} + +/* + * Get frame payload opcode (first byte) from message in fc_frame structure. + * This hides a cast and provides a place to add some checking. Return 0 + * if the frame has no payload. + */ +static inline u8 fc_frame_payload_op(const struct fc_frame *fp) +{ + u8 *cp; + + cp = fc_frame_payload_get(fp, sizeof(u8)); + if (!cp) + return 0; + return *cp; + +} + +/* + * Get FC class from frame. + */ +static inline enum fc_class fc_frame_class(const struct fc_frame *fp) +{ + return fc_sof_class(fr_sof(fp)); +} + +/* + * Check the CRC in a frame. + * The CRC immediately follows the last data item *AFTER* the length. + * The return value is zero if the CRC matches. + */ +u32 fc_frame_crc_check(struct fc_frame *); + +static inline u8 fc_frame_rctl(const struct fc_frame *fp) +{ + return fc_frame_header_get(fp)->fh_r_ctl; +} + +static inline bool fc_frame_is_cmd(const struct fc_frame *fp) +{ + return fc_frame_rctl(fp) == FC_RCTL_DD_UNSOL_CMD; +} + +static inline bool fc_frame_is_read(const struct fc_frame *fp) +{ + if (fc_frame_is_cmd(fp) && fr_cmd(fp)) + return fr_dir(fp) == DMA_FROM_DEVICE; + return false; +} + +static inline bool fc_frame_is_write(const struct fc_frame *fp) +{ + if (fc_frame_is_cmd(fp) && fr_cmd(fp)) + return fr_dir(fp) == DMA_TO_DEVICE; + return false; +} + +/* + * Check for leaks. + * Print the frame header of any currently allocated frame, assuming there + * should be none at this point. + */ +void fc_frame_leak_check(void); + +#endif /* _FC_FRAME_H_ */ diff --git a/include/scsi/fc_transport_fcoe.h b/include/scsi/fc_transport_fcoe.h new file mode 100644 index 00000000000..8dca2af14ff --- /dev/null +++ b/include/scsi/fc_transport_fcoe.h @@ -0,0 +1,54 @@ +#ifndef FC_TRANSPORT_FCOE_H +#define FC_TRANSPORT_FCOE_H + +#include <linux/device.h> +#include <linux/netdevice.h> +#include <scsi/scsi_host.h> +#include <scsi/libfc.h> + +/** + * struct fcoe_transport - FCoE transport struct for generic transport + * for Ethernet devices as well as pure HBAs + * + * @name: name for thsi transport + * @bus: physical bus type (pci_bus_type) + * @driver: physical bus driver for network device + * @create: entry create function + * @destroy: exit destroy function + * @list: list of transports + */ +struct fcoe_transport { + char *name; + unsigned short vendor; + unsigned short device; + struct bus_type *bus; + struct device_driver *driver; + int (*create)(struct net_device *device); + int (*destroy)(struct net_device *device); + bool (*match)(struct net_device *device); + struct list_head list; + struct list_head devlist; + struct mutex devlock; +}; + +/** + * MODULE_ALIAS_FCOE_PCI + * + * some care must be taken with this, vendor and device MUST be a hex value + * preceded with 0x and with letters in lower case (0x12ab, not 0x12AB or 12AB) + */ +#define MODULE_ALIAS_FCOE_PCI(vendor, device) \ + MODULE_ALIAS("fcoe-pci-" __stringify(vendor) "-" __stringify(device)) + +/* exported funcs */ +int fcoe_transport_attach(struct net_device *netdev); +int fcoe_transport_release(struct net_device *netdev); +int fcoe_transport_register(struct fcoe_transport *t); +int fcoe_transport_unregister(struct fcoe_transport *t); +int fcoe_load_transport_driver(struct net_device *netdev); +int __init fcoe_transport_init(void); +int __exit fcoe_transport_exit(void); + +/* fcow_sw is the default transport */ +extern struct fcoe_transport fcoe_sw_transport; +#endif /* FC_TRANSPORT_FCOE_H */ diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h index 0c9514de5df..d0ed5226f8c 100644 --- a/include/scsi/iscsi_if.h +++ b/include/scsi/iscsi_if.h @@ -333,8 +333,11 @@ enum iscsi_host_param { #define CAP_TEXT_NEGO 0x80 #define CAP_MARKERS 0x100 #define CAP_FW_DB 0x200 -#define CAP_SENDTARGETS_OFFLOAD 0x400 -#define CAP_DATA_PATH_OFFLOAD 0x800 +#define CAP_SENDTARGETS_OFFLOAD 0x400 /* offload discovery process */ +#define CAP_DATA_PATH_OFFLOAD 0x800 /* offload entire IO path */ +#define CAP_DIGEST_OFFLOAD 0x1000 /* offload hdr and data digests */ +#define CAP_PADDING_OFFLOAD 0x2000 /* offload padding insertion, removal, + and verification */ /* * These flags describes reason of stop_conn() call diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h new file mode 100644 index 00000000000..9f2876397dd --- /dev/null +++ b/include/scsi/libfc.h @@ -0,0 +1,938 @@ +/* + * Copyright(c) 2007 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + * Maintained at www.Open-FCoE.org + */ + +#ifndef _LIBFC_H_ +#define _LIBFC_H_ + +#include <linux/timer.h> +#include <linux/if.h> + +#include <scsi/scsi_transport.h> +#include <scsi/scsi_transport_fc.h> + +#include <scsi/fc/fc_fcp.h> +#include <scsi/fc/fc_ns.h> +#include <scsi/fc/fc_els.h> +#include <scsi/fc/fc_gs.h> + +#include <scsi/fc_frame.h> + +#define LIBFC_DEBUG + +#ifdef LIBFC_DEBUG +/* Log messages */ +#define FC_DBG(fmt, args...) \ + do { \ + printk(KERN_INFO "%s " fmt, __func__, ##args); \ + } while (0) +#else +#define FC_DBG(fmt, args...) +#endif + +/* + * libfc error codes + */ +#define FC_NO_ERR 0 /* no error */ +#define FC_EX_TIMEOUT 1 /* Exchange timeout */ +#define FC_EX_CLOSED 2 /* Exchange closed */ + +/* some helpful macros */ + +#define ntohll(x) be64_to_cpu(x) +#define htonll(x) cpu_to_be64(x) + +#define ntoh24(p) (((p)[0] << 16) | ((p)[1] << 8) | ((p)[2])) + +#define hton24(p, v) do { \ + p[0] = (((v) >> 16) & 0xFF); \ + p[1] = (((v) >> 8) & 0xFF); \ + p[2] = ((v) & 0xFF); \ + } while (0) + +/* + * FC HBA status + */ +#define FC_PAUSE (1 << 1) +#define FC_LINK_UP (1 << 0) + +enum fc_lport_state { + LPORT_ST_NONE = 0, + LPORT_ST_FLOGI, + LPORT_ST_DNS, + LPORT_ST_RPN_ID, + LPORT_ST_RFT_ID, + LPORT_ST_SCR, + LPORT_ST_READY, + LPORT_ST_LOGO, + LPORT_ST_RESET +}; + +enum fc_disc_event { + DISC_EV_NONE = 0, + DISC_EV_SUCCESS, + DISC_EV_FAILED +}; + +enum fc_rport_state { + RPORT_ST_NONE = 0, + RPORT_ST_INIT, /* initialized */ + RPORT_ST_PLOGI, /* waiting for PLOGI completion */ + RPORT_ST_PRLI, /* waiting for PRLI completion */ + RPORT_ST_RTV, /* waiting for RTV completion */ + RPORT_ST_READY, /* ready for use */ + RPORT_ST_LOGO, /* port logout sent */ +}; + +enum fc_rport_trans_state { + FC_PORTSTATE_ROGUE, + FC_PORTSTATE_REAL, +}; + +/** + * struct fc_disc_port - temporary discovery port to hold rport identifiers + * @lp: Fibre Channel host port instance + * @peers: node for list management during discovery and RSCN processing + * @ids: identifiers structure to pass to fc_remote_port_add() + * @rport_work: work struct for starting the rport state machine + */ +struct fc_disc_port { + struct fc_lport *lp; + struct list_head peers; + struct fc_rport_identifiers ids; + struct work_struct rport_work; +}; + +enum fc_rport_event { + RPORT_EV_NONE = 0, + RPORT_EV_CREATED, + RPORT_EV_FAILED, + RPORT_EV_STOP, + RPORT_EV_LOGO +}; + +struct fc_rport_operations { + void (*event_callback)(struct fc_lport *, struct fc_rport *, + enum fc_rport_event); +}; + +/** + * struct fc_rport_libfc_priv - libfc internal information about a remote port + * @local_port: Fibre Channel host port instance + * @rp_state: state tracks progress of PLOGI, PRLI, and RTV exchanges + * @flags: REC and RETRY supported flags + * @max_seq: maximum number of concurrent sequences + * @retries: retry count in current state + * @e_d_tov: error detect timeout value (in msec) + * @r_a_tov: resource allocation timeout value (in msec) + * @rp_mutex: mutex protects rport + * @retry_work: + * @event_callback: Callback for rport READY, FAILED or LOGO + */ +struct fc_rport_libfc_priv { + struct fc_lport *local_port; + enum fc_rport_state rp_state; + u16 flags; + #define FC_RP_FLAGS_REC_SUPPORTED (1 << 0) + #define FC_RP_FLAGS_RETRY (1 << 1) + u16 max_seq; + unsigned int retries; + unsigned int e_d_tov; + unsigned int r_a_tov; + enum fc_rport_trans_state trans_state; + struct mutex rp_mutex; + struct delayed_work retry_work; + enum fc_rport_event event; + struct fc_rport_operations *ops; + struct list_head peers; + struct work_struct event_work; +}; + +#define PRIV_TO_RPORT(x) \ + (struct fc_rport *)((void *)x - sizeof(struct fc_rport)); +#define RPORT_TO_PRIV(x) \ + (struct fc_rport_libfc_priv *)((void *)x + sizeof(struct fc_rport)); + +struct fc_rport *fc_rport_rogue_create(struct fc_disc_port *); + +static inline void fc_rport_set_name(struct fc_rport *rport, u64 wwpn, u64 wwnn) +{ + rport->node_name = wwnn; + rport->port_name = wwpn; +} + +/* + * fcoe stats structure + */ +struct fcoe_dev_stats { + u64 SecondsSinceLastReset; + u64 TxFrames; + u64 TxWords; + u64 RxFrames; + u64 RxWords; + u64 ErrorFrames; + u64 DumpedFrames; + u64 LinkFailureCount; + u64 LossOfSignalCount; + u64 InvalidTxWordCount; + u64 InvalidCRCCount; + u64 InputRequests; + u64 OutputRequests; + u64 ControlRequests; + u64 InputMegabytes; + u64 OutputMegabytes; +}; + +/* + * els data is used for passing ELS respone specific + * data to send ELS response mainly using infomation + * in exchange and sequence in EM layer. + */ +struct fc_seq_els_data { + struct fc_frame *fp; + enum fc_els_rjt_reason reason; + enum fc_els_rjt_explan explan; +}; + +/* + * FCP request structure, one for each scsi cmd request + */ +struct fc_fcp_pkt { + /* + * housekeeping stuff + */ + struct fc_lport *lp; /* handle to hba struct */ + u16 state; /* scsi_pkt state state */ + u16 tgt_flags; /* target flags */ + atomic_t ref_cnt; /* fcp pkt ref count */ + spinlock_t scsi_pkt_lock; /* Must be taken before the host lock + * if both are held at the same time */ + /* + * SCSI I/O related stuff + */ + struct scsi_cmnd *cmd; /* scsi command pointer. set/clear + * under host lock */ + struct list_head list; /* tracks queued commands. access under + * host lock */ + /* + * timeout related stuff + */ + struct timer_list timer; /* command timer */ + struct completion tm_done; + int wait_for_comp; + unsigned long start_time; /* start jiffie */ + unsigned long end_time; /* end jiffie */ + unsigned long last_pkt_time; /* jiffies of last frame received */ + + /* + * scsi cmd and data transfer information + */ + u32 data_len; + /* + * transport related veriables + */ + struct fcp_cmnd cdb_cmd; + size_t xfer_len; + u32 xfer_contig_end; /* offset of end of contiguous xfer */ + u16 max_payload; /* max payload size in bytes */ + + /* + * scsi/fcp return status + */ + u32 io_status; /* SCSI result upper 24 bits */ + u8 cdb_status; + u8 status_code; /* FCP I/O status */ + /* bit 3 Underrun bit 2: overrun */ + u8 scsi_comp_flags; + u32 req_flags; /* bit 0: read bit:1 write */ + u32 scsi_resid; /* residule length */ + + struct fc_rport *rport; /* remote port pointer */ + struct fc_seq *seq_ptr; /* current sequence pointer */ + /* + * Error Processing + */ + u8 recov_retry; /* count of recovery retries */ + struct fc_seq *recov_seq; /* sequence for REC or SRR */ +}; + +/* + * Structure and function definitions for managing Fibre Channel Exchanges + * and Sequences + * + * fc_exch holds state for one exchange and links to its active sequence. + * + * fc_seq holds the state for an individual sequence. + */ + +struct fc_exch_mgr; + +/* + * Sequence. + */ +struct fc_seq { + u8 id; /* seq ID */ + u16 ssb_stat; /* status flags for sequence status block */ + u16 cnt; /* frames sent so far on sequence */ + u32 rec_data; /* FC-4 value for REC */ +}; + +#define FC_EX_DONE (1 << 0) /* ep is completed */ +#define FC_EX_RST_CLEANUP (1 << 1) /* reset is forcing completion */ + +/* + * Exchange. + * + * Locking notes: The ex_lock protects following items: + * state, esb_stat, f_ctl, seq.ssb_stat + * seq_id + * sequence allocation + */ +struct fc_exch { + struct fc_exch_mgr *em; /* exchange manager */ + u32 state; /* internal driver state */ + u16 xid; /* our exchange ID */ + struct list_head ex_list; /* free or busy list linkage */ + spinlock_t ex_lock; /* lock covering exchange state */ + atomic_t ex_refcnt; /* reference counter */ + struct delayed_work timeout_work; /* timer for upper level protocols */ + struct fc_lport *lp; /* fc device instance */ + u16 oxid; /* originator's exchange ID */ + u16 rxid; /* responder's exchange ID */ + u32 oid; /* originator's FCID */ + u32 sid; /* source FCID */ + u32 did; /* destination FCID */ + u32 esb_stat; /* exchange status for ESB */ + u32 r_a_tov; /* r_a_tov from rport (msec) */ + u8 seq_id; /* next sequence ID to use */ + u32 f_ctl; /* F_CTL flags for sequences */ + u8 fh_type; /* frame type */ + enum fc_class class; /* class of service */ + struct fc_seq seq; /* single sequence */ + /* + * Handler for responses to this current exchange. + */ + void (*resp)(struct fc_seq *, struct fc_frame *, void *); + void (*destructor)(struct fc_seq *, void *); + /* + * arg is passed as void pointer to exchange + * resp and destructor handlers + */ + void *arg; +}; +#define fc_seq_exch(sp) container_of(sp, struct fc_exch, seq) + +struct libfc_function_template { + + /** + * Mandatory Fields + * + * These handlers must be implemented by the LLD. + */ + + /* + * Interface to send a FC frame + */ + int (*frame_send)(struct fc_lport *lp, struct fc_frame *fp); + + /** + * Optional Fields + * + * The LLD may choose to implement any of the following handlers. + * If LLD doesn't specify hander and leaves its pointer NULL then + * the default libfc function will be used for that handler. + */ + + /** + * ELS/CT interfaces + */ + + /* + * elsct_send - sends ELS/CT frame + */ + struct fc_seq *(*elsct_send)(struct fc_lport *lport, + struct fc_rport *rport, + struct fc_frame *fp, + unsigned int op, + void (*resp)(struct fc_seq *, + struct fc_frame *fp, + void *arg), + void *arg, u32 timer_msec); + /** + * Exhance Manager interfaces + */ + + /* + * Send the FC frame payload using a new exchange and sequence. + * + * The frame pointer with some of the header's fields must be + * filled before calling exch_seq_send(), those fields are, + * + * - routing control + * - FC port did + * - FC port sid + * - FC header type + * - frame control + * - parameter or relative offset + * + * The exchange response handler is set in this routine to resp() + * function pointer. It can be called in two scenarios: if a timeout + * occurs or if a response frame is received for the exchange. The + * fc_frame pointer in response handler will also indicate timeout + * as error using IS_ERR related macros. + * + * The exchange destructor handler is also set in this routine. + * The destructor handler is invoked by EM layer when exchange + * is about to free, this can be used by caller to free its + * resources along with exchange free. + * + * The arg is passed back to resp and destructor handler. + * + * The timeout value (in msec) for an exchange is set if non zero + * timer_msec argument is specified. The timer is canceled when + * it fires or when the exchange is done. The exchange timeout handler + * is registered by EM layer. + */ + struct fc_seq *(*exch_seq_send)(struct fc_lport *lp, + struct fc_frame *fp, + void (*resp)(struct fc_seq *sp, + struct fc_frame *fp, + void *arg), + void (*destructor)(struct fc_seq *sp, + void *arg), + void *arg, unsigned int timer_msec); + + /* + * send a frame using existing sequence and exchange. + */ + int (*seq_send)(struct fc_lport *lp, struct fc_seq *sp, + struct fc_frame *fp); + + /* + * Send ELS response using mainly infomation + * in exchange and sequence in EM layer. + */ + void (*seq_els_rsp_send)(struct fc_seq *sp, enum fc_els_cmd els_cmd, + struct fc_seq_els_data *els_data); + + /* + * Abort an exchange and sequence. Generally called because of a + * exchange timeout or an abort from the upper layer. + * + * A timer_msec can be specified for abort timeout, if non-zero + * timer_msec value is specified then exchange resp handler + * will be called with timeout error if no response to abort. + */ + int (*seq_exch_abort)(const struct fc_seq *req_sp, + unsigned int timer_msec); + + /* + * Indicate that an exchange/sequence tuple is complete and the memory + * allocated for the related objects may be freed. + */ + void (*exch_done)(struct fc_seq *sp); + + /* + * Assigns a EM and a free XID for an new exchange and then + * allocates a new exchange and sequence pair. + * The fp can be used to determine free XID. + */ + struct fc_exch *(*exch_get)(struct fc_lport *lp, struct fc_frame *fp); + + /* + * Release previously assigned XID by exch_get API. + * The LLD may implement this if XID is assigned by LLD + * in exch_get(). + */ + void (*exch_put)(struct fc_lport *lp, struct fc_exch_mgr *mp, + u16 ex_id); + + /* + * Start a new sequence on the same exchange/sequence tuple. + */ + struct fc_seq *(*seq_start_next)(struct fc_seq *sp); + + /* + * Reset an exchange manager, completing all sequences and exchanges. + * If s_id is non-zero, reset only exchanges originating from that FID. + * If d_id is non-zero, reset only exchanges sending to that FID. + */ + void (*exch_mgr_reset)(struct fc_exch_mgr *, + u32 s_id, u32 d_id); + + void (*rport_flush_queue)(void); + /** + * Local Port interfaces + */ + + /* + * Receive a frame to a local port. + */ + void (*lport_recv)(struct fc_lport *lp, struct fc_seq *sp, + struct fc_frame *fp); + + int (*lport_reset)(struct fc_lport *); + + /** + * Remote Port interfaces + */ + + /* + * Initiates the RP state machine. It is called from the LP module. + * This function will issue the following commands to the N_Port + * identified by the FC ID provided. + * + * - PLOGI + * - PRLI + * - RTV + */ + int (*rport_login)(struct fc_rport *rport); + + /* + * Logoff, and remove the rport from the transport if + * it had been added. This will send a LOGO to the target. + */ + int (*rport_logoff)(struct fc_rport *rport); + + /* + * Recieve a request from a remote port. + */ + void (*rport_recv_req)(struct fc_seq *, struct fc_frame *, + struct fc_rport *); + + struct fc_rport *(*rport_lookup)(const struct fc_lport *, u32); + + /** + * FCP interfaces + */ + + /* + * Send a fcp cmd from fsp pkt. + * Called with the SCSI host lock unlocked and irqs disabled. + * + * The resp handler is called when FCP_RSP received. + * + */ + int (*fcp_cmd_send)(struct fc_lport *lp, struct fc_fcp_pkt *fsp, + void (*resp)(struct fc_seq *, struct fc_frame *fp, + void *arg)); + + /* + * Used at least durring linkdown and reset + */ + void (*fcp_cleanup)(struct fc_lport *lp); + + /* + * Abort all I/O on a local port + */ + void (*fcp_abort_io)(struct fc_lport *lp); + + /** + * Discovery interfaces + */ + + void (*disc_recv_req)(struct fc_seq *, + struct fc_frame *, struct fc_lport *); + + /* + * Start discovery for a local port. + */ + void (*disc_start)(void (*disc_callback)(struct fc_lport *, + enum fc_disc_event), + struct fc_lport *); + + /* + * Stop discovery for a given lport. This will remove + * all discovered rports + */ + void (*disc_stop) (struct fc_lport *); + + /* + * Stop discovery for a given lport. This will block + * until all discovered rports are deleted from the + * FC transport class + */ + void (*disc_stop_final) (struct fc_lport *); +}; + +/* information used by the discovery layer */ +struct fc_disc { + unsigned char retry_count; + unsigned char delay; + unsigned char pending; + unsigned char requested; + unsigned short seq_count; + unsigned char buf_len; + enum fc_disc_event event; + + void (*disc_callback)(struct fc_lport *, + enum fc_disc_event); + + struct list_head rports; + struct fc_lport *lport; + struct mutex disc_mutex; + struct fc_gpn_ft_resp partial_buf; /* partial name buffer */ + struct delayed_work disc_work; +}; + +struct fc_lport { + struct list_head list; + + /* Associations */ + struct Scsi_Host *host; + struct fc_exch_mgr *emp; + struct fc_rport *dns_rp; + struct fc_rport *ptp_rp; + void *scsi_priv; + struct fc_disc disc; + + /* Operational Information */ + struct libfc_function_template tt; + u16 link_status; + enum fc_lport_state state; + unsigned long boot_time; + + struct fc_host_statistics host_stats; + struct fcoe_dev_stats *dev_stats[NR_CPUS]; + u64 wwpn; + u64 wwnn; + u8 retry_count; + + /* Capabilities */ + u32 sg_supp:1; /* scatter gather supported */ + u32 seq_offload:1; /* seq offload supported */ + u32 crc_offload:1; /* crc offload supported */ + u32 lro_enabled:1; /* large receive offload */ + u32 mfs; /* max FC payload size */ + unsigned int service_params; + unsigned int e_d_tov; + unsigned int r_a_tov; + u8 max_retry_count; + u16 link_speed; + u16 link_supported_speeds; + u16 lro_xid; /* max xid for fcoe lro */ + struct fc_ns_fts fcts; /* FC-4 type masks */ + struct fc_els_rnid_gen rnid_gen; /* RNID information */ + + /* Semaphores */ + struct mutex lp_mutex; + + /* Miscellaneous */ + struct delayed_work retry_work; + struct delayed_work disc_work; +}; + +/** + * FC_LPORT HELPER FUNCTIONS + *****************************/ +static inline void *lport_priv(const struct fc_lport *lp) +{ + return (void *)(lp + 1); +} + +static inline int fc_lport_test_ready(struct fc_lport *lp) +{ + return lp->state == LPORT_ST_READY; +} + +static inline void fc_set_wwnn(struct fc_lport *lp, u64 wwnn) +{ + lp->wwnn = wwnn; +} + +static inline void fc_set_wwpn(struct fc_lport *lp, u64 wwnn) +{ + lp->wwpn = wwnn; +} + +static inline void fc_lport_state_enter(struct fc_lport *lp, + enum fc_lport_state state) +{ + if (state != lp->state) + lp->retry_count = 0; + lp->state = state; +} + + +/** + * LOCAL PORT LAYER + *****************************/ +int fc_lport_init(struct fc_lport *lp); + +/* + * Destroy the specified local port by finding and freeing all + * fc_rports associated with it and then by freeing the fc_lport + * itself. + */ +int fc_lport_destroy(struct fc_lport *lp); + +/* + * Logout the specified local port from the fabric + */ +int fc_fabric_logoff(struct fc_lport *lp); + +/* + * Initiate the LP state machine. This handler will use fc_host_attr + * to store the FLOGI service parameters, so fc_host_attr must be + * initialized before calling this handler. + */ +int fc_fabric_login(struct fc_lport *lp); + +/* + * The link is up for the given local port. + */ +void fc_linkup(struct fc_lport *); + +/* + * Link is down for the given local port. + */ +void fc_linkdown(struct fc_lport *); + +/* + * Pause and unpause traffic. + */ +void fc_pause(struct fc_lport *); +void fc_unpause(struct fc_lport *); + +/* + * Configure the local port. + */ +int fc_lport_config(struct fc_lport *); + +/* + * Reset the local port. + */ +int fc_lport_reset(struct fc_lport *); + +/* + * Set the mfs or reset + */ +int fc_set_mfs(struct fc_lport *lp, u32 mfs); + + +/** + * REMOTE PORT LAYER + *****************************/ +int fc_rport_init(struct fc_lport *lp); +void fc_rport_terminate_io(struct fc_rport *rp); + +/** + * DISCOVERY LAYER + *****************************/ +int fc_disc_init(struct fc_lport *lp); + + +/** + * SCSI LAYER + *****************************/ +/* + * Initialize the SCSI block of libfc + */ +int fc_fcp_init(struct fc_lport *); + +/* + * This section provides an API which allows direct interaction + * with the SCSI-ml. Each of these functions satisfies a function + * pointer defined in Scsi_Host and therefore is always called + * directly from the SCSI-ml. + */ +int fc_queuecommand(struct scsi_cmnd *sc_cmd, + void (*done)(struct scsi_cmnd *)); + +/* + * complete processing of a fcp packet + * + * This function may sleep if a fsp timer is pending. + * The host lock must not be held by caller. + */ +void fc_fcp_complete(struct fc_fcp_pkt *fsp); + +/* + * Send an ABTS frame to the target device. The sc_cmd argument + * is a pointer to the SCSI command to be aborted. + */ +int fc_eh_abort(struct scsi_cmnd *sc_cmd); + +/* + * Reset a LUN by sending send the tm cmd to the target. + */ +int fc_eh_device_reset(struct scsi_cmnd *sc_cmd); + +/* + * Reset the host adapter. + */ +int fc_eh_host_reset(struct scsi_cmnd *sc_cmd); + +/* + * Check rport status. + */ +int fc_slave_alloc(struct scsi_device *sdev); + +/* + * Adjust the queue depth. + */ +int fc_change_queue_depth(struct scsi_device *sdev, int qdepth); + +/* + * Change the tag type. + */ +int fc_change_queue_type(struct scsi_device *sdev, int tag_type); + +/* + * Free memory pools used by the FCP layer. + */ +void fc_fcp_destroy(struct fc_lport *); + +/** + * ELS/CT interface + *****************************/ +/* + * Initializes ELS/CT interface + */ +int fc_elsct_init(struct fc_lport *lp); + + +/** + * EXCHANGE MANAGER LAYER + *****************************/ +/* + * Initializes Exchange Manager related + * function pointers in struct libfc_function_template. + */ +int fc_exch_init(struct fc_lport *lp); + +/* + * Allocates an Exchange Manager (EM). + * + * The EM manages exchanges for their allocation and + * free, also allows exchange lookup for received + * frame. + * + * The class is used for initializing FC class of + * allocated exchange from EM. + * + * The min_xid and max_xid will limit new + * exchange ID (XID) within this range for + * a new exchange. + * The LLD may choose to have multiple EMs, + * e.g. one EM instance per CPU receive thread in LLD. + * The LLD can use exch_get() of struct libfc_function_template + * to specify XID for a new exchange within + * a specified EM instance. + * + * The em_idx to uniquely identify an EM instance. + */ +struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp, + enum fc_class class, + u16 min_xid, + u16 max_xid); + +/* + * Free an exchange manager. + */ +void fc_exch_mgr_free(struct fc_exch_mgr *mp); + +/* + * Receive a frame on specified local port and exchange manager. + */ +void fc_exch_recv(struct fc_lport *lp, struct fc_exch_mgr *mp, + struct fc_frame *fp); + +/* + * This function is for exch_seq_send function pointer in + * struct libfc_function_template, see comment block on + * exch_seq_send for description of this function. + */ +struct fc_seq *fc_exch_seq_send(struct fc_lport *lp, + struct fc_frame *fp, + void (*resp)(struct fc_seq *sp, + struct fc_frame *fp, + void *arg), + void (*destructor)(struct fc_seq *sp, + void *arg), + void *arg, u32 timer_msec); + +/* + * send a frame using existing sequence and exchange. + */ +int fc_seq_send(struct fc_lport *lp, struct fc_seq *sp, struct fc_frame *fp); + +/* + * Send ELS response using mainly infomation + * in exchange and sequence in EM layer. + */ +void fc_seq_els_rsp_send(struct fc_seq *sp, enum fc_els_cmd els_cmd, + struct fc_seq_els_data *els_data); + +/* + * This function is for seq_exch_abort function pointer in + * struct libfc_function_template, see comment block on + * seq_exch_abort for description of this function. + */ +int fc_seq_exch_abort(const struct fc_seq *req_sp, unsigned int timer_msec); + +/* + * Indicate that an exchange/sequence tuple is complete and the memory + * allocated for the related objects may be freed. + */ +void fc_exch_done(struct fc_seq *sp); + +/* + * Assigns a EM and XID for a frame and then allocates + * a new exchange and sequence pair. + * The fp can be used to determine free XID. + */ +struct fc_exch *fc_exch_get(struct fc_lport *lp, struct fc_frame *fp); + +/* + * Allocate a new exchange and sequence pair. + * if ex_id is zero then next free exchange id + * from specified exchange manger mp will be assigned. + */ +struct fc_exch *fc_exch_alloc(struct fc_exch_mgr *mp, + struct fc_frame *fp, u16 ex_id); +/* + * Start a new sequence on the same exchange as the supplied sequence. + */ +struct fc_seq *fc_seq_start_next(struct fc_seq *sp); + +/* + * Reset an exchange manager, completing all sequences and exchanges. + * If s_id is non-zero, reset only exchanges originating from that FID. + * If d_id is non-zero, reset only exchanges sending to that FID. + */ +void fc_exch_mgr_reset(struct fc_exch_mgr *, u32 s_id, u32 d_id); + +/* + * Functions for fc_functions_template + */ +void fc_get_host_speed(struct Scsi_Host *shost); +void fc_get_host_port_type(struct Scsi_Host *shost); +void fc_get_host_port_state(struct Scsi_Host *shost); +void fc_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout); +struct fc_host_statistics *fc_get_host_stats(struct Scsi_Host *); + +/* + * module setup functions. + */ +int fc_setup_exch_mgr(void); +void fc_destroy_exch_mgr(void); +int fc_setup_rport(void); +void fc_destroy_rport(void); + +#endif /* _LIBFC_H_ */ diff --git a/include/scsi/libfcoe.h b/include/scsi/libfcoe.h new file mode 100644 index 00000000000..89fdbb9a6a1 --- /dev/null +++ b/include/scsi/libfcoe.h @@ -0,0 +1,176 @@ +/* + * Copyright(c) 2007 - 2008 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + * Maintained at www.Open-FCoE.org + */ + +#ifndef _LIBFCOE_H +#define _LIBFCOE_H + +#include <linux/netdevice.h> +#include <linux/skbuff.h> +#include <scsi/fc/fc_fcoe.h> +#include <scsi/libfc.h> + +/* + * this percpu struct for fcoe + */ +struct fcoe_percpu_s { + int cpu; + struct task_struct *thread; + struct sk_buff_head fcoe_rx_list; + struct page *crc_eof_page; + int crc_eof_offset; +}; + +/* + * the fcoe sw transport private data + */ +struct fcoe_softc { + struct list_head list; + struct fc_lport *lp; + struct net_device *real_dev; + struct net_device *phys_dev; /* device with ethtool_ops */ + struct packet_type fcoe_packet_type; + struct sk_buff_head fcoe_pending_queue; + + u8 dest_addr[ETH_ALEN]; + u8 ctl_src_addr[ETH_ALEN]; + u8 data_src_addr[ETH_ALEN]; + /* + * fcoe protocol address learning related stuff + */ + u16 flogi_oxid; + u8 flogi_progress; + u8 address_mode; +}; + +static inline struct fcoe_softc *fcoe_softc( + const struct fc_lport *lp) +{ + return (struct fcoe_softc *)lport_priv(lp); +} + +static inline struct net_device *fcoe_netdev( + const struct fc_lport *lp) +{ + return fcoe_softc(lp)->real_dev; +} + +static inline struct fcoe_hdr *skb_fcoe_header(const struct sk_buff *skb) +{ + return (struct fcoe_hdr *)skb_network_header(skb); +} + +static inline int skb_fcoe_offset(const struct sk_buff *skb) +{ + return skb_network_offset(skb); +} + +static inline struct fc_frame_header *skb_fc_header(const struct sk_buff *skb) +{ + return (struct fc_frame_header *)skb_transport_header(skb); +} + +static inline int skb_fc_offset(const struct sk_buff *skb) +{ + return skb_transport_offset(skb); +} + +static inline void skb_reset_fc_header(struct sk_buff *skb) +{ + skb_reset_network_header(skb); + skb_set_transport_header(skb, skb_network_offset(skb) + + sizeof(struct fcoe_hdr)); +} + +static inline bool skb_fc_is_data(const struct sk_buff *skb) +{ + return skb_fc_header(skb)->fh_r_ctl == FC_RCTL_DD_SOL_DATA; +} + +static inline bool skb_fc_is_cmd(const struct sk_buff *skb) +{ + return skb_fc_header(skb)->fh_r_ctl == FC_RCTL_DD_UNSOL_CMD; +} + +static inline bool skb_fc_has_exthdr(const struct sk_buff *skb) +{ + return (skb_fc_header(skb)->fh_r_ctl == FC_RCTL_VFTH) || + (skb_fc_header(skb)->fh_r_ctl == FC_RCTL_IFRH) || + (skb_fc_header(skb)->fh_r_ctl == FC_RCTL_ENCH); +} + +static inline bool skb_fc_is_roff(const struct sk_buff *skb) +{ + return skb_fc_header(skb)->fh_f_ctl[2] & FC_FC_REL_OFF; +} + +static inline u16 skb_fc_oxid(const struct sk_buff *skb) +{ + return be16_to_cpu(skb_fc_header(skb)->fh_ox_id); +} + +static inline u16 skb_fc_rxid(const struct sk_buff *skb) +{ + return be16_to_cpu(skb_fc_header(skb)->fh_rx_id); +} + +/* FIXME - DMA_BIDIRECTIONAL ? */ +#define skb_cb(skb) ((struct fcoe_rcv_info *)&((skb)->cb[0])) +#define skb_cmd(skb) (skb_cb(skb)->fr_cmd) +#define skb_dir(skb) (skb_cmd(skb)->sc_data_direction) +static inline bool skb_fc_is_read(const struct sk_buff *skb) +{ + if (skb_fc_is_cmd(skb) && skb_cmd(skb)) + return skb_dir(skb) == DMA_FROM_DEVICE; + return false; +} + +static inline bool skb_fc_is_write(const struct sk_buff *skb) +{ + if (skb_fc_is_cmd(skb) && skb_cmd(skb)) + return skb_dir(skb) == DMA_TO_DEVICE; + return false; +} + +/* libfcoe funcs */ +int fcoe_reset(struct Scsi_Host *shost); +u64 fcoe_wwn_from_mac(unsigned char mac[MAX_ADDR_LEN], + unsigned int scheme, unsigned int port); + +u32 fcoe_fc_crc(struct fc_frame *fp); +int fcoe_xmit(struct fc_lport *, struct fc_frame *); +int fcoe_rcv(struct sk_buff *, struct net_device *, + struct packet_type *, struct net_device *); + +int fcoe_percpu_receive_thread(void *arg); +void fcoe_clean_pending_queue(struct fc_lport *lp); +void fcoe_percpu_clean(struct fc_lport *lp); +void fcoe_watchdog(ulong vp); +int fcoe_link_ok(struct fc_lport *lp); + +struct fc_lport *fcoe_hostlist_lookup(const struct net_device *); +int fcoe_hostlist_add(const struct fc_lport *); +int fcoe_hostlist_remove(const struct fc_lport *); + +struct Scsi_Host *fcoe_host_alloc(struct scsi_host_template *, int); +int fcoe_libfc_config(struct fc_lport *, struct libfc_function_template *); + +/* fcoe sw hba */ +int __init fcoe_sw_init(void); +int __exit fcoe_sw_exit(void); +#endif /* _LIBFCOE_H */ diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index 61e53f14f7e..7360e1916e7 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h @@ -30,6 +30,7 @@ #include <linux/workqueue.h> #include <scsi/iscsi_proto.h> #include <scsi/iscsi_if.h> +#include <scsi/scsi_transport_iscsi.h> struct scsi_transport_template; struct scsi_host_template; @@ -70,12 +71,12 @@ enum { /* Connection suspend "bit" */ #define ISCSI_SUSPEND_BIT 1 -#define ISCSI_ITT_MASK (0x1fff) +#define ISCSI_ITT_MASK 0x1fff #define ISCSI_TOTAL_CMDS_MAX 4096 /* this must be a power of two greater than ISCSI_MGMT_CMDS_MAX */ #define ISCSI_TOTAL_CMDS_MIN 16 #define ISCSI_AGE_SHIFT 28 -#define ISCSI_AGE_MASK (0xf << ISCSI_AGE_SHIFT) +#define ISCSI_AGE_MASK 0xf #define ISCSI_ADDRESS_BUF_LEN 64 @@ -93,24 +94,38 @@ enum { ISCSI_TASK_RUNNING, }; +struct iscsi_r2t_info { + __be32 ttt; /* copied from R2T */ + __be32 exp_statsn; /* copied from R2T */ + uint32_t data_length; /* copied from R2T */ + uint32_t data_offset; /* copied from R2T */ + int data_count; /* DATA-Out payload progress */ + int datasn; + /* LLDs should set/update these values */ + int sent; /* R2T sequence progress */ +}; + struct iscsi_task { /* * Because LLDs allocate their hdr differently, this is a pointer * and length to that storage. It must be setup at session * creation time. */ - struct iscsi_cmd *hdr; + struct iscsi_hdr *hdr; unsigned short hdr_max; unsigned short hdr_len; /* accumulated size of hdr used */ + /* copied values in case we need to send tmfs */ + itt_t hdr_itt; + __be32 cmdsn; + uint8_t lun[8]; + int itt; /* this ITT */ - uint32_t unsol_datasn; unsigned imm_count; /* imm-data (bytes) */ - unsigned unsol_count; /* unsolicited (bytes)*/ /* offset in unsolicited stream (bytes); */ - unsigned unsol_offset; - unsigned data_count; /* remaining Data-Out */ + struct iscsi_r2t_info unsol_r2t; char *data; /* mgmt payload */ + unsigned data_count; struct scsi_cmnd *sc; /* associated SCSI cmd*/ struct iscsi_conn *conn; /* used connection */ @@ -121,6 +136,11 @@ struct iscsi_task { void *dd_data; /* driver/transport data */ }; +static inline int iscsi_task_has_unsol_data(struct iscsi_task *task) +{ + return task->unsol_r2t.data_length > task->unsol_r2t.sent; +} + static inline void* iscsi_next_hdr(struct iscsi_task *task) { return (void*)task->hdr + task->hdr_len; @@ -376,8 +396,9 @@ extern void iscsi_suspend_tx(struct iscsi_conn *conn); * pdu and task processing */ extern void iscsi_update_cmdsn(struct iscsi_session *, struct iscsi_nopin *); -extern void iscsi_prep_unsolicit_data_pdu(struct iscsi_task *, - struct iscsi_data *hdr); +extern void iscsi_prep_data_out_pdu(struct iscsi_task *task, + struct iscsi_r2t_info *r2t, + struct iscsi_data *hdr); extern int iscsi_conn_send_pdu(struct iscsi_cls_conn *, struct iscsi_hdr *, char *, uint32_t); extern int iscsi_complete_pdu(struct iscsi_conn *, struct iscsi_hdr *, diff --git a/include/scsi/libiscsi_tcp.h b/include/scsi/libiscsi_tcp.h new file mode 100644 index 00000000000..83e32f6d785 --- /dev/null +++ b/include/scsi/libiscsi_tcp.h @@ -0,0 +1,132 @@ +/* + * iSCSI over TCP/IP Data-Path lib + * + * Copyright (C) 2008 Mike Christie + * Copyright (C) 2008 Red Hat, Inc. All rights reserved. + * maintained by open-iscsi@googlegroups.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. + * + * See the file COPYING included with this distribution for more details. + */ + +#ifndef LIBISCSI_TCP_H +#define LIBISCSI_TCP_H + +#include <scsi/libiscsi.h> + +struct iscsi_tcp_conn; +struct iscsi_segment; +struct sk_buff; +struct hash_desc; + +typedef int iscsi_segment_done_fn_t(struct iscsi_tcp_conn *, + struct iscsi_segment *); + +struct iscsi_segment { + unsigned char *data; + unsigned int size; + unsigned int copied; + unsigned int total_size; + unsigned int total_copied; + + struct hash_desc *hash; + unsigned char recv_digest[ISCSI_DIGEST_SIZE]; + unsigned char digest[ISCSI_DIGEST_SIZE]; + unsigned int digest_len; + + struct scatterlist *sg; + void *sg_mapped; + unsigned int sg_offset; + + iscsi_segment_done_fn_t *done; +}; + +/* Socket connection recieve helper */ +struct iscsi_tcp_recv { + struct iscsi_hdr *hdr; + struct iscsi_segment segment; + + /* Allocate buffer for BHS + AHS */ + uint32_t hdr_buf[64]; + + /* copied and flipped values */ + int datalen; +}; + +struct iscsi_tcp_conn { + struct iscsi_conn *iscsi_conn; + void *dd_data; + int stop_stage; /* conn_stop() flag: * + * stop to recover, * + * stop to terminate */ + /* control data */ + struct iscsi_tcp_recv in; /* TCP receive context */ + /* CRC32C (Rx) LLD should set this is they do not offload */ + struct hash_desc *rx_hash; +}; + +struct iscsi_tcp_task { + uint32_t exp_datasn; /* expected target's R2TSN/DataSN */ + int data_offset; + struct iscsi_r2t_info *r2t; /* in progress solict R2T */ + struct iscsi_pool r2tpool; + struct kfifo *r2tqueue; + void *dd_data; +}; + +enum { + ISCSI_TCP_SEGMENT_DONE, /* curr seg has been processed */ + ISCSI_TCP_SKB_DONE, /* skb is out of data */ + ISCSI_TCP_CONN_ERR, /* iscsi layer has fired a conn err */ + ISCSI_TCP_SUSPENDED, /* conn is suspended */ +}; + +extern void iscsi_tcp_hdr_recv_prep(struct iscsi_tcp_conn *tcp_conn); +extern int iscsi_tcp_recv_skb(struct iscsi_conn *conn, struct sk_buff *skb, + unsigned int offset, bool offloaded, int *status); +extern void iscsi_tcp_cleanup_task(struct iscsi_task *task); +extern int iscsi_tcp_task_init(struct iscsi_task *task); +extern int iscsi_tcp_task_xmit(struct iscsi_task *task); + +/* segment helpers */ +extern int iscsi_tcp_recv_segment_is_hdr(struct iscsi_tcp_conn *tcp_conn); +extern int iscsi_tcp_segment_done(struct iscsi_tcp_conn *tcp_conn, + struct iscsi_segment *segment, int recv, + unsigned copied); +extern void iscsi_tcp_segment_unmap(struct iscsi_segment *segment); + +extern void iscsi_segment_init_linear(struct iscsi_segment *segment, + void *data, size_t size, + iscsi_segment_done_fn_t *done, + struct hash_desc *hash); +extern int +iscsi_segment_seek_sg(struct iscsi_segment *segment, + struct scatterlist *sg_list, unsigned int sg_count, + unsigned int offset, size_t size, + iscsi_segment_done_fn_t *done, struct hash_desc *hash); + +/* digest helpers */ +extern void iscsi_tcp_dgst_header(struct hash_desc *hash, const void *hdr, + size_t hdrlen, + unsigned char digest[ISCSI_DIGEST_SIZE]); +extern struct iscsi_cls_conn * +iscsi_tcp_conn_setup(struct iscsi_cls_session *cls_session, int dd_data_size, + uint32_t conn_idx); +extern void iscsi_tcp_conn_teardown(struct iscsi_cls_conn *cls_conn); + +/* misc helpers */ +extern int iscsi_tcp_r2tpool_alloc(struct iscsi_session *session); +extern void iscsi_tcp_r2tpool_free(struct iscsi_session *session); + +extern void iscsi_tcp_conn_get_stats(struct iscsi_cls_conn *cls_conn, + struct iscsi_stats *stats); +#endif /* LIBISCSI_TCP_H */ diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index a37a8148a31..01a4c58f8ba 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -159,8 +159,6 @@ struct scsi_device { atomic_t iodone_cnt; atomic_t ioerr_cnt; - int timeout; - struct device sdev_gendev, sdev_dev; @@ -367,10 +365,11 @@ extern int scsi_is_target_device(const struct device *); extern int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, int data_direction, void *buffer, unsigned bufflen, unsigned char *sense, int timeout, int retries, - int flag); + int flag, int *resid); extern int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd, int data_direction, void *buffer, unsigned bufflen, - struct scsi_sense_hdr *, int timeout, int retries); + struct scsi_sense_hdr *, int timeout, int retries, + int *resid); extern int scsi_execute_async(struct scsi_device *sdev, const unsigned char *cmd, int cmd_len, int data_direction, void *buffer, unsigned bufflen, int use_sg, diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index c667cc39654..b50aabe2861 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -113,10 +113,18 @@ struct iscsi_transport { char *data, uint32_t data_size); void (*get_stats) (struct iscsi_cls_conn *conn, struct iscsi_stats *stats); + int (*init_task) (struct iscsi_task *task); int (*xmit_task) (struct iscsi_task *task); - void (*cleanup_task) (struct iscsi_conn *conn, - struct iscsi_task *task); + void (*cleanup_task) (struct iscsi_task *task); + + int (*alloc_pdu) (struct iscsi_task *task, uint8_t opcode); + int (*xmit_pdu) (struct iscsi_task *task); + int (*init_pdu) (struct iscsi_task *task, unsigned int offset, + unsigned int count); + void (*parse_pdu_itt) (struct iscsi_conn *conn, itt_t itt, + int *index, int *age); + void (*session_recovery_timedout) (struct iscsi_cls_session *session); struct iscsi_endpoint *(*ep_connect) (struct sockaddr *dst_addr, int non_blocking); |