summaryrefslogtreecommitdiff
path: root/Documentation/dma-buf-sync.txt
AgeCommit message (Collapse)AuthorFilesLines
2014-11-21dma-buf/dmabuf-sync: add dmabuf sync frameworkInki Dae1-0/+258
The DMA Buffer synchronization API provides buffer synchronization mechanism based on DMA buffer sharing machanism[1], dmafence and reservation frameworks[2]; i.e., buffer access control to CPU and DMA, and easy-to-use interfaces for device drivers and user application. And this API can be used for all dma devices using system memory as dma buffer, especially for most ARM based SoCs. For more details, please refer to Documentation/dma-buf-syc.txt [1] http://lwn.net/Articles/470339/ [2] https://lkml.org/lkml/2014/2/24/824 Change-Id: I3b2084a3c331fc06992fa8d2a4c71378e88b10b5 Signed-off-by: Inki Dae <inki.dae@samsung.com>
2014-11-21Revert "dmabuf-sync: add buffer synchronization framework"Chanho Park1-290/+0
This reverts commit 7a9958fedb90ef4000b6461d77a5c6dfd795c1c1.
2014-11-21Revert "dmabuf-sync: update it to patch v8"Chanho Park1-48/+52
This reverts commit cf7e07ce2d9843105d2ed8f9d30ee66c06d83bb0.
2014-11-18dmabuf-sync: update it to patch v8Inki Dae1-52/+48
- Consider the write-and-then-read ordering. The ordering issue means that a task don't take a lock to the dmabuf so this task would be stalled even though this task requested a lock to the dmabuf between other task unlocked and tries to lock the dmabuf again. For this, it addes a wait event mechanism using only generic APIs, wait_event_timeout and wake_up functions. The below is how to handle the ordering issue using this mechanism: 1. Check if there is a sync object added prior to current task's one. 2. If exists, it unlocks the dmabuf so that other task can take a lock to the dmabuf first. 3. Wait for the wake up event from other task: current task will be waked up when other task unlocks the dmabuf. 4. Take a lock to the dmabuf again. - Update Document - Code cleanups. Signed-off-by: Inki Dae <inki.dae@samsung.com>
2014-11-18dmabuf-sync: add buffer synchronization frameworkInki Dae1-0/+290
This patch adds a buffer synchronization framework based on DMA BUF[1] and and based on ww-mutexes[2] for lock mechanism. The purpose of this framework is to provide not only buffer access control to CPU and DMA but also easy-to-use interfaces for device drivers and user application. This framework can be used for all dma devices using system memory as dma buffer, especially for most ARM based SoCs. Changelog v5: - Rmove a dependence on reservation_object: the reservation_object is used to hook up to ttm and dma-buf for easy sharing of reservations across devices. However, the dmabuf sync can be used for all dma devices; v4l2 and drm based drivers, so doesn't need the reservation_object anymore. With regared to this, it adds 'void *sync' to dma_buf structure. - All patches are rebased on mainline, Linux v3.10. Changelog v4: - Add user side interface for buffer synchronization mechanism and update descriptions related to the user side interface. Changelog v3: - remove cache operation relevant codes and update document file. Changelog v2: - use atomic_add_unless to avoid potential bug. - add a macro for checking valid access type. - code clean. The mechanism of this framework has the following steps, 1. Register dmabufs to a sync object - A task gets a new sync object and can add one or more dmabufs that the task wants to access. This registering should be performed when a device context or an event context such as a page flip event is created or before CPU accesses a shared buffer. dma_buf_sync_get(a sync object, a dmabuf); 2. Lock a sync object - A task tries to lock all dmabufs added in its own sync object. Basically, the lock mechanism uses ww-mutex[1] to avoid dead lock issue and for race condition between CPU and CPU, CPU and DMA, and DMA and DMA. Taking a lock means that others cannot access all locked dmabufs until the task that locked the corresponding dmabufs, unlocks all the locked dmabufs. This locking should be performed before DMA or CPU accesses these dmabufs. dma_buf_sync_lock(a sync object); 3. Unlock a sync object - The task unlocks all dmabufs added in its own sync object. The unlock means that the DMA or CPU accesses to the dmabufs have been completed so that others may access them. This unlocking should be performed after DMA or CPU has completed accesses to the dmabufs. dma_buf_sync_unlock(a sync object); 4. Unregister one or all dmabufs from a sync object - A task unregisters the given dmabufs from the sync object. This means that the task dosen't want to lock the dmabufs. The unregistering should be performed after DMA or CPU has completed accesses to the dmabufs or when dma_buf_sync_lock() is failed. dma_buf_sync_put(a sync object, a dmabuf); dma_buf_sync_put_all(a sync object); The described steps may be summarized as: get -> lock -> CPU or DMA access to a buffer/s -> unlock -> put This framework includes the following two features. 1. read (shared) and write (exclusive) locks - A task is required to declare the access type when the task tries to register a dmabuf; READ, WRITE, READ DMA, or WRITE DMA. The below is example codes, struct dmabuf_sync *sync; sync = dmabuf_sync_init(NULL, "test sync"); dmabuf_sync_get(sync, dmabuf, DMA_BUF_ACCESS_R); ... And the below can be used as access types: DMA_BUF_ACCESS_R - CPU will access a buffer for read. DMA_BUF_ACCESS_W - CPU will access a buffer for read or write. DMA_BUF_ACCESS_DMA_R - DMA will access a buffer for read DMA_BUF_ACCESS_DMA_W - DMA will access a buffer for read or write. 2. Mandatory resource releasing - a task cannot hold a lock indefinitely. A task may never try to unlock a buffer after taking a lock to the buffer. In this case, a timer handler to the corresponding sync object is called in five (default) seconds and then the timed-out buffer is unlocked by work queue handler to avoid lockups and to enforce resources of the buffer. The below is how to use interfaces for device driver: 1. Allocate and Initialize a sync object: struct dmabuf_sync *sync; sync = dmabuf_sync_init(NULL, "test sync"); ... 2. Add a dmabuf to the sync object when setting up dma buffer relevant registers: dmabuf_sync_get(sync, dmabuf, DMA_BUF_ACCESS_READ); ... 3. Lock all dmabufs of the sync object before DMA or CPU accesses the dmabufs: dmabuf_sync_lock(sync); ... 4. Now CPU or DMA can access all dmabufs locked in step 3. 5. Unlock all dmabufs added in a sync object after DMA or CPU access to these dmabufs is completed: dmabuf_sync_unlock(sync); And call the following functions to release all resources, dmabuf_sync_put_all(sync); dmabuf_sync_fini(sync); You can refer to actual example codes: "drm/exynos: add dmabuf sync support for g2d driver" and "drm/exynos: add dmabuf sync support for kms framework" from https://git.kernel.org/cgit/linux/kernel/git/daeinki/ drm-exynos.git/log/?h=dmabuf-sync And this framework includes fcntl system call[3] as interfaces exported to user. As you know, user sees a buffer object as a dma-buf file descriptor. So fcntl() call with the file descriptor means to lock some buffer region being managed by the dma-buf object. The below is how to use interfaces for user application: struct flock filelock; 1. Lock a dma buf: filelock.l_type = F_WRLCK or F_RDLCK; /* lock entire region to the dma buf. */ filelock.lwhence = SEEK_CUR; filelock.l_start = 0; filelock.l_len = 0; fcntl(dmabuf fd, F_SETLKW or F_SETLK, &filelock); ... CPU access to the dma buf 2. Unlock a dma buf: filelock.l_type = F_UNLCK; fcntl(dmabuf fd, F_SETLKW or F_SETLK, &filelock); close(dmabuf fd) call would also unlock the dma buf. And for more detail, please refer to [3] References: [1] http://lwn.net/Articles/470339/ [2] https://patchwork.kernel.org/patch/2625361/ [3] http://linux.die.net/man/2/fcntl Signed-off-by: Inki Dae <inki.dae@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>