Commit 2b983f21 authored by Quinn Tran's avatar Quinn Tran Committed by Greg Kroah-Hartman

scsi: qla2xxx: Remove all rports if fabric scan retry fails

[ Upstream commit 9ba1cb25 ]

When all fabric scan retries fail, remove all RPorts, DMA resources for the
command. Otherwise we have stale Rports.
Signed-off-by: default avatarQuinn Tran <quinn.tran@cavium.com>
Signed-off-by: default avatarHimanshu Madhani <himanshu.madhani@cavium.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 6b449e4c
...@@ -4045,6 +4045,41 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp) ...@@ -4045,6 +4045,41 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
} }
} }
static int qla2x00_post_gnnft_gpnft_done_work(struct scsi_qla_host *vha,
srb_t *sp, int cmd)
{
struct qla_work_evt *e;
if (cmd != QLA_EVT_GPNFT_DONE && cmd != QLA_EVT_GNNFT_DONE)
return QLA_PARAMETER_ERROR;
e = qla2x00_alloc_work(vha, cmd);
if (!e)
return QLA_FUNCTION_FAILED;
e->u.iosb.sp = sp;
return qla2x00_post_work(vha, e);
}
static int qla2x00_post_nvme_gpnft_done_work(struct scsi_qla_host *vha,
srb_t *sp, int cmd)
{
struct qla_work_evt *e;
if (cmd != QLA_EVT_GPNFT)
return QLA_PARAMETER_ERROR;
e = qla2x00_alloc_work(vha, cmd);
if (!e)
return QLA_FUNCTION_FAILED;
e->u.gpnft.fc4_type = FC4_TYPE_NVME;
e->u.gpnft.sp = sp;
return qla2x00_post_work(vha, e);
}
static void qla2x00_find_free_fcp_nvme_slot(struct scsi_qla_host *vha, static void qla2x00_find_free_fcp_nvme_slot(struct scsi_qla_host *vha,
struct srb *sp) struct srb *sp)
{ {
...@@ -4145,22 +4180,36 @@ static void qla2x00_async_gpnft_gnnft_sp_done(void *s, int res) ...@@ -4145,22 +4180,36 @@ static void qla2x00_async_gpnft_gnnft_sp_done(void *s, int res)
{ {
struct srb *sp = s; struct srb *sp = s;
struct scsi_qla_host *vha = sp->vha; struct scsi_qla_host *vha = sp->vha;
struct qla_work_evt *e;
struct ct_sns_req *ct_req = struct ct_sns_req *ct_req =
(struct ct_sns_req *)sp->u.iocb_cmd.u.ctarg.req; (struct ct_sns_req *)sp->u.iocb_cmd.u.ctarg.req;
u16 cmd = be16_to_cpu(ct_req->command); u16 cmd = be16_to_cpu(ct_req->command);
u8 fc4_type = sp->gen2; u8 fc4_type = sp->gen2;
unsigned long flags; unsigned long flags;
int rc;
/* gen2 field is holding the fc4type */ /* gen2 field is holding the fc4type */
ql_dbg(ql_dbg_disc, vha, 0xffff, ql_dbg(ql_dbg_disc, vha, 0xffff,
"Async done-%s res %x FC4Type %x\n", "Async done-%s res %x FC4Type %x\n",
sp->name, res, sp->gen2); sp->name, res, sp->gen2);
sp->rc = res;
if (res) { if (res) {
unsigned long flags; unsigned long flags;
const char *name = sp->name;
/*
* We are in an Interrupt context, queue up this
* sp for GNNFT_DONE work. This will allow all
* the resource to get freed up.
*/
rc = qla2x00_post_gnnft_gpnft_done_work(vha, sp,
QLA_EVT_GNNFT_DONE);
if (rc) {
/* Cleanup here to prevent memory leak */
qla24xx_sp_unmap(vha, sp);
sp->free(sp);
}
sp->free(sp);
spin_lock_irqsave(&vha->work_lock, flags); spin_lock_irqsave(&vha->work_lock, flags);
vha->scan.scan_flags &= ~SF_SCANNING; vha->scan.scan_flags &= ~SF_SCANNING;
vha->scan.scan_retry++; vha->scan.scan_retry++;
...@@ -4171,9 +4220,9 @@ static void qla2x00_async_gpnft_gnnft_sp_done(void *s, int res) ...@@ -4171,9 +4220,9 @@ static void qla2x00_async_gpnft_gnnft_sp_done(void *s, int res)
set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
qla2xxx_wake_dpc(vha); qla2xxx_wake_dpc(vha);
} else { } else {
ql_dbg(ql_dbg_disc, sp->vha, 0xffff, ql_dbg(ql_dbg_disc, vha, 0xffff,
"Async done-%s rescan failed on all retries\n", "Async done-%s rescan failed on all retries.\n",
sp->name); name);
} }
return; return;
} }
...@@ -4188,80 +4237,31 @@ static void qla2x00_async_gpnft_gnnft_sp_done(void *s, int res) ...@@ -4188,80 +4237,31 @@ static void qla2x00_async_gpnft_gnnft_sp_done(void *s, int res)
vha->scan.scan_flags &= ~SF_SCANNING; vha->scan.scan_flags &= ~SF_SCANNING;
spin_unlock_irqrestore(&vha->work_lock, flags); spin_unlock_irqrestore(&vha->work_lock, flags);
e = qla2x00_alloc_work(vha, QLA_EVT_GPNFT); sp->rc = res;
if (!e) { rc = qla2x00_post_nvme_gpnft_done_work(vha, sp, QLA_EVT_GPNFT);
/* if (!rc) {
* please ignore kernel warning. Otherwise, qla24xx_sp_unmap(vha, sp);
* we have mem leak.
*/
if (sp->u.iocb_cmd.u.ctarg.req) {
dma_free_coherent(&vha->hw->pdev->dev,
sp->u.iocb_cmd.u.ctarg.req_allocated_size,
sp->u.iocb_cmd.u.ctarg.req,
sp->u.iocb_cmd.u.ctarg.req_dma);
sp->u.iocb_cmd.u.ctarg.req = NULL;
}
if (sp->u.iocb_cmd.u.ctarg.rsp) {
dma_free_coherent(&vha->hw->pdev->dev,
sp->u.iocb_cmd.u.ctarg.rsp_allocated_size,
sp->u.iocb_cmd.u.ctarg.rsp,
sp->u.iocb_cmd.u.ctarg.rsp_dma);
sp->u.iocb_cmd.u.ctarg.rsp = NULL;
}
ql_dbg(ql_dbg_disc, vha, 0xffff,
"Async done-%s unable to alloc work element\n",
sp->name);
sp->free(sp);
set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
return; return;
} }
e->u.gpnft.fc4_type = FC4_TYPE_NVME;
sp->rc = res;
e->u.gpnft.sp = sp;
qla2x00_post_work(vha, e);
return;
} }
if (cmd == GPN_FT_CMD) { if (cmd == GPN_FT_CMD) {
del_timer(&sp->u.iocb_cmd.timer); del_timer(&sp->u.iocb_cmd.timer);
e = qla2x00_alloc_work(vha, QLA_EVT_GPNFT_DONE); rc = qla2x00_post_gnnft_gpnft_done_work(vha, sp,
QLA_EVT_GPNFT_DONE);
} else { } else {
e = qla2x00_alloc_work(vha, QLA_EVT_GNNFT_DONE); rc = qla2x00_post_gnnft_gpnft_done_work(vha, sp,
QLA_EVT_GNNFT_DONE);
} }
if (!e) { if (rc) {
/* please ignore kernel warning. Otherwise, we have mem leak. */ qla24xx_sp_unmap(vha, sp);
if (sp->u.iocb_cmd.u.ctarg.req) {
dma_free_coherent(&vha->hw->pdev->dev,
sp->u.iocb_cmd.u.ctarg.req_allocated_size,
sp->u.iocb_cmd.u.ctarg.req,
sp->u.iocb_cmd.u.ctarg.req_dma);
sp->u.iocb_cmd.u.ctarg.req = NULL;
}
if (sp->u.iocb_cmd.u.ctarg.rsp) {
dma_free_coherent(&vha->hw->pdev->dev,
sp->u.iocb_cmd.u.ctarg.rsp_allocated_size,
sp->u.iocb_cmd.u.ctarg.rsp,
sp->u.iocb_cmd.u.ctarg.rsp_dma);
sp->u.iocb_cmd.u.ctarg.rsp = NULL;
}
ql_dbg(ql_dbg_disc, vha, 0xffff,
"Async done-%s unable to alloc work element\n",
sp->name);
sp->free(sp);
set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
return; return;
} }
sp->rc = res;
e->u.iosb.sp = sp;
qla2x00_post_work(vha, e);
} }
/* /*
......
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