forked from Imagelibrary/rtems
grlib/l2c: Prevent concurrent register access
Accesses to the L2C registers performed by the L2C driver are now serialized with spin locks. This avoids concurrent access to the L2C registers by multiple processors. Proposed by GRLIB-TN-0021. Update #4925.
This commit is contained in:
committed by
Kinsey Moore
parent
1ce6347976
commit
85add65a91
@@ -38,6 +38,7 @@
|
|||||||
#include <grlib/grlib.h>
|
#include <grlib/grlib.h>
|
||||||
#include <bsp.h>
|
#include <bsp.h>
|
||||||
#include <grlib/l2c.h>
|
#include <grlib/l2c.h>
|
||||||
|
#include <grlib/grlib_impl.h>
|
||||||
|
|
||||||
/*#define STATIC*/
|
/*#define STATIC*/
|
||||||
#define STATIC static
|
#define STATIC static
|
||||||
@@ -317,6 +318,8 @@ struct l2cache_priv {
|
|||||||
int ft_support;
|
int ft_support;
|
||||||
int split_support;
|
int split_support;
|
||||||
int atomic_flush;
|
int atomic_flush;
|
||||||
|
/* Avoid concurrent accesses to L2C registers. */
|
||||||
|
SPIN_DECLARE(devlock);
|
||||||
|
|
||||||
/* User defined ISR */
|
/* User defined ISR */
|
||||||
l2cache_isr_t isr;
|
l2cache_isr_t isr;
|
||||||
@@ -383,8 +386,25 @@ static struct l2cache_priv *l2cachepriv = NULL;
|
|||||||
static char * repl_names[4] = {"LRU","Random","Master-Idx-1","Master-IDx-2"};
|
static char * repl_names[4] = {"LRU","Random","Master-Idx-1","Master-IDx-2"};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define REG_WRITE(addr, val) (*(volatile unsigned int *)(addr) = (unsigned int)(val))
|
static void REG_WRITE(volatile unsigned int *addr, unsigned int val) {
|
||||||
#define REG_READ(addr) (*(volatile unsigned int *)(addr))
|
struct l2cache_priv *priv = l2cachepriv;
|
||||||
|
SPIN_IRQFLAGS(irqflags);
|
||||||
|
|
||||||
|
SPIN_LOCK_IRQ(&priv->devlock, irqflags);
|
||||||
|
*addr = val;
|
||||||
|
SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int REG_READ(volatile unsigned int *addr) {
|
||||||
|
struct l2cache_priv *priv = l2cachepriv;
|
||||||
|
SPIN_IRQFLAGS(irqflags);
|
||||||
|
unsigned int val;
|
||||||
|
|
||||||
|
SPIN_LOCK_IRQ(&priv->devlock, irqflags);
|
||||||
|
val = *addr;
|
||||||
|
SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(__sparc__)
|
#if defined(__sparc__)
|
||||||
static inline uint32_t atomic_swap32(uint32_t *addr, uint32_t val) {
|
static inline uint32_t atomic_swap32(uint32_t *addr, uint32_t val) {
|
||||||
@@ -397,7 +417,15 @@ static inline uint32_t atomic_swap32(uint32_t *addr, uint32_t val) {
|
|||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define REG_WRITE_ATOMIC(addr, val) atomic_swap32((uint32_t *)addr, val)
|
static void REG_WRITE_ATOMIC(volatile unsigned int *addr, unsigned int val) {
|
||||||
|
struct l2cache_priv *priv = l2cachepriv;
|
||||||
|
SPIN_IRQFLAGS(irqflags);
|
||||||
|
|
||||||
|
SPIN_LOCK_IRQ(&priv->devlock, irqflags);
|
||||||
|
atomic_swap32((uint32_t *) addr, val);
|
||||||
|
SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#define REG_WRITE_ATOMIC(addr, val) REG_WRITE(addr, val)
|
#define REG_WRITE_ATOMIC(addr, val) REG_WRITE(addr, val)
|
||||||
#endif
|
#endif
|
||||||
@@ -513,6 +541,7 @@ int l2cache_init1(struct drvmgr_dev *dev)
|
|||||||
priv->dev = dev;
|
priv->dev = dev;
|
||||||
strncpy(&priv->devname[0], "l2cache0", DEVNAME_LEN);
|
strncpy(&priv->devname[0], "l2cache0", DEVNAME_LEN);
|
||||||
l2cachepriv = priv;
|
l2cachepriv = priv;
|
||||||
|
SPIN_INIT(&priv->devlock, priv->devname);
|
||||||
|
|
||||||
/* Initialize L2CACHE Hardware */
|
/* Initialize L2CACHE Hardware */
|
||||||
status = l2cache_init(priv);
|
status = l2cache_init(priv);
|
||||||
|
|||||||
Reference in New Issue
Block a user