The disable_vport path calls the discovery state machine on all ndlps, puts them into NPR state, and then calls lpfc_cleanup_rpis with the remove flag set. This unintentionally decrements an ndlp's kref twice and can result in premature release of an ndlp because lpfc_dev_loss_tmo_handler triggers clean up of the ndlp again later. Remove redundant code in disable_vport that sets all the ndlps to NPR, and change the call to cleanup_rpis to not remove the ndlps. lpfc_dev_loss_tmo_handler will handle final removal of the ndlps. Signed-off-by: Justin Tee <justin.tee@xxxxxxxxxxxx> --- drivers/scsi/lpfc/lpfc_vport.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c index 4d171f5c213f..5aeda245369b 100644 --- a/drivers/scsi/lpfc/lpfc_vport.c +++ b/drivers/scsi/lpfc/lpfc_vport.c @@ -534,7 +534,7 @@ disable_vport(struct fc_vport *fc_vport) { struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data; struct lpfc_hba *phba = vport->phba; - struct lpfc_nodelist *ndlp = NULL, *next_ndlp = NULL; + struct lpfc_nodelist *ndlp = NULL; struct Scsi_Host *shost = lpfc_shost_from_vport(vport); /* Can't disable during an outstanding delete. */ @@ -546,17 +546,7 @@ disable_vport(struct fc_vport *fc_vport) (void)lpfc_send_npiv_logo(vport, ndlp); lpfc_sli_host_down(vport); - - /* Mark all nodes for discovery so we can remove them by - * calling lpfc_cleanup_rpis(vport, 1) - */ - list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) { - if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) - continue; - lpfc_disc_state_machine(vport, ndlp, NULL, - NLP_EVT_DEVICE_RECOVERY); - } - lpfc_cleanup_rpis(vport, 1); + lpfc_cleanup_rpis(vport, 0); lpfc_stop_vport_timers(vport); lpfc_unreg_all_rpis(vport); -- 2.38.0