mirror of
https://gitea.osmocom.org/sim-card/simtrace2.git
synced 2026-08-15 16:55:16 +03:00
firmware: protect uart_tx_queue against ISR
cardem: - dispatch_usb_command_cardem() appends to uart_tx_queue from the main loop - tx_byte_tpdu() dequeues from the USART IRQ handler @ NVIC prio 0 card_handle_reset() has the same issue, drains queue and frees uart_tx_msg from main loop while the ISR may own them. All of this needs protection against the irq. Needs a fixed llist_add_tail_irqsafe(), which called __enable_irq() instead of restoring the saved PRIMASK for some unknown reason?!?!?!? Change-Id: I7d9cdcc56263b27dfd4649dfb1da1d67761ee923
This commit is contained in:
@@ -34,7 +34,7 @@ static inline void llist_add_tail_irqsafe(struct llist_head *_new,
|
|||||||
|
|
||||||
local_irq_save(x);
|
local_irq_save(x);
|
||||||
llist_add_tail(_new, head);
|
llist_add_tail(_new, head);
|
||||||
__enable_irq();
|
local_irq_restore(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct llist_head *llist_head_dequeue_irqsafe(struct llist_head *head)
|
static inline struct llist_head *llist_head_dequeue_irqsafe(struct llist_head *head)
|
||||||
|
|||||||
@@ -219,19 +219,31 @@ struct card_handle {
|
|||||||
static void card_handle_reset(struct card_handle *ch)
|
static void card_handle_reset(struct card_handle *ch)
|
||||||
{
|
{
|
||||||
struct msgb *msg;
|
struct msgb *msg;
|
||||||
|
unsigned long x;
|
||||||
|
|
||||||
card_emu_uart_update_wt(ch->uart_chan, 0);
|
card_emu_uart_update_wt(ch->uart_chan, 0);
|
||||||
|
|
||||||
/* release any buffers we may still own */
|
/* Release any buffers we may still own.
|
||||||
if (ch->uart_tx_msg) {
|
* uart_tx_msg + uart_tx_queue are shared with the UART IRQ handler,
|
||||||
usb_buf_free(ch->uart_tx_msg);
|
* that preempts us here -> needs atomic detach and free */
|
||||||
ch->uart_tx_msg = NULL;
|
local_irq_save(x);
|
||||||
}
|
msg = ch->uart_tx_msg;
|
||||||
|
ch->uart_tx_msg = NULL;
|
||||||
|
local_irq_restore(x);
|
||||||
|
if (msg)
|
||||||
|
usb_buf_free(msg);
|
||||||
|
|
||||||
if (ch->uart_rx_msg) {
|
if (ch->uart_rx_msg) {
|
||||||
usb_buf_free(ch->uart_rx_msg);
|
usb_buf_free(ch->uart_rx_msg);
|
||||||
ch->uart_rx_msg = NULL;
|
ch->uart_rx_msg = NULL;
|
||||||
}
|
}
|
||||||
while ((msg = msgb_dequeue(&ch->uart_tx_queue))) {
|
|
||||||
|
while (1) {
|
||||||
|
local_irq_save(x);
|
||||||
|
msg = msgb_dequeue(&ch->uart_tx_queue);
|
||||||
|
local_irq_restore(x);
|
||||||
|
if (!msg)
|
||||||
|
break;
|
||||||
usb_buf_free(msg);
|
usb_buf_free(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -737,7 +737,8 @@ static void dispatch_usb_command_cardem(struct msgb *msg, struct cardem_inst *ci
|
|||||||
switch (hdr->msg_type) {
|
switch (hdr->msg_type) {
|
||||||
case SIMTRACE_MSGT_DT_CEMU_TX_DATA:
|
case SIMTRACE_MSGT_DT_CEMU_TX_DATA:
|
||||||
queue = card_emu_get_uart_tx_queue(ci->ch);
|
queue = card_emu_get_uart_tx_queue(ci->ch);
|
||||||
llist_add_tail(&msg->list, queue);
|
/* drained from the USART IRQ handler at highest NVIC prio */
|
||||||
|
llist_add_tail_irqsafe(&msg->list, queue);
|
||||||
card_emu_have_new_uart_tx(ci->ch);
|
card_emu_have_new_uart_tx(ci->ch);
|
||||||
break;
|
break;
|
||||||
case SIMTRACE_MSGT_DT_CEMU_SET_ATR:
|
case SIMTRACE_MSGT_DT_CEMU_SET_ATR:
|
||||||
|
|||||||
Reference in New Issue
Block a user