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

Commit 84807727 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'drm-next-4.2' of git://people.freedesktop.org/~agd5f/linux

Pull radeon and amdgpu fixes from Alex Deucher:
 "First round of fixes for 4.2 for radeon and amdgpu.  Stuff all over
  the place:

   - hibernation, suspend fixes for radeon and amdgpu
   - radeon audio fix
   - amdgpu ioctl optimzations and fixes
   - amdgpu VCE cs checker improvements
   - misc bug fixes"

[ Dave on vacation, pulling directly ]

* 'drm-next-4.2' of git://people.freedesktop.org/~agd5f/linux: (30 commits)
  drm/radeon: only check the sink type on DP connectors
  drm/amdgpu: add flag to delay VM updates
  drm/amdgpu: add optional dependencies to the CS IOCTL v2
  drm/amdgpu: recreate fence from user seq
  gpu/drm/amdgpu: Fix build when CONFIG_DEBUG_FS is not set
  Revert "drm/radeon: dont switch vt on suspend"
  drm/amdgpu: disable enable_nb_ps_policy temporarily
  drm/amdgpu: correct define SMU_EnabledFeatureScoreboard_SclkDpmOn
  drm/amdgpu: allocate ip_block_enabled memory in common code
  drm/amdgpu: remove unnecessary check before kfree
  drm/amdgpu: use kzalloc for allocating one thing
  drm/radeon: fix adding all VAs to the freed list on remove v2
  drm/amdgpu: add chunk id validity check
  drm/amdgpu: fix crash on invalid CS IOCTL
  drm/amdgpu: reset wptr at cp compute resume (v2)
  drm/amdgpu: check VCE feedback and bitstream index
  drm/amdgpu: make VCE handle check more strict
  drm/amdgpu: check VCE relocation buffer range
  drm/amdgpu: silence invalid error message
  drm/amdgpu: fix wrong type
  ...
parents c021bf1e 479e9a95
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -425,6 +425,8 @@ int amdgpu_fence_driver_start_ring(struct amdgpu_ring *ring,
				   unsigned irq_type);
int amdgpu_fence_emit(struct amdgpu_ring *ring, void *owner,
		      struct amdgpu_fence **fence);
int amdgpu_fence_recreate(struct amdgpu_ring *ring, void *owner,
			  uint64_t seq, struct amdgpu_fence **fence);
void amdgpu_fence_process(struct amdgpu_ring *ring);
int amdgpu_fence_wait_next(struct amdgpu_ring *ring);
int amdgpu_fence_wait_empty(struct amdgpu_ring *ring);
@@ -435,9 +437,6 @@ int amdgpu_fence_wait(struct amdgpu_fence *fence, bool interruptible);
int amdgpu_fence_wait_any(struct amdgpu_device *adev,
			  struct amdgpu_fence **fences,
			  bool intr);
long amdgpu_fence_wait_seq_timeout(struct amdgpu_device *adev,
				   u64 *target_seq, bool intr,
				   long timeout);
struct amdgpu_fence *amdgpu_fence_ref(struct amdgpu_fence *fence);
void amdgpu_fence_unref(struct amdgpu_fence **fence);

@@ -1622,6 +1621,7 @@ struct amdgpu_vce {
	unsigned		fb_version;
	atomic_t		handles[AMDGPU_MAX_VCE_HANDLES];
	struct drm_file		*filp[AMDGPU_MAX_VCE_HANDLES];
	uint32_t		img_size[AMDGPU_MAX_VCE_HANDLES];
	struct delayed_work	idle_work;
	const struct firmware	*fw;	/* VCE firmware */
	struct amdgpu_ring	ring[AMDGPU_MAX_VCE_RINGS];
+3 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@

#include <drm/drmP.h>
#include "amdgpu.h"
#include "amdgpu_trace.h"

static int amdgpu_bo_list_create(struct amdgpu_fpriv *fpriv,
				 struct amdgpu_bo_list **result,
@@ -124,6 +125,8 @@ static int amdgpu_bo_list_set(struct amdgpu_device *adev,
			gws_obj = entry->robj;
		if (entry->prefered_domains == AMDGPU_GEM_DOMAIN_OA)
			oa_obj = entry->robj;

		trace_amdgpu_bo_list_set(list, entry->robj);
	}

	for (i = 0; i < list->num_entries; ++i)
+79 −10
Original line number Diff line number Diff line
@@ -181,8 +181,6 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
		}
		p->chunks[i].chunk_id = user_chunk.chunk_id;
		p->chunks[i].length_dw = user_chunk.length_dw;
		if (p->chunks[i].chunk_id == AMDGPU_CHUNK_ID_IB)
			p->num_ibs++;

		size = p->chunks[i].length_dw;
		cdata = (void __user *)(unsigned long)user_chunk.chunk_data;
@@ -199,7 +197,12 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
			goto out;
		}

		if (p->chunks[i].chunk_id == AMDGPU_CHUNK_ID_FENCE) {
		switch (p->chunks[i].chunk_id) {
		case AMDGPU_CHUNK_ID_IB:
			p->num_ibs++;
			break;

		case AMDGPU_CHUNK_ID_FENCE:
			size = sizeof(struct drm_amdgpu_cs_chunk_fence);
			if (p->chunks[i].length_dw * sizeof(uint32_t) >= size) {
				uint32_t handle;
@@ -221,6 +224,14 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
				r = -EINVAL;
				goto out;
			}
			break;

		case AMDGPU_CHUNK_ID_DEPENDENCIES:
			break;

		default:
			r = -EINVAL;
			goto out;
		}
	}

