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

Commit 2cca4557 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'topic/drm-misc-2016-06-07' of git://anongit.freedesktop.org/drm-intel into drm-next

As promised, piles of prep work all around:
- drm_atomic_state rework, prep for nonblocking commit helpers
- fence patches from Gustavo and Christian to prep for atomic fences and
  some cool work in ttm/amdgpu from Christian
- drm event prep for both nonblocking commit and atomic fences
- Gustavo seems on a crusade against the non-kms-native version of the
  vblank functions.
- prep work from Boris to nuke all the silly ->best_encoder
  implementations we have (we really only need that for truly dynamic
  cases like dvi-i vs dvi-d or dp mst selecting the right transcoder on
  intel)
- prep work from Laurent to rework the format handling functions
- and few small things all over

* tag 'topic/drm-misc-2016-06-07' of git://anongit.freedesktop.org/drm-intel: (47 commits)
  drm/dsi: Implement set tear scanline
  drm/fb_cma_helper: Implement fb_mmap callback
  drm/qxl: Remove useless drm_fb_get_bpp_depth() call
  drm/ast: Remove useless drm_fb_get_bpp_depth() call
  drm/atomic: Fix remaining places where !funcs->best_encoder is valid
  drm/core: Change declaration for gamma_set.
  Documentation: add fence-array to kernel DocBook
  drm/shmobile: use drm_crtc_vblank_{get,put}()
  drm/radeon: use drm_crtc_vblank_{get,put}()
  drm/qxl: use drm_crtc_vblank_{get,put}()
  drm/atmel: use drm_crtc_vblank_{get,put}()
  drm/armada: use drm_crtc_vblank_{get,put}()
  drm/amdgpu: use drm_crtc_vblank_{get,put}()
  drm/virtio: use drm_crtc_send_vblank_event()
  drm/udl: use drm_crtc_send_vblank_event()
  drm/qxl: use drm_crtc_send_vblank_event()
  drm/atmel: use drm_crtc_send_vblank_event()
  drm/armada: use drm_crtc_send_vblank_event()
  drm/doc: Switch to sphinx/rst fixed-width quoting
  drm/doc: Drop kerneldoc for static functions in drm_irq.c
  ...
parents bb4cec02 e8395081
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -161,6 +161,10 @@ X!Edrivers/base/interface.c
!Iinclude/linux/fence.h
!Edrivers/dma-buf/seqno-fence.c
!Iinclude/linux/seqno-fence.h
!Edrivers/dma-buf/fence-array.c
!Iinclude/linux/fence-array.h
!Edrivers/dma-buf/reservation.c
!Iinclude/linux/reservation.h
!Edrivers/dma-buf/sync_file.c
!Iinclude/linux/sync_file.h
       </sect2>
+1 −1
Original line number Diff line number Diff line
@@ -1570,7 +1570,7 @@ void intel_crt_init(struct drm_device *dev)
      </sect3>
      <sect3>
	<title>Implementing Asynchronous Atomic Commit</title>
!Pdrivers/gpu/drm/drm_atomic_helper.c implementing async commit
!Pdrivers/gpu/drm/drm_atomic_helper.c implementing nonblocking commit
      </sect3>
      <sect3>
	<title>Atomic State Reset and Initialization</title>
+1 −1
Original line number Diff line number Diff line
obj-y := dma-buf.o fence.o reservation.o seqno-fence.o
obj-y := dma-buf.o fence.o reservation.o seqno-fence.o fence-array.o
obj-$(CONFIG_SYNC_FILE)		+= sync_file.o
+144 −0
Original line number Diff line number Diff line
/*
 * fence-array: aggregate fences to be waited together
 *
 * Copyright (C) 2016 Collabora Ltd
 * Copyright (C) 2016 Advanced Micro Devices, Inc.
 * Authors:
 *	Gustavo Padovan <gustavo@padovan.org>
 *	Christian König <christian.koenig@amd.com>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 as published by
 * the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 */

#include <linux/export.h>
#include <linux/slab.h>
#include <linux/fence-array.h>

static void fence_array_cb_func(struct fence *f, struct fence_cb *cb);

static const char *fence_array_get_driver_name(struct fence *fence)
{
	return "fence_array";
}

static const char *fence_array_get_timeline_name(struct fence *fence)
{
	return "unbound";
}

static void fence_array_cb_func(struct fence *f, struct fence_cb *cb)
{
	struct fence_array_cb *array_cb =
		container_of(cb, struct fence_array_cb, cb);
	struct fence_array *array = array_cb->array;

	if (atomic_dec_and_test(&array->num_pending))
		fence_signal(&array->base);
	fence_put(&array->base);
}

