Example #1
0
int
drm_reservation_cb_add(struct drm_reservation_cb *rcb,
			struct reservation_object *resv, bool exclusive)
{
	int ret = 0;
	struct fence *fence;
	unsigned shared_count = 0, f;
	struct fence **shared_fences = NULL;

	/* enum all the fences in the reservation and add callbacks */
	ret = reservation_object_get_fences_rcu(resv, &fence,
					&shared_count, &shared_fences);
	if (ret < 0)
		return ret;

	if (fence) {
		ret = reservation_cb_add_fence_cb(rcb, fence);
		if (ret < 0) {
			reservation_cb_cleanup(rcb);
			goto error;
		}
	}

	if (exclusive) {
		for (f = 0; f < shared_count; f++) {
			ret = reservation_cb_add_fence_cb(rcb,
						shared_fences[f]);
			if (ret < 0) {
				reservation_cb_cleanup(rcb);
				goto error;
			}
		}
	}

error:
	if (fence)
		fence_put(fence);
	if (shared_fences) {
		for (f = 0; f < shared_count; f++)
			fence_put(shared_fences[f]);
		kfree(shared_fences);
	}
	return ret;
}
Example #2
0
static int ipu_page_flip(struct drm_crtc *crtc,
		struct drm_framebuffer *fb,
		struct drm_pending_vblank_event *event,
		uint32_t page_flip_flags)
{
	struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
	struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
	struct ipu_flip_work *flip_work;
	int ret;

	if (ipu_crtc->flip_state != IPU_FLIP_NONE)
		return -EBUSY;

	ret = imx_drm_crtc_vblank_get(ipu_crtc->imx_crtc);
	if (ret) {
		dev_dbg(ipu_crtc->dev, "failed to acquire vblank counter\n");
		list_del(&event->base.link);

		return ret;
	}

	flip_work = kzalloc(sizeof *flip_work, GFP_KERNEL);
	if (!flip_work) {
		ret = -ENOMEM;
		goto put_vblank;
	}
	INIT_WORK(&flip_work->unref_work, ipu_flip_unref_work_func);
	flip_work->page_flip_event = event;

	/* get BO backing the old framebuffer and take a reference */
	flip_work->bo = &drm_fb_cma_get_gem_obj(crtc->primary->fb, 0)->base;
	drm_gem_object_reference(flip_work->bo);

	ipu_crtc->flip_work = flip_work;
	/*
	 * If the object has a DMABUF attached, we need to wait on its fences
	 * if there are any.
	 */
	if (cma_obj->base.dma_buf) {
		INIT_WORK(&flip_work->fence_work, ipu_flip_fence_work_func);
		flip_work->crtc = ipu_crtc;

		ret = reservation_object_get_fences_rcu(
				cma_obj->base.dma_buf->resv, &flip_work->excl,
				&flip_work->shared_count, &flip_work->shared);

		if (unlikely(ret)) {
			DRM_ERROR("failed to get fences for buffer\n");
			goto free_flip_work;
		}

		/* No need to queue the worker if the are no fences */
		if (!flip_work->excl && !flip_work->shared_count) {
			ipu_crtc->flip_state = IPU_FLIP_SUBMITTED;
		} else {
			ipu_crtc->flip_state = IPU_FLIP_PENDING;
			queue_work(ipu_crtc->flip_queue,
				   &flip_work->fence_work);
		}
	} else {
		ipu_crtc->flip_state = IPU_FLIP_SUBMITTED;
	}

	return 0;

free_flip_work:
	drm_gem_object_unreference_unlocked(flip_work->bo);
	kfree(flip_work);
	ipu_crtc->flip_work = NULL;
put_vblank:
	imx_drm_crtc_vblank_put(ipu_crtc->imx_crtc);

	return ret;
}