struct zfcp_dbf_scsi_record *rec = &dbf->scsi_buf;
        struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)rec;
        unsigned long flags;
-       struct fcp_rsp_iu *fcp_rsp;
-       char *fcp_rsp_info = NULL, *fcp_sns_info = NULL;
+       struct fcp_resp_with_ext *fcp_rsp;
+       struct fcp_resp_rsp_info *fcp_rsp_info = NULL;
+       char *fcp_sns_info = NULL;
        int offset = 0, buflen = 0;
 
        spin_lock_irqsave(&dbf->scsi_lock, flags);
                                rec->scsi_allowed = scsi_cmnd->allowed;
                        }
                        if (fsf_req != NULL) {
-                               fcp_rsp = (struct fcp_rsp_iu *)
-                                   &(fsf_req->qtcb->bottom.io.fcp_rsp);
-                               fcp_rsp_info = (unsigned char *) &fcp_rsp[1];
-                               fcp_sns_info =
-                                   zfcp_get_fcp_sns_info_ptr(fcp_rsp);
-
-                               rec->rsp_validity = fcp_rsp->validity.value;
-                               rec->rsp_scsi_status = fcp_rsp->scsi_status;
-                               rec->rsp_resid = fcp_rsp->fcp_resid;
-                               if (fcp_rsp->validity.bits.fcp_rsp_len_valid)
-                                       rec->rsp_code = *(fcp_rsp_info + 3);
-                               if (fcp_rsp->validity.bits.fcp_sns_len_valid) {
-                                       buflen = min((int)fcp_rsp->fcp_sns_len,
-                                                    ZFCP_DBF_SCSI_MAX_FCP_SNS_INFO);
+                               fcp_rsp = (struct fcp_resp_with_ext *)
+                                       &(fsf_req->qtcb->bottom.io.fcp_rsp);
+                               fcp_rsp_info = (struct fcp_resp_rsp_info *)
+                                       &fcp_rsp[1];
+                               fcp_sns_info = (char *) &fcp_rsp[1];
+                               if (fcp_rsp->resp.fr_flags & FCP_RSP_LEN_VAL)
+                                       fcp_sns_info += fcp_rsp->ext.fr_sns_len;
+
+                               rec->rsp_validity = fcp_rsp->resp.fr_flags;
+                               rec->rsp_scsi_status = fcp_rsp->resp.fr_status;
+                               rec->rsp_resid = fcp_rsp->ext.fr_resid;
+                               if (fcp_rsp->resp.fr_flags & FCP_RSP_LEN_VAL)
+                                       rec->rsp_code = fcp_rsp_info->rsp_code;
+                               if (fcp_rsp->resp.fr_flags & FCP_SNS_LEN_VAL) {
+                                       buflen = min(fcp_rsp->ext.fr_sns_len,
+                                          (u32)ZFCP_DBF_SCSI_MAX_FCP_SNS_INFO);
                                        rec->sns_info_len = buflen;
                                        memcpy(rec->sns_info, fcp_sns_info,
                                               min(buflen,
 
 #ifndef ZFCP_DBF_H
 #define ZFCP_DBF_H
 
+#include <scsi/fc/fc_fcp.h>
 #include "zfcp_ext.h"
 #include "zfcp_fsf.h"
 #include "zfcp_def.h"
 void zfcp_dbf_scsi_devreset(const char *tag, u8 flag, struct zfcp_unit *unit,
                            struct scsi_cmnd *scsi_cmnd)
 {
-       zfcp_dbf_scsi(flag == FCP_TARGET_RESET ? "trst" : "lrst", tag, 1,
+       zfcp_dbf_scsi(flag == FCP_TMF_TGT_RESET ? "trst" : "lrst", tag, 1,
                            unit->port->adapter->dbf, scsi_cmnd, NULL, 0);
 }
 
 
 
 /*************** FIBRE CHANNEL PROTOCOL SPECIFIC DEFINES ********************/
 
-/* task attribute values in FCP-2 FCP_CMND IU */
-#define SIMPLE_Q       0
-#define HEAD_OF_Q      1
-#define ORDERED_Q      2
-#define ACA_Q          4
-#define UNTAGGED       5
-
-/* task management flags in FCP-2 FCP_CMND IU */
-#define FCP_CLEAR_ACA          0x40
-#define FCP_TARGET_RESET       0x20
-#define FCP_LOGICAL_UNIT_RESET 0x10
-#define FCP_CLEAR_TASK_SET     0x04
-#define FCP_ABORT_TASK_SET     0x02
-
-#define FCP_CDB_LENGTH         16
-
 #define ZFCP_DID_MASK           0x00FFFFFF
 
-/* FCP(-2) FCP_CMND IU */
-struct fcp_cmnd_iu {
-       u64 fcp_lun;       /* FCP logical unit number */
-       u8  crn;                   /* command reference number */
-       u8  reserved0:5;           /* reserved */
-       u8  task_attribute:3;      /* task attribute */
-       u8  task_management_flags; /* task management flags */
-       u8  add_fcp_cdb_length:6;  /* additional FCP_CDB length */
-       u8  rddata:1;              /* read data */
-       u8  wddata:1;              /* write data */
-       u8  fcp_cdb[FCP_CDB_LENGTH];
-} __attribute__((packed));
-
-/* FCP(-2) FCP_RSP IU */
-struct fcp_rsp_iu {
-       u8  reserved0[10];
-       union {
-               struct {
-                       u8 reserved1:3;
-                       u8 fcp_conf_req:1;
-                       u8 fcp_resid_under:1;
-                       u8 fcp_resid_over:1;
-                       u8 fcp_sns_len_valid:1;
-                       u8 fcp_rsp_len_valid:1;
-               } bits;
-               u8 value;
-       } validity;
-       u8  scsi_status;
-       u32 fcp_resid;
-       u32 fcp_sns_len;
-       u32 fcp_rsp_len;
-} __attribute__((packed));
-
-
-#define RSP_CODE_GOOD           0
-#define RSP_CODE_LENGTH_MISMATCH 1
-#define RSP_CODE_FIELD_INVALID  2
-#define RSP_CODE_RO_MISMATCH    3
-#define RSP_CODE_TASKMAN_UNSUPP         4
-#define RSP_CODE_TASKMAN_FAILED         5
-
 /* see fc-fs */
 #define LS_RSCN  0x61
 #define LS_LOGO  0x05
 
 extern struct zfcp_data zfcp_data;
 extern int zfcp_adapter_scsi_register(struct zfcp_adapter *);
 extern void zfcp_adapter_scsi_unregister(struct zfcp_adapter *);
-extern char *zfcp_get_fcp_sns_info_ptr(struct fcp_rsp_iu *);
 extern struct fc_function_template zfcp_transport_functions;
 extern void zfcp_scsi_rport_work(struct work_struct *);
 extern void zfcp_scsi_schedule_rport_register(struct zfcp_port *);
 
--- /dev/null
+/*
+ * zfcp device driver
+ *
+ * Fibre Channel related definitions and inline functions for the zfcp
+ * device driver
+ *
+ * Copyright IBM Corporation 2009
+ */
+
+#ifndef ZFCP_FC_H
+#define ZFCP_FC_H
+
+#include <scsi/fc/fc_fcp.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_tcq.h>
+
+/**
+ * zfcp_fc_scsi_to_fcp - setup FCP command with data from scsi_cmnd
+ * @fcp: fcp_cmnd to setup
+ * @scsi: scsi_cmnd where to get LUN, task attributes/flags and CDB
+ */
+static inline
+void zfcp_fc_scsi_to_fcp(struct fcp_cmnd *fcp, struct scsi_cmnd *scsi)
+{
+       char tag[2];
+
+       int_to_scsilun(scsi->device->lun, (struct scsi_lun *) &fcp->fc_lun);
+
+       if (scsi_populate_tag_msg(scsi, tag)) {
+               switch (tag[0]) {
+               case MSG_ORDERED_TAG:
+                       fcp->fc_pri_ta |= FCP_PTA_ORDERED;
+                       break;
+               case MSG_SIMPLE_TAG:
+                       fcp->fc_pri_ta |= FCP_PTA_SIMPLE;
+                       break;
+               };
+       } else
+               fcp->fc_pri_ta = FCP_PTA_SIMPLE;
+
+       if (scsi->sc_data_direction == DMA_FROM_DEVICE)
+               fcp->fc_flags |= FCP_CFL_RDDATA;
+       if (scsi->sc_data_direction == DMA_TO_DEVICE)
+               fcp->fc_flags |= FCP_CFL_WRDATA;
+
+       memcpy(fcp->fc_cdb, scsi->cmnd, scsi->cmd_len);
+
+       fcp->fc_dl = scsi_bufflen(scsi);
+}
+
+/**
+ * zfcp_fc_fcp_tm - setup FCP command as task management command
+ * @fcp: fcp_cmnd to setup
+ * @dev: scsi_device where to send the task management command
+ * @tm: task management flags to setup tm command
+ */
+static inline
+void zfcp_fc_fcp_tm(struct fcp_cmnd *fcp, struct scsi_device *dev, u8 tm_flags)
+{
+       int_to_scsilun(dev->lun, (struct scsi_lun *) &fcp->fc_lun);
+       fcp->fc_tm_flags |= tm_flags;
+}
+
+/**
+ * zfcp_fc_evap_fcp_rsp - evaluate FCP RSP IU and update scsi_cmnd accordingly
+ * @fcp_rsp: FCP RSP IU to evaluate
+ * @scsi: SCSI command where to update status and sense buffer
+ */
+static inline
+void zfcp_fc_eval_fcp_rsp(struct fcp_resp_with_ext *fcp_rsp,
+                         struct scsi_cmnd *scsi)
+{
+       struct fcp_resp_rsp_info *rsp_info;
+       char *sense;
+       u32 sense_len, resid;
+       u8 rsp_flags;
+
+       set_msg_byte(scsi, COMMAND_COMPLETE);
+       scsi->result |= fcp_rsp->resp.fr_status;
+
+       rsp_flags = fcp_rsp->resp.fr_flags;
+
+       if (unlikely(rsp_flags & FCP_RSP_LEN_VAL)) {
+               rsp_info = (struct fcp_resp_rsp_info *) &fcp_rsp[1];
+               if (rsp_info->rsp_code == FCP_TMF_CMPL)
+                       set_host_byte(scsi, DID_OK);
+               else {
+                       set_host_byte(scsi, DID_ERROR);
+                       return;
+               }
+       }
+
+       if (unlikely(rsp_flags & FCP_SNS_LEN_VAL)) {
+               sense = (char *) &fcp_rsp[1];
+               if (rsp_flags & FCP_RSP_LEN_VAL)
+                       sense += fcp_rsp->ext.fr_sns_len;
+               sense_len = min(fcp_rsp->ext.fr_sns_len,
+                               (u32) SCSI_SENSE_BUFFERSIZE);
+               memcpy(scsi->sense_buffer, sense, sense_len);
+       }
+
+       if (unlikely(rsp_flags & FCP_RESID_UNDER)) {
+               resid = fcp_rsp->ext.fr_resid;
+               scsi_set_resid(scsi, resid);
+               if (scsi_bufflen(scsi) - resid < scsi->underflow &&
+                    !(rsp_flags & FCP_SNS_LEN_VAL) &&
+                    fcp_rsp->resp.fr_status == SAM_STAT_GOOD)
+                       set_host_byte(scsi, DID_ERROR);
+       }
+}
+
+#endif
 
 
 #include <linux/blktrace_api.h>
 #include "zfcp_ext.h"
+#include "zfcp_fc.h"
 #include "zfcp_dbf.h"
 
 static void zfcp_fsf_request_timeout_handler(unsigned long data)
 static void zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *req)
 {
        struct scsi_cmnd *scpnt;
-       struct fcp_rsp_iu *fcp_rsp_iu = (struct fcp_rsp_iu *)
-           &(req->qtcb->bottom.io.fcp_rsp);
-       u32 sns_len;
-       char *fcp_rsp_info = (unsigned char *) &fcp_rsp_iu[1];
+       struct fcp_resp_with_ext *fcp_rsp;
        unsigned long flags;
 
        read_lock_irqsave(&req->adapter->abort_lock, flags);
                goto skip_fsfstatus;
        }
 
-       set_msg_byte(scpnt, COMMAND_COMPLETE);
-
-       scpnt->result |= fcp_rsp_iu->scsi_status;
+       fcp_rsp = (struct fcp_resp_with_ext *) &req->qtcb->bottom.io.fcp_rsp;
+       zfcp_fc_eval_fcp_rsp(fcp_rsp, scpnt);
 
        zfcp_fsf_req_trace(req, scpnt);
 
-       if (unlikely(fcp_rsp_iu->validity.bits.fcp_rsp_len_valid)) {
-               if (fcp_rsp_info[3] == RSP_CODE_GOOD)
-                       set_host_byte(scpnt, DID_OK);
-               else {
-                       set_host_byte(scpnt, DID_ERROR);
-                       goto skip_fsfstatus;
-               }
-       }
-
-       if (unlikely(fcp_rsp_iu->validity.bits.fcp_sns_len_valid)) {
-               sns_len = FSF_FCP_RSP_SIZE - sizeof(struct fcp_rsp_iu) +
-                         fcp_rsp_iu->fcp_rsp_len;
-               sns_len = min(sns_len, (u32) SCSI_SENSE_BUFFERSIZE);
-               sns_len = min(sns_len, fcp_rsp_iu->fcp_sns_len);
-
-               memcpy(scpnt->sense_buffer,
-                      zfcp_get_fcp_sns_info_ptr(fcp_rsp_iu), sns_len);
-       }
-
-       if (unlikely(fcp_rsp_iu->validity.bits.fcp_resid_under)) {
-               scsi_set_resid(scpnt, fcp_rsp_iu->fcp_resid);
-               if (scsi_bufflen(scpnt) - scsi_get_resid(scpnt) <
-                   scpnt->underflow)
-                       set_host_byte(scpnt, DID_ERROR);
-       }
 skip_fsfstatus:
        if (scpnt->result != 0)
                zfcp_dbf_scsi_result("erro", 3, req->adapter->dbf, scpnt, req);
 
 static void zfcp_fsf_send_fcp_ctm_handler(struct zfcp_fsf_req *req)
 {
-       struct fcp_rsp_iu *fcp_rsp_iu = (struct fcp_rsp_iu *)
-           &(req->qtcb->bottom.io.fcp_rsp);
-       char *fcp_rsp_info = (unsigned char *) &fcp_rsp_iu[1];
+       struct fcp_resp_with_ext *fcp_rsp;
+       struct fcp_resp_rsp_info *rsp_info;
 
-       if ((fcp_rsp_info[3] != RSP_CODE_GOOD) ||
+       fcp_rsp = (struct fcp_resp_with_ext *) &req->qtcb->bottom.io.fcp_rsp;
+       rsp_info = (struct fcp_resp_rsp_info *) &fcp_rsp[1];
+
+       if ((rsp_info->rsp_code != FCP_TMF_CMPL) ||
             (req->status & ZFCP_STATUS_FSFREQ_ERROR))
                req->status |= ZFCP_STATUS_FSFREQ_TMFUNCFAILED;
 }
        }
 }
 
-static void zfcp_set_fcp_dl(struct fcp_cmnd_iu *fcp_cmd, u32 fcp_dl)
-{
-       u32 *fcp_dl_ptr;
-
-       /*
-        * fcp_dl_addr = start address of fcp_cmnd structure +
-        * size of fixed part + size of dynamically sized add_dcp_cdb field
-        * SEE FCP-2 documentation
-        */
-       fcp_dl_ptr = (u32 *) ((unsigned char *) &fcp_cmd[1] +
-                       (fcp_cmd->add_fcp_cdb_length << 2));
-       *fcp_dl_ptr = fcp_dl;
-}
-
 /**
  * zfcp_fsf_send_fcp_command_task - initiate an FCP command (for a SCSI command)
  * @unit: unit where command is sent to
                                   struct scsi_cmnd *scsi_cmnd)
 {
        struct zfcp_fsf_req *req;
-       struct fcp_cmnd_iu *fcp_cmnd_iu;
+       struct fcp_cmnd *fcp_cmnd;
        unsigned int sbtype = SBAL_FLAGS0_TYPE_READ;
        int real_bytes, retval = -EIO;
        struct zfcp_adapter *adapter = unit->port->adapter;
        req->qtcb->header.lun_handle = unit->handle;
        req->qtcb->header.port_handle = unit->port->handle;
        req->qtcb->bottom.io.service_class = FSF_CLASS_3;
+       req->qtcb->bottom.io.fcp_cmnd_length = FCP_CMND_LEN;
 
        scsi_cmnd->host_scribble = (unsigned char *) req->req_id;
 
-       fcp_cmnd_iu = (struct fcp_cmnd_iu *) &(req->qtcb->bottom.io.fcp_cmnd);
-       fcp_cmnd_iu->fcp_lun = unit->fcp_lun;
        /*
         * set depending on data direction:
         *      data direction bits in SBALE (SB Type)
         *      data direction bits in QTCB
-        *      data direction bits in FCP_CMND IU
         */
        switch (scsi_cmnd->sc_data_direction) {
        case DMA_NONE:
                break;
        case DMA_FROM_DEVICE:
                req->qtcb->bottom.io.data_direction = FSF_DATADIR_READ;
-               fcp_cmnd_iu->rddata = 1;
                break;
        case DMA_TO_DEVICE:
                req->qtcb->bottom.io.data_direction = FSF_DATADIR_WRITE;
                sbtype = SBAL_FLAGS0_TYPE_WRITE;
-               fcp_cmnd_iu->wddata = 1;
                break;
        case DMA_BIDIRECTIONAL:
                goto failed_scsi_cmnd;
        }
 
-       if (likely((scsi_cmnd->device->simple_tags) ||
-                  ((atomic_read(&unit->status) & ZFCP_STATUS_UNIT_READONLY) &&
-                   (atomic_read(&unit->status) & ZFCP_STATUS_UNIT_SHARED))))
-               fcp_cmnd_iu->task_attribute = SIMPLE_Q;
-       else
-               fcp_cmnd_iu->task_attribute = UNTAGGED;
-
-       if (unlikely(scsi_cmnd->cmd_len > FCP_CDB_LENGTH))
-               fcp_cmnd_iu->add_fcp_cdb_length =
-                       (scsi_cmnd->cmd_len - FCP_CDB_LENGTH) >> 2;
-
-       memcpy(fcp_cmnd_iu->fcp_cdb, scsi_cmnd->cmnd, scsi_cmnd->cmd_len);
-
-       req->qtcb->bottom.io.fcp_cmnd_length = sizeof(struct fcp_cmnd_iu) +
-               fcp_cmnd_iu->add_fcp_cdb_length + sizeof(u32);
+       fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd;
+       zfcp_fc_scsi_to_fcp(fcp_cmnd, scsi_cmnd);
 
        real_bytes = zfcp_qdio_sbals_from_sg(qdio, &req->queue_req, sbtype,
                                             scsi_sglist(scsi_cmnd),
                goto failed_scsi_cmnd;
        }
 
-       zfcp_set_fcp_dl(fcp_cmnd_iu, real_bytes);
-
        retval = zfcp_fsf_req_send(req);
        if (unlikely(retval))
                goto failed_scsi_cmnd;
 {
        struct qdio_buffer_element *sbale;
        struct zfcp_fsf_req *req = NULL;
-       struct fcp_cmnd_iu *fcp_cmnd_iu;
+       struct fcp_cmnd *fcp_cmnd;
        struct zfcp_qdio *qdio = unit->port->adapter->qdio;
 
        if (unlikely(!(atomic_read(&unit->status) &
        req->qtcb->header.port_handle = unit->port->handle;
        req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND;
        req->qtcb->bottom.io.service_class = FSF_CLASS_3;
-       req->qtcb->bottom.io.fcp_cmnd_length =  sizeof(struct fcp_cmnd_iu) +
-                                               sizeof(u32);
+       req->qtcb->bottom.io.fcp_cmnd_length = FCP_CMND_LEN;
 
        sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
        sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE;
        sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
 
-       fcp_cmnd_iu = (struct fcp_cmnd_iu *) &req->qtcb->bottom.io.fcp_cmnd;
-       fcp_cmnd_iu->fcp_lun = unit->fcp_lun;
-       fcp_cmnd_iu->task_management_flags = tm_flags;
+       fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd;
+       zfcp_fc_fcp_tm(fcp_cmnd, unit->device, tm_flags);
 
        zfcp_fsf_start_timer(req, ZFCP_SCSI_ER_TIMEOUT);
        if (!zfcp_fsf_req_send(req))
 
 #define KMSG_COMPONENT "zfcp"
 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
 
+#include <linux/types.h>
+#include <scsi/fc/fc_fcp.h>
 #include <asm/atomic.h>
 #include "zfcp_ext.h"
 #include "zfcp_dbf.h"
 module_param_named(queue_depth, default_depth, uint, 0600);
 MODULE_PARM_DESC(queue_depth, "Default queue depth for new SCSI devices");
 
-/* Find start of Sense Information in FCP response unit*/
-char *zfcp_get_fcp_sns_info_ptr(struct fcp_rsp_iu *fcp_rsp_iu)
-{
-       char *fcp_sns_info_ptr;
-
-       fcp_sns_info_ptr = (unsigned char *) &fcp_rsp_iu[1];
-       if (fcp_rsp_iu->validity.bits.fcp_rsp_len_valid)
-               fcp_sns_info_ptr += fcp_rsp_iu->fcp_rsp_len;
-
-       return fcp_sns_info_ptr;
-}
-
 static int zfcp_scsi_change_queue_depth(struct scsi_device *sdev, int depth,
                                        int reason)
 {
 
 static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
 {
-       return zfcp_task_mgmt_function(scpnt, FCP_LOGICAL_UNIT_RESET);
+       return zfcp_task_mgmt_function(scpnt, FCP_TMF_LUN_RESET);
 }
 
 static int zfcp_scsi_eh_target_reset_handler(struct scsi_cmnd *scpnt)
 {
-       return zfcp_task_mgmt_function(scpnt, FCP_TARGET_RESET);
+       return zfcp_task_mgmt_function(scpnt, FCP_TMF_TGT_RESET);
 }
 
 static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
        adapter->scsi_host->max_lun = 1;
        adapter->scsi_host->max_channel = 0;
        adapter->scsi_host->unique_id = dev_id.devno;
-       adapter->scsi_host->max_cmd_len = 255;
+       adapter->scsi_host->max_cmd_len = 16; /* in struct fcp_cmnd */
        adapter->scsi_host->transportt = zfcp_data.scsi_transport_template;
 
        adapter->scsi_host->hostdata[0] = (unsigned long) adapter;