Commit faef62d1 authored by Armen Baloyan's avatar Armen Baloyan Committed by James Bottomley

[SCSI] qla2xxx: Fix Task Management command asynchronous handling

- Fix interpreting the wrong IOCB type for task management
functions in the response path.
- Merge the task management function handling for various adapters.
Signed-off-by: default avatarArmen Baloyan <armen.baloyan@qlogic.com>
Signed-off-by: default avatarSaurav Kashyap <saurav.kashyap@qlogic.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 43a9c38b
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
* | | | 0x5047,0x5052 | * | | | 0x5047,0x5052 |
* | | | 0x5084,0x5075 | * | | | 0x5084,0x5075 |
* | | | 0x503d,0x5044 | * | | | 0x503d,0x5044 |
* | | | 0x507b |
* | Timer Routines | 0x6012 | | * | Timer Routines | 0x6012 | |
* | User Space Interactions | 0x70e2 | 0x7018,0x702e | * | User Space Interactions | 0x70e2 | 0x7018,0x702e |
* | | | 0x7020,0x7024 | * | | | 0x7020,0x7024 |
......
...@@ -271,56 +271,46 @@ qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t *fcport, ...@@ -271,56 +271,46 @@ qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t *fcport,
} }
static void static void
qla2x00_async_tm_cmd_done(void *data, void *ptr, int res) qla2x00_tmf_iocb_timeout(void *data)
{ {
srb_t *sp = (srb_t *)ptr; srb_t *sp = (srb_t *)data;
struct srb_iocb *iocb = &sp->u.iocb_cmd; struct srb_iocb *tmf = &sp->u.iocb_cmd;
struct scsi_qla_host *vha = (scsi_qla_host_t *)data;
uint32_t flags;
uint16_t lun;
int rval;
if (!test_bit(UNLOADING, &vha->dpc_flags)) {
flags = iocb->u.tmf.flags;
lun = (uint16_t)iocb->u.tmf.lun;
/* Issue Marker IOCB */ tmf->u.tmf.comp_status = CS_TIMEOUT;
rval = qla2x00_marker(vha, vha->hw->req_q_map[0], complete(&tmf->u.tmf.comp);
vha->hw->rsp_q_map[0], sp->fcport->loop_id, lun, }
flags == TCF_LUN_RESET ? MK_SYNC_ID_LUN : MK_SYNC_ID);
if ((rval != QLA_SUCCESS) || iocb->u.tmf.data) { static void
ql_dbg(ql_dbg_taskm, vha, 0x8030, qla2x00_tmf_sp_done(void *data, void *ptr, int res)
"TM IOCB failed (%x).\n", rval); {
} srb_t *sp = (srb_t *)ptr;
} struct srb_iocb *tmf = &sp->u.iocb_cmd;
sp->free(sp->fcport->vha, sp); complete(&tmf->u.tmf.comp);
} }
int int
qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t tm_flags, uint32_t lun, qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
uint32_t tag) uint32_t tag)
{ {
struct scsi_qla_host *vha = fcport->vha; struct scsi_qla_host *vha = fcport->vha;
struct srb_iocb *tm_iocb;
srb_t *sp; srb_t *sp;
struct srb_iocb *tcf; int rval = QLA_FUNCTION_FAILED;
int rval;
rval = QLA_FUNCTION_FAILED;
sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL); sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
if (!sp) if (!sp)
goto done; goto done;
tm_iocb = &sp->u.iocb_cmd;
sp->type = SRB_TM_CMD; sp->type = SRB_TM_CMD;
sp->name = "tmf"; sp->name = "tmf";
qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2); qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha));
tm_iocb->u.tmf.flags = flags;
tcf = &sp->u.iocb_cmd; tm_iocb->u.tmf.lun = lun;
tcf->u.tmf.flags = tm_flags; tm_iocb->u.tmf.data = tag;
tcf->u.tmf.lun = lun; sp->done = qla2x00_tmf_sp_done;
tcf->u.tmf.data = tag; tm_iocb->timeout = qla2x00_tmf_iocb_timeout;
tcf->timeout = qla2x00_async_iocb_timeout; init_completion(&tm_iocb->u.tmf.comp);
sp->done = qla2x00_async_tm_cmd_done;
rval = qla2x00_start_sp(sp); rval = qla2x00_start_sp(sp);
if (rval != QLA_SUCCESS) if (rval != QLA_SUCCESS)
...@@ -330,10 +320,29 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t tm_flags, uint32_t lun, ...@@ -330,10 +320,29 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t tm_flags, uint32_t lun,
"Async-tmf hdl=%x loop-id=%x portid=%02x%02x%02x.\n", "Async-tmf hdl=%x loop-id=%x portid=%02x%02x%02x.\n",
sp->handle, fcport->loop_id, fcport->d_id.b.domain, sp->handle, fcport->loop_id, fcport->d_id.b.domain,
fcport->d_id.b.area, fcport->d_id.b.al_pa); fcport->d_id.b.area, fcport->d_id.b.al_pa);
return rval;
wait_for_completion(&tm_iocb->u.tmf.comp);
rval = tm_iocb->u.tmf.comp_status == CS_COMPLETE ?
QLA_SUCCESS : QLA_FUNCTION_FAILED;
if ((rval != QLA_SUCCESS) || tm_iocb->u.tmf.data) {
ql_dbg(ql_dbg_taskm, vha, 0x8030,
"TM IOCB failed (%x).\n", rval);
}
if (!test_bit(UNLOADING, &vha->dpc_flags) && !IS_QLAFX00(vha->hw)) {
flags = tm_iocb->u.tmf.flags;
lun = (uint16_t)tm_iocb->u.tmf.lun;
/* Issue Marker IOCB */
qla2x00_marker(vha, vha->hw->req_q_map[0],
vha->hw->rsp_q_map[0], sp->fcport->loop_id, lun,
flags == TCF_LUN_RESET ? MK_SYNC_ID_LUN : MK_SYNC_ID);
}
done_free_sp: done_free_sp:
sp->free(fcport->vha, sp); sp->free(vha, sp);
done: done:
return rval; return rval;
} }
......
...@@ -1498,8 +1498,7 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req, ...@@ -1498,8 +1498,7 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
} }
static void static void
qla24xx_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, qla24xx_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, void *tsk)
struct tsk_mgmt_entry *tsk)
{ {
const char func[] = "TMF-IOCB"; const char func[] = "TMF-IOCB";
const char *type; const char *type;
...@@ -1507,7 +1506,6 @@ qla24xx_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, ...@@ -1507,7 +1506,6 @@ qla24xx_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
srb_t *sp; srb_t *sp;
struct srb_iocb *iocb; struct srb_iocb *iocb;
struct sts_entry_24xx *sts = (struct sts_entry_24xx *)tsk; struct sts_entry_24xx *sts = (struct sts_entry_24xx *)tsk;
int error = 1;
sp = qla2x00_get_sp_from_handle(vha, func, req, tsk); sp = qla2x00_get_sp_from_handle(vha, func, req, tsk);
if (!sp) if (!sp)
...@@ -1516,37 +1514,35 @@ qla24xx_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, ...@@ -1516,37 +1514,35 @@ qla24xx_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
iocb = &sp->u.iocb_cmd; iocb = &sp->u.iocb_cmd;
type = sp->name; type = sp->name;
fcport = sp->fcport; fcport = sp->fcport;
iocb->u.tmf.data = QLA_SUCCESS;
if (sts->entry_status) { if (sts->entry_status) {
ql_log(ql_log_warn, fcport->vha, 0x5038, ql_log(ql_log_warn, fcport->vha, 0x5038,
"Async-%s error - hdl=%x entry-status(%x).\n", "Async-%s error - hdl=%x entry-status(%x).\n",
type, sp->handle, sts->entry_status); type, sp->handle, sts->entry_status);
iocb->u.tmf.data = QLA_FUNCTION_FAILED;
} else if (sts->comp_status != __constant_cpu_to_le16(CS_COMPLETE)) { } else if (sts->comp_status != __constant_cpu_to_le16(CS_COMPLETE)) {
ql_log(ql_log_warn, fcport->vha, 0x5039, ql_log(ql_log_warn, fcport->vha, 0x5039,
"Async-%s error - hdl=%x completion status(%x).\n", "Async-%s error - hdl=%x completion status(%x).\n",
type, sp->handle, sts->comp_status); type, sp->handle, sts->comp_status);
} else if (!(le16_to_cpu(sts->scsi_status) & iocb->u.tmf.data = QLA_FUNCTION_FAILED;
} else if ((le16_to_cpu(sts->scsi_status) &
SS_RESPONSE_INFO_LEN_VALID)) { SS_RESPONSE_INFO_LEN_VALID)) {
ql_log(ql_log_warn, fcport->vha, 0x503a, if (le32_to_cpu(sts->rsp_data_len) < 4) {
"Async-%s error - hdl=%x no response info(%x).\n", ql_log(ql_log_warn, fcport->vha, 0x503b,
type, sp->handle, sts->scsi_status); "Async-%s error - hdl=%x not enough response(%d).\n",
} else if (le32_to_cpu(sts->rsp_data_len) < 4) { type, sp->handle, sts->rsp_data_len);
ql_log(ql_log_warn, fcport->vha, 0x503b, } else if (sts->data[3]) {
"Async-%s error - hdl=%x not enough response(%d).\n", ql_log(ql_log_warn, fcport->vha, 0x503c,
type, sp->handle, sts->rsp_data_len); "Async-%s error - hdl=%x response(%x).\n",
} else if (sts->data[3]) { type, sp->handle, sts->data[3]);
ql_log(ql_log_warn, fcport->vha, 0x503c, iocb->u.tmf.data = QLA_FUNCTION_FAILED;
"Async-%s error - hdl=%x response(%x).\n", }
type, sp->handle, sts->data[3]);
} else {
error = 0;
} }
if (error) { if (iocb->u.tmf.data != QLA_SUCCESS)
iocb->u.tmf.data = error;
ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5055, ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5055,
(uint8_t *)sts, sizeof(*sts)); (uint8_t *)sts, sizeof(*sts));
}
sp->done(vha, sp, 0); sp->done(vha, sp, 0);
} }
...@@ -2026,6 +2022,12 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) ...@@ -2026,6 +2022,12 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
return; return;
} }
/* Task Management completion. */
if (sp->type == SRB_TM_CMD) {
qla24xx_tm_iocb_entry(vha, req, pkt);
return;
}
/* Fast path completion. */ /* Fast path completion. */
if (comp_status == CS_COMPLETE && scsi_status == 0) { if (comp_status == CS_COMPLETE && scsi_status == 0) {
qla2x00_process_completed_request(vha, req, handle); qla2x00_process_completed_request(vha, req, handle);
...@@ -2475,10 +2477,6 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha, ...@@ -2475,10 +2477,6 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
qla24xx_logio_entry(vha, rsp->req, qla24xx_logio_entry(vha, rsp->req,
(struct logio_entry_24xx *)pkt); (struct logio_entry_24xx *)pkt);
break; break;
case TSK_MGMT_IOCB_TYPE:
qla24xx_tm_iocb_entry(vha, rsp->req,
(struct tsk_mgmt_entry *)pkt);
break;
case CT_IOCB_TYPE: case CT_IOCB_TYPE:
qla24xx_els_ct_entry(vha, rsp->req, pkt, CT_IOCB_TYPE); qla24xx_els_ct_entry(vha, rsp->req, pkt, CT_IOCB_TYPE);
break; break;
......
...@@ -685,78 +685,16 @@ qlafx00_disable_intrs(struct qla_hw_data *ha) ...@@ -685,78 +685,16 @@ qlafx00_disable_intrs(struct qla_hw_data *ha)
spin_unlock_irqrestore(&ha->hardware_lock, flags); spin_unlock_irqrestore(&ha->hardware_lock, flags);
} }
static void
qlafx00_tmf_iocb_timeout(void *data)
{
srb_t *sp = (srb_t *)data;
struct srb_iocb *tmf = &sp->u.iocb_cmd;
tmf->u.tmf.comp_status = cpu_to_le16((uint16_t)CS_TIMEOUT);
complete(&tmf->u.tmf.comp);
}
static void
qlafx00_tmf_sp_done(void *data, void *ptr, int res)
{
srb_t *sp = (srb_t *)ptr;
struct srb_iocb *tmf = &sp->u.iocb_cmd;
complete(&tmf->u.tmf.comp);
}
static int
qlafx00_async_tm_cmd(fc_port_t *fcport, uint32_t flags,
uint32_t lun, uint32_t tag)
{
scsi_qla_host_t *vha = fcport->vha;
struct srb_iocb *tm_iocb;
srb_t *sp;
int rval = QLA_FUNCTION_FAILED;
sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
if (!sp)
goto done;
tm_iocb = &sp->u.iocb_cmd;
sp->type = SRB_TM_CMD;
sp->name = "tmf";
qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha));
tm_iocb->u.tmf.flags = flags;
tm_iocb->u.tmf.lun = lun;
tm_iocb->u.tmf.data = tag;
sp->done = qlafx00_tmf_sp_done;
tm_iocb->timeout = qlafx00_tmf_iocb_timeout;
init_completion(&tm_iocb->u.tmf.comp);
rval = qla2x00_start_sp(sp);
if (rval != QLA_SUCCESS)
goto done_free_sp;
ql_dbg(ql_dbg_async, vha, 0x507b,
"Task management command issued target_id=%x\n",
fcport->tgt_id);
wait_for_completion(&tm_iocb->u.tmf.comp);
rval = tm_iocb->u.tmf.comp_status == CS_COMPLETE ?
QLA_SUCCESS : QLA_FUNCTION_FAILED;
done_free_sp:
sp->free(vha, sp);
done:
return rval;
}
int int
qlafx00_abort_target(fc_port_t *fcport, unsigned int l, int tag) qlafx00_abort_target(fc_port_t *fcport, unsigned int l, int tag)
{ {
return qlafx00_async_tm_cmd(fcport, TCF_TARGET_RESET, l, tag); return qla2x00_async_tm_cmd(fcport, TCF_TARGET_RESET, l, tag);
} }
int int
qlafx00_lun_reset(fc_port_t *fcport, unsigned int l, int tag) qlafx00_lun_reset(fc_port_t *fcport, unsigned int l, int tag)
{ {
return qlafx00_async_tm_cmd(fcport, TCF_LUN_RESET, l, tag); return qla2x00_async_tm_cmd(fcport, TCF_LUN_RESET, l, tag);
} }
int int
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment