altos: reorder stm USB state stores to avoid races
authorKeith Packard <keithp@keithp.com>
Wed, 27 Jun 2012 21:35:56 +0000 (14:35 -0700)
committerKeith Packard <keithp@keithp.com>
Wed, 27 Jun 2012 21:35:56 +0000 (14:35 -0700)
Must set ao_usb_in_pending before telling USB about new data or an
interrupt could arrive at the wrong time to clear it.

Same for ao_usb_in_flushed.

Without these changes, I've seen the USB bus lock up on occasion,
waiting for an IN packet to consume data, but with no IN data pending
in the hardware.

Signed-off-by: Keith Packard <keithp@keithp.com>
src/stm/ao_usb_stm.c

index c093f526164452bf8355379d76854f26d7c6f098..4f37a7d9e7af5256a7ce4b89ecb8a2ec65ca7249 100644 (file)
@@ -792,10 +792,10 @@ static void
 ao_usb_in_send(void)
 {
        debug ("send %d\n", ao_usb_tx_count);
+       ao_usb_in_pending = 1;
        ao_usb_write(ao_usb_tx_buffer, ao_usb_in_tx_buffer, 0, ao_usb_tx_count);
        ao_usb_bdt[AO_USB_IN_EPR].single.count_tx = ao_usb_tx_count;
        ao_usb_set_stat_tx(AO_USB_IN_EPR, STM_USB_EPR_STAT_TX_VALID);
-       ao_usb_in_pending = 1;
        ao_usb_tx_count = 0;
 }
 
@@ -848,12 +848,12 @@ ao_usb_putchar(char c) __critical __reentrant
 
        ao_usb_in_wait();
 
+       ao_usb_in_flushed = 0;
        ao_usb_tx_buffer[ao_usb_tx_count++] = (uint8_t) c;
 
        /* Send the packet when full */
        if (ao_usb_tx_count == AO_USB_IN_SIZE)
                ao_usb_in_send();
-       ao_usb_in_flushed = 0;
 }
 
 static void