[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <Y9zkQTXLzOzYqtV+@jade>
Date: Fri, 3 Feb 2023 11:38:57 +0100
From: Jens Wiklander <jens.wiklander@...aro.org>
To: Etienne Carriere <etienne.carriere@...aro.org>
Cc: linux-kernel@...r.kernel.org, linux-arm-kernel@...ts.infradead.org,
devicetree@...r.kernel.org, Marc Zyngier <maz@...nel.org>,
Sumit Garg <sumit.garg@...aro.org>
Subject: Re: [PATCH v2 3/3] optee: add enable/disable/set_wake handlers to
optee irqs
On Tue, Jan 24, 2023 at 11:56:43AM +0100, Etienne Carriere wrote:
> Implements OP-TEE's It Notif PTA API to deactivate and activate an
> interrupt notifier and to configure the wakeup capability
> of that interrupt. These controls are useful for efficient power
> management of the device when an interrupt controller resources is
> hosted in OP-TEE world.
>
> When OP-TEE does not implement the It Notif PTA, the related handlers
> simply return with success. If OP-TEE exposes the PTA services, they
> are invoked on enable, disable and set_wake irqchip operations.
>
> Cc: Jens Wiklander <jens.wiklander@...aro.org>
> Cc: Marc Zyngier <maz@...nel.org>
> Cc: Sumit Garg <sumit.garg@...aro.org>
>
> Signed-off-by: Etienne Carriere <etienne.carriere@...aro.org>
> ---
> Changes since v1:
> - Patch added in v2 series for power-up/down and wakeup configuration
> of the irq chip.
> ---
> drivers/tee/optee/optee_private.h | 2 +
> drivers/tee/optee/smc_abi.c | 157 ++++++++++++++++++++++++++++++
> 2 files changed, 159 insertions(+)
>
> diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
> index f467409e02e9..257bb505a1fb 100644
> --- a/drivers/tee/optee/optee_private.h
> +++ b/drivers/tee/optee/optee_private.h
> @@ -166,6 +166,7 @@ struct optee_ops {
> * @scan_bus_done flag if device registation was already done.
> * @scan_bus_wq workqueue to scan optee bus and register optee drivers
> * @scan_bus_work workq to scan optee bus and register optee drivers
> + * @notif_it_pta_ctx TEE context for invoking interrupt conif services
We already have "ctx" above, why do we need another TEE context?
Thanks,
Jens
> */
> struct optee {
> struct tee_device *supp_teedev;
> @@ -185,6 +186,7 @@ struct optee {
> bool scan_bus_done;
> struct workqueue_struct *scan_bus_wq;
> struct work_struct scan_bus_work;
> + struct tee_context *notif_it_pta_ctx;
> };
>
> struct optee_session {
> diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c
> index 9f4fdd28f04a..95adf8c93c98 100644
> --- a/drivers/tee/optee/smc_abi.c
> +++ b/drivers/tee/optee/smc_abi.c
> @@ -52,6 +52,43 @@
> */
> #define OPTEE_MIN_STATIC_POOL_ALIGN 9 /* 512 bytes aligned */
>
> +/*
> + * Interrupt notification can be configured using Notif-IT PTA services.
> + * Below are the PTA UUID and its API commands.
> + */
> +#define PTA_IT_NOTIF_UUID \
> + UUID_INIT(0x4461e5c7, 0xb523, 0x4b73, 0xac, 0xed, 0x75, 0xad, \
> + 0x2b, 0x9b, 0x59, 0xa1)
> +
> +/*
> + * PTA_IT_NOTIF_ACTIVATE_DETECTION - Enable a interrupt notification
> + *
> + * [in] params[0].value.a Interrupt ID
> + */
> +#define PTA_IT_NOTIF_ACTIVATE_DETECTION 0
> +
> +/*
> + * PTA_IT_NOTIF_DEACTIVATE_DETECTION - Disable a interrupt notification
> + *
> + * [in] params[0].value.a Interrupt ID
> + */
> +#define PTA_IT_NOTIF_DEACTIVATE_DETECTION 1
> +
> +/*
> + * PTA_IT_NOTIF_ENABLE_WAKEUP_SOURCE - Enable an interrupt wakeup source
> + *
> + * [in] params[0].value.a Interrupt ID
> + */
> +#define PTA_IT_NOTIF_ENABLE_WAKEUP_SOURCE 2
> +
> +/*
> + * PTA_IT_NOTIF_ENABLE_WAKEUP_SOURCE - Disable an interrupt wakeup source
> + *
> + * [in] params[0].value.a Interrupt ID
> + */
> +#define PTA_IT_NOTIF_DISABLE_WAKEUP_SOURCE 3
> +
> +
> /*
> * 1. Convert between struct tee_param and struct optee_msg_param
> *
> @@ -977,6 +1014,92 @@ static int optee_smc_stop_async_notif(struct tee_context *ctx)
> * 5. Asynchronous notification
> */
>
> +static int optee_ctx_match(struct tee_ioctl_version_data *ver, const void *data)
> +{
> + return ver->impl_id == TEE_IMPL_ID_OPTEE;
> +}
> +
> +static void init_optee_pta_context(struct optee *optee)
> +{
> + struct tee_context *ctx = NULL;
> + const uuid_t pta_uuid = PTA_IT_NOTIF_UUID;
> + struct tee_ioctl_open_session_arg sess_arg;
> + int ret;
> +
> + ctx = tee_client_open_context(NULL, optee_ctx_match, NULL, NULL);
> + if (IS_ERR(ctx))
> + return;
> +
> + memset(&sess_arg, 0, sizeof(sess_arg));
> + export_uuid(sess_arg.uuid, &pta_uuid);
> + sess_arg.clnt_login = TEE_IOCTL_LOGIN_REE_KERNEL;
> +
> + ret = tee_client_open_session(ctx, &sess_arg, NULL);
> + if ((ret < 0) || (sess_arg.ret != 0)) {
> + pr_err("Can't open IT_NOTIF PTA session: %#x\n", sess_arg.ret);
> + tee_client_close_context(ctx);
> + return;
> + }
> +
> + tee_client_close_session(ctx, sess_arg.session);
> +
> + optee->notif_it_pta_ctx = ctx;
> +}
> +
> +static void release_optee_pta_context(struct optee *optee)
> +{
> + if (optee->notif_it_pta_ctx) {
> + tee_client_close_context(optee->notif_it_pta_ctx);
> + optee->notif_it_pta_ctx = NULL;
> + }
> +}
> +
> +static int invoke_optee_pta(struct optee *optee, unsigned int command,
> + unsigned int irq_id)
> +{
> + const uuid_t pta_uuid = PTA_IT_NOTIF_UUID;
> + struct tee_ioctl_open_session_arg sess_arg;
> + struct tee_ioctl_invoke_arg inv_arg;
> + struct tee_param param[1];
> + int ret;
> +
> + if (!optee->notif_it_pta_ctx)
> + return -ENOENT;
> +
> + memset(&sess_arg, 0, sizeof(sess_arg));
> + export_uuid(sess_arg.uuid, &pta_uuid);
> + sess_arg.clnt_login = TEE_IOCTL_LOGIN_REE_KERNEL;
> +
> + ret = tee_client_open_session(optee->notif_it_pta_ctx, &sess_arg, NULL);
> + if ((ret < 0) || (sess_arg.ret != 0)) {
> + pr_err("tee_client_open_session failed, err: %#x\n", sess_arg.ret);
> + if (!ret)
> + ret = -EINVAL;
> + return ret;
> + }
> +
> + memset(&inv_arg, 0, sizeof(inv_arg));
> + inv_arg.session = sess_arg.session;
> + inv_arg.func = command;
> + inv_arg.num_params = 1;
> +
> + memset(¶m, 0, sizeof(param));
> + param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
> + param[0].u.value.a = irq_id;
> +
> + ret = tee_client_invoke_func(optee->notif_it_pta_ctx, &inv_arg, param);
> + if ((ret < 0) || (inv_arg.ret != 0)) {
> + pr_err("tee_client_invoke_func failed, ret: %d, err: %#x\n",
> + ret, inv_arg.ret);
> + if (!ret)
> + ret = -EINVAL;
> + }
> +
> + tee_client_close_session(optee->notif_it_pta_ctx, sess_arg.session);
> +
> + return ret;
> +}
> +
> static void config_notif_it(optee_invoke_fn *invoke_fn, u32 it_value,
> u32 op_mask, u32 val_mask)
> {
> @@ -1001,10 +1124,40 @@ static void optee_it_irq_unmask(struct irq_data *d)
> config_notif_it(optee->smc.invoke_fn, d->hwirq, OPTEE_SMC_NOTIF_CONFIG_MASK, 0);
> }
>
> +static void optee_it_irq_disable(struct irq_data *d)
> +{
> + struct optee *optee = d->domain->host_data;
> +
> + (void)invoke_optee_pta(optee, PTA_IT_NOTIF_DEACTIVATE_DETECTION, d->hwirq);
> +}
> +
> +static void optee_it_irq_enable(struct irq_data *d)
> +{
> + struct optee *optee = d->domain->host_data;
> +
> + (void)invoke_optee_pta(optee, PTA_IT_NOTIF_ACTIVATE_DETECTION, d->hwirq);
> +}
> +
> +static int optee_it_irq_set_wake(struct irq_data *d, unsigned int on)
> +{
> + struct optee *optee = d->domain->host_data;
> + u32 command;
> +
> + if (on)
> + command = PTA_IT_NOTIF_ENABLE_WAKEUP_SOURCE;
> + else
> + command = PTA_IT_NOTIF_DISABLE_WAKEUP_SOURCE;
> +
> + return invoke_optee_pta(optee, command, d->hwirq);
> +}
> +
> static struct irq_chip optee_it_irq_chip = {
> .name = "optee-it",
> .irq_mask = optee_it_irq_mask,
> .irq_unmask = optee_it_irq_unmask,
> + .irq_disable = optee_it_irq_disable,
> + .irq_enable = optee_it_irq_enable,
> + .irq_set_wake = optee_it_irq_set_wake,
> };
>
> static int optee_it_alloc(struct irq_domain *d, unsigned int virq,
> @@ -1463,6 +1616,7 @@ static int optee_smc_remove(struct platform_device *pdev)
> optee_disable_shm_cache(optee);
>
> optee_smc_notif_uninit_irq(optee);
> + release_optee_pta_context(optee);
>
> optee_remove_common(optee);
>
> @@ -1650,6 +1804,8 @@ static int optee_probe(struct platform_device *pdev)
> irq_dispose_mapping(irq);
> goto err_notif_uninit;
> }
> +
> + init_optee_pta_context(optee);
> }
>
> enable_async_notif(optee->smc.invoke_fn);
> @@ -1687,6 +1843,7 @@ static int optee_probe(struct platform_device *pdev)
> optee_disable_shm_cache(optee);
> optee_smc_notif_uninit_irq(optee);
> optee_unregister_devices();
> + release_optee_pta_context(optee);
> err_notif_uninit:
> optee_notif_uninit(optee);
> err_close_ctx:
> --
> 2.25.1
>
Powered by blists - more mailing lists