diff options
author | Suman Anna <s-anna@ti.com> | 2010-07-15 13:16:08 -0500 |
---|---|---|
committer | Ricardo Perez Olivares <x0081762@ti.com> | 2010-07-16 17:41:47 -0500 |
commit | 3966d6f08967d87103e45ac905366d0d359f2147 (patch) | |
tree | ae7397089fd4a34403ce4886d3ce083f63fdff83 /drivers | |
parent | 5f5c3d9528f92848068d1708180592c319a0cb32 (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.c | 103 | ||||
-rw-r--r-- | drivers/dsp/syslink/multicore_ipc/gatemp.c | 30 | ||||
-rw-r--r-- | drivers/dsp/syslink/multicore_ipc/gatepeterson.c | 11 |
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. |