Driver unload isn't waiting for all outstanding nvme associations
to terminate before clearing structures. In particular, it did not
set dev_loss_tmo to 0 such that all associations are immediately
terminated. Thus the transport would enter reconnect timeouts and
reattempt reconnect to an nvme controller. The call makes a call
into the driver to create hw queues for the controller which causes
a NULL pointer reference.

Correct by changing the teardown process to change all dev_loss_tmo
timeouts to 0 so that they are immediate. Now the teardown process
initiates, the remote ports unregistered and delete callback made,
and as the assocations are immediate upon remoteport unregister, the
transport will not longer invoke the callbacks for a new controller.

Signed-off-by: Dick Kennedy <dick.kenn...@broadcom.com>
Signed-off-by: James Smart <james.sm...@broadcom.com>
---
 drivers/scsi/lpfc/lpfc_hbadisc.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 3e7712cd6c9a..2c103a12a1d2 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -840,8 +840,28 @@ lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove)
 void
 lpfc_port_link_failure(struct lpfc_vport *vport)
 {
+       struct lpfc_nodelist *ndlp, *next_ndlp;
+       struct lpfc_nvme_rport *rport;
+
        lpfc_vport_set_state(vport, FC_VPORT_LINKDOWN);
 
+       list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
+               if (ndlp->nlp_type & NLP_NVME_TARGET) {
+                       rport = lpfc_ndlp_get_nrport(ndlp);
+                       if (!rport)
+                               continue;
+
+                       /*
+                        * Update dev_loss_tmo when driver is being unloaded.
+                        * Setting dev_loss_tmo = 0 there won't be any reconnect
+                        * tries and controller would be deleted in nvme-layer
+                        **/
+                       nvme_fc_set_remoteport_devloss(ndlp->nrport->remoteport,
+                                                      0);
+                       lpfc_nvme_unregister_port(vport, ndlp);
+               }
+       }
+
        /* Cleanup any outstanding received buffers */
        lpfc_cleanup_rcv_buffers(vport);
 
-- 
2.13.1

Reply via email to