Commit 633aa7e5 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-misc-next-2019-10-31' of git://anongit.freedesktop.org/drm/drm-misc into drm-next



drm-misc-next for 5.5:

UAPI Changes:
-dma-buf: Introduce and revert dma-buf heap (Andrew/John/Sean)

Cross-subsystem Changes:
- None

Core Changes:
-dma-buf: add dynamic mapping to allow exporters to choose dma_resv lock
	  state on mmap/munmap (Christian)
-vram: add prepare/cleanup fb helpers to vram helpers (Thomas)
-ttm: always keep bo's on the lru + ttm cleanups (Christian)
-sched: allow a free_job routine to sleep (Steven)
-fb_helper: remove unused drm_fb_helper_defio_init() (Thomas)

Driver Changes:
-bochs/hibmc/vboxvideo: Use new vram helpers for prepare/cleanup fb (Thomas)
-amdgpu: Implement dma-buf import/export without drm helpers (Christian)
-panfrost: Simplify devfreq integration in driver (Steven)

Cc: Christian König <christian.koenig@amd.com>
Cc: Thomas Zimmermann <tzimmermann@suse.de>
Cc: Steven Price <steven.price@arm.com>
Cc: Andrew F. Davis <afd@ti.com>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Sean Paul <seanpaul@chromium.org>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Sean Paul <sean@poorly.run>
Link: https://patchwork.freedesktop.org/patch/msgid/20191031193015.GA243509@art_vandelay
parents 57c2af79 fae7d7d5
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -118,13 +118,13 @@ Kernel Functions and Structures Reference
Reservation Objects
-------------------

.. kernel-doc:: drivers/dma-buf/reservation.c
.. kernel-doc:: drivers/dma-buf/dma-resv.c
   :doc: Reservation Object Overview

.. kernel-doc:: drivers/dma-buf/reservation.c
.. kernel-doc:: drivers/dma-buf/dma-resv.c
   :export:

.. kernel-doc:: include/linux/reservation.h
.. kernel-doc:: include/linux/dma-resv.h
   :internal:

DMA Fences
+4 −4
Original line number Diff line number Diff line
@@ -206,10 +206,10 @@ Generic fbdev defio support
---------------------------

The defio support code in the fbdev core has some very specific requirements,
which means drivers need to have a special framebuffer for fbdev. Which prevents
us from using the generic fbdev emulation code everywhere. The main issue is
that it uses some fields in struct page itself, which breaks shmem gem objects
(and other things).
which means drivers need to have a special framebuffer for fbdev. The main
issue is that it uses some fields in struct page itself, which breaks shmem
gem objects (and other things). To support defio, affected drivers require
the use of a shadow buffer, which may add CPU and memory overhead.

Possible solution would be to write our own defio mmap code in the drm fbdev
emulation. It would need to fully wrap the existing mmap ops, forwarding
+95 −25
Original line number Diff line number Diff line
@@ -45,10 +45,10 @@ static char *dmabuffs_dname(struct dentry *dentry, char *buffer, int buflen)
	size_t ret = 0;

	dmabuf = dentry->d_fsdata;
	mutex_lock(&dmabuf->lock);
	dma_resv_lock(dmabuf->resv, NULL);
	if (dmabuf->name)
		ret = strlcpy(name, dmabuf->name, DMA_BUF_NAME_LEN);
	mutex_unlock(&dmabuf->lock);
	dma_resv_unlock(dmabuf->resv);

	return dynamic_dname(dentry, buffer, buflen, "/%s:%s",
			     dentry->d_name.name, ret > 0 ? name : "");
@@ -334,7 +334,7 @@ static long dma_buf_set_name(struct dma_buf *dmabuf, const char __user *buf)
	if (IS_ERR(name))
		return PTR_ERR(name);

	mutex_lock(&dmabuf->lock);
	dma_resv_lock(dmabuf->resv, NULL);
	if (!list_empty(&dmabuf->attachments)) {
		ret = -EBUSY;
		kfree(name);
@@ -344,7 +344,7 @@ static long dma_buf_set_name(struct dma_buf *dmabuf, const char __user *buf)
	dmabuf->name = name;

out_unlock:
	mutex_unlock(&dmabuf->lock);
	dma_resv_unlock(dmabuf->resv);
	return ret;
}

@@ -403,10 +403,10 @@ static void dma_buf_show_fdinfo(struct seq_file *m, struct file *file)
	/* Don't count the temporary reference taken inside procfs seq_show */
	seq_printf(m, "count:\t%ld\n", file_count(dmabuf->file) - 1);
	seq_printf(m, "exp_name:\t%s\n", dmabuf->exp_name);
	mutex_lock(&dmabuf->lock);
	dma_resv_lock(dmabuf->resv, NULL);
	if (dmabuf->name)
		seq_printf(m, "name:\t%s\n", dmabuf->name);
	mutex_unlock(&dmabuf->lock);
	dma_resv_unlock(dmabuf->resv);
}

