mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-22 09:12:24 +03:00
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 <ddutta@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/1790002 Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
committed by
mobile promotions
parent
519948a9c6
commit
85c323c3e8
@@ -772,6 +772,11 @@ int nvgpu_clk_arb_init_arbiter(struct gk20a *g)
|
|||||||
return err;
|
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)
|
void nvgpu_clk_arb_send_thermal_alarm(struct gk20a *g)
|
||||||
{
|
{
|
||||||
nvgpu_clk_arb_schedule_alarm(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 *dev = container_of(refcount,
|
||||||
struct nvgpu_clk_dev, refcount);
|
struct nvgpu_clk_dev, refcount);
|
||||||
struct nvgpu_clk_session *session = dev->session;
|
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)
|
void nvgpu_clk_arb_free_session(struct nvgpu_ref *refcount)
|
||||||
|
|||||||
@@ -215,6 +215,9 @@ int gp10b_init_clk_arbiter(struct gk20a *g)
|
|||||||
goto init_fail;
|
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);
|
nvgpu_clk_arb_worker_enqueue(g, &arb->update_arb_work_item);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
@@ -224,6 +227,8 @@ int gp10b_init_clk_arbiter(struct gk20a *g)
|
|||||||
nvgpu_atomic_read(&arb->req_nr) != 0, 0);
|
nvgpu_atomic_read(&arb->req_nr) != 0, 0);
|
||||||
} while (nvgpu_atomic_read(&arb->req_nr) == 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;
|
return arb->status;
|
||||||
|
|
||||||
|
|||||||
@@ -295,6 +295,8 @@ int nvgpu_clk_arb_worker_init(struct gk20a *g);
|
|||||||
|
|
||||||
int nvgpu_clk_arb_init_arbiter(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,
|
int nvgpu_clk_arb_get_arbiter_clk_range(struct gk20a *g, u32 api_domain,
|
||||||
u16 *min_mhz, u16 *max_mhz);
|
u16 *min_mhz, u16 *max_mhz);
|
||||||
|
|
||||||
|
|||||||
@@ -1596,6 +1596,8 @@ struct gk20a {
|
|||||||
|
|
||||||
struct nvgpu_mutex clk_arb_enable_lock;
|
struct nvgpu_mutex clk_arb_enable_lock;
|
||||||
|
|
||||||
|
nvgpu_atomic_t clk_arb_global_nr;
|
||||||
|
|
||||||
struct gk20a_ce_app ce_app;
|
struct gk20a_ce_app ce_app;
|
||||||
|
|
||||||
bool ltc_intr_en_illegal_compstat;
|
bool ltc_intr_en_illegal_compstat;
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include <linux/seq_file.h>
|
#include <linux/seq_file.h>
|
||||||
|
|
||||||
#include <nvgpu/io.h>
|
#include <nvgpu/io.h>
|
||||||
|
#include <nvgpu/clk_arb.h>
|
||||||
|
|
||||||
#include "gm20b/clk_gm20b.h"
|
#include "gm20b/clk_gm20b.h"
|
||||||
#include "os_linux.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)
|
static int rate_set(void *data, u64 val)
|
||||||
{
|
{
|
||||||
struct gk20a *g = (struct gk20a *)data;
|
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);
|
return g->ops.clk.set_rate(g, CTRL_CLK_DOMAIN_GPCCLK, (u32)val);
|
||||||
}
|
}
|
||||||
DEFINE_SIMPLE_ATTRIBUTE(rate_fops, rate_get, rate_set, "%llu\n");
|
DEFINE_SIMPLE_ATTRIBUTE(rate_fops, rate_get, rate_set, "%llu\n");
|
||||||
|
|||||||
@@ -66,6 +66,9 @@ static void nvgpu_init_vars(struct gk20a *g)
|
|||||||
nvgpu_mutex_init(&g->tpc_pg_lock);
|
nvgpu_mutex_init(&g->tpc_pg_lock);
|
||||||
nvgpu_mutex_init(&g->clk_arb_enable_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->regs_saved = l->regs;
|
||||||
l->bar1_saved = l->bar1;
|
l->bar1_saved = l->bar1;
|
||||||
|
|
||||||
|
|||||||
@@ -436,6 +436,7 @@ int nvgpu_clk_arb_commit_request_fd(struct gk20a *g,
|
|||||||
clk_arb_dbg(g, "requested target = %u\n",
|
clk_arb_dbg(g, "requested target = %u\n",
|
||||||
(u32)dev->gpc2clk_target_mhz);
|
(u32)dev->gpc2clk_target_mhz);
|
||||||
|
|
||||||
|
nvgpu_atomic_inc(&g->clk_arb_global_nr);
|
||||||
nvgpu_ref_get(&dev->refcount);
|
nvgpu_ref_get(&dev->refcount);
|
||||||
nvgpu_spinlock_acquire(&session->session_lock);
|
nvgpu_spinlock_acquire(&session->session_lock);
|
||||||
nvgpu_list_add(&dev->node, &session->targets);
|
nvgpu_list_add(&dev->node, &session->targets);
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include <nvgpu/kmem.h>
|
#include <nvgpu/kmem.h>
|
||||||
#include <nvgpu/log.h>
|
#include <nvgpu/log.h>
|
||||||
|
#include <nvgpu/clk_arb.h>
|
||||||
|
|
||||||
#include "gk20a/gk20a.h"
|
#include "gk20a/gk20a.h"
|
||||||
#include "platform_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 rounded_rate;
|
||||||
unsigned long min_freq = 0, max_freq = 0;
|
unsigned long min_freq = 0, max_freq = 0;
|
||||||
|
|
||||||
|
if (nvgpu_clk_arb_has_active_req(g))
|
||||||
|
return 0;
|
||||||
/*
|
/*
|
||||||
* Calculate floor and cap frequency values
|
* Calculate floor and cap frequency values
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -52,6 +52,11 @@ int nvgpu_clk_arb_worker_init(struct gk20a *g)
|
|||||||
return -ENOSYS;
|
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,
|
int nvgpu_clk_arb_get_arbiter_actual_mhz(struct gk20a *g,
|
||||||
u32 api_domain, u16 *actual_mhz)
|
u32 api_domain, u16 *actual_mhz)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user