Patch "cpufreq: Fix the race condition while updating the transition_task of policy" has been added to the 5.15-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    cpufreq: Fix the race condition while updating the transition_task of policy

to the 5.15-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     cpufreq-fix-the-race-condition-while-updating-the-tr.patch
and it can be found in the queue-5.15 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit a8f85d4e64baa51fe1e36ab70ef58d8a8013f3d8
Author: Liao Chang <liaochang1@xxxxxxxxxx>
Date:   Tue Aug 29 07:03:18 2023 +0000

    cpufreq: Fix the race condition while updating the transition_task of policy
    
    [ Upstream commit 61bfbf7951ba561dcbdd5357702d3cbc2d447812 ]
    
    The field 'transition_task' of policy structure is used to track the
    task which is performing the frequency transition. Using this field to
    print a warning once detect a case where the same task is calling
    _begin() again before completing the preivous frequency transition via
    the _end().
    
    However, there is a potential race condition in _end() and _begin() APIs
    while updating the field 'transition_task' of policy, the scenario is
    depicted below:
    
                 Task A                            Task B
    
            /* 1st freq transition */
            Invoke _begin() {
                    ...
                    ...
            }
                                            /* 2nd freq transition */
                                            Invoke _begin() {
                                                    ... //waiting for A to
                                                    ... //clear
                                                    ... //transition_ongoing
                                                    ... //in _end() for
                                                    ... //the 1st transition
                                                            |
            Change the frequency                            |
                                                            |
            Invoke _end() {                                 |
                    ...                                     |
                    ...                                     |
                    transition_ongoing = false;             V
                                                    transition_ongoing = true;
                                                    transition_task = current;
                    transition_task = NULL;
                    ... //A overwrites the task
                    ... //performing the transition
                    ... //result in error warning.
            }
    
    To fix this race condition, the transition_lock of policy structure is
    now acquired before updating policy structure in _end() API. Which ensure
    that only one task can update the 'transition_task' field at a time.
    
    Link: https://lore.kernel.org/all/b3c61d8a-d52d-3136-fbf0-d1de9f1ba411@xxxxxxxxxx/
    Fixes: ca654dc3a93d ("cpufreq: Catch double invocations of cpufreq_freq_transition_begin/end")
    Signed-off-by: Liao Chang <liaochang1@xxxxxxxxxx>
    Acked-by: Viresh Kumar <viresh.kumar@xxxxxxxxxx>
    Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@xxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index ae7b95e15ac7e..c2227be7bad88 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -450,8 +450,10 @@ void cpufreq_freq_transition_end(struct cpufreq_policy *policy,
 			    policy->cur,
 			    policy->cpuinfo.max_freq);
 
+	spin_lock(&policy->transition_lock);
 	policy->transition_ongoing = false;
 	policy->transition_task = NULL;
+	spin_unlock(&policy->transition_lock);
 
 	wake_up(&policy->transition_wait);
 }



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux