struct artpec6_crypto_req_common {
        struct list_head list;
+       struct list_head complete_in_progress;
        struct artpec6_crypto_dma_descriptors *dma;
        struct crypto_async_request *req;
        void (*complete)(struct crypto_async_request *req);
        return artpec6_crypto_dma_map_descs(common);
 }
 
-static void artpec6_crypto_process_queue(struct artpec6_crypto *ac)
+static void artpec6_crypto_process_queue(struct artpec6_crypto *ac,
+           struct list_head *completions)
 {
        struct artpec6_crypto_req_common *req;
 
                list_move_tail(&req->list, &ac->pending);
                artpec6_crypto_start_dma(req);
 
-               req->req->complete(req->req, -EINPROGRESS);
+               list_add_tail(&req->complete_in_progress, completions);
        }
 
        /*
        struct artpec6_crypto *ac = (struct artpec6_crypto *)data;
        struct artpec6_crypto_req_common *req;
        struct artpec6_crypto_req_common *n;
+       struct list_head complete_done;
+       struct list_head complete_in_progress;
+
+       INIT_LIST_HEAD(&complete_done);
+       INIT_LIST_HEAD(&complete_in_progress);
 
        if (list_empty(&ac->pending)) {
                pr_debug("Spurious IRQ\n");
 
                pr_debug("Completing request %p\n", req);
 
-               list_del(&req->list);
+               list_move_tail(&req->list, &complete_done);
 
                artpec6_crypto_dma_unmap_all(req);
                artpec6_crypto_copy_bounce_buffers(req);
 
                ac->pending_count--;
                artpec6_crypto_common_destroy(req);
-               req->complete(req->req);
        }
 
-       artpec6_crypto_process_queue(ac);
+       artpec6_crypto_process_queue(ac, &complete_in_progress);
 
        spin_unlock_bh(&ac->queue_lock);
+
+       /* Perform the completion callbacks without holding the queue lock
+        * to allow new request submissions from the callbacks.
+        */
+       list_for_each_entry_safe(req, n, &complete_done, list) {
+               req->complete(req->req);
+       }
+
+       list_for_each_entry_safe(req, n, &complete_in_progress,
+                                complete_in_progress) {
+               req->req->complete(req->req, -EINPROGRESS);
+       }
 }
 
 static void artpec6_crypto_complete_crypto(struct crypto_async_request *req)