---
 c/src/lib/libbsp/sparc/shared/tmtc/grtc.c | 91 ++++++++++++++++++-------------
 1 file changed, 54 insertions(+), 37 deletions(-)

diff --git a/c/src/lib/libbsp/sparc/shared/tmtc/grtc.c 
b/c/src/lib/libbsp/sparc/shared/tmtc/grtc.c
index 3cceb60..c01d7d8 100644
--- a/c/src/lib/libbsp/sparc/shared/tmtc/grtc.c
+++ b/c/src/lib/libbsp/sparc/shared/tmtc/grtc.c
@@ -23,17 +23,20 @@
 #include <ambapp.h>
 #include <bsp/grtc.h>
 
-#ifndef IRQ_GLOBAL_PREPARE
- #define IRQ_GLOBAL_PREPARE(level) rtems_interrupt_level level
-#endif
-
-#ifndef IRQ_GLOBAL_DISABLE
- #define IRQ_GLOBAL_DISABLE(level) rtems_interrupt_disable(level)
-#endif
-
-#ifndef IRQ_GLOBAL_ENABLE
- #define IRQ_GLOBAL_ENABLE(level) rtems_interrupt_enable(level)
-#endif
+/* map via rtems_interrupt_lock_* API: */
+#define SPIN_DECLARE(lock) RTEMS_INTERRUPT_LOCK_MEMBER(lock)
+#define SPIN_INIT(lock, name) rtems_interrupt_lock_initialize(lock, name)
+#define SPIN_LOCK(lock, level) rtems_interrupt_lock_acquire_isr(lock, &level)
+#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_lock_acquire(lock, &level)
+#define SPIN_UNLOCK(lock, level) rtems_interrupt_lock_release_isr(lock, &level)
+#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_lock_release(lock, &level)
+#define SPIN_IRQFLAGS(k) rtems_interrupt_lock_context k
+#define SPIN_ISR_IRQFLAGS(k) SPIN_IRQFLAGS(k)
+
+/* turn on/off local CPU's interrupt to ensure HW timing - not SMP safe. */
+#define IRQ_LOCAL_DECLARE(_level) rtems_interrupt_level _level
+#define IRQ_LOCAL_DISABLE(_level) rtems_interrupt_local_disable(_level)
+#define IRQ_LOCAL_ENABLE(_level) rtems_interrupt_local_enable(_level)
 
 /*
 #define DEBUG
@@ -236,6 +239,7 @@ struct grtc_priv {
        char                    devName[32];    /* Device Name */
        struct grtc_regs        *regs;          /* TC Hardware Register MAP */
        int                     irq;            /* IRQ number of TC core */
+       SPIN_DECLARE(devlock);                  /* spin-lock of registers */
 
        int                     major;          /* Driver major */
        int                     minor;          /* Device Minor */
@@ -398,6 +402,8 @@ static int grtc_init3(struct drvmgr_dev *dev)
                sprintf(priv->devName, "/dev/%sgrtc%d", prefix, dev->minor_bus);
        }
 
+       SPIN_INIT(&priv->devlock, priv->devName);
+
        /* Register Device */
        status = rtems_io_register_name(priv->devName, grtc_driver_io_major, 
dev->minor_drv);
        if (status != RTEMS_SUCCESSFUL) {
@@ -703,9 +709,12 @@ static int grtc_start(struct grtc_priv *pDev)
        return 0;
 }
 
-static void grtc_stop(struct grtc_priv *pDev)
+static void grtc_stop(struct grtc_priv *pDev, int overrun)
 {
        struct grtc_regs *regs = pDev->regs;
+       SPIN_IRQFLAGS(irqflags);
+
+       SPIN_LOCK_IRQ(&pDev->devlock, irqflags);
 
        /* Disable the receiver */
        regs->cor = GRTC_SEB;
@@ -717,6 +726,14 @@ static void grtc_stop(struct grtc_priv *pDev)
 
        DBG("GRTC: STOPPED\n");
 
+       if (overrun) {
+               pDev->overrun_condition = 1;
+       } else {
+               pDev->running = 0;
+       }
+
+       SPIN_UNLOCK_IRQ(&pDev->devlock, irqflags);
+
        /* Flush semaphores in case a thread is stuck waiting for CLTUs (RX 
data) */
        rtems_semaphore_flush(pDev->sem_rx);
 }
