Message ID | 20220308082048.9774-4-njavali@marvell.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | qla2xxx driver fixes | expand |
> On Mar 8, 2022, at 12:20 AM, Nilesh Javali <njavali@marvell.com> wrote: > > From: Arun Easi <aeasi@marvell.com> > > Driver registration of localport can race when it > happens at the remote port discovery time. Fix > this by calling the registration under a mutex. > > Reported-by: Marco Patalano <mpatalan@redhat.com> > Tested-by: Marco Patalano <mpatalan@redhat.com> > Cc: stable@vger.kernel.org > Fixes: e84067d74301 ("scsi: qla2xxx: Add FC-NVMe F/W initialization and transport registration") > Signed-off-by: Arun Easi <aeasi@marvell.com> > Signed-off-by: Nilesh Javali <njavali@marvell.com> > --- > drivers/scsi/qla2xxx/qla_nvme.c | 30 ++++++++++++++++++++---------- > 1 file changed, 20 insertions(+), 10 deletions(-) > > diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c > index 5723082d94d6..3bf5cbd754a7 100644 > --- a/drivers/scsi/qla2xxx/qla_nvme.c > +++ b/drivers/scsi/qla2xxx/qla_nvme.c > @@ -782,8 +782,6 @@ int qla_nvme_register_hba(struct scsi_qla_host *vha) > ha = vha->hw; > tmpl = &qla_nvme_fc_transport; > > - WARN_ON(vha->nvme_local_port); > - > if (ql2xnvme_queues < MIN_NVME_HW_QUEUES || ql2xnvme_queues > MAX_NVME_HW_QUEUES) { > ql_log(ql_log_warn, vha, 0xfffd, > "ql2xnvme_queues=%d is out of range(MIN:%d - MAX:%d). Resetting ql2xnvme_queues to:%d\n", > @@ -797,7 +795,7 @@ int qla_nvme_register_hba(struct scsi_qla_host *vha) > (uint8_t)(ha->max_qpairs ? ha->max_qpairs : 1)); > > ql_log(ql_log_info, vha, 0xfffb, > - "Number of NVME queues used for this port: %d\n", > + "Number of NVME queues used for this port: %d\n", > qla_nvme_fc_transport.max_hw_queues); > > pinfo.node_name = wwn_to_u64(vha->node_name); > @@ -805,13 +803,25 @@ int qla_nvme_register_hba(struct scsi_qla_host *vha) > pinfo.port_role = FC_PORT_ROLE_NVME_INITIATOR; > pinfo.port_id = vha->d_id.b24; > > - ql_log(ql_log_info, vha, 0xffff, > - "register_localport: host-traddr=nn-0x%llx:pn-0x%llx on portID:%x\n", > - pinfo.node_name, pinfo.port_name, pinfo.port_id); > - qla_nvme_fc_transport.dma_boundary = vha->host->dma_boundary; > - > - ret = nvme_fc_register_localport(&pinfo, tmpl, > - get_device(&ha->pdev->dev), &vha->nvme_local_port); > + mutex_lock(&ha->vport_lock); > + /* > + * Check again for nvme_local_port to see if any other thread raced > + * with this one and finished registration. > + */ > + if (!vha->nvme_local_port) { > + ql_log(ql_log_info, vha, 0xffff, > + "register_localport: host-traddr=nn-0x%llx:pn-0x%llx on portID:%x\n", > + pinfo.node_name, pinfo.port_name, pinfo.port_id); > + qla_nvme_fc_transport.dma_boundary = vha->host->dma_boundary; > + > + ret = nvme_fc_register_localport(&pinfo, tmpl, > + get_device(&ha->pdev->dev), > + &vha->nvme_local_port); > + mutex_unlock(&ha->vport_lock); > + } else { > + mutex_unlock(&ha->vport_lock); > + return 0; > + } > if (ret) { > ql_log(ql_log_warn, vha, 0xffff, > "register_localport failed: ret=%x\n", ret); > -- > 2.19.0.rc0 > Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com> -- Himanshu Madhani Oracle Linux Engineering
diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c index 5723082d94d6..3bf5cbd754a7 100644 --- a/drivers/scsi/qla2xxx/qla_nvme.c +++ b/drivers/scsi/qla2xxx/qla_nvme.c @@ -782,8 +782,6 @@ int qla_nvme_register_hba(struct scsi_qla_host *vha) ha = vha->hw; tmpl = &qla_nvme_fc_transport; - WARN_ON(vha->nvme_local_port); - if (ql2xnvme_queues < MIN_NVME_HW_QUEUES || ql2xnvme_queues > MAX_NVME_HW_QUEUES) { ql_log(ql_log_warn, vha, 0xfffd, "ql2xnvme_queues=%d is out of range(MIN:%d - MAX:%d). Resetting ql2xnvme_queues to:%d\n", @@ -797,7 +795,7 @@ int qla_nvme_register_hba(struct scsi_qla_host *vha) (uint8_t)(ha->max_qpairs ? ha->max_qpairs : 1)); ql_log(ql_log_info, vha, 0xfffb, - "Number of NVME queues used for this port: %d\n", + "Number of NVME queues used for this port: %d\n", qla_nvme_fc_transport.max_hw_queues); pinfo.node_name = wwn_to_u64(vha->node_name); @@ -805,13 +803,25 @@ int qla_nvme_register_hba(struct scsi_qla_host *vha) pinfo.port_role = FC_PORT_ROLE_NVME_INITIATOR; pinfo.port_id = vha->d_id.b24; - ql_log(ql_log_info, vha, 0xffff, - "register_localport: host-traddr=nn-0x%llx:pn-0x%llx on portID:%x\n", - pinfo.node_name, pinfo.port_name, pinfo.port_id); - qla_nvme_fc_transport.dma_boundary = vha->host->dma_boundary; - - ret = nvme_fc_register_localport(&pinfo, tmpl, - get_device(&ha->pdev->dev), &vha->nvme_local_port); + mutex_lock(&ha->vport_lock); + /* + * Check again for nvme_local_port to see if any other thread raced + * with this one and finished registration. + */ + if (!vha->nvme_local_port) { + ql_log(ql_log_info, vha, 0xffff, + "register_localport: host-traddr=nn-0x%llx:pn-0x%llx on portID:%x\n", + pinfo.node_name, pinfo.port_name, pinfo.port_id); + qla_nvme_fc_transport.dma_boundary = vha->host->dma_boundary; + + ret = nvme_fc_register_localport(&pinfo, tmpl, + get_device(&ha->pdev->dev), + &vha->nvme_local_port); + mutex_unlock(&ha->vport_lock); + } else { + mutex_unlock(&ha->vport_lock); + return 0; + } if (ret) { ql_log(ql_log_warn, vha, 0xffff, "register_localport failed: ret=%x\n", ret);