This patch adds some local_irq_{save,restore}() code to usbtty to cope with the lack of lacking in the case of irq-accelerated usb device drivers (such as our s3c24xx udc driver). Index: u-boot/drivers/serial/usbtty.c =================================================================== --- u-boot.orig/drivers/serial/usbtty.c +++ u-boot/drivers/serial/usbtty.c @@ -26,6 +26,7 @@ #ifdef CONFIG_USB_TTY #include +#include #include #include #include "usbtty.h" @@ -1039,16 +1040,26 @@ struct usb_endpoint_instance *endpoint = &endpoint_instance[tx_endpoint]; struct urb *current_urb = NULL; + unsigned long flags; + local_irq_save(flags); current_urb = next_urb (device_instance, endpoint); /* TX data still exists - send it now */ + + /* I don't really understand what this logic is supposed to do, + * at least on the s3c24xx usb driver it causes all data to be + * transmitted twice !?! - Harald Welte */ +#if !(defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440) || \ + defined(CONFIG_S3C2442) || defined(CONFIG_S3C2443)) if(endpoint->sent < current_urb->actual_length){ if(udc_endpoint_write (endpoint)){ /* Write pre-empted by RX */ + local_irq_restore(flags); return -1; } } +#endif if (buf->size) { char *dest; @@ -1065,6 +1076,7 @@ if (!current_urb) { TTYERR ("current_urb is NULL, buf->size %d\n", buf->size); + local_irq_restore(flags); return total; } @@ -1090,14 +1102,17 @@ if (endpoint->last == 0) { if(udc_endpoint_write (endpoint)){ /* Write pre-empted by RX */ + local_irq_restore(flags); return -1; } } }/* end while */ + local_irq_restore(flags); return total; } + local_irq_restore(flags); return 0; } @@ -1105,9 +1120,11 @@ { struct usb_endpoint_instance *endpoint = &endpoint_instance[rx_endpoint]; + unsigned int nb = 0; + unsigned long flags; + local_irq_save(flags); if (endpoint->rcv_urb && endpoint->rcv_urb->actual_length) { - unsigned int nb = 0; char *src = (char *) endpoint->rcv_urb->buffer; unsigned int rx_avail = buf->totalsize - buf->size; @@ -1118,9 +1135,9 @@ endpoint->rcv_urb->actual_length = 0; } - return nb; } - return 0; + local_irq_restore(flags); + return nb; } static int usbtty_configured (void)