static const struct file_operations dma_buf_fops = {
@@ -525,6 +525,10 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
		return ERR_PTR(-EINVAL);
	}

	if (WARN_ON(exp_info->ops->cache_sgt_mapping &&
		    exp_info->ops->dynamic_mapping))
		return ERR_PTR(-EINVAL);

	if (!try_module_get(exp_info->owner))
		return ERR_PTR(-ENOENT);

@@ -645,10 +649,11 @@ void dma_buf_put(struct dma_buf *dmabuf)
EXPORT_SYMBOL_GPL(dma_buf_put);

/**
 * dma_buf_attach - Add the device to dma_buf's attachments list; optionally,
 * dma_buf_dynamic_attach - Add the device to dma_buf's attachments list; optionally,
 * calls attach() of dma_buf_ops to allow device-specific attach functionality
 * @dmabuf:		[in]	buffer to attach device to.
 * @dev:		[in]	device to be attached.
 * @dynamic_mapping:	[in]	calling convention for map/unmap
 *
 * Returns struct dma_buf_attachment pointer for this attachment. Attachments
 * must be cleaned up by calling dma_buf_detach().
@@ -662,8 +667,9 @@ EXPORT_SYMBOL_GPL(dma_buf_put);
 * accessible to @dev, and cannot be moved to a more suitable place. This is
 * indicated with the error code -EBUSY.
 */
struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
					  struct device *dev)
struct dma_buf_attachment *
dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
		       bool dynamic_mapping)
{
	struct dma_buf_attachment *attach;
	int ret;
@@ -677,25 +683,69 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,

	attach->dev = dev;
	attach->dmabuf = dmabuf;

	mutex_lock(&dmabuf->lock);
	attach->dynamic_mapping = dynamic_mapping;

	if (dmabuf->ops->attach) {
		ret = dmabuf->ops->attach(dmabuf, attach);
		if (ret)
			goto err_attach;
	}
	dma_resv_lock(dmabuf->resv, NULL);
	list_add(&attach->node, &dmabuf->attachments);
	dma_resv_unlock(dmabuf->resv);

	mutex_unlock(&dmabuf->lock);
	/* When either the importer or the exporter can't handle dynamic
	 * mappings we cache the mapping here to avoid issues with the
	 * reservation object lock.
	 */
	if (dma_buf_attachment_is_dynamic(attach) !=
	    dma_buf_is_dynamic(dmabuf)) {
		struct sg_table *sgt;

		if (dma_buf_is_dynamic(attach->dmabuf))
			dma_resv_lock(attach->dmabuf->resv, NULL);

		sgt = dmabuf->ops->map_dma_buf(attach, DMA_BIDIRECTIONAL);
		if (!sgt)
			sgt = ERR_PTR(-ENOMEM);
		if (IS_ERR(sgt)) {
			ret = PTR_ERR(sgt);
			goto err_unlock;
		}
		if (dma_buf_is_dynamic(attach->dmabuf))
			dma_resv_unlock(attach->dmabuf->resv);
		attach->sgt = sgt;
		attach->dir = DMA_BIDIRECTIONAL;
	}

	return attach;

err_attach:
	kfree(attach);
	mutex_unlock(&dmabuf->lock);
	return ERR_PTR(ret);

err_unlock:
	if (dma_buf_is_dynamic(attach->dmabuf))
		dma_resv_unlock(attach->dmabuf->resv);

	dma_buf_detach(dmabuf, attach);
	return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(dma_buf_dynamic_attach);

/**
 * dma_buf_attach - Wrapper for dma_buf_dynamic_attach
 * @dmabuf:	[in]	buffer to attach device to.
 * @dev:	[in]	device to be attached.
 *
 * Wrapper to call dma_buf_dynamic_attach() for drivers which still use a static
 * mapping.
 */
struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
					  struct device *dev)
{
	return dma_buf_dynamic_attach(dmabuf, dev, false);
}
EXPORT_SYMBOL_GPL(dma_buf_attach);

