From 18c7ae79cb4f912948f797d5594a2fff0514649f Mon Sep 17 00:00:00 2001 From: Shown Han Date: Tue, 19 Jan 2021 16:12:47 +0800 Subject: [PATCH] tee: optee: Fix RPC call break system sleep operation. The system sleep can be break when freezer try to freeze tasks who are waitting for unreachable conditions. All RPC calls waiting on tee-supplicant results are unreachable conditions when tee-supplicant be frozen. And TEE wait queue sleep becomes to unreachable condition on the corresponding wakeup process be frozen. By introduce freezer help functions tell to freezer ignoring tasks which can help to avoid freezer wakeup those tasks and wait them call into try_to_freeze(), the wait of those tasks are constantly timeout because they are waitting on unreachable conditions. This patch utilize freezer help functions to enclose those potential unreachable conditions boundaries to avoid breaking system sleep. Signed-off-by: Shown Han --- drivers/tee/optee/call.c | 6 ++++++ drivers/tee/optee/optee_private.h | 1 + drivers/tee/optee/rpc.c | 6 ++++++ drivers/tee/optee/supp.c | 7 +++++++ 4 files changed, 20 insertions(+) diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c index 3945041e661557..16b56fa979afc0 100644 --- a/drivers/tee/optee/call.c +++ b/drivers/tee/optee/call.c @@ -48,8 +48,14 @@ static void optee_cq_wait_init(struct optee_call_queue *cq, static void optee_cq_wait_for_completion(struct optee_call_queue *cq, struct optee_call_waiter *w) { + /* Tell freezers to ignore the current task. */ + freezer_do_not_count(); + wait_for_completion(&w->c); + /* Tell freezer to stop ignoring current task. */ + freezer_count(); + mutex_lock(&cq->mutex); /* Move to end of list to get out of the way for other waiters */ diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h index 8b71839a357ede..4efc2879af5606 100644 --- a/drivers/tee/optee/optee_private.h +++ b/drivers/tee/optee/optee_private.h @@ -10,6 +10,7 @@ #include #include #include +#include #include "optee_msg.h" #define OPTEE_MAX_ARG_SIZE 1024 diff --git a/drivers/tee/optee/rpc.c b/drivers/tee/optee/rpc.c index 817b1caee28c3e..f3136305702597 100644 --- a/drivers/tee/optee/rpc.c +++ b/drivers/tee/optee/rpc.c @@ -77,7 +77,13 @@ static void wq_sleep(struct optee_wait_queue *wq, u32 key) struct wq_entry *w = wq_entry_get(wq, key); if (w) { + /* Tell freezers to ignore the current task. */ + freezer_do_not_count(); + wait_for_completion(&w->c); + + /* Tell freezer to stop ignoring current task. */ + freezer_count(); mutex_lock(&wq->mu); list_del(&w->link); mutex_unlock(&wq->mu); diff --git a/drivers/tee/optee/supp.c b/drivers/tee/optee/supp.c index 322a543b8c278a..46172edac191f0 100644 --- a/drivers/tee/optee/supp.c +++ b/drivers/tee/optee/supp.c @@ -108,6 +108,10 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params, /* Tell an eventual waiter there's a new request */ complete(&supp->reqs_c); + + /* Tell freezers to ignore the current task. */ + freezer_do_not_count(); + /* * Wait for supplicant to process and return result, once we've * returned from wait_for_completion(&req->c) successfully we have @@ -143,6 +147,9 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params, } } + /* Tell freezer to stop ignoring current task. */ + freezer_count(); + ret = req->ret; kfree(req);