}
/* After the final retire, the entire struct may be freed */
- if (ref->retire) {
- if (ref->active) {
- bool freed = false;
-
- /* Don't race with the active callback, and avoid UaF */
- down_write(&ref->rwsem);
- ref->freed = &freed;
- ref->retire(ref);
- if (!freed) {
- ref->freed = NULL;
- up_write(&ref->rwsem);
- }
- } else {
- ref->retire(ref);
- }
- }
+ if (ref->retire)
+ ref->retire(ref);
}
static void
struct i915_active *ref,
int (*active)(struct i915_active *ref),
void (*retire)(struct i915_active *ref),
- struct lock_class_key *key,
- struct lock_class_key *rkey)
+ struct lock_class_key *key)
{
debug_active_init(ref);
init_llist_head(&ref->preallocated_barriers);
atomic_set(&ref->count, 0);
__mutex_init(&ref->mutex, "i915_active", key);
- ref->freed = NULL;
- if (ref->active && ref->retire)
- __init_rwsem(&ref->rwsem, "i915_active.rwsem", rkey);
}
static bool ____active_del_barrier(struct i915_active *ref,
if (err)
return err;
- if (!atomic_read(&ref->count) && ref->active) {
- if (ref->retire) {
- /*
- * This can be a recursive call, and the mutex above
- * already protects from concurrent active callbacks, so
- * a read lock fits best.
- */
- down_read(&ref->rwsem);
- err = ref->active(ref);
- up_read(&ref->rwsem);
- } else {
- err = ref->active(ref);
- }
- }
+ if (!atomic_read(&ref->count) && ref->active)
+ err = ref->active(ref);
if (!err) {
debug_active_activate(ref);
atomic_inc(&ref->count);
return err;
}
+#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)
void i915_active_fini(struct i915_active *ref)
{
- if (ref->freed) {
- *ref->freed = true;
- up_write(&ref->rwsem);
- }
-#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)
debug_active_fini(ref);
GEM_BUG_ON(!RB_EMPTY_ROOT(&ref->tree));
GEM_BUG_ON(atomic_read(&ref->count));
mutex_destroy(&ref->mutex);
-#endif
}
+#endif
static inline bool is_idle_barrier(struct active_node *node, u64 idx)
{
struct i915_active *ref,
int (*active)(struct i915_active *ref),
void (*retire)(struct i915_active *ref),
- struct lock_class_key *key,
- struct lock_class_key *rkey);
+ struct lock_class_key *key);
#define i915_active_init(i915, ref, active, retire) do { \
static struct lock_class_key __key; \
- static struct lock_class_key __rkey; \
\
- __i915_active_init(i915, ref, active, retire, &__key, &__rkey); \
+ __i915_active_init(i915, ref, active, retire, &__key); \
} while (0)
int i915_active_ref(struct i915_active *ref,
return !atomic_read(&ref->count);
}
+#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)
void i915_active_fini(struct i915_active *ref);
+#else
+static inline void i915_active_fini(struct i915_active *ref) { }
+#endif
int i915_active_acquire_preallocate_barrier(struct i915_active *ref,
struct intel_engine_cs *engine);