summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDeepak Nibade <dnibade@nvidia.com>2016-06-08 08:22:30 -0400
committerTerje Bergstrom <tbergstrom@nvidia.com>2016-06-27 12:14:04 -0400
commit61d4e27607c0ce4080ef02daeb09200181662337 (patch)
tree3dd3e7428e1d9c5c32c29062f96de4fa1e77d054
parenta445a678bcf480bde01ab784ab050096fd5725eb (diff)
gpu: nvgpu: add QoS notifier for common clk framework
Define specific QoS notifier for common clk framework and protect it with CONFIG_COMMON_CLK This new API will first get min/max requirements from pm_qos and set min/max freq values in devfreq A call to update_devfreq() will then ensure that new estimated frequency is clipped appropriately between min and max values This also ensures that frequency is set along with all the book-keeping Add below platform specific notifier callback and use it with pm_qos_add_notifier() int (*qos_notify)() If qos_notify is set, then only register the callback We currently support only one qos_id which is treated as notifier for min frequency Remove dependency on qos_id, and use appropriate QoS APIs like pm_qos_read_min/max_bound() Store devfreq's min/max frequency in struct gk20a for reference Bug 1772462 Change-Id: I63d6d17451d19c9d376b67df7db775b38929287d Signed-off-by: Deepak Nibade <dnibade@nvidia.com> Reviewed-on: http://git-master/r/1161161 Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com> Tested-by: Terje Bergstrom <tbergstrom@nvidia.com>
-rw-r--r--drivers/gpu/nvgpu/gk20a/gk20a.h2
-rw-r--r--drivers/gpu/nvgpu/gk20a/gk20a_scale.c66
-rw-r--r--drivers/gpu/nvgpu/gk20a/gk20a_scale.h7
-rw-r--r--drivers/gpu/nvgpu/gk20a/platform_gk20a.h9
-rw-r--r--drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c4
5 files changed, 69 insertions, 19 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h
index 997da125..9acaa007 100644
--- a/drivers/gpu/nvgpu/gk20a/gk20a.h
+++ b/drivers/gpu/nvgpu/gk20a/gk20a.h
@@ -815,6 +815,8 @@ struct gk20a {
815 wait_queue_head_t sw_irq_nonstall_last_handled_wq; 815 wait_queue_head_t sw_irq_nonstall_last_handled_wq;
816 816
817 struct devfreq *devfreq; 817 struct devfreq *devfreq;
818 u32 devfreq_max_freq;
819 u32 devfreq_min_freq;
818 820
819 struct gk20a_scale_profile *scale_profile; 821 struct gk20a_scale_profile *scale_profile;
820 822
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a_scale.c b/drivers/gpu/nvgpu/gk20a/gk20a_scale.c
index 6d60d899..eeabd919 100644
--- a/drivers/gpu/nvgpu/gk20a/gk20a_scale.c
+++ b/drivers/gpu/nvgpu/gk20a/gk20a_scale.c
@@ -41,8 +41,44 @@
41 * has changed. The function calls postscaling callback if it is defined. 41 * has changed. The function calls postscaling callback if it is defined.
42 */ 42 */
43 43
44static int gk20a_scale_qos_notify(struct notifier_block *nb, 44#if defined(CONFIG_COMMON_CLK)
45 unsigned long n, void *p) 45int gk20a_scale_qos_notify(struct notifier_block *nb,
46 unsigned long n, void *p)
47{
48 struct gk20a_scale_profile *profile =
49 container_of(nb, struct gk20a_scale_profile,
50 qos_notify_block);
51 struct gk20a *g = get_gk20a(profile->dev);
52 struct devfreq *devfreq = g->devfreq;
53 s32 min_qos_freq, max_qos_freq;
54
55 if (!devfreq)
56 return NOTIFY_OK;
57
58 /* check for pm_qos min and max frequency requirement */
59 min_qos_freq = pm_qos_read_min_bound(PM_QOS_GPU_FREQ_BOUNDS) * 1000;
60 max_qos_freq = pm_qos_read_max_bound(PM_QOS_GPU_FREQ_BOUNDS) * 1000;
61
62 mutex_lock(&devfreq->lock);
63
64 devfreq->min_freq = max_t(u32, g->devfreq_min_freq, min_qos_freq);
65 devfreq->max_freq = min_t(u32, g->devfreq_max_freq, max_qos_freq);
66
67 WARN_ON(devfreq->min_freq > devfreq->max_freq);
68
69 /*
70 * update_devfreq() will adjust the current (or newly estimated)
71 * frequency based on devfreq->min_freq/max_freq
72 */
73 update_devfreq(devfreq);
74
75 mutex_unlock(&devfreq->lock);
76
77 return NOTIFY_OK;
78}
79#else
80int gk20a_scale_qos_notify(struct notifier_block *nb,
81 unsigned long n, void *p)
46{ 82{
47 struct gk20a_scale_profile *profile = 83 struct gk20a_scale_profile *profile =
48 container_of(nb, struct gk20a_scale_profile, 84 container_of(nb, struct gk20a_scale_profile,
@@ -57,7 +93,7 @@ static int gk20a_scale_qos_notify(struct notifier_block *nb,
57 /* get the frequency requirement. if devfreq is enabled, check if it 93 /* get the frequency requirement. if devfreq is enabled, check if it
58 * has higher demand than qos */ 94 * has higher demand than qos */
59 freq = platform->clk_round_rate(profile->dev, 95 freq = platform->clk_round_rate(profile->dev,
60 pm_qos_request(platform->qos_id)); 96 (u32)pm_qos_read_min_bound(PM_QOS_GPU_FREQ_BOUNDS));
61 if (g->devfreq) 97 if (g->devfreq)
62 freq = max(g->devfreq->previous_freq, freq); 98 freq = max(g->devfreq->previous_freq, freq);
63 99
@@ -68,6 +104,7 @@ static int gk20a_scale_qos_notify(struct notifier_block *nb,
68 104
69 return NOTIFY_OK; 105 return NOTIFY_OK;
70} 106}
107#endif
71 108
72/* 109/*
73 * gk20a_scale_make_freq_table(profile) 110 * gk20a_scale_make_freq_table(profile)
@@ -311,16 +348,19 @@ void gk20a_scale_init(struct device *dev)
311 devfreq = NULL; 348 devfreq = NULL;
312 349
313 g->devfreq = devfreq; 350 g->devfreq = devfreq;
351 g->devfreq_max_freq = devfreq->max_freq;
352 g->devfreq_min_freq = devfreq->min_freq;
314 } 353 }
315 354
316 /* Should we register QoS callback for this device? */ 355 /* Should we register QoS callback for this device? */
317 if (platform->qos_id < PM_QOS_NUM_CLASSES && 356 if (platform->qos_notify) {
318 platform->qos_id != PM_QOS_RESERVED &&
319 platform->postscale) {
320 profile->qos_notify_block.notifier_call = 357 profile->qos_notify_block.notifier_call =
321 &gk20a_scale_qos_notify; 358 platform->qos_notify;
322 pm_qos_add_notifier(platform->qos_id, 359
323 &profile->qos_notify_block); 360 pm_qos_add_min_notifier(PM_QOS_GPU_FREQ_BOUNDS,
361 &profile->qos_notify_block);
362 pm_qos_add_max_notifier(PM_QOS_GPU_FREQ_BOUNDS,
363 &profile->qos_notify_block);
324 } 364 }
325 365
326 return; 366 return;
@@ -335,10 +375,10 @@ void gk20a_scale_exit(struct device *dev)
335 struct gk20a *g = platform->g; 375 struct gk20a *g = platform->g;
336 int err; 376 int err;
337 377
338 if (platform->qos_id < PM_QOS_NUM_CLASSES && 378 if (platform->qos_notify) {
339 platform->qos_id != PM_QOS_RESERVED && 379 pm_qos_remove_min_notifier(PM_QOS_GPU_FREQ_BOUNDS,
340 platform->postscale) { 380 &g->scale_profile->qos_notify_block);
341 pm_qos_remove_notifier(platform->qos_id, 381 pm_qos_remove_max_notifier(PM_QOS_GPU_FREQ_BOUNDS,
342 &g->scale_profile->qos_notify_block); 382 &g->scale_profile->qos_notify_block);
343 } 383 }
344 384
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a_scale.h b/drivers/gpu/nvgpu/gk20a/gk20a_scale.h
index 5c8618eb..025c2070 100644
--- a/drivers/gpu/nvgpu/gk20a/gk20a_scale.h
+++ b/drivers/gpu/nvgpu/gk20a/gk20a_scale.h
@@ -47,11 +47,18 @@ void gk20a_scale_notify_idle(struct device *);
47 47
48void gk20a_scale_suspend(struct device *); 48void gk20a_scale_suspend(struct device *);
49void gk20a_scale_resume(struct device *); 49void gk20a_scale_resume(struct device *);
50int gk20a_scale_qos_notify(struct notifier_block *nb,
51 unsigned long n, void *p);
50#else 52#else
51static inline void gk20a_scale_notify_busy(struct device *dev) {} 53static inline void gk20a_scale_notify_busy(struct device *dev) {}
52static inline void gk20a_scale_notify_idle(struct device *dev) {} 54static inline void gk20a_scale_notify_idle(struct device *dev) {}
53static inline void gk20a_scale_suspend(struct device *dev) {} 55static inline void gk20a_scale_suspend(struct device *dev) {}
54static inline void gk20a_scale_resume(struct device *dev) {} 56static inline void gk20a_scale_resume(struct device *dev) {}
57static inline int gk20a_scale_qos_notify(struct notifier_block *nb,
58 unsigned long n, void *p)
59{
60 return -ENOSYS;
61}
55#endif 62#endif
56 63
57#endif 64#endif
diff --git a/drivers/gpu/nvgpu/gk20a/platform_gk20a.h b/drivers/gpu/nvgpu/gk20a/platform_gk20a.h
index 66d97915..a753201b 100644
--- a/drivers/gpu/nvgpu/gk20a/platform_gk20a.h
+++ b/drivers/gpu/nvgpu/gk20a/platform_gk20a.h
@@ -181,10 +181,11 @@ struct gk20a_platform {
181 * this governor to be used in scaling */ 181 * this governor to be used in scaling */
182 const char *devfreq_governor; 182 const char *devfreq_governor;
183 183
184 /* Quality of service id. If this is set, the scaling routines 184 /* Quality of service notifier callback. If this is set, the scaling
185 * will register a callback to id. Each time we receive a new value, 185 * routines will register a callback to Qos. Each time we receive
186 * the postscale callback gets called. */ 186 * a new value, this callback gets called. */
187 int qos_id; 187 int (*qos_notify)(struct notifier_block *nb,
188 unsigned long n, void *p);
188 189
189 /* Called as part of debug dump. If the gpu gets hung, this function 190 /* Called as part of debug dump. If the gpu gets hung, this function
190 * is responsible for delivering all necessary debug data of other 191 * is responsible for delivering all necessary debug data of other
diff --git a/drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c b/drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c
index 618b1716..b8f70ab3 100644
--- a/drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c
+++ b/drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c
@@ -896,7 +896,7 @@ struct gk20a_platform gk20a_tegra_platform = {
896 .prescale = gk20a_tegra_prescale, 896 .prescale = gk20a_tegra_prescale,
897 .postscale = gk20a_tegra_postscale, 897 .postscale = gk20a_tegra_postscale,
898 .devfreq_governor = "nvhost_podgov", 898 .devfreq_governor = "nvhost_podgov",
899 .qos_id = PM_QOS_GPU_FREQ_MIN, 899 .qos_notify = gk20a_scale_qos_notify,
900 900
901 .secure_alloc = gk20a_tegra_secure_alloc, 901 .secure_alloc = gk20a_tegra_secure_alloc,
902 .secure_page_alloc = gk20a_tegra_secure_page_alloc, 902 .secure_page_alloc = gk20a_tegra_secure_page_alloc,
@@ -956,7 +956,7 @@ struct gk20a_platform gm20b_tegra_platform = {
956 .prescale = gk20a_tegra_prescale, 956 .prescale = gk20a_tegra_prescale,
957 .postscale = gk20a_tegra_postscale, 957 .postscale = gk20a_tegra_postscale,
958 .devfreq_governor = "nvhost_podgov", 958 .devfreq_governor = "nvhost_podgov",
959 .qos_id = PM_QOS_GPU_FREQ_MIN, 959 .qos_notify = gk20a_scale_qos_notify,
960 960
961 .secure_alloc = gk20a_tegra_secure_alloc, 961 .secure_alloc = gk20a_tegra_secure_alloc,
962 .secure_page_alloc = gk20a_tegra_secure_page_alloc, 962 .secure_page_alloc = gk20a_tegra_secure_page_alloc,