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

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.comCo-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
...@@ -1601,7 +1601,6 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, ...@@ -1601,7 +1601,6 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
u32 keep_nlp_fc4_type = 0; u32 keep_nlp_fc4_type = 0;
struct lpfc_nvme_rport *keep_nrport = NULL; struct lpfc_nvme_rport *keep_nrport = NULL;
int put_node; int put_node;
int put_rport;
unsigned long *active_rrqs_xri_bitmap = NULL; unsigned long *active_rrqs_xri_bitmap = NULL;
/* Fabric nodes can have the same WWPN so we don't bother searching /* 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, ...@@ -1804,13 +1803,10 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
if (rport) { if (rport) {
rdata = rport->dd_data; rdata = rport->dd_data;
put_node = rdata->pnode != NULL; put_node = rdata->pnode != NULL;
put_rport = ndlp->rport != NULL;
rdata->pnode = NULL; rdata->pnode = NULL;
ndlp->rport = NULL; ndlp->rport = NULL;
if (put_node) if (put_node)
lpfc_nlp_put(ndlp); lpfc_nlp_put(ndlp);
if (put_rport)
put_device(&rport->dev);
} }
} }
......
...@@ -117,7 +117,6 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) ...@@ -117,7 +117,6 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
struct lpfc_hba *phba; struct lpfc_hba *phba;
struct lpfc_work_evt *evtp; struct lpfc_work_evt *evtp;
int put_node; int put_node;
int put_rport;
unsigned long iflags; unsigned long iflags;
rdata = rport->dd_data; rdata = rport->dd_data;
...@@ -142,13 +141,10 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) ...@@ -142,13 +141,10 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
*/ */
if (vport->load_flag & FC_UNLOADING) { if (vport->load_flag & FC_UNLOADING) {
put_node = rdata->pnode != NULL; put_node = rdata->pnode != NULL;
put_rport = ndlp->rport != NULL;
rdata->pnode = NULL; rdata->pnode = NULL;
ndlp->rport = NULL; ndlp->rport = NULL;
if (put_node) if (put_node)
lpfc_nlp_put(ndlp); lpfc_nlp_put(ndlp);
if (put_rport)
put_device(&rport->dev);
return; return;
} }
...@@ -263,7 +259,6 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) ...@@ -263,7 +259,6 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
ndlp->rport = NULL; ndlp->rport = NULL;
if (put_node) if (put_node)
lpfc_nlp_put(ndlp); lpfc_nlp_put(ndlp);
put_device(&rport->dev);
return fcf_inuse; return fcf_inuse;
} }
...@@ -284,7 +279,6 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) ...@@ -284,7 +279,6 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
ndlp->rport = NULL; ndlp->rport = NULL;
if (put_node) if (put_node)
lpfc_nlp_put(ndlp); lpfc_nlp_put(ndlp);
put_device(&rport->dev);
if (ndlp->nlp_type & NLP_FABRIC) if (ndlp->nlp_type & NLP_FABRIC)
return fcf_inuse; return fcf_inuse;
...@@ -4190,8 +4184,6 @@ lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) ...@@ -4190,8 +4184,6 @@ lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
lpfc_nlp_put(ndlp); lpfc_nlp_put(ndlp);
rdata->pnode = NULL; rdata->pnode = NULL;
} }
/* drop reference for earlier registeration */
put_device(&rport->dev);
} }
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT, 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) ...@@ -4203,7 +4195,7 @@ lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
return; return;
ndlp->rport = rport = fc_remote_port_add(shost, 0, &rport_ids); 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, dev_printk(KERN_WARNING, &phba->pcidev->dev,
"Warning: fc_remote_port_add failed\n"); "Warning: fc_remote_port_add failed\n");
return; return;
...@@ -4244,6 +4236,7 @@ lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) ...@@ -4244,6 +4236,7 @@ lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
(rport->scsi_target_id < LPFC_MAX_TARGET)) { (rport->scsi_target_id < LPFC_MAX_TARGET)) {
ndlp->nlp_sid = rport->scsi_target_id; ndlp->nlp_sid = rport->scsi_target_id;
} }
return; return;
} }
...@@ -5217,7 +5210,6 @@ lpfc_nlp_remove(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) ...@@ -5217,7 +5210,6 @@ lpfc_nlp_remove(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
rdata = rport->dd_data; rdata = rport->dd_data;
rdata->pnode = NULL; rdata->pnode = NULL;
ndlp->rport = NULL; ndlp->rport = NULL;
put_device(&rport->dev);
} }
} }
......
...@@ -12499,12 +12499,15 @@ lpfc_pci_remove_one_s3(struct pci_dev *pdev) ...@@ -12499,12 +12499,15 @@ lpfc_pci_remove_one_s3(struct pci_dev *pdev)
} }
lpfc_destroy_vport_work_array(phba, vports); 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); fc_remove_host(shost);
scsi_remove_host(shost);
/* Clean up all nodes, mailboxes and IOs. */
lpfc_cleanup(vport); 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, * Bring down the SLI Layer. This step disable all interrupts,
* clears the rings, discards all mailbox commands, and resets * clears the rings, discards all mailbox commands, and resets
...@@ -13342,7 +13345,6 @@ lpfc_pci_remove_one_s4(struct pci_dev *pdev) ...@@ -13342,7 +13345,6 @@ lpfc_pci_remove_one_s4(struct pci_dev *pdev)
vport->load_flag |= FC_UNLOADING; vport->load_flag |= FC_UNLOADING;
spin_unlock_irq(&phba->hbalock); spin_unlock_irq(&phba->hbalock);
/* Free the HBA sysfs attributes */
lpfc_free_sysfs_attr(vport); lpfc_free_sysfs_attr(vport);
/* Release all the vports against this physical port */ /* Release all the vports against this physical port */
...@@ -13355,9 +13357,8 @@ lpfc_pci_remove_one_s4(struct pci_dev *pdev) ...@@ -13355,9 +13357,8 @@ lpfc_pci_remove_one_s4(struct pci_dev *pdev)
} }
lpfc_destroy_vport_work_array(phba, vports); 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); fc_remove_host(shost);
scsi_remove_host(shost);
/* Perform ndlp cleanup on the physical port. The nvme and nvmet /* Perform ndlp cleanup on the physical port. The nvme and nvmet
* localports are destroyed after to cleanup all transport memory. * localports are destroyed after to cleanup all transport memory.
...@@ -13370,6 +13371,9 @@ lpfc_pci_remove_one_s4(struct pci_dev *pdev) ...@@ -13370,6 +13371,9 @@ lpfc_pci_remove_one_s4(struct pci_dev *pdev)
if (phba->cfg_xri_rebalancing) if (phba->cfg_xri_rebalancing)
lpfc_destroy_multixri_pools(phba); 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, * Bring down the SLI Layer. This step disables all interrupts,
* clears the rings, discards all mailbox commands, and resets * clears the rings, discards all mailbox commands, and resets
......
...@@ -664,9 +664,8 @@ lpfc_vport_delete(struct fc_vport *fc_vport) ...@@ -664,9 +664,8 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
ns_ndlp_referenced = true; 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); fc_remove_host(shost);
scsi_remove_host(shost);
ndlp = lpfc_findnode_did(phba->pport, Fabric_DID); ndlp = lpfc_findnode_did(phba->pport, Fabric_DID);
...@@ -747,6 +746,9 @@ lpfc_vport_delete(struct fc_vport *fc_vport) ...@@ -747,6 +746,9 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
} }
lpfc_cleanup(vport); lpfc_cleanup(vport);
/* Remove scsi host now. The nodes are cleaned up. */
scsi_remove_host(shost);
lpfc_sli_host_down(vport); lpfc_sli_host_down(vport);
lpfc_stop_vport_timers(vport); lpfc_stop_vport_timers(vport);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment