Files
linux-nv-oot/drivers/gpu/host1x/actmon.c
Jon Hunter 620319b7c8 gpu: host1x: Remove unused variable
Building the host1x driver generates the following warning ...

 drivers/gpu/host1x/actmon.c:334:16:
 warning: unused variable ‘err’ [-Wunused-variable]
  334 |         int i, err;
      |                ^~~

Fix this by removing the unused variable.

Bug 4190030

Change-Id: I1c026253793a850bc2ac0d7778029407cc79f162
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/2934694
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
Reviewed-by: svc-mobile-cert <svc-mobile-cert@nvidia.com>
Reviewed-by: Johnny Liu <johnliu@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
2023-07-12 19:11:43 -07:00

571 lines
16 KiB
C

// SPDX-License-Identifier: GPL-2.0-only
/*
* Tegra host1x activity monitor interfaces
*
* Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*/
#include <linux/clk.h>
#include <linux/debugfs.h>
#include <linux/fs.h>
#include <linux/host1x-next.h>
#include "dev.h"
#include "actmon.h"
#include "hw/actmon.h"
static void actmon_writel(struct host1x_actmon *actmon, u32 val, u32 offset)
{
writel(val, actmon->regs+offset);
}
static u32 actmon_readl(struct host1x_actmon *actmon, u32 offset)
{
return readl(actmon->regs+offset);
}
static void actmon_module_writel(struct host1x_actmon_module *module, u32 val, u32 offset)
{
writel(val, module->regs+offset);
}
static u32 actmon_module_readl(struct host1x_actmon_module *module, u32 offset)
{
return readl(module->regs+offset);
}
static void host1x_actmon_update_sample_period(struct host1x_actmon *actmon)
{
unsigned long actmon_mhz;
u32 actmon_clks_per_sample, sample_period, val = 0;
actmon_mhz = actmon->rate / 1000000;
actmon_clks_per_sample = actmon_mhz * actmon->usecs_per_sample;
val |= HOST1X_ACTMON_CTRL_SOURCE(2);
if (actmon_clks_per_sample > 65536) {
val |= HOST1X_ACTMON_CTRL_SAMPLE_TICK(1);
sample_period = actmon_clks_per_sample / 65536;
} else {
val &= ~HOST1X_ACTMON_CTRL_SAMPLE_TICK(1);
sample_period = actmon_clks_per_sample / 256;
}
val &= ~HOST1X_ACTMON_CTRL_SAMPLE_PERIOD_MASK;
val |= HOST1X_ACTMON_CTRL_SAMPLE_PERIOD(sample_period);
actmon_writel(actmon, val, HOST1X_ACTMON_CTRL_REG);
}
static int host1x_actmon_sample_period_get(void *data, u64 *val)
{
struct host1x_actmon *actmon = (struct host1x_actmon *)data;
*val = (u64) actmon->usecs_per_sample;
return 0;
}
static int host1x_actmon_sample_period_set(void *data, u64 val)
{
struct host1x_actmon *actmon = (struct host1x_actmon *)data;
actmon->usecs_per_sample = (u32)val;
host1x_actmon_update_sample_period(actmon);
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(host1x_actmon_sample_period_fops,
host1x_actmon_sample_period_get,
host1x_actmon_sample_period_set,
"%lld\n");
static void host1x_actmon_debug_init(struct host1x_actmon *actmon, const char *name)
{
struct host1x *host = dev_get_drvdata(actmon->client->host->parent);
struct dentry *debugfs = host->actmon_debugfs;
if (!debugfs)
return;
actmon->debugfs = debugfs_create_dir(name, debugfs);
/* R/W files */
debugfs_create_file("sample_period", 0644, actmon->debugfs, actmon,
&host1x_actmon_sample_period_fops);
}
static int host1x_actmon_module_k_get(void *data, u64 *val)
{
struct host1x_actmon_module *module = (struct host1x_actmon_module *)data;
*val = (u64) module->k;
return 0;
}
static int host1x_actmon_module_k_set(void *data, u64 val)
{
struct host1x_actmon_module *module = (struct host1x_actmon_module *)data;
u32 val32;
module->k = (u32)val;
val32 = actmon_module_readl(module, HOST1X_ACTMON_MODULE_CTRL_REG);
val32 &= ~HOST1X_ACTMON_MODULE_CTRL_K_VAL_MASK;
val32 |= HOST1X_ACTMON_MODULE_CTRL_K_VAL(module->k);
actmon_module_writel(module, val32, HOST1X_ACTMON_MODULE_CTRL_REG);
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(host1x_actmon_module_k_fops,
host1x_actmon_module_k_get,
host1x_actmon_module_k_set,
"%lld\n");
static int host1x_actmon_module_consec_upper_num_get(void *data, u64 *val)
{
struct host1x_actmon_module *module = (struct host1x_actmon_module *)data;
*val = (u64) module->consec_upper_num;
return 0;
}
static int host1x_actmon_module_consec_upper_num_set(void *data, u64 val)
{
struct host1x_actmon_module *module = (struct host1x_actmon_module *)data;
u32 val32;
module->consec_upper_num = (u32)val;
val32 = actmon_module_readl(module, HOST1X_ACTMON_MODULE_CTRL_REG);
val32 &= ~HOST1X_ACTMON_MODULE_CTRL_CONSEC_UPPER_NUM_MASK;
val32 |= HOST1X_ACTMON_MODULE_CTRL_CONSEC_UPPER_NUM(module->consec_upper_num);
actmon_module_writel(module, val32, HOST1X_ACTMON_MODULE_CTRL_REG);
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(host1x_actmon_module_consec_upper_num_fops,
host1x_actmon_module_consec_upper_num_get,
host1x_actmon_module_consec_upper_num_set,
"%lld\n");
static int host1x_actmon_module_consec_lower_num_get(void *data, u64 *val)
{
struct host1x_actmon_module *module = (struct host1x_actmon_module *)data;
*val = (u64) module->consec_lower_num;
return 0;
}
static int host1x_actmon_module_consec_lower_num_set(void *data, u64 val)
{
struct host1x_actmon_module *module = (struct host1x_actmon_module *)data;
u32 val32;
module->consec_lower_num = (u32)val;
val32 = actmon_module_readl(module, HOST1X_ACTMON_MODULE_CTRL_REG);
val32 &= ~HOST1X_ACTMON_MODULE_CTRL_CONSEC_LOWER_NUM_MASK;
val32 |= HOST1X_ACTMON_MODULE_CTRL_CONSEC_LOWER_NUM(module->consec_lower_num);
actmon_module_writel(module, val32, HOST1X_ACTMON_MODULE_CTRL_REG);
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(host1x_actmon_module_consec_lower_num_fops,
host1x_actmon_module_consec_lower_num_get,
host1x_actmon_module_consec_lower_num_set,
"%lld\n");
static int host1x_actmon_module_avg_norm_get(void *data, u64 *val)
{
struct host1x_actmon_module *module = (struct host1x_actmon_module *)data;
struct host1x_actmon *actmon = module->actmon;
struct host1x_client *client = actmon->client;
unsigned long client_freq;
u32 active_clks, client_clks;
active_clks = actmon_module_readl(module, HOST1X_ACTMON_MODULE_AVG_COUNT_REG);
client_freq = client->ops->get_rate(client);
client_clks = ((client_freq / 1000) * actmon->usecs_per_sample) / 1000;
*val = (u64) (active_clks * 1000) / client_clks;
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(host1x_actmon_module_avg_norm_fops,
host1x_actmon_module_avg_norm_get, NULL,
"%lld\n");
static void host1x_actmon_module_debug_init(struct host1x_actmon_module *module)
{
struct dentry *debugfs = module->actmon->debugfs;
char dirname[8];
if (!debugfs)
return;
snprintf(dirname, sizeof(dirname), "module%d", module->type);
module->debugfs = debugfs_create_dir(dirname, debugfs);
/* R/W files */
debugfs_create_file("k", 0644, module->debugfs, module,
&host1x_actmon_module_k_fops);
debugfs_create_file("consec_upper_num", 0644, module->debugfs, module,
&host1x_actmon_module_consec_upper_num_fops);
debugfs_create_file("consec_lower_num", 0644, module->debugfs, module,
&host1x_actmon_module_consec_lower_num_fops);
/* R files */
debugfs_create_file("usage", 0444, module->debugfs, module,
&host1x_actmon_module_avg_norm_fops);
}
static void host1x_actmon_init(struct host1x_actmon *actmon)
{
u32 val;
/* Global control register */
host1x_actmon_update_sample_period(actmon);
/* Global interrupt enable register */
val = (1 << actmon->num_modules) - 1;
actmon_writel(actmon, val, HOST1X_ACTMON_INTR_ENB_REG);
}
static void host1x_actmon_deinit(struct host1x_actmon *actmon)
{
actmon_writel(actmon, 0, HOST1X_ACTMON_CTRL_REG);
actmon_writel(actmon, 0, HOST1X_ACTMON_INTR_ENB_REG);
}
static void host1x_actmon_module_init(struct host1x_actmon_module *module)
{
/* Local control register */
actmon_module_writel(module,
HOST1X_ACTMON_MODULE_CTRL_ACTMON_ENB(0) |
HOST1X_ACTMON_MODULE_CTRL_ENB_PERIODIC(1) |
HOST1X_ACTMON_MODULE_CTRL_K_VAL(module->k) |
HOST1X_ACTMON_MODULE_CTRL_CONSEC_UPPER_NUM(module->consec_upper_num) |
HOST1X_ACTMON_MODULE_CTRL_CONSEC_LOWER_NUM(module->consec_lower_num),
HOST1X_ACTMON_MODULE_CTRL_REG);
/* Interrupt enable register (disable interrupts by default) */
actmon_module_writel(module, 0, HOST1X_ACTMON_MODULE_INTR_ENB_REG);
/* Interrupt status register */
actmon_module_writel(module, ~0, HOST1X_ACTMON_MODULE_INTR_STATUS_REG);
/* Consecutive watermark registers */
actmon_module_writel(module, ~0, HOST1X_ACTMON_MODULE_UPPER_WMARK_REG);
actmon_module_writel(module, 0, HOST1X_ACTMON_MODULE_LOWER_WMARK_REG);
/* Moving-average watermark registers */
actmon_module_writel(module, ~0, HOST1X_ACTMON_MODULE_AVG_UPPER_WMARK_REG);
actmon_module_writel(module, 0, HOST1X_ACTMON_MODULE_AVG_LOWER_WMARK_REG);
/* Init average value register */
actmon_module_writel(module, 0, HOST1X_ACTMON_MODULE_INIT_AVG_REG);
}
static void host1x_actmon_module_deinit(struct host1x_actmon_module *module)
{
actmon_module_writel(module, 0, HOST1X_ACTMON_MODULE_CTRL_REG);
actmon_module_writel(module, 0, HOST1X_ACTMON_MODULE_INTR_ENB_REG);
actmon_module_writel(module, ~0, HOST1X_ACTMON_MODULE_INTR_STATUS_REG);
actmon_module_writel(module, 0, HOST1X_ACTMON_MODULE_UPPER_WMARK_REG);
actmon_module_writel(module, 0, HOST1X_ACTMON_MODULE_LOWER_WMARK_REG);
actmon_module_writel(module, 0, HOST1X_ACTMON_MODULE_AVG_UPPER_WMARK_REG);
actmon_module_writel(module, 0, HOST1X_ACTMON_MODULE_AVG_LOWER_WMARK_REG);
actmon_module_writel(module, 0, HOST1X_ACTMON_MODULE_INIT_AVG_REG);
actmon_module_writel(module, 0, HOST1X_ACTMON_MODULE_COUNT_WEIGHT_REG);
}
void host1x_actmon_handle_interrupt(struct host1x *host, int classid)
{
unsigned long actmon_status, module_status;
struct host1x_actmon_module *module;
struct host1x_actmon *actmon;
struct host1x_client *client;
list_for_each_entry(actmon, &host->actmons, list) {
if (actmon->client->class == classid)
break;
}
client = actmon->client;
module = &actmon->modules[HOST1X_ACTMON_MODULE_ACTIVE];
actmon_status = actmon_readl(actmon, HOST1X_ACTMON_INTR_STATUS_REG);
module_status = actmon_module_readl(module, HOST1X_ACTMON_MODULE_INTR_STATUS_REG);
/* Trigger DFS if client supports it */
if (!client->ops->actmon_event)
;
else if (module_status & HOST1X_ACTMON_MODULE_INTR_CONSEC_WMARK_ABOVE)
client->ops->actmon_event(client, HOST1X_ACTMON_CONSEC_WMARK_ABOVE);
else if (module_status & HOST1X_ACTMON_MODULE_INTR_CONSEC_WMARK_BELOW)
client->ops->actmon_event(client, HOST1X_ACTMON_CONSEC_WMARK_BELOW);
else if (module_status & HOST1X_ACTMON_MODULE_INTR_AVG_WMARK_ABOVE)
client->ops->actmon_event(client, HOST1X_ACTMON_AVG_WMARK_ABOVE);
else if (module_status & HOST1X_ACTMON_MODULE_INTR_AVG_WMARK_BELOW)
client->ops->actmon_event(client, HOST1X_ACTMON_AVG_WMARK_BELOW);
actmon_module_writel(module, module_status, HOST1X_ACTMON_MODULE_INTR_STATUS_REG);
actmon_writel(actmon, actmon_status, HOST1X_ACTMON_INTR_STATUS_REG);
}
int host1x_actmon_register(struct host1x_client *client)
{
struct host1x *host = dev_get_drvdata(client->host->parent);
const struct host1x_info *info = host->info;
const struct host1x_actmon_entry *entry = NULL;
struct host1x_actmon_module *module;
struct host1x_actmon *actmon;
unsigned long flags;
int i;
if (!host->actmon_regs || !host->actmon_clk)
return -ENODEV;
for (i = 0; i < info->num_actmon_entries; i++) {
if (info->actmon_table[i].classid == client->class)
entry = &info->actmon_table[i];
}
if (!entry)
return -ENODEV;
actmon = devm_kzalloc(client->dev, sizeof(*actmon), GFP_KERNEL);
if (!actmon)
return -ENOMEM;
INIT_LIST_HEAD(&actmon->list);
spin_lock_irqsave(&host->actmons_lock, flags);
list_add_tail(&actmon->list, &host->actmons);
spin_unlock_irqrestore(&host->actmons_lock, flags);
actmon->client = client;
actmon->rate = clk_get_rate(host->actmon_clk);
actmon->regs = host->actmon_regs + entry->offset;
actmon->irq = entry->irq;
actmon->num_modules = entry->num_modules;
actmon->usecs_per_sample = 1500;
/* Configure actmon registers */
host1x_actmon_init(actmon);
/* Create debugfs for the actmon */
host1x_actmon_debug_init(actmon, entry->name);
/* Configure actmon module registers */
for (i = 0; i < actmon->num_modules; i++) {
module = &actmon->modules[i];
module->actmon = actmon;
module->type = i;
module->regs = actmon->regs + (i * HOST1X_ACTMON_MODULE_OFFSET);
module->k = 6;
module->consec_upper_num = 7;
module->consec_lower_num = 7;
host1x_actmon_module_init(module);
/* Create debugfs for the actmon module */
host1x_actmon_module_debug_init(module);
}
client->actmon = actmon;
return 0;
}
EXPORT_SYMBOL(host1x_actmon_register);
int host1x_actmon_unregister(struct host1x_client *client)
{
struct host1x_actmon_module *module;
struct host1x *host = dev_get_drvdata(client->host->parent);
struct host1x_actmon *actmon = client->actmon;
unsigned long flags;
int i;
if (!host->actmon_regs || !host->actmon_clk)
return 0;
if (!actmon)
return 0;
for (i = 0; i < actmon->num_modules; i++) {
module = &actmon->modules[i];
host1x_actmon_module_deinit(module);
debugfs_remove_recursive(module->debugfs);
}
debugfs_remove_recursive(actmon->debugfs);
host1x_actmon_deinit(actmon);
spin_lock_irqsave(&host->actmons_lock, flags);
list_del(&actmon->list);
spin_unlock_irqrestore(&host->actmons_lock, flags);
return 0;
}
EXPORT_SYMBOL(host1x_actmon_unregister);
void host1x_actmon_enable(struct host1x_client *client)
{
struct host1x_actmon *actmon = client->actmon;
struct host1x_actmon_module *module;
int i;
if (!actmon)
return;
for (i = 0; i < actmon->num_modules; i++) {
module = &actmon->modules[i];
actmon_module_writel(module,
actmon_module_readl(module, HOST1X_ACTMON_MODULE_CTRL_REG) |
HOST1X_ACTMON_MODULE_CTRL_ACTMON_ENB(1),
HOST1X_ACTMON_MODULE_CTRL_REG);
}
}
EXPORT_SYMBOL(host1x_actmon_enable);
void host1x_actmon_disable(struct host1x_client *client)
{
struct host1x_actmon *actmon = client->actmon;
struct host1x_actmon_module *module;
int i;
if (!actmon)
return;
for (i = 0; i < actmon->num_modules; i++) {
module = &actmon->modules[i];
actmon_module_writel(module,
actmon_module_readl(module, HOST1X_ACTMON_MODULE_CTRL_REG) &
~HOST1X_ACTMON_MODULE_CTRL_ACTMON_ENB(1),
HOST1X_ACTMON_MODULE_CTRL_REG);
}
}
EXPORT_SYMBOL(host1x_actmon_disable);
void host1x_actmon_update_client_rate(struct host1x_client *client,
unsigned long rate,
u32 *weight)
{
struct host1x_actmon *actmon = client->actmon;
struct host1x_actmon_module *module;
u32 val;
int i;
if (!actmon) {
*weight = 0;
return;
}
val = (rate / actmon->rate) << 2;
for (i = 0; i < actmon->num_modules; i++) {
module = &actmon->modules[i];
actmon_module_writel(module, val, HOST1X_ACTMON_MODULE_COUNT_WEIGHT_REG);
}
*weight = val;
}
EXPORT_SYMBOL(host1x_actmon_update_client_rate);
void host1x_actmon_read_active_norm(struct host1x_client *client, unsigned long *usage)
{
struct host1x_actmon *actmon = client->actmon;
struct host1x_actmon_module *module;
u64 val;
if (!actmon || !actmon->num_modules) {
*usage = 0;
return;
}
module = &actmon->modules[HOST1X_ACTMON_MODULE_ACTIVE];
host1x_actmon_module_avg_norm_get(module, &val);
*usage = (unsigned long)val;
}
EXPORT_SYMBOL(host1x_actmon_read_active_norm);
int host1x_actmon_read_avg_count(struct host1x_client *client)
{
struct host1x *host = dev_get_drvdata(client->host->parent);
unsigned int offset;
if (!host->actmon_regs)
return -ENODEV;
/* FIXME: Only T234 supported */
switch (client->class) {
case HOST1X_CLASS_NVENC:
offset = 0x0;
break;
case HOST1X_CLASS_VIC:
offset = 0x10000;
break;
case HOST1X_CLASS_NVDEC:
offset = 0x20000;
break;
default:
return -EINVAL;
}
return readl(host->actmon_regs + offset + 0xa4);
}
EXPORT_SYMBOL(host1x_actmon_read_avg_count);
void host1x_actmon_update_active_wmark(struct host1x_client *client,
u32 avg_upper_wmark,
u32 avg_lower_wmark,
u32 consec_upper_wmark,
u32 consec_lower_wmark,
bool upper_wmark_enabled,
bool lower_wmark_enabled)
{
struct host1x_actmon *actmon = client->actmon;
struct host1x_actmon_module *module;
u32 val = 0;
if (!actmon || !actmon->num_modules)
return;
module = &actmon->modules[HOST1X_ACTMON_MODULE_ACTIVE];
/* Update watermark thresholds */
actmon_module_writel(module,
avg_upper_wmark / 1000 * actmon->usecs_per_sample / 1000,
HOST1X_ACTMON_MODULE_AVG_UPPER_WMARK_REG);
actmon_module_writel(module,
avg_lower_wmark / 1000 * actmon->usecs_per_sample / 1000,
HOST1X_ACTMON_MODULE_AVG_LOWER_WMARK_REG);
actmon_module_writel(module,
consec_upper_wmark / 1000 * actmon->usecs_per_sample / 1000,
HOST1X_ACTMON_MODULE_UPPER_WMARK_REG);
actmon_module_writel(module,
consec_lower_wmark / 1000 * actmon->usecs_per_sample / 1000,
HOST1X_ACTMON_MODULE_LOWER_WMARK_REG);
/* Update watermark interrupt enable bits */
val |= HOST1X_ACTMON_MODULE_INTR_AVG_WMARK_ABOVE_ENB(upper_wmark_enabled);
val |= HOST1X_ACTMON_MODULE_INTR_AVG_WMARK_BELOW_ENB(lower_wmark_enabled);
val |= HOST1X_ACTMON_MODULE_INTR_CONSEC_WMARK_ABOVE_ENB(upper_wmark_enabled);
val |= HOST1X_ACTMON_MODULE_INTR_CONSEC_WMARK_BELOW_ENB(lower_wmark_enabled);
actmon_module_writel(module, val, HOST1X_ACTMON_MODULE_INTR_ENB_REG);
}
EXPORT_SYMBOL(host1x_actmon_update_active_wmark);