els->type =
                (bsg_job->request->msgcode == FC_BSG_RPT_ELS ?
                SRB_ELS_CMD_RPT : SRB_ELS_CMD_HST);
+       els->name =
+               (bsg_job->request->msgcode == FC_BSG_RPT_ELS ?
+               "bsg_els_rpt" : "bsg_els_hst");
        els->u.bsg_job = bsg_job;
 
        DEBUG2(qla_printk(KERN_INFO, ha,
 
        ct = sp->ctx;
        ct->type = SRB_CT_CMD;
+       ct->name = "bsg_ct";
        ct->u.bsg_job = bsg_job;
 
        DEBUG2(qla_printk(KERN_INFO, ha,
 
 #define SRB_LOGIN_SKIP_PRLI    BIT_2
                        uint16_t data[2];
                } logio;
+               struct {
+                       /*
+                        * Values for flags field below are as
+                        * defined in tsk_mgmt_entry struct
+                        * for control_flags field in qla_fw.h.
+                        */
+                       uint32_t flags;
+                       uint32_t lun;
+                       uint32_t data;
+               } tmf;
+               struct {
+                       /*
+                        * values for modif field below are as
+                        * defined in mrk_entry_24xx struct
+                        * for the modifier field in qla_fw.h.
+                        */
+                       uint8_t modif;
+                       uint16_t lun;
+                       uint32_t data;
+               } marker;
        } u;
 
        struct timer_list timer;
 #define SRB_ELS_CMD_HST 4
 #define SRB_CT_CMD     5
 #define SRB_ADISC_CMD  6
+#define SRB_TM_CMD     7
+#define SRB_MARKER_CMD 8
 
 struct srb_ctx {
        uint16_t type;
 
 extern int qla2x00_async_logout(struct scsi_qla_host *, fc_port_t *);
 extern int qla2x00_async_adisc(struct scsi_qla_host *, fc_port_t *,
     uint16_t *);
+extern int qla2x00_async_tm_cmd(fc_port_t *, uint32_t, uint32_t, uint32_t);
+extern int qla2x00_async_marker(fc_port_t *, uint16_t, uint8_t);
 extern void qla2x00_async_login_done(struct scsi_qla_host *, fc_port_t *,
     uint16_t *);
 extern void qla2x00_async_logout_done(struct scsi_qla_host *, fc_port_t *,
     uint16_t *);
 extern void qla2x00_async_adisc_done(struct scsi_qla_host *, fc_port_t *,
     uint16_t *);
+extern void qla2x00_async_tm_cmd_done(struct scsi_qla_host *, fc_port_t *,
+       struct srb_iocb *);
+extern void qla2x00_async_marker_done(struct scsi_qla_host *, fc_port_t *,
+       struct srb_iocb *);
 
 extern fc_port_t *
 qla2x00_alloc_fcport(scsi_qla_host_t *, gfp_t );
 extern int ql2xshiftctondsd;
 extern int ql2xdbwr;
 extern int ql2xdontresethba;
+extern int ql2xasynctmfenable;
 
 extern int qla2x00_loop_reset(scsi_qla_host_t *);
 extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
 
 #define ELS_TMO_2_RATOV(ha) ((ha)->r_a_tov / 10 * 2)
 
 static void
-qla2x00_async_logio_timeout(srb_t *sp)
+qla2x00_async_iocb_timeout(srb_t *sp)
 {
        fc_port_t *fcport = sp->fcport;
        struct srb_ctx *ctx = sp->ctx;
        ctx->type = SRB_LOGIN_CMD;
        ctx->name = "login";
        lio = ctx->u.iocb_cmd;
-       lio->timeout = qla2x00_async_logio_timeout;
+       lio->timeout = qla2x00_async_iocb_timeout;
        lio->done = qla2x00_async_login_ctx_done;
        lio->u.logio.flags |= SRB_LOGIN_COND_PLOGI;
        if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
        ctx->type = SRB_LOGOUT_CMD;
        ctx->name = "logout";
        lio = ctx->u.iocb_cmd;
-       lio->timeout = qla2x00_async_logio_timeout;
+       lio->timeout = qla2x00_async_iocb_timeout;
        lio->done = qla2x00_async_logout_ctx_done;
        rval = qla2x00_start_sp(sp);
        if (rval != QLA_SUCCESS)
        ctx->type = SRB_ADISC_CMD;
        ctx->name = "adisc";
        lio = ctx->u.iocb_cmd;
-       lio->timeout = qla2x00_async_logio_timeout;
+       lio->timeout = qla2x00_async_iocb_timeout;
        lio->done = qla2x00_async_adisc_ctx_done;
        if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
                lio->u.logio.flags |= SRB_LOGIN_RETRIED;
        return rval;
 }
 
+static void
+qla2x00_async_tm_cmd_ctx_done(srb_t *sp)
+{
+       struct srb_ctx *ctx = sp->ctx;
+       struct srb_iocb *iocb = (struct srb_iocb *)ctx->u.iocb_cmd;
+
+       qla2x00_async_tm_cmd_done(sp->fcport->vha, sp->fcport, iocb);
+       iocb->free(sp);
+}
+
+int
+qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
+       uint32_t tag)
+{
+       struct scsi_qla_host *vha = fcport->vha;
+       struct qla_hw_data *ha = vha->hw;
+       srb_t *sp;
+       struct srb_ctx *ctx;
+       struct srb_iocb *tcf;
+       int rval;
+
+       rval = QLA_FUNCTION_FAILED;
+       sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_ctx),
+           ELS_TMO_2_RATOV(ha) + 2);
+       if (!sp)
+               goto done;
+
+       ctx = sp->ctx;
+       ctx->type = SRB_TM_CMD;
+       ctx->name = "tmf";
+       tcf = ctx->u.iocb_cmd;
+       tcf->u.tmf.flags = flags;
+       tcf->u.tmf.lun = lun;
+       tcf->u.tmf.data = tag;
+       tcf->timeout = qla2x00_async_iocb_timeout;
+       tcf->done = qla2x00_async_tm_cmd_ctx_done;
+
+       rval = qla2x00_start_sp(sp);
+       if (rval != QLA_SUCCESS)
+               goto done_free_sp;
+
+       DEBUG2(printk(KERN_DEBUG
+           "scsi(%ld:%x): Async-tmf - loop-id=%x portid=%02x%02x%02x.\n",
+           fcport->vha->host_no, sp->handle, fcport->loop_id,
+           fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa));
+
+       return rval;
+
+done_free_sp:
+       tcf->free(sp);
+done:
+       return rval;
+}
+
+static void
+qla2x00_async_marker_ctx_done(srb_t *sp)
+{
+       struct srb_ctx *ctx = sp->ctx;
+       struct srb_iocb *iocb = (struct srb_iocb *)ctx->u.iocb_cmd;
+
+       qla2x00_async_marker_done(sp->fcport->vha, sp->fcport, iocb);
+       iocb->free(sp);
+}
+
+int
+qla2x00_async_marker(fc_port_t *fcport, uint16_t lun, uint8_t modif)
+{
+       struct scsi_qla_host *vha = fcport->vha;
+       srb_t *sp;
+       struct srb_ctx *ctx;
+       struct srb_iocb *mrk;
+       int rval;
+
+       rval = QLA_FUNCTION_FAILED;
+       sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_ctx), 0);
+       if (!sp)
+               goto done;
+
+       ctx = sp->ctx;
+       ctx->type = SRB_MARKER_CMD;
+       ctx->name = "marker";
+       mrk = ctx->u.iocb_cmd;
+       mrk->u.marker.lun = lun;
+       mrk->u.marker.modif = modif;
+       mrk->timeout = qla2x00_async_iocb_timeout;
+       mrk->done = qla2x00_async_marker_ctx_done;
+
+       rval = qla2x00_start_sp(sp);
+       if (rval != QLA_SUCCESS)
+               goto done_free_sp;
+
+       DEBUG2(printk(KERN_DEBUG
+           "scsi(%ld:%x): Async-marker - loop-id=%x "
+           "portid=%02x%02x%02x.\n",
+           fcport->vha->host_no, sp->handle, fcport->loop_id,
+           fcport->d_id.b.domain, fcport->d_id.b.area,
+           fcport->d_id.b.al_pa));
+
+       return rval;
+
+done_free_sp:
+       mrk->free(sp);
+done:
+       return rval;
+}
+
 void
 qla2x00_async_login_done(struct scsi_qla_host *vha, fc_port_t *fcport,
     uint16_t *data)
        return;
 }
 
