summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/char/adsprpc.c8
-rw-r--r--drivers/devfreq/governor_msm_adreno_tz.c10
-rw-r--r--drivers/hid/hid-core.c55
-rw-r--r--drivers/misc/qseecom.c3
-rw-r--r--drivers/net/wireless/cnss2/pci.c13
-rw-r--r--drivers/soc/qcom/peripheral-loader.c20
-rw-r--r--drivers/soc/qcom/peripheral-loader.h4
-rw-r--r--drivers/soc/qcom/pil-msa.c23
-rw-r--r--drivers/soc/qcom/subsys-pil-tz.c5
-rw-r--r--include/linux/hid.h2
-rw-r--r--include/net/cnss2.h3
-rw-r--r--sound/soc/msm/qdsp6v2/msm-pcm-loopback-v2.c13
-rw-r--r--sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c56
-rw-r--r--sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c107
-rw-r--r--sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h1
-rw-r--r--sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c10
16 files changed, 273 insertions, 60 deletions
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/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++];