[rtems commit] leon, grcan: split hw_stop() into hw and sw stop

Daniel Hellstrom danielh at rtems.org
Sun May 14 10:34:28 UTC 2017


Module:    rtems
Branch:    master
Commit:    9855690300d8aa5c8f025811e3cc0bbb2c2d91e9
Changeset: http://git.rtems.org/rtems/commit/?id=9855690300d8aa5c8f025811e3cc0bbb2c2d91e9

Author:    Daniel Hellstrom <daniel at gaisler.com>
Date:      Tue Apr 11 10:47:39 2017 +0200

leon, grcan: split hw_stop() into hw and sw stop

this is to avoid owning the spin-lock during semaphore operations.

---

 c/src/lib/libbsp/sparc/shared/can/grcan.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/c/src/lib/libbsp/sparc/shared/can/grcan.c b/c/src/lib/libbsp/sparc/shared/can/grcan.c
index 1348d7a..1050934 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.




More information about the vc mailing list