+void
+qla2x00_async_tm_cmd_done(struct scsi_qla_host *vha, fc_port_t *fcport,
+    struct srb_iocb *iocb)
+{
+       int rval;
+       uint32_t flags;
+       uint16_t lun;
+
+       flags = iocb->u.tmf.flags;
+       lun = (uint16_t)iocb->u.tmf.lun;
+
+       /* Issue Marker IOCB */
+       rval = qla2x00_async_marker(fcport, lun,
+               flags == TCF_LUN_RESET ? MK_SYNC_ID_LUN : MK_SYNC_ID);
+
+       if ((rval != QLA_SUCCESS) || iocb->u.tmf.data) {
+               DEBUG2_3_11(printk(KERN_WARNING
+                       "%s(%ld): TM IOCB failed (%x).\n",
+                       __func__, vha->host_no, rval));
+       }
+
+       return;
+}
+
+void
+qla2x00_async_marker_done(struct scsi_qla_host *vha, fc_port_t *fcport,
+    struct srb_iocb *iocb)
+{
+       /*
+        * Currently we dont have any specific post response processing
+        * for this IOCB. We'll just return success or failed
+        * depending on whether the IOCB command succeeded or failed.
+        */
+       if (iocb->u.tmf.data) {
+               DEBUG2_3_11(printk(KERN_WARNING
+                   "%s(%ld): Marker IOCB failed (%x).\n",
+                   __func__, vha->host_no, iocb->u.tmf.data));
+       }
+
+       return;
+}
+
 /****************************************************************************/
 /*                QLogic ISP2x00 Hardware Support Functions.                */
 /****************************************************************************/
 
        mbx->mb9 = cpu_to_le16(sp->fcport->vp_idx);
 }
 
