diff options
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/nvgpu/vgpu/vgpu.c | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/vgpu/vgpu.c b/drivers/gpu/nvgpu/vgpu/vgpu.c index c28130f2..dc7c4320 100644 --- a/drivers/gpu/nvgpu/vgpu/vgpu.c +++ b/drivers/gpu/nvgpu/vgpu/vgpu.c | |||
@@ -17,6 +17,8 @@ | |||
17 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
18 | #include <linux/dma-mapping.h> | 18 | #include <linux/dma-mapping.h> |
19 | #include <linux/pm_runtime.h> | 19 | #include <linux/pm_runtime.h> |
20 | #include <linux/pm_qos.h> | ||
21 | |||
20 | #include "vgpu/vgpu.h" | 22 | #include "vgpu/vgpu.h" |
21 | #include "vgpu/fecs_trace_vgpu.h" | 23 | #include "vgpu/fecs_trace_vgpu.h" |
22 | #include "gk20a/debug_gk20a.h" | 24 | #include "gk20a/debug_gk20a.h" |
@@ -24,6 +26,7 @@ | |||
24 | #include "gk20a/hw_mc_gk20a.h" | 26 | #include "gk20a/hw_mc_gk20a.h" |
25 | #include "gk20a/ctxsw_trace_gk20a.h" | 27 | #include "gk20a/ctxsw_trace_gk20a.h" |
26 | #include "gk20a/tsg_gk20a.h" | 28 | #include "gk20a/tsg_gk20a.h" |
29 | #include "gk20a/gk20a_scale.h" | ||
27 | #include "gk20a/channel_gk20a.h" | 30 | #include "gk20a/channel_gk20a.h" |
28 | #include "gm20b/hal_gm20b.h" | 31 | #include "gm20b/hal_gm20b.h" |
29 | 32 | ||
@@ -430,6 +433,61 @@ done: | |||
430 | return err; | 433 | return err; |
431 | } | 434 | } |
432 | 435 | ||
436 | static int vgpu_qos_notify(struct notifier_block *nb, | ||
437 | unsigned long n, void *data) | ||
438 | { | ||
439 | struct gk20a_scale_profile *profile = | ||
440 | container_of(nb, struct gk20a_scale_profile, | ||
441 | qos_notify_block); | ||
442 | struct gk20a_platform *platform = gk20a_get_platform(profile->dev); | ||
443 | struct tegra_vgpu_cmd_msg msg = {}; | ||
444 | struct tegra_vgpu_gpu_clk_rate_params *p = &msg.params.gpu_clk_rate; | ||
445 | u32 max_freq; | ||
446 | int err; | ||
447 | |||
448 | gk20a_dbg_fn(""); | ||
449 | |||
450 | max_freq = (u32)pm_qos_read_max_bound(PM_QOS_GPU_FREQ_BOUNDS); | ||
451 | |||
452 | msg.cmd = TEGRA_VGPU_CMD_SET_GPU_CLK_RATE; | ||
453 | msg.handle = platform->virt_handle; | ||
454 | p->rate = max_freq; | ||
455 | err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg)); | ||
456 | err = err ? err : msg.ret; | ||
457 | if (err) | ||
458 | gk20a_err(profile->dev, "%s failed, err=%d", __func__, err); | ||
459 | |||
460 | return NOTIFY_OK; /* need notify call further */ | ||
461 | } | ||
462 | |||
463 | static int vgpu_pm_qos_init(struct device *dev) | ||
464 | { | ||
465 | struct gk20a *g = get_gk20a(dev); | ||
466 | struct gk20a_scale_profile *profile; | ||
467 | |||
468 | profile = kzalloc(sizeof(*profile), GFP_KERNEL); | ||
469 | if (!profile) | ||
470 | return -ENOMEM; | ||
471 | |||
472 | profile->dev = dev; | ||
473 | profile->qos_notify_block.notifier_call = vgpu_qos_notify; | ||
474 | g->scale_profile = profile; | ||
475 | pm_qos_add_max_notifier(PM_QOS_GPU_FREQ_BOUNDS, | ||
476 | &profile->qos_notify_block); | ||
477 | |||
478 | return 0; | ||
479 | } | ||
480 | |||
481 | static void vgpu_pm_qos_remove(struct device *dev) | ||
482 | { | ||
483 | struct gk20a *g = get_gk20a(dev); | ||
484 | |||
485 | pm_qos_remove_max_notifier(PM_QOS_GPU_FREQ_BOUNDS, | ||
486 | &g->scale_profile->qos_notify_block); | ||
487 | kfree(g->scale_profile); | ||
488 | g->scale_profile = NULL; | ||
489 | } | ||
490 | |||
433 | static int vgpu_pm_init(struct device *dev) | 491 | static int vgpu_pm_init(struct device *dev) |
434 | { | 492 | { |
435 | int err = 0; | 493 | int err = 0; |
@@ -437,6 +495,9 @@ static int vgpu_pm_init(struct device *dev) | |||
437 | gk20a_dbg_fn(""); | 495 | gk20a_dbg_fn(""); |
438 | 496 | ||
439 | __pm_runtime_disable(dev, false); | 497 | __pm_runtime_disable(dev, false); |
498 | err = vgpu_pm_qos_init(dev); | ||
499 | if (err) | ||
500 | return err; | ||
440 | 501 | ||
441 | return err; | 502 | return err; |
442 | } | 503 | } |
@@ -534,6 +595,7 @@ int vgpu_remove(struct platform_device *pdev) | |||
534 | struct gk20a *g = get_gk20a(dev); | 595 | struct gk20a *g = get_gk20a(dev); |
535 | gk20a_dbg_fn(""); | 596 | gk20a_dbg_fn(""); |
536 | 597 | ||
598 | vgpu_pm_qos_remove(dev); | ||
537 | if (g->remove_support) | 599 | if (g->remove_support) |
538 | g->remove_support(dev); | 600 | g->remove_support(dev); |
539 | 601 | ||