/**
@@ -711,15 +761,22 @@ void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach)
	if (WARN_ON(!dmabuf || !attach))
		return;

	if (attach->sgt)
	if (attach->sgt) {
		if (dma_buf_is_dynamic(attach->dmabuf))
			dma_resv_lock(attach->dmabuf->resv, NULL);

		dmabuf->ops->unmap_dma_buf(attach, attach->sgt, attach->dir);

	mutex_lock(&dmabuf->lock);
		if (dma_buf_is_dynamic(attach->dmabuf))
			dma_resv_unlock(attach->dmabuf->resv);
	}

	dma_resv_lock(dmabuf->resv, NULL);
	list_del(&attach->node);
	dma_resv_unlock(dmabuf->resv);
	if (dmabuf->ops->detach)
		dmabuf->ops->detach(dmabuf, attach);

	mutex_unlock(&dmabuf->lock);
	kfree(attach);
}
EXPORT_SYMBOL_GPL(dma_buf_detach);
@@ -749,6 +806,9 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
	if (WARN_ON(!attach || !attach->dmabuf))
		return ERR_PTR(-EINVAL);

	if (dma_buf_attachment_is_dynamic(attach))
		dma_resv_assert_held(attach->dmabuf->resv);

	if (attach->sgt) {
		/*
		 * Two mappings with different directions for the same
@@ -761,6 +821,9 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
		return attach->sgt;
	}

	if (dma_buf_is_dynamic(attach->dmabuf))
		dma_resv_assert_held(attach->dmabuf->resv);

	sg_table = attach->dmabuf->ops->map_dma_buf(attach, direction);
	if (!sg_table)
		sg_table = ERR_PTR(-ENOMEM);
@@ -793,9 +856,15 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment *attach,
	if (WARN_ON(!attach || !attach->dmabuf || !sg_table))
		return;

	if (dma_buf_attachment_is_dynamic(attach))
		dma_resv_assert_held(attach->dmabuf->resv);

	if (attach->sgt == sg_table)
		return;

	if (dma_buf_is_dynamic(attach->dmabuf))
		dma_resv_assert_held(attach->dmabuf->resv);

	attach->dmabuf->ops->unmap_dma_buf(attach, sg_table, direction);
}
EXPORT_SYMBOL_GPL(dma_buf_unmap_attachment);
@@ -1171,13 +1240,10 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
		   "size", "flags", "mode", "count", "ino");

	list_for_each_entry(buf_obj, &db_list.head, list_node) {
		ret = mutex_lock_interruptible(&buf_obj->lock);

		if (ret) {
			seq_puts(s,
				 "\tERROR locking buffer object: skipping\n");
			continue;
		}
		ret = dma_resv_lock_interruptible(buf_obj->resv, NULL);
		if (ret)
			goto error_unlock;

		seq_printf(s, "%08zu\t%08x\t%08x\t%08ld\t%s\t%08lu\t%s\n",
				buf_obj->size,
@@ -1223,19 +1289,23 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
			seq_printf(s, "\t%s\n", dev_name(attach_obj->dev));
			attach_count++;
		}
		dma_resv_unlock(buf_obj->resv);

		seq_printf(s, "Total %d devices attached\n\n",
				attach_count);

		count++;
		size += buf_obj->size;
		mutex_unlock(&buf_obj->lock);
	}

	seq_printf(s, "\nTotal %d objects, %zu bytes\n", count, size);

	mutex_unlock(&db_list.lock);
	return 0;

error_unlock:
	mutex_unlock(&db_list.lock);
	return ret;
}

DEFINE_SHOW_ATTRIBUTE(dma_buf_debug);
+4 −5
Original line number Diff line number Diff line
@@ -613,7 +613,7 @@ static int reserve_bo_and_vm(struct kgd_mem *mem,
	amdgpu_vm_get_pd_bo(vm, &ctx->list, &ctx->vm_pd[0]);

	ret = ttm_eu_reserve_buffers(&ctx->ticket, &ctx->list,
				     false, &ctx->duplicates, true);
				     false, &ctx->duplicates);
	if (!ret)
		ctx->reserved = true;
	else {
@@ -686,7 +686,7 @@ static int reserve_bo_and_cond_vms(struct kgd_mem *mem,
	}

	ret = ttm_eu_reserve_buffers(&ctx->ticket, &ctx->list,
				     false, &ctx->duplicates, true);
				     false, &ctx->duplicates);
	if (!ret)
		ctx->reserved = true;
	else
@@ -1805,8 +1805,7 @@ static int validate_invalid_user_pages(struct amdkfd_process_info *process_info)
	}

	/* Reserve all BOs and page tables for validation */
	ret = ttm_eu_reserve_buffers(&ticket, &resv_list, false, &duplicates,
				     true);
	ret = ttm_eu_reserve_buffers(&ticket, &resv_list, false, &duplicates);
	WARN(!list_empty(&duplicates), "Duplicates should be empty");
	if (ret)
		goto out_free;
@@ -2004,7 +2003,7 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence **ef)
	}

	ret = ttm_eu_reserve_buffers(&ctx.ticket, &ctx.list,
				     false, &duplicate_save, true);
				     false, &duplicate_save);
	if (ret) {
		pr_debug("Memory eviction: TTM Reserve Failed. Try again\n");
		goto ttm_reserve_fail;
+1 −1
Original line number Diff line number Diff line
@@ -581,7 +581,7 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
	}

	r = ttm_eu_reserve_buffers(&p->ticket, &p->validated, true,
				   &duplicates, false);
				   &duplicates);
	if (unlikely(r != 0)) {
		if (r != -ERESTARTSYS)
			DRM_ERROR("ttm_eu_reserve_buffers failed.\n");
Loading