From: Jean-Philippe Brucker <[email protected]> Introduce a nr_contexts members to cla_domain to count the mapped contexts. At the moment PL0 contexts share the domain, while PL1 contexts require exclusive assignment, since there is no context save/restore. A negative count indicates the domain is exclusive.
Signed-off-by: Jean-Philippe Brucker <[email protected]> --- drivers/misc/arm-cla/arm-cla.h | 2 ++ drivers/misc/arm-cla/cla-ctx.c | 44 ++++++++++++++++++++++++++++++++-- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/drivers/misc/arm-cla/arm-cla.h b/drivers/misc/arm-cla/arm-cla.h index c9ecab5ab6bf..43a58a329525 100644 --- a/drivers/misc/arm-cla/arm-cla.h +++ b/drivers/misc/arm-cla/arm-cla.h @@ -105,6 +105,7 @@ struct cla_dev { * @lock: Protects the following members. * @ctxs: All live contexts, keyed on cla_ctx_key. * @queued_ctxs: Queue of contexts waiting for assignment. + * @nr_ctxs: Context count. Negative value for exclusive assignment. * @worker: Kthread worker to coordinate reassignment. * @reassign: Delayed work that switches contexts with time slicing. * @@ -120,6 +121,7 @@ struct cla_domain { struct mutex lock; bool broken; + long nr_ctxs; struct rhashtable ctxs; struct list_head queued_ctxs; struct cla_ctx *assigned_ctx; diff --git a/drivers/misc/arm-cla/cla-ctx.c b/drivers/misc/arm-cla/cla-ctx.c index 0489bf7a103f..f956cc88909f 100644 --- a/drivers/misc/arm-cla/cla-ctx.c +++ b/drivers/misc/arm-cla/cla-ctx.c @@ -39,6 +39,38 @@ static inline void cla_ctx_put_pl1(struct cla_ctx *ctx) } #endif +static int cla_domain_get(struct cla_domain *domain, bool share) +{ + lockdep_assert_held(&domain->lock); + + if (share) { + /* Time share the domain with other contexts. */ + if (domain->nr_ctxs < 0) + return -EBUSY; + domain->nr_ctxs++; + WARN_ON(domain->nr_ctxs < 0); /* LONG_MAX contexts?! */ + } else { + /* Reserve the domain for exclusive assignment. */ + if (domain->nr_ctxs != 0) + return -EBUSY; + domain->nr_ctxs--; + } + return 0; +} + +/* Undo cla_domain_get() */ +static void cla_domain_put(struct cla_domain *domain) +{ + lockdep_assert_held(&domain->lock); + + if (domain->nr_ctxs == -1) + domain->nr_ctxs = 0; + else if (domain->nr_ctxs > 0) + domain->nr_ctxs--; + else + WARN(1, "invalid domain refcount %ld\n", domain->nr_ctxs); +} + /** * cla_ctx_create - Create a context or increase its user count * @domain: CLA domain @@ -53,7 +85,7 @@ struct cla_ctx *cla_ctx_create(struct cla_domain *domain, struct cla_ctx_key *key) { struct cla_ctx *ctx; - int ret = -ENOMEM; + int ret; mutex_lock(&domain->lock); ctx = cla_domain_lookup_ctx(domain, key); @@ -68,9 +100,14 @@ struct cla_ctx *cla_ctx_create(struct cla_domain *domain, goto err_unlock; } + ret = cla_domain_get(domain, key->type == CLA_CTX_PL0); + if (ret) + goto err_unlock; + + ret = -ENOMEM; ctx = kzalloc_obj(*ctx, GFP_KERNEL_ACCOUNT); if (!ctx) - goto err_unlock; + goto err_put_domain; kref_init(&ctx->refcnt); refcount_set(&ctx->users, 1); @@ -116,6 +153,8 @@ struct cla_ctx *cla_ctx_create(struct cla_domain *domain, cla_ctx_put_pl1(ctx); } kfree(ctx); +err_put_domain: + cla_domain_put(domain); err_unlock: mutex_unlock(&domain->lock); return ERR_PTR(ret); @@ -161,6 +200,7 @@ void cla_ctx_destroy(struct cla_domain *domain, struct cla_ctx_key *key) */ if (domain->assigned_ctx == ctx) cla_domain_schedule_reassignment(domain); + cla_domain_put(domain); mutex_unlock(&domain->lock); /* Release initial reference from cla_ctx_create(). */ -- 2.43.0
