Commit 95f0ef8a authored by James Smart's avatar James Smart Committed by Martin K. Petersen
Browse files

scsi: lpfc: Fix removal of SCSI transport device get and put on dev structure

The lpfc driver is calling get_device and put_device on scsi_fc_transport
device structure. When this code was removed, the driver triggered an oops
in "scsi_is_host_dev" when the first SCSI target was unregistered from the
transport.

The reason the calls were necessary is that the driver is calling
scsi_remove_host too early, before the target rports are unregistered and
the scsi devices disconnected from the scsi_host.  The fc_host was torn
down during fc_remove_host.

Fix by moving the lpfc_pci_remove_one_s3/s4 calls to scsi_remove_host to
after the nodes are cleaned up.  Remove the get_device and put_device calls
and the supporting code.

Link: https://lore.kernel.org/r/20201115192646.12977-4-james.smart@broadcom.com


Co-developed-by: default avatarDick Kennedy <dick.kennedy@broadcom.com>
Signed-off-by: default avatarDick Kennedy <dick.kennedy@broadcom.com>
Signed-off-by: default avatarJames Smart <james.smart@broadcom.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 4430f7fd
Loading
Loading
Loading
Loading
+0 −4
Original line number Diff line number Diff line
@@ -1601,7 +1601,6 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
	u32 keep_nlp_fc4_type = 0;
	struct lpfc_nvme_rport *keep_nrport = NULL;
	int  put_node;
	int  put_rport;
	unsigned long *active_rrqs_xri_bitmap = NULL;

	/* Fabric nodes can have the same WWPN so we don't bother searching
@@ -1804,13 +1803,10 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
		if (rport) {
			rdata = rport->dd_data;
			put_node = rdata->pnode != NULL;
			put_rport = ndlp->rport != NULL;
			rdata->pnode = NULL;
			ndlp->rport = NULL;
			if (put_node)
				lpfc_nlp_put(ndlp);
			if (put_rport)
				put_device(&rport->dev);
		}
	}

+2 −10
Original line number Diff line number Diff line
@@ -117,7 +117,6 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
	struct lpfc_hba   *phba;
	struct lpfc_work_evt *evtp;
	int  put_node;
	int  put_rport;
	unsigned long iflags;

	rdata = rport->dd_data;
@@ -142,13 +141,10 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
	 */
	if (vport->load_flag & FC_UNLOADING) {
		put_node = rdata->pnode != NULL;
		put_rport = ndlp->rport != NULL;
		rdata->pnode = NULL;
		ndlp->rport = NULL;
		if (put_node)
			lpfc_nlp_put(ndlp);
		if (put_rport)
			put_device(&rport->dev);
		return;
	}

@@ -263,7 +259,6 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
		ndlp->rport = NULL;
		if (put_node)
			lpfc_nlp_put(ndlp);
		put_device(&rport->dev);

		return fcf_inuse;
	}
@@ -284,7 +279,6 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
	ndlp->rport = NULL;
	if (put_node)
		lpfc_nlp_put(ndlp);
	put_device(&rport->dev);

	if (ndlp->nlp_type & NLP_FABRIC)
		return fcf_inuse;
@@ -4190,8 +4184,6 @@ lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
				lpfc_nlp_put(ndlp);
			rdata->pnode = NULL;
		}
		/* drop reference for earlier registeration */
		put_device(&rport->dev);
	}

	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT,
@@ -4203,7 +4195,7 @@ lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
		return;

	ndlp->rport = rport = fc_remote_port_add(shost, 0, &rport_ids);
	if (!rport || !get_device(&rport->dev)) {
	if (!rport) {
		dev_printk(KERN_WARNING, &phba->pcidev->dev,
			   "Warning: fc_remote_port_add failed\n");
		return;
@@ -4244,6 +4236,7 @@ lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
	    (rport->scsi_target_id < LPFC_MAX_TARGET)) {
		ndlp->nlp_sid = rport->scsi_target_id;
	}

	return;
}

@@ -5217,7 +5210,6 @@ lpfc_nlp_remove(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
		rdata = rport->dd_data;
		rdata->pnode = NULL;
		ndlp->rport = NULL;
		put_device(&rport->dev);
	}
}

+9 −5
Original line number Diff line number Diff line
@@ -12499,12 +12499,15 @@ lpfc_pci_remove_one_s3(struct pci_dev *pdev)
		}
	lpfc_destroy_vport_work_array(phba, vports);

	/* Remove FC host and then SCSI host with the physical port */
	/* Remove FC host with the physical port */
	fc_remove_host(shost);
	scsi_remove_host(shost);

	/* Clean up all nodes, mailboxes and IOs. */
	lpfc_cleanup(vport);

	/* Remove the shost now that the devices connections are lost. */
	scsi_remove_host(shost);

	/*
	 * Bring down the SLI Layer. This step disable all interrupts,
	 * clears the rings, discards all mailbox commands, and resets
@@ -13342,7 +13345,6 @@ lpfc_pci_remove_one_s4(struct pci_dev *pdev)
	vport->load_flag |= FC_UNLOADING;
	spin_unlock_irq(&phba->hbalock);

	/* Free the HBA sysfs attributes */
	lpfc_free_sysfs_attr(vport);

	/* Release all the vports against this physical port */
@@ -13355,9 +13357,8 @@ lpfc_pci_remove_one_s4(struct pci_dev *pdev)
		}
	lpfc_destroy_vport_work_array(phba, vports);

	/* Remove FC host and then SCSI host with the physical port */
	/* Remove FC host with the physical port */
	fc_remove_host(shost);
	scsi_remove_host(shost);

	/* Perform ndlp cleanup on the physical port.  The nvme and nvmet
	 * localports are destroyed after to cleanup all transport memory.
@@ -13370,6 +13371,9 @@ lpfc_pci_remove_one_s4(struct pci_dev *pdev)
	if (phba->cfg_xri_rebalancing)
		lpfc_destroy_multixri_pools(phba);

	/* Remove the shost now that the devices connections are lost. */
	scsi_remove_host(shost);

	/*
	 * Bring down the SLI Layer. This step disables all interrupts,
	 * clears the rings, discards all mailbox commands, and resets
+4 −2
Original line number Diff line number Diff line
@@ -664,9 +664,8 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
		ns_ndlp_referenced = true;
	}

	/* Remove FC host and then SCSI host with the vport */
	/* Remove FC host to break driver binding. */
	fc_remove_host(shost);
	scsi_remove_host(shost);

	ndlp = lpfc_findnode_did(phba->pport, Fabric_DID);

@@ -747,6 +746,9 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
	}

	lpfc_cleanup(vport);

	/* Remove scsi host now.  The nodes are cleaned up. */
	scsi_remove_host(shost);
	lpfc_sli_host_down(vport);

	lpfc_stop_vport_timers(vport);