OMAP: hwmod: separate list locking and hwmod hardware locking
Currently omap_hwmod_mutex is being used to protect both the list access/modification and concurrent access to hwmod functions. This patch separates these two types of locking. First, omap_hwmod_mutex is used only to protect access and modification of omap_hwmod_list. Also cleaned up some comments referring to this mutex that are no longer needed. Then, for protecting concurrent access to hwmod functions, use a per-hwmod mutex. This protects concurrent access to a single hwmod, but would allow concurrent access to different hwmods. Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com> [paul@pwsan.com: added structure documentation; changed mutex variable name] Signed-off-by: Paul Walmsley <paul@pwsan.com>
This commit is contained in:
committed by
Paul Walmsley
parent
ff4d3e186b
commit
12b1fdb45c
@@ -767,10 +767,10 @@ static struct omap_hwmod *_lookup(const char *name)
|
|||||||
* @data: not used; pass NULL
|
* @data: not used; pass NULL
|
||||||
*
|
*
|
||||||
* Called by omap_hwmod_late_init() (after omap2_clk_init()).
|
* Called by omap_hwmod_late_init() (after omap2_clk_init()).
|
||||||
* Resolves all clock names embedded in the hwmod. Must be called
|
* Resolves all clock names embedded in the hwmod. Returns -EINVAL if
|
||||||
* with omap_hwmod_mutex held. Returns -EINVAL if the omap_hwmod
|
* the omap_hwmod has not yet been registered or if the clocks have
|
||||||
* has not yet been registered or if the clocks have already been
|
* already been initialized, 0 on success, or a non-zero error on
|
||||||
* initialized, 0 on success, or a non-zero error on failure.
|
* failure.
|
||||||
*/
|
*/
|
||||||
static int _init_clocks(struct omap_hwmod *oh, void *data)
|
static int _init_clocks(struct omap_hwmod *oh, void *data)
|
||||||
{
|
{
|
||||||
@@ -838,10 +838,9 @@ static int _wait_target_ready(struct omap_hwmod *oh)
|
|||||||
* @oh: struct omap_hwmod *
|
* @oh: struct omap_hwmod *
|
||||||
*
|
*
|
||||||
* Resets an omap_hwmod @oh via the OCP_SYSCONFIG bit. hwmod must be
|
* Resets an omap_hwmod @oh via the OCP_SYSCONFIG bit. hwmod must be
|
||||||
* enabled for this to work. Must be called with omap_hwmod_mutex
|
* enabled for this to work. Returns -EINVAL if the hwmod cannot be
|
||||||
* held. Returns -EINVAL if the hwmod cannot be reset this way or if
|
* reset this way or if the hwmod is in the wrong state, -ETIMEDOUT if
|
||||||
* the hwmod is in the wrong state, -ETIMEDOUT if the module did not
|
* the module did not reset in time, or 0 upon success.
|
||||||
* reset in time, or 0 upon success.
|
|
||||||
*/
|
*/
|
||||||
static int _reset(struct omap_hwmod *oh)
|
static int _reset(struct omap_hwmod *oh)
|
||||||
{
|
{
|
||||||
@@ -891,9 +890,8 @@ static int _reset(struct omap_hwmod *oh)
|
|||||||
* @oh: struct omap_hwmod *
|
* @oh: struct omap_hwmod *
|
||||||
*
|
*
|
||||||
* Enables an omap_hwmod @oh such that the MPU can access the hwmod's
|
* Enables an omap_hwmod @oh such that the MPU can access the hwmod's
|
||||||
* register target. Must be called with omap_hwmod_mutex held.
|
* register target. Returns -EINVAL if the hwmod is in the wrong
|
||||||
* Returns -EINVAL if the hwmod is in the wrong state or passes along
|
* state or passes along the return value of _wait_target_ready().
|
||||||
* the return value of _wait_target_ready().
|
|
||||||
*/
|
*/
|
||||||
int _omap_hwmod_enable(struct omap_hwmod *oh)
|
int _omap_hwmod_enable(struct omap_hwmod *oh)
|
||||||
{
|
{
|
||||||
@@ -1004,11 +1002,10 @@ static int _shutdown(struct omap_hwmod *oh)
|
|||||||
* @skip_setup_idle_p: do not idle hwmods at the end of the fn if 1
|
* @skip_setup_idle_p: do not idle hwmods at the end of the fn if 1
|
||||||
*
|
*
|
||||||
* Writes the CLOCKACTIVITY bits @clockact to the hwmod @oh
|
* Writes the CLOCKACTIVITY bits @clockact to the hwmod @oh
|
||||||
* OCP_SYSCONFIG register. Must be called with omap_hwmod_mutex held.
|
* OCP_SYSCONFIG register. @skip_setup_idle is intended to be used on
|
||||||
* @skip_setup_idle is intended to be used on a system that will not
|
* a system that will not call omap_hwmod_enable() to enable devices
|
||||||
* call omap_hwmod_enable() to enable devices (e.g., a system without
|
* (e.g., a system without PM runtime). Returns -EINVAL if the hwmod
|
||||||
* PM runtime). Returns -EINVAL if the hwmod is in the wrong state or
|
* is in the wrong state or returns 0.
|
||||||
* returns 0.
|
|
||||||
*/
|
*/
|
||||||
static int _setup(struct omap_hwmod *oh, void *data)
|
static int _setup(struct omap_hwmod *oh, void *data)
|
||||||
{
|
{
|
||||||
@@ -1038,6 +1035,7 @@ static int _setup(struct omap_hwmod *oh, void *data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutex_init(&oh->_mutex);
|
||||||
oh->_state = _HWMOD_STATE_INITIALIZED;
|
oh->_state = _HWMOD_STATE_INITIALIZED;
|
||||||
|
|
||||||
r = _omap_hwmod_enable(oh);
|
r = _omap_hwmod_enable(oh);
|
||||||
@@ -1323,9 +1321,9 @@ int omap_hwmod_enable(struct omap_hwmod *oh)
|
|||||||
if (!oh)
|
if (!oh)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
mutex_lock(&omap_hwmod_mutex);
|
mutex_lock(&oh->_mutex);
|
||||||
r = _omap_hwmod_enable(oh);
|
r = _omap_hwmod_enable(oh);
|
||||||
mutex_unlock(&omap_hwmod_mutex);
|
mutex_unlock(&oh->_mutex);
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@@ -1343,9 +1341,9 @@ int omap_hwmod_idle(struct omap_hwmod *oh)
|
|||||||
if (!oh)
|
if (!oh)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
mutex_lock(&omap_hwmod_mutex);
|
mutex_lock(&oh->_mutex);
|
||||||
_omap_hwmod_idle(oh);
|
_omap_hwmod_idle(oh);
|
||||||
mutex_unlock(&omap_hwmod_mutex);
|
mutex_unlock(&oh->_mutex);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1363,9 +1361,9 @@ int omap_hwmod_shutdown(struct omap_hwmod *oh)
|
|||||||
if (!oh)
|
if (!oh)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
mutex_lock(&omap_hwmod_mutex);
|
mutex_lock(&oh->_mutex);
|
||||||
_shutdown(oh);
|
_shutdown(oh);
|
||||||
mutex_unlock(&omap_hwmod_mutex);
|
mutex_unlock(&oh->_mutex);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1378,9 +1376,9 @@ int omap_hwmod_shutdown(struct omap_hwmod *oh)
|
|||||||
*/
|
*/
|
||||||
int omap_hwmod_enable_clocks(struct omap_hwmod *oh)
|
int omap_hwmod_enable_clocks(struct omap_hwmod *oh)
|
||||||
{
|
{
|
||||||
mutex_lock(&omap_hwmod_mutex);
|
mutex_lock(&oh->_mutex);
|
||||||
_enable_clocks(oh);
|
_enable_clocks(oh);
|
||||||
mutex_unlock(&omap_hwmod_mutex);
|
mutex_unlock(&oh->_mutex);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1393,9 +1391,9 @@ int omap_hwmod_enable_clocks(struct omap_hwmod *oh)
|
|||||||
*/
|
*/
|
||||||
int omap_hwmod_disable_clocks(struct omap_hwmod *oh)
|
int omap_hwmod_disable_clocks(struct omap_hwmod *oh)
|
||||||
{
|
{
|
||||||
mutex_lock(&omap_hwmod_mutex);
|
mutex_lock(&oh->_mutex);
|
||||||
_disable_clocks(oh);
|
_disable_clocks(oh);
|
||||||
mutex_unlock(&omap_hwmod_mutex);
|
mutex_unlock(&oh->_mutex);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1443,9 +1441,9 @@ int omap_hwmod_reset(struct omap_hwmod *oh)
|
|||||||
if (!oh)
|
if (!oh)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
mutex_lock(&omap_hwmod_mutex);
|
mutex_lock(&oh->_mutex);
|
||||||
r = _reset(oh);
|
r = _reset(oh);
|
||||||
mutex_unlock(&omap_hwmod_mutex);
|
mutex_unlock(&oh->_mutex);
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@@ -1646,9 +1644,9 @@ int omap_hwmod_enable_wakeup(struct omap_hwmod *oh)
|
|||||||
!(oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP))
|
!(oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
mutex_lock(&omap_hwmod_mutex);
|
mutex_lock(&oh->_mutex);
|
||||||
_enable_wakeup(oh);
|
_enable_wakeup(oh);
|
||||||
mutex_unlock(&omap_hwmod_mutex);
|
mutex_unlock(&oh->_mutex);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1671,9 +1669,9 @@ int omap_hwmod_disable_wakeup(struct omap_hwmod *oh)
|
|||||||
!(oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP))
|
!(oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
mutex_lock(&omap_hwmod_mutex);
|
mutex_lock(&oh->_mutex);
|
||||||
_disable_wakeup(oh);
|
_disable_wakeup(oh);
|
||||||
mutex_unlock(&omap_hwmod_mutex);
|
mutex_unlock(&oh->_mutex);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -35,6 +35,7 @@
|
|||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <linux/ioport.h>
|
#include <linux/ioport.h>
|
||||||
|
#include <linux/mutex.h>
|
||||||
#include <plat/cpu.h>
|
#include <plat/cpu.h>
|
||||||
|
|
||||||
struct omap_device;
|
struct omap_device;
|
||||||
@@ -433,6 +434,7 @@ struct omap_hwmod_class {
|
|||||||
* @_state: internal-use hwmod state
|
* @_state: internal-use hwmod state
|
||||||
* @flags: hwmod flags (documented below)
|
* @flags: hwmod flags (documented below)
|
||||||
* @omap_chip: OMAP chips this hwmod is present on
|
* @omap_chip: OMAP chips this hwmod is present on
|
||||||
|
* @_mutex: mutex serializing operations on this hwmod
|
||||||
* @node: list node for hwmod list (internal use)
|
* @node: list node for hwmod list (internal use)
|
||||||
*
|
*
|
||||||
* @main_clk refers to this module's "main clock," which for our
|
* @main_clk refers to this module's "main clock," which for our
|
||||||
@@ -461,6 +463,7 @@ struct omap_hwmod {
|
|||||||
void *dev_attr;
|
void *dev_attr;
|
||||||
u32 _sysc_cache;
|
u32 _sysc_cache;
|
||||||
void __iomem *_mpu_rt_va;
|
void __iomem *_mpu_rt_va;
|
||||||
|
struct mutex _mutex;
|
||||||
struct list_head node;
|
struct list_head node;
|
||||||
u16 flags;
|
u16 flags;
|
||||||
u8 _mpu_port_index;
|
u8 _mpu_port_index;
|
||||||
|
Reference in New Issue
Block a user