Changeset 1ea73e2b in rtems


Ignore:
Timestamp:
May 11, 2017, 11:43:53 AM (2 years ago)
Author:
Daniel Hellstrom <daniel@…>
Branches:
master
Children:
8639685
Parents:
818f10bc
git-author:
Daniel Hellstrom <daniel@…> (05/11/17 11:43:53)
git-committer:
Daniel Hellstrom <daniel@…> (05/14/17 10:32:00)
Message:

leon, grtc: SMP support by using spin-locks

File:
1 edited

Legend:

Unmodified
Added
Removed
  • c/src/lib/libbsp/sparc/shared/tmtc/grtc.c

    r818f10bc r1ea73e2b  
    2424#include <bsp/grtc.h>
    2525
    26 #ifndef IRQ_GLOBAL_PREPARE
    27  #define IRQ_GLOBAL_PREPARE(level) rtems_interrupt_level level
    28 #endif
    29 
    30 #ifndef IRQ_GLOBAL_DISABLE
    31  #define IRQ_GLOBAL_DISABLE(level) rtems_interrupt_disable(level)
    32 #endif
    33 
    34 #ifndef IRQ_GLOBAL_ENABLE
    35  #define IRQ_GLOBAL_ENABLE(level) rtems_interrupt_enable(level)
    36 #endif
     26/* map via rtems_interrupt_lock_* API: */
     27#define SPIN_DECLARE(lock) RTEMS_INTERRUPT_LOCK_MEMBER(lock)
     28#define SPIN_INIT(lock, name) rtems_interrupt_lock_initialize(lock, name)
     29#define SPIN_LOCK(lock, level) rtems_interrupt_lock_acquire_isr(lock, &level)
     30#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_lock_acquire(lock, &level)
     31#define SPIN_UNLOCK(lock, level) rtems_interrupt_lock_release_isr(lock, &level)
     32#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_lock_release(lock, &level)
     33#define SPIN_IRQFLAGS(k) rtems_interrupt_lock_context k
     34#define SPIN_ISR_IRQFLAGS(k) SPIN_IRQFLAGS(k)
     35
     36/* turn on/off local CPU's interrupt to ensure HW timing - not SMP safe. */
     37#define IRQ_LOCAL_DECLARE(_level) rtems_interrupt_level _level
     38#define IRQ_LOCAL_DISABLE(_level) rtems_interrupt_local_disable(_level)
     39#define IRQ_LOCAL_ENABLE(_level) rtems_interrupt_local_enable(_level)
    3740
    3841/*
     
    237240        struct grtc_regs        *regs;          /* TC Hardware Register MAP */
    238241        int                     irq;            /* IRQ number of TC core */
     242        SPIN_DECLARE(devlock);                  /* spin-lock of registers */
    239243
    240244        int                     major;          /* Driver major */
     
    398402                sprintf(priv->devName, "/dev/%sgrtc%d", prefix, dev->minor_bus);
    399403        }
     404
     405        SPIN_INIT(&priv->devlock, priv->devName);
    400406
    401407        /* Register Device */
     
    704710}
    705711
    706 static void grtc_stop(struct grtc_priv *pDev)
     712static void grtc_stop(struct grtc_priv *pDev, int overrun)
    707713{
    708714        struct grtc_regs *regs = pDev->regs;
     715        SPIN_IRQFLAGS(irqflags);
     716
     717        SPIN_LOCK_IRQ(&pDev->devlock, irqflags);
    709718
    710719        /* Disable the receiver */
     
    718727        DBG("GRTC: STOPPED\n");
    719728
     729        if (overrun) {
     730                pDev->overrun_condition = 1;
     731        } else {
     732                pDev->running = 0;
     733        }
     734
     735        SPIN_UNLOCK_IRQ(&pDev->devlock, irqflags);
     736
    720737        /* Flush semaphores in case a thread is stuck waiting for CLTUs (RX data) */
    721738        rtems_semaphore_flush(pDev->sem_rx);
     
    729746        int avail;
    730747        int ret;
    731         IRQ_GLOBAL_PREPARE(oldLevel);
     748        SPIN_IRQFLAGS(irqflags);
    732749
    733750        FUNCDBG();
     
    736753                return 0;
    737754
    738         IRQ_GLOBAL_DISABLE(oldLevel);
     755        SPIN_LOCK_IRQ(&pDev->devlock, irqflags);
    739756
    740757        /* Enable interrupts when receiving CLTUs, Also clear old pending CLTUs store
     
    748765                /* Wait for interrupt. */
    749766
    750                 IRQ_GLOBAL_ENABLE(oldLevel);
     767                SPIN_UNLOCK_IRQ(&pDev->devlock, irqflags);
    751768
    752769                if ( timeout == 0 ){
     
    760777                 * RTEMS_OBJECT_WAS_DELETED, RTEMS_INVALID_ID = driver error.
    761778                 */
    762                 IRQ_GLOBAL_DISABLE(oldLevel);
     779                SPIN_LOCK_IRQ(&pDev->devlock, irqflags);
    763780        }else{
    764781                ret = RTEMS_SUCCESSFUL;
     
    768785        pDev->regs->imr = READ_REG(&pDev->regs->imr) & ~GRTC_INT_CS;
    769786
    770         IRQ_GLOBAL_ENABLE(oldLevel);
     787        SPIN_UNLOCK_IRQ(&pDev->devlock, irqflags);
    771788
    772789        return ret;
     
    846863
    847864        if ( pDev->running ){
    848                 grtc_stop(pDev);
    849                 pDev->running = 0;
     865                grtc_stop(pDev, 0);
    850866        }
    851867
     
    15431559        struct grtc_ioc_stats *stats;
    15441560        unsigned int mem;
    1545        
    1546         IRQ_GLOBAL_PREPARE(oldLevel);
     1561        IRQ_LOCAL_DECLARE(oldLevel);
    15471562
    15481563        FUNCDBG();
     
    15761591                }
    15771592                drvmgr_interrupt_unregister(pDev->dev, 0, grtc_interrupt, pDev);
    1578                 grtc_stop(pDev);
    1579                 pDev->running = 0;
     1593                grtc_stop(pDev, 0);
    15801594                break;
    15811595
     
    17171731                        return RTEMS_INVALID_NAME;
    17181732                }
    1719                 /* We disable interrupt in order to get a snapshot of the registers */
    1720                 IRQ_GLOBAL_DISABLE(oldLevel);
     1733                /* We disable interrupt on the local CPU in order to get a
     1734                 * snapshot of the registers.
     1735                 */
     1736                IRQ_LOCAL_DISABLE(oldLevel);
    17211737                hwregs->sir     = READ_REG(&pDev->regs->sir);
    17221738                hwregs->far     = READ_REG(&pDev->regs->far);
     
    17251741                hwregs->phir    = READ_REG(&pDev->regs->phir);
    17261742                hwregs->str     = READ_REG(&pDev->regs->str);
    1727                 IRQ_GLOBAL_ENABLE(oldLevel);
     1743                IRQ_LOCAL_ENABLE(oldLevel);
    17281744                break;
    17291745
     
    18981914        struct grtc_regs *regs = pDev->regs;
    18991915        unsigned int status;
     1916        SPIN_ISR_IRQFLAGS(irqflags);
    19001917
    19011918        /* Clear interrupt by reading it */
     
    19071924
    19081925        if ( status & GRTC_INT_OV ){
    1909                
    19101926                /* Stop core (Disable receiver, interrupts), set overrun condition,
    19111927                 * Flush semaphore if thread waiting for data in grtc_wait_data().
    19121928                 */
    1913                 pDev->overrun_condition = 1;
    1914 
    1915                 grtc_stop(pDev);
     1929                grtc_stop(pDev, 1);
    19161930
    19171931                /* No need to handle the reset of interrupts, we are still */
     
    19201934
    19211935        if ( status & GRTC_INT_CS ){
     1936                SPIN_LOCK(&pDev->devlock, irqflags);
     1937
    19221938                if ( (pDev->blocking==GRTC_BLKMODE_COMPLETE) && pDev->timeout ){
    19231939                        /* Signal to thread only if enough data is available */
     
    19261942                                goto procceed_processing_interrupts;
    19271943                        }
    1928                        
    1929                         /* Enough data is available which means that we should wake
    1930                          * up thread sleeping.
     1944
     1945                        /* Enough data is available which means that we should
     1946                         * wake up the thread sleeping.
    19311947                         */
    19321948                }
    1933                
    1934                 /* Disable further CLTUs Stored interrupts, no point until thread waiting for them
    1935                  * say it want to wait for more.
     1949
     1950                /* Disable further CLTUs Stored interrupts, no point until
     1951                 * thread waiting for them says it want to wait for more.
    19361952                 */
    19371953                regs->imr = READ_REG(&regs->imr) & ~GRTC_INT_CS;
    1938                
     1954                SPIN_UNLOCK(&pDev->devlock, irqflags);
     1955
    19391956                /* Signal Semaphore to wake waiting thread in read() */
    19401957                rtems_semaphore_release(pDev->sem_rx);
Note: See TracChangeset for help on using the changeset viewer.