diff --git a/drivers/gpu/host1x/actmon.c b/drivers/gpu/host1x/actmon.c index 49960fb9..c2f0b75c 100644 --- a/drivers/gpu/host1x/actmon.c +++ b/drivers/gpu/host1x/actmon.c @@ -249,35 +249,27 @@ static void host1x_actmon_deinit(struct host1x_actmon *actmon) 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); + actmon_module_writel(module, + HOST1X_ACTMON_MODULE_CTRL_ACTMON_ENB(1) | + 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 */ - 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 enable register (disable interrupts by default) */ + actmon_module_writel(module, 0, HOST1X_ACTMON_MODULE_INTR_ENB_REG); /* Interrupt status register */ - actmon_module_writel(module, 0xffffffff, HOST1X_ACTMON_MODULE_INTR_STATUS_REG); + actmon_module_writel(module, ~0, 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_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_UPPER_WMARK_REG); actmon_module_writel(module, 0, HOST1X_ACTMON_MODULE_AVG_LOWER_WMARK_REG); /* Init average value register */ @@ -288,7 +280,7 @@ 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_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); @@ -297,6 +289,40 @@ static void host1x_actmon_module_deinit(struct host1x_actmon_module *module) 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); @@ -304,6 +330,7 @@ int host1x_actmon_register(struct host1x_client *client) struct host1x_actmon_entry *entry = NULL; struct host1x_actmon_module *module; struct host1x_actmon *actmon; + unsigned long flags; int i, err; if (!host->actmon_regs || !host->actmon_clk) @@ -320,6 +347,12 @@ int host1x_actmon_register(struct host1x_client *client) 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; @@ -361,6 +394,7 @@ 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) @@ -379,6 +413,10 @@ int host1x_actmon_unregister(struct host1x_client *client) 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); diff --git a/drivers/gpu/host1x/actmon.h b/drivers/gpu/host1x/actmon.h index 1b3a50aa..1f92987f 100644 --- a/drivers/gpu/host1x/actmon.h +++ b/drivers/gpu/host1x/actmon.h @@ -40,6 +40,11 @@ struct host1x_actmon { struct host1x_client *client; struct host1x_actmon_module modules[8]; struct dentry *debugfs; + struct list_head list; }; +struct host1x; + +void host1x_actmon_handle_interrupt(struct host1x *host, int classid); + #endif diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c index 46b2e57b..03a95ac9 100644 --- a/drivers/gpu/host1x/dev.c +++ b/drivers/gpu/host1x/dev.c @@ -47,6 +47,11 @@ void host1x_common_writel(struct host1x *host1x, u32 v, u32 r) writel(v, host1x->common_regs + r); } +u32 host1x_common_readl(struct host1x *host1x, u32 r) +{ + return readl(host1x->common_regs + r); +} + void host1x_hypervisor_writel(struct host1x *host1x, u32 v, u32 r) { writel(v, host1x->hv_regs + r); @@ -832,8 +837,12 @@ static int host1x_probe(struct platform_device *pdev) if (host->syncpt_irq < 0) return host->syncpt_irq; + host->general_irq = platform_get_irq_byname_optional(pdev, "host1x"); + mutex_init(&host->devices_lock); INIT_LIST_HEAD(&host->devices); + spin_lock_init(&host->actmons_lock); + INIT_LIST_HEAD(&host->actmons); INIT_LIST_HEAD(&host->list); host->dev = &pdev->dev; @@ -849,6 +858,12 @@ static int host1x_probe(struct platform_device *pdev) return err; } + if (host->general_irq > 0 && host->common_regs) { + err = host1x_hw_intr_init_host_general(host); + if (err) + return err; + } + err = host1x_get_assigned_resources(host); if (err) return err; @@ -979,6 +994,7 @@ static int __maybe_unused host1x_runtime_suspend(struct device *dev) struct host1x *host = dev_get_drvdata(dev); int err; + host1x_hw_intr_disable_all_general_intrs(host); host1x_intr_stop(host); host1x_syncpt_save(host); @@ -999,6 +1015,7 @@ static int __maybe_unused host1x_runtime_suspend(struct device *dev) resume_host1x: host1x_setup_virtualization_tables(host); host1x_syncpt_restore(host); + host1x_hw_intr_enable_general_intrs(host); host1x_intr_start(host); return err; @@ -1035,6 +1052,7 @@ static int __maybe_unused host1x_runtime_resume(struct device *dev) host1x_setup_virtualization_tables(host); host1x_syncpt_restore(host); + host1x_hw_intr_enable_general_intrs(host); host1x_intr_start(host); return 0; diff --git a/drivers/gpu/host1x/dev.h b/drivers/gpu/host1x/dev.h index d72c5bf3..aa1d9157 100644 --- a/drivers/gpu/host1x/dev.h +++ b/drivers/gpu/host1x/dev.h @@ -12,6 +12,7 @@ #include #include +#include "actmon.h" #include "cdma.h" #include "channel.h" #include "context.h" @@ -73,6 +74,12 @@ struct host1x_syncpt_ops { void (*enable_protection)(struct host1x *host); }; +struct host1x_intr_general_ops { + int (*init_host_general)(struct host1x *host); + void (*enable_general_intrs)(struct host1x *host); + void (*disable_all_general_intrs)(struct host1x *host); +}; + struct host1x_intr_ops { int (*init_host_sync)(struct host1x *host, u32 cpm); void (*set_syncpt_threshold)( @@ -142,6 +149,7 @@ struct host1x { void __iomem *common_regs; void __iomem *actmon_regs; int syncpt_irq; + int general_irq; struct host1x_syncpt *syncpt; struct host1x_syncpt_base *bases; struct device *dev; @@ -166,6 +174,7 @@ struct host1x { struct mutex intr_mutex; const struct host1x_syncpt_ops *syncpt_op; + const struct host1x_intr_general_ops *intr_general_op; const struct host1x_intr_ops *intr_op; const struct host1x_channel_ops *channel_op; const struct host1x_cdma_ops *cdma_op; @@ -185,6 +194,9 @@ struct host1x { struct mutex devices_lock; struct list_head devices; + spinlock_t actmons_lock; + struct list_head actmons; + struct list_head list; struct device_dma_parameters dma_parms; @@ -193,6 +205,7 @@ struct host1x { }; void host1x_common_writel(struct host1x *host1x, u32 v, u32 r); +u32 host1x_common_readl(struct host1x *host1x, u32 r); void host1x_hypervisor_writel(struct host1x *host1x, u32 r, u32 v); u32 host1x_hypervisor_readl(struct host1x *host1x, u32 r); void host1x_sync_writel(struct host1x *host1x, u32 r, u32 v); @@ -242,6 +255,30 @@ static inline void host1x_hw_syncpt_enable_protection(struct host1x *host) return host->syncpt_op->enable_protection(host); } +static inline int host1x_hw_intr_init_host_general(struct host1x *host) +{ + if (!host->intr_general_op) + return -EPERM; + + return host->intr_general_op->init_host_general(host); +} + +static inline void host1x_hw_intr_enable_general_intrs(struct host1x *host) +{ + if (!host->intr_general_op) + return; + + host->intr_general_op->enable_general_intrs(host); +} + +static inline void host1x_hw_intr_disable_all_general_intrs(struct host1x *host) +{ + if (!host->intr_general_op) + return; + + host->intr_general_op->disable_all_general_intrs(host); +} + static inline int host1x_hw_intr_init_host_sync(struct host1x *host, u32 cpm) { return host->intr_op->init_host_sync(host, cpm); diff --git a/drivers/gpu/host1x/hw/actmon.h b/drivers/gpu/host1x/hw/actmon.h index 23cd627b..71eba1f1 100644 --- a/drivers/gpu/host1x/hw/actmon.h +++ b/drivers/gpu/host1x/hw/actmon.h @@ -12,6 +12,7 @@ #define HOST1X_ACTMON_CTRL_REG 0x0 #define HOST1X_ACTMON_INTR_ENB_REG 0x4 +#define HOST1X_ACTMON_INTR_STATUS_REG 0x8 #define HOST1X_ACTMON_MODULE_INIT_AVG_REG 0x14 #define HOST1X_ACTMON_MODULE_CTRL_REG 0x80 #define HOST1X_ACTMON_MODULE_INTR_ENB_REG 0x84 @@ -31,14 +32,19 @@ #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_MODULE_INTR_CONSEC_WMARK_ABOVE_ENB(v) ((v & 0x1) << 31) +#define HOST1X_ACTMON_MODULE_INTR_CONSEC_WMARK_BELOW_ENB(v) ((v & 0x1) << 30) +#define HOST1X_ACTMON_MODULE_INTR_AVG_WMARK_ABOVE_ENB(v) ((v & 0x1) << 29) +#define HOST1X_ACTMON_MODULE_INTR_AVG_WMARK_BELOW_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) +#define HOST1X_ACTMON_MODULE_INTR_CONSEC_WMARK_ABOVE BIT(31) +#define HOST1X_ACTMON_MODULE_INTR_CONSEC_WMARK_BELOW BIT(30) +#define HOST1X_ACTMON_MODULE_INTR_AVG_WMARK_ABOVE BIT(29) +#define HOST1X_ACTMON_MODULE_INTR_AVG_WMARK_BELOW BIT(28) + #endif diff --git a/drivers/gpu/host1x/hw/host1x08.c b/drivers/gpu/host1x/hw/host1x08.c index 754890c3..1d452a07 100644 --- a/drivers/gpu/host1x/hw/host1x08.c +++ b/drivers/gpu/host1x/hw/host1x08.c @@ -2,7 +2,7 @@ /* * Host1x init for Tegra234 SoCs * - * Copyright (c) 2022 NVIDIA Corporation. + * Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All Rights Reserved. */ /* include hw specification */ @@ -15,6 +15,7 @@ #include "cdma_hw.c" #include "channel_hw.c" #include "debug_hw.c" +#include "intr_general_hw.c" #include "intr_hw.c" #include "syncpt_hw.c" @@ -26,6 +27,7 @@ int host1x08_init(struct host1x *host) host->cdma_op = &host1x_cdma_ops; host->cdma_pb_op = &host1x_pushbuffer_ops; host->syncpt_op = &host1x_syncpt_ops; + host->intr_general_op = &host1x_intr_general_ops; host->intr_op = &host1x_intr_ops; host->debug_op = &host1x_debug_ops; diff --git a/drivers/gpu/host1x/hw/hw_host1x08_common.h b/drivers/gpu/host1x/hw/hw_host1x08_common.h index 8e0c9915..c2220f9f 100644 --- a/drivers/gpu/host1x/hw/hw_host1x08_common.h +++ b/drivers/gpu/host1x/hw/hw_host1x08_common.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2022 NVIDIA Corporation. + * Copyright (c) 2022-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ #define HOST1X_COMMON_OFA_MLOCK 0x4050 @@ -9,3 +9,20 @@ #define HOST1X_COMMON_NVENC_MLOCK 0x407c #define HOST1X_COMMON_NVDEC_MLOCK 0x4080 #define HOST1X_COMMON_NVJPG_MLOCK 0x4084 + +#define HOST1X_COMMON_INTR_CPU0_MASK 0x4 +#define HOST1X_COMMON_THOST_INTRSTATUS 0x1c +#define HOST1X_COMMON_THOST_INTRMASK 0x30 +#define HOST1X_COMMON_THOST_GLOBAL_INTRMASK 0x44 + +#define HOST1X_COMMON_THOST_INTRMASK_NVENC_ACTMON(v) (v << 2) +#define HOST1X_COMMON_THOST_INTRMASK_VIC_ACTMON(v) (v << 3) +#define HOST1X_COMMON_THOST_INTRMASK_NVDEC_ACTMON(v) (v << 4) +#define HOST1X_COMMON_THOST_INTRMASK_NVJPG_ACTMON(v) (v << 5) +#define HOST1X_COMMON_THOST_INTRMASK_NVJPG1_ACTMON(v) (v << 6) + +#define HOST1X_COMMON_THOST_INTRSTATUS_NVENC_ACTMON_INTR BIT(2) +#define HOST1X_COMMON_THOST_INTRSTATUS_VIC_ACTMON_INTR BIT(3) +#define HOST1X_COMMON_THOST_INTRSTATUS_NVDEC_ACTMON_INTR BIT(4) +#define HOST1X_COMMON_THOST_INTRSTATUS_NVJPG_ACTMON_INTR BIT(5) +#define HOST1X_COMMON_THOST_INTRSTATUS_NVJPG1_ACTMON_INTR BIT(6) diff --git a/drivers/gpu/host1x/hw/intr_general_hw.c b/drivers/gpu/host1x/hw/intr_general_hw.c new file mode 100644 index 00000000..35667aa0 --- /dev/null +++ b/drivers/gpu/host1x/hw/intr_general_hw.c @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Tegra host1x General Interrupt Management + * + * Copyright (C) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + */ + +#include + +#include "../dev.h" + +static irqreturn_t host1x_general_isr(int irq, void *dev_id) +{ + struct host1x *host = dev_id; + unsigned long status; + + status = host1x_common_readl(host, HOST1X_COMMON_THOST_INTRSTATUS); + + if (status & HOST1X_COMMON_THOST_INTRSTATUS_NVENC_ACTMON_INTR) + host1x_actmon_handle_interrupt(host, HOST1X_CLASS_NVENC); + + if (status & HOST1X_COMMON_THOST_INTRSTATUS_VIC_ACTMON_INTR) + host1x_actmon_handle_interrupt(host, HOST1X_CLASS_VIC); + + if (status & HOST1X_COMMON_THOST_INTRSTATUS_NVDEC_ACTMON_INTR) + host1x_actmon_handle_interrupt(host, HOST1X_CLASS_NVDEC); + + if (status & HOST1X_COMMON_THOST_INTRSTATUS_NVJPG_ACTMON_INTR) + host1x_actmon_handle_interrupt(host, HOST1X_CLASS_NVJPG); + + if (status & HOST1X_COMMON_THOST_INTRSTATUS_NVJPG1_ACTMON_INTR) + host1x_actmon_handle_interrupt(host, HOST1X_CLASS_NVJPG1); + + host1x_common_writel(host, status, HOST1X_COMMON_THOST_INTRSTATUS); + + return IRQ_HANDLED; +} + +static int host1x_intr_init_host_general(struct host1x *host) +{ + int err; + + host1x_hw_intr_disable_all_general_intrs(host); + + err = devm_request_threaded_irq(host->dev, + host->general_irq, + NULL, host1x_general_isr, + IRQF_ONESHOT, "host1x_general", + host); + if (err < 0) { + devm_free_irq(host->dev, host->general_irq, host); + return err; + } + + return 0; +} + +static void host1x_intr_enable_general_intrs(struct host1x *host) +{ + if (!host->common_regs) + return; + + /* Assign CPU0 for host1x general interrupts */ + host1x_common_writel(host, 0x1, HOST1X_COMMON_INTR_CPU0_MASK); + + /* Allow host1x general interrupts go to CPU0 only */ + host1x_common_writel(host, 0x1, HOST1X_COMMON_THOST_GLOBAL_INTRMASK); + + /* Enable host1x general interrupts */ + host1x_common_writel(host, + HOST1X_COMMON_THOST_INTRMASK_NVENC_ACTMON(1) | + HOST1X_COMMON_THOST_INTRMASK_VIC_ACTMON(1) | + HOST1X_COMMON_THOST_INTRMASK_NVDEC_ACTMON(1) | + HOST1X_COMMON_THOST_INTRMASK_NVJPG_ACTMON(1) | + HOST1X_COMMON_THOST_INTRMASK_NVJPG1_ACTMON(1), + HOST1X_COMMON_THOST_INTRMASK); +} + +static void host1x_intr_disable_all_general_intrs(struct host1x *host) +{ + if (!host->common_regs) + return; + + host1x_common_writel(host, 0x0, HOST1X_COMMON_THOST_INTRMASK); +} + +static const struct host1x_intr_general_ops host1x_intr_general_ops = { + .init_host_general = host1x_intr_init_host_general, + .enable_general_intrs = host1x_intr_enable_general_intrs, + .disable_all_general_intrs = host1x_intr_disable_all_general_intrs, +}; diff --git a/drivers/gpu/host1x/include/linux/host1x-next.h b/drivers/gpu/host1x/include/linux/host1x-next.h index 813f36a9..e65f26f6 100644 --- a/drivers/gpu/host1x/include/linux/host1x-next.h +++ b/drivers/gpu/host1x/include/linux/host1x-next.h @@ -27,6 +27,13 @@ enum host1x_class { HOST1X_CLASS_NVDEC1 = 0xF5, }; +enum host1x_actmon_wmark_event { + HOST1X_ACTMON_AVG_WMARK_BELOW, + HOST1X_ACTMON_AVG_WMARK_ABOVE, + HOST1X_ACTMON_CONSEC_WMARK_BELOW, + HOST1X_ACTMON_CONSEC_WMARK_ABOVE, +}; + struct host1x; struct host1x_client; struct iommu_group; @@ -69,6 +76,7 @@ static inline void host1x_bo_cache_destroy(struct host1x_bo_cache *cache) * @suspend: host1x client suspend code * @resume: host1x client resume code * @get_rate: host1x client get clock rate code + * @actmon_event: host1x client actmon event handling code in threaded interrupt context */ struct host1x_client_ops { int (*early_init)(struct host1x_client *client); @@ -78,6 +86,8 @@ struct host1x_client_ops { int (*suspend)(struct host1x_client *client); int (*resume)(struct host1x_client *client); unsigned long (*get_rate)(struct host1x_client *client); + void (*actmon_event)(struct host1x_client *client, + enum host1x_actmon_wmark_event event); }; struct host1x_actmon;