blob: ab691d15a2e5569bdab4d53e0fb17f65d57d70aa [file] [log] [blame]
/*
* drm_sync_helper.h: software fence and helper functions for fences and
* reservations used for dma buffer access synchronization between drivers.
*
* Copyright 2014 Google, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* 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.
*/
#ifndef _DRM_SYNC_HELPER_H_
#define _DRM_SYNC_HELPER_H_
#include <linux/dma-fence.h>
#include <linux/reservation.h>
#include <linux/atomic.h>
#include <linux/workqueue.h>
/**
* Create software fence
* @context: execution context
* @seqno: the sequence number of this fence inside the execution context
*/
struct dma_fence *drm_sw_fence_new(u64 context,
unsigned seqno);
/**
* Signal and decrease reference count for a fence if it exists
* @fence: fence to signal
*
* Utility function called when owner access to object associated with fence is
* finished (e.g. GPU done with rendering).
*/
static inline void drm_fence_signal_and_put(struct dma_fence **fence)
{
if (*fence) {
dma_fence_signal(*fence);
dma_fence_put(*fence);
*fence = NULL;
}
}
struct drm_reservation_cb;
struct drm_reservation_fence_cb {
struct dma_fence_cb base;
struct drm_reservation_cb *parent;
struct dma_fence *fence;
};
/**
* Callback executed when all fences in reservation callback are signaled
* @rcb: reservation callback structure
* @context: context provided by user at init time
*/
typedef void (*drm_reservation_cb_func_t)(struct drm_reservation_cb *rcb,
void *context);
/**
* Reservation callback structure
* @work: work context in which func is executed
* @fence_cbs: fence callbacks array
* @num_fence_cbs: number of fence callbacks
* @count: count of signaled fences, when it drops to 0 func is called
* @func: callback to execute when all fences are signaled
* @context: context provided by user during initialization
*
* It is safe and expected that func will destroy this structure before
* returning.
*/
struct drm_reservation_cb {
struct work_struct work;
struct drm_reservation_fence_cb **fence_cbs;
unsigned num_fence_cbs;
atomic_t count;
void *context;
drm_reservation_cb_func_t func;
};
/**
* Initialize reservation callback
* @rcb: reservation callback structure to initialize
* @func: function to call when all fences are signaled
* @context: parameter to call func with
*/
void drm_reservation_cb_init(struct drm_reservation_cb *rcb,
drm_reservation_cb_func_t func,
void *context);
/**
* Add fences from reservation object to callback
* @rcb: reservation callback structure
* @resv: reservation object
* @exclusive: (for exclusive wait) when true add all fences, otherwise only
* exclusive fence
*/
int drm_reservation_cb_add(struct drm_reservation_cb *rcb,
struct reservation_object *resv,
bool exclusive);
/**
* Finish adding fences
* @rcb: reservation callback structure
*
* It will trigger callback worker if all fences were signaled before.
*/
void drm_reservation_cb_done(struct drm_reservation_cb *rcb);
/**
* Cleanup reservation callback structure
* @rcb: reservation callback structure
*
* Can be called to cancel primed reservation callback.
*/
void drm_reservation_cb_fini(struct drm_reservation_cb *rcb);
/**
* Add reservation to array of reservations
* @resv: reservation to add
* @resvs: array of reservations
* @excl_resvs_bitmap: bitmap for exclusive reservations
* @num_resvs: number of reservations in array
* @exclusive: bool to store in excl_resvs_bitmap
*/
void
drm_add_reservation(struct reservation_object *resv,
struct reservation_object **resvs,
unsigned long *excl_resvs_bitmap,
unsigned int *num_resvs, bool exclusive);
/**
* Acquire ww_mutex lock on all reservations in the array
* @resvs: array of reservations
* @num_resvs: number of reservations in the array
* @ctx: ww mutex context
*/
int drm_lock_reservations(struct reservation_object **resvs,
unsigned int num_resvs, struct ww_acquire_ctx *ctx);
/**
* Release ww_mutex lock on all reservations in the array
* @resvs: array of reservations
* @num_resvs: number of reservations in the array
* @ctx: ww mutex context
*/
void drm_unlock_reservations(struct reservation_object **resvs,
unsigned int num_resvs,
struct ww_acquire_ctx *ctx);
#endif