index 142f3e1823094f2c76818032a62c0f62eb64fed2..64fa93a40d2f665df5fc128d5cc9092a7a42be1b 100644 (file)
#include <sys/mman.h>
#include <sys/stat.h>
+#include <linux/ioctl.h>
+#include <linux/hwspinlock_user.h>
+
/* =============================================================================
* Structures & Enums
* =============================================================================
Int32 fd; /* spinlock device handle */
UInt32 * baseAddr; /* base addr lock registers */
GateMutex_Handle gmHandle; /* handle to gate mutex */
+ Bool useHwlockDrv; /* use the hwspinlock driver */
} GateHWSpinlock_Module_State;
/* GateHWSpinlock instance object */
{
.fd = -1,
.baseAddr = NULL,
- .gmHandle = NULL
+ .gmHandle = NULL,
+ .useHwlockDrv = false,
};
static GateHWSpinlock_Module_State *Mod = &GateHWSpinlock_state;
UInt32 dst;
int flags;
- Mod->fd = open ("/dev/mem", O_RDWR | O_SYNC);
- if (Mod->fd < 0){
- PRINTVERBOSE0("GateHWSpinlock_start: failed to open the /dev/mem");
- status = GateHWSpinlock_E_OSFAILURE;
+ /* Fall back to /dev/mem if hwspinlock_user driver is not supported */
+ Mod->fd = open("/dev/hwspinlock", O_RDWR);
+ if (Mod->fd < 0) {
+ Mod->fd = open ("/dev/mem", O_RDWR | O_SYNC);
+ }
+ else {
+ Mod->useHwlockDrv = true;
}
- /* make sure /dev/mem fd doesn't exist for 'fork() -> exec*()'ed child */
- flags = fcntl(Mod->fd, F_GETFD);
- if (flags != -1) {
- fcntl(Mod->fd, F_SETFD, flags | FD_CLOEXEC);
+ if (Mod->fd < 0){
+ PRINTVERBOSE0("GateHWSpinlock_start: failed to open the spinlock device");
+ status = GateHWSpinlock_E_OSFAILURE;
}
- /* map the hardware lock registers into the local address space */
- if (status == GateHWSpinlock_S_SUCCESS) {
- dst = (UInt32)mmap(NULL, _GateHWSpinlock_cfgParams.size,
- (PROT_READ | PROT_WRITE),
- (MAP_SHARED), Mod->fd,
- (off_t)_GateHWSpinlock_cfgParams.baseAddr);
-
- if (dst == (UInt32)MAP_FAILED) {
- PRINTVERBOSE0("GateHWSpinlock_start: Memory map failed")
- status = GateHWSpinlock_E_OSFAILURE;
- close(Mod->fd);
- Mod->fd = -1;
+ if (!Mod->useHwlockDrv) {
+ /* make sure /dev/mem fd doesn't exist for 'fork() -> exec*()'ed child */
+ flags = fcntl(Mod->fd, F_GETFD);
+ if (flags != -1) {
+ fcntl(Mod->fd, F_SETFD, flags | FD_CLOEXEC);
}
- else {
- Mod->baseAddr = (UInt32 *)(dst + _GateHWSpinlock_cfgParams.offset);
- status = GateHWSpinlock_S_SUCCESS;
+
+ /* map the hardware lock registers into the local address space */
+ if (status == GateHWSpinlock_S_SUCCESS) {
+ dst = (UInt32)mmap(NULL, _GateHWSpinlock_cfgParams.size,
+ (PROT_READ | PROT_WRITE),
+ (MAP_SHARED), Mod->fd,
+ (off_t)_GateHWSpinlock_cfgParams.baseAddr);
+
+ if (dst == (UInt32)MAP_FAILED) {
+ PRINTVERBOSE0("GateHWSpinlock_start: Memory map failed")
+ status = GateHWSpinlock_E_OSFAILURE;
+ close(Mod->fd);
+ Mod->fd = -1;
+ }
+ else {
+ Mod->baseAddr = (UInt32 *)(dst + _GateHWSpinlock_cfgParams.offset);
+ status = GateHWSpinlock_S_SUCCESS;
+ }
}
}
}
/* release lock register mapping */
- if (Mod->baseAddr != NULL) {
+ if (!Mod->useHwlockDrv && (Mod->baseAddr != NULL)) {
munmap((void *)_GateHWSpinlock_cfgParams.baseAddr,
_GateHWSpinlock_cfgParams.size);
}
IArg GateHWSpinlock_enter(GateHWSpinlock_Object *obj)
{
volatile UInt32 *baseAddr = Mod->baseAddr;
+ struct hwspinlock_user_lock data = {
+ .id = obj->lockNum,
+ .timeout = 10,
+ };
IArg key;
+ Bool locked;
key = IGateProvider_enter(obj->localGate);
/* enter the spinlock */
while (1) {
- /* read the spinlock, returns non-zero when we get it */
- if (baseAddr[obj->lockNum] == 0) {
+ if (Mod->useHwlockDrv) {
+ locked = !ioctl(Mod->fd, HWSPINLOCK_USER_LOCK, &data);
+ }
+ else {
+ /* read the spinlock, returns non-zero when we get it */
+ locked = (baseAddr[obj->lockNum] == 0);
+ }
+
+ if (locked) {
break;
}
+
obj->nested--;
IGateProvider_leave(obj->localGate, key);
key = IGateProvider_enter(obj->localGate);
Int GateHWSpinlock_leave(GateHWSpinlock_Object *obj, IArg key)
{
volatile UInt32 *baseAddr = Mod->baseAddr;
+ struct hwspinlock_user_unlock data = {
+ .id = obj->lockNum,
+ };
obj->nested--;
/* release the spinlock if not nested */
if (obj->nested == 0) {
- baseAddr[obj->lockNum] = 0;
+ if (Mod->useHwlockDrv) {
+ ioctl(Mod->fd, HWSPINLOCK_USER_UNLOCK, &data);
+ }
+ else {
+ baseAddr[obj->lockNum] = 0;
+ }
}
IGateProvider_leave(obj->localGate, key);