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

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>

From: Maxime Ripard <maxime@cerno.tech>
Link: https://patchwork.freedesktop.org/patch/msgid/20230126104018.cbrcjxl5wefdbb2f@houat

+76 -30
+8 -7
drivers/gpu/drm/drm_fbdev_generic.c
··· 171 171 .fb_imageblit = drm_fbdev_fb_imageblit, 172 172 }; 173 173 174 - static struct fb_deferred_io drm_fbdev_defio = { 175 - .delay = HZ / 20, 176 - .deferred_io = drm_fb_helper_deferred_io, 177 - }; 178 - 179 174 /* 180 175 * This function uses the client API to create a framebuffer backed by a dumb buffer. 181 176 */ ··· 217 222 return -ENOMEM; 218 223 fbi->flags |= FBINFO_VIRTFB | FBINFO_READS_FAST; 219 224 220 - fbi->fbdefio = &drm_fbdev_defio; 221 - fb_deferred_io_init(fbi); 225 + /* Set a default deferred I/O handler */ 226 + fb_helper->fbdefio.delay = HZ / 20; 227 + fb_helper->fbdefio.deferred_io = drm_fb_helper_deferred_io; 228 + 229 + fbi->fbdefio = &fb_helper->fbdefio; 230 + ret = fb_deferred_io_init(fbi); 231 + if (ret) 232 + return ret; 222 233 } else { 223 234 /* buffer is mapped for HW framebuffer */ 224 235 ret = drm_client_buffer_vmap(fb_helper->buffer, &map);
+54 -22
drivers/gpu/drm/drm_vma_manager.c
··· 240 240 } 241 241 EXPORT_SYMBOL(drm_vma_offset_remove); 242 242 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) 264 245 { 265 246 struct rb_node **iter; 266 247 struct rb_node *parent = NULL; ··· 263 282 entry = rb_entry(*iter, struct drm_vma_offset_file, vm_rb); 264 283 265 284 if (tag == entry->vm_tag) { 266 - entry->vm_count++; 285 + if (ref_counted) 286 + entry->vm_count++; 267 287 goto unlock; 268 288 } else if (tag > entry->vm_tag) { 269 289 iter = &(*iter)->rb_right; ··· 289 307 kfree(new); 290 308 return ret; 291 309 } 310 + 311 + /** 312 + * drm_vma_node_allow - Add open-file to list of allowed users 313 + * @node: Node to modify 314 + * @tag: Tag of file to remove 315 + * 316 + * Add @tag to the list of allowed open-files for this node. If @tag is 317 + * already on this list, the ref-count is incremented. 318 + * 319 + * The list of allowed-users is preserved across drm_vma_offset_add() and 320 + * drm_vma_offset_remove() calls. You may even call it if the node is currently 321 + * not added to any offset-manager. 322 + * 323 + * You must remove all open-files the same number of times as you added them 324 + * before destroying the node. Otherwise, you will leak memory. 325 + * 326 + * This is locked against concurrent access internally. 327 + * 328 + * RETURNS: 329 + * 0 on success, negative error code on internal failure (out-of-mem) 330 + */ 331 + int drm_vma_node_allow(struct drm_vma_offset_node *node, struct drm_file *tag) 332 + { 333 + return vma_node_allow(node, tag, true); 334 + } 292 335 EXPORT_SYMBOL(drm_vma_node_allow); 336 + 337 + /** 338 + * drm_vma_node_allow_once - Add open-file to list of allowed users 339 + * @node: Node to modify 340 + * @tag: Tag of file to remove 341 + * 342 + * Add @tag to the list of allowed open-files for this node. 343 + * 344 + * The list of allowed-users is preserved across drm_vma_offset_add() and 345 + * drm_vma_offset_remove() calls. You may even call it if the node is currently 346 + * not added to any offset-manager. 347 + * 348 + * This is not ref-counted unlike drm_vma_node_allow() hence drm_vma_node_revoke() 349 + * should only be called once after this. 350 + * 351 + * This is locked against concurrent access internally. 352 + * 353 + * RETURNS: 354 + * 0 on success, negative error code on internal failure (out-of-mem) 355 + */ 356 + int drm_vma_node_allow_once(struct drm_vma_offset_node *node, struct drm_file *tag) 357 + { 358 + return vma_node_allow(node, tag, false); 359 + } 360 + EXPORT_SYMBOL(drm_vma_node_allow_once); 293 361 294 362 /** 295 363 * drm_vma_node_revoke - Remove open-file from list of allowed users
+1 -1
drivers/gpu/drm/i915/gem/i915_gem_mman.c
··· 697 697 GEM_BUG_ON(lookup_mmo(obj, mmap_type) != mmo); 698 698 out: 699 699 if (file) 700 - drm_vma_node_allow(&mmo->vma_node, file); 700 + drm_vma_node_allow_once(&mmo->vma_node, file); 701 701 return mmo; 702 702 703 703 err:
+12
include/drm/drm_fb_helper.h
··· 208 208 * the smem_start field should always be cleared to zero. 209 209 */ 210 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 213 225 static inline struct drm_fb_helper *
+1
include/drm/drm_vma_manager.h
··· 74 74 struct drm_vma_offset_node *node); 75 75 76 76 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); 77 78 void drm_vma_node_revoke(struct drm_vma_offset_node *node, 78 79 struct drm_file *tag); 79 80 bool drm_vma_node_is_allowed(struct drm_vma_offset_node *node,