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
171 .fb_imageblit = drm_fbdev_fb_imageblit,171 .fb_imageblit = drm_fbdev_fb_imageblit,
172};172};
173 173
174static struct fb_deferred_io drm_fbdev_defio = {
175 .delay = HZ / 20,
176 .deferred_io = drm_fb_helper_deferred_io,
177};
178
179/*174/*
180 * This function uses the client API to create a framebuffer backed by a dumb buffer.175 * This function uses the client API to create a framebuffer backed by a dumb buffer.
181 */176 */
@@ -222,8 +217,14 @@ static int drm_fbdev_fb_probe(struct drm_fb_helper *fb_helper, · 40 unmodified lines
222 return -ENOMEM;217 return -ENOMEM;
223 fbi->flags |= FBINFO_VIRTFB | FBINFO_READS_FAST;218 fbi->flags |= FBINFO_VIRTFB | FBINFO_READS_FAST;
224 219
225 fbi->fbdefio = &drm_fbdev_defio;220 /* Set a default deferred I/O handler */
226 fb_deferred_io_init(fbi);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;
227 } else {228 } else {
228 /* buffer is mapped for HW framebuffer */229 /* buffer is mapped for HW framebuffer */
229 ret = drm_client_buffer_vmap(fb_helper->buffer, &map);230 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
240}240}
241EXPORT_SYMBOL(drm_vma_offset_remove);241EXPORT_SYMBOL(drm_vma_offset_remove);
242 242
243/**243static int vma_node_allow(struct drm_vma_offset_node *node,
244 * drm_vma_node_allow - Add open-file to list of allowed users244 struct drm_file *tag, bool ref_counted)
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 */
263int drm_vma_node_allow(struct drm_vma_offset_node *node, struct drm_file *tag)
264{245{
265 struct rb_node **iter;246 struct rb_node **iter;
266 struct rb_node *parent = NULL;247 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
282 entry = rb_entry(*iter, struct drm_vma_offset_file, vm_rb);263 entry = rb_entry(*iter, struct drm_vma_offset_file, vm_rb);
283 264
284 if (tag == entry->vm_tag) {265 if (tag == entry->vm_tag) {
285 entry->vm_count++;266 if (ref_counted)
267 entry->vm_count++;
286 goto unlock;268 goto unlock;
287 } else if (tag > entry->vm_tag) {269 } else if (tag > entry->vm_tag) {
288 iter = &(*iter)->rb_right;270 iter = &(*iter)->rb_right;
@@ -307,8 +289,58 @@ unlock: · 18 unmodified lines
307 kfree(new);289 kfree(new);
308 return ret;290 return ret;
309}291}
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 */
313int drm_vma_node_allow(struct drm_vma_offset_node *node, struct drm_file *tag)
314{
315 return vma_node_allow(node, tag, true);
316}
310EXPORT_SYMBOL(drm_vma_node_allow);317EXPORT_SYMBOL(drm_vma_node_allow);
311 318
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 */
338int 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}
342EXPORT_SYMBOL(drm_vma_node_allow_once);
343
312/**344/**
313 * drm_vma_node_revoke - Remove open-file from list of allowed users345 * drm_vma_node_revoke - Remove open-file from list of allowed users
314 * @node: Node to modify346 * @node: Node to modify
drivers/gpu/drm/i915/gem/i915_gem_mman.c+1−1
@@ -697,7 +697,7 @@ insert: · 696 unmodified lines
697 GEM_BUG_ON(lookup_mmo(obj, mmap_type) != mmo);697 GEM_BUG_ON(lookup_mmo(obj, mmap_type) != mmo);
698out:698out:
699 if (file)699 if (file)
700 drm_vma_node_allow(&mmo->vma_node, file);700 drm_vma_node_allow_once(&mmo->vma_node, file);
701 return mmo;701 return mmo;
702 702
703err:703err:
include/drm/drm_fb_helper.h+12−0
@@ -208,6 +208,18 @@ struct drm_fb_helper { · 207 unmodified lines
208 * the smem_start field should always be cleared to zero.208 * the smem_start field should always be cleared to zero.
209 */209 */
210 bool hint_leak_smem_start;210 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
211};223};
212 224
213static inline struct drm_fb_helper *225static 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
74 struct drm_vma_offset_node *node);74 struct drm_vma_offset_node *node);
75 75
76int drm_vma_node_allow(struct drm_vma_offset_node *node, struct drm_file *tag);76int drm_vma_node_allow(struct drm_vma_offset_node *node, struct drm_file *tag);
77int drm_vma_node_allow_once(struct drm_vma_offset_node *node, struct drm_file *tag);
77void drm_vma_node_revoke(struct drm_vma_offset_node *node,78void drm_vma_node_revoke(struct drm_vma_offset_node *node,
78 struct drm_file *tag);79 struct drm_file *tag);
79bool drm_vma_node_is_allowed(struct drm_vma_offset_node *node,80bool drm_vma_node_is_allowed(struct drm_vma_offset_node *node,