Loading drivers/char/adsprpc.c +66 −18 Original line number Diff line number Diff line Loading @@ -224,6 +224,7 @@ struct smq_invoke_ctx { struct fastrpc_buf *lbuf; size_t used; struct fastrpc_file *fl; uint32_t handle; uint32_t sc; struct overlap *overs; struct overlap **overps; Loading @@ -231,6 +232,7 @@ struct smq_invoke_ctx { uint32_t *crc; unsigned int magic; uint64_t ctxid; bool pm_awake_voted; }; struct fastrpc_ctx_lst { Loading Loading @@ -308,6 +310,7 @@ struct fastrpc_apps { spinlock_t ctxlock; struct smq_invoke_ctx *ctxtable[FASTRPC_CTX_MAX]; bool legacy_remote_heap; struct wakeup_source *wake_source; }; struct fastrpc_mmap { Loading Loading @@ -389,6 +392,8 @@ struct fastrpc_file { /* Identifies the device (MINOR_NUM_DEV / MINOR_NUM_SECURE_DEV) */ int dev_minor; char *debug_buf; /* Flag to enable PM wake/relax voting for every remote invoke */ int wake_enable; }; static struct fastrpc_apps gfa; Loading Loading @@ -446,6 +451,9 @@ 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 inline int64_t getnstimediff(struct timespec *start) { int64_t ns; Loading Loading @@ -1199,6 +1207,7 @@ static int context_alloc(struct fastrpc_file *fl, uint32_t kernel, goto bail; } ctx->crc = (uint32_t *)invokefd->crc; ctx->handle = invoke->handle; ctx->sc = invoke->sc; if (bufs) { VERIFY(err, 0 == context_build_overlap(ctx)); Loading @@ -1210,6 +1219,7 @@ static int context_alloc(struct fastrpc_file *fl, uint32_t kernel, ctx->tgid = fl->tgid; init_completion(&ctx->work); ctx->magic = FASTRPC_CTX_MAGIC; ctx->pm_awake_voted = false; spin_lock(&fl->hlock); hlist_add_head(&ctx->hn, &clst->pending); Loading Loading @@ -1280,6 +1290,7 @@ static void context_free(struct smq_invoke_ctx *ctx) static void context_notify_user(struct smq_invoke_ctx *ctx, int retval) { ctx->retval = retval; fastrpc_pm_awake(ctx->fl->wake_enable, &ctx->pm_awake_voted); complete(&ctx->work); } Loading Loading @@ -1872,7 +1883,25 @@ static void fastrpc_init(struct fastrpc_apps *me) me->channel[CDSP_DOMAIN_ID].secure = NON_SECURE_CHANNEL; } static int fastrpc_release_current_dsp_process(struct fastrpc_file *fl); 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) { struct fastrpc_apps *me = &gfa; if (!(*pm_awake_voted)) return; __pm_relax(me->wake_source); *pm_awake_voted = false; } static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode, uint32_t kernel, Loading @@ -1880,12 +1909,12 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode, { struct smq_invoke_ctx *ctx = NULL; struct fastrpc_ioctl_invoke *invoke = &inv->inv; int cid = fl->cid; int interrupted = 0; int err = 0; int err = 0, interrupted = 0, cid = fl->cid; struct timespec invoket = {0}; int64_t *perf_counter = getperfcounter(fl, PERF_COUNT); bool pm_awake_voted = false; fastrpc_pm_awake(fl->wake_enable, &pm_awake_voted); if (fl->profile) getnstimeofday(&invoket); Loading @@ -1900,7 +1929,7 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode, VERIFY(err, fl->cid >= 0 && fl->cid < NUM_CHANNELS && fl->sctx != NULL); if (err) { pr_err("adsprpc: ERROR: %s: user application %s domain is not set\n", pr_err("adsprpc: ERROR: %s: kernel session not initialized yet for %s\n", __func__, current->comm); err = -EBADR; goto bail; Loading Loading @@ -1946,14 +1975,16 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode, if (err) goto bail; wait: fastrpc_pm_relax(&pm_awake_voted); if (kernel) wait_for_completion(&ctx->work); else { else interrupted = wait_for_completion_interruptible(&ctx->work); pm_awake_voted = ctx->pm_awake_voted; VERIFY(err, 0 == (err = interrupted)); if (err) goto bail; } PERF(fl->profile, GET_COUNTER(perf_counter, PERF_INVARGS), inv_args(ctx); Loading Loading @@ -1990,6 +2021,7 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode, *count = *count+1; } } fastrpc_pm_relax(&pm_awake_voted); return err; } Loading Loading @@ -2760,9 +2792,12 @@ static int fastrpc_session_alloc_locked(struct fastrpc_channel_ctx *chan, break; } } VERIFY(err, idx < chan->sesscount); if (err) if (idx >= chan->sesscount) { err = -EUSERS; pr_err("adsprpc: ERROR %d: %s: max concurrent sessions limit (%d) already reached on %s\n", err, __func__, chan->sesscount, chan->subsys); goto bail; } chan->session[idx].smmu.faults = 0; } else { VERIFY(err, me->dev != NULL); Loading Loading @@ -3218,7 +3253,7 @@ static int fastrpc_channel_open(struct fastrpc_file *fl) VERIFY(err, fl && fl->sctx && fl->cid >= 0 && fl->cid < NUM_CHANNELS); if (err) { pr_err("adsprpc: ERROR: %s: user application %s domain is not set\n", pr_err("adsprpc: ERROR: %s: kernel session not initialized yet for %s\n", __func__, current->comm); err = -EBADR; return err; Loading Loading @@ -3361,8 +3396,8 @@ static int fastrpc_get_info(struct fastrpc_file *fl, uint32_t *info) fl->cid = cid; fl->ssrcount = fl->apps->channel[cid].ssrcount; mutex_lock(&fl->apps->channel[cid].smd_mutex); VERIFY(err, !fastrpc_session_alloc_locked( &fl->apps->channel[cid], 0, &fl->sctx)); err = fastrpc_session_alloc_locked(&fl->apps->channel[cid], 0, &fl->sctx); mutex_unlock(&fl->apps->channel[cid].smd_mutex); if (err) goto bail; Loading Loading @@ -3405,8 +3440,11 @@ static int fastrpc_internal_control(struct fastrpc_file *fl, case FASTRPC_CONTROL_KALLOC: cp->kalloc.kalloc_support = 1; break; case FASTRPC_CONTROL_WAKELOCK: fl->wake_enable = cp->wp.enable; break; default: err = -ENOTTY; err = -EBADRQC; break; } bail: Loading Loading @@ -4303,11 +4341,19 @@ static int __init fastrpc_device_init(void) err = register_rpmsg_driver(&fastrpc_rpmsg_client); if (err) { pr_err("adsprpc: register_rpmsg_driver: failed with err %d\n", err); pr_err("adsprpc: %s: register_rpmsg_driver failed with err %d\n", __func__, err); goto device_create_bail; } me->rpmsg_register = 1; me->wake_source = wakeup_source_register("adsprpc"); VERIFY(err, !IS_ERR_OR_NULL(me->wake_source)); if (err) { pr_err("adsprpc: Error: %s: wakeup_source_register failed with err %d\n", __func__, PTR_ERR(me->wake_source)); goto device_create_bail; } return 0; device_create_bail: for (i = 0; i < NUM_CHANNELS; i++) { Loading Loading @@ -4356,6 +4402,8 @@ static void __exit fastrpc_device_exit(void) unregister_chrdev_region(me->dev_no, NUM_CHANNELS); if (me->rpmsg_register == 1) unregister_rpmsg_driver(&fastrpc_rpmsg_client); if (me->wake_source) wakeup_source_unregister(me->wake_source); debugfs_remove_recursive(debugfs_root); } Loading drivers/char/adsprpc_shared.h +13 −3 Original line number Diff line number Diff line Loading @@ -241,22 +241,32 @@ struct fastrpc_ioctl_perf { /* kernel performance data */ uintptr_t keys; }; #define FASTRPC_CONTROL_LATENCY (1) enum fastrpc_control_type { FASTRPC_CONTROL_LATENCY = 1, FASTRPC_CONTROL_SMMU = 2, FASTRPC_CONTROL_KALLOC = 3, FASTRPC_CONTROL_WAKELOCK = 4, }; struct fastrpc_ctrl_latency { uint32_t enable; /* latency control enable */ uint32_t level; /* level of control */ }; #define FASTRPC_CONTROL_KALLOC (3) struct fastrpc_ctrl_kalloc { uint32_t kalloc_support; /* Remote memory allocation from kernel */ }; /* FASTRPC_CONTROL value 2 is reserved in user space */ struct fastrpc_ctrl_wakelock { uint32_t enable; /* wakelock control enable */ }; struct fastrpc_ioctl_control { uint32_t req; union { struct fastrpc_ctrl_latency lp; struct fastrpc_ctrl_kalloc kalloc; struct fastrpc_ctrl_wakelock wp; }; }; Loading Loading
drivers/char/adsprpc.c +66 −18 Original line number Diff line number Diff line Loading @@ -224,6 +224,7 @@ struct smq_invoke_ctx { struct fastrpc_buf *lbuf; size_t used; struct fastrpc_file *fl; uint32_t handle; uint32_t sc; struct overlap *overs; struct overlap **overps; Loading @@ -231,6 +232,7 @@ struct smq_invoke_ctx { uint32_t *crc; unsigned int magic; uint64_t ctxid; bool pm_awake_voted; }; struct fastrpc_ctx_lst { Loading Loading @@ -308,6 +310,7 @@ struct fastrpc_apps { spinlock_t ctxlock; struct smq_invoke_ctx *ctxtable[FASTRPC_CTX_MAX]; bool legacy_remote_heap; struct wakeup_source *wake_source; }; struct fastrpc_mmap { Loading Loading @@ -389,6 +392,8 @@ struct fastrpc_file { /* Identifies the device (MINOR_NUM_DEV / MINOR_NUM_SECURE_DEV) */ int dev_minor; char *debug_buf; /* Flag to enable PM wake/relax voting for every remote invoke */ int wake_enable; }; static struct fastrpc_apps gfa; Loading Loading @@ -446,6 +451,9 @@ 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 inline int64_t getnstimediff(struct timespec *start) { int64_t ns; Loading Loading @@ -1199,6 +1207,7 @@ static int context_alloc(struct fastrpc_file *fl, uint32_t kernel, goto bail; } ctx->crc = (uint32_t *)invokefd->crc; ctx->handle = invoke->handle; ctx->sc = invoke->sc; if (bufs) { VERIFY(err, 0 == context_build_overlap(ctx)); Loading @@ -1210,6 +1219,7 @@ static int context_alloc(struct fastrpc_file *fl, uint32_t kernel, ctx->tgid = fl->tgid; init_completion(&ctx->work); ctx->magic = FASTRPC_CTX_MAGIC; ctx->pm_awake_voted = false; spin_lock(&fl->hlock); hlist_add_head(&ctx->hn, &clst->pending); Loading Loading @@ -1280,6 +1290,7 @@ static void context_free(struct smq_invoke_ctx *ctx) static void context_notify_user(struct smq_invoke_ctx *ctx, int retval) { ctx->retval = retval; fastrpc_pm_awake(ctx->fl->wake_enable, &ctx->pm_awake_voted); complete(&ctx->work); } Loading Loading @@ -1872,7 +1883,25 @@ static void fastrpc_init(struct fastrpc_apps *me) me->channel[CDSP_DOMAIN_ID].secure = NON_SECURE_CHANNEL; } static int fastrpc_release_current_dsp_process(struct fastrpc_file *fl); 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) { struct fastrpc_apps *me = &gfa; if (!(*pm_awake_voted)) return; __pm_relax(me->wake_source); *pm_awake_voted = false; } static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode, uint32_t kernel, Loading @@ -1880,12 +1909,12 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode, { struct smq_invoke_ctx *ctx = NULL; struct fastrpc_ioctl_invoke *invoke = &inv->inv; int cid = fl->cid; int interrupted = 0; int err = 0; int err = 0, interrupted = 0, cid = fl->cid; struct timespec invoket = {0}; int64_t *perf_counter = getperfcounter(fl, PERF_COUNT); bool pm_awake_voted = false; fastrpc_pm_awake(fl->wake_enable, &pm_awake_voted); if (fl->profile) getnstimeofday(&invoket); Loading @@ -1900,7 +1929,7 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode, VERIFY(err, fl->cid >= 0 && fl->cid < NUM_CHANNELS && fl->sctx != NULL); if (err) { pr_err("adsprpc: ERROR: %s: user application %s domain is not set\n", pr_err("adsprpc: ERROR: %s: kernel session not initialized yet for %s\n", __func__, current->comm); err = -EBADR; goto bail; Loading Loading @@ -1946,14 +1975,16 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode, if (err) goto bail; wait: fastrpc_pm_relax(&pm_awake_voted); if (kernel) wait_for_completion(&ctx->work); else { else interrupted = wait_for_completion_interruptible(&ctx->work); pm_awake_voted = ctx->pm_awake_voted; VERIFY(err, 0 == (err = interrupted)); if (err) goto bail; } PERF(fl->profile, GET_COUNTER(perf_counter, PERF_INVARGS), inv_args(ctx); Loading Loading @@ -1990,6 +2021,7 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode, *count = *count+1; } } fastrpc_pm_relax(&pm_awake_voted); return err; } Loading Loading @@ -2760,9 +2792,12 @@ static int fastrpc_session_alloc_locked(struct fastrpc_channel_ctx *chan, break; } } VERIFY(err, idx < chan->sesscount); if (err) if (idx >= chan->sesscount) { err = -EUSERS; pr_err("adsprpc: ERROR %d: %s: max concurrent sessions limit (%d) already reached on %s\n", err, __func__, chan->sesscount, chan->subsys); goto bail; } chan->session[idx].smmu.faults = 0; } else { VERIFY(err, me->dev != NULL); Loading Loading @@ -3218,7 +3253,7 @@ static int fastrpc_channel_open(struct fastrpc_file *fl) VERIFY(err, fl && fl->sctx && fl->cid >= 0 && fl->cid < NUM_CHANNELS); if (err) { pr_err("adsprpc: ERROR: %s: user application %s domain is not set\n", pr_err("adsprpc: ERROR: %s: kernel session not initialized yet for %s\n", __func__, current->comm); err = -EBADR; return err; Loading Loading @@ -3361,8 +3396,8 @@ static int fastrpc_get_info(struct fastrpc_file *fl, uint32_t *info) fl->cid = cid; fl->ssrcount = fl->apps->channel[cid].ssrcount; mutex_lock(&fl->apps->channel[cid].smd_mutex); VERIFY(err, !fastrpc_session_alloc_locked( &fl->apps->channel[cid], 0, &fl->sctx)); err = fastrpc_session_alloc_locked(&fl->apps->channel[cid], 0, &fl->sctx); mutex_unlock(&fl->apps->channel[cid].smd_mutex); if (err) goto bail; Loading Loading @@ -3405,8 +3440,11 @@ static int fastrpc_internal_control(struct fastrpc_file *fl, case FASTRPC_CONTROL_KALLOC: cp->kalloc.kalloc_support = 1; break; case FASTRPC_CONTROL_WAKELOCK: fl->wake_enable = cp->wp.enable; break; default: err = -ENOTTY; err = -EBADRQC; break; } bail: Loading Loading @@ -4303,11 +4341,19 @@ static int __init fastrpc_device_init(void) err = register_rpmsg_driver(&fastrpc_rpmsg_client); if (err) { pr_err("adsprpc: register_rpmsg_driver: failed with err %d\n", err); pr_err("adsprpc: %s: register_rpmsg_driver failed with err %d\n", __func__, err); goto device_create_bail; } me->rpmsg_register = 1; me->wake_source = wakeup_source_register("adsprpc"); VERIFY(err, !IS_ERR_OR_NULL(me->wake_source)); if (err) { pr_err("adsprpc: Error: %s: wakeup_source_register failed with err %d\n", __func__, PTR_ERR(me->wake_source)); goto device_create_bail; } return 0; device_create_bail: for (i = 0; i < NUM_CHANNELS; i++) { Loading Loading @@ -4356,6 +4402,8 @@ static void __exit fastrpc_device_exit(void) unregister_chrdev_region(me->dev_no, NUM_CHANNELS); if (me->rpmsg_register == 1) unregister_rpmsg_driver(&fastrpc_rpmsg_client); if (me->wake_source) wakeup_source_unregister(me->wake_source); debugfs_remove_recursive(debugfs_root); } Loading
drivers/char/adsprpc_shared.h +13 −3 Original line number Diff line number Diff line Loading @@ -241,22 +241,32 @@ struct fastrpc_ioctl_perf { /* kernel performance data */ uintptr_t keys; }; #define FASTRPC_CONTROL_LATENCY (1) enum fastrpc_control_type { FASTRPC_CONTROL_LATENCY = 1, FASTRPC_CONTROL_SMMU = 2, FASTRPC_CONTROL_KALLOC = 3, FASTRPC_CONTROL_WAKELOCK = 4, }; struct fastrpc_ctrl_latency { uint32_t enable; /* latency control enable */ uint32_t level; /* level of control */ }; #define FASTRPC_CONTROL_KALLOC (3) struct fastrpc_ctrl_kalloc { uint32_t kalloc_support; /* Remote memory allocation from kernel */ }; /* FASTRPC_CONTROL value 2 is reserved in user space */ struct fastrpc_ctrl_wakelock { uint32_t enable; /* wakelock control enable */ }; struct fastrpc_ioctl_control { uint32_t req; union { struct fastrpc_ctrl_latency lp; struct fastrpc_ctrl_kalloc kalloc; struct fastrpc_ctrl_wakelock wp; }; }; Loading