From 85c323c3e89d6e1b624b839c3325ae072952e545 Mon Sep 17 00:00:00 2001 From: Debarshi Dutta Date: Wed, 8 Aug 2018 17:36:01 +0530 Subject: gpu: nvgpu: restrict devfreq during active clk_arb set requests Restrict access to devfreq when there are active set requests in the clk_arbiter. We make the following changes in the patch. 1) Add a global counter in the struct gk20a named clk_arb_global_nr which is used to track the number of active set requests in the system. 2) Anytime a set request is successfully made by the userspace, clk_arb_global_nr is incremented by 1 and during the completion of request(releasing the corresponding file handle), clk_arb_global_nr is decremented by 1. 3) gk20a_scale_target(invoked by devfreq to set the new frequency based on load) atomically checks clk_arb_global_nr. If the value = 0, the code simply continue or else if its > 0, it quits thus making devfreq requests mutually exclusive with the clk_arbiter. Bug 2061372 Change-Id: I5d19de03e45520f4ff8fccb97b1f1589d04c8ab8 Signed-off-by: Debarshi Dutta Reviewed-on: https://git-master.nvidia.com/r/1790002 Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/gpu/nvgpu/clk/clk_arb.c | 11 +++++++++-- drivers/gpu/nvgpu/gp10b/clk_arb_gp10b.c | 5 +++++ drivers/gpu/nvgpu/include/nvgpu/clk_arb.h | 2 ++ drivers/gpu/nvgpu/include/nvgpu/gk20a.h | 2 ++ drivers/gpu/nvgpu/os/linux/debug_clk_gm20b.c | 3 +++ drivers/gpu/nvgpu/os/linux/driver_common.c | 3 +++ drivers/gpu/nvgpu/os/linux/ioctl_clk_arb.c | 1 + drivers/gpu/nvgpu/os/linux/scale.c | 3 +++ drivers/gpu/nvgpu/os/posix/clk_arb.c | 5 +++++ 9 files changed, 33 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/nvgpu/clk/clk_arb.c b/drivers/gpu/nvgpu/clk/clk_arb.c index 452d9de3..3d97535d 100644 --- a/drivers/gpu/nvgpu/clk/clk_arb.c +++ b/drivers/gpu/nvgpu/clk/clk_arb.c @@ -772,6 +772,11 @@ int nvgpu_clk_arb_init_arbiter(struct gk20a *g) return err; } +bool nvgpu_clk_arb_has_active_req(struct gk20a *g) +{ + return (nvgpu_atomic_read(&g->clk_arb_global_nr) > 0); +} + void nvgpu_clk_arb_send_thermal_alarm(struct gk20a *g) { nvgpu_clk_arb_schedule_alarm(g, @@ -854,10 +859,12 @@ void nvgpu_clk_arb_free_fd(struct nvgpu_ref *refcount) struct nvgpu_clk_dev *dev = container_of(refcount, struct nvgpu_clk_dev, refcount); struct nvgpu_clk_session *session = dev->session; + struct gk20a *g = session->g; - nvgpu_clk_notification_queue_free(session->g, &dev->queue); + nvgpu_clk_notification_queue_free(g, &dev->queue); - nvgpu_kfree(session->g, dev); + nvgpu_atomic_dec(&g->clk_arb_global_nr); + nvgpu_kfree(g, dev); } void nvgpu_clk_arb_free_session(struct nvgpu_ref *refcount) diff --git a/drivers/gpu/nvgpu/gp10b/clk_arb_gp10b.c b/drivers/gpu/nvgpu/gp10b/clk_arb_gp10b.c index 4dcc3ca5..78fb1261 100644 --- a/drivers/gpu/nvgpu/gp10b/clk_arb_gp10b.c +++ b/drivers/gpu/nvgpu/gp10b/clk_arb_gp10b.c @@ -215,6 +215,9 @@ int gp10b_init_clk_arbiter(struct gk20a *g) goto init_fail; } + /* This is set for the duration of the default req */ + nvgpu_atomic_inc(&g->clk_arb_global_nr); + nvgpu_clk_arb_worker_enqueue(g, &arb->update_arb_work_item); do { @@ -224,6 +227,8 @@ int gp10b_init_clk_arbiter(struct gk20a *g) nvgpu_atomic_read(&arb->req_nr) != 0, 0); } while (nvgpu_atomic_read(&arb->req_nr) == 0); + /* Once the default request is completed, reduce the usage count */ + nvgpu_atomic_dec(&g->clk_arb_global_nr); return arb->status; diff --git a/drivers/gpu/nvgpu/include/nvgpu/clk_arb.h b/drivers/gpu/nvgpu/include/nvgpu/clk_arb.h index 81b1df1b..a04e3542 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/clk_arb.h +++ b/drivers/gpu/nvgpu/include/nvgpu/clk_arb.h @@ -295,6 +295,8 @@ int nvgpu_clk_arb_worker_init(struct gk20a *g); int nvgpu_clk_arb_init_arbiter(struct gk20a *g); +bool nvgpu_clk_arb_has_active_req(struct gk20a *g); + int nvgpu_clk_arb_get_arbiter_clk_range(struct gk20a *g, u32 api_domain, u16 *min_mhz, u16 *max_mhz); diff --git a/drivers/gpu/nvgpu/include/nvgpu/gk20a.h b/drivers/gpu/nvgpu/include/nvgpu/gk20a.h index b8ca5754..5f875707 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/gk20a.h +++ b/drivers/gpu/nvgpu/include/nvgpu/gk20a.h @@ -1596,6 +1596,8 @@ struct gk20a { struct nvgpu_mutex clk_arb_enable_lock; + nvgpu_atomic_t clk_arb_global_nr; + struct gk20a_ce_app ce_app; bool ltc_intr_en_illegal_compstat; diff --git a/drivers/gpu/nvgpu/os/linux/debug_clk_gm20b.c b/drivers/gpu/nvgpu/os/linux/debug_clk_gm20b.c index 52eea83f..b8b95fd7 100644 --- a/drivers/gpu/nvgpu/os/linux/debug_clk_gm20b.c +++ b/drivers/gpu/nvgpu/os/linux/debug_clk_gm20b.c @@ -17,6 +17,7 @@ #include #include +#include #include "gm20b/clk_gm20b.h" #include "os_linux.h" @@ -33,6 +34,8 @@ static int rate_get(void *data, u64 *val) static int rate_set(void *data, u64 val) { struct gk20a *g = (struct gk20a *)data; + if (nvgpu_clk_arb_has_active_req(g)) + return 0; return g->ops.clk.set_rate(g, CTRL_CLK_DOMAIN_GPCCLK, (u32)val); } DEFINE_SIMPLE_ATTRIBUTE(rate_fops, rate_get, rate_set, "%llu\n"); diff --git a/drivers/gpu/nvgpu/os/linux/driver_common.c b/drivers/gpu/nvgpu/os/linux/driver_common.c index ebd0b40b..0a25cd3f 100644 --- a/drivers/gpu/nvgpu/os/linux/driver_common.c +++ b/drivers/gpu/nvgpu/os/linux/driver_common.c @@ -66,6 +66,9 @@ static void nvgpu_init_vars(struct gk20a *g) nvgpu_mutex_init(&g->tpc_pg_lock); nvgpu_mutex_init(&g->clk_arb_enable_lock); + /* Init the clock req count to 0 */ + nvgpu_atomic_set(&g->clk_arb_global_nr, 0); + l->regs_saved = l->regs; l->bar1_saved = l->bar1; diff --git a/drivers/gpu/nvgpu/os/linux/ioctl_clk_arb.c b/drivers/gpu/nvgpu/os/linux/ioctl_clk_arb.c index 2d9946b1..ff1cc00a 100644 --- a/drivers/gpu/nvgpu/os/linux/ioctl_clk_arb.c +++ b/drivers/gpu/nvgpu/os/linux/ioctl_clk_arb.c @@ -436,6 +436,7 @@ int nvgpu_clk_arb_commit_request_fd(struct gk20a *g, clk_arb_dbg(g, "requested target = %u\n", (u32)dev->gpc2clk_target_mhz); + nvgpu_atomic_inc(&g->clk_arb_global_nr); nvgpu_ref_get(&dev->refcount); nvgpu_spinlock_acquire(&session->session_lock); nvgpu_list_add(&dev->node, &session->targets); diff --git a/drivers/gpu/nvgpu/os/linux/scale.c b/drivers/gpu/nvgpu/os/linux/scale.c index ecc8207a..cbb9fdc5 100644 --- a/drivers/gpu/nvgpu/os/linux/scale.c +++ b/drivers/gpu/nvgpu/os/linux/scale.c @@ -25,6 +25,7 @@ #include #include +#include #include "gk20a/gk20a.h" #include "platform_gk20a.h" @@ -154,6 +155,8 @@ static int gk20a_scale_target(struct device *dev, unsigned long *freq, unsigned long rounded_rate; unsigned long min_freq = 0, max_freq = 0; + if (nvgpu_clk_arb_has_active_req(g)) + return 0; /* * Calculate floor and cap frequency values * diff --git a/drivers/gpu/nvgpu/os/posix/clk_arb.c b/drivers/gpu/nvgpu/os/posix/clk_arb.c index 63ab0f13..fcba0a26 100644 --- a/drivers/gpu/nvgpu/os/posix/clk_arb.c +++ b/drivers/gpu/nvgpu/os/posix/clk_arb.c @@ -52,6 +52,11 @@ int nvgpu_clk_arb_worker_init(struct gk20a *g) return -ENOSYS; } +bool nvgpu_clk_arb_has_active_req(struct gk20a *g) +{ + return false; +} + int nvgpu_clk_arb_get_arbiter_actual_mhz(struct gk20a *g, u32 api_domain, u16 *actual_mhz) { -- cgit v1.2.2