diff options
author | Daniel Hellstrom <daniel@gaisler.com> | 2017-04-11 10:47:39 +0200 |
---|---|---|
committer | Daniel Hellstrom <daniel@gaisler.com> | 2017-05-14 12:31:58 +0200 |
commit | 9855690300d8aa5c8f025811e3cc0bbb2c2d91e9 (patch) | |
tree | 8fb42477313fcc9ebe940eb3f14749ce5aac433c /c/src/lib/libbsp/sparc/shared/can/grcan.c | |
parent | leon, grcan: RTEMS_NO_TIMEOUT on tx_sem (diff) | |
download | rtems-9855690300d8aa5c8f025811e3cc0bbb2c2d91e9.tar.bz2 |
leon, grcan: split hw_stop() into hw and sw stop
this is to avoid owning the spin-lock during semaphore operations.
Diffstat (limited to '')
-rw-r--r-- | c/src/lib/libbsp/sparc/shared/can/grcan.c | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/sparc/shared/can/grcan.c b/c/src/lib/libbsp/sparc/shared/can/grcan.c index 1348d7ab41..10509342ee 100644 --- a/c/src/lib/libbsp/sparc/shared/can/grcan.c +++ b/c/src/lib/libbsp/sparc/shared/can/grcan.c @@ -488,7 +488,10 @@ static void grcan_hw_stop(struct grcan_priv *pDev) /* Disable receiver & transmitter */ pDev->regs->rx0ctrl = 0; pDev->regs->tx0ctrl = 0; +} +static void grcan_sw_stop(struct grcan_priv *pDev) +{ /* Reset semaphores to the initial state and wakeing * all threads waiting for an IRQ. The threads that * get woken up must check for RTEMS_UNSATISFIED in @@ -1577,6 +1580,7 @@ int grcan_stop(void *d) { struct grcan_priv *pDev = d; SPIN_IRQFLAGS(oldLevel); + int do_sw_stop; FUNCDBG(); @@ -1586,6 +1590,7 @@ int grcan_stop(void *d) SPIN_LOCK_IRQ(&pDev->devlock, oldLevel); if (pDev->started == STATE_STARTED) { grcan_hw_stop(pDev); + do_sw_stop = 1; DBGC(DBG_STATE, "STARTED->STOPPED\n"); } else { /* @@ -1593,10 +1598,14 @@ int grcan_stop(void *d) * might already been called from ISR. */ DBGC(DBG_STATE, "[STOPPED|BUSOFF|AHBERR]->STOPPED\n"); + do_sw_stop = 0; } pDev->started = STATE_STOPPED; SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel); + if (do_sw_stop) + grcan_sw_stop(pDev); + /* Disable interrupts */ drvmgr_interrupt_unregister(pDev->dev, 0, grcan_interrupt, pDev); @@ -1932,6 +1941,10 @@ static void grcan_interrupt(void *arg) * again with grcan_start(). */ SPIN_UNLOCK(&pDev->devlock, irqflags); + + /* flush semaphores to wake blocked threads */ + grcan_sw_stop(pDev); + /* * NOTE: Another interrupt may be pending now so ISR could be * executed one more time aftert this (first) return. |