Commit db212f2e authored by Arun Easi's avatar Arun Easi Committed by Martin K. Petersen
Browse files

scsi: qla2xxx: Fix loss of NVMe namespaces after driver reload test

Driver registration of localport can race when it happens at the remote
port discovery time. Fix this by calling the registration under a mutex.

Link: https://lore.kernel.org/r/20220310092604.22950-4-njavali@marvell.com


Fixes: e84067d7 ("scsi: qla2xxx: Add FC-NVMe F/W initialization and transport registration")
Cc: stable@vger.kernel.org
Reported-by: default avatarMarco Patalano <mpatalan@redhat.com>
Tested-by: default avatarMarco Patalano <mpatalan@redhat.com>
Reviewed-by: default avatarHimanshu Madhani <himanshu.madhani@oracle.com>
Signed-off-by: default avatarArun Easi <aeasi@marvell.com>
Signed-off-by: default avatarNilesh Javali <njavali@marvell.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 6a45c8e1
Loading
Loading
Loading
Loading
+20 −10
Original line number Diff line number Diff line
@@ -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",
@@ -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;

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