summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx/qla_gs.c
diff options
context:
space:
mode:
authorQuinn Tran <quinn.tran@cavium.com>2017-12-04 23:45:02 +0100
committerMartin K. Petersen <martin.petersen@oracle.com>2017-12-08 03:07:03 +0100
commit2d73ac6102d943c4be4945735a338005359c6abc (patch)
tree289aa4d960a737eb33a1de6b784617c79374ff8a /drivers/scsi/qla2xxx/qla_gs.c
parentscsi: qla2xxx: Retry switch command on time out (diff)
downloadlinux-2d73ac6102d943c4be4945735a338005359c6abc.tar.xz
linux-2d73ac6102d943c4be4945735a338005359c6abc.zip
scsi: qla2xxx: Serialize GPNID for multiple RSCN
GPNID is triggered by RSCN. For multiple RSCNs of the same affected NPORT ID, serialize the GPNID to prevent confusion. Fixes: 726b85487067d ("qla2xxx: Add framework for async fabric discovery") Cc: <stable@vger.kernel.org> # 4.10+ Signed-off-by: Quinn Tran <quinn.tran@cavium.com> Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_gs.c')
-rw-r--r--drivers/scsi/qla2xxx/qla_gs.c35
1 files changed, 30 insertions, 5 deletions
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index ea1b562ebc8a..59ecc4eda6cd 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -3221,16 +3221,17 @@ static void qla2x00_async_gpnid_sp_done(void *s, int res)
(struct ct_sns_rsp *)sp->u.iocb_cmd.u.ctarg.rsp;
struct event_arg ea;
struct qla_work_evt *e;
+ unsigned long flags;
if (res)
ql_dbg(ql_dbg_disc, vha, 0x2066,
- "Async done-%s fail res %x ID %3phC. %8phC\n",
- sp->name, res, ct_req->req.port_id.port_id,
+ "Async done-%s fail res %x rscn gen %d ID %3phC. %8phC\n",
+ sp->name, res, sp->gen1, ct_req->req.port_id.port_id,
ct_rsp->rsp.gpn_id.port_name);
else
ql_dbg(ql_dbg_disc, vha, 0x2066,
- "Async done-%s good ID %3phC. %8phC\n",
- sp->name, ct_req->req.port_id.port_id,
+ "Async done-%s good rscn gen %d ID %3phC. %8phC\n",
+ sp->name, sp->gen1, ct_req->req.port_id.port_id,
ct_rsp->rsp.gpn_id.port_name);
memset(&ea, 0, sizeof(ea));
@@ -3242,11 +3243,20 @@ static void qla2x00_async_gpnid_sp_done(void *s, int res)
ea.rc = res;
ea.event = FCME_GPNID_DONE;
+ spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
+ list_del(&sp->elem);
+ spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
+
if (res) {
if (res == QLA_FUNCTION_TIMEOUT)
qla24xx_post_gpnid_work(sp->vha, &ea.id);
sp->free(sp);
return;
+ } else if (sp->gen1) {
+ /* There was anoter RSNC for this Nport ID */
+ qla24xx_post_gpnid_work(sp->vha, &ea.id);
+ sp->free(sp);
+ return;
}
qla2x00_fcport_event_handler(vha, &ea);
@@ -3282,8 +3292,9 @@ int qla24xx_async_gpnid(scsi_qla_host_t *vha, port_id_t *id)
{
int rval = QLA_FUNCTION_FAILED;
struct ct_sns_req *ct_req;
- srb_t *sp;
+ srb_t *sp, *tsp;
struct ct_sns_pkt *ct_sns;
+ unsigned long flags;
if (!vha->flags.online)
goto done;
@@ -3294,8 +3305,22 @@ int qla24xx_async_gpnid(scsi_qla_host_t *vha, port_id_t *id)
sp->type = SRB_CT_PTHRU_CMD;
sp->name = "gpnid";
+ sp->u.iocb_cmd.u.ctarg.id = *id;
+ sp->gen1 = 0;
qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+ spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
+ list_for_each_entry(tsp, &vha->gpnid_list, elem) {
+ if (tsp->u.iocb_cmd.u.ctarg.id.b24 == id->b24) {
+ tsp->gen1++;
+ spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
+ sp->free(sp);
+ goto done;
+ }
+ }
+ list_add_tail(&sp->elem, &vha->gpnid_list);
+ spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
+
sp->u.iocb_cmd.u.ctarg.req = dma_alloc_coherent(&vha->hw->pdev->dev,
sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.req_dma,
GFP_KERNEL);