summary refs log tree commit diff
path: root/include/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'include/scsi')
-rw-r--r--include/scsi/fc/fc_els.h816
-rw-r--r--include/scsi/fc/fc_encaps.h138
-rw-r--r--include/scsi/fc/fc_fc2.h124
-rw-r--r--include/scsi/fc/fc_fcoe.h114
-rw-r--r--include/scsi/fc/fc_fcp.h199
-rw-r--r--include/scsi/fc/fc_fs.h340
-rw-r--r--include/scsi/fc/fc_gs.h93
-rw-r--r--include/scsi/fc/fc_ns.h159
-rw-r--r--include/scsi/fc_encode.h309
-rw-r--r--include/scsi/fc_frame.h242
-rw-r--r--include/scsi/fc_transport_fcoe.h54
-rw-r--r--include/scsi/iscsi_if.h7
-rw-r--r--include/scsi/libfc.h938
-rw-r--r--include/scsi/libfcoe.h176
-rw-r--r--include/scsi/libiscsi.h39
-rw-r--r--include/scsi/libiscsi_tcp.h132
-rw-r--r--include/scsi/scsi_device.h7
-rw-r--r--include/scsi/scsi_transport_iscsi.h12
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 000000000000..195ca014d3ce
--- /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 000000000000..f180c3e16220
--- /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 000000000000..cff8a8c22f50
--- /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 000000000000..57aaa8f0d613
--- /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 000000000000..5d38f1989f37
--- /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 000000000000..3e4801d2bdbb
--- /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 000000000000..ffab0272c65a
--- /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 000000000000..790d7b97d4bc
--- /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 000000000000..6300f556bce5
--- /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 000000000000..04d34a71355f
--- /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 000000000000..8dca2af14ffc
--- /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 0c9514de5df7..d0ed5226f8c4 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 000000000000..9f2876397dda
--- /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 000000000000..89fdbb9a6a1b
--- /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 61e53f14f7e1..7360e1916e75 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 000000000000..83e32f6d7859
--- /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 a37a8148a310..01a4c58f8bad 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 c667cc396545..b50aabe2861e 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);