summaryrefslogtreecommitdiffstats
path: root/src/target
diff options
context:
space:
mode:
authorSylvain Munaut2011-06-25 22:42:38 +0200
committerSylvain Munaut2011-06-25 22:42:38 +0200
commit402634a0cf58e8273185b008f9775e8353f3d7d2 (patch)
tree7d2f5df2af7cac46fffb782b77857da746d49f0a /src/target
parentfw/sercomm: Fix up the locking using an 'abstraction' layer (diff)
downloadosmocom-402634a0cf58e8273185b008f9775e8353f3d7d2.tar.gz
osmocom-402634a0cf58e8273185b008f9775e8353f3d7d2.tar.xz
osmocom-402634a0cf58e8273185b008f9775e8353f3d7d2.zip
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 <tnt@246tNt.com>
Diffstat (limited to 'src/target')
-rw-r--r--src/target/firmware/comm/sercomm.c14
1 files changed, 11 insertions, 3 deletions
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;
}