Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1f2a8699 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "drivers: soc: add mutex to prevent response being processed twice"

parents af6d354a d3237316
Loading
Loading
Loading
Loading
+20 −6
Original line number Diff line number Diff line
/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2014-2017, 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
@@ -42,6 +42,12 @@ struct voice_svc_prvt {
	struct list_head response_queue;
	wait_queue_head_t response_wait;
	spinlock_t response_lock;
	/*
	 * This mutex ensures responses are processed in sequential order and
	 * that no two threads access and free the same response at the same
	 * time.
	 */
	struct mutex response_mutex_lock;
};

struct apr_data {
@@ -467,6 +473,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg,
		goto done;
	}

	mutex_lock(&prtd->response_mutex_lock);
	spin_lock_irqsave(&prtd->response_lock, spin_flags);

	if (list_empty(&prtd->response_queue)) {
@@ -480,7 +487,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg,
			pr_debug("%s: Read timeout\n", __func__);

			ret = -ETIMEDOUT;
			goto done;
			goto unlock;
		} else if (ret > 0 && !list_empty(&prtd->response_queue)) {
			pr_debug("%s: Interrupt recieved for response\n",
				 __func__);
@@ -488,7 +495,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg,
			pr_debug("%s: Interrupted by SIGNAL %d\n",
				 __func__, ret);

			goto done;
			goto unlock;
		}

		spin_lock_irqsave(&prtd->response_lock, spin_flags);
@@ -507,7 +514,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg,
		       __func__, count, size);

		ret = -ENOMEM;
		goto done;
		goto unlock;
	}

	if (!access_ok(VERIFY_WRITE, arg, size)) {
@@ -515,7 +522,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg,
		       __func__);

		ret = -EPERM;
		goto done;
		goto unlock;
	}

	ret = copy_to_user(arg, &resp->resp,
@@ -525,7 +532,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg,
		pr_err("%s: copy_to_user failed %d\n", __func__, ret);

		ret = -EPERM;
		goto done;
		goto unlock;
	}

	spin_lock_irqsave(&prtd->response_lock, spin_flags);
@@ -539,6 +546,8 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg,

	ret = count;

unlock:
	mutex_unlock(&prtd->response_mutex_lock);
done:
	return ret;
}
@@ -594,6 +603,7 @@ static int voice_svc_open(struct inode *inode, struct file *file)
	INIT_LIST_HEAD(&prtd->response_queue);
	init_waitqueue_head(&prtd->response_wait);
	spin_lock_init(&prtd->response_lock);
	mutex_init(&prtd->response_mutex_lock);
	file->private_data = (void *)prtd;

	/* Current APR implementation doesn't support session based
@@ -644,6 +654,7 @@ static int voice_svc_release(struct inode *inode, struct file *file)
			pr_err("%s: Failed to dereg MVM %d\n", __func__, ret);
	}

	mutex_lock(&prtd->response_mutex_lock);
	spin_lock_irqsave(&prtd->response_lock, spin_flags);

	while (!list_empty(&prtd->response_queue)) {
@@ -657,6 +668,9 @@ static int voice_svc_release(struct inode *inode, struct file *file)
	}

	spin_unlock_irqrestore(&prtd->response_lock, spin_flags);
	mutex_unlock(&prtd->response_mutex_lock);

	mutex_destroy(&prtd->response_mutex_lock);

	kfree(file->private_data);
	file->private_data = NULL;