diff options
| author | Mikko Perttunen <mperttunen@nvidia.com> | 2026-07-10 16:14:32 +0900 |
|---|---|---|
| committer | Thierry Reding <treding@nvidia.com> | 2026-10-02 01:01:40 +0200 |
| commit | b9110d86fa4ff96f3a7ecee0729f111149acc805 (patch) | |
| tree | ebc6ba86130a724b7632e7fca11c4eeab0f02a65 /drivers | |
| parent | 6eb92f5520b8c0b97c3317f622a2b69bcde75395 (diff) | |
| download | linux-b9110d86fa4ff96f3a7ecee0729f111149acc805.tar.gz linux-b9110d86fa4ff96f3a7ecee0729f111149acc805.zip | |
gpu: host1x: Add option for disabling context stealing
Add kernel module parameter to allow disabling context stealing in cases
where reliability and consistency is preferred.
Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
Link: https://patch.msgid.link/20260710-b4-host1x-ctxsteal-v1-2-b1f8f6b37cc5@nvidia.com
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/gpu/host1x/context.c | 62 |
1 files changed, 47 insertions, 15 deletions
diff --git a/drivers/gpu/host1x/context.c b/drivers/gpu/host1x/context.c index 776bd4fbb554..c2c8a9bb5896 100644 --- a/drivers/gpu/host1x/context.c +++ b/drivers/gpu/host1x/context.c @@ -8,6 +8,7 @@ #include <linux/host1x_context_bus.h> #include <linux/kref.h> #include <linux/list.h> +#include <linux/moduleparam.h> #include <linux/of.h> #include <linux/of_device.h> #include <linux/pid.h> @@ -16,6 +17,10 @@ #include "context.h" #include "dev.h" +static bool static_context_alloc; +module_param(static_context_alloc, bool, 0644); +MODULE_PARM_DESC(static_context_alloc, "If enabled, memory contexts are allocated immediately on channel open and cannot be relinquished while a channel is open"); + static void host1x_memory_context_release(struct device *dev) { /* context device is freed in host1x_memory_context_list_free() */ @@ -168,7 +173,7 @@ host1x_memory_context_alloc_hw_locked(struct host1x *host1x, struct device *dev, /* Steal */ - if (!can_steal) + if (!can_steal || static_context_alloc) return ERR_PTR(-EBUSY); list_for_each_entry(ctx, &can_steal->owners, entry) { @@ -222,6 +227,7 @@ struct host1x_memory_context *host1x_memory_context_alloc(struct host1x *host1x, { struct host1x_memory_context_list *cdl = &host1x->context_list; struct host1x_memory_context *ctx; + int err; if (!cdl->len) return ERR_PTR(-EOPNOTSUPP); @@ -237,6 +243,17 @@ struct host1x_memory_context *host1x_memory_context_alloc(struct host1x *host1x, refcount_set(&ctx->ref, 1); INIT_LIST_HEAD(&ctx->mappings); + if (static_context_alloc) { + err = host1x_memory_context_active(ctx); + if (err) { + put_pid(ctx->pid); + kfree(ctx); + return ERR_PTR(err); + } + + ctx->static_alloc = true; + } + return ctx; } EXPORT_SYMBOL_GPL(host1x_memory_context_alloc); @@ -282,6 +299,11 @@ retry: hw = host1x_memory_context_alloc_hw_locked(ctx->host, ctx->dev, ctx->pid); if (PTR_ERR(hw) == -EBUSY) { /* All contexts busy. Wait for free context. */ + if (static_context_alloc) { + dev_warn(ctx->dev, "%s: all memory contexts are busy\n", current->comm); + err = -EBUSY; + goto unlock; + } if (!retrying) dev_warn(ctx->dev, "%s: all memory contexts are busy, waiting\n", current->comm); @@ -419,24 +441,11 @@ void host1x_memory_context_unmap(struct host1x_context_mapping *m) } EXPORT_SYMBOL_GPL(host1x_memory_context_unmap); -/** - * host1x_memory_context_inactive() - mark a memory context as no longer in use - * @ctx: memory context - * - * Drop one active reference taken by host1x_memory_context_active(). When the - * last active reference is dropped, the backing hardware context becomes - * eligible to be stolen by another context, and any waiters are woken. - * - * Must be called exactly once for each successful - * host1x_memory_context_active(). - */ -void host1x_memory_context_inactive(struct host1x_memory_context *ctx) +static void host1x_memory_context_inactive_locked(struct host1x_memory_context *ctx) { struct host1x_memory_context_list *cdl = &ctx->host->context_list; struct hw_alloc_waiter *waiter; - mutex_lock(&cdl->lock); - if (refcount_dec_and_test(&ctx->hw->active)) { /* Hardware context becomes eligible for stealing */ list_for_each_entry(waiter, &cdl->waiters, entry) { @@ -451,6 +460,26 @@ void host1x_memory_context_inactive(struct host1x_memory_context *ctx) */ } } +} + +/** + * host1x_memory_context_inactive() - mark a memory context as no longer in use + * @ctx: memory context + * + * Drop one active reference taken by host1x_memory_context_active(). When the + * last active reference is dropped, the backing hardware context becomes + * eligible to be stolen by another context, and any waiters are woken. + * + * Must be called exactly once for each successful + * host1x_memory_context_active(). + */ +void host1x_memory_context_inactive(struct host1x_memory_context *ctx) +{ + struct host1x_memory_context_list *cdl = &ctx->host->context_list; + + mutex_lock(&cdl->lock); + + host1x_memory_context_inactive_locked(ctx); mutex_unlock(&cdl->lock); } @@ -479,6 +508,9 @@ void host1x_memory_context_put(struct host1x_memory_context *ctx) struct host1x_memory_context_list *cdl = &ctx->host->context_list; if (refcount_dec_and_mutex_lock(&ctx->ref, &cdl->lock)) { + if (ctx->static_alloc) + host1x_memory_context_inactive_locked(ctx); + if (ctx->hw) { list_del(&ctx->entry); |
