struct tty_port *tport = &port->state->port;
        struct stm32_port *stm32_port = to_stm32_port(port);
        const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
-       unsigned long c;
+       unsigned long c, flags;
        u32 sr;
        char flag;
 
        if (irqd_is_wakeup_set(irq_get_irq_data(port->irq)))
                pm_wakeup_event(tport->tty->dev, 0);
 
+       if (threaded)
+               spin_lock_irqsave(&port->lock, flags);
+       else
+               spin_lock(&port->lock);
+
        while (stm32_usart_pending_rx(port, &sr, &stm32_port->last_res,
                                      threaded)) {
                sr |= USART_SR_DUMMY_RX;
                uart_insert_char(port, sr, USART_SR_ORE, c, flag);
        }
 
-       spin_unlock(&port->lock);
+       if (threaded)
+               spin_unlock_irqrestore(&port->lock, flags);
+       else
+               spin_unlock(&port->lock);
+
        tty_flip_buffer_push(tport);
-       spin_lock(&port->lock);
 }
 
 static void stm32_usart_tx_dma_complete(void *arg)
        const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
        u32 sr;
 
-       spin_lock(&port->lock);
-
        sr = readl_relaxed(port->membase + ofs->isr);
 
        if ((sr & USART_SR_RTOF) && ofs->icr != UNDEF_REG)
        if ((sr & USART_SR_RXNE) && !(stm32_port->rx_ch))
                stm32_usart_receive_chars(port, false);
 
-       if ((sr & USART_SR_TXE) && !(stm32_port->tx_ch))
+       if ((sr & USART_SR_TXE) && !(stm32_port->tx_ch)) {
+               spin_lock(&port->lock);
                stm32_usart_transmit_chars(port);
-
-       spin_unlock(&port->lock);
+               spin_unlock(&port->lock);
+       }
 
        if (stm32_port->rx_ch)
                return IRQ_WAKE_THREAD;
        struct uart_port *port = ptr;
        struct stm32_port *stm32_port = to_stm32_port(port);
 
-       spin_lock(&port->lock);
-
        if (stm32_port->rx_ch)
                stm32_usart_receive_chars(port, true);
 
-       spin_unlock(&port->lock);
-
        return IRQ_HANDLED;
 }