+static void
+qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk)
+{
+       uint32_t flags;
+       unsigned int lun;
+       struct fc_port *fcport = sp->fcport;
+       scsi_qla_host_t *vha = fcport->vha;
+       struct qla_hw_data *ha = vha->hw;
+       struct srb_ctx *ctx = sp->ctx;
+       struct srb_iocb *iocb = ctx->u.iocb_cmd;
+       struct req_que *req = vha->req;
+
+       flags = iocb->u.tmf.flags;
+       lun = iocb->u.tmf.lun;
+
+       tsk->entry_type = TSK_MGMT_IOCB_TYPE;
+       tsk->entry_count = 1;
+       tsk->handle = MAKE_HANDLE(req->id, tsk->handle);
+       tsk->nport_handle = cpu_to_le16(fcport->loop_id);
+       tsk->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
+       tsk->control_flags = cpu_to_le32(flags);
+       tsk->port_id[0] = fcport->d_id.b.al_pa;
+       tsk->port_id[1] = fcport->d_id.b.area;
+       tsk->port_id[2] = fcport->d_id.b.domain;
+       tsk->vp_index = fcport->vp_idx;
+
+       if (flags == TCF_LUN_RESET) {
+               int_to_scsilun(lun, &tsk->lun);
+               host_to_fcp_swap((uint8_t *)&tsk->lun,
+                       sizeof(tsk->lun));
+       }
+}
+
+static void
+qla24xx_marker_iocb(srb_t *sp, struct mrk_entry_24xx *mrk)
+{
+       uint16_t lun;
+       uint8_t modif;
+       struct fc_port *fcport = sp->fcport;
+       scsi_qla_host_t *vha = fcport->vha;
+       struct srb_ctx *ctx = sp->ctx;
+       struct srb_iocb *iocb = ctx->u.iocb_cmd;
+       struct req_que *req = vha->req;
+
+       lun = iocb->u.marker.lun;
+       modif = iocb->u.marker.modif;
+       mrk->entry_type = MARKER_TYPE;
+       mrk->modifier = modif;
+       if (modif !=  MK_SYNC_ALL) {
+               mrk->nport_handle = cpu_to_le16(fcport->loop_id);
+               mrk->lun[1] = LSB(lun);
+               mrk->lun[2] = MSB(lun);
+               host_to_fcp_swap(mrk->lun, sizeof(mrk->lun));
+               mrk->vp_index = vha->vp_idx;
+               mrk->handle = MAKE_HANDLE(req->id, mrk->handle);
+       }
+}
+
 static void
 qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb)
 {
                    qla24xx_adisc_iocb(sp, pkt) :
                    qla2x00_adisc_iocb(sp, pkt);
                break;
+       case SRB_TM_CMD:
+               qla24xx_tm_iocb(sp, pkt);
+               break;
+       case SRB_MARKER_CMD:
+               qla24xx_marker_iocb(sp, pkt);
+               break;
        default:
                break;
        }
 
        lio->done(sp);
 }
 
