Commit 0f0d8406 authored by Maarten Lankhorst's avatar Maarten Lankhorst Committed by Greg Kroah-Hartman
Browse files

android: convert sync to fence api, v6



Just to show it's easy.

Android syncpoints can be mapped to a timeline. This removes the need
to maintain a separate api for synchronization. I've left the android
trace events in place, but the core fence events should already be
sufficient for debugging.

v2:
- Call fence_remove_callback in sync_fence_free if not all fences have fired.
v3:
- Merge Colin Cross' bugfixes, and the android fence merge optimization.
v4:
- Merge with the upstream fixes.
v5:
- Fix small style issues pointed out by Thomas Hellstrom.
v6:
- Fix for updates to fence api.

Signed-off-by: default avatarMaarten Lankhorst <maarten.lankhorst@canonical.com>
Acked-by: default avatarJohn Stultz <john.stultz@linaro.org>
Acked-by: default avatarSumit Semwal <sumit.semwal@linaro.org>
Acked-by: default avatarDaniel Vetter <daniel@ffwll.ch>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 3aac4502
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -88,6 +88,7 @@ config SYNC
	bool "Synchronization framework"
	default n
	select ANON_INODES
	select DMA_SHARED_BUFFER
	---help---
	  This option enables the framework for synchronization between multiple
	  drivers.  Sync implementations can take advantage of hardware
+1 −1
Original line number Diff line number Diff line
@@ -9,5 +9,5 @@ obj-$(CONFIG_ANDROID_TIMED_OUTPUT) += timed_output.o
obj-$(CONFIG_ANDROID_TIMED_GPIO)	+= timed_gpio.o
obj-$(CONFIG_ANDROID_LOW_MEMORY_KILLER)	+= lowmemorykiller.o
obj-$(CONFIG_ANDROID_INTF_ALARM_DEV)	+= alarm-dev.o
obj-$(CONFIG_SYNC)			+= sync.o
obj-$(CONFIG_SYNC)			+= sync.o sync_debug.o
obj-$(CONFIG_SW_SYNC)			+= sw_sync.o
+2 −4
Original line number Diff line number Diff line
@@ -50,7 +50,7 @@ static struct sync_pt *sw_sync_pt_dup(struct sync_pt *sync_pt)
{
	struct sw_sync_pt *pt = (struct sw_sync_pt *) sync_pt;
	struct sw_sync_timeline *obj =
		(struct sw_sync_timeline *)sync_pt->parent;
		(struct sw_sync_timeline *)sync_pt_parent(sync_pt);

	return (struct sync_pt *) sw_sync_pt_create(obj, pt->value);
}
@@ -59,7 +59,7 @@ static int sw_sync_pt_has_signaled(struct sync_pt *sync_pt)
{
	struct sw_sync_pt *pt = (struct sw_sync_pt *)sync_pt;
	struct sw_sync_timeline *obj =
		(struct sw_sync_timeline *)sync_pt->parent;
		(struct sw_sync_timeline *)sync_pt_parent(sync_pt);

	return sw_sync_cmp(obj->value, pt->value) >= 0;
}
@@ -97,7 +97,6 @@ static void sw_sync_pt_value_str(struct sync_pt *sync_pt,
				       char *str, int size)
{
	struct sw_sync_pt *pt = (struct sw_sync_pt *)sync_pt;

	snprintf(str, size, "%d", pt->value);
}

@@ -157,7 +156,6 @@ static int sw_sync_open(struct inode *inode, struct file *file)
static int sw_sync_release(struct inode *inode, struct file *file)
{
	struct sw_sync_timeline *obj = file->private_data;

	sync_timeline_destroy(&obj->obj);
	return 0;
}
+307 −606

File changed.

Preview size limit exceeded, changes collapsed.

+45 −34
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/wait.h>
#include <linux/fence.h>

#include "uapi/sync.h"

@@ -40,8 +41,6 @@ struct sync_fence;
 *			 -1 if a will signal before b
 * @free_pt:		called before sync_pt is freed
 * @release_obj:	called before sync_timeline is freed
 * @print_obj:		deprecated
 * @print_pt:		deprecated
 * @fill_driver_data:	write implementation specific driver data to data.
 *			  should return an error if there is not enough room
 *			  as specified by size.  This information is returned
