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

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

Merge "drm/msm: fix leak in failed submit path"

parents c65d7c1c 5fb06424
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -437,6 +437,7 @@ struct msm_gem_address_space *
msm_gem_smmu_address_space_create(struct device *dev, struct msm_mmu *mmu,
		const char *name);

void msm_gem_submit_free(struct msm_gem_submit *submit);
int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
		struct drm_file *file);

+9 −1
Original line number Diff line number Diff line
@@ -653,7 +653,15 @@ void *msm_gem_vaddr(struct drm_gem_object *obj)
	struct msm_gem_object *msm_obj = to_msm_bo(obj);

	mutex_lock(&msm_obj->lock);
	if (!msm_obj->vaddr) {

	if (msm_obj->vaddr) {
		mutex_unlock(&msm_obj->lock);
		return msm_obj->vaddr;
	}

	if (obj->import_attach) {
		msm_obj->vaddr = dma_buf_vmap(obj->import_attach->dmabuf);
	} else {
		struct page **pages = get_pages(obj);
		if (IS_ERR(pages)) {
			mutex_unlock(&msm_obj->lock);
+20 −2
Original line number Diff line number Diff line
@@ -59,6 +59,11 @@ static struct msm_gem_submit *submit_create(struct drm_device *dev,

		submit->secure = false;

		/*
		 * Initalize node so we can safely list_del() on it if
		 * we fail in the submit path
		 */
		INIT_LIST_HEAD(&submit->node);
		INIT_LIST_HEAD(&submit->bo_list);
		ww_acquire_init(&submit->ticket, &reservation_ww_class);
	}
@@ -74,6 +79,15 @@ copy_from_user_inatomic(void *to, const void __user *from, unsigned long n)
	return -EFAULT;
}

void msm_gem_submit_free(struct msm_gem_submit *submit)
{
	if (!submit)
		return;

	list_del(&submit->node);
	kfree(submit);
}

static int submit_lookup_objects(struct msm_gpu *gpu,
		struct msm_gem_submit *submit,
		struct drm_msm_gem_submit *args, struct drm_file *file)
@@ -381,6 +395,9 @@ static void submit_cleanup(struct msm_gpu *gpu, struct msm_gem_submit *submit,
{
	unsigned i;

	if (!submit)
		return;

	for (i = 0; i < submit->nr_bos; i++) {
		struct msm_gem_object *msm_obj = submit->bos[i].obj;
		submit_unlock_unpin_bo(gpu, submit, i);
@@ -510,8 +527,9 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
	args->fence = submit->fence;

out:
	if (submit)
	submit_cleanup(gpu, submit, !!ret);
	if (ret)
		msm_gem_submit_free(submit);
	mutex_unlock(&dev->struct_mutex);
	return ret;
}
+1 −2
Original line number Diff line number Diff line
@@ -479,8 +479,7 @@ static void retire_submits(struct msm_gpu *gpu, uint32_t fence)

	list_for_each_entry_safe(submit, tmp, &gpu->submit_list, node) {
		if (COMPARE_FENCE_LTE(submit->fence, fence)) {
			list_del(&submit->node);
			kfree(submit);
			msm_gem_submit_free(submit);
		}
	}
}
+48 −13
Original line number Diff line number Diff line
@@ -27,6 +27,11 @@
 * This bypasses drm_debugfs_create_files() mainly because we need to use
 * our own fops for a bit more control.  In particular, we don't want to
 * do anything if userspace doesn't have the debugfs file open.
 *
 * The module-param "rd_full", which defaults to false, enables snapshotting
 * all (non-written) buffers in the submit, rather than just cmdstream bo's.
 * This is useful to capture the contents of (for example) vbo's or textures,
 * or shader programs (if not emitted inline in cmdstream).
 */

#ifdef CONFIG_DEBUG_FS
@@ -40,6 +45,10 @@
#include "msm_gpu.h"
#include "msm_gem.h"

static bool rd_full = false;
MODULE_PARM_DESC(rd_full, "If true, $debugfs/.../rd will snapshot all buffer contents");
module_param_named(rd_full, rd_full, bool, 0600);

enum rd_sect_type {
	RD_NONE,
	RD_TEST,       /* ascii text */
@@ -277,6 +286,36 @@ void msm_rd_debugfs_cleanup(struct drm_minor *minor)
	kfree(rd);
}

static void snapshot_buf(struct msm_rd_state *rd,
		struct msm_gem_submit *submit, int idx,
		uint64_t iova, uint32_t size)
{
	struct msm_gem_object *obj = submit->bos[idx].obj;
	uint64_t offset = 0;

	if (iova) {
		offset = iova - submit->bos[idx].iova;
	} else {
		iova = submit->bos[idx].iova;
		size = obj->base.size;
	}

	/* Always write the RD_GPUADDR so we know how big the buffer is */
	rd_write_section(rd, RD_GPUADDR,
			(uint64_t[2]) { iova, size }, 16);

	/* But only dump contents for buffers marked as read and not secure */
	if (submit->bos[idx].flags & MSM_SUBMIT_BO_READ &&
		!(obj->flags & MSM_BO_SECURE)) {
		const char *buf = msm_gem_vaddr(&obj->base);

		if (IS_ERR_OR_NULL(buf))
			return;

		rd_write_section(rd, RD_BUFFER_CONTENTS, buf + offset, size);
	}
}

/* called under struct_mutex */
void msm_rd_dump_submit(struct msm_gem_submit *submit)
{
@@ -300,24 +339,20 @@ void msm_rd_dump_submit(struct msm_gem_submit *submit)

	rd_write_section(rd, RD_CMD, msg, ALIGN(n, 4));

	/* could be nice to have an option (module-param?) to snapshot
	 * all the bo's associated with the submit.  Handy to see vtx
	 * buffers, etc.  For now just the cmdstream bo's is enough.
	 */
	if (rd_full) {
		for (i = 0; i < submit->nr_bos; i++)
			snapshot_buf(rd, submit, i, 0, 0);
	}

	for (i = 0; i < submit->nr_cmds; i++) {
		uint32_t idx  = submit->cmd[i].idx;
		uint64_t iova = submit->cmd[i].iova;
		uint32_t szd  = submit->cmd[i].size; /* in dwords */
		struct msm_gem_object *obj = submit->bos[idx].obj;
		const char *buf = msm_gem_vaddr(&obj->base);

		buf += iova - submit->bos[idx].iova;

		rd_write_section(rd, RD_GPUADDR,
				(uint64_t[2]) { iova, szd * 4 }, 16);
		rd_write_section(rd, RD_BUFFER_CONTENTS,
				buf, szd * 4);
		/* snapshot cmdstream bo's (if we haven't already): */
		if (!rd_full) {
			snapshot_buf(rd, submit, submit->cmd[i].idx,
					submit->cmd[i].iova, szd * 4);
		}

		switch (submit->cmd[i].type) {
		case MSM_SUBMIT_CMD_IB_TARGET_BUF: