Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

dma-buf: nuke reservation_object seq number

The only remaining use for this is to protect against setting a new exclusive
fence while we grab both exclusive and shared. That can also be archived by
looking if the exclusive fence has changed or not after completing the
operation.

v2: switch setting excl fence to rcu_assign_pointer

Signed-off-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: https://patchwork.freedesktop.org/patch/322380/

+7 -26
+5 -19
drivers/dma-buf/reservation.c
··· 49 49 DEFINE_WD_CLASS(reservation_ww_class); 50 50 EXPORT_SYMBOL(reservation_ww_class); 51 51 52 - struct lock_class_key reservation_seqcount_class; 53 - EXPORT_SYMBOL(reservation_seqcount_class); 54 - 55 - const char reservation_seqcount_string[] = "reservation_seqcount"; 56 - EXPORT_SYMBOL(reservation_seqcount_string); 57 - 58 52 /** 59 53 * reservation_object_list_alloc - allocate fence list 60 54 * @shared_max: number of fences we need space for ··· 97 103 void reservation_object_init(struct reservation_object *obj) 98 104 { 99 105 ww_mutex_init(&obj->lock, &reservation_ww_class); 100 - 101 - __seqcount_init(&obj->seq, reservation_seqcount_string, 102 - &reservation_seqcount_class); 103 106 RCU_INIT_POINTER(obj->fence, NULL); 104 107 RCU_INIT_POINTER(obj->fence_excl, NULL); 105 108 } ··· 273 282 dma_fence_get(fence); 274 283 275 284 preempt_disable(); 276 - write_seqcount_begin(&obj->seq); 277 - /* write_seqcount_begin provides the necessary memory barrier */ 278 - RCU_INIT_POINTER(obj->fence_excl, fence); 285 + rcu_assign_pointer(obj->fence_excl, fence); 286 + /* pointer update must be visible before we modify the shared_count */ 279 287 if (old) 280 - old->shared_count = 0; 281 - write_seqcount_end(&obj->seq); 288 + smp_store_mb(old->shared_count, 0); 282 289 preempt_enable(); 283 290 284 291 /* inplace update, no shared fences */ ··· 357 368 old = reservation_object_get_excl(dst); 358 369 359 370 preempt_disable(); 360 - write_seqcount_begin(&dst->seq); 361 - /* write_seqcount_begin provides the necessary memory barrier */ 362 - RCU_INIT_POINTER(dst->fence_excl, new); 363 - RCU_INIT_POINTER(dst->fence, dst_list); 364 - write_seqcount_end(&dst->seq); 371 + rcu_assign_pointer(dst->fence_excl, new); 372 + rcu_assign_pointer(dst->fence, dst_list); 365 373 preempt_enable(); 366 374 367 375 reservation_object_list_free(src_list);
+2 -7
include/linux/reservation.h
··· 46 46 #include <linux/rcupdate.h> 47 47 48 48 extern struct ww_class reservation_ww_class; 49 - extern struct lock_class_key reservation_seqcount_class; 50 - extern const char reservation_seqcount_string[]; 51 49 52 50 /** 53 51 * struct reservation_object_list - a list of shared fences ··· 69 71 */ 70 72 struct reservation_object { 71 73 struct ww_mutex lock; 72 - seqcount_t seq; 73 74 74 75 struct dma_fence __rcu *fence_excl; 75 76 struct reservation_object_list __rcu *fence; ··· 127 130 struct reservation_object_list **list, 128 131 u32 *shared_count) 129 132 { 130 - unsigned int seq; 131 - 132 133 do { 133 - seq = read_seqcount_begin(&obj->seq); 134 134 *excl = rcu_dereference(obj->fence_excl); 135 135 *list = rcu_dereference(obj->fence); 136 136 *shared_count = *list ? (*list)->shared_count : 0; 137 - } while (read_seqcount_retry(&obj->seq, seq)); 137 + smp_rmb(); /* See reservation_object_add_excl_fence */ 138 + } while (rcu_access_pointer(obj->fence_excl) != *excl); 138 139 } 139 140 140 141 /**