Skip to content

Commit

Permalink
[SCSI] qla2xxx: Support for asynchronous TM and Marker IOCBs.
Browse files Browse the repository at this point in the history
Currently we can only issue the task management (TM)
commands via the mailbox mechanism. This is a limitation,
since only one mailbox command can be issued at a time.
The purpose of this effort is to provide support for
issuing and processing the respose to TM and Marker
IOCBs asynchronously. Towards achieving this, the
consolidated srb architecture that is currently used for
BSG and IOCB/Logio commands has been enhanced and used.

Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
  • Loading branch information
Madhuranath Iyengar authored and James Bottomley committed May 16, 2010
1 parent 4916392 commit 3822263
Show file tree
Hide file tree
Showing 8 changed files with 366 additions and 4 deletions.
4 changes: 4 additions & 0 deletions drivers/scsi/qla2xxx/qla_bsg.c
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,9 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job)
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,
Expand Down Expand Up @@ -450,6 +453,7 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job)

ct = sp->ctx;
ct->type = SRB_CT_CMD;
ct->name = "bsg_ct";
ct->u.bsg_job = bsg_job;

DEBUG2(qla_printk(KERN_INFO, ha,
Expand Down
22 changes: 22 additions & 0 deletions drivers/scsi/qla2xxx/qla_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,26 @@ struct srb_iocb {
#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;
Expand All @@ -239,6 +259,8 @@ struct srb_iocb {
#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;
Expand Down
7 changes: 7 additions & 0 deletions drivers/scsi/qla2xxx/qla_gbl.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,18 @@ extern int qla2x00_async_login(struct scsi_qla_host *, fc_port_t *,
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 );
Expand All @@ -87,6 +93,7 @@ extern int ql2xetsenable;
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);
Expand Down
156 changes: 152 additions & 4 deletions drivers/scsi/qla2xxx/qla_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ qla2x00_get_ctx_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size,
#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;
Expand Down Expand Up @@ -170,7 +170,7 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
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)
Expand Down Expand Up @@ -222,7 +222,7 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport)
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)
Expand Down Expand Up @@ -271,7 +271,7 @@ qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t *fcport,
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;
Expand All @@ -292,6 +292,112 @@ qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t *fcport,
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)
Expand Down Expand Up @@ -360,6 +466,48 @@ qla2x00_async_adisc_done(struct scsi_qla_host *vha, fc_port_t *fcport,
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. */
/****************************************************************************/
Expand Down
64 changes: 64 additions & 0 deletions drivers/scsi/qla2xxx/qla_iocb.c
Original file line number Diff line number Diff line change
Expand Up @@ -1085,6 +1085,64 @@ qla2x00_adisc_iocb(srb_t *sp, struct mbx_entry *mbx)
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)
{
Expand Down Expand Up @@ -1239,6 +1297,12 @@ qla2x00_start_sp(srb_t *sp)
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;
}
Expand Down
Loading

0 comments on commit 3822263

Please sign in to comment.