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

Commit d10e4b6e authored by Konstantin Dorfman's avatar Konstantin Dorfman Committed by Ashwini Muduganti
Browse files

soc: qcom: spcom: fix unlock ion buffer



The buffer is referenced by 'fd' supplied by user space. Lock/Unlock
functionality adds/removes reference on underlying dma buffer. 'fd' is
mapped to dma_buf pointer by dma buf framework. After lock every dma
buffer tracked in spcom driver (per channel).

This change fixes unlock operation by look up underlying dma_buf pointer
and doing unlock for the dma buffer pointer stored before (by lock
operation), instead comparing only 'fd' value (which may be re-mapped
after lock by userspace).

Change-Id: I11cf9399eef2607c31ab1a9deb655fdd90d99d22
Signed-off-by: default avatarKonstantin Dorfman <kdorfman@codeaurora.org>
parent 9c599582
Loading
Loading
Loading
Loading
+20 −6
Original line number Original line Diff line number Diff line
@@ -920,8 +920,10 @@ static int spcom_handle_lock_ion_buf_command(struct spcom_channel *ch,
		if (ch->dmabuf_handle_table[i] == NULL) {
		if (ch->dmabuf_handle_table[i] == NULL) {
			ch->dmabuf_handle_table[i] = dma_buf;
			ch->dmabuf_handle_table[i] = dma_buf;
			ch->dmabuf_fd_table[i] = fd;
			ch->dmabuf_fd_table[i] = fd;
			pr_debug("ch [%s] locked ion buf #%d, fd [%d].\n",
			pr_debug("ch [%s] locked ion buf #%d fd [%d] dma_buf=0x%x\n",
				ch->name, i, fd);
				ch->name, i,
				ch->dmabuf_fd_table[i],
				ch->dmabuf_handle_table[i]);
			mutex_unlock(&ch->lock);
			mutex_unlock(&ch->lock);
			return 0;
			return 0;
		}
		}
@@ -948,6 +950,7 @@ static int spcom_handle_unlock_ion_buf_command(struct spcom_channel *ch,
	struct spcom_user_command *cmd = cmd_buf;
	struct spcom_user_command *cmd = cmd_buf;
	int fd;
	int fd;
	bool found = false;
	bool found = false;
	struct dma_buf *dma_buf;


	if (size != sizeof(*cmd)) {
	if (size != sizeof(*cmd)) {
		pr_err("cmd size [%d], expected [%d]\n",
		pr_err("cmd size [%d], expected [%d]\n",
@@ -961,6 +964,15 @@ static int spcom_handle_unlock_ion_buf_command(struct spcom_channel *ch,
	fd = cmd->arg;
	fd = cmd->arg;


	pr_debug("Unlock ion buf ch [%s] fd [%d].\n", ch->name, fd);
	pr_debug("Unlock ion buf ch [%s] fd [%d].\n", ch->name, fd);

	dma_buf = dma_buf_get(fd);
	if (IS_ERR_OR_NULL(dma_buf)) {
		pr_err("fail to get dma buf handle\n");
		return -EINVAL;
	}
	dma_buf_put(dma_buf);
	pr_debug("dma_buf referenced ok\n");

	/* shared buf unlock doesn't involve any rx/tx data to SP. */
	/* shared buf unlock doesn't involve any rx/tx data to SP. */
	mutex_lock(&ch->lock);
	mutex_lock(&ch->lock);
	if (fd == (int) SPCOM_ION_FD_UNLOCK_ALL) {
	if (fd == (int) SPCOM_ION_FD_UNLOCK_ALL) {
@@ -969,7 +981,7 @@ static int spcom_handle_unlock_ion_buf_command(struct spcom_channel *ch,
		/* unlock all buf */
		/* unlock all buf */
		for (i = 0; i < ARRAY_SIZE(ch->dmabuf_handle_table); i++) {
		for (i = 0; i < ARRAY_SIZE(ch->dmabuf_handle_table); i++) {
			if (ch->dmabuf_handle_table[i] != NULL) {
			if (ch->dmabuf_handle_table[i] != NULL) {
				pr_debug("unlocked ion buf #%d fd [%d].\n",
				pr_debug("unlocked ion buf #%d fd [%d]\n",
					i, ch->dmabuf_fd_table[i]);
					i, ch->dmabuf_fd_table[i]);
				dma_buf_put(ch->dmabuf_handle_table[i]);
				dma_buf_put(ch->dmabuf_handle_table[i]);
				ch->dmabuf_handle_table[i] = NULL;
				ch->dmabuf_handle_table[i] = NULL;
@@ -981,9 +993,11 @@ static int spcom_handle_unlock_ion_buf_command(struct spcom_channel *ch,
		for (i = 0 ; i < ARRAY_SIZE(ch->dmabuf_handle_table) ; i++) {
		for (i = 0 ; i < ARRAY_SIZE(ch->dmabuf_handle_table) ; i++) {
			if (!ch->dmabuf_handle_table[i])
			if (!ch->dmabuf_handle_table[i])
				continue;
				continue;
			if (ch->dmabuf_fd_table[i] == fd) {
			if (ch->dmabuf_handle_table[i] == dma_buf) {
				pr_debug("unlocked ion buf #%d fd [%d].\n",
				pr_debug("ch [%s] unlocked ion buf #%d fd [%d] dma_buf=0x%x\n",
					i, ch->dmabuf_fd_table[i]);
					ch->name, i,
					ch->dmabuf_fd_table[i],
					ch->dmabuf_handle_table[i]);
				dma_buf_put(ch->dmabuf_handle_table[i]);
				dma_buf_put(ch->dmabuf_handle_table[i]);
				ch->dmabuf_handle_table[i] = NULL;
				ch->dmabuf_handle_table[i] = NULL;
				ch->dmabuf_fd_table[i] = -1;
				ch->dmabuf_fd_table[i] = -1;