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

Commit abfe262a authored by John Harrison's avatar John Harrison Committed by Daniel Vetter
Browse files

drm/i915: Add reference count to request structure



The plan is to use request structures everywhere that seqno values were
previously used. This means saving pointers to structures in places that used to
be simple integers. In turn, that means that the target structure now needs much
more stringent lifetime tracking. That is, it must not be freed while some other
random object still holds a pointer to it.

To achieve this tracking, a reference count needs to be added. Whenever a
pointer to the structure is saved away, the count must be incremented and the
free must only occur when all references have been released.

For: VIZ-4377
Signed-off-by: default avatarJohn Harrison <John.C.Harrison@Intel.com>
Reviewed-by: default avatarThomas Daniel <Thomas.Daniel@intel.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 9eba5d4a
Loading
Loading
Loading
Loading
+28 −0
Original line number Original line Diff line number Diff line
@@ -1991,6 +1991,8 @@ void i915_gem_track_fb(struct drm_i915_gem_object *old,
 * an emission time with seqnos for tracking how far ahead of the GPU we are.
 * an emission time with seqnos for tracking how far ahead of the GPU we are.
 */
 */
struct drm_i915_gem_request {
struct drm_i915_gem_request {
	struct kref ref;

	/** On Which ring this request was generated */
	/** On Which ring this request was generated */
	struct intel_engine_cs *ring;
	struct intel_engine_cs *ring;


@@ -2020,6 +2022,32 @@ struct drm_i915_gem_request {
	struct list_head client_list;
	struct list_head client_list;
};
};


void i915_gem_request_free(struct kref *req_ref);

static inline void
i915_gem_request_reference(struct drm_i915_gem_request *req)
{
	kref_get(&req->ref);
}

static inline void
i915_gem_request_unreference(struct drm_i915_gem_request *req)
{
	kref_put(&req->ref, i915_gem_request_free);
}

static inline void i915_gem_request_assign(struct drm_i915_gem_request **pdst,
					   struct drm_i915_gem_request *src)
{
	if (src)
		i915_gem_request_reference(src);

	if (*pdst)
		i915_gem_request_unreference(*pdst);

	*pdst = src;
}

struct drm_i915_file_private {
struct drm_i915_file_private {
	struct drm_i915_private *dev_priv;
	struct drm_i915_private *dev_priv;
	struct drm_file *file;
	struct drm_file *file;
+14 −6
Original line number Original line Diff line number Diff line
@@ -2569,21 +2569,30 @@ static void i915_set_reset_status(struct drm_i915_private *dev_priv,


static void i915_gem_free_request(struct drm_i915_gem_request *request)
static void i915_gem_free_request(struct drm_i915_gem_request *request)
{
{
	struct intel_context *ctx = request->ctx;

	list_del(&request->list);
	list_del(&request->list);
	i915_gem_request_remove_from_client(request);
	i915_gem_request_remove_from_client(request);


	i915_gem_request_unreference(request);
}

void i915_gem_request_free(struct kref *req_ref)
{
	struct drm_i915_gem_request *req = container_of(req_ref,
						 typeof(*req), ref);
	struct intel_context *ctx = req->ctx;

	if (ctx) {
	if (ctx) {
		if (i915.enable_execlists) {
		if (i915.enable_execlists) {
			struct intel_engine_cs *ring = request->ring;
			struct intel_engine_cs *ring = req->ring;


			if (ctx != ring->default_context)
			if (ctx != ring->default_context)
				intel_lr_context_unpin(ring, ctx);
				intel_lr_context_unpin(ring, ctx);
		}
		}

		i915_gem_context_unreference(ctx);
		i915_gem_context_unreference(ctx);
	}
	}
	kfree(request);

	kfree(req);
}
}


struct drm_i915_gem_request *
struct drm_i915_gem_request *
@@ -2671,8 +2680,7 @@ static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv,
	}
	}


	/* These may not have been flush before the reset, do so now */
	/* These may not have been flush before the reset, do so now */
	kfree(ring->preallocated_lazy_request);
	i915_gem_request_assign(&ring->preallocated_lazy_request, NULL);
	ring->preallocated_lazy_request = NULL;
	ring->outstanding_lazy_seqno = 0;
	ring->outstanding_lazy_seqno = 0;
}
}


+3 −1
Original line number Original line Diff line number Diff line
@@ -905,6 +905,8 @@ static int logical_ring_alloc_seqno(struct intel_engine_cs *ring,
		}
		}
	}
	}


	kref_init(&request->ref);

	ret = i915_gem_get_seqno(ring->dev, &ring->outstanding_lazy_seqno);
	ret = i915_gem_get_seqno(ring->dev, &ring->outstanding_lazy_seqno);
	if (ret) {
	if (ret) {
		intel_lr_context_unpin(ring, ctx);
		intel_lr_context_unpin(ring, ctx);
@@ -1374,7 +1376,7 @@ void intel_logical_ring_cleanup(struct intel_engine_cs *ring)


	intel_logical_ring_stop(ring);
	intel_logical_ring_stop(ring);
	WARN_ON((I915_READ_MODE(ring) & MODE_IDLE) == 0);
	WARN_ON((I915_READ_MODE(ring) & MODE_IDLE) == 0);
	ring->preallocated_lazy_request = NULL;
	i915_gem_request_assign(&ring->preallocated_lazy_request, NULL);
	ring->outstanding_lazy_seqno = 0;
	ring->outstanding_lazy_seqno = 0;


	if (ring->cleanup)
	if (ring->cleanup)
+3 −1
Original line number Original line Diff line number Diff line
@@ -1870,7 +1870,7 @@ void intel_cleanup_ring_buffer(struct intel_engine_cs *ring)


	intel_unpin_ringbuffer_obj(ringbuf);
	intel_unpin_ringbuffer_obj(ringbuf);
	intel_destroy_ringbuffer_obj(ringbuf);
	intel_destroy_ringbuffer_obj(ringbuf);
	ring->preallocated_lazy_request = NULL;
	i915_gem_request_assign(&ring->preallocated_lazy_request, NULL);
	ring->outstanding_lazy_seqno = 0;
	ring->outstanding_lazy_seqno = 0;


	if (ring->cleanup)
	if (ring->cleanup)
@@ -2043,6 +2043,8 @@ intel_ring_alloc_seqno(struct intel_engine_cs *ring)
	if (request == NULL)
	if (request == NULL)
		return -ENOMEM;
		return -ENOMEM;


	kref_init(&request->ref);

	ret = i915_gem_get_seqno(ring->dev, &ring->outstanding_lazy_seqno);
	ret = i915_gem_get_seqno(ring->dev, &ring->outstanding_lazy_seqno);
	if (ret) {
	if (ret) {
		kfree(request);
		kfree(request);