Commit 12b1fdb4 authored by Kevin Hilman's avatar Kevin Hilman Committed by Paul Walmsley

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: default avatarKevin Hilman <khilman@deeprootsystems.com>
[paul@pwsan.com: added structure documentation; changed mutex variable
 name]
Signed-off-by: default avatarPaul Walmsley <paul@pwsan.com>
parent ff4d3e18
...@@ -767,10 +767,10 @@ static struct omap_hwmod *_lookup(const char *name) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 @@ ...@@ -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 { ...@@ -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 { ...@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment