Loading drivers/dma-buf/reservation.c +68 −4 Original line number Diff line number Diff line Loading @@ -35,6 +35,17 @@ #include <linux/reservation.h> #include <linux/export.h> /** * DOC: Reservation Object Overview * * The reservation object provides a mechanism to manage shared and * exclusive fences associated with a buffer. A reservation object * can have attached one exclusive fence (normally associated with * write operations) or N shared fences (read operations). The RCU * mechanism is used to protect read access to fences from locked * write-side updates. */ DEFINE_WW_CLASS(reservation_ww_class); EXPORT_SYMBOL(reservation_ww_class); Loading @@ -43,9 +54,17 @@ EXPORT_SYMBOL(reservation_seqcount_class); const char reservation_seqcount_string[] = "reservation_seqcount"; EXPORT_SYMBOL(reservation_seqcount_string); /* * Reserve space to add a shared fence to a reservation_object, * must be called with obj->lock held. /** * reservation_object_reserve_shared - Reserve space to add a shared * fence to a reservation_object. * @obj: reservation object * * Should be called before reservation_object_add_shared_fence(). Must * be called with obj->lock held. * * RETURNS * Zero for success, or -errno */ int reservation_object_reserve_shared(struct reservation_object *obj) { Loading Loading @@ -180,7 +199,11 @@ reservation_object_add_shared_replace(struct reservation_object *obj, fence_put(old_fence); } /* /** * reservation_object_add_shared_fence - Add a fence to a shared slot * @obj: the reservation object * @fence: the shared fence to add * * Add a fence to a shared slot, obj->lock must be held, and * reservation_object_reserve_shared_fence has been called. */ Loading @@ -200,6 +223,13 @@ void reservation_object_add_shared_fence(struct reservation_object *obj, } EXPORT_SYMBOL(reservation_object_add_shared_fence); /** * reservation_object_add_excl_fence - Add an exclusive fence. * @obj: the reservation object * @fence: the shared fence to add * * Add a fence to the exclusive slot. The obj->lock must be held. */ void reservation_object_add_excl_fence(struct reservation_object *obj, struct fence *fence) { Loading Loading @@ -233,6 +263,18 @@ void reservation_object_add_excl_fence(struct reservation_object *obj, } EXPORT_SYMBOL(reservation_object_add_excl_fence); /** * reservation_object_get_fences_rcu - Get an object's shared and exclusive * fences without update side lock held * @obj: the reservation object * @pfence_excl: the returned exclusive fence (or NULL) * @pshared_count: the number of shared fences returned * @pshared: the array of shared fence ptrs returned (array is krealloc'd to * the required size, and must be freed by caller) * * RETURNS * Zero or -errno */ int reservation_object_get_fences_rcu(struct reservation_object *obj, struct fence **pfence_excl, unsigned *pshared_count, Loading Loading @@ -319,6 +361,18 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj, } EXPORT_SYMBOL_GPL(reservation_object_get_fences_rcu); /** * reservation_object_wait_timeout_rcu - Wait on reservation's objects * shared and/or exclusive fences. * @obj: the reservation object * @wait_all: if true, wait on all fences, else wait on just exclusive fence * @intr: if true, do interruptible wait * @timeout: timeout value in jiffies or zero to return immediately * * RETURNS * Returns -ERESTARTSYS if interrupted, 0 if the wait timed out, or * greater than zer on success. */ long reservation_object_wait_timeout_rcu(struct reservation_object *obj, bool wait_all, bool intr, unsigned long timeout) Loading Loading @@ -416,6 +470,16 @@ reservation_object_test_signaled_single(struct fence *passed_fence) return ret; } /** * reservation_object_test_signaled_rcu - Test if a reservation object's * fences have been signaled. * @obj: the reservation object * @test_all: if true, test all fences, otherwise only test the exclusive * fence * * RETURNS * true if all fences signaled, else false */ bool reservation_object_test_signaled_rcu(struct reservation_object *obj, bool test_all) { Loading include/linux/reservation.h +53 −0 Original line number Diff line number Diff line Loading @@ -49,12 +49,27 @@ extern struct ww_class reservation_ww_class; extern struct lock_class_key reservation_seqcount_class; extern const char reservation_seqcount_string[]; /** * struct reservation_object_list - a list of shared fences * @rcu: for internal use * @shared_count: table of shared fences * @shared_max: for growing shared fence table * @shared: shared fence table */ struct reservation_object_list { struct rcu_head rcu; u32 shared_count, shared_max; struct fence __rcu *shared[]; }; /** * struct reservation_object - a reservation object manages fences for a buffer * @lock: update side lock * @seq: sequence count for managing RCU read-side synchronization * @fence_excl: the exclusive fence, if there is one currently * @fence: list of current shared fences * @staged: staged copy of shared fences for RCU updates */ struct reservation_object { struct ww_mutex lock; seqcount_t seq; Loading @@ -68,6 +83,10 @@ struct reservation_object { #define reservation_object_assert_held(obj) \ lockdep_assert_held(&(obj)->lock.base) /** * reservation_object_init - initialize a reservation object * @obj: the reservation object */ static inline void reservation_object_init(struct reservation_object *obj) { Loading @@ -79,6 +98,10 @@ reservation_object_init(struct reservation_object *obj) obj->staged = NULL; } /** * reservation_object_fini - destroys a reservation object * @obj: the reservation object */ static inline void reservation_object_fini(struct reservation_object *obj) { Loading Loading @@ -106,6 +129,14 @@ reservation_object_fini(struct reservation_object *obj) ww_mutex_destroy(&obj->lock); } /** * reservation_object_get_list - get the reservation object's * shared fence list, with update-side lock held * @obj: the reservation object * * Returns the shared fence list. Does NOT take references to * the fence. The obj->lock must be held. */ static inline struct reservation_object_list * reservation_object_get_list(struct reservation_object *obj) { Loading @@ -113,6 +144,17 @@ reservation_object_get_list(struct reservation_object *obj) reservation_object_held(obj)); } /** * reservation_object_get_excl - get the reservation object's * exclusive fence, with update-side lock held * @obj: the reservation object * * Returns the exclusive fence (if any). Does NOT take a * reference. The obj->lock must be held. * * RETURNS * The exclusive fence or NULL */ static inline struct fence * reservation_object_get_excl(struct reservation_object *obj) { Loading @@ -120,6 +162,17 @@ reservation_object_get_excl(struct reservation_object *obj) reservation_object_held(obj)); } /** * reservation_object_get_excl_rcu - get the reservation object's * exclusive fence, without lock held. * @obj: the reservation object * * If there is an exclusive fence, this atomically increments it's * reference count and returns it. * * RETURNS * The exclusive fence or NULL if none */ static inline struct fence * reservation_object_get_excl_rcu(struct reservation_object *obj) { Loading Loading
drivers/dma-buf/reservation.c +68 −4 Original line number Diff line number Diff line Loading @@ -35,6 +35,17 @@ #include <linux/reservation.h> #include <linux/export.h> /** * DOC: Reservation Object Overview * * The reservation object provides a mechanism to manage shared and * exclusive fences associated with a buffer. A reservation object * can have attached one exclusive fence (normally associated with * write operations) or N shared fences (read operations). The RCU * mechanism is used to protect read access to fences from locked * write-side updates. */ DEFINE_WW_CLASS(reservation_ww_class); EXPORT_SYMBOL(reservation_ww_class); Loading @@ -43,9 +54,17 @@ EXPORT_SYMBOL(reservation_seqcount_class); const char reservation_seqcount_string[] = "reservation_seqcount"; EXPORT_SYMBOL(reservation_seqcount_string); /* * Reserve space to add a shared fence to a reservation_object, * must be called with obj->lock held. /** * reservation_object_reserve_shared - Reserve space to add a shared * fence to a reservation_object. * @obj: reservation object * * Should be called before reservation_object_add_shared_fence(). Must * be called with obj->lock held. * * RETURNS * Zero for success, or -errno */ int reservation_object_reserve_shared(struct reservation_object *obj) { Loading Loading @@ -180,7 +199,11 @@ reservation_object_add_shared_replace(struct reservation_object *obj, fence_put(old_fence); } /* /** * reservation_object_add_shared_fence - Add a fence to a shared slot * @obj: the reservation object * @fence: the shared fence to add * * Add a fence to a shared slot, obj->lock must be held, and * reservation_object_reserve_shared_fence has been called. */ Loading @@ -200,6 +223,13 @@ void reservation_object_add_shared_fence(struct reservation_object *obj, } EXPORT_SYMBOL(reservation_object_add_shared_fence); /** * reservation_object_add_excl_fence - Add an exclusive fence. * @obj: the reservation object * @fence: the shared fence to add * * Add a fence to the exclusive slot. The obj->lock must be held. */ void reservation_object_add_excl_fence(struct reservation_object *obj, struct fence *fence) { Loading Loading @@ -233,6 +263,18 @@ void reservation_object_add_excl_fence(struct reservation_object *obj, } EXPORT_SYMBOL(reservation_object_add_excl_fence); /** * reservation_object_get_fences_rcu - Get an object's shared and exclusive * fences without update side lock held * @obj: the reservation object * @pfence_excl: the returned exclusive fence (or NULL) * @pshared_count: the number of shared fences returned * @pshared: the array of shared fence ptrs returned (array is krealloc'd to * the required size, and must be freed by caller) * * RETURNS * Zero or -errno */ int reservation_object_get_fences_rcu(struct reservation_object *obj, struct fence **pfence_excl, unsigned *pshared_count, Loading Loading @@ -319,6 +361,18 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj, } EXPORT_SYMBOL_GPL(reservation_object_get_fences_rcu); /** * reservation_object_wait_timeout_rcu - Wait on reservation's objects * shared and/or exclusive fences. * @obj: the reservation object * @wait_all: if true, wait on all fences, else wait on just exclusive fence * @intr: if true, do interruptible wait * @timeout: timeout value in jiffies or zero to return immediately * * RETURNS * Returns -ERESTARTSYS if interrupted, 0 if the wait timed out, or * greater than zer on success. */ long reservation_object_wait_timeout_rcu(struct reservation_object *obj, bool wait_all, bool intr, unsigned long timeout) Loading Loading @@ -416,6 +470,16 @@ reservation_object_test_signaled_single(struct fence *passed_fence) return ret; } /** * reservation_object_test_signaled_rcu - Test if a reservation object's * fences have been signaled. * @obj: the reservation object * @test_all: if true, test all fences, otherwise only test the exclusive * fence * * RETURNS * true if all fences signaled, else false */ bool reservation_object_test_signaled_rcu(struct reservation_object *obj, bool test_all) { Loading
include/linux/reservation.h +53 −0 Original line number Diff line number Diff line Loading @@ -49,12 +49,27 @@ extern struct ww_class reservation_ww_class; extern struct lock_class_key reservation_seqcount_class; extern const char reservation_seqcount_string[]; /** * struct reservation_object_list - a list of shared fences * @rcu: for internal use * @shared_count: table of shared fences * @shared_max: for growing shared fence table * @shared: shared fence table */ struct reservation_object_list { struct rcu_head rcu; u32 shared_count, shared_max; struct fence __rcu *shared[]; }; /** * struct reservation_object - a reservation object manages fences for a buffer * @lock: update side lock * @seq: sequence count for managing RCU read-side synchronization * @fence_excl: the exclusive fence, if there is one currently * @fence: list of current shared fences * @staged: staged copy of shared fences for RCU updates */ struct reservation_object { struct ww_mutex lock; seqcount_t seq; Loading @@ -68,6 +83,10 @@ struct reservation_object { #define reservation_object_assert_held(obj) \ lockdep_assert_held(&(obj)->lock.base) /** * reservation_object_init - initialize a reservation object * @obj: the reservation object */ static inline void reservation_object_init(struct reservation_object *obj) { Loading @@ -79,6 +98,10 @@ reservation_object_init(struct reservation_object *obj) obj->staged = NULL; } /** * reservation_object_fini - destroys a reservation object * @obj: the reservation object */ static inline void reservation_object_fini(struct reservation_object *obj) { Loading Loading @@ -106,6 +129,14 @@ reservation_object_fini(struct reservation_object *obj) ww_mutex_destroy(&obj->lock); } /** * reservation_object_get_list - get the reservation object's * shared fence list, with update-side lock held * @obj: the reservation object * * Returns the shared fence list. Does NOT take references to * the fence. The obj->lock must be held. */ static inline struct reservation_object_list * reservation_object_get_list(struct reservation_object *obj) { Loading @@ -113,6 +144,17 @@ reservation_object_get_list(struct reservation_object *obj) reservation_object_held(obj)); } /** * reservation_object_get_excl - get the reservation object's * exclusive fence, with update-side lock held * @obj: the reservation object * * Returns the exclusive fence (if any). Does NOT take a * reference. The obj->lock must be held. * * RETURNS * The exclusive fence or NULL */ static inline struct fence * reservation_object_get_excl(struct reservation_object *obj) { Loading @@ -120,6 +162,17 @@ reservation_object_get_excl(struct reservation_object *obj) reservation_object_held(obj)); } /** * reservation_object_get_excl_rcu - get the reservation object's * exclusive fence, without lock held. * @obj: the reservation object * * If there is an exclusive fence, this atomically increments it's * reference count and returns it. * * RETURNS * The exclusive fence or NULL if none */ static inline struct fence * reservation_object_get_excl_rcu(struct reservation_object *obj) { Loading