diff --git a/drivers/gpu/host1x/actmon.c b/drivers/gpu/host1x/actmon.c index 33bac0db..49960fb9 100644 --- a/drivers/gpu/host1x/actmon.c +++ b/drivers/gpu/host1x/actmon.c @@ -1,11 +1,412 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Tegra host1x activity monitor interfaes + * Tegra host1x activity monitor interfaces * - * Copyright (c) 2023, NVIDIA Corporation. + * Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ +#include +#include +#include +#include + #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) +{ + struct host1x *host = dev_get_drvdata(actmon->client->host->parent); + struct dentry *debugfs = host->actmon_debugfs; + + if (!debugfs) + return; + + actmon->debugfs = debugfs_create_dir(actmon->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) +{ + struct host1x_actmon *actmon = module->actmon; + u32 val; + + /* Local control register */ + val = 0; + val |= HOST1X_ACTMON_MODULE_CTRL_ACTMON_ENB(1); + val |= HOST1X_ACTMON_MODULE_CTRL_ENB_PERIODIC(1); + val |= HOST1X_ACTMON_MODULE_CTRL_K_VAL(module->k); + val |= HOST1X_ACTMON_MODULE_CTRL_CONSEC_UPPER_NUM(module->consec_upper_num); + val |= HOST1X_ACTMON_MODULE_CTRL_CONSEC_LOWER_NUM(module->consec_lower_num); + actmon_module_writel(module, val, HOST1X_ACTMON_MODULE_CTRL_REG); + + /* Interrupt enable register */ + val = 0; + val |= HOST1X_ACTMON_MODULE_INTR_AVG_BELOW_WORK_ENB(1); + val |= HOST1X_ACTMON_MODULE_INTR_AVG_ABOVE_WORK_ENB(1); + val |= HOST1X_ACTMON_MODULE_INTR_CONSEC_BELOW_WORK_ENB(1); + val |= HOST1X_ACTMON_MODULE_INTR_CONSEC_ABOVE_WORK_ENB(1); + actmon_module_writel(module, val, HOST1X_ACTMON_MODULE_INTR_ENB_REG); + + /* Interrupt status register */ + actmon_module_writel(module, 0xffffffff, HOST1X_ACTMON_MODULE_INTR_STATUS_REG); + + /* Consecutive watermark registers */ + actmon_module_writel(module, 0xffffffff, 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, 0xffffffff, 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, 0xffffffff, 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); +} + +int host1x_actmon_register(struct host1x_client *client) +{ + struct host1x *host = dev_get_drvdata(client->host->parent); + struct host1x_info *info = host->info; + struct host1x_actmon_entry *entry = NULL; + struct host1x_actmon_module *module; + struct host1x_actmon *actmon; + int i, err; + + 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; + + actmon->client = client; + actmon->rate = clk_get_rate(host->actmon_clk); + actmon->regs = host->actmon_regs + entry->offset; + actmon->irq = entry->irq; + actmon->name = entry->name; + 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); + + /* 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; + 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); + + return 0; +} +EXPORT_SYMBOL(host1x_actmon_unregister); + +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); int host1x_actmon_read_avg_count(struct host1x_client *client) { diff --git a/drivers/gpu/host1x/actmon.h b/drivers/gpu/host1x/actmon.h new file mode 100644 index 00000000..1b3a50aa --- /dev/null +++ b/drivers/gpu/host1x/actmon.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Tegra host1x Actmon + * + * Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + */ + +#ifndef HOST1X_ACTMON_H +#define HOST1X_ACTMON_H + +#include +#include + +enum host1x_actmon_module_type { + HOST1X_ACTMON_MODULE_ACTIVE, + HOST1X_ACTMON_MODULE_STALL, +}; + +struct host1x_actmon; + +struct host1x_actmon_module { + enum host1x_actmon_module_type type; + u32 k; + u32 consec_upper_num; + u32 consec_lower_num; + void __iomem *regs; + struct host1x_actmon *actmon; + struct dentry *debugfs; +}; + +struct host1x_client; + +struct host1x_actmon { + char *name; + unsigned int irq; + unsigned int num_modules; + unsigned long rate; + u32 usecs_per_sample; + void __iomem *regs; + struct host1x_client *client; + struct host1x_actmon_module modules[8]; + struct dentry *debugfs; +}; + +#endif diff --git a/drivers/gpu/host1x/debug.c b/drivers/gpu/host1x/debug.c index b4d6a9e2..ffb6979f 100644 --- a/drivers/gpu/host1x/debug.c +++ b/drivers/gpu/host1x/debug.c @@ -3,7 +3,7 @@ * Copyright (C) 2010 Google, Inc. * Author: Erik Gilling * - * Copyright (C) 2011-2013 NVIDIA Corporation + * Copyright (C) 2011-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ #include @@ -196,6 +196,8 @@ static void host1x_debugfs_init(struct host1x *host1x) /* Store the created entry */ host1x->debugfs = de; + host1x->actmon_debugfs = debugfs_create_dir("actmon", host1x->debugfs); + debugfs_create_file("status", S_IRUGO, de, host1x, &host1x_debug_fops); debugfs_create_file("status_all", S_IRUGO, de, host1x, &host1x_debug_all_fops); diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c index b3f2c5a8..46b2e57b 100644 --- a/drivers/gpu/host1x/dev.c +++ b/drivers/gpu/host1x/dev.c @@ -432,6 +432,44 @@ static const struct host1x_sid_entry tegra234_sid_table[] = { }, }; +static const struct host1x_actmon_entry tegra234_actmon_table[] = { + { + .classid = HOST1X_CLASS_NVENC, + .name = "nvenc", + .irq = 2, + .offset = 0x00000, + .num_modules = 1, + }, + { + .classid = HOST1X_CLASS_VIC, + .name = "vic", + .irq = 3, + .offset = 0x10000, + .num_modules = 1, + }, + { + .classid = HOST1X_CLASS_NVDEC, + .name = "nvdec", + .irq = 4, + .offset = 0x20000, + .num_modules = 1, + }, + { + .classid = HOST1X_CLASS_NVJPG, + .name = "nvjpg", + .irq = 5, + .offset = 0x30000, + .num_modules = 1, + }, + { + .classid = HOST1X_CLASS_NVJPG1, + .name = "nvjpg1", + .irq = 6, + .offset = 0x40000, + .num_modules = 1, + }, +}; + static const struct host1x_info host1x08_info = { .nb_channels = 63, .nb_pts = 1024, @@ -445,6 +483,8 @@ static const struct host1x_info host1x08_info = { .has_common = true, .num_sid_entries = ARRAY_SIZE(tegra234_sid_table), .sid_table = tegra234_sid_table, + .num_actmon_entries = ARRAY_SIZE(tegra234_actmon_table), + .actmon_table = tegra234_actmon_table, .streamid_vm_table = { 0x1004, 128 }, .classid_vm_table = { 0x1404, 25 }, .mmio_vm_table = { 0x1504, 25 }, diff --git a/drivers/gpu/host1x/dev.h b/drivers/gpu/host1x/dev.h index 299e5b3a..d72c5bf3 100644 --- a/drivers/gpu/host1x/dev.h +++ b/drivers/gpu/host1x/dev.h @@ -83,6 +83,14 @@ struct host1x_intr_ops { int (*free_syncpt_irq)(struct host1x *host); }; +struct host1x_actmon_entry { + int classid; + const char *name; + unsigned int irq; + unsigned int offset; + unsigned int num_modules; +}; + struct host1x_sid_entry { unsigned int base; unsigned int offset; @@ -107,6 +115,8 @@ struct host1x_info { bool has_common; /* has common registers separate from hypervisor */ unsigned int num_sid_entries; const struct host1x_sid_entry *sid_table; + unsigned int num_actmon_entries; + const struct host1x_actmon_entry *actmon_table; struct host1x_table_desc streamid_vm_table; struct host1x_table_desc classid_vm_table; struct host1x_table_desc mmio_vm_table; @@ -170,6 +180,7 @@ struct host1x { struct host1x_memory_context_list context_list; struct dentry *debugfs; + struct dentry *actmon_debugfs; struct mutex devices_lock; struct list_head devices; diff --git a/drivers/gpu/host1x/hw/actmon.h b/drivers/gpu/host1x/hw/actmon.h new file mode 100644 index 00000000..23cd627b --- /dev/null +++ b/drivers/gpu/host1x/hw/actmon.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Tegra host1x Actmon Register Offsets + * + * Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + */ + +#ifndef __HOST1X_ACTMON_HARDWARE_H +#define __HOST1X_ACTMON_HARDWARE_H + +#define HOST1X_ACTMON_MODULE_OFFSET 0x80 + +#define HOST1X_ACTMON_CTRL_REG 0x0 +#define HOST1X_ACTMON_INTR_ENB_REG 0x4 +#define HOST1X_ACTMON_MODULE_INIT_AVG_REG 0x14 +#define HOST1X_ACTMON_MODULE_CTRL_REG 0x80 +#define HOST1X_ACTMON_MODULE_INTR_ENB_REG 0x84 +#define HOST1X_ACTMON_MODULE_INTR_STATUS_REG 0x88 +#define HOST1X_ACTMON_MODULE_UPPER_WMARK_REG 0x8c +#define HOST1X_ACTMON_MODULE_LOWER_WMARK_REG 0x90 +#define HOST1X_ACTMON_MODULE_AVG_UPPER_WMARK_REG 0x94 +#define HOST1X_ACTMON_MODULE_AVG_LOWER_WMARK_REG 0x98 +#define HOST1X_ACTMON_MODULE_AVG_COUNT_REG 0xa4 +#define HOST1X_ACTMON_MODULE_COUNT_WEIGHT_REG 0xa8 + +#define HOST1X_ACTMON_CTRL_SOURCE(v) ((v & 0x3) << 8) +#define HOST1X_ACTMON_CTRL_SAMPLE_TICK(v) ((v & 0x1) << 10) +#define HOST1X_ACTMON_CTRL_SAMPLE_PERIOD(v) ((v & 0xff) << 0) +#define HOST1X_ACTMON_MODULE_CTRL_ACTMON_ENB(v) ((v & 0x1) << 31) +#define HOST1X_ACTMON_MODULE_CTRL_CONSEC_UPPER_NUM(v) ((v & 0x7) << 26) +#define HOST1X_ACTMON_MODULE_CTRL_CONSEC_LOWER_NUM(v) ((v & 0x7) << 21) +#define HOST1X_ACTMON_MODULE_CTRL_ENB_PERIODIC(v) ((v & 0x1) << 13) +#define HOST1X_ACTMON_MODULE_CTRL_K_VAL(v) ((v & 0x7) << 10) +#define HOST1X_ACTMON_MODULE_INTR_CONSEC_ABOVE_WORK_ENB(v) ((v & 0x1) << 31) +#define HOST1X_ACTMON_MODULE_INTR_CONSEC_BELOW_WORK_ENB(v) ((v & 0x1) << 30) +#define HOST1X_ACTMON_MODULE_INTR_AVG_ABOVE_WORK_ENB(v) ((v & 0x1) << 29) +#define HOST1X_ACTMON_MODULE_INTR_AVG_BELOW_WORK_ENB(v) ((v & 0x1) << 28) + +#define HOST1X_ACTMON_CTRL_SAMPLE_PERIOD_MASK 0xff +#define HOST1X_ACTMON_MODULE_CTRL_CONSEC_UPPER_NUM_MASK (0x7 << 26) +#define HOST1X_ACTMON_MODULE_CTRL_CONSEC_LOWER_NUM_MASK (0x7 << 21) +#define HOST1X_ACTMON_MODULE_CTRL_K_VAL_MASK (0x7 << 10) + +#endif diff --git a/drivers/gpu/host1x/include/linux/host1x-next.h b/drivers/gpu/host1x/include/linux/host1x-next.h index 0c0134f0..55766f13 100644 --- a/drivers/gpu/host1x/include/linux/host1x-next.h +++ b/drivers/gpu/host1x/include/linux/host1x-next.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* - * Copyright (c) 2009-2013, NVIDIA Corporation. All rights reserved. + * Copyright (c) 2009-2023, NVIDIA Corporation. All rights reserved. */ #ifndef __LINUX_HOST1X_H @@ -68,6 +68,7 @@ static inline void host1x_bo_cache_destroy(struct host1x_bo_cache *cache) * @late_exit: host1x client late tear down code * @suspend: host1x client suspend code * @resume: host1x client resume code + * @get_rate: host1x client get clock rate code */ struct host1x_client_ops { int (*early_init)(struct host1x_client *client); @@ -76,8 +77,11 @@ struct host1x_client_ops { int (*late_exit)(struct host1x_client *client); int (*suspend)(struct host1x_client *client); int (*resume)(struct host1x_client *client); + unsigned long (*get_rate)(struct host1x_client *client); }; +struct host1x_actmon; + /** * struct host1x_client - host1x client structure * @list: list node for the host1x client @@ -93,6 +97,7 @@ struct host1x_client_ops { * @usecount: reference count for this structure * @lock: mutex for mutually exclusive concurrency * @cache: host1x buffer object cache + * @actmon: unit actmon for this client */ struct host1x_client { struct list_head list; @@ -113,6 +118,8 @@ struct host1x_client { struct mutex lock; struct host1x_bo_cache cache; + + struct host1x_actmon *actmon; }; /* @@ -507,5 +514,10 @@ static inline void host1x_memory_context_put(struct host1x_memory_context *cd) #endif int host1x_actmon_read_avg_count(struct host1x_client *client); +int host1x_actmon_register(struct host1x_client *client); +int host1x_actmon_unregister(struct host1x_client *client); +void host1x_actmon_update_client_rate(struct host1x_client *client, + unsigned long rate, + u32 *weight); #endif