[layer1] Fixed double IRQ bug
[osmocom-bb.git] / src / target / firmware / layer1 / async.c
index 22a6f77..68fee03 100644 (file)
 
 #include <debug.h>
 #include <arm.h>
+#include <asm/system.h>
 
 #include <osmocore/msgb.h>
 
 #include <layer1/sync.h>
+#include <layer1/async.h>
 #include <layer1/mframe_sched.h>
 #include <layer1/sched_gsmtime.h>
 #include <layer1/l23_api.h>
 
 extern const struct tdma_sched_item rach_sched_set_ul[];
 
-/* When altering data structures used by L1 Sync part, we need to
- * make sure to temporarily disable IRQ/FIQ to keep data consistent */
-static inline void l1a_lock_sync(void)
-{
-       arm_disable_interrupts();
-}
-
-static inline void l1a_unlock_sync(void)
-{
-       arm_enable_interrupts();
-}
-
 /* safely enable a message into the L1S TX queue */
 void l1a_txq_msgb_enq(struct llist_head *queue, struct msgb *msg)
 {
-       l1a_lock_sync();
-       msgb_enqueue(queue, msg);
-       l1a_unlock_sync();
-}
-
-/* request a RACH request at the next multiframe T3 = fn51 */
-void l1a_rach_req(uint8_t fn51, uint8_t ra)
-{
-       uint32_t fn_sched;
+       unsigned long flags;
 
-       l1a_lock_sync();
-       l1s.rach.ra = ra;
-       /* TODO: can we wrap here? I don't think so */
-       fn_sched = l1s.current_time.fn - l1s.current_time.t3;
-       fn_sched += fn51;
-       sched_gsmtime(rach_sched_set_ul, fn_sched, 0);
-       l1a_unlock_sync();
+       local_firq_save(flags);
+       msgb_enqueue(queue, msg);
+       local_irq_restore(flags);
 }
 
 /* Enable a repeating multiframe task */
 void l1a_mftask_enable(enum mframe_task task)
 {
-       /* we don't need locking here as L1S only reads mf_tasks */
-       l1s.mf_tasks |= (1 << task);
+       /* we don't need locking here as L1S only reads mframe.tasks */
+       mframe_enable(task);
 }
 
 /* Disable a repeating multiframe task */
 void l1a_mftask_disable(enum mframe_task task)
 {
-       /* we don't need locking here as L1S only reads mf_tasks */
-       l1s.mf_tasks &= ~(1 << task);
+       /* we don't need locking here as L1S only reads mframe.tasks */
+       mframe_disable(task);
+}
+
+/* Set the mask for repeating multiframe tasks */
+void l1a_mftask_set(uint32_t tasks)
+{
+       /* we don't need locking here as L1S only reads mframe.tasks */
+       mframe_set(tasks);
 }
 
 /* Initialize asynchronous part of Layer1 */
@@ -87,3 +72,26 @@ void l1a_init(void)
 {
        l1a_l23api_init();
 }
+
+/* Execute pending L1A completions */
+void l1a_compl_execute(void)
+{
+       unsigned long flags;
+       unsigned int scheduled;
+       unsigned int i;
+
+       /* get and reset the currently scheduled tasks */
+       local_firq_save(flags);
+       scheduled = l1s.scheduled_compl;
+       l1s.scheduled_compl = 0;
+       local_irq_restore(flags);
+
+       /* Iterate over list of scheduled completions, call their
+        * respective completion handler */
+       for (i = 0; i < 32; i++) {
+               if (!(scheduled & (1 << i)))
+                       continue;
+               /* call completion function */
+               l1s.completion[i](i);
+       }
+}