diff options
| author | Tirupathi Reddy <tirupath@codeaurora.org> | 2017-07-12 14:38:13 +0300 | 
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2017-07-20 15:22:29 +0300 | 
| commit | c9ccaa0cac3fc8e7d17a668aabfdf632c7c0517a (patch) | |
| tree | 18bec2aa296cb39252cfa511a7f0932ce19ae5b0 /tools/perf/scripts/python/stat-cpi.py | |
| parent | 5771a8c08880cdca3bfb4a3fc6d309d6bba20877 (diff) | |
| download | linux-c9ccaa0cac3fc8e7d17a668aabfdf632c7c0517a.tar.xz | |
regulator: core: fix a possible race in disable_work handling
A race condition between queueing and processing the disable_work
instances results in having a work instance in the queue and the
deferred_disables variable of regulator device structure having a
value '0'. If no new regulator_disable_deferred() call later from
clients, the deferred_disables variable value remains '0' and hits
BUG() in regulator_disable_work() when the queued instance scheduled
for processing the work.
The race occurs as below:
	Core-0					     Core-1
	.....	       /* deferred_disables = 2 */   .....
	.....	       /* disable_work is queued */  .....
	.....					     .....
regulator_disable_deferred: 		regulator_disable_work:
   mutex_lock(&rdev->mutex);			     .....
   rdev->deferred_disables++;		             .....
   mutex_unlock(&rdev->mutex);			     .....
   queue_delayed_work(...)		    mutex_lock(&rdev->mutex);
	.....				    count =rdev->deferred_disables;
	.....				    rdev->deferred_disables = 0;
	.....					     .....
	.....				    mutex_unlock(&rdev->mutex);
	.....					     .....
	.....				    return;
	.....					     .....
	/* No new regulator_disable_deferred() calls from clients */
	/* The newly queued instance is scheduled for processing */
	.....					     .....
regulator_disable_work:
	.....
   mutex_lock(&rdev->mutex);
   BUG_ON(!rdev->deferred_disables); /* deferred_disables = 0 */
The race is fixed by removing the work instance that is queued while
processing the previous queued instance. Cancel the newly queued instance
from disable_work() handler just after reset the deferred_disables variable
to value '0'. Also move the work queueing step before mutex_unlock in
regulator_disable_deferred().
Also use mod_delayed_work() in the pace of queue_delayed_work() as
queue_delayed_work() always uses the delay requested in the first call
when multiple consumers call regulator_disable_deferred() close in time
and does not guarantee the semantics of regulator_disable_deferred().
Signed-off-by: Tirupathi Reddy <tirupath@codeaurora.org>
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'tools/perf/scripts/python/stat-cpi.py')
0 files changed, 0 insertions, 0 deletions
