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