static bool fence_array_enable_signaling(struct fence *fence)
{
	struct fence_array *array = to_fence_array(fence);
	struct fence_array_cb *cb = (void *)(&array[1]);
	unsigned i;

	for (i = 0; i < array->num_fences; ++i) {
		cb[i].array = array;
		/*
		 * As we may report that the fence is signaled before all
		 * callbacks are complete, we need to take an additional
		 * reference count on the array so that we do not free it too
		 * early. The core fence handling will only hold the reference
		 * until we signal the array as complete (but that is now
		 * insufficient).
		 */
		fence_get(&array->base);
		if (fence_add_callback(array->fences[i], &cb[i].cb,
				       fence_array_cb_func)) {
			fence_put(&array->base);
			if (atomic_dec_and_test(&array->num_pending))
				return false;
		}
	}

	return true;
}

static bool fence_array_signaled(struct fence *fence)
{
	struct fence_array *array = to_fence_array(fence);

	return atomic_read(&array->num_pending) <= 0;
}

static void fence_array_release(struct fence *fence)
{
	struct fence_array *array = to_fence_array(fence);
	unsigned i;

	for (i = 0; i < array->num_fences; ++i)
		fence_put(array->fences[i]);

	kfree(array->fences);
	fence_free(fence);
}

const struct fence_ops fence_array_ops = {
	.get_driver_name = fence_array_get_driver_name,
	.get_timeline_name = fence_array_get_timeline_name,
	.enable_signaling = fence_array_enable_signaling,
	.signaled = fence_array_signaled,
	.wait = fence_default_wait,
	.release = fence_array_release,
};

/**
 * fence_array_create - Create a custom fence array
 * @num_fences:		[in]	number of fences to add in the array
 * @fences:		[in]	array containing the fences
 * @context:		[in]	fence context to use
 * @seqno:		[in]	sequence number to use
 * @signal_on_any	[in]	signal on any fence in the array
 *
 * Allocate a fence_array object and initialize the base fence with fence_init().
 * In case of error it returns NULL.
 *
 * The caller should allocte the fences array with num_fences size
 * and fill it with the fences it wants to add to the object. Ownership of this
 * array is take and fence_put() is used on each fence on release.
 *
 * If @signal_on_any is true the fence array signals if any fence in the array
 * signals, otherwise it signals when all fences in the array signal.
 */
struct fence_array *fence_array_create(int num_fences, struct fence **fences,
				       u64 context, unsigned seqno,
				       bool signal_on_any)
{
	struct fence_array *array;
	size_t size = sizeof(*array);

	/* Allocate the callback structures behind the array. */
	size += num_fences * sizeof(struct fence_array_cb);
	array = kzalloc(size, GFP_KERNEL);
	if (!array)
		return NULL;

	spin_lock_init(&array->lock);
	fence_init(&array->base, &fence_array_ops, &array->lock,
		   context, seqno);

	array->num_fences = num_fences;
	atomic_set(&array->num_pending, signal_on_any ? 1 : num_fences);
	array->fences = fences;

	return array;
}
EXPORT_SYMBOL(fence_array_create);
+4 −4
Original line number Diff line number Diff line
@@ -35,7 +35,7 @@ EXPORT_TRACEPOINT_SYMBOL(fence_emit);
 * context or not. One device can have multiple separate contexts,
 * and they're used if some engine can run independently of another.
 */
static atomic_t fence_context_counter = ATOMIC_INIT(0);
static atomic64_t fence_context_counter = ATOMIC64_INIT(0);

/**
 * fence_context_alloc - allocate an array of fence contexts
@@ -44,10 +44,10 @@ static atomic_t fence_context_counter = ATOMIC_INIT(0);
 * This function will return the first index of the number of fences allocated.
 * The fence context is used for setting fence->context to a unique number.
 */
unsigned fence_context_alloc(unsigned num)
u64 fence_context_alloc(unsigned num)
{
	BUG_ON(!num);
	return atomic_add_return(num, &fence_context_counter) - num;
	return atomic64_add_return(num, &fence_context_counter) - num;
}
EXPORT_SYMBOL(fence_context_alloc);

@@ -513,7 +513,7 @@ EXPORT_SYMBOL(fence_wait_any_timeout);
 */
void
fence_init(struct fence *fence, const struct fence_ops *ops,
	     spinlock_t *lock, unsigned context, unsigned seqno)
	     spinlock_t *lock, u64 context, unsigned seqno)
{
	BUG_ON(!lock);
	BUG_ON(!ops || !ops->wait || !ops->enable_signaling ||
Loading