scsi: qla2xxx: Change abort wait_loop from msleep to wait_event_timeout
This patch converts driver wait time from using msleep to wair_event_timeout to prevent race condition. Signed-off-by: Giridhar Malavali <gmalavali@marvell.com> Signed-off-by: Himanshu Madhani <hmadhani@marvell.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
b2d1453a45
commit
711a08d79f
|
@ -546,6 +546,7 @@ typedef struct srb {
|
||||||
int rc;
|
int rc;
|
||||||
int retry_count;
|
int retry_count;
|
||||||
struct completion comp;
|
struct completion comp;
|
||||||
|
wait_queue_head_t *cwaitq;
|
||||||
union {
|
union {
|
||||||
struct srb_iocb iocb_cmd;
|
struct srb_iocb iocb_cmd;
|
||||||
struct bsg_job *bsg_job;
|
struct bsg_job *bsg_job;
|
||||||
|
@ -4794,5 +4795,4 @@ struct sff_8247_a0 {
|
||||||
#include "qla_gbl.h"
|
#include "qla_gbl.h"
|
||||||
#include "qla_dbg.h"
|
#include "qla_dbg.h"
|
||||||
#include "qla_inline.h"
|
#include "qla_inline.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -726,7 +726,7 @@ qla2x00_sp_free_dma(void *ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
goto end;
|
return;
|
||||||
|
|
||||||
if (sp->flags & SRB_CRC_CTX_DSD_VALID) {
|
if (sp->flags & SRB_CRC_CTX_DSD_VALID) {
|
||||||
/* List assured to be having elements */
|
/* List assured to be having elements */
|
||||||
|
@ -751,12 +751,6 @@ qla2x00_sp_free_dma(void *ptr)
|
||||||
ha->gbl_dsd_avail += ctx1->dsd_use_cnt;
|
ha->gbl_dsd_avail += ctx1->dsd_use_cnt;
|
||||||
mempool_free(ctx1, ha->ctx_mempool);
|
mempool_free(ctx1, ha->ctx_mempool);
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
|
||||||
if (sp->type != SRB_NVME_CMD && sp->type != SRB_NVME_LS) {
|
|
||||||
CMD_SP(cmd) = NULL;
|
|
||||||
qla2x00_rel_sp(sp);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -764,6 +758,7 @@ qla2x00_sp_compl(void *ptr, int res)
|
||||||
{
|
{
|
||||||
srb_t *sp = ptr;
|
srb_t *sp = ptr;
|
||||||
struct scsi_cmnd *cmd = GET_CMD_SP(sp);
|
struct scsi_cmnd *cmd = GET_CMD_SP(sp);
|
||||||
|
wait_queue_head_t *cwaitq = sp->cwaitq;
|
||||||
|
|
||||||
if (atomic_read(&sp->ref_count) == 0) {
|
if (atomic_read(&sp->ref_count) == 0) {
|
||||||
ql_dbg(ql_dbg_io, sp->vha, 0x3015,
|
ql_dbg(ql_dbg_io, sp->vha, 0x3015,
|
||||||
|
@ -778,7 +773,11 @@ qla2x00_sp_compl(void *ptr, int res)
|
||||||
|
|
||||||
sp->free(sp);
|
sp->free(sp);
|
||||||
cmd->result = res;
|
cmd->result = res;
|
||||||
|
CMD_SP(cmd) = NULL;
|
||||||
cmd->scsi_done(cmd);
|
cmd->scsi_done(cmd);
|
||||||
|
if (cwaitq)
|
||||||
|
wake_up(cwaitq);
|
||||||
|
qla2x00_rel_sp(sp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -801,7 +800,7 @@ qla2xxx_qpair_sp_free_dma(void *ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
goto end;
|
return;
|
||||||
|
|
||||||
if (sp->flags & SRB_CRC_CTX_DSD_VALID) {
|
if (sp->flags & SRB_CRC_CTX_DSD_VALID) {
|
||||||
/* List assured to be having elements */
|
/* List assured to be having elements */
|
||||||
|
@ -861,10 +860,6 @@ qla2xxx_qpair_sp_free_dma(void *ptr)
|
||||||
}
|
}
|
||||||
sp->flags &= ~SRB_DIF_BUNDL_DMA_VALID;
|
sp->flags &= ~SRB_DIF_BUNDL_DMA_VALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
|
||||||
CMD_SP(cmd) = NULL;
|
|
||||||
qla2xxx_rel_qpair_sp(sp->qpair, sp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -872,8 +867,7 @@ qla2xxx_qpair_sp_compl(void *ptr, int res)
|
||||||
{
|
{
|
||||||
srb_t *sp = ptr;
|
srb_t *sp = ptr;
|
||||||
struct scsi_cmnd *cmd = GET_CMD_SP(sp);
|
struct scsi_cmnd *cmd = GET_CMD_SP(sp);
|
||||||
|
wait_queue_head_t *cwaitq = sp->cwaitq;
|
||||||
cmd->result = res;
|
|
||||||
|
|
||||||
if (atomic_read(&sp->ref_count) == 0) {
|
if (atomic_read(&sp->ref_count) == 0) {
|
||||||
ql_dbg(ql_dbg_io, sp->fcport->vha, 0x3079,
|
ql_dbg(ql_dbg_io, sp->fcport->vha, 0x3079,
|
||||||
|
@ -887,7 +881,12 @@ qla2xxx_qpair_sp_compl(void *ptr, int res)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
sp->free(sp);
|
sp->free(sp);
|
||||||
|
cmd->result = res;
|
||||||
|
CMD_SP(cmd) = NULL;
|
||||||
cmd->scsi_done(cmd);
|
cmd->scsi_done(cmd);
|
||||||
|
if (cwaitq)
|
||||||
|
wake_up(cwaitq);
|
||||||
|
qla2xxx_rel_qpair_sp(sp->qpair, sp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we are SP1 here, we need to still take and release the host_lock as SP1
|
/* If we are SP1 here, we need to still take and release the host_lock as SP1
|
||||||
|
@ -1377,7 +1376,6 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
|
||||||
vha->host_no, id, lun, sp, cmd, sp->handle);
|
vha->host_no, id, lun, sp, cmd, sp->handle);
|
||||||
|
|
||||||
/* Get a reference to the sp and drop the lock.*/
|
/* Get a reference to the sp and drop the lock.*/
|
||||||
|
|
||||||
rval = ha->isp_ops->abort_command(sp);
|
rval = ha->isp_ops->abort_command(sp);
|
||||||
if (rval) {
|
if (rval) {
|
||||||
if (rval == QLA_FUNCTION_PARAMETER_ERROR)
|
if (rval == QLA_FUNCTION_PARAMETER_ERROR)
|
||||||
|
@ -1394,37 +1392,46 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock_irqsave(qpair->qp_lock_ptr, flags);
|
spin_lock_irqsave(qpair->qp_lock_ptr, flags);
|
||||||
/*
|
|
||||||
* Clear the slot in the oustanding_cmds array if we can't find the
|
|
||||||
* command to reclaim the resources.
|
|
||||||
*/
|
|
||||||
if (rval == QLA_FUNCTION_PARAMETER_ERROR)
|
|
||||||
vha->req->outstanding_cmds[sp->handle] = NULL;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* sp->done will do ref_count--
|
* Releasing of the SRB and associated command resources
|
||||||
* sp_get() took an extra count above
|
* is managed through ref_count.
|
||||||
|
* Whether we need to wait for the abort completion or complete
|
||||||
|
* the abort handler should be based on the ref_count.
|
||||||
*/
|
*/
|
||||||
sp->done(sp, DID_RESET << 16);
|
if (atomic_read(&sp->ref_count) > 1) {
|
||||||
|
/*
|
||||||
|
* The command is not yet completed. We need to wait for either
|
||||||
|
* command completion or abort completion.
|
||||||
|
*/
|
||||||
|
DECLARE_WAIT_QUEUE_HEAD_ONSTACK(eh_waitq);
|
||||||
|
uint32_t ratov = ha->r_a_tov/10;
|
||||||
|
|
||||||
/* Did the command return during mailbox execution? */
|
/* Go ahead and release the extra ref_count obtained earlier */
|
||||||
if (ret == FAILED && !CMD_SP(cmd))
|
sp->done(sp, DID_RESET << 16);
|
||||||
ret = SUCCESS;
|
sp->cwaitq = &eh_waitq;
|
||||||
|
|
||||||
if (!CMD_SP(cmd))
|
if (!wait_event_lock_irq_timeout(eh_waitq,
|
||||||
wait = 0;
|
CMD_SP(cmd) == NULL, *qpair->qp_lock_ptr,
|
||||||
|
msecs_to_jiffies(4 * ratov * 1000))) {
|
||||||
spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
|
/*
|
||||||
|
* The abort got dropped, LOGO will be sent and the
|
||||||
/* Wait for the command to be returned. */
|
* original command will be completed with CS_TIMEOUT
|
||||||
if (wait) {
|
* completion
|
||||||
if (qla2x00_eh_wait_on_command(cmd) != QLA_SUCCESS) {
|
*/
|
||||||
ql_log(ql_log_warn, vha, 0x8006,
|
ql_dbg(ql_dbg_taskm, vha, 0xffff,
|
||||||
"Abort handler timed out cmd=%p.\n", cmd);
|
"%s: Abort wait timer (4 * R_A_TOV[%d]) expired\n",
|
||||||
|
__func__, ha->r_a_tov);
|
||||||
|
sp->cwaitq = NULL;
|
||||||
ret = FAILED;
|
ret = FAILED;
|
||||||
|
goto end;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
/* Command completed while processing the abort */
|
||||||
|
sp->done(sp, DID_RESET << 16);
|
||||||
}
|
}
|
||||||
|
end:
|
||||||
|
spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
|
||||||
ql_log(ql_log_info, vha, 0x801c,
|
ql_log(ql_log_info, vha, 0x801c,
|
||||||
"Abort command issued nexus=%ld:%d:%llu -- %d %x.\n",
|
"Abort command issued nexus=%ld:%d:%llu -- %d %x.\n",
|
||||||
vha->host_no, id, lun, wait, ret);
|
vha->host_no, id, lun, wait, ret);
|
||||||
|
|
Loading…
Reference in New Issue