Motivation: In complicated DMA pipelines such as graphics (multimedia, camera, gpu, display) a consumer of a buffer needs to know when the producer has finished producing it. Likewise the producer needs to know when the consumer is finished with the buffer so it can reuse it. A particular buffer may be consumed by multiple consumers which will retain the buffer for different amounts of time. In addition, a consumer may consume multiple buffers atomically. The sync framework adds an API which allows synchronization between the producers and consumers in a generic way while also allowing platforms which have shared hardware synchronization primitives to exploit them. Goals: * provide a generic API for expressing synchronization dependencies * allow drivers to exploit hardware synchronization between hardware blocks * provide a userspace API that allows a compositor to manage dependencies. * provide rich telemetry data to allow debugging slowdowns and stalls of the graphics pipeline. Objects: * sync_timeline * sync_pt * sync_fence sync_timeline: A sync_timeline is an abstract monotonically increasing counter. In general, each driver/hardware block context will have one of these. They can be backed by the appropriate hardware or rely on the generic sw_sync implementation. Timelines are only ever created through their specific implementations (i.e. sw_sync.) sync_pt: A sync_pt is an abstract value which marks a point on a sync_timeline. Sync_pts have a single timeline parent. They have 3 states: active, signaled, and error. They start in active state and transition, once, to either signaled (when the timeline counter advances beyond the sync_pt’s value) or error state. sync_fence: Sync_fences are the primary primitives used by drivers to coordinate synchronization of their buffers. They are a collection of sync_pts which may or may not have the same timeline parent. A sync_pt can only exist in one fence and the fence's list of sync_pts is immutable once created. Fences can be waited on synchronously or asynchronously. Two fences can also be merged to create a third fence containing a copy of the two fences’ sync_pts. Fences are backed by file descriptors to allow userspace to coordinate the display pipeline dependencies. Use: A driver implementing sync support should have a work submission function which: * takes a fence argument specifying when to begin work * asynchronously queues that work to kick off when the fence is signaled * returns a fence to indicate when its work will be done. * signals the returned fence once the work is completed. Consider an imaginary display driver that has the following API: /* * assumes buf is ready to be displayed. * blocks until the buffer is on screen. */ void display_buffer(struct dma_buf *buf); The new API will become: /* * will display buf when fence is signaled. * returns immediately with a fence that will signal when buf * is no longer displayed. */ struct sync_fence* display_buffer(struct dma_buf *buf, struct sync_fence *fence);