History

Merge tag 'drm-misc-fixes-2023-01-26' of git://anongit.freedesktop.org/drm/drm-misc into drm-fixes

A fix and a preliminary patch to fix a memory leak in i915, and a use after free fix for fbdev deferred io Signed-off-by: Dave Airlie <airlied@redhat.com>

Dave Airlie committed 3 years ago

Commit d23db892 parents f439a95 d6591da5 files · +76 −30Browse files

Unified · Split

5 files
  1. drivers/gpu/drm/drm_fbdev_generic.c +8 −7
  2. drivers/gpu/drm/drm_vma_manager.c +54 −22
  3. drivers/gpu/drm/i915/gem/i915_gem_mman.c +1 −1
  4. include/drm/drm_fb_helper.h +12 −0
  5. include/drm/drm_vma_manager.h +1 −0
drivers/gpu/drm/drm_fbdev_generic.c+8−7
@@ -171,11 +171,6 @@ static const struct fb_ops drm_fbdev_fb_ops = { · 170 unmodified lines
171171 .fb_imageblit = drm_fbdev_fb_imageblit,
172172 };
173173
174−static struct fb_deferred_io drm_fbdev_defio = {
175− .delay = HZ / 20,
176− .deferred_io = drm_fb_helper_deferred_io,
177−};
178−
179174 /*
180175 * This function uses the client API to create a framebuffer backed by a dumb buffer.
181176 */
@@ -222,8 +217,14 @@ static int drm_fbdev_fb_probe(struct drm_fb_helper *fb_helper, · 40 unmodified lines
222217 return -ENOMEM;
223218 fbi->flags |= FBINFO_VIRTFB | FBINFO_READS_FAST;
224219
225− fbi->fbdefio = &drm_fbdev_defio;
226− fb_deferred_io_init(fbi);
220+ /* Set a default deferred I/O handler */
221+ fb_helper->fbdefio.delay = HZ / 20;
222+ fb_helper->fbdefio.deferred_io = drm_fb_helper_deferred_io;
223+
224+ fbi->fbdefio = &fb_helper->fbdefio;
225+ ret = fb_deferred_io_init(fbi);
226+ if (ret)
227+ return ret;
227228 } else {
228229 /* buffer is mapped for HW framebuffer */
229230 ret = drm_client_buffer_vmap(fb_helper->buffer, &map);
drivers/gpu/drm/drm_vma_manager.c+54−22
@@ -240,27 +240,8 @@ void drm_vma_offset_remove(struct drm_vma_offset_manager *mgr, · 239 unmodified lines
240240 }
241241 EXPORT_SYMBOL(drm_vma_offset_remove);
242242
243−/**
244− * drm_vma_node_allow - Add open-file to list of allowed users
245− * @node: Node to modify
246− * @tag: Tag of file to remove
247− *
248− * Add @tag to the list of allowed open-files for this node. If @tag is
249− * already on this list, the ref-count is incremented.
250− *
251− * The list of allowed-users is preserved across drm_vma_offset_add() and
252− * drm_vma_offset_remove() calls. You may even call it if the node is currently
253− * not added to any offset-manager.
254− *
255− * You must remove all open-files the same number of times as you added them
256− * before destroying the node. Otherwise, you will leak memory.
257− *
258− * This is locked against concurrent access internally.
259− *
260− * RETURNS:
261− * 0 on success, negative error code on internal failure (out-of-mem)
262− */
263−int drm_vma_node_allow(struct drm_vma_offset_node *node, struct drm_file *tag)
243+static int vma_node_allow(struct drm_vma_offset_node *node,
244+ struct drm_file *tag, bool ref_counted)
264245 {
265246 struct rb_node **iter;
266247 struct rb_node *parent = NULL;
@@ -282,7 +263,8 @@ int drm_vma_node_allow(struct drm_vma_offset_node *node, struct drm_file *tag) · 15 unmodified lines
282263 entry = rb_entry(*iter, struct drm_vma_offset_file, vm_rb);
283264
284265 if (tag == entry->vm_tag) {
285− entry->vm_count++;
266+ if (ref_counted)
267+ entry->vm_count++;
286268 goto unlock;
287269 } else if (tag > entry->vm_tag) {
288270 iter = &(*iter)->rb_right;
@@ -307,8 +289,58 @@ unlock: · 18 unmodified lines
307289 kfree(new);
308290 return ret;
309291 }
292+
293+/**
294+ * drm_vma_node_allow - Add open-file to list of allowed users
295+ * @node: Node to modify
296+ * @tag: Tag of file to remove
297+ *
298+ * Add @tag to the list of allowed open-files for this node. If @tag is
299+ * already on this list, the ref-count is incremented.
300+ *
301+ * The list of allowed-users is preserved across drm_vma_offset_add() and
302+ * drm_vma_offset_remove() calls. You may even call it if the node is currently
303+ * not added to any offset-manager.
304+ *
305+ * You must remove all open-files the same number of times as you added them
306+ * before destroying the node. Otherwise, you will leak memory.
307+ *
308+ * This is locked against concurrent access internally.
309+ *
310+ * RETURNS:
311+ * 0 on success, negative error code on internal failure (out-of-mem)
312+ */
313+int drm_vma_node_allow(struct drm_vma_offset_node *node, struct drm_file *tag)
314+{
315+ return vma_node_allow(node, tag, true);
316+}
310317 EXPORT_SYMBOL(drm_vma_node_allow);
311318
319+/**
320+ * drm_vma_node_allow_once - Add open-file to list of allowed users
321+ * @node: Node to modify
322+ * @tag: Tag of file to remove
323+ *
324+ * Add @tag to the list of allowed open-files for this node.
325+ *
326+ * The list of allowed-users is preserved across drm_vma_offset_add() and
327+ * drm_vma_offset_remove() calls. You may even call it if the node is currently
328+ * not added to any offset-manager.
329+ *
330+ * This is not ref-counted unlike drm_vma_node_allow() hence drm_vma_node_revoke()
331+ * should only be called once after this.
332+ *
333+ * This is locked against concurrent access internally.
334+ *
335+ * RETURNS:
336+ * 0 on success, negative error code on internal failure (out-of-mem)
337+ */
338+int drm_vma_node_allow_once(struct drm_vma_offset_node *node, struct drm_file *tag)
339+{
340+ return vma_node_allow(node, tag, false);
341+}
342+EXPORT_SYMBOL(drm_vma_node_allow_once);
343+
312344 /**
313345 * drm_vma_node_revoke - Remove open-file from list of allowed users
314346 * @node: Node to modify
drivers/gpu/drm/i915/gem/i915_gem_mman.c+1−1
@@ -697,7 +697,7 @@ insert: · 696 unmodified lines
697697 GEM_BUG_ON(lookup_mmo(obj, mmap_type) != mmo);
698698 out:
699699 if (file)
700− drm_vma_node_allow(&mmo->vma_node, file);
700+ drm_vma_node_allow_once(&mmo->vma_node, file);
701701 return mmo;
702702
703703 err:
include/drm/drm_fb_helper.h+12−0
@@ -208,6 +208,18 @@ struct drm_fb_helper { · 207 unmodified lines
208208 * the smem_start field should always be cleared to zero.
209209 */
210210 bool hint_leak_smem_start;
211+
212+#ifdef CONFIG_FB_DEFERRED_IO
213+ /**
214+ * @fbdefio:
215+ *
216+ * Temporary storage for the driver's FB deferred I/O handler. If the
217+ * driver uses the DRM fbdev emulation layer, this is set by the core
218+ * to a generic deferred I/O handler if a driver is preferring to use
219+ * a shadow buffer.
220+ */
221+ struct fb_deferred_io fbdefio;
222+#endif
211223 };
212224
213225 static inline struct drm_fb_helper *
include/drm/drm_vma_manager.h+1−0
@@ -74,6 +74,7 @@ void drm_vma_offset_remove(struct drm_vma_offset_manager *mgr, · 73 unmodified lines
7474 struct drm_vma_offset_node *node);
7575
7676 int drm_vma_node_allow(struct drm_vma_offset_node *node, struct drm_file *tag);
77+int drm_vma_node_allow_once(struct drm_vma_offset_node *node, struct drm_file *tag);
7778 void drm_vma_node_revoke(struct drm_vma_offset_node *node,
7879 struct drm_file *tag);
7980 bool drm_vma_node_is_allowed(struct drm_vma_offset_node *node,