summaryrefslogtreecommitdiffstats
path: root/cf-code
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2018-06-12 11:38:05 +1000
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2018-06-12 11:38:05 +1000
commit1e0f2bb69f73b87e49aa15ba00d60a18736bc0b6 (patch)
treea434c5021a148fe5c7c38889f2c2cc904ffc2a32 /cf-code
parent8028b238dd950e62ddd4c2336c7aac1e1a01400e (diff)
downloadcf-fsi-1e0f2bb69f73b87e49aa15ba00d60a18736bc0b6.tar.gz
cf-fsi-1e0f2bb69f73b87e49aa15ba00d60a18736bc0b6.zip
Fix interrupt race
The current sequence is possible in the main command loop and in the arbitration sequence: - STOP enables interrupt and stops execution - Interrupt occurs (stale from previous command) - No command (or arbitration response) - Command is written - Interrupt occurs again, is taken, does nothing - STOP executes, doesn't wake up We need to ensure that we only take the interrupt on STOP, so we need to re-mask after every STOP. (We could alternatively modify the SR in the interrupt stack to return from the handler with IRQs disabled but this is easier). Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'cf-code')
-rw-r--r--cf-code/cf-fsi-fw.S23
1 files changed, 7 insertions, 16 deletions
diff --git a/cf-code/cf-fsi-fw.S b/cf-code/cf-fsi-fw.S
index 44a02d2..14b80d2 100644
--- a/cf-code/cf-fsi-fw.S
+++ b/cf-code/cf-fsi-fw.S
@@ -259,7 +259,7 @@ _start:
move.l %a0,(0x46*4)
/* Mask interrupts */
- move.w #0x2000,%sr
+ move.w #0x2007,%sr
/* Configure GPIOs to output */
bsr config_gpio_out
@@ -271,25 +271,21 @@ _start:
* Main command loop
*/
main_loop:
+ /* Reset trace pointer */
+#ifdef ENABLE_TRACE
lea %a1@(TRACEBUF),%a3
-
- /* Wait arbitration request or command
- *
- * Note: This can run with interrupts enabled as a result of
- * the stop op, so %d0 can be clobbered at any time.
- */
+#endif
+ /* Wait arbitration request or command */
1: move.b %a1@(ARB_REG),%d2
bne arbitration_request
move.l %a1@(CMD_STAT_REG),%d2
tst.b %d2
bne command_request
stop #0x2000
+ move.w #0x2007,%sr
bra 1b
arbitration_request:
- /* Mask interrupts */
- move.w #0x2007,%sr
-
/* Ack request */
move.b #ARB_ARM_ACK,%a1@(ARB_REG)
@@ -297,9 +293,6 @@ arbitration_request:
0: move.b %a1@(ARB_REG),%d1
bne 1f
- /* Mask interrupts */
- move.w #0x2007,%sr
-
/* Got it, re-load the GPIO caches */
move.l %a5@(0),%DCLK
move.l %a4@(0),%DDAT
@@ -314,12 +307,10 @@ arbitration_request:
/* Wait, we'll get an interrupt when the host clears it */
1: stop #0x2000
+ move.w #0x2007,%sr
bra 0b
command_request:
- /* Mask interrupts */
- move.w #0x2007,%sr
-
/* Clear the command/status register */
moveq.l #0,%d0
move.l %d0,%a1@(CMD_STAT_REG)
OpenPOWER on IntegriCloud