[SCSI] qla2xxx: Proper clean-up of BSG requests when request times out.
Fix for BSG request cleanup when the request timesout. Proper release of driver resources used for BSG request during timeout cleanup. Cc: stable@kernel.org Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
This commit is contained in:
parent
236b0249c2
commit
db3ad7f885
2 changed files with 65 additions and 71 deletions
|
@ -1882,12 +1882,6 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job)
|
||||||
ha = vha->hw;
|
ha = vha->hw;
|
||||||
type = "FC_BSG_RPT_ELS";
|
type = "FC_BSG_RPT_ELS";
|
||||||
|
|
||||||
DEBUG2(printk(KERN_INFO
|
|
||||||
"scsi(%ld): loop-id=%x portid=%02x%02x%02x.\n",
|
|
||||||
fcport->vha->host_no, fcport->loop_id,
|
|
||||||
fcport->d_id.b.domain, fcport->d_id.b.area,
|
|
||||||
fcport->d_id.b.al_pa));
|
|
||||||
|
|
||||||
/* make sure the rport is logged in,
|
/* make sure the rport is logged in,
|
||||||
* if not perform fabric login
|
* if not perform fabric login
|
||||||
*/
|
*/
|
||||||
|
@ -1904,11 +1898,6 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job)
|
||||||
ha = vha->hw;
|
ha = vha->hw;
|
||||||
type = "FC_BSG_HST_ELS_NOLOGIN";
|
type = "FC_BSG_HST_ELS_NOLOGIN";
|
||||||
|
|
||||||
DEBUG2(printk(KERN_INFO
|
|
||||||
"scsi(%ld): loop-id=%x portid=%02x%02x%02x.\n",
|
|
||||||
vha->host_no, vha->loop_id,
|
|
||||||
vha->d_id.b.domain, vha->d_id.b.area, vha->d_id.b.al_pa));
|
|
||||||
|
|
||||||
/* Allocate a dummy fcport structure, since functions
|
/* Allocate a dummy fcport structure, since functions
|
||||||
* preparing the IOCB and mailbox command retrieves port
|
* preparing the IOCB and mailbox command retrieves port
|
||||||
* specific information from fcport structure. For Host based
|
* specific information from fcport structure. For Host based
|
||||||
|
@ -1934,9 +1923,12 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job)
|
||||||
NPH_FABRIC_CONTROLLER : NPH_F_PORT;
|
NPH_FABRIC_CONTROLLER : NPH_F_PORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG2(printk(KERN_INFO
|
if (!vha->flags.online) {
|
||||||
"scsi(%ld): vendor-id = %llu\n",
|
DEBUG2(qla_printk(KERN_WARNING, ha,
|
||||||
vha->host_no, host->hostt->vendor_id));
|
"host not online\n"));
|
||||||
|
rval = -EIO;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
req_sg_cnt =
|
req_sg_cnt =
|
||||||
dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
|
dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
|
||||||
|
@ -2059,6 +2051,13 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job)
|
||||||
goto done_unmap_sg;
|
goto done_unmap_sg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!vha->flags.online) {
|
||||||
|
DEBUG2(qla_printk(KERN_WARNING, ha,
|
||||||
|
"host not online\n"));
|
||||||
|
rval = -EIO;
|
||||||
|
goto done_unmap_sg;
|
||||||
|
}
|
||||||
|
|
||||||
loop_id =
|
loop_id =
|
||||||
(bsg_job->request->rqst_data.h_ct.preamble_word1 & 0xFF000000)
|
(bsg_job->request->rqst_data.h_ct.preamble_word1 & 0xFF000000)
|
||||||
>> 24;
|
>> 24;
|
||||||
|
@ -2161,6 +2160,13 @@ qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!vha->flags.online) {
|
||||||
|
DEBUG2(qla_printk(KERN_WARNING, ha,
|
||||||
|
"host not online\n"));
|
||||||
|
rval = -EIO;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
elreq.req_sg_cnt =
|
elreq.req_sg_cnt =
|
||||||
dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
|
dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
|
||||||
bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
|
bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
|
||||||
|
@ -2219,20 +2225,10 @@ qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job)
|
||||||
if (ha->current_topology != ISP_CFG_F) {
|
if (ha->current_topology != ISP_CFG_F) {
|
||||||
type = "FC_BSG_HST_VENDOR_LOOPBACK";
|
type = "FC_BSG_HST_VENDOR_LOOPBACK";
|
||||||
|
|
||||||
if ((IS_QLA81XX(ha)) &&
|
|
||||||
((elreq.options == 0) || (elreq.options == 2))) {
|
|
||||||
DEBUG2(qla_printk(KERN_INFO, ha, "scsi(%ld)"
|
|
||||||
"loopback option:0x%x not supported\n", vha->host_no, elreq.options));
|
|
||||||
rval = -EINVAL;
|
|
||||||
goto done_unmap_sg;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG2(qla_printk(KERN_INFO, ha,
|
DEBUG2(qla_printk(KERN_INFO, ha,
|
||||||
"scsi(%ld) bsg rqst type: %s vendor rqst type: %x options: %x.\n",
|
"scsi(%ld) bsg rqst type: %s vendor rqst type: %x options: %x.\n",
|
||||||
vha->host_no, type, vendor_cmd, elreq.options));
|
vha->host_no, type, vendor_cmd, elreq.options));
|
||||||
DEBUG2(qla_printk(KERN_INFO, ha,
|
|
||||||
"scsi(%ld) tx_addr: 0x%llx rx_addr: 0x%llx tx_sg_cnt: %x rx_sg_cnt: %x\n",
|
|
||||||
vha->host_no, (unsigned long long)elreq.send_dma, (unsigned long long)elreq.rcv_dma, elreq.req_sg_cnt, elreq.rsp_sg_cnt));
|
|
||||||
command_sent = INT_DEF_LB_LOOPBACK_CMD;
|
command_sent = INT_DEF_LB_LOOPBACK_CMD;
|
||||||
rval = qla2x00_loopback_test(vha, &elreq, response);
|
rval = qla2x00_loopback_test(vha, &elreq, response);
|
||||||
if (IS_QLA81XX(ha)) {
|
if (IS_QLA81XX(ha)) {
|
||||||
|
@ -2248,9 +2244,7 @@ qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job)
|
||||||
DEBUG2(qla_printk(KERN_INFO, ha,
|
DEBUG2(qla_printk(KERN_INFO, ha,
|
||||||
"scsi(%ld) bsg rqst type: %s vendor rqst type: %x options: %x.\n",
|
"scsi(%ld) bsg rqst type: %s vendor rqst type: %x options: %x.\n",
|
||||||
vha->host_no, type, vendor_cmd, elreq.options));
|
vha->host_no, type, vendor_cmd, elreq.options));
|
||||||
DEBUG2(qla_printk(KERN_INFO, ha,
|
|
||||||
"scsi(%ld) tx_addr: 0x%llx rx_addr: 0x%llx tx_sg_cnt: %x rx_sg_cnt: %x\n",
|
|
||||||
vha->host_no, (unsigned long long)elreq.send_dma, (unsigned long long)elreq.rcv_dma, elreq.req_sg_cnt, elreq.rsp_sg_cnt));
|
|
||||||
command_sent = INT_DEF_LB_ECHO_CMD;
|
command_sent = INT_DEF_LB_ECHO_CMD;
|
||||||
rval = qla2x00_echo_test(vha, &elreq, response);
|
rval = qla2x00_echo_test(vha, &elreq, response);
|
||||||
}
|
}
|
||||||
|
@ -2353,60 +2347,49 @@ qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job)
|
||||||
scsi_qla_host_t *vha = shost_priv(bsg_job->shost);
|
scsi_qla_host_t *vha = shost_priv(bsg_job->shost);
|
||||||
struct qla_hw_data *ha = vha->hw;
|
struct qla_hw_data *ha = vha->hw;
|
||||||
srb_t *sp;
|
srb_t *sp;
|
||||||
int i;
|
int cnt, que;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
uint16_t que_id;
|
|
||||||
struct req_que *req;
|
struct req_que *req;
|
||||||
struct rsp_que *rsp;
|
|
||||||
int found = 0;
|
|
||||||
struct srb_bsg *sp_bsg;
|
struct srb_bsg *sp_bsg;
|
||||||
|
|
||||||
/* find the bsg job from the active list of commands */
|
/* find the bsg job from the active list of commands */
|
||||||
spin_lock_irqsave(&ha->hardware_lock, flags);
|
spin_lock_irqsave(&ha->hardware_lock, flags);
|
||||||
req = ha->req_q_map[0];
|
for (que = 0; que < ha->max_req_queues; que++) {
|
||||||
que_id = req->id;
|
req = ha->req_q_map[que];
|
||||||
if (req->rsp)
|
if (!req)
|
||||||
rsp = req->rsp;
|
continue;
|
||||||
else
|
|
||||||
rsp = ha->rsp_q_map[que_id];
|
|
||||||
|
|
||||||
for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++ ) {
|
for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++ ) {
|
||||||
sp = req->outstanding_cmds[i];
|
sp = req->outstanding_cmds[cnt];
|
||||||
|
|
||||||
if (sp == NULL)
|
if (sp) {
|
||||||
continue;
|
sp_bsg = (struct srb_bsg*)sp->ctx;
|
||||||
|
|
||||||
sp_bsg = (struct srb_bsg*)sp->ctx;
|
if (((sp_bsg->ctx.type == SRB_CT_CMD) ||
|
||||||
|
(sp_bsg->ctx.type == SRB_ELS_CMD_RPT)
|
||||||
if (((sp_bsg->ctx.type == SRB_CT_CMD) ||
|
|| ( sp_bsg->ctx.type == SRB_ELS_CMD_HST)) &&
|
||||||
(sp_bsg->ctx.type == SRB_ELS_CMD_RPT)
|
(sp_bsg->bsg_job == bsg_job)) {
|
||||||
|| ( sp_bsg->ctx.type == SRB_ELS_CMD_HST)) &&
|
if (ha->isp_ops->abort_command(sp)) {
|
||||||
(sp_bsg->bsg_job == bsg_job)) {
|
DEBUG2(qla_printk(KERN_INFO, ha,
|
||||||
DEBUG2(qla_printk(KERN_INFO, ha,
|
"scsi(%ld): mbx abort_command failed\n", vha->host_no));
|
||||||
"scsi(%ld) req_q: %p rsp_q: %p que_id: %x sp: %p\n",
|
bsg_job->req->errors = bsg_job->reply->result = -EIO;
|
||||||
vha->host_no, req, rsp, que_id, sp));
|
} else {
|
||||||
found = 1;
|
DEBUG2(qla_printk(KERN_INFO, ha,
|
||||||
break;
|
"scsi(%ld): mbx abort_command success\n", vha->host_no));
|
||||||
|
bsg_job->req->errors = bsg_job->reply->result = 0;
|
||||||
|
}
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||||
if (!found) {
|
DEBUG2(qla_printk(KERN_INFO, ha,
|
||||||
DEBUG2(qla_printk(KERN_INFO, ha,
|
"scsi(%ld) SRB not found to abort\n", vha->host_no));
|
||||||
"scsi(%ld) SRB not found to abort\n", vha->host_no));
|
bsg_job->req->errors = bsg_job->reply->result = -ENXIO;
|
||||||
bsg_job->req->errors = bsg_job->reply->result = -ENXIO;
|
return 0;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ha->isp_ops->abort_command(sp)) {
|
|
||||||
DEBUG2(qla_printk(KERN_INFO, ha,
|
|
||||||
"scsi(%ld): mbx abort_command failed\n", vha->host_no));
|
|
||||||
bsg_job->req->errors = bsg_job->reply->result = -EIO;
|
|
||||||
} else {
|
|
||||||
DEBUG2(qla_printk(KERN_INFO, ha,
|
|
||||||
"scsi(%ld): mbx abort_command success\n", vha->host_no));
|
|
||||||
bsg_job->req->errors = bsg_job->reply->result = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
done:
|
||||||
if (bsg_job->request->msgcode == FC_BSG_HST_CT)
|
if (bsg_job->request->msgcode == FC_BSG_HST_CT)
|
||||||
kfree(sp->fcport);
|
kfree(sp->fcport);
|
||||||
kfree(sp->ctx);
|
kfree(sp->ctx);
|
||||||
|
|
|
@ -1160,8 +1160,19 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res)
|
||||||
qla2x00_sp_compl(ha, sp);
|
qla2x00_sp_compl(ha, sp);
|
||||||
} else {
|
} else {
|
||||||
ctx = sp->ctx;
|
ctx = sp->ctx;
|
||||||
del_timer_sync(&ctx->timer);
|
if (ctx->type == SRB_LOGIN_CMD || ctx->type == SRB_LOGOUT_CMD) {
|
||||||
ctx->free(sp);
|
del_timer_sync(&ctx->timer);
|
||||||
|
ctx->free(sp);
|
||||||
|
} else {
|
||||||
|
struct srb_bsg* sp_bsg = (struct srb_bsg*)sp->ctx;
|
||||||
|
if (sp_bsg->bsg_job->request->msgcode == FC_BSG_HST_CT)
|
||||||
|
kfree(sp->fcport);
|
||||||
|
sp_bsg->bsg_job->req->errors = 0;
|
||||||
|
sp_bsg->bsg_job->reply->result = res;
|
||||||
|
sp_bsg->bsg_job->job_done(sp_bsg->bsg_job);
|
||||||
|
kfree(sp->ctx);
|
||||||
|
mempool_free(sp, ha->srb_mempool);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue