• Liao Chang's avatar
    cpufreq: Fix the race condition while updating the transition_task of policy · 61bfbf79
    Liao Chang authored
    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@huawei.com/
    Fixes: ca654dc3 ("cpufreq: Catch double invocations of cpufreq_freq_transition_begin/end")
    Signed-off-by: default avatarLiao Chang <liaochang1@huawei.com>
    Acked-by: default avatarViresh Kumar <viresh.kumar@linaro.org>
    Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
    61bfbf79
cpufreq.c 77 KB