@@ -445,6 +456,7 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bo
	for (i = 0; i < parser->nchunks; i++)
		drm_free_large(parser->chunks[i].kdata);
	kfree(parser->chunks);
	if (parser->ibs)
		for (i = 0; i < parser->num_ibs; i++)
			amdgpu_ib_free(parser->adev, &parser->ibs[i]);
	kfree(parser->ibs);
@@ -654,6 +666,55 @@ static int amdgpu_cs_ib_fill(struct amdgpu_device *adev,
	return 0;
}

static int amdgpu_cs_dependencies(struct amdgpu_device *adev,
				  struct amdgpu_cs_parser *p)
{
	struct amdgpu_ib *ib;
	int i, j, r;

	if (!p->num_ibs)
		return 0;

	/* Add dependencies to first IB */
	ib = &p->ibs[0];
	for (i = 0; i < p->nchunks; ++i) {
		struct drm_amdgpu_cs_chunk_dep *deps;
		struct amdgpu_cs_chunk *chunk;
		unsigned num_deps;

		chunk = &p->chunks[i];

		if (chunk->chunk_id != AMDGPU_CHUNK_ID_DEPENDENCIES)
			continue;

		deps = (struct drm_amdgpu_cs_chunk_dep *)chunk->kdata;
		num_deps = chunk->length_dw * 4 /
			sizeof(struct drm_amdgpu_cs_chunk_dep);

		for (j = 0; j < num_deps; ++j) {
			struct amdgpu_fence *fence;
			struct amdgpu_ring *ring;

			r = amdgpu_cs_get_ring(adev, deps[j].ip_type,
					       deps[j].ip_instance,
					       deps[j].ring, &ring);
			if (r)
				return r;

			r = amdgpu_fence_recreate(ring, p->filp,
						  deps[j].handle,
						  &fence);
			if (r)
				return r;

			amdgpu_sync_fence(&ib->sync, fence);
			amdgpu_fence_unref(&fence);
		}
	}

	return 0;
}

