[PATCH 2/2] ASoC: qcom: qdsp6: q6adm: Add reference count for opening/closing copps

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



---
 sound/soc/qcom/qdsp6/q6adm.c | 71 ++++++++++++++++++++++--------------
 1 file changed, 43 insertions(+), 28 deletions(-)

diff --git a/sound/soc/qcom/qdsp6/q6adm.c b/sound/soc/qcom/qdsp6/q6adm.c
index b4879cac76a6..b073980bb967 100644
--- a/sound/soc/qcom/qdsp6/q6adm.c
+++ b/sound/soc/qcom/qdsp6/q6adm.c
@@ -51,6 +51,9 @@ struct q6copp {
 	wait_queue_head_t wait;
 	struct list_head node;
 	struct q6adm *adm;
+
+	int open_count;
+	struct mutex open_lock;
 };
 
 struct q6adm {
@@ -396,35 +399,43 @@ struct q6copp *q6adm_open(struct device *dev, int port_id, int path, int rate,
 
 	copp = q6adm_find_matching_copp(adm, port_id, topology, perf_mode,
 				      rate, channel_mode, bit_width, app_type);
-	if (copp) {
-		dev_err(dev, "Found Matching Copp 0x%x\n", copp->copp_idx);
-		return copp;
-	}
+	if (!copp) {
+		spin_lock_irqsave(&adm->copps_list_lock, flags);
+		copp = q6adm_alloc_copp(adm, port_id);
+		if (IS_ERR(copp)) {
+			spin_unlock_irqrestore(&adm->copps_list_lock, flags);
+			return ERR_CAST(copp);
+		}
 
-	spin_lock_irqsave(&adm->copps_list_lock, flags);
-	copp = q6adm_alloc_copp(adm, port_id);
-	if (IS_ERR(copp)) {
+		kref_init(&copp->refcount);
+		copp->topology = topology;
+		copp->mode = perf_mode;
+		copp->rate = rate;
+		copp->channels = channel_mode;
+		copp->bit_width = bit_width;
+		copp->app_type = app_type;
+		mutex_init(&copp->open_lock);
+
+		list_add_tail(&copp->node, &adm->copps_list);
 		spin_unlock_irqrestore(&adm->copps_list_lock, flags);
-		return ERR_CAST(copp);
+	} else {
+		dev_dbg(dev, "Found Matching Copp 0x%x\n", copp->copp_idx);
 	}
 
-	kref_init(&copp->refcount);
-	copp->topology = topology;
-	copp->mode = perf_mode;
-	copp->rate = rate;
-	copp->channels = channel_mode;
-	copp->bit_width = bit_width;
-	copp->app_type = app_type;
-
-	list_add_tail(&copp->node, &adm->copps_list);
-	spin_unlock_irqrestore(&adm->copps_list_lock, flags);
-
-	ret = q6adm_device_open(adm, copp, port_id, path, topology,
-				channel_mode, bit_width, rate);
-	if (ret < 0) {
-		kref_put(&copp->refcount, q6adm_free_copp);
-		return ERR_PTR(ret);
+	mutex_lock(&copp->open_lock);
+	if (copp->open_count == 0) {
+		ret = q6adm_device_open(adm, copp, port_id, path, topology,
+					channel_mode, bit_width, rate);
+		if (ret < 0) {
+			mutex_unlock(&copp->open_lock);
+			kref_put(&copp->refcount, q6adm_free_copp);
+			return ERR_PTR(ret);
+		}
+		copp->open_count = 1;
+	} else {
+		copp->open_count++;
 	}
+	mutex_unlock(&copp->open_lock);
 
 	return copp;
 }
@@ -570,11 +581,15 @@ int q6adm_close(struct device *dev, struct q6copp *copp)
 	struct q6adm *adm = dev_get_drvdata(dev->parent);
 	int ret = 0;
 
-	ret = q6adm_device_close(adm, copp, copp->afe_port, copp->copp_idx);
-	if (ret < 0) {
-		dev_err(adm->dev, "Failed to close copp %d\n", ret);
-		return ret;
+	mutex_lock(&copp->open_lock);
+	if (--copp->open_count == 0) {
+		ret = q6adm_device_close(adm, copp, copp->afe_port, copp->copp_idx);
+		if (ret < 0) {
+			dev_err(adm->dev, "Failed to close copp %d\n", ret);
+			return ret;
+		}
 	}
+	mutex_unlock(&copp->open_lock);
 
 	kref_put(&copp->refcount, q6adm_free_copp);
 
-- 
2.47.2






[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux FS]     [Yosemite Forum]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]     [Linux Resources]

  Powered by Linux