diff mbox series

[03/13] qla2xxx: Fix loss of NVME namespaces after driver reload test

Message ID 20220308082048.9774-4-njavali@marvell.com (mailing list archive)
State Superseded
Headers show
Series qla2xxx driver fixes | expand

Commit Message

Nilesh Javali March 8, 2022, 8:20 a.m. UTC
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(-)

Comments

Himanshu Madhani March 9, 2022, 6:39 p.m. UTC | #1
> 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 mbox series

Patch

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);