int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
{
	struct amdgpu_device *adev = dev->dev_private;
@@ -688,11 +749,16 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
			else
				DRM_ERROR("Failed to process the buffer list %d!\n", r);
		}
	} else {
	}

	if (!r) {
		reserved_buffers = true;
		r = amdgpu_cs_ib_fill(adev, &parser);
	}

	if (!r)
		r = amdgpu_cs_dependencies(adev, &parser);

	if (r) {
		amdgpu_cs_parser_fini(&parser, r, reserved_buffers);
		up_read(&adev->exclusive_lock);
@@ -730,9 +796,9 @@ int amdgpu_cs_wait_ioctl(struct drm_device *dev, void *data,
{
	union drm_amdgpu_wait_cs *wait = data;
	struct amdgpu_device *adev = dev->dev_private;
	uint64_t seq[AMDGPU_MAX_RINGS] = {0};
	struct amdgpu_ring *ring = NULL;
	unsigned long timeout = amdgpu_gem_timeout(wait->in.timeout);
	struct amdgpu_fence *fence = NULL;
	struct amdgpu_ring *ring = NULL;
	struct amdgpu_ctx *ctx;
	long r;

@@ -745,9 +811,12 @@ int amdgpu_cs_wait_ioctl(struct drm_device *dev, void *data,
	if (r)
		return r;

	seq[ring->idx] = wait->in.handle;
	r = amdgpu_fence_recreate(ring, filp, wait->in.handle, &fence);
	if (r)
		return r;

	r = amdgpu_fence_wait_seq_timeout(adev, seq, true, timeout);
	r = fence_wait_timeout(&fence->base, true, timeout);
	amdgpu_fence_unref(&fence);
	amdgpu_ctx_put(ctx);
	if (r < 0)
		return r;
+10 −3
Original line number Diff line number Diff line
@@ -1191,7 +1191,9 @@ static int amdgpu_early_init(struct amdgpu_device *adev)
		return -EINVAL;
	}


	adev->ip_block_enabled = kcalloc(adev->num_ip_blocks, sizeof(bool), GFP_KERNEL);
	if (adev->ip_block_enabled == NULL)
		return -ENOMEM;

	if (adev->ip_blocks == NULL) {
		DRM_ERROR("No IP blocks found!\n");
@@ -1575,7 +1577,6 @@ void amdgpu_device_fini(struct amdgpu_device *adev)
	amdgpu_fence_driver_fini(adev);
	amdgpu_fbdev_fini(adev);
	r = amdgpu_fini(adev);
	if (adev->ip_block_enabled)
	kfree(adev->ip_block_enabled);
	adev->ip_block_enabled = NULL;
	adev->accel_working = false;
@@ -2000,4 +2001,10 @@ int amdgpu_debugfs_init(struct drm_minor *minor)
void amdgpu_debugfs_cleanup(struct drm_minor *minor)
{
}
#else
static int amdgpu_debugfs_regs_init(struct amdgpu_device *adev)
{
	return 0;
}
static void amdgpu_debugfs_regs_cleanup(struct amdgpu_device *adev) { }
#endif
+40 −5
Original line number Diff line number Diff line
@@ -135,6 +135,38 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, void *owner,
	return 0;
}

/**
 * amdgpu_fence_recreate - recreate a fence from an user fence
 *
 * @ring: ring the fence is associated with
 * @owner: creator of the fence
 * @seq: user fence sequence number
 * @fence: resulting amdgpu fence object
 *
 * Recreates a fence command from the user fence sequence number (all asics).
 * Returns 0 on success, -ENOMEM on failure.
 */
int amdgpu_fence_recreate(struct amdgpu_ring *ring, void *owner,
			  uint64_t seq, struct amdgpu_fence **fence)
{
	struct amdgpu_device *adev = ring->adev;

	if (seq > ring->fence_drv.sync_seq[ring->idx])
		return -EINVAL;

	*fence = kmalloc(sizeof(struct amdgpu_fence), GFP_KERNEL);
	if ((*fence) == NULL)
		return -ENOMEM;

	(*fence)->seq = seq;
	(*fence)->ring = ring;
	(*fence)->owner = owner;
	fence_init(&(*fence)->base, &amdgpu_fence_ops,
		&adev->fence_queue.lock, adev->fence_context + ring->idx,
		(*fence)->seq);
	return 0;
}

/**
 * amdgpu_fence_check_signaled - callback from fence_queue
 *
@@ -517,12 +549,14 @@ static bool amdgpu_fence_any_seq_signaled(struct amdgpu_device *adev, u64 *seq)
 * the wait timeout, or an error for all other cases.
 * -EDEADLK is returned when a GPU lockup has been detected.
 */
long amdgpu_fence_wait_seq_timeout(struct amdgpu_device *adev, u64 *target_seq,
				   bool intr, long timeout)
static long amdgpu_fence_wait_seq_timeout(struct amdgpu_device *adev,
					  u64 *target_seq, bool intr,
					  long timeout)
{
	uint64_t last_seq[AMDGPU_MAX_RINGS];
	bool signaled;
	int i, r;
	int i;
	long r;

	if (timeout == 0) {
		return amdgpu_fence_any_seq_signaled(adev, target_seq);
@@ -1023,7 +1057,7 @@ static int amdgpu_debugfs_fence_info(struct seq_file *m, void *data)

		amdgpu_fence_process(ring);

		seq_printf(m, "--- ring %d ---\n", i);
		seq_printf(m, "--- ring %d (%s) ---\n", i, ring->name);
		seq_printf(m, "Last signaled fence 0x%016llx\n",
			   (unsigned long long)atomic64_read(&ring->fence_drv.last_seq));
		seq_printf(m, "Last emitted        0x%016llx\n",
@@ -1031,7 +1065,8 @@ static int amdgpu_debugfs_fence_info(struct seq_file *m, void *data)

		for (j = 0; j < AMDGPU_MAX_RINGS; ++j) {
			struct amdgpu_ring *other = adev->rings[j];
			if (i != j && other && other->fence_drv.initialized)
			if (i != j && other && other->fence_drv.initialized &&
			    ring->fence_drv.sync_seq[j])
				seq_printf(m, "Last sync to ring %d 0x%016llx\n",
					   j, ring->fence_drv.sync_seq[j]);
		}
Loading