use irq-safe version of llist operations between USB callback and main
diff --git a/firmware/src_simtrace/host_communication.c b/firmware/src_simtrace/host_communication.c
index c06c140..dde5403 100644
--- a/firmware/src_simtrace/host_communication.c
+++ b/firmware/src_simtrace/host_communication.c
@@ -5,6 +5,7 @@
 #include "board.h"
 #include "req_ctx.h"
 #include "linuxlist.h"
+#include "llist_irqsafe.h"
 
 static volatile uint32_t usbep_in_progress[BOARD_USB_NUMENDPOINTS];
 
@@ -90,7 +91,7 @@
 	}
 	rctx->tot_len = transferred;
 	req_ctx_set_state(rctx, RCTX_S_MAIN_PROCESSING);
-	llist_add_tail(&rctx->list, queue);
+	llist_add_tail_irqsafe(&rctx->list, queue);
 }
 
 int usb_refill_from_host(struct llist_head *queue, int ep)
diff --git a/firmware/src_simtrace/llist_irqsafe.h b/firmware/src_simtrace/llist_irqsafe.h
new file mode 100644
index 0000000..b466939
--- /dev/null
+++ b/firmware/src_simtrace/llist_irqsafe.h
@@ -0,0 +1,27 @@
+#pragma once
+
+#include "linuxlist.h"
+
+static inline void llist_add_tail_irqsafe(struct llist_head *_new,
+					  struct llist_head *head)
+{
+	__disable_irq();
+	llist_add_tail(_new, head);
+	__enable_irq();
+}
+
+static inline struct llist_head *llist_head_dequeue_irqsafe(struct llist_head *head)
+{
+	struct llist_head *lh;
+
+	__disable_irq();
+	if (llist_empty(head)) {
+		lh = NULL;
+	} else {
+		lh = head->next;
+		llist_del(lh);
+	}
+	__enable_irq();
+
+	return lh;
+}
diff --git a/firmware/src_simtrace/mode_cardemu.c b/firmware/src_simtrace/mode_cardemu.c
index e51e990..a26abe7 100644
--- a/firmware/src_simtrace/mode_cardemu.c
+++ b/firmware/src_simtrace/mode_cardemu.c
@@ -7,6 +7,7 @@
 #include "iso7816_fidi.h"
 #include "utils.h"
 #include "linuxlist.h"
+#include "llist_irqsafe.h"
 #include "req_ctx.h"
 #include "cardemu_prot.h"
 
@@ -326,12 +327,22 @@
 
 /* iterate over the queue of incoming USB commands and dispatch/execute
  * them */
-static void process_any_usb_commands(struct llist_head *main_q, struct cardem_inst *ci)
+static void process_any_usb_commands(struct llist_head *main_q,
+				     struct cardem_inst *ci)
 {
-	struct req_ctx *rctx, *tmp;
+	struct llist_head *lh;
+	struct req_ctx *rctx;
+	int i;
 
-	llist_for_each_entry_safe(rctx, tmp, main_q, list) {
-		llist_del(&rctx->list);
+	/* limit the number of iterations to 10, to ensure we don't get
+	 * stuck here without returning to main loop processing */
+	for (i = 0; i < 10; i++) {
+		/* de-queue the list head in an irq-safe way */
+		lh = llist_head_dequeue_irqsafe(main_q);
+		if (!lh)
+			break;
+		rctx = llist_entry(lh, struct req_ctx, list);
+		/* dispatch the command with interrupts enabled */
 		dispatch_usb_command(rctx, ci);
 	}
 }