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

Commit 6476e65d authored by Isaac J. Manjarres's avatar Isaac J. Manjarres
Browse files

soc: qcom: mem-buf: Fix error handling when releasing memory



When releasing memory, notify the owner of the memory that it
can be reclaimed only if the recipient VM has successfully
released the memory. There is also no reason to continue
to hold onto the mem-buf descriptor memory if a failure
occurs when relinquishing the memory, so free those structures
as well, independent of the result of the relinquish operation.
While we're here, touch up some of the error logging in the
error paths as well.

Change-Id: I29bb1774507fd75f206c0537b6007182b4d6cb48
Signed-off-by: default avatarIsaac J. Manjarres <isaacm@codeaurora.org>
parent dbe59ab3
Loading
Loading
Loading
Loading
+52 −16
Original line number Diff line number Diff line
@@ -286,8 +286,11 @@ static int mem_buf_txn_wait(struct mem_buf_txn *txn)

	ret = wait_for_completion_timeout(&txn->txn_done,
					  msecs_to_jiffies(MEM_BUF_TIMEOUT_MS));
	if (ret == 0)
	if (ret == 0) {
		pr_err("%s: timed out waiting for allocation response\n",
		       __func__);
		return -ETIMEDOUT;
	}

	return txn->txn_ret;
}
@@ -498,7 +501,8 @@ static int mem_buf_retrieve_memparcel_hdl(struct mem_buf_xfer_mem *xfer_mem)
					&xfer_mem->acl_desc, sgl_desc, NULL,
					&xfer_mem->hdl);
	if (ret < 0)
		pr_err("%s: hh_rm_mem_qcom_lookup_sgl failure rc: %d\n", ret);
		pr_err("%s: hh_rm_mem_qcom_lookup_sgl failure rc: %d\n",
		       __func__, ret);

	kfree(sgl_desc);
	return ret;
@@ -960,10 +964,15 @@ static int mem_buf_map_mem_s2(struct mem_buf_desc *membuf)
	return ret;
}

static void mem_buf_unmap_mem_s2(struct mem_buf_desc *membuf)
static int mem_buf_unmap_mem_s2(struct mem_buf_desc *membuf)
{
	hh_rm_mem_release(membuf->memparcel_hdl, HH_RM_MEM_RELEASE_CLEAR);
	kfree(membuf->sgl_desc);
	int ret = hh_rm_mem_release(membuf->memparcel_hdl,
				    HH_RM_MEM_RELEASE_CLEAR);

	if (ret < 0)
		pr_err("%s: Failed to release memparcel hdl: 0x%lx rc: %d\n",
		       __func__, membuf->memparcel_hdl, ret);
	return ret;
}

#ifdef CONFIG_MEMORY_HOTPLUG
@@ -1019,8 +1028,9 @@ static inline int mem_buf_map_mem_s1(struct mem_buf_desc *membuf)
#endif /* CONFIG_MEMORY_HOTPLUG */

#ifdef CONFIG_MEMORY_HOTREMOVE
static void mem_buf_unmap_mem_s1(struct mem_buf_desc *membuf)
static int mem_buf_unmap_mem_s1(struct mem_buf_desc *membuf)
{
	int ret;
	unsigned int i, nid;
	u64 base, size;

@@ -1031,14 +1041,22 @@ static void mem_buf_unmap_mem_s1(struct mem_buf_desc *membuf)
		size = membuf->sgl_desc->sgl_entries[i].size;
		nid = memory_add_physaddr_to_nid(base);
		arch_remove_memory(nid, base, size, NULL);
		memblock_remove(base, size);
		ret = memblock_remove(base, size);
		if (ret) {
			pr_err("%s: memblock_remove failed rc: %d\n", __func__,
			       ret);
			goto out;
		}
	}

out:
	mem_hotplug_done();
	return ret;
}
#else /* CONFIG_MEMORY_HOTREMOVE */
static inline void mem_buf_unmap_mem_s1(struct mem_buf_desc *membuf)
static inline int mem_buf_unmap_mem_s1(struct mem_buf_desc *membuf)
{
	return -EINVAL;
}
#endif /* CONFIG_MEMORY_HOTREMOVE */

@@ -1136,12 +1154,19 @@ static bool is_valid_mem_buf_vmid(u32 mem_buf_vmid)
	    (mem_buf_vmid == MEM_BUF_VMID_TRUSTED_VM))
		return true;

	pr_err_ratelimited("%s: Invalid mem-buf VMID detected\n",
			   __func__);
	return false;
}

static bool is_valid_mem_buf_perms(u32 mem_buf_perms)
{
	return !(mem_buf_perms & ~MEM_BUF_PERM_VALID_FLAGS);
	if (mem_buf_perms & ~MEM_BUF_PERM_VALID_FLAGS) {
		pr_err_ratelimited("%s: Invalid mem-buf permissions detected\n",
				   __func__);
		return false;
	}
	return true;
}

static int mem_buf_vmid_to_vmid(u32 mem_buf_vmid)
@@ -1277,16 +1302,25 @@ static int mem_buf_buffer_release(struct inode *inode, struct file *filp)

	ret = mem_buf_remove_mem(membuf);
	if (ret < 0)
		return ret;
		goto out_free_mem;

	ret = mem_buf_unmap_mem_s1(membuf);
	if (ret < 0)
		goto out_free_mem;

	ret = mem_buf_unmap_mem_s2(membuf);
	if (ret < 0)
		goto out_free_mem;

	mem_buf_unmap_mem_s1(membuf);
	mem_buf_unmap_mem_s2(membuf);
	mem_buf_relinquish_mem(membuf);

out_free_mem:
	mem_buf_free_mem_type_data(membuf->dst_mem_type, membuf->dst_data);
	mem_buf_free_mem_type_data(membuf->src_mem_type, membuf->src_data);
	kfree(membuf->sgl_desc);
	kfree(membuf->acl_desc);
	kfree(membuf);
	return 0;
	return ret;
}

static const struct file_operations mem_buf_fops = {
@@ -1376,11 +1410,13 @@ void *mem_buf_alloc(struct mem_buf_allocation_data *alloc_data)

err_get_file:
	if (mem_buf_remove_mem(membuf) < 0)
		return ERR_PTR(ret);
		goto err_mem_req;
err_add_mem:
	mem_buf_unmap_mem_s1(membuf);
	if (mem_buf_unmap_mem_s1(membuf) < 0)
		goto err_mem_req;
err_map_mem_s1:
	mem_buf_unmap_mem_s2(membuf);
	if (mem_buf_unmap_mem_s2(membuf) < 0)
		goto err_mem_req;
err_map_mem_s2:
	mem_buf_relinquish_mem(membuf);
err_mem_req: