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

Commit 39813c1d authored by Dan Bar-On's avatar Dan Bar-On
Browse files

soc: qcom: spcom: fix race condition when creating channel



This change handles the race condition when creating
the same channel from different userspace contexts.

Change-Id: I6a8f82b251d8f206bdfef4cbc6b4478250137e06
Signed-off-by: default avatarDan Bar-On <dbaron@codeaurora.org>
parent 6a1ffe01
Loading
Loading
Loading
Loading
+8 −0
Original line number Original line Diff line number Diff line
@@ -234,6 +234,7 @@ struct spcom_device {


	int32_t nvm_ion_fd;
	int32_t nvm_ion_fd;
	struct mutex ioctl_lock;
	struct mutex ioctl_lock;
	struct mutex create_channel_lock;
};
};


/* Device Driver State */
/* Device Driver State */
@@ -1898,22 +1899,26 @@ static int spcom_create_channel_chardev(const char *name, bool is_sharable)
	struct cdev *cdev;
	struct cdev *cdev;


	pr_debug("Add channel [%s]\n", name);
	pr_debug("Add channel [%s]\n", name);
	mutex_lock(&spcom_dev->create_channel_lock);


	ch = spcom_find_channel_by_name(name);
	ch = spcom_find_channel_by_name(name);
	if (ch) {
	if (ch) {
		pr_err("channel [%s] already exist\n", name);
		pr_err("channel [%s] already exist\n", name);
		mutex_unlock(&spcom_dev->create_channel_lock);
		return -EBUSY;
		return -EBUSY;
	}
	}


	ch = spcom_find_channel_by_name(""); /* find reserved channel */
	ch = spcom_find_channel_by_name(""); /* find reserved channel */
	if (!ch) {
	if (!ch) {
		pr_err("no free channel\n");
		pr_err("no free channel\n");
		mutex_unlock(&spcom_dev->create_channel_lock);
		return -ENODEV;
		return -ENODEV;
	}
	}


	ret = spcom_init_channel(ch, is_sharable, name);
	ret = spcom_init_channel(ch, is_sharable, name);
	if (ret < 0) {
	if (ret < 0) {
		pr_err("can't init channel %d\n", ret);
		pr_err("can't init channel %d\n", ret);
		mutex_unlock(&spcom_dev->create_channel_lock);
		return ret;
		return ret;
	}
	}


@@ -1952,6 +1957,7 @@ static int spcom_create_channel_chardev(const char *name, bool is_sharable)
	ch->cdev = cdev;
	ch->cdev = cdev;
	ch->dev = dev;
	ch->dev = dev;
	mutex_unlock(&ch->lock);
	mutex_unlock(&ch->lock);
	mutex_unlock(&spcom_dev->create_channel_lock);


	return 0;
	return 0;


@@ -1968,6 +1974,7 @@ static int spcom_create_channel_chardev(const char *name, bool is_sharable)
	mutex_lock(&ch->lock);
	mutex_lock(&ch->lock);
	memset(ch->name, 0, SPCOM_CHANNEL_NAME_SIZE);
	memset(ch->name, 0, SPCOM_CHANNEL_NAME_SIZE);
	mutex_unlock(&ch->lock);
	mutex_unlock(&ch->lock);
	mutex_unlock(&spcom_dev->create_channel_lock);
	return -EFAULT;
	return -EFAULT;
}
}


@@ -2422,6 +2429,7 @@ static int spcom_probe(struct platform_device *pdev)
	spin_lock_init(&spcom_dev->rx_lock);
	spin_lock_init(&spcom_dev->rx_lock);
	spcom_dev->nvm_ion_fd = -1;
	spcom_dev->nvm_ion_fd = -1;
	mutex_init(&spcom_dev->ioctl_lock);
	mutex_init(&spcom_dev->ioctl_lock);
	mutex_init(&spcom_dev->create_channel_lock);


	ret = spcom_register_chardev();
	ret = spcom_register_chardev();
	if (ret) {
	if (ret) {