#include "lpfc_debugfs.h"
 
 
+/* Called to clear RSCN discovery flags when driver is unloading. */
+static bool
+lpfc_check_unload_and_clr_rscn(unsigned long *fc_flag)
+{
+       /* If unloading, then clear the FC_RSCN_DEFERRED flag */
+       if (test_bit(FC_UNLOADING, fc_flag)) {
+               clear_bit(FC_RSCN_DEFERRED, fc_flag);
+               return false;
+       }
+       return test_bit(FC_RSCN_DEFERRED, fc_flag);
+}
+
 /* Called to verify a rcv'ed ADISC was intended for us. */
 static int
 lpfc_check_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
 lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
 {
        LIST_HEAD(abort_list);
+       LIST_HEAD(drv_cmpl_list);
        struct lpfc_sli_ring *pring;
        struct lpfc_iocbq *iocb, *next_iocb;
+       int retval = 0;
 
        pring = lpfc_phba_elsring(phba);
 
 
        /* Abort the targeted IOs and remove them from the abort list. */
        list_for_each_entry_safe(iocb, next_iocb, &abort_list, dlist) {
-                       spin_lock_irq(&phba->hbalock);
-                       list_del_init(&iocb->dlist);
-                       lpfc_sli_issue_abort_iotag(phba, pring, iocb, NULL);
-                       spin_unlock_irq(&phba->hbalock);
+               spin_lock_irq(&phba->hbalock);
+               list_del_init(&iocb->dlist);
+               retval = lpfc_sli_issue_abort_iotag(phba, pring, iocb, NULL);
+               spin_unlock_irq(&phba->hbalock);
+
+               if (retval && test_bit(FC_UNLOADING, &phba->pport->load_flag)) {
+                       list_del_init(&iocb->list);
+                       list_add_tail(&iocb->list, &drv_cmpl_list);
+               }
        }
+
+       lpfc_sli_cancel_iocbs(phba, &drv_cmpl_list, IOSTAT_LOCAL_REJECT,
+                             IOERR_SLI_ABORTED);
+
        /* Make sure HBA is alive */
        lpfc_issue_hb_tmo(phba);
 
 {
        struct lpfc_hba  *phba = vport->phba;
 
-       /* Don't do anything that will mess up processing of the
-        * previous RSCN.
-        */
-       if (test_bit(FC_RSCN_DEFERRED, &vport->fc_flag))
+       /* Don't do anything that disrupts the RSCN unless lpfc is unloading. */
+       if (lpfc_check_unload_and_clr_rscn(&vport->fc_flag))
                return ndlp->nlp_state;
 
        /* software abort outstanding PLOGI */
 {
        struct lpfc_hba  *phba = vport->phba;
 
-       /* Don't do anything that will mess up processing of the
-        * previous RSCN.
-        */
-       if (test_bit(FC_RSCN_DEFERRED, &vport->fc_flag))
+       /* Don't do anything that disrupts the RSCN unless lpfc is unloading. */
+       if (lpfc_check_unload_and_clr_rscn(&vport->fc_flag))
                return ndlp->nlp_state;
 
        /* software abort outstanding ADISC */
                                 void *arg,
                                 uint32_t evt)
 {
-       /* Don't do anything that will mess up processing of the
-        * previous RSCN.
-        */
-       if (test_bit(FC_RSCN_DEFERRED, &vport->fc_flag))
+       /* Don't do anything that disrupts the RSCN unless lpfc is unloading. */
+       if (lpfc_check_unload_and_clr_rscn(&vport->fc_flag))
                return ndlp->nlp_state;
 
        ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
 {
        struct lpfc_hba  *phba = vport->phba;
 
-       /* Don't do anything that will mess up processing of the
-        * previous RSCN.
-        */
-       if (test_bit(FC_RSCN_DEFERRED, &vport->fc_flag))
+       /* Don't do anything that disrupts the RSCN unless lpfc is unloading. */
+       if (lpfc_check_unload_and_clr_rscn(&vport->fc_flag))
                return ndlp->nlp_state;
 
        /* software abort outstanding PRLI */
 lpfc_device_recov_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
                           void *arg, uint32_t evt)
 {
-       /* Don't do anything that will mess up processing of the
-        * previous RSCN.
-        */
-       if (test_bit(FC_RSCN_DEFERRED, &vport->fc_flag))
+       /* Don't do anything that disrupts the RSCN unless lpfc is unloading. */
+       if (lpfc_check_unload_and_clr_rscn(&vport->fc_flag))
                return ndlp->nlp_state;
 
        lpfc_cancel_retry_delay_tmo(vport, ndlp);
 
 
        /* ELS cmd tag <ulpIoTag> completes */
        lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-                       "0139 Ignoring ELS cmd code x%x completion Data: "
+                       "0139 Ignoring ELS cmd code x%x ref cnt x%x Data: "
                        "x%x x%x x%x x%px\n",
-                       ulp_command, ulp_status, ulp_word4, iotag,
-                       cmdiocb->ndlp);
+                       ulp_command, kref_read(&cmdiocb->ndlp->kref),
+                       ulp_status, ulp_word4, iotag, cmdiocb->ndlp);
        /*
         * Deref the ndlp after free_iocb. sli_release_iocb will access the ndlp
         * if exchange is busy.
                }
        }
 
-       if (phba->link_state < LPFC_LINK_UP ||
+       /* Just close the exchange under certain conditions. */
+       if (test_bit(FC_UNLOADING, &vport->load_flag) ||
+           phba->link_state < LPFC_LINK_UP ||
            (phba->sli_rev == LPFC_SLI_REV4 &&
             phba->sli4_hba.link_state.status == LPFC_FC_LA_TYPE_LINK_DOWN) ||
            (phba->link_flag & LS_EXTERNAL_LOOPBACK))
        lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI,
                         "0339 Abort IO XRI x%x, Original iotag x%x, "
                         "abort tag x%x Cmdjob : x%px Abortjob : x%px "
-                        "retval x%x\n",
+                        "retval x%x : IA %d\n",
                         ulp_context, (phba->sli_rev == LPFC_SLI_REV4) ?
                         cmdiocb->iotag : iotag, iotag, cmdiocb, abtsiocbp,
-                        retval);
+                        retval, ia);
        if (retval) {
                cmdiocb->cmd_flag &= ~LPFC_DRIVER_ABORTED;
                __lpfc_sli_release_iocbq(phba, abtsiocbp);