@@ -67,13 +66,6 @@ struct sync_timeline_ops {
	/* optional */
	void (*release_obj)(struct sync_timeline *sync_timeline);

	/* deprecated */
	void (*print_obj)(struct seq_file *s,
			  struct sync_timeline *sync_timeline);

	/* deprecated */
	void (*print_pt)(struct seq_file *s, struct sync_pt *sync_pt);

	/* optional */
	int (*fill_driver_data)(struct sync_pt *syncpt, void *data, int size);

@@ -104,19 +96,21 @@ struct sync_timeline {

	/* protected by child_list_lock */
	bool			destroyed;
	int			context, value;

	struct list_head	child_list_head;
	spinlock_t		child_list_lock;

	struct list_head	active_list_head;
	spinlock_t		active_list_lock;

#ifdef CONFIG_DEBUG_FS
	struct list_head	sync_timeline_list;
#endif
};

/**
 * struct sync_pt - sync point
 * @parent:		sync_timeline to which this sync_pt belongs
 * @fence:		base fence class
 * @child_list:		membership in sync_timeline.child_list_head
 * @active_list:	membership in sync_timeline.active_list_head
 * @signaled_list:	membership in temporary signaled_list on stack
@@ -127,19 +121,22 @@ struct sync_timeline {
 *			  signaled or error.
 */
struct sync_pt {
	struct sync_timeline		*parent;
	struct list_head	child_list;
	struct fence base;

	struct list_head	child_list;
	struct list_head	active_list;
	struct list_head	signaled_list;

	struct sync_fence	*fence;
	struct list_head	pt_list;
};

	/* protected by parent->active_list_lock */
	int			status;
static inline struct sync_timeline *sync_pt_parent(struct sync_pt *pt)
{
	return container_of(pt->base.lock, struct sync_timeline,
			    child_list_lock);
}

	ktime_t			timestamp;
struct sync_fence_cb {
	struct fence_cb cb;
	struct fence *sync_pt;
	struct sync_fence *fence;
};

/**
@@ -149,9 +146,7 @@ struct sync_pt {
 * @name:		name of sync_fence.  Useful for debugging
 * @pt_list_head:	list of sync_pts in the fence.  immutable once fence
 *			  is created
 * @waiter_list_head:	list of asynchronous waiters on this fence
 * @waiter_list_lock:	lock protecting @waiter_list_head and @status
 * @status:		1: signaled, 0:active, <0: error
 * @status:		0: signaled, >0:active, <0: error
 *
 * @wq:			wait queue for fence signaling
 * @sync_fence_list:	membership in global fence list
@@ -160,17 +155,15 @@ struct sync_fence {
	struct file		*file;
	struct kref		kref;
	char			name[32];

	/* this list is immutable once the fence is created */
	struct list_head	pt_list_head;

	struct list_head	waiter_list_head;
	spinlock_t		waiter_list_lock; /* also protects status */
	int			status;
#ifdef CONFIG_DEBUG_FS
	struct list_head	sync_fence_list;
#endif
	int num_fences;

	wait_queue_head_t	wq;
	atomic_t		status;

	struct list_head	sync_fence_list;
	struct sync_fence_cb	cbs[];
};

struct sync_fence_waiter;
@@ -184,14 +177,14 @@ typedef void (*sync_callback_t)(struct sync_fence *fence,
 * @callback_data:	pointer to pass to @callback
 */
struct sync_fence_waiter {
	struct list_head	waiter_list;

	wait_queue_t work;
	sync_callback_t callback;
};

static inline void sync_fence_waiter_init(struct sync_fence_waiter *waiter,
					  sync_callback_t callback)
{
	INIT_LIST_HEAD(&waiter->work.task_list);
	waiter->callback = callback;
}

@@ -341,4 +334,22 @@ int sync_fence_cancel_async(struct sync_fence *fence,
 */
int sync_fence_wait(struct sync_fence *fence, long timeout);

#ifdef CONFIG_DEBUG_FS

extern void sync_timeline_debug_add(struct sync_timeline *obj);
extern void sync_timeline_debug_remove(struct sync_timeline *obj);
extern void sync_fence_debug_add(struct sync_fence *fence);
extern void sync_fence_debug_remove(struct sync_fence *fence);
extern void sync_dump(void);

#else
# define sync_timeline_debug_add(obj)
# define sync_timeline_debug_remove(obj)
# define sync_fence_debug_add(fence)
# define sync_fence_debug_remove(fence)
# define sync_dump()
#endif
int sync_fence_wake_up_wq(wait_queue_t *curr, unsigned mode,
				 int wake_flags, void *key);

#endif /* _LINUX_SYNC_H */
Loading