psli = &phba->sli;
 
+       /*
+        * If freeing the queues have already started, don't access them.
+        * Otherwise set FREE_WAIT to indicate that queues are being used
+        * to hold the freeing process until we finish.
+        */
+       spin_lock_irq(&phba->hbalock);
+       if (!(psli->sli_flag & LPFC_QUEUE_FREE_INIT)) {
+               psli->sli_flag |= LPFC_QUEUE_FREE_WAIT;
+       } else {
+               spin_unlock_irq(&phba->hbalock);
+               goto skip_wait;
+       }
+       spin_unlock_irq(&phba->hbalock);
+
        /* Wait a little for things to settle down, but not
         * long enough for dev loss timeout to expire.
         */
                }
        }
 out:
+       spin_lock_irq(&phba->hbalock);
+       psli->sli_flag &= ~LPFC_QUEUE_FREE_WAIT;
+       spin_unlock_irq(&phba->hbalock);
+
+skip_wait:
        init_completion(&online_compl);
        rc = lpfc_workq_post_event(phba, &status, &online_compl, type);
        if (rc == 0)
 
 void
 lpfc_sli4_queue_destroy(struct lpfc_hba *phba)
 {
+       /*
+        * Set FREE_INIT before beginning to free the queues.
+        * Wait until the users of queues to acknowledge to
+        * release queues by clearing FREE_WAIT.
+        */
+       spin_lock_irq(&phba->hbalock);
+       phba->sli.sli_flag |= LPFC_QUEUE_FREE_INIT;
+       while (phba->sli.sli_flag & LPFC_QUEUE_FREE_WAIT) {
+               spin_unlock_irq(&phba->hbalock);
+               msleep(20);
+               spin_lock_irq(&phba->hbalock);
+       }
+       spin_unlock_irq(&phba->hbalock);
+
        /* Release HBA eqs */
        if (phba->sli4_hba.hdwq)
                lpfc_sli4_release_hdwq(phba);
 
        /* Everything on this list has been freed */
        INIT_LIST_HEAD(&phba->sli4_hba.lpfc_wq_list);
+
+       /* Done with freeing the queues */
+       spin_lock_irq(&phba->hbalock);
+       phba->sli.sli_flag &= ~LPFC_QUEUE_FREE_INIT;
+       spin_unlock_irq(&phba->hbalock);
 }
 
 int
 
        if (!queue)
                return;
 
+       if (!list_empty(&queue->wq_list))
+               list_del(&queue->wq_list);
+
        while (!list_empty(&queue->page_list)) {
                list_remove_head(&queue->page_list, dmabuf, struct lpfc_dmabuf,
                                 list);
        if (!list_empty(&queue->cpu_list))
                list_del(&queue->cpu_list);
 
-       if (!list_empty(&queue->wq_list))
-               list_del(&queue->wq_list);
-
        kfree(queue);
        return;
 }
 
 #define LPFC_SLI_ASYNC_MBX_BLK    0x2000 /* Async mailbox is blocked */
 #define LPFC_SLI_SUPPRESS_RSP     0x4000 /* Suppress RSP feature is supported */
 #define LPFC_SLI_USE_EQDR         0x8000 /* EQ Delay Register is supported */
+#define LPFC_QUEUE_FREE_INIT     0x10000 /* Queue freeing is in progress */
+#define LPFC_QUEUE_FREE_WAIT     0x20000 /* Hold Queue free as it is being
+                                          * used outside worker thread
+                                          */
 
        struct lpfc_sli_ring *sli3_ring;