diff options
| -rw-r--r-- | arch/arm64/configs/msm-auto-perf_defconfig | 1 | ||||
| -rw-r--r-- | drivers/char/adsprpc.c | 8 | ||||
| -rw-r--r-- | drivers/devfreq/governor_msm_adreno_tz.c | 10 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/ekms/edrm_drv.c | 35 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c | 7 | ||||
| -rw-r--r-- | drivers/gpu/msm/adreno_dispatch.c | 18 | ||||
| -rw-r--r-- | drivers/hid/hid-core.c | 55 | ||||
| -rw-r--r-- | drivers/misc/qseecom.c | 3 | ||||
| -rw-r--r-- | drivers/net/wireless/cnss2/pci.c | 13 | ||||
| -rw-r--r-- | drivers/soc/qcom/peripheral-loader.c | 20 | ||||
| -rw-r--r-- | drivers/soc/qcom/peripheral-loader.h | 4 | ||||
| -rw-r--r-- | drivers/soc/qcom/pil-msa.c | 23 | ||||
| -rw-r--r-- | drivers/soc/qcom/subsys-pil-tz.c | 5 | ||||
| -rw-r--r-- | include/linux/hid.h | 2 | ||||
| -rw-r--r-- | include/net/cnss2.h | 3 | ||||
| -rw-r--r-- | sound/soc/msm/qdsp6v2/msm-pcm-loopback-v2.c | 13 | ||||
| -rw-r--r-- | sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c | 56 | ||||
| -rw-r--r-- | sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c | 107 | ||||
| -rw-r--r-- | sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h | 1 | ||||
| -rw-r--r-- | sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c | 10 |
20 files changed, 297 insertions, 97 deletions
diff --git a/arch/arm64/configs/msm-auto-perf_defconfig b/arch/arm64/configs/msm-auto-perf_defconfig index 1c83060d2d2f..f5130c4c4611 100644 --- a/arch/arm64/configs/msm-auto-perf_defconfig +++ b/arch/arm64/configs/msm-auto-perf_defconfig @@ -329,6 +329,7 @@ CONFIG_SENSORS_BMG_FIFO=y # CONFIG_LEGACY_PTYS is not set # CONFIG_DEVMEM is not set # CONFIG_DEVKMEM is not set +CONFIG_SERIAL_MSM=y CONFIG_SERIAL_MSM_HS=y CONFIG_SERIAL_MSM_SMD=y CONFIG_DIAG_CHAR=y diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index b898007c63d9..23b48dc6981b 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -479,6 +479,10 @@ static int fastrpc_mmap_find(struct fastrpc_file *fl, int fd, uintptr_t va, if (va >= map->va && va + len <= map->va + map->len && map->fd == fd) { + if (map->refs + 1 == INT_MAX) { + spin_unlock(&me->hlock); + return -ETOOMANYREFS; + } map->refs++; match = map; break; @@ -491,6 +495,10 @@ static int fastrpc_mmap_find(struct fastrpc_file *fl, int fd, uintptr_t va, if (va >= map->va && va + len <= map->va + map->len && map->fd == fd) { + if (map->refs + 1 == INT_MAX) { + spin_unlock(&fl->hlock); + return -ETOOMANYREFS; + } map->refs++; match = map; break; diff --git a/drivers/devfreq/governor_msm_adreno_tz.c b/drivers/devfreq/governor_msm_adreno_tz.c index f31089d63e0c..4c010654204c 100644 --- a/drivers/devfreq/governor_msm_adreno_tz.c +++ b/drivers/devfreq/governor_msm_adreno_tz.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2017, 2019 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -150,6 +150,8 @@ void compute_work_load(struct devfreq_dev_status *stats, struct devfreq_msm_adreno_tz_data *priv, struct devfreq *devfreq) { + u64 busy; + spin_lock(&sample_lock); /* * Keep collecting the stats till the client @@ -157,8 +159,10 @@ void compute_work_load(struct devfreq_dev_status *stats, * is done when the entry is read */ acc_total += stats->total_time; - acc_relative_busy += (stats->busy_time * stats->current_frequency) / - devfreq->profile->freq_table[0]; + busy = (u64)stats->busy_time * stats->current_frequency; + do_div(busy, devfreq->profile->freq_table[0]); + acc_relative_busy += busy; + spin_unlock(&sample_lock); } diff --git a/drivers/gpu/drm/msm/ekms/edrm_drv.c b/drivers/gpu/drm/msm/ekms/edrm_drv.c index 144dd231e428..69b8c01e59d4 100644 --- a/drivers/gpu/drm/msm/ekms/edrm_drv.c +++ b/drivers/gpu/drm/msm/ekms/edrm_drv.c @@ -23,9 +23,6 @@ #include "msm_mmu.h" #include "edrm_kms.h" -static struct completion wait_display_completion; -static bool msm_edrm_probed; - static int msm_edrm_unload(struct drm_device *dev) { struct msm_drm_private *priv = dev->dev_private; @@ -331,8 +328,6 @@ static int msm_pdev_edrm_probe(struct platform_device *pdev) struct msm_drm_private *master_priv; struct msm_kms *master_kms; - msm_edrm_probed = true; - /* main DRM's minor ID is zero */ minor = drm_minor_acquire(0); if (IS_ERR(minor)) { @@ -372,7 +367,6 @@ static int msm_pdev_edrm_probe(struct platform_device *pdev) if (ret) DRM_ERROR("drm_platform_init failed: %d\n", ret); - complete(&wait_display_completion); return ret; } @@ -414,20 +408,6 @@ static const struct of_device_id dt_match[] = { }; MODULE_DEVICE_TABLE(of, dt_match); -static int find_match(struct device *dev, void *data) -{ - struct device_driver *drv = data; - - return drv->bus->match(dev, drv); -} - -static bool find_device(struct platform_driver *pdrv) -{ - struct device_driver *drv = &pdrv->driver; - - return bus_for_each_dev(drv->bus, NULL, drv, find_match); -} - static struct platform_driver msm_platform_driver = { .probe = msm_pdev_edrm_probe, .remove = msm_pdev_edrm_remove, @@ -443,7 +423,6 @@ static struct platform_driver msm_platform_driver = { static int __init msm_edrm_register(void) { DBG("init"); - init_completion(&wait_display_completion); return platform_driver_register(&msm_platform_driver); } @@ -453,22 +432,8 @@ static void __exit msm_edrm_unregister(void) platform_driver_unregister(&msm_platform_driver); } -static int __init msm_edrm_late_register(void) -{ - struct platform_driver *pdrv; - - pdrv = &msm_platform_driver; - if (msm_edrm_probed || find_device(pdrv)) { - pr_debug("wait for eDRM display probe completion\n"); - wait_for_completion(&wait_display_completion); - } - return 0; -} - module_init(msm_edrm_register); module_exit(msm_edrm_unregister); -/* init level 7 */ -late_initcall(msm_edrm_late_register); MODULE_DESCRIPTION("MSM EARLY DRM Driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c index 5a9e56b58158..d755ba959c20 100644 --- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c +++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c @@ -78,7 +78,12 @@ static ssize_t _sde_hdmi_debugfs_dump_info_read(struct file *file, if (!buf) return -ENOMEM; - len += snprintf(buf, SZ_4K, "name = %s\n", display->name); + len += snprintf(buf, SZ_1K, "name = %s\n", display->name); + + if (len > count) { + kfree(buf); + return -ENOMEM; + } if (copy_to_user(buff, buf, len)) { kfree(buf); diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c index 002722f75c6c..49b14fbf439c 100644 --- a/drivers/gpu/msm/adreno_dispatch.c +++ b/drivers/gpu/msm/adreno_dispatch.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1405,6 +1405,22 @@ int adreno_dispatcher_queue_cmds(struct kgsl_device_private *dev_priv, user_ts = *timestamp; + /* + * If there is only one drawobj in the array and it is of + * type SYNCOBJ_TYPE, skip comparing user_ts as it can be 0 + */ + if (!(count == 1 && drawobj[0]->type == SYNCOBJ_TYPE) && + (drawctxt->base.flags & KGSL_CONTEXT_USER_GENERATED_TS)) { + /* + * User specified timestamps need to be greater than the last + * issued timestamp in the context + */ + if (timestamp_cmp(drawctxt->timestamp, user_ts) >= 0) { + spin_unlock(&drawctxt->lock); + return -ERANGE; + } + } + for (i = 0; i < count; i++) { switch (drawobj[i]->type) { diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 7f6c13740f4f..a22881befa27 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -200,13 +200,22 @@ static unsigned hid_lookup_collection(struct hid_parser *parser, unsigned type) * Add a usage to the temporary parser table. */ -static int hid_add_usage(struct hid_parser *parser, unsigned usage) +static int hid_add_usage(struct hid_parser *parser, unsigned usage, u8 size) { if (parser->local.usage_index >= HID_MAX_USAGES) { hid_err(parser->device, "usage index exceeded\n"); return -1; } - parser->local.usage[parser->local.usage_index] = usage; + if (!parser->local.usage_index && parser->global.usage_page) + parser->local.usage_page_preceding = 1; + if (parser->local.usage_page_preceding == 2) + parser->local.usage_page_preceding = 3; + if (size <= 2 && parser->global.usage_page) + parser->local.usage[parser->local.usage_index] = + (usage & 0xffff) + (parser->global.usage_page << 16); + else + parser->local.usage[parser->local.usage_index] = usage; + parser->local.usage_size[parser->local.usage_index] = size; parser->local.collection_index[parser->local.usage_index] = parser->collection_stack_ptr ? parser->collection_stack[parser->collection_stack_ptr - 1] : 0; @@ -345,6 +354,8 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item) case HID_GLOBAL_ITEM_TAG_USAGE_PAGE: parser->global.usage_page = item_udata(item); + if (parser->local.usage_page_preceding == 1) + parser->local.usage_page_preceding = 2; return 0; case HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM: @@ -463,10 +474,7 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item) return 0; } - if (item->size <= 2) - data = (parser->global.usage_page << 16) + data; - - return hid_add_usage(parser, data); + return hid_add_usage(parser, data, item->size); case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM: @@ -475,9 +483,6 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item) return 0; } - if (item->size <= 2) - data = (parser->global.usage_page << 16) + data; - parser->local.usage_minimum = data; return 0; @@ -488,9 +493,6 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item) return 0; } - if (item->size <= 2) - data = (parser->global.usage_page << 16) + data; - count = data - parser->local.usage_minimum; if (count + parser->local.usage_index >= HID_MAX_USAGES) { /* @@ -510,7 +512,7 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item) } for (n = parser->local.usage_minimum; n <= data; n++) - if (hid_add_usage(parser, n)) { + if (hid_add_usage(parser, n, item->size)) { dbg_hid("hid_add_usage failed\n"); return -1; } @@ -525,6 +527,29 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item) } /* + * Concatenate Usage Pages into Usages where relevant: + * As per specification, 6.2.2.8: "When the parser encounters a main item it + * concatenates the last declared Usage Page with a Usage to form a complete + * usage value." + */ + +static void hid_concatenate_usage_page(struct hid_parser *parser) +{ + int i; + + if (parser->local.usage_page_preceding == 3) { + dbg_hid("Using preceding usage page for final usage\n"); + return; + } + + for (i = 0; i < parser->local.usage_index; i++) + if (parser->local.usage_size[i] <= 2) + parser->local.usage[i] = + (parser->global.usage_page << 16) + + (parser->local.usage[i] & 0xffff); +} + +/* * Process a main item. */ @@ -533,6 +558,8 @@ static int hid_parser_main(struct hid_parser *parser, struct hid_item *item) __u32 data; int ret; + hid_concatenate_usage_page(parser); + data = item_udata(item); switch (item->tag) { @@ -746,6 +773,8 @@ static int hid_scan_main(struct hid_parser *parser, struct hid_item *item) __u32 data; int i; + hid_concatenate_usage_page(parser); + data = item_udata(item); switch (item->tag) { diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index dfa3bb6b186f..d50144e0fed9 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -2533,7 +2533,8 @@ static int qseecom_unmap_ion_allocated_memory(struct qseecom_dev_handle *data) if (!IS_ERR_OR_NULL(data->client.ihandle)) { ion_unmap_kernel(qseecom.ion_clnt, data->client.ihandle); ion_free(qseecom.ion_clnt, data->client.ihandle); - data->client.ihandle = NULL; + memset((void *)&data->client, + 0, sizeof(struct qseecom_client_handle)); } return ret; } diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c index 7dc419753a80..099aa9d38bb8 100644 --- a/drivers/net/wireless/cnss2/pci.c +++ b/drivers/net/wireless/cnss2/pci.c @@ -56,6 +56,7 @@ #ifdef CONFIG_PCI_MSM static DEFINE_SPINLOCK(pci_link_down_lock); #endif +static DEFINE_SPINLOCK(pci_reg_window_lock); static unsigned int pci_link_down_panic; module_param(pci_link_down_panic, uint, 0600); @@ -268,6 +269,18 @@ int cnss_pci_is_device_down(struct device *dev) } EXPORT_SYMBOL(cnss_pci_is_device_down); +void cnss_pci_lock_reg_window(struct device *dev, unsigned long *flags) +{ + spin_lock_bh(&pci_reg_window_lock); +} +EXPORT_SYMBOL(cnss_pci_lock_reg_window); + +void cnss_pci_unlock_reg_window(struct device *dev, unsigned long *flags) +{ + spin_unlock_bh(&pci_reg_window_lock); +} +EXPORT_SYMBOL(cnss_pci_unlock_reg_window); + int cnss_pci_recovery_update_status(struct cnss_pci_data *pci_priv) { struct cnss_plat_data *plat_priv; diff --git a/drivers/soc/qcom/peripheral-loader.c b/drivers/soc/qcom/peripheral-loader.c index 32a457730869..2a3b2a313c69 100644 --- a/drivers/soc/qcom/peripheral-loader.c +++ b/drivers/soc/qcom/peripheral-loader.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -980,7 +980,9 @@ int pil_boot(struct pil_desc *desc) trace_pil_event("before_init_image", desc); if (desc->ops->init_image) - ret = desc->ops->init_image(desc, fw->data, fw->size); + ret = desc->ops->init_image(desc, fw->data, fw->size, + priv->region_start, + priv->region_end - priv->region_start); if (ret) { pil_err(desc, "Initializing image failed(rc:%d)\n", ret); subsys_set_error(desc->subsys_dev, firmware_error_msg); @@ -997,20 +999,6 @@ int pil_boot(struct pil_desc *desc) } if (desc->subsys_vmid > 0) { - /** - * In case of modem ssr, we need to assign memory back to linux. - * This is not true after cold boot since linux already owns it. - * Also for secure boot devices, modem memory has to be released - * after MBA is booted - */ - trace_pil_event("before_assign_mem", desc); - if (desc->modem_ssr) { - ret = pil_assign_mem_to_linux(desc, priv->region_start, - (priv->region_end - priv->region_start)); - if (ret) - pil_err(desc, "Failed to assign to linux, ret- %d\n", - ret); - } ret = pil_assign_mem_to_subsys_and_linux(desc, priv->region_start, (priv->region_end - priv->region_start)); diff --git a/drivers/soc/qcom/peripheral-loader.h b/drivers/soc/qcom/peripheral-loader.h index 6e74743c8c21..6800fd83944a 100644 --- a/drivers/soc/qcom/peripheral-loader.h +++ b/drivers/soc/qcom/peripheral-loader.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2017, 2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -116,7 +116,7 @@ struct md_ssr_toc /* Shared IMEM ToC struct */ */ struct pil_reset_ops { int (*init_image)(struct pil_desc *pil, const u8 *metadata, - size_t size); + size_t size, phys_addr_t addr, size_t sz); int (*mem_setup)(struct pil_desc *pil, phys_addr_t addr, size_t size); int (*verify_blob)(struct pil_desc *pil, phys_addr_t phy_addr, size_t size); diff --git a/drivers/soc/qcom/pil-msa.c b/drivers/soc/qcom/pil-msa.c index f7d183a7bbcc..b7f55bbfe267 100644 --- a/drivers/soc/qcom/pil-msa.c +++ b/drivers/soc/qcom/pil-msa.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -685,7 +685,7 @@ err_invalid_fw: } static int pil_msa_auth_modem_mdt(struct pil_desc *pil, const u8 *metadata, - size_t size) + size_t size, phys_addr_t phy_addr, size_t phy_sz) { struct modem_data *drv = dev_get_drvdata(pil->dev); void *mdata_virt; @@ -715,6 +715,19 @@ static int pil_msa_auth_modem_mdt(struct pil_desc *pil, const u8 *metadata, wmb(); if (pil->subsys_vmid > 0) { + /** + * In case of modem ssr,we need to assign memory back to linux. + * This is not true after cold boot since linux already owns + * it. Also for secure boot devices, modem memory has to be + * released after MBA is booted + */ + if (pil->modem_ssr) { + ret = pil_assign_mem_to_linux(pil, phy_addr, phy_sz); + if (ret) + dev_err(pil->dev, + "Failed to assign to linux, ret- %d\n", + ret); + } ret = pil_assign_mem_to_subsys(pil, mdata_phys, ALIGN(size, SZ_4K)); if (ret) { @@ -769,7 +782,8 @@ fail: } static int pil_msa_mss_reset_mba_load_auth_mdt(struct pil_desc *pil, - const u8 *metadata, size_t size) + const u8 *metadata, size_t size, + phys_addr_t modem_reg, size_t sz_modem_reg) { int ret; @@ -777,7 +791,8 @@ static int pil_msa_mss_reset_mba_load_auth_mdt(struct pil_desc *pil, if (ret) return ret; - return pil_msa_auth_modem_mdt(pil, metadata, size); + return pil_msa_auth_modem_mdt(pil, metadata, size, + modem_reg, sz_modem_reg); } static int pil_msa_mba_verify_blob(struct pil_desc *pil, phys_addr_t phy_addr, diff --git a/drivers/soc/qcom/subsys-pil-tz.c b/drivers/soc/qcom/subsys-pil-tz.c index b448f5297f95..c6dff952ff3a 100644 --- a/drivers/soc/qcom/subsys-pil-tz.c +++ b/drivers/soc/qcom/subsys-pil-tz.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2017, 2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -582,7 +582,8 @@ static void pil_remove_proxy_vote(struct pil_desc *pil) } static int pil_init_image_trusted(struct pil_desc *pil, - const u8 *metadata, size_t size) + const u8 *metadata, size_t size, + phys_addr_t addr, size_t sz) { struct pil_tz_data *d = desc_to_data(pil); struct pas_init_image_req { diff --git a/include/linux/hid.h b/include/linux/hid.h index d16de62231d3..e558919bd86a 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -378,11 +378,13 @@ struct hid_global { struct hid_local { unsigned usage[HID_MAX_USAGES]; /* usage array */ + u8 usage_size[HID_MAX_USAGES]; /* usage size array */ unsigned collection_index[HID_MAX_USAGES]; /* collection index array */ unsigned usage_index; unsigned usage_minimum; unsigned delimiter_depth; unsigned delimiter_branch; + unsigned int usage_page_preceding; }; /* diff --git a/include/net/cnss2.h b/include/net/cnss2.h index 5ed1b05277b1..4a541581f9d7 100644 --- a/include/net/cnss2.h +++ b/include/net/cnss2.h @@ -245,6 +245,9 @@ extern void cnss_request_pm_qos(struct device *dev, u32 qos_val); extern void cnss_remove_pm_qos(struct device *dev); extern void cnss_lock_pm_sem(struct device *dev); extern void cnss_release_pm_sem(struct device *dev); +extern void cnss_pci_lock_reg_window(struct device *dev, unsigned long *flags); +extern void cnss_pci_unlock_reg_window(struct device *dev, + unsigned long *flags); extern int cnss_auto_suspend(struct device *dev); extern int cnss_auto_resume(struct device *dev); extern int cnss_pci_is_drv_connected(struct device *dev); diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-loopback-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-loopback-v2.c index 2fbefa7b42dc..0add46fb979f 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-loopback-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-loopback-v2.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -177,6 +177,7 @@ static int msm_loopback_session_mute_put(struct snd_kcontrol *kcontrol, goto done; } + mutex_lock(&loopback_session_lock); pr_debug("%s: mute=%d\n", __func__, mute); hfp_tx_mute = mute; for (n = 0; n < LOOPBACK_SESSION_MAX; n++) { @@ -189,6 +190,7 @@ static int msm_loopback_session_mute_put(struct snd_kcontrol *kcontrol, pr_err("%s: Send mute command failed rc=%d\n", __func__, ret); } + mutex_unlock(&loopback_session_lock); done: return ret; } @@ -381,6 +383,8 @@ static void stop_pcm(struct msm_pcm_loopback *pcm) if (pcm->audio_client == NULL) return; + + mutex_lock(&loopback_session_lock); q6asm_cmd(pcm->audio_client, CMD_CLOSE); if (pcm->playback_substream != NULL) { @@ -395,6 +399,7 @@ static void stop_pcm(struct msm_pcm_loopback *pcm) } q6asm_audio_client_free(pcm->audio_client); pcm->audio_client = NULL; + mutex_unlock(&loopback_session_lock); } static int msm_pcm_close(struct snd_pcm_substream *substream) @@ -545,6 +550,7 @@ static int msm_pcm_volume_ctl_put(struct snd_kcontrol *kcontrol, int volume = ucontrol->value.integer.value[0]; pr_debug("%s: volume : 0x%x\n", __func__, volume); + mutex_lock(&loopback_session_lock); if ((!substream) || (!substream->runtime)) { pr_err("%s substream or runtime not found\n", __func__); rc = -ENODEV; @@ -553,9 +559,11 @@ static int msm_pcm_volume_ctl_put(struct snd_kcontrol *kcontrol, prtd = substream->runtime->private_data; if (!prtd) { rc = -ENODEV; + mutex_unlock(&loopback_session_lock); goto exit; } rc = pcm_loopback_set_volume(prtd, volume); + mutex_unlock(&loopback_session_lock); exit: return rc; @@ -576,12 +584,15 @@ static int msm_pcm_volume_ctl_get(struct snd_kcontrol *kcontrol, rc = -ENODEV; goto exit; } + mutex_lock(&loopback_session_lock); prtd = substream->runtime->private_data; if (!prtd) { rc = -ENODEV; + mutex_unlock(&loopback_session_lock); goto exit; } ucontrol->value.integer.value[0] = prtd->volume; + mutex_unlock(&loopback_session_lock); exit: return rc; diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c index ce9091b1ca16..5c78349f8d70 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017, 2019 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -15,6 +15,7 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/time.h> +#include <linux/mutex.h> #include <linux/wait.h> #include <linux/platform_device.h> #include <linux/slab.h> @@ -578,6 +579,7 @@ static int msm_pcm_prepare(struct snd_pcm_substream *substream) static int msm_pcm_close(struct snd_pcm_substream *substream) { + struct msm_plat_data *pdata = NULL; struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *soc_prtd = substream->private_data; struct msm_audio *prtd = runtime->private_data; @@ -586,6 +588,20 @@ static int msm_pcm_close(struct snd_pcm_substream *substream) int dir = 0; int ret = 0; + if (!soc_prtd) { + pr_debug("%s private_data not found\n", + __func__); + return 0; + } + + pdata = (struct msm_plat_data *) + dev_get_drvdata(soc_prtd->platform->dev); + if (!pdata) { + pr_err("%s: pdata not found\n", __func__); + return -ENODEV; + } + + mutex_lock(&pdata->lock); if (ac) { if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) dir = IN; @@ -620,6 +636,7 @@ static int msm_pcm_close(struct snd_pcm_substream *substream) SNDRV_PCM_STREAM_CAPTURE); kfree(prtd); runtime->private_data = NULL; + mutex_unlock(&pdata->lock); return 0; } @@ -644,8 +661,10 @@ static int msm_pcm_volume_ctl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_pcm_volume *vol = snd_kcontrol_chip(kcontrol); + struct msm_plat_data *pdata = NULL; struct snd_pcm_substream *substream = vol->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; + struct snd_soc_pcm_runtime *soc_prtd = NULL; struct msm_audio *prtd; pr_debug("%s\n", __func__); @@ -653,13 +672,24 @@ static int msm_pcm_volume_ctl_get(struct snd_kcontrol *kcontrol, pr_err("%s substream not found\n", __func__); return -ENODEV; } - if (!substream->runtime) { - pr_err("%s substream runtime not found\n", __func__); + soc_prtd = substream->private_data; + if (!substream->runtime || !soc_prtd) { + pr_debug("%s substream runtime or private_data not found\n", + __func__); return 0; } + + pdata = (struct msm_plat_data *) + dev_get_drvdata(soc_prtd->platform->dev); + if (!pdata) { + pr_err("%s: pdata not found\n", __func__); + return -ENODEV; + } + mutex_lock(&pdata->lock); prtd = substream->runtime->private_data; if (prtd) ucontrol->value.integer.value[0] = prtd->volume; + mutex_unlock(&pdata->lock); return 0; } @@ -668,8 +698,10 @@ static int msm_pcm_volume_ctl_put(struct snd_kcontrol *kcontrol, { int rc = 0; struct snd_pcm_volume *vol = snd_kcontrol_chip(kcontrol); + struct msm_plat_data *pdata = NULL; struct snd_pcm_substream *substream = vol->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; + struct snd_soc_pcm_runtime *soc_prtd = NULL; struct msm_audio *prtd; int volume = ucontrol->value.integer.value[0]; @@ -678,15 +710,26 @@ static int msm_pcm_volume_ctl_put(struct snd_kcontrol *kcontrol, pr_err("%s substream not found\n", __func__); return -ENODEV; } - if (!substream->runtime) { - pr_err("%s substream runtime not found\n", __func__); + soc_prtd = substream->private_data; + if (!substream->runtime || !soc_prtd) { + pr_err("%s substream runtime or private_data not found\n", + __func__); return 0; } + + pdata = (struct msm_plat_data *) + dev_get_drvdata(soc_prtd->platform->dev); + if (!pdata) { + pr_err("%s: pdata not found\n", __func__); + return -ENODEV; + } + mutex_lock(&pdata->lock); prtd = substream->runtime->private_data; if (prtd) { rc = msm_pcm_set_volume(prtd, volume); prtd->volume = volume; } + mutex_unlock(&pdata->lock); return rc; } @@ -1233,6 +1276,8 @@ static int msm_pcm_probe(struct platform_device *pdev) pdata->perf_mode = perf_mode; + mutex_init(&pdata->lock); + dev_set_drvdata(&pdev->dev, pdata); dev_dbg(&pdev->dev, "%s: dev name %s\n", @@ -1253,6 +1298,7 @@ static int msm_pcm_remove(struct platform_device *pdev) dev_dbg(&pdev->dev, "Pull mode remove\n"); pdata = dev_get_drvdata(&pdev->dev); + mutex_destroy(&pdata->lock); devm_kfree(&pdev->dev, pdata); snd_soc_unregister_platform(&pdev->dev); return 0; diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c index a7aab839e6db..b2154620c8ae 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c @@ -16,6 +16,7 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/time.h> +#include <linux/mutex.h> #include <linux/wait.h> #include <linux/platform_device.h> #include <linux/slab.h> @@ -880,6 +881,14 @@ static int msm_pcm_playback_close(struct snd_pcm_substream *substream) pr_debug("%s: cmd_pending 0x%lx\n", __func__, prtd->cmd_pending); + pdata = (struct msm_plat_data *) + dev_get_drvdata(soc_prtd->platform->dev); + if (!pdata) { + pr_err("%s: platform data is NULL\n", __func__); + return -EINVAL; + } + + mutex_lock(&pdata->lock); if (prtd->audio_client) { dir = IN; @@ -922,6 +931,7 @@ static int msm_pcm_playback_close(struct snd_pcm_substream *substream) msm_adsp_clean_mixer_ctl_pp_event_queue(soc_prtd); kfree(prtd); runtime->private_data = NULL; + mutex_unlock(&pdata->lock); return 0; } @@ -1016,8 +1026,18 @@ static int msm_pcm_capture_close(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *soc_prtd = substream->private_data; struct msm_audio *prtd = runtime->private_data; int dir = OUT; + struct msm_plat_data *pdata; pr_debug("%s\n", __func__); + + pdata = (struct msm_plat_data *) + dev_get_drvdata(soc_prtd->platform->dev); + if (!pdata) { + pr_err("%s: platform data is NULL\n", __func__); + return -EINVAL; + } + + mutex_lock(&pdata->lock); if (prtd->audio_client) { q6asm_cmd(prtd->audio_client, CMD_CLOSE); q6asm_audio_client_buf_free_contiguous(dir, @@ -1029,6 +1049,7 @@ static int msm_pcm_capture_close(struct snd_pcm_substream *substream) SNDRV_PCM_STREAM_CAPTURE); kfree(prtd); runtime->private_data = NULL; + mutex_unlock(&pdata->lock); return 0; } @@ -1167,10 +1188,10 @@ static int msm_pcm_adsp_stream_cmd_put(struct snd_kcontrol *kcontrol, if (!pdata) { pr_err("%s pdata is NULL\n", __func__); - ret = -ENODEV; - goto done; + return -ENODEV; } + mutex_lock(&pdata->lock); substream = pdata->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; if (!substream) { pr_err("%s substream not found\n", __func__); @@ -1197,6 +1218,7 @@ static int msm_pcm_adsp_stream_cmd_put(struct snd_kcontrol *kcontrol, goto done; } + mutex_lock(&pdata->lock); event_data = (struct msm_adsp_event_data *)ucontrol->value.bytes.data; if ((event_data->event_type < ADSP_STREAM_PP_EVENT) || (event_data->event_type >= ADSP_STREAM_EVENT_MAX)) { @@ -1228,6 +1250,7 @@ static int msm_pcm_adsp_stream_cmd_put(struct snd_kcontrol *kcontrol, pr_err("%s: failed to send stream event cmd, err = %d\n", __func__, ret); done: + mutex_unlock(&pdata->lock); return ret; } @@ -1365,8 +1388,10 @@ static int msm_pcm_volume_ctl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_pcm_volume *vol = snd_kcontrol_chip(kcontrol); + struct msm_plat_data *pdata = NULL; struct snd_pcm_substream *substream = vol->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; + struct snd_soc_pcm_runtime *soc_prtd = NULL; struct msm_audio *prtd; pr_debug("%s\n", __func__); @@ -1374,13 +1399,25 @@ static int msm_pcm_volume_ctl_get(struct snd_kcontrol *kcontrol, pr_err("%s substream not found\n", __func__); return -ENODEV; } - if (!substream->runtime) { - pr_err("%s substream runtime not found\n", __func__); + soc_prtd = substream->private_data; + if (!substream->runtime || !soc_prtd) { + pr_debug("%s substream runtime or private_data not found\n", + __func__); return 0; } + + pdata = (struct msm_plat_data *) + dev_get_drvdata(soc_prtd->platform->dev); + if (!pdata) { + pr_err("%s: pdata not found\n", __func__); + return -ENODEV; + } + + mutex_lock(&pdata->lock); prtd = substream->runtime->private_data; if (prtd) ucontrol->value.integer.value[0] = prtd->volume; + mutex_unlock(&pdata->lock); return 0; } @@ -1393,21 +1430,35 @@ static int msm_pcm_volume_ctl_put(struct snd_kcontrol *kcontrol, vol->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; struct msm_audio *prtd; int volume = ucontrol->value.integer.value[0]; + struct snd_soc_pcm_runtime *soc_prtd = NULL; + struct msm_plat_data *pdata = NULL; pr_debug("%s: volume : 0x%x\n", __func__, volume); if (!substream) { - pr_err("%s substream not found\n", __func__); + pr_err("%s: substream not found\n", __func__); return -ENODEV; } - if (!substream->runtime) { - pr_err("%s substream runtime not found\n", __func__); + soc_prtd = substream->private_data; + if (!substream->runtime || !soc_prtd) { + pr_err("%s: substream runtime or private_data not found\n", + __func__); return 0; } + + pdata = (struct msm_plat_data *) + dev_get_drvdata(soc_prtd->platform->dev); + if (!pdata) { + pr_err("%s: pdata not found\n", __func__); + return -ENODEV; + } + + mutex_lock(&pdata->lock); prtd = substream->runtime->private_data; if (prtd) { rc = msm_pcm_set_volume(prtd, volume); prtd->volume = volume; } + mutex_unlock(&pdata->lock); return rc; } @@ -1465,9 +1516,11 @@ static int msm_pcm_compress_ctl_get(struct snd_kcontrol *kcontrol, pr_err("%s substream runtime not found\n", __func__); return 0; } + mutex_lock(&pdata->lock); prtd = substream->runtime->private_data; if (prtd) ucontrol->value.integer.value[0] = prtd->compress_enable; + mutex_unlock(&pdata->lock); return 0; } @@ -1496,12 +1549,14 @@ static int msm_pcm_compress_ctl_put(struct snd_kcontrol *kcontrol, pr_err("%s substream runtime not found\n", __func__); return 0; } + mutex_lock(&pdata->lock); prtd = substream->runtime->private_data; if (prtd) { pr_debug("%s: setting compress flag to 0x%x\n", __func__, compress); prtd->compress_enable = compress; } + mutex_unlock(&pdata->lock); return rc; } @@ -1572,14 +1627,28 @@ static int msm_pcm_chmap_ctl_put(struct snd_kcontrol *kcontrol, unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); struct snd_pcm_substream *substream; struct msm_audio *prtd; + struct snd_soc_pcm_runtime *rtd = NULL; + struct msm_plat_data *pdata = NULL; pr_debug("%s", __func__); substream = snd_pcm_chmap_substream(info, idx); if (!substream) return -ENODEV; - if (!substream->runtime) + + rtd = substream->private_data; + if (rtd) { + pdata = (struct msm_plat_data *) + dev_get_drvdata(rtd->platform->dev); + if (!pdata) { + pr_err("%s: pdata not found\n", __func__); + return -ENODEV; + } + } + + if (!substream->runtime || !rtd) return 0; + mutex_lock(&pdata->lock); prtd = substream->runtime->private_data; if (prtd) { prtd->set_channel_map = true; @@ -1587,6 +1656,7 @@ static int msm_pcm_chmap_ctl_put(struct snd_kcontrol *kcontrol, prtd->channel_map[i] = (char)(ucontrol->value.integer.value[i]); } + mutex_unlock(&pdata->lock); return 0; } @@ -1598,16 +1668,30 @@ static int msm_pcm_chmap_ctl_get(struct snd_kcontrol *kcontrol, unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); struct snd_pcm_substream *substream; struct msm_audio *prtd; + struct snd_soc_pcm_runtime *rtd = NULL; + struct msm_plat_data *pdata = NULL; pr_debug("%s", __func__); substream = snd_pcm_chmap_substream(info, idx); if (!substream) return -ENODEV; + + rtd = substream->private_data; + if (rtd) { + pdata = (struct msm_plat_data *) + dev_get_drvdata(rtd->platform->dev); + if (!pdata) { + pr_err("%s: pdata not found\n", __func__); + return -ENODEV; + } + } + memset(ucontrol->value.integer.value, 0, sizeof(ucontrol->value.integer.value)); - if (!substream->runtime) + if (!substream->runtime || !rtd) return 0; /* no channels set */ + mutex_lock(&pdata->lock); prtd = substream->runtime->private_data; if (prtd && prtd->set_channel_map == true) { @@ -1619,6 +1703,7 @@ static int msm_pcm_chmap_ctl_get(struct snd_kcontrol *kcontrol, ucontrol->value.integer.value[i] = 0; } + mutex_unlock(&pdata->lock); return 0; } @@ -2244,6 +2329,7 @@ static int msm_pcm_channel_mixer_cfg_ctl_put(struct snd_kcontrol *kcontrol, chmixer_pspd->output_channel = ucontrol->value.integer.value[3]; chmixer_pspd->port_idx = ucontrol->value.integer.value[4]; + mutex_lock(&pdata->lock); /* cache value and take effect during adm_open stage */ msm_pcm_routing_set_channel_mixer_cfg(fe_id, session_type, @@ -2266,6 +2352,7 @@ static int msm_pcm_channel_mixer_cfg_ctl_put(struct snd_kcontrol *kcontrol, } } done: + mutex_unlock(&pdata->lock); return ret; } @@ -3089,6 +3176,7 @@ static int msm_pcm_probe(struct platform_device *pdev) pr_debug("%s: avs_ver = %d\n", __func__, pdata->avs_ver); + mutex_init(&pdata->lock); dev_set_drvdata(&pdev->dev, pdata); dev_dbg(&pdev->dev, "%s: dev name %s\n", @@ -3102,6 +3190,7 @@ static int msm_pcm_remove(struct platform_device *pdev) struct msm_plat_data *pdata; pdata = dev_get_drvdata(&pdev->dev); + mutex_destroy(&pdata->lock); kfree(pdata); snd_soc_unregister_platform(&pdev->dev); return 0; diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h index a90e9f7d4fc9..f0a96484a03b 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h +++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h @@ -127,6 +127,7 @@ struct msm_plat_data { struct snd_pcm *pcm; struct snd_pcm *pcm_device[MSM_FRONTEND_DAI_MM_SIZE]; struct msm_pcm_channel_mixer chmixer_pspd[MSM_FRONTEND_DAI_MM_SIZE][2]; + struct mutex lock; }; #endif /*_MSM_PCM_H*/ diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c index 965de5ca4f66..ed3ee03553b3 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c @@ -15269,16 +15269,18 @@ static int msm_routing_put_lsm_app_type_cfg_control( struct snd_ctl_elem_value *ucontrol) { int i = 0, j; - int num_app_types = ucontrol->value.integer.value[i++]; + int num_app_types; - memset(lsm_app_type_cfg, 0, MAX_APP_TYPES* - sizeof(struct msm_pcm_routing_app_type_data)); - if (num_app_types > MAX_APP_TYPES) { + if (ucontrol->value.integer.value[0] > MAX_APP_TYPES) { pr_err("%s: number of app types exceed the max supported\n", __func__); return -EINVAL; } + num_app_types = ucontrol->value.integer.value[i++]; + memset(lsm_app_type_cfg, 0, MAX_APP_TYPES* + sizeof(struct msm_pcm_routing_app_type_data)); + for (j = 0; j < num_app_types; j++) { lsm_app_type_cfg[j].app_type = ucontrol->value.integer.value[i++]; |
