omap-pm: resource: Lock resource list in update_resource_level
Subsystems (2)
PATCH 1/2 omap-pm: resource: Lock resource list in update_resource_level
Take the resource mutex when iterating over the resource user_list. A race can occur if resource_request() adds a first time user to the user_list while update_resource_level() is called.
Signed-off-by Mike Chan <[email protected]>
--- arch/arm/plat-omap/resource.c | 9 +++++++-- 1 files changed, 7 insertions(+), 2 deletions(-)
arch/arm/plat-omap/resource.c +7 -2
@@ -106,6 +106,7 @@ static int update_resource_level(struct shared_resource *resp)unsigned long target_level;int ret; +mutex_lock (&resp->resource_mutex);/* Regenerate the target_value for the resource */ if (resp->flags &RES_TYPE_PERFORMANCE ) { target_level =RES_PERFORMANCE_DEFAULTLEVEL ;
@@ -118,9 +119,11 @@ static int update_resource_level(struct shared_resource *resp)if (user->level < target_level) target_level = user->level; }else { +mutex_unlock (&resp->resource_mutex);pr_debug ("SRF: Unknown resource type\n" );return -EINVAL ; } +mutex_unlock (&resp->resource_mutex);pr_debug ("SRF: Changing Level for resource %s to %ld\n" , resp->name, target_level);
@@ -439,10 +442,12 @@ int resource_release(const char *name, struct device *dev)list_del (&user->node);free_user (user); -/* Recompute and set the current level for the resource */ - ret =update_resource_level (resp); res_unlock:mutex_unlock (&resp->resource_mutex); +/* Recompute and set the current level for the resource */ +if (!ret) + ret =update_resource_level (resp); +return ret; }EXPORT_SYMBOL (resource_release);
Signature · 1 line
1.7.0.1
PATCH 2/2 omap-pm: resource: Only update resource level if there is a change
Previosuly update_resource_level() would always call the change_level() function, even if there was no change necessary.
Signed-off-by Mike Chan <[email protected]>
--- arch/arm/plat-omap/resource.c | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-)
arch/arm/plat-omap/resource.c +4 -1
@@ -104,7 +104,7 @@ static int update_resource_level(struct shared_resource *resp) {struct users_list *user;unsigned long target_level; -int ret; +int ret =0 ;mutex_lock (&resp->resource_mutex);/* Regenerate the target_value for the resource */
@@ -125,6 +125,9 @@ static int update_resource_level(struct shared_resource *resp) }mutex_unlock (&resp->resource_mutex); +if (resp->curr_level == target_level) +return ret; +pr_debug ("SRF: Changing Level for resource %s to %ld\n" , resp->name, target_level); ret = resp->ops->change_level (resp, target_level);
Signature · 1 line
1.7.0.1