Loading drivers/char/adsprpc.c +39 −26 Original line number Diff line number Diff line Loading @@ -111,6 +111,9 @@ #define FASTRPC_STATIC_HANDLE_MAX (20) #define FASTRPC_LATENCY_CTRL_ENB (1) /* Maximum PM timeout that can be voted through fastrpc*/ #define MAX_PM_TIMEOUT_MS 50 /* timeout in us for busy polling after early response from remote processor */ #define FASTRPC_POLL_TIME (4000) Loading Loading @@ -285,7 +288,6 @@ struct smq_invoke_ctx { uint32_t earlyWakeTime; /* work done status flag */ bool isWorkDone; bool pm_awake_voted; }; struct fastrpc_ctx_lst { Loading Loading @@ -460,6 +462,8 @@ struct fastrpc_file { char *debug_buf; /* Flag to enable PM wake/relax voting for every remote invoke */ int wake_enable; struct wakeup_source *wake_source; uint32_t ws_timeout; }; static struct fastrpc_apps gfa; Loading Loading @@ -532,8 +536,7 @@ static struct fastrpc_channel_ctx gcinfo[NUM_CHANNELS] = { static int hlosvm[1] = {VMID_HLOS}; static int hlosvmperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC}; static void fastrpc_pm_awake(int fl_wake_enable, bool *pm_awake_voted); static void fastrpc_pm_relax(bool *pm_awake_voted); static void fastrpc_pm_awake(struct fastrpc_file *fl); static inline int64_t getnstimediff(struct timespec *start) { Loading Loading @@ -1364,7 +1367,6 @@ static int context_alloc(struct fastrpc_file *fl, uint32_t kernel, ctx->magic = FASTRPC_CTX_MAGIC; ctx->rspFlags = NORMAL_RESPONSE; ctx->isWorkDone = false; ctx->pm_awake_voted = false; spin_lock(&fl->hlock); hlist_add_head(&ctx->hn, &clst->pending); Loading Loading @@ -1444,7 +1446,7 @@ static void context_free(struct smq_invoke_ctx *ctx) static void context_notify_user(struct smq_invoke_ctx *ctx, int retval, uint32_t rspFlags, uint32_t earlyWakeTime) { fastrpc_pm_awake(ctx->fl->wake_enable, &ctx->pm_awake_voted); fastrpc_pm_awake(ctx->fl); ctx->retval = retval; switch (rspFlags) { case NORMAL_RESPONSE: Loading Loading @@ -2090,24 +2092,15 @@ static void fastrpc_init(struct fastrpc_apps *me) me->channel[CDSP_DOMAIN_ID].secure = NON_SECURE_CHANNEL; } static inline void fastrpc_pm_awake(int fl_wake_enable, bool *pm_awake_voted) { struct fastrpc_apps *me = &gfa; if (!fl_wake_enable || *pm_awake_voted) return; __pm_stay_awake(me->wake_source); *pm_awake_voted = true; } static inline void fastrpc_pm_relax(bool *pm_awake_voted) static inline void fastrpc_pm_awake(struct fastrpc_file *fl) { struct fastrpc_apps *me = &gfa; if (!(*pm_awake_voted)) if (!fl->wake_enable || !fl->wake_source) return; __pm_relax(me->wake_source); *pm_awake_voted = false; /* * Vote with PM to abort any suspend in progress and * keep system awake for specified timeout */ pm_wakeup_ws_event(fl->wake_source, fl->ws_timeout, true); } static inline int fastrpc_wait_for_response(struct smq_invoke_ctx *ctx, Loading Loading @@ -2229,9 +2222,7 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode, int err = 0, interrupted = 0, cid = fl->cid; struct timespec invoket = {0}; int64_t *perf_counter = NULL; bool pm_awake_voted = false; fastrpc_pm_awake(fl->wake_enable, &pm_awake_voted); if (fl->profile) { perf_counter = getperfcounter(fl, PERF_COUNT); getnstimeofday(&invoket); Loading Loading @@ -2300,9 +2291,7 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode, if (err) goto bail; wait: fastrpc_pm_relax(&pm_awake_voted); fastrpc_wait_for_completion(ctx, &interrupted, kernel); pm_awake_voted = ctx->pm_awake_voted; VERIFY(err, 0 == (err = interrupted)); if (err) goto bail; Loading Loading @@ -2341,7 +2330,6 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode, if (fl->profile && !interrupted) fastrpc_update_invoke_count(invoke->handle, perf_counter, &invoket); fastrpc_pm_relax(&pm_awake_voted); return err; } Loading Loading @@ -3503,6 +3491,8 @@ static int fastrpc_file_free(struct fastrpc_file *fl) spin_lock(&fl->apps->hlock); hlist_del_init(&fl->hn); spin_unlock(&fl->apps->hlock); if (fl->wake_source) wakeup_source_unregister(fl->wake_source); kfree(fl->debug_buf); if (!fl->sctx) { Loading Loading @@ -3890,6 +3880,11 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp) debugfs_file = debugfs_create_file(fl->debug_buf, 0644, debugfs_root, fl, &debugfs_fops); fl->wake_source = wakeup_source_register(fl->debug_buf); if (IS_ERR_OR_NULL(fl->wake_source)) { pr_err("adsprpc: Error: %s: %s: wakeup_source_register failed with err %ld\n", current->comm, __func__, PTR_ERR(fl->wake_source)); } context_list_ctor(&fl->clst); spin_lock_init(&fl->hlock); INIT_HLIST_HEAD(&fl->maps); Loading Loading @@ -4006,8 +4001,26 @@ static int fastrpc_internal_control(struct fastrpc_file *fl, cp->kalloc.kalloc_support = 1; break; case FASTRPC_CONTROL_WAKELOCK: if (fl->dev_minor != MINOR_NUM_SECURE_DEV) { pr_err("adsprpc: %s: %s: PM voting not allowed for non-secure device node %d\n", current->comm, __func__, fl->dev_minor); err = -EPERM; goto bail; } fl->wake_enable = cp->wp.enable; break; case FASTRPC_CONTROL_PM: if (!fl->wake_enable) { /* Kernel PM voting not requested by this application */ err = -EACCES; goto bail; } if (cp->pm.timeout > MAX_PM_TIMEOUT_MS) fl->ws_timeout = MAX_PM_TIMEOUT_MS; else fl->ws_timeout = cp->pm.timeout; fastrpc_pm_awake(fl); break; default: err = -EBADRQC; break; Loading drivers/char/adsprpc_compat.c +16 −0 Original line number Diff line number Diff line Loading @@ -130,11 +130,21 @@ struct compat_fastrpc_ctrl_kalloc { compat_uint_t kalloc_support; /* Remote memory allocation from kernel */ }; struct compat_fastrpc_ctrl_wakelock { compat_uint_t enable; /* wakelock control enable */ }; struct compat_fastrpc_ctrl_pm { compat_uint_t timeout; /* timeout(in ms) for PM to keep system awake*/ }; struct compat_fastrpc_ioctl_control { compat_uint_t req; union { struct compat_fastrpc_ctrl_latency lp; struct compat_fastrpc_ctrl_kalloc kalloc; struct compat_fastrpc_ctrl_wakelock wp; struct compat_fastrpc_ctrl_pm pm; }; }; Loading Loading @@ -336,6 +346,12 @@ static int compat_get_fastrpc_ioctl_control( err |= put_user(p, &ctrl->lp.enable); err |= get_user(p, &ctrl32->lp.latency); err |= put_user(p, &ctrl->lp.latency); } else if (p == FASTRPC_CONTROL_WAKELOCK) { err |= get_user(p, &ctrl32->wp.enable); err |= put_user(p, &ctrl->wp.enable); } else if (p == FASTRPC_CONTROL_PM) { err |= get_user(p, &ctrl32->pm.timeout); err |= put_user(p, &ctrl->pm.timeout); } return err; Loading drivers/char/adsprpc_shared.h +6 −0 Original line number Diff line number Diff line Loading @@ -249,6 +249,7 @@ enum fastrpc_control_type { FASTRPC_CONTROL_SMMU = 2, FASTRPC_CONTROL_KALLOC = 3, FASTRPC_CONTROL_WAKELOCK = 4, FASTRPC_CONTROL_PM = 5, }; struct fastrpc_ctrl_latency { Loading @@ -264,12 +265,17 @@ struct fastrpc_ctrl_wakelock { uint32_t enable; /* wakelock control enable */ }; struct fastrpc_ctrl_pm { uint32_t timeout; /* timeout(in ms) for PM to keep system awake*/ }; struct fastrpc_ioctl_control { uint32_t req; union { struct fastrpc_ctrl_latency lp; struct fastrpc_ctrl_kalloc kalloc; struct fastrpc_ctrl_wakelock wp; struct fastrpc_ctrl_pm pm; }; }; Loading Loading
drivers/char/adsprpc.c +39 −26 Original line number Diff line number Diff line Loading @@ -111,6 +111,9 @@ #define FASTRPC_STATIC_HANDLE_MAX (20) #define FASTRPC_LATENCY_CTRL_ENB (1) /* Maximum PM timeout that can be voted through fastrpc*/ #define MAX_PM_TIMEOUT_MS 50 /* timeout in us for busy polling after early response from remote processor */ #define FASTRPC_POLL_TIME (4000) Loading Loading @@ -285,7 +288,6 @@ struct smq_invoke_ctx { uint32_t earlyWakeTime; /* work done status flag */ bool isWorkDone; bool pm_awake_voted; }; struct fastrpc_ctx_lst { Loading Loading @@ -460,6 +462,8 @@ struct fastrpc_file { char *debug_buf; /* Flag to enable PM wake/relax voting for every remote invoke */ int wake_enable; struct wakeup_source *wake_source; uint32_t ws_timeout; }; static struct fastrpc_apps gfa; Loading Loading @@ -532,8 +536,7 @@ static struct fastrpc_channel_ctx gcinfo[NUM_CHANNELS] = { static int hlosvm[1] = {VMID_HLOS}; static int hlosvmperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC}; static void fastrpc_pm_awake(int fl_wake_enable, bool *pm_awake_voted); static void fastrpc_pm_relax(bool *pm_awake_voted); static void fastrpc_pm_awake(struct fastrpc_file *fl); static inline int64_t getnstimediff(struct timespec *start) { Loading Loading @@ -1364,7 +1367,6 @@ static int context_alloc(struct fastrpc_file *fl, uint32_t kernel, ctx->magic = FASTRPC_CTX_MAGIC; ctx->rspFlags = NORMAL_RESPONSE; ctx->isWorkDone = false; ctx->pm_awake_voted = false; spin_lock(&fl->hlock); hlist_add_head(&ctx->hn, &clst->pending); Loading Loading @@ -1444,7 +1446,7 @@ static void context_free(struct smq_invoke_ctx *ctx) static void context_notify_user(struct smq_invoke_ctx *ctx, int retval, uint32_t rspFlags, uint32_t earlyWakeTime) { fastrpc_pm_awake(ctx->fl->wake_enable, &ctx->pm_awake_voted); fastrpc_pm_awake(ctx->fl); ctx->retval = retval; switch (rspFlags) { case NORMAL_RESPONSE: Loading Loading @@ -2090,24 +2092,15 @@ static void fastrpc_init(struct fastrpc_apps *me) me->channel[CDSP_DOMAIN_ID].secure = NON_SECURE_CHANNEL; } static inline void fastrpc_pm_awake(int fl_wake_enable, bool *pm_awake_voted) { struct fastrpc_apps *me = &gfa; if (!fl_wake_enable || *pm_awake_voted) return; __pm_stay_awake(me->wake_source); *pm_awake_voted = true; } static inline void fastrpc_pm_relax(bool *pm_awake_voted) static inline void fastrpc_pm_awake(struct fastrpc_file *fl) { struct fastrpc_apps *me = &gfa; if (!(*pm_awake_voted)) if (!fl->wake_enable || !fl->wake_source) return; __pm_relax(me->wake_source); *pm_awake_voted = false; /* * Vote with PM to abort any suspend in progress and * keep system awake for specified timeout */ pm_wakeup_ws_event(fl->wake_source, fl->ws_timeout, true); } static inline int fastrpc_wait_for_response(struct smq_invoke_ctx *ctx, Loading Loading @@ -2229,9 +2222,7 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode, int err = 0, interrupted = 0, cid = fl->cid; struct timespec invoket = {0}; int64_t *perf_counter = NULL; bool pm_awake_voted = false; fastrpc_pm_awake(fl->wake_enable, &pm_awake_voted); if (fl->profile) { perf_counter = getperfcounter(fl, PERF_COUNT); getnstimeofday(&invoket); Loading Loading @@ -2300,9 +2291,7 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode, if (err) goto bail; wait: fastrpc_pm_relax(&pm_awake_voted); fastrpc_wait_for_completion(ctx, &interrupted, kernel); pm_awake_voted = ctx->pm_awake_voted; VERIFY(err, 0 == (err = interrupted)); if (err) goto bail; Loading Loading @@ -2341,7 +2330,6 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode, if (fl->profile && !interrupted) fastrpc_update_invoke_count(invoke->handle, perf_counter, &invoket); fastrpc_pm_relax(&pm_awake_voted); return err; } Loading Loading @@ -3503,6 +3491,8 @@ static int fastrpc_file_free(struct fastrpc_file *fl) spin_lock(&fl->apps->hlock); hlist_del_init(&fl->hn); spin_unlock(&fl->apps->hlock); if (fl->wake_source) wakeup_source_unregister(fl->wake_source); kfree(fl->debug_buf); if (!fl->sctx) { Loading Loading @@ -3890,6 +3880,11 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp) debugfs_file = debugfs_create_file(fl->debug_buf, 0644, debugfs_root, fl, &debugfs_fops); fl->wake_source = wakeup_source_register(fl->debug_buf); if (IS_ERR_OR_NULL(fl->wake_source)) { pr_err("adsprpc: Error: %s: %s: wakeup_source_register failed with err %ld\n", current->comm, __func__, PTR_ERR(fl->wake_source)); } context_list_ctor(&fl->clst); spin_lock_init(&fl->hlock); INIT_HLIST_HEAD(&fl->maps); Loading Loading @@ -4006,8 +4001,26 @@ static int fastrpc_internal_control(struct fastrpc_file *fl, cp->kalloc.kalloc_support = 1; break; case FASTRPC_CONTROL_WAKELOCK: if (fl->dev_minor != MINOR_NUM_SECURE_DEV) { pr_err("adsprpc: %s: %s: PM voting not allowed for non-secure device node %d\n", current->comm, __func__, fl->dev_minor); err = -EPERM; goto bail; } fl->wake_enable = cp->wp.enable; break; case FASTRPC_CONTROL_PM: if (!fl->wake_enable) { /* Kernel PM voting not requested by this application */ err = -EACCES; goto bail; } if (cp->pm.timeout > MAX_PM_TIMEOUT_MS) fl->ws_timeout = MAX_PM_TIMEOUT_MS; else fl->ws_timeout = cp->pm.timeout; fastrpc_pm_awake(fl); break; default: err = -EBADRQC; break; Loading
drivers/char/adsprpc_compat.c +16 −0 Original line number Diff line number Diff line Loading @@ -130,11 +130,21 @@ struct compat_fastrpc_ctrl_kalloc { compat_uint_t kalloc_support; /* Remote memory allocation from kernel */ }; struct compat_fastrpc_ctrl_wakelock { compat_uint_t enable; /* wakelock control enable */ }; struct compat_fastrpc_ctrl_pm { compat_uint_t timeout; /* timeout(in ms) for PM to keep system awake*/ }; struct compat_fastrpc_ioctl_control { compat_uint_t req; union { struct compat_fastrpc_ctrl_latency lp; struct compat_fastrpc_ctrl_kalloc kalloc; struct compat_fastrpc_ctrl_wakelock wp; struct compat_fastrpc_ctrl_pm pm; }; }; Loading Loading @@ -336,6 +346,12 @@ static int compat_get_fastrpc_ioctl_control( err |= put_user(p, &ctrl->lp.enable); err |= get_user(p, &ctrl32->lp.latency); err |= put_user(p, &ctrl->lp.latency); } else if (p == FASTRPC_CONTROL_WAKELOCK) { err |= get_user(p, &ctrl32->wp.enable); err |= put_user(p, &ctrl->wp.enable); } else if (p == FASTRPC_CONTROL_PM) { err |= get_user(p, &ctrl32->pm.timeout); err |= put_user(p, &ctrl->pm.timeout); } return err; Loading
drivers/char/adsprpc_shared.h +6 −0 Original line number Diff line number Diff line Loading @@ -249,6 +249,7 @@ enum fastrpc_control_type { FASTRPC_CONTROL_SMMU = 2, FASTRPC_CONTROL_KALLOC = 3, FASTRPC_CONTROL_WAKELOCK = 4, FASTRPC_CONTROL_PM = 5, }; struct fastrpc_ctrl_latency { Loading @@ -264,12 +265,17 @@ struct fastrpc_ctrl_wakelock { uint32_t enable; /* wakelock control enable */ }; struct fastrpc_ctrl_pm { uint32_t timeout; /* timeout(in ms) for PM to keep system awake*/ }; struct fastrpc_ioctl_control { uint32_t req; union { struct fastrpc_ctrl_latency lp; struct fastrpc_ctrl_kalloc kalloc; struct fastrpc_ctrl_wakelock wp; struct fastrpc_ctrl_pm pm; }; }; Loading