hc
2024-01-31 f70575805708cabdedea7498aaa3f710fde4d920
kernel/include/drm/drm_modeset_lock.h
....@@ -68,7 +68,7 @@
6868 /**
6969 * struct drm_modeset_lock - used for locking modeset resources.
7070 * @mutex: resource locking
71
- * @head: used to hold it's place on &drm_atomi_state.locked list when
71
+ * @head: used to hold its place on &drm_atomi_state.locked list when
7272 * part of an atomic update
7373 *
7474 * Used for locking CRTCs and other modeset resources.
....@@ -114,6 +114,15 @@
114114 return ww_mutex_is_locked(&lock->mutex);
115115 }
116116
117
+/**
118
+ * drm_modeset_lock_assert_held - equivalent to lockdep_assert_held()
119
+ * @lock: lock to check
120
+ */
121
+static inline void drm_modeset_lock_assert_held(struct drm_modeset_lock *lock)
122
+{
123
+ lockdep_assert_held(&lock->mutex.base);
124
+}
125
+
117126 int drm_modeset_lock(struct drm_modeset_lock *lock,
118127 struct drm_modeset_acquire_ctx *ctx);
119128 int __must_check drm_modeset_lock_single_interruptible(struct drm_modeset_lock *lock);
....@@ -130,4 +139,68 @@
130139 int drm_modeset_lock_all_ctx(struct drm_device *dev,
131140 struct drm_modeset_acquire_ctx *ctx);
132141
142
+/**
143
+ * DRM_MODESET_LOCK_ALL_BEGIN - Helper to acquire modeset locks
144
+ * @dev: drm device
145
+ * @ctx: local modeset acquire context, will be dereferenced
146
+ * @flags: DRM_MODESET_ACQUIRE_* flags to pass to drm_modeset_acquire_init()
147
+ * @ret: local ret/err/etc variable to track error status
148
+ *
149
+ * Use these macros to simplify grabbing all modeset locks using a local
150
+ * context. This has the advantage of reducing boilerplate, but also properly
151
+ * checking return values where appropriate.
152
+ *
153
+ * Any code run between BEGIN and END will be holding the modeset locks.
154
+ *
155
+ * This must be paired with DRM_MODESET_LOCK_ALL_END(). We will jump back and
156
+ * forth between the labels on deadlock and error conditions.
157
+ *
158
+ * Drivers can acquire additional modeset locks. If any lock acquisition
159
+ * fails, the control flow needs to jump to DRM_MODESET_LOCK_ALL_END() with
160
+ * the @ret parameter containing the return value of drm_modeset_lock().
161
+ *
162
+ * Returns:
163
+ * The only possible value of ret immediately after DRM_MODESET_LOCK_ALL_BEGIN()
164
+ * is 0, so no error checking is necessary
165
+ */
166
+#define DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, flags, ret) \
167
+ if (!drm_drv_uses_atomic_modeset(dev)) \
168
+ mutex_lock(&dev->mode_config.mutex); \
169
+ drm_modeset_acquire_init(&ctx, flags); \
170
+modeset_lock_retry: \
171
+ ret = drm_modeset_lock_all_ctx(dev, &ctx); \
172
+ if (ret) \
173
+ goto modeset_lock_fail;
174
+
175
+/**
176
+ * DRM_MODESET_LOCK_ALL_END - Helper to release and cleanup modeset locks
177
+ * @dev: drm device
178
+ * @ctx: local modeset acquire context, will be dereferenced
179
+ * @ret: local ret/err/etc variable to track error status
180
+ *
181
+ * The other side of DRM_MODESET_LOCK_ALL_BEGIN(). It will bounce back to BEGIN
182
+ * if ret is -EDEADLK.
183
+ *
184
+ * It's important that you use the same ret variable for begin and end so
185
+ * deadlock conditions are properly handled.
186
+ *
187
+ * Returns:
188
+ * ret will be untouched unless it is -EDEADLK on entry. That means that if you
189
+ * successfully acquire the locks, ret will be whatever your code sets it to. If
190
+ * there is a deadlock or other failure with acquire or backoff, ret will be set
191
+ * to that failure. In both of these cases the code between BEGIN/END will not
192
+ * be run, so the failure will reflect the inability to grab the locks.
193
+ */
194
+#define DRM_MODESET_LOCK_ALL_END(dev, ctx, ret) \
195
+modeset_lock_fail: \
196
+ if (ret == -EDEADLK) { \
197
+ ret = drm_modeset_backoff(&ctx); \
198
+ if (!ret) \
199
+ goto modeset_lock_retry; \
200
+ } \
201
+ drm_modeset_drop_locks(&ctx); \
202
+ drm_modeset_acquire_fini(&ctx); \
203
+ if (!drm_drv_uses_atomic_modeset(dev)) \
204
+ mutex_unlock(&dev->mode_config.mutex);
205
+
133206 #endif /* DRM_MODESET_LOCK_H_ */