diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 5e66551dcaa3..54f137a3f78a 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. */ #include #include @@ -156,6 +156,8 @@ (int64_t *)(perf_ptr + offset)\ : (int64_t *)NULL) : (int64_t *)NULL) +#define IS_ASYNC_FASTRPC_AVAILABLE (0) + static int fastrpc_pdr_notifier_cb(struct notifier_block *nb, unsigned long code, void *data); @@ -2709,36 +2711,62 @@ bail: } static int fastrpc_get_info_from_kernel( - struct fastrpc_ioctl_dsp_capabilities *dsp_cap, + struct fastrpc_ioctl_remote_dsp_capability *dsp_cap, struct fastrpc_file *fl) { int err = 0; uint32_t domain_support; uint32_t domain = dsp_cap->domain; + uint32_t async_capability = IS_ASYNC_FASTRPC_AVAILABLE; + struct fastrpc_dsp_capabilities *dsp_cap_ptr; - if (!gcinfo[domain].dsp_cap_kernel.is_cached) { + VERIFY(err, dsp_cap->domain < NUM_CHANNELS); + + /* + * Check if number of attribute IDs obtained from userspace + * is less than the number of attribute IDs supported by + * kernel + */ + if (dsp_cap->attribute_ID >= FASTRPC_MAX_DSP_ATTRIBUTES) { + err = EOVERFLOW; + dsp_cap->capability = 0; + goto bail; + } + + dsp_cap_ptr = &gcinfo[domain].dsp_cap_kernel; + + if (!dsp_cap_ptr->is_cached) { /* * Information not on kernel, query device for information * and cache on kernel */ - err = fastrpc_get_info_from_dsp(fl, dsp_cap->dsp_attributes, - FASTRPC_MAX_DSP_ATTRIBUTES - 1, - domain); + err = fastrpc_get_info_from_dsp(fl, + dsp_cap_ptr->dsp_attributes, + FASTRPC_MAX_DSP_ATTRIBUTES - 1, + domain); if (err) goto bail; - domain_support = dsp_cap->dsp_attributes[0]; + domain_support = + dsp_cap_ptr->dsp_attributes[0]; + switch (domain_support) { case 0: - memset(dsp_cap->dsp_attributes, 0, - sizeof(dsp_cap->dsp_attributes)); - memset(&gcinfo[domain].dsp_cap_kernel.dsp_attributes, - 0, sizeof(dsp_cap->dsp_attributes)); + memset(&dsp_cap_ptr->dsp_attributes, + 0, + sizeof(dsp_cap_ptr->dsp_attributes)); + memset(&dsp_cap->capability, + 0, sizeof(dsp_cap->capability)); break; case 1: - memcpy(&gcinfo[domain].dsp_cap_kernel.dsp_attributes, - dsp_cap->dsp_attributes, - sizeof(dsp_cap->dsp_attributes)); + async_capability = + async_capability && + dsp_cap_ptr->dsp_attributes[ASYNC_FASTRPC_CAP]; + dsp_cap_ptr->dsp_attributes[ASYNC_FASTRPC_CAP] = + async_capability; + memcpy(&dsp_cap->capability, + &dsp_cap_ptr->dsp_attributes[dsp_cap->attribute_ID], + sizeof(dsp_cap->capability)); break; default: err = -1; @@ -2746,19 +2774,19 @@ static int fastrpc_get_info_from_kernel( * Reset is_cached flag to 0 so subsequent calls * can try to query dsp again */ - gcinfo[domain].dsp_cap_kernel.is_cached = 0; + dsp_cap_ptr->is_cached = 0; pr_warn("adsprpc: %s: %s: returned bad domain support value %d\n", current->comm, __func__, domain_support); goto bail; } - gcinfo[domain].dsp_cap_kernel.is_cached = 1; + dsp_cap_ptr->is_cached = 1; } else { // Information on Kernel, pass it to user - memcpy(dsp_cap->dsp_attributes, - &gcinfo[domain].dsp_cap_kernel.dsp_attributes, - sizeof(dsp_cap->dsp_attributes)); + memcpy(&dsp_cap->capability, + &dsp_cap_ptr->dsp_attributes[dsp_cap->attribute_ID], + sizeof(dsp_cap->capability)); } bail: return err; @@ -4041,13 +4069,15 @@ static int fastrpc_control(struct fastrpc_ioctl_control *cp, bail: return err; } -static int fastrpc_get_dsp_info(struct fastrpc_ioctl_dsp_capabilities *dsp_cap, - void *param, struct fastrpc_file *fl) + +static int fastrpc_get_dsp_info( + struct fastrpc_ioctl_remote_dsp_capability *dsp_cap, + void *param, struct fastrpc_file *fl) { int err = 0; K_COPY_FROM_USER(err, 0, dsp_cap, param, - sizeof(struct fastrpc_ioctl_dsp_capabilities)); + sizeof(struct fastrpc_ioctl_remote_dsp_capability)); VERIFY(err, dsp_cap->domain < NUM_CHANNELS); if (err) goto bail; @@ -4055,8 +4085,13 @@ static int fastrpc_get_dsp_info(struct fastrpc_ioctl_dsp_capabilities *dsp_cap, err = fastrpc_get_info_from_kernel(dsp_cap, fl); if (err) goto bail; - K_COPY_TO_USER(err, 0, param, dsp_cap, - sizeof(struct fastrpc_ioctl_dsp_capabilities)); + K_COPY_TO_USER( + err, + 0, + &((struct fastrpc_ioctl_remote_dsp_capability *) + param)->capability, + &dsp_cap->capability, + sizeof(dsp_cap->capability)); bail: return err; } @@ -4074,7 +4109,7 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num, struct fastrpc_ioctl_init_attrs init; struct fastrpc_ioctl_perf perf; struct fastrpc_ioctl_control cp; - struct fastrpc_ioctl_dsp_capabilities dsp_cap; + struct fastrpc_ioctl_remote_dsp_capability dsp_cap; } p; union { struct fastrpc_ioctl_mmap mmap; diff --git a/drivers/char/adsprpc_compat.c b/drivers/char/adsprpc_compat.c index 8c01385f56bd..845768db908b 100644 --- a/drivers/char/adsprpc_compat.c +++ b/drivers/char/adsprpc_compat.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2020, The Linux Foundation. All rights reserved. */ #include #include @@ -35,7 +35,8 @@ #define COMPAT_FASTRPC_IOCTL_MUNMAP_64 \ _IOWR('R', 15, struct compat_fastrpc_ioctl_munmap_64) #define COMPAT_FASTRPC_IOCTL_GET_DSP_INFO \ - _IOWR('R', 16, struct compat_fastrpc_ioctl_dsp_capabilities) + _IOWR('R', 17, \ + struct compat_fastrpc_ioctl_remote_dsp_capability) struct compat_remote_buf { compat_uptr_t pv; /* buffer pointer */ @@ -138,9 +139,22 @@ struct compat_fastrpc_ioctl_control { }; }; -struct compat_fastrpc_ioctl_dsp_capabilities { - compat_uint_t domain; /* DSP domain to query capabilities */ - compat_uint_t dsp_attributes[FASTRPC_MAX_DSP_ATTRIBUTES]; +struct compat_fastrpc_ioctl_remote_dsp_capability { + /* + * @param[in]: DSP domain ADSP_DOMAIN_ID, + * SDSP_DOMAIN_ID, or CDSP_DOMAIN_ID + */ + compat_uint_t domain; + /* + * @param[in]: One of the DSP attributes + * from enum remote_dsp_attributes + */ + compat_uint_t attribute_ID; + /* + * @param[out]: Result of the DSP + * capability query based on attribute_ID + */ + compat_uint_t capability; }; static int compat_get_fastrpc_ioctl_invoke( @@ -382,19 +396,14 @@ static int compat_get_fastrpc_ioctl_init( } static int compat_put_fastrpc_ioctl_get_dsp_info( - struct compat_fastrpc_ioctl_dsp_capabilities __user *info32, - struct fastrpc_ioctl_dsp_capabilities __user *info) + struct compat_fastrpc_ioctl_remote_dsp_capability __user *info32, + struct fastrpc_ioctl_remote_dsp_capability __user *info) { - compat_uint_t u, *dsp_attr, *dsp_attr_32; - int err, ii; - - dsp_attr = info->dsp_attributes; - dsp_attr_32 = info32->dsp_attributes; - for (ii = 0, err = 0; ii < FASTRPC_MAX_DSP_ATTRIBUTES; ii++) { - err |= get_user(u, dsp_attr++); - err |= put_user(u, dsp_attr_32++); - } + compat_uint_t u; + int err = 0; + err |= get_user(u, &info->capability); + err |= put_user(u, &info32->capability); return err; } @@ -466,8 +475,8 @@ static int compat_fastrpc_getperf(struct file *filp, static int compat_fastrpc_get_dsp_info(struct file *filp, unsigned long arg) { - struct compat_fastrpc_ioctl_dsp_capabilities __user *info32; - struct fastrpc_ioctl_dsp_capabilities *info; + struct compat_fastrpc_ioctl_remote_dsp_capability __user *info32; + struct fastrpc_ioctl_remote_dsp_capability *info; compat_uint_t u; long ret; int err = 0; diff --git a/drivers/char/adsprpc_shared.h b/drivers/char/adsprpc_shared.h index 8673a04639a2..2469fbead694 100644 --- a/drivers/char/adsprpc_shared.h +++ b/drivers/char/adsprpc_shared.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. */ #ifndef ADSPRPC_SHARED_H #define ADSPRPC_SHARED_H @@ -24,7 +24,7 @@ #define FASTRPC_IOCTL_CONTROL _IOWR('R', 12, struct fastrpc_ioctl_control) #define FASTRPC_IOCTL_MUNMAP_FD _IOWR('R', 13, struct fastrpc_ioctl_munmap_fd) #define FASTRPC_IOCTL_GET_DSP_INFO \ - _IOWR('R', 16, struct fastrpc_ioctl_dsp_capabilities) + _IOWR('R', 17, struct fastrpc_ioctl_remote_dsp_capability) #define FASTRPC_GLINK_GUID "fastrpcglink-apps-dsp" #define FASTRPC_SMD_GUID "fastrpcsmd-apps-dsp" @@ -263,10 +263,13 @@ struct fastrpc_ioctl_control { }; }; -#define FASTRPC_MAX_DSP_ATTRIBUTES (7) -struct fastrpc_ioctl_dsp_capabilities { - uint32_t domain; //! DSP domain to query capabilities - uint32_t dsp_attributes[FASTRPC_MAX_DSP_ATTRIBUTES]; +#define FASTRPC_MAX_DSP_ATTRIBUTES (9) +#define ASYNC_FASTRPC_CAP (8) + +struct fastrpc_ioctl_remote_dsp_capability { + uint32_t domain; + uint32_t attribute_ID; + uint32_t capability; }; struct smq_null_invoke {