^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * drm_sync_helper.h: software fence and helper functions for fences and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * reservations used for dma buffer access synchronization between drivers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright 2014 Google, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * This software is licensed under the terms of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * License version 2, as published by the Free Software Foundation, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * may be copied, distributed, and modified under those terms.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * This program is distributed in the hope that it will be useful,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * but WITHOUT ANY WARRANTY; without even the implied warranty of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * GNU General Public License for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #ifndef _DRM_SYNC_HELPER_H_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define _DRM_SYNC_HELPER_H_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/fence.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/reservation.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/atomic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/workqueue.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * Create software fence
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * @context: execution context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * @seqno: the sequence number of this fence inside the execution context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) struct fence *drm_sw_fence_new(unsigned int context,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) unsigned seqno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * Signal and decrease reference count for a fence if it exists
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * @fence: fence to signal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * Utility function called when owner access to object associated with fence is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * finished (e.g. GPU done with rendering).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static inline void drm_fence_signal_and_put(struct fence **fence)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) if (*fence) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) fence_signal(*fence);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) fence_put(*fence);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) *fence = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) struct drm_reservation_cb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) struct drm_reservation_fence_cb {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct fence_cb base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct drm_reservation_cb *parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) struct fence *fence;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * Callback executed when all fences in reservation callback are signaled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * @rcb: reservation callback structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * @context: context provided by user at init time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) typedef void (*drm_reservation_cb_func_t)(struct drm_reservation_cb *rcb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) void *context);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * Reservation callback structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * @work: work context in which func is executed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * @fence_cbs: fence callbacks array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * @num_fence_cbs: number of fence callbacks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * @count: count of signaled fences, when it drops to 0 func is called
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * @func: callback to execute when all fences are signaled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * @context: context provided by user during initialization
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * It is safe and expected that func will destroy this structure before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * returning.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct drm_reservation_cb {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) struct work_struct work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) struct drm_reservation_fence_cb **fence_cbs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) unsigned num_fence_cbs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) atomic_t count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) void *context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) drm_reservation_cb_func_t func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * Initialize reservation callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * @rcb: reservation callback structure to initialize
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * @func: function to call when all fences are signaled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * @context: parameter to call func with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) void drm_reservation_cb_init(struct drm_reservation_cb *rcb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) drm_reservation_cb_func_t func,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) void *context);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * Add fences from reservation object to callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * @rcb: reservation callback structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * @resv: reservation object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * @exclusive: (for exclusive wait) when true add all fences, otherwise only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * exclusive fence
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) int drm_reservation_cb_add(struct drm_reservation_cb *rcb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) struct reservation_object *resv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) bool exclusive);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * Finish adding fences
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * @rcb: reservation callback structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * It will trigger callback worker if all fences were signaled before.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) void drm_reservation_cb_done(struct drm_reservation_cb *rcb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * Cleanup reservation callback structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * @rcb: reservation callback structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * Can be called to cancel primed reservation callback.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) void drm_reservation_cb_fini(struct drm_reservation_cb *rcb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * Add reservation to array of reservations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * @resv: reservation to add
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * @resvs: array of reservations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) * @excl_resvs_bitmap: bitmap for exclusive reservations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) * @num_resvs: number of reservations in array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) * @exclusive: bool to store in excl_resvs_bitmap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) drm_add_reservation(struct reservation_object *resv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) struct reservation_object **resvs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) unsigned long *excl_resvs_bitmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) unsigned int *num_resvs, bool exclusive);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) * Acquire ww_mutex lock on all reservations in the array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) * @resvs: array of reservations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * @num_resvs: number of reservations in the array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * @ctx: ww mutex context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) int drm_lock_reservations(struct reservation_object **resvs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) unsigned int num_resvs, struct ww_acquire_ctx *ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * Release ww_mutex lock on all reservations in the array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * @resvs: array of reservations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * @num_resvs: number of reservations in the array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * @ctx: ww mutex context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) void drm_unlock_reservations(struct reservation_object **resvs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) unsigned int num_resvs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) struct ww_acquire_ctx *ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) #endif