+static void
+qla24xx_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
+    struct tsk_mgmt_entry *tsk)
+{
+       const char func[] = "TMF-IOCB";
+       const char *type;
+       fc_port_t *fcport;
+       srb_t *sp;
+       struct srb_iocb *iocb;
+       struct srb_ctx *ctx;
+       struct sts_entry_24xx *sts = (struct sts_entry_24xx *)tsk;
+       int error = 1;
+
+       sp = qla2x00_get_sp_from_handle(vha, func, req, tsk);
+       if (!sp)
+               return;
+
+       ctx = sp->ctx;
+       iocb = ctx->u.iocb_cmd;
+       type = ctx->name;
+       fcport = sp->fcport;
+
+       if (sts->entry_status) {
+               DEBUG2(printk(KERN_WARNING
+                   "scsi(%ld:%x): Async-%s error - entry-status(%x).\n",
+                   fcport->vha->host_no, sp->handle, type,
+                   sts->entry_status));
+       } else if (sts->comp_status != __constant_cpu_to_le16(CS_COMPLETE)) {
+               DEBUG2(printk(KERN_WARNING
+                   "scsi(%ld:%x): Async-%s error - completion status(%x).\n",
+                   fcport->vha->host_no, sp->handle, type,
+                   sts->comp_status));
+       } else if (!(le16_to_cpu(sts->scsi_status) &
+           SS_RESPONSE_INFO_LEN_VALID)) {
+               DEBUG2(printk(KERN_WARNING
+                   "scsi(%ld:%x): Async-%s error - no response info(%x).\n",
+                   fcport->vha->host_no, sp->handle, type,
+                   sts->scsi_status));
+       } else if (le32_to_cpu(sts->rsp_data_len) < 4) {
+               DEBUG2(printk(KERN_WARNING
+                   "scsi(%ld:%x): Async-%s error - not enough response(%d).\n",
+                   fcport->vha->host_no, sp->handle, type,
+                   sts->rsp_data_len));
+       } else if (sts->data[3]) {
+               DEBUG2(printk(KERN_WARNING
+                   "scsi(%ld:%x): Async-%s error - response(%x).\n",
+                   fcport->vha->host_no, sp->handle, type,
+                   sts->data[3]));
+       } else {
+               error = 0;
+       }
+
+       if (error) {
+               iocb->u.tmf.data = error;
+               DEBUG2(qla2x00_dump_buffer((uint8_t *)sts, sizeof(*sts)));
+       }
+
+       iocb->done(sp);
+}
+
+static void
+qla24xx_marker_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
+    struct mrk_entry_24xx *mrk)
+{
+       const char func[] = "MRK-IOCB";
+       const char *type;
+       fc_port_t *fcport;
+       srb_t *sp;
+       struct srb_iocb *iocb;
+       struct srb_ctx *ctx;
+       struct sts_entry_24xx *sts = (struct sts_entry_24xx *)mrk;
+
+       sp = qla2x00_get_sp_from_handle(vha, func, req, mrk);
+       if (!sp)
+               return;
+
+       ctx = sp->ctx;
+       iocb = ctx->u.iocb_cmd;
+       type = ctx->name;
+       fcport = sp->fcport;
+
+       if (sts->entry_status) {
+               iocb->u.marker.data = 1;
+               DEBUG2(printk(KERN_WARNING
+                   "scsi(%ld:%x): Async-%s error entry - entry-status=%x.\n",
+                   fcport->vha->host_no, sp->handle, type,
+                   sts->entry_status));
+               DEBUG2(qla2x00_dump_buffer((uint8_t *)mrk, sizeof(*sts)));
+       }
+
+       iocb->done(sp);
+}
+
 /**
  * qla2x00_process_response_queue() - Process response queue entries.
  * @ha: SCSI driver HA context
                case MBX_IOCB_TYPE:
                        qla2x00_mbx_iocb_entry(vha, rsp->req,
                            (struct mbx_entry *)pkt);
+                       break;
                default:
                        /* Type Not Supported. */
                        DEBUG4(printk(KERN_WARNING
                        qla24xx_logio_entry(vha, rsp->req,
                            (struct logio_entry_24xx *)pkt);
                        break;
+               case TSK_MGMT_IOCB_TYPE:
+                       qla24xx_tm_iocb_entry(vha, rsp->req,
+                           (struct tsk_mgmt_entry *)pkt);
+                       break;
+               case MARKER_TYPE:
+                       qla24xx_marker_iocb_entry(vha, rsp->req,
+                           (struct mrk_entry_24xx *)pkt);
+                       break;
                 case CT_IOCB_TYPE:
                        qla24xx_els_ct_entry(vha, rsp->req, pkt, CT_IOCB_TYPE);
                        clear_bit(MBX_INTERRUPT, &vha->hw->mbx_cmd_flags);
 
 int
 qla24xx_abort_target(struct fc_port *fcport, unsigned int l, int tag)
 {
+       struct qla_hw_data *ha = fcport->vha->hw;
+
+       if ((ql2xasynctmfenable) && IS_FWI2_CAPABLE(ha))
+               return qla2x00_async_tm_cmd(fcport, TCF_TARGET_RESET, l, tag);
+
        return __qla24xx_issue_tmf("Target", TCF_TARGET_RESET, fcport, l, tag);
 }
 
 int
 qla24xx_lun_reset(struct fc_port *fcport, unsigned int l, int tag)
 {
+       struct qla_hw_data *ha = fcport->vha->hw;
+
+       if ((ql2xasynctmfenable) && IS_FWI2_CAPABLE(ha))
+               return qla2x00_async_tm_cmd(fcport, TCF_LUN_RESET, l, tag);
+
        return __qla24xx_issue_tmf("Lun", TCF_LUN_RESET, fcport, l, tag);
 }
 
 
        " 1 -- Do not reset on failure.\n");
 
 
+int ql2xasynctmfenable;
+module_param(ql2xasynctmfenable, int, S_IRUGO|S_IRUSR);
+MODULE_PARM_DESC(ql2xasynctmfenable,
+               "Enables issue of TM IOCBs asynchronously via IOCB mechanism"
+               "Default is 0 - Issue TM IOCBs via mailbox mechanism.");
 /*
  * SCSI host template entry points
  */