@@ -728,14 +745,14 @@ static int grtc_wait_data(struct grtc_priv *pDev, int 
count, rtems_interval time
 {
        int avail;
        int ret;
-       IRQ_GLOBAL_PREPARE(oldLevel);
+       SPIN_IRQFLAGS(irqflags);
 
        FUNCDBG();
 
        if ( count < 1 )
                return 0;
 
-       IRQ_GLOBAL_DISABLE(oldLevel);
+       SPIN_LOCK_IRQ(&pDev->devlock, irqflags);
 
        /* Enable interrupts when receiving CLTUs, Also clear old pending CLTUs 
store
         * interrupts.
@@ -747,7 +764,7 @@ static int grtc_wait_data(struct grtc_priv *pDev, int 
count, rtems_interval time
        if ( avail < count ) {
                /* Wait for interrupt. */
 
-               IRQ_GLOBAL_ENABLE(oldLevel);
+               SPIN_UNLOCK_IRQ(&pDev->devlock, irqflags);
 
                if ( timeout == 0 ){
                        timeout = RTEMS_NO_TIMEOUT;
@@ -759,7 +776,7 @@ static int grtc_wait_data(struct grtc_priv *pDev, int 
count, rtems_interval time
                 *                     which should cancel this operation.
                 * RTEMS_OBJECT_WAS_DELETED, RTEMS_INVALID_ID = driver error.
                 */
-               IRQ_GLOBAL_DISABLE(oldLevel);
+               SPIN_LOCK_IRQ(&pDev->devlock, irqflags);
        }else{
                ret = RTEMS_SUCCESSFUL; 
        }
@@ -767,7 +784,7 @@ static int grtc_wait_data(struct grtc_priv *pDev, int 
count, rtems_interval time
        /* Disable interrupts when receiving CLTUs */
        pDev->regs->imr = READ_REG(&pDev->regs->imr) & ~GRTC_INT_CS;
 
-       IRQ_GLOBAL_ENABLE(oldLevel);
+       SPIN_UNLOCK_IRQ(&pDev->devlock, irqflags);
 
        return ret;
 }
@@ -845,8 +862,7 @@ static rtems_device_driver 
grtc_close(rtems_device_major_number major, rtems_dev
        pDev = (struct grtc_priv *)dev->priv;
 
        if ( pDev->running ){
-               grtc_stop(pDev);
-               pDev->running = 0;
+               grtc_stop(pDev, 0);
        }
 
        /* Reset core */
@@ -1542,8 +1558,7 @@ static rtems_device_driver 
grtc_ioctl(rtems_device_major_number major, rtems_dev
        struct grtc_list *frmlist;
        struct grtc_ioc_stats *stats;
        unsigned int mem;
-       
-       IRQ_GLOBAL_PREPARE(oldLevel);
+       IRQ_LOCAL_DECLARE(oldLevel);
 
        FUNCDBG();
 
@@ -1575,8 +1590,7 @@ static rtems_device_driver 
grtc_ioctl(rtems_device_major_number major, rtems_dev
                        return RTEMS_RESOURCE_IN_USE;
                }
                drvmgr_interrupt_unregister(pDev->dev, 0, grtc_interrupt, pDev);
-               grtc_stop(pDev);
-               pDev->running = 0;
+               grtc_stop(pDev, 0);
                break;
 
                case GRTC_IOC_ISSTARTED:
@@ -1716,15 +1730,17 @@ static rtems_device_driver 
grtc_ioctl(rtems_device_major_number major, rtems_dev
                if ( !hwregs ) {
                        return RTEMS_INVALID_NAME;
                }
-               /* We disable interrupt in order to get a snapshot of the 
registers */
-               IRQ_GLOBAL_DISABLE(oldLevel);
+               /* We disable interrupt on the local CPU in order to get a
+                * snapshot of the registers.
+                */
+               IRQ_LOCAL_DISABLE(oldLevel);
                hwregs->sir     = READ_REG(&pDev->regs->sir);
                hwregs->far     = READ_REG(&pDev->regs->far);
                hwregs->clcw1   = READ_REG(&pDev->regs->clcw1);
                hwregs->clcw2   = READ_REG(&pDev->regs->clcw2);
                hwregs->phir    = READ_REG(&pDev->regs->phir);
                hwregs->str     = READ_REG(&pDev->regs->str);
-               IRQ_GLOBAL_ENABLE(oldLevel);
+               IRQ_LOCAL_ENABLE(oldLevel);
                break;
 
                case GRTC_IOC_GET_STATS:
@@ -1897,6 +1913,7 @@ static void grtc_interrupt(void *arg)
        struct grtc_priv *pDev = arg;
        struct grtc_regs *regs = pDev->regs;
        unsigned int status;
+       SPIN_ISR_IRQFLAGS(irqflags);
 
        /* Clear interrupt by reading it */
        status = READ_REG(&regs->pisr);
@@ -1906,36 +1923,36 @@ static void grtc_interrupt(void *arg)
                return;
 
        if ( status & GRTC_INT_OV ){
-               
                /* Stop core (Disable receiver, interrupts), set overrun 
condition, 
                 * Flush semaphore if thread waiting for data in 
grtc_wait_data(). 
                 */
-               pDev->overrun_condition = 1;
-
-               grtc_stop(pDev);
+               grtc_stop(pDev, 1);
 
                /* No need to handle the reset of interrupts, we are still */
                goto out;
        }
 
        if ( status & GRTC_INT_CS ){
+               SPIN_LOCK(&pDev->devlock, irqflags);
+
                if ( (pDev->blocking==GRTC_BLKMODE_COMPLETE) && pDev->timeout ){
                        /* Signal to thread only if enough data is available */
                        if ( pDev->wait_for_nbytes > grtc_data_avail(pDev) ){
                                /* Not enough data available */
                                goto procceed_processing_interrupts;
                        }
-                       
-                       /* Enough data is available which means that we should 
wake 
-                        * up thread sleeping.
+
+                       /* Enough data is available which means that we should
+                        * wake up the thread sleeping.
                         */
                }
-               
-               /* Disable further CLTUs Stored interrupts, no point until 
thread waiting for them
-                * say it want to wait for more.
+
+               /* Disable further CLTUs Stored interrupts, no point until
+                * thread waiting for them says it want to wait for more.
                 */
                regs->imr = READ_REG(&regs->imr) & ~GRTC_INT_CS;
-               
+               SPIN_UNLOCK(&pDev->devlock, irqflags);
+
                /* Signal Semaphore to wake waiting thread in read() */
                rtems_semaphore_release(pDev->sem_rx);
        }
-- 
2.7.4

_______________________________________________
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel

Reply via email to