summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorSuman Anna <s-anna@ti.com>2010-07-15 13:16:08 -0500
committerRicardo Perez Olivares <x0081762@ti.com>2010-07-16 17:41:47 -0500
commit3966d6f08967d87103e45ac905366d0d359f2147 (patch)
treeae7397089fd4a34403ce4886d3ce083f63fdff83 /drivers
parent5f5c3d9528f92848068d1708180592c319a0cb32 (diff)
SYSLINK: ipc - adapt gatehwspinlock module to use hwspinlock driver
The gatemp, gatehwspinlock & gatepeterson modules have been enhanced to support reserved resources for each gate_type. This change is done as part of the gatehwspinlock adaptation to the open-source hwspinlock driver code. gatemp module was managing all the spinlocks previously, and with this patch, gatemp module will only control and manage a contiguous block of spinlocks from 4 to 31. The h/w spinlocks 0 to 3 will be reserved for usage by I2C driver. All the spinlocks except the reserved spinlocks are acquired upfront in the gatehwspinlock_setup function, instead of requesting it during create time. This ensures the GateMP module has control over these so that BIOS-side functionality can remain the same as before. Signed-off-by: Suman Anna <s-anna@ti.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/dsp/syslink/multicore_ipc/gatehwspinlock.c103
-rw-r--r--drivers/dsp/syslink/multicore_ipc/gatemp.c30
-rw-r--r--drivers/dsp/syslink/multicore_ipc/gatepeterson.c11
3 files changed, 121 insertions, 23 deletions
diff --git a/drivers/dsp/syslink/multicore_ipc/gatehwspinlock.c b/drivers/dsp/syslink/multicore_ipc/gatehwspinlock.c
index c97e57cb30f8..20405a14fdd4 100644
--- a/drivers/dsp/syslink/multicore_ipc/gatehwspinlock.c
+++ b/drivers/dsp/syslink/multicore_ipc/gatehwspinlock.c
@@ -21,6 +21,7 @@
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/slab.h>
+#include <plat/hwspinlock.h>
#include <syslink/atomic_linux.h>
#include <multiproc.h>
@@ -51,6 +52,9 @@ struct gatehwspinlock_module_object {
paramters */
u32 *base_addr; /* Base address of lock registers */
u32 num_locks; /* Maximum number of locks */
+ u32 num_reserved; /* Number of reserved locks */
+ struct hwspinlock **hw_lock_handles;
+ /* Array of hwspinlock handles controlled by gatemp */
};
/*
@@ -62,6 +66,7 @@ struct gatehwspinlock_object {
u32 lock_num;
u32 nested;
void *local_gate;
+ struct hwspinlock *hwhandle;
};
/*
@@ -74,7 +79,10 @@ struct gatehwspinlock_module_object gatehwspinlock_state = {
.def_inst_params.shared_addr = NULL,
.def_inst_params.resource_id = 0x0,
.def_inst_params.region_id = 0x0,
- .num_locks = 32u
+ .hw_lock_handles = NULL,
+ .num_locks = 32u,
+ .num_reserved = 4
+ /* GateMP controls SpinLocks 4-31. 0-3 are reserved for usage by I2C */
};
static struct gatehwspinlock_module_object *gatehwspinlock_module =
@@ -131,6 +139,9 @@ int gatehwspinlock_setup(const struct gatehwspinlock_config *config)
{
struct gatehwspinlock_config tmp_cfg;
int *key = 0;
+ struct hwspinlock *lock_handle;
+ int i;
+ s32 retval;
key = gate_enter_system();
@@ -153,14 +164,44 @@ int gatehwspinlock_setup(const struct gatehwspinlock_config *config)
}
gate_leave_system(key);
+ gatehwspinlock_module->hw_lock_handles = kzalloc(
+ gatehwspinlock_module->num_locks * sizeof(struct hwspinlock *),
+ GFP_KERNEL);
+ if (gatehwspinlock_module->hw_lock_handles == NULL) {
+ retval = -ENOMEM;
+ goto exit;
+ }
+
memcpy(&gatehwspinlock_module->cfg, config,
sizeof(struct gatehwspinlock_config));
gatehwspinlock_module->base_addr = (void *)config->base_addr;
gatehwspinlock_module->num_locks = config->num_locks;
-
+ for (i = gatehwspinlock_module->num_reserved;
+ i < gatehwspinlock_module->num_locks; i++) {
+ lock_handle = hwspinlock_request_specific(i);
+ if (lock_handle == NULL) {
+ retval = -EBUSY;
+ printk(KERN_ERR "hwspinlock_request failed for"
+ "id = %d", i);
+ goto spinlock_request_fail;
+ }
+ gatehwspinlock_module->hw_lock_handles[i] = lock_handle;
+ }
return 0;
+spinlock_request_fail:
+ for (; i >= gatehwspinlock_module->num_reserved; i--) {
+ hwspinlock_free(gatehwspinlock_module->hw_lock_handles[i]);
+ gatehwspinlock_module->hw_lock_handles[i] = NULL;
+ }
+exit:
+ kfree(gatehwspinlock_module->hw_lock_handles);
+ atomic_dec_return(&gatehwspinlock_module->ref_count);
+ if (retval < 0)
+ printk(KERN_ERR "gatehwspinlock_setup failed! status = 0x%x",
+ retval);
+ return retval;
}
EXPORT_SYMBOL(gatehwspinlock_setup);
@@ -173,6 +214,8 @@ int gatehwspinlock_destroy(void)
{
s32 retval = 0;
int *key = 0;
+ struct hwspinlock *lock_handle;
+ int i;
key = gate_enter_system();
@@ -191,8 +234,19 @@ int gatehwspinlock_destroy(void)
}
gate_leave_system(key);
+ for (i = gatehwspinlock_module->num_reserved;
+ i < gatehwspinlock_module->num_locks; i++) {
+ lock_handle = gatehwspinlock_module->hw_lock_handles[i];
+ retval = hwspinlock_free(lock_handle);
+ if (retval < 0)
+ printk(KERN_ERR "hwspinlock_free failed for"
+ "id = %d", i);
+ gatehwspinlock_module->hw_lock_handles[i] = NULL;
+ }
memset(&gatehwspinlock_module->cfg, 0,
sizeof(struct gatehwspinlock_config));
+ kfree(gatehwspinlock_module->hw_lock_handles);
+ gatehwspinlock_module->hw_lock_handles = NULL;
return 0;
exit:
@@ -217,6 +271,17 @@ u32 gatehwspinlock_get_num_instances(void)
EXPORT_SYMBOL(gatehwspinlock_get_num_instances);
/*
+ * ======== gatehwspinlock_get_num_reserved ========
+ * Purpose:
+ * Function to return the number of instances not under GateMP's control.
+ */
+u32 gatehwspinlock_get_num_reserved(void)
+{
+ return gatehwspinlock_module->num_reserved;
+}
+EXPORT_SYMBOL(gatehwspinlock_get_num_reserved);
+
+/*
* ======== gatepeterson_locks_init ========
* Purpose:
* Function to initialize the locks.
@@ -304,10 +369,19 @@ void *gatehwspinlock_create(enum igatempsupport_local_protect local_protect,
obj->lock_num = params->resource_id;
obj->nested = 0;
-
+ obj->hwhandle = \
+ gatehwspinlock_module->hw_lock_handles[params->resource_id];
+ if (obj->hwhandle == NULL) {
+ retval = -EBUSY;
+ printk(KERN_ERR "hwspinlock_request failed for id = %d",
+ params->resource_id);
+ goto free_obj;
+ }
handle = obj;
return handle;
+free_obj:
+ kfree(obj);
exit:
printk(KERN_ERR "gatehwspinlock_create failed status: %x\n", retval);
return NULL;
@@ -344,7 +418,7 @@ int gatehwspinlock_delete(void **gphandle)
/* No need to delete the local gate, as it is gatemp module wide
* local mutex. */
-
+ obj->hwhandle = NULL;
kfree(obj);
*gphandle = NULL;
@@ -367,8 +441,6 @@ int *gatehwspinlock_enter(void *gphandle)
struct gatehwspinlock_object *obj = NULL;
s32 retval = 0;
int *key = 0;
- VOLATILE u32 *base_addr = (VOLATILE u32 *)
- gatehwspinlock_module->base_addr;
if (WARN_ON(atomic_cmpmask_and_lt(&(gatehwspinlock_module->ref_count),
GATEHWSPINLOCK_MAKE_MAGICSTAMP(0),
@@ -384,7 +456,6 @@ int *gatehwspinlock_enter(void *gphandle)
obj = (struct gatehwspinlock_object *)gphandle;
/* Enter local gate */
- /* Enter local gate */
if (obj->local_gate != NULL) {
retval = mutex_lock_interruptible(
(struct mutex *)obj->local_gate);
@@ -399,9 +470,10 @@ int *gatehwspinlock_enter(void *gphandle)
return key;
/* Enter the spinlock */
- while (1) {
- if (base_addr[obj->lock_num] == 0)
- break;
+ retval = hwspinlock_lock(obj->hwhandle);
+ if (retval < 0) {
+ obj->nested--;
+ mutex_unlock((struct mutex *)obj->local_gate);
}
exit:
@@ -420,8 +492,6 @@ EXPORT_SYMBOL(gatehwspinlock_enter);
void gatehwspinlock_leave(void *gphandle, int *key)
{
struct gatehwspinlock_object *obj = NULL;
- VOLATILE u32 *base_addr = (VOLATILE u32 *)
- gatehwspinlock_module->base_addr;
s32 retval = 0;
if (WARN_ON(atomic_cmpmask_and_lt(&(gatehwspinlock_module->ref_count),
@@ -438,8 +508,13 @@ void gatehwspinlock_leave(void *gphandle, int *key)
obj = (struct gatehwspinlock_object *)gphandle;
obj->nested--;
/* Leave the spinlock if the leave() is not nested */
- if (obj->nested == 0)
- base_addr[obj->lock_num] = 0;
+ if (obj->nested == 0) {
+ retval = hwspinlock_unlock(obj->hwhandle);
+ if (retval < 0) {
+ obj->nested++;
+ goto exit;
+ }
+ }
/* Leave local gate */
mutex_unlock(obj->local_gate);
diff --git a/drivers/dsp/syslink/multicore_ipc/gatemp.c b/drivers/dsp/syslink/multicore_ipc/gatemp.c
index 4c7244168bbd..a0de6c60b117 100644
--- a/drivers/dsp/syslink/multicore_ipc/gatemp.c
+++ b/drivers/dsp/syslink/multicore_ipc/gatemp.c
@@ -106,6 +106,9 @@ struct gatemp_module_state {
int num_remote_system;
int num_remote_custom1;
int num_remote_custom2;
+ int num_remote_system_reserved;
+ int num_remote_custom1_reserved;
+ int num_remote_custom2_reserved;
u8 *remote_system_in_use_alloc;
u8 *remote_custom1_in_use_alloc;
u8 *remote_custom2_in_use_alloc;
@@ -188,7 +191,7 @@ static void gatemp_clear_region0_reserved(void);
static void gatemp_open_region0_reserved(void *shared_addr);
static void gatemp_close_region0_reserved(void *shared_addr);
static void gatemp_set_default_remote(void *handle);
-static uint gatemp_get_free_resource(u8 *in_use, int num);
+static uint gatemp_get_free_resource(u8 *in_use, int num, int start_id);
static struct gatemp_object *_gatemp_create(
const struct _gatemp_params *params);
@@ -303,7 +306,7 @@ s32 gatemp_setup(const struct gatemp_config *cfg)
goto error_nameserver;
}
- /* Get the number of coonfigured instances from the plugged in
+ /* Get the number of configured instances from the plugged in
* Proxy gates */
gatemp_module->num_remote_system = \
gatemp_remote_system_proxy_get_num_instances();
@@ -311,6 +314,12 @@ s32 gatemp_setup(const struct gatemp_config *cfg)
gatemp_remote_custom1_proxy_get_num_instances();
gatemp_module->num_remote_custom2 = \
gatemp_remote_custom2_proxy_get_num_instances();
+ gatemp_module->num_remote_system_reserved = \
+ gatemp_remote_system_proxy_get_num_reserved();
+ gatemp_module->num_remote_custom1_reserved = \
+ gatemp_remote_custom1_proxy_get_num_reserved();
+ gatemp_module->num_remote_custom2_reserved = \
+ gatemp_remote_custom2_proxy_get_num_reserved();
gatemp_module->remote_system_in_use_alloc = \
kzalloc((sizeof(u8) * cfg->num_resources), GFP_KERNEL);
if (gatemp_module->remote_system_in_use_alloc == NULL) {
@@ -679,8 +688,9 @@ proxy_work:
if (obj->obj_type != IPC_OBJTYPE_OPENDYNAMIC) {
/* Created Instance */
obj->resource_id = gatemp_get_free_resource(
- gatemp_module->remote_system_in_use,
- gatemp_module->num_remote_system);
+ gatemp_module->remote_system_in_use,
+ gatemp_module->num_remote_system,
+ gatemp_module->num_remote_system_reserved);
if (obj->resource_id == -1)
retval = 6;
} else {
@@ -722,8 +732,9 @@ proxy_work:
if (obj->obj_type != IPC_OBJTYPE_OPENDYNAMIC) {
/* Created Instance */
obj->resource_id = gatemp_get_free_resource(
- gatemp_module->remote_custom1_in_use,
- gatemp_module->num_remote_custom1);
+ gatemp_module->remote_custom1_in_use,
+ gatemp_module->num_remote_custom1,
+ gatemp_module->num_remote_custom1_reserved);
if (obj->resource_id == -1)
retval = 6;
} else {
@@ -766,7 +777,8 @@ proxy_work:
/* Created Instance */
obj->resource_id = gatemp_get_free_resource(
gatemp_module->remote_custom2_in_use,
- gatemp_module->num_remote_custom2);
+ gatemp_module->num_remote_custom2,
+ gatemp_module->num_remote_custom1_reserved);
if (obj->resource_id == -1)
retval = 6;
} else {
@@ -1589,7 +1601,7 @@ int gatemp_stop(void)
* Internal functions
*************************************************************************
*/
-uint gatemp_get_free_resource(u8 *in_use, int num)
+uint gatemp_get_free_resource(u8 *in_use, int num, int start_id)
{
int *key = 0;
bool flag = false;
@@ -1610,7 +1622,7 @@ uint gatemp_get_free_resource(u8 *in_use, int num)
/* Find a free resource id. Note: zero is reserved on the
* system proxy for the default gate. */
- for (resource_id = 0; resource_id < num; resource_id++) {
+ for (resource_id = start_id; resource_id < num; resource_id++) {
/* If not in-use, set the in_use to true to prevent other
* creates from getting this one. */
if (in_use[resource_id] == false) {
diff --git a/drivers/dsp/syslink/multicore_ipc/gatepeterson.c b/drivers/dsp/syslink/multicore_ipc/gatepeterson.c
index d49561759f75..d692650b5903 100644
--- a/drivers/dsp/syslink/multicore_ipc/gatepeterson.c
+++ b/drivers/dsp/syslink/multicore_ipc/gatepeterson.c
@@ -293,6 +293,17 @@ u32 gatepeterson_get_num_instances(void)
EXPORT_SYMBOL(gatepeterson_get_num_instances);
/*
+ * ======== gatepeterson_get_num_reserved ========
+ * Purpose:
+ * Function to return the number of instances not under GateMP's control.
+ */
+u32 gatepeterson_get_num_reserved(void)
+{
+ return 0;
+}
+EXPORT_SYMBOL(gatepeterson_get_num_reserved);
+
+/*
* ======== gatepeterson_locks_init ========
* Purpose:
* Function to initialize the locks.