From: Sylvain Munaut Date: Sat, 25 Jun 2011 20:42:38 +0000 (+0200) Subject: fw/sercomm: Additional locking needed in drv_pull X-Git-Url: http://git.rot13.org/?p=osmocom-bb.git;a=commitdiff_plain;h=402634a0cf58e8273185b008f9775e8353f3d7d2 fw/sercomm: Additional locking needed in drv_pull Credits to Andreas Eversberg for finding this bug after countless hours of debug and providing initial patch :) Signed-off-by: Sylvain Munaut --- diff --git a/src/target/firmware/comm/sercomm.c b/src/target/firmware/comm/sercomm.c index 8fa0347..ddc852c 100644 --- a/src/target/firmware/comm/sercomm.c +++ b/src/target/firmware/comm/sercomm.c @@ -147,9 +147,13 @@ unsigned int sercomm_tx_queue_depth(uint8_t dlci) /* fetch one octet of to-be-transmitted serial data */ int sercomm_drv_pull(uint8_t *ch) { - /* we are always called from interrupt context in this function, - * which means that any data structures we use need to be for - * our exclusive access */ + unsigned long flags; + + /* we may be called from interrupt context, but we stiff need to lock + * because sercomm could be accessed from a FIQ context ... */ + + sercomm_lock(&flags); + if (!sercomm.tx.msg) { unsigned int i; /* dequeue a new message from the queues */ @@ -162,9 +166,11 @@ int sercomm_drv_pull(uint8_t *ch) /* start of a new message, send start flag octet */ *ch = HDLC_FLAG; sercomm.tx.next_char = sercomm.tx.msg->data; + sercomm_unlock(&flags); return 1; } else { /* no more data avilable */ + sercomm_unlock(&flags); return 0; } } @@ -195,6 +201,8 @@ int sercomm_drv_pull(uint8_t *ch) /* standard case, simply send next octet */ *ch = *sercomm.tx.next_char++; } + + sercomm_unlock(&flags); return 1; }