Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2013 Red Hat
0004  * Author: Rob Clark <robdclark@gmail.com>
0005  */
0006 
0007 #include "msm_gpu.h"
0008 #include "msm_gpu_trace.h"
0009 
0010 #include <linux/devfreq.h>
0011 #include <linux/devfreq_cooling.h>
0012 #include <linux/math64.h>
0013 #include <linux/units.h>
0014 
0015 /*
0016  * Power Management:
0017  */
0018 
0019 static int msm_devfreq_target(struct device *dev, unsigned long *freq,
0020         u32 flags)
0021 {
0022     struct msm_gpu *gpu = dev_to_gpu(dev);
0023     struct msm_gpu_devfreq *df = &gpu->devfreq;
0024     struct dev_pm_opp *opp;
0025 
0026     /*
0027      * Note that devfreq_recommended_opp() can modify the freq
0028      * to something that actually is in the opp table:
0029      */
0030     opp = devfreq_recommended_opp(dev, freq, flags);
0031     if (IS_ERR(opp))
0032         return PTR_ERR(opp);
0033 
0034     trace_msm_gpu_freq_change(dev_pm_opp_get_freq(opp));
0035 
0036     if (gpu->funcs->gpu_set_freq) {
0037         mutex_lock(&df->lock);
0038         gpu->funcs->gpu_set_freq(gpu, opp, df->suspended);
0039         mutex_unlock(&df->lock);
0040     } else {
0041         clk_set_rate(gpu->core_clk, *freq);
0042     }
0043 
0044     dev_pm_opp_put(opp);
0045 
0046     return 0;
0047 }
0048 
0049 static unsigned long get_freq(struct msm_gpu *gpu)
0050 {
0051     if (gpu->funcs->gpu_get_freq)
0052         return gpu->funcs->gpu_get_freq(gpu);
0053 
0054     return clk_get_rate(gpu->core_clk);
0055 }
0056 
0057 static void get_raw_dev_status(struct msm_gpu *gpu,
0058         struct devfreq_dev_status *status)
0059 {
0060     struct msm_gpu_devfreq *df = &gpu->devfreq;
0061     u64 busy_cycles, busy_time;
0062     unsigned long sample_rate;
0063     ktime_t time;
0064 
0065     mutex_lock(&df->lock);
0066 
0067     status->current_frequency = get_freq(gpu);
0068     time = ktime_get();
0069     status->total_time = ktime_us_delta(time, df->time);
0070     df->time = time;
0071 
0072     if (df->suspended) {
0073         mutex_unlock(&df->lock);
0074         status->busy_time = 0;
0075         return;
0076     }
0077 
0078     busy_cycles = gpu->funcs->gpu_busy(gpu, &sample_rate);
0079     busy_time = busy_cycles - df->busy_cycles;
0080     df->busy_cycles = busy_cycles;
0081 
0082     mutex_unlock(&df->lock);
0083 
0084     busy_time *= USEC_PER_SEC;
0085     busy_time = div64_ul(busy_time, sample_rate);
0086     if (WARN_ON(busy_time > ~0LU))
0087         busy_time = ~0LU;
0088 
0089     status->busy_time = busy_time;
0090 }
0091 
0092 static void update_average_dev_status(struct msm_gpu *gpu,
0093         const struct devfreq_dev_status *raw)
0094 {
0095     struct msm_gpu_devfreq *df = &gpu->devfreq;
0096     const u32 polling_ms = df->devfreq->profile->polling_ms;
0097     const u32 max_history_ms = polling_ms * 11 / 10;
0098     struct devfreq_dev_status *avg = &df->average_status;
0099     u64 avg_freq;
0100 
0101     /* simple_ondemand governor interacts poorly with gpu->clamp_to_idle.
0102      * When we enforce the constraint on idle, it calls get_dev_status
0103      * which would normally reset the stats.  When we remove the
0104      * constraint on active, it calls get_dev_status again where busy_time
0105      * would be 0.
0106      *
0107      * To remedy this, we always return the average load over the past
0108      * polling_ms.
0109      */
0110 
0111     /* raw is longer than polling_ms or avg has no history */
0112     if (div_u64(raw->total_time, USEC_PER_MSEC) >= polling_ms ||
0113         !avg->total_time) {
0114         *avg = *raw;
0115         return;
0116     }
0117 
0118     /* Truncate the oldest history first.
0119      *
0120      * Because we keep the history with a single devfreq_dev_status,
0121      * rather than a list of devfreq_dev_status, we have to assume freq
0122      * and load are the same over avg->total_time.  We can scale down
0123      * avg->busy_time and avg->total_time by the same factor to drop
0124      * history.
0125      */
0126     if (div_u64(avg->total_time + raw->total_time, USEC_PER_MSEC) >=
0127             max_history_ms) {
0128         const u32 new_total_time = polling_ms * USEC_PER_MSEC -
0129             raw->total_time;
0130         avg->busy_time = div_u64(
0131                 mul_u32_u32(avg->busy_time, new_total_time),
0132                 avg->total_time);
0133         avg->total_time = new_total_time;
0134     }
0135 
0136     /* compute the average freq over avg->total_time + raw->total_time */
0137     avg_freq = mul_u32_u32(avg->current_frequency, avg->total_time);
0138     avg_freq += mul_u32_u32(raw->current_frequency, raw->total_time);
0139     do_div(avg_freq, avg->total_time + raw->total_time);
0140 
0141     avg->current_frequency = avg_freq;
0142     avg->busy_time += raw->busy_time;
0143     avg->total_time += raw->total_time;
0144 }
0145 
0146 static int msm_devfreq_get_dev_status(struct device *dev,
0147         struct devfreq_dev_status *status)
0148 {
0149     struct msm_gpu *gpu = dev_to_gpu(dev);
0150     struct devfreq_dev_status raw;
0151 
0152     get_raw_dev_status(gpu, &raw);
0153     update_average_dev_status(gpu, &raw);
0154     *status = gpu->devfreq.average_status;
0155 
0156     return 0;
0157 }
0158 
0159 static int msm_devfreq_get_cur_freq(struct device *dev, unsigned long *freq)
0160 {
0161     *freq = get_freq(dev_to_gpu(dev));
0162 
0163     return 0;
0164 }
0165 
0166 static struct devfreq_dev_profile msm_devfreq_profile = {
0167     .timer = DEVFREQ_TIMER_DELAYED,
0168     .polling_ms = 50,
0169     .target = msm_devfreq_target,
0170     .get_dev_status = msm_devfreq_get_dev_status,
0171     .get_cur_freq = msm_devfreq_get_cur_freq,
0172 };
0173 
0174 static void msm_devfreq_boost_work(struct kthread_work *work);
0175 static void msm_devfreq_idle_work(struct kthread_work *work);
0176 
0177 static bool has_devfreq(struct msm_gpu *gpu)
0178 {
0179     struct msm_gpu_devfreq *df = &gpu->devfreq;
0180     return !!df->devfreq;
0181 }
0182 
0183 void msm_devfreq_init(struct msm_gpu *gpu)
0184 {
0185     struct msm_gpu_devfreq *df = &gpu->devfreq;
0186 
0187     /* We need target support to do devfreq */
0188     if (!gpu->funcs->gpu_busy)
0189         return;
0190 
0191     mutex_init(&df->lock);
0192 
0193     dev_pm_qos_add_request(&gpu->pdev->dev, &df->idle_freq,
0194                    DEV_PM_QOS_MAX_FREQUENCY,
0195                    PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE);
0196     dev_pm_qos_add_request(&gpu->pdev->dev, &df->boost_freq,
0197                    DEV_PM_QOS_MIN_FREQUENCY, 0);
0198 
0199     msm_devfreq_profile.initial_freq = gpu->fast_rate;
0200 
0201     /*
0202      * Don't set the freq_table or max_state and let devfreq build the table
0203      * from OPP
0204      * After a deferred probe, these may have be left to non-zero values,
0205      * so set them back to zero before creating the devfreq device
0206      */
0207     msm_devfreq_profile.freq_table = NULL;
0208     msm_devfreq_profile.max_state = 0;
0209 
0210     df->devfreq = devm_devfreq_add_device(&gpu->pdev->dev,
0211             &msm_devfreq_profile, DEVFREQ_GOV_SIMPLE_ONDEMAND,
0212             NULL);
0213 
0214     if (IS_ERR(df->devfreq)) {
0215         DRM_DEV_ERROR(&gpu->pdev->dev, "Couldn't initialize GPU devfreq\n");
0216         dev_pm_qos_remove_request(&df->idle_freq);
0217         dev_pm_qos_remove_request(&df->boost_freq);
0218         df->devfreq = NULL;
0219         return;
0220     }
0221 
0222     devfreq_suspend_device(df->devfreq);
0223 
0224     gpu->cooling = of_devfreq_cooling_register(gpu->pdev->dev.of_node, df->devfreq);
0225     if (IS_ERR(gpu->cooling)) {
0226         DRM_DEV_ERROR(&gpu->pdev->dev,
0227                 "Couldn't register GPU cooling device\n");
0228         gpu->cooling = NULL;
0229     }
0230 
0231     msm_hrtimer_work_init(&df->boost_work, gpu->worker, msm_devfreq_boost_work,
0232                   CLOCK_MONOTONIC, HRTIMER_MODE_REL);
0233     msm_hrtimer_work_init(&df->idle_work, gpu->worker, msm_devfreq_idle_work,
0234                   CLOCK_MONOTONIC, HRTIMER_MODE_REL);
0235 }
0236 
0237 static void cancel_idle_work(struct msm_gpu_devfreq *df)
0238 {
0239     hrtimer_cancel(&df->idle_work.timer);
0240     kthread_cancel_work_sync(&df->idle_work.work);
0241 }
0242 
0243 static void cancel_boost_work(struct msm_gpu_devfreq *df)
0244 {
0245     hrtimer_cancel(&df->boost_work.timer);
0246     kthread_cancel_work_sync(&df->boost_work.work);
0247 }
0248 
0249 void msm_devfreq_cleanup(struct msm_gpu *gpu)
0250 {
0251     struct msm_gpu_devfreq *df = &gpu->devfreq;
0252 
0253     if (!has_devfreq(gpu))
0254         return;
0255 
0256     devfreq_cooling_unregister(gpu->cooling);
0257     dev_pm_qos_remove_request(&df->boost_freq);
0258     dev_pm_qos_remove_request(&df->idle_freq);
0259 }
0260 
0261 void msm_devfreq_resume(struct msm_gpu *gpu)
0262 {
0263     struct msm_gpu_devfreq *df = &gpu->devfreq;
0264     unsigned long sample_rate;
0265 
0266     if (!has_devfreq(gpu))
0267         return;
0268 
0269     mutex_lock(&df->lock);
0270     df->busy_cycles = gpu->funcs->gpu_busy(gpu, &sample_rate);
0271     df->time = ktime_get();
0272     df->suspended = false;
0273     mutex_unlock(&df->lock);
0274 
0275     devfreq_resume_device(df->devfreq);
0276 }
0277 
0278 void msm_devfreq_suspend(struct msm_gpu *gpu)
0279 {
0280     struct msm_gpu_devfreq *df = &gpu->devfreq;
0281 
0282     if (!has_devfreq(gpu))
0283         return;
0284 
0285     mutex_lock(&df->lock);
0286     df->suspended = true;
0287     mutex_unlock(&df->lock);
0288 
0289     devfreq_suspend_device(df->devfreq);
0290 
0291     cancel_idle_work(df);
0292     cancel_boost_work(df);
0293 }
0294 
0295 static void msm_devfreq_boost_work(struct kthread_work *work)
0296 {
0297     struct msm_gpu_devfreq *df = container_of(work,
0298             struct msm_gpu_devfreq, boost_work.work);
0299 
0300     dev_pm_qos_update_request(&df->boost_freq, 0);
0301 }
0302 
0303 void msm_devfreq_boost(struct msm_gpu *gpu, unsigned factor)
0304 {
0305     struct msm_gpu_devfreq *df = &gpu->devfreq;
0306     uint64_t freq;
0307 
0308     if (!has_devfreq(gpu))
0309         return;
0310 
0311     freq = get_freq(gpu);
0312     freq *= factor;
0313 
0314     /*
0315      * A nice little trap is that PM QoS operates in terms of KHz,
0316      * while devfreq operates in terms of Hz:
0317      */
0318     do_div(freq, HZ_PER_KHZ);
0319 
0320     dev_pm_qos_update_request(&df->boost_freq, freq);
0321 
0322     msm_hrtimer_queue_work(&df->boost_work,
0323                    ms_to_ktime(msm_devfreq_profile.polling_ms),
0324                    HRTIMER_MODE_REL);
0325 }
0326 
0327 void msm_devfreq_active(struct msm_gpu *gpu)
0328 {
0329     struct msm_gpu_devfreq *df = &gpu->devfreq;
0330     unsigned int idle_time;
0331 
0332     if (!has_devfreq(gpu))
0333         return;
0334 
0335     /*
0336      * Cancel any pending transition to idle frequency:
0337      */
0338     cancel_idle_work(df);
0339 
0340     idle_time = ktime_to_ms(ktime_sub(ktime_get(), df->idle_time));
0341 
0342     /*
0343      * If we've been idle for a significant fraction of a polling
0344      * interval, then we won't meet the threshold of busyness for
0345      * the governor to ramp up the freq.. so give some boost
0346      */
0347     if (idle_time > msm_devfreq_profile.polling_ms) {
0348         msm_devfreq_boost(gpu, 2);
0349     }
0350 
0351     dev_pm_qos_update_request(&df->idle_freq,
0352                   PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE);
0353 }
0354 
0355 
0356 static void msm_devfreq_idle_work(struct kthread_work *work)
0357 {
0358     struct msm_gpu_devfreq *df = container_of(work,
0359             struct msm_gpu_devfreq, idle_work.work);
0360     struct msm_gpu *gpu = container_of(df, struct msm_gpu, devfreq);
0361 
0362     df->idle_time = ktime_get();
0363 
0364     if (gpu->clamp_to_idle)
0365         dev_pm_qos_update_request(&df->idle_freq, 0);
0366 }
0367 
0368 void msm_devfreq_idle(struct msm_gpu *gpu)
0369 {
0370     struct msm_gpu_devfreq *df = &gpu->devfreq;
0371 
0372     if (!has_devfreq(gpu))
0373         return;
0374 
0375     msm_hrtimer_queue_work(&df->idle_work, ms_to_ktime(1),
0376                    HRTIMER_MODE_REL);
0377 }