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

drm/simpledrm: Preallocate format-conversion buffer in atomic_check

Preallocate the format-conversion state's storage in the plane's
atomic_check function if a format conversion is necessary. Allows
the update to fail if no memory is available. Avoids the same
allocation within atomic_update, which may not fail.

Also inline drm_plane_helper_atomic_check() into the driver and thus
return early for invisible planes. Avoids memory allocation entirely
in this case.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20231009141018.11291-6-tzimmermann@suse.de

+40 -1
+40 -1
drivers/gpu/drm/tiny/simpledrm.c
··· 19 19 #include <drm/drm_drv.h> 20 20 #include <drm/drm_fbdev_generic.h> 21 21 #include <drm/drm_format_helper.h> 22 + #include <drm/drm_framebuffer.h> 22 23 #include <drm/drm_gem_atomic_helper.h> 23 24 #include <drm/drm_gem_framebuffer_helper.h> 24 25 #include <drm/drm_gem_shmem_helper.h> ··· 580 579 DRM_FORMAT_MOD_INVALID 581 580 }; 582 581 582 + static int simpledrm_primary_plane_helper_atomic_check(struct drm_plane *plane, 583 + struct drm_atomic_state *state) 584 + { 585 + struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane); 586 + struct drm_shadow_plane_state *new_shadow_plane_state = 587 + to_drm_shadow_plane_state(new_plane_state); 588 + struct drm_framebuffer *new_fb = new_plane_state->fb; 589 + struct drm_crtc *new_crtc = new_plane_state->crtc; 590 + struct drm_crtc_state *new_crtc_state = NULL; 591 + struct drm_device *dev = plane->dev; 592 + struct simpledrm_device *sdev = simpledrm_device_of_dev(dev); 593 + int ret; 594 + 595 + if (new_crtc) 596 + new_crtc_state = drm_atomic_get_new_crtc_state(state, new_crtc); 597 + 598 + ret = drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state, 599 + DRM_PLANE_NO_SCALING, 600 + DRM_PLANE_NO_SCALING, 601 + false, false); 602 + if (ret) 603 + return ret; 604 + else if (!new_plane_state->visible) 605 + return 0; 606 + 607 + if (new_fb->format != sdev->format) { 608 + void *buf; 609 + 610 + /* format conversion necessary; reserve buffer */ 611 + buf = drm_format_conv_state_reserve(&new_shadow_plane_state->fmtcnv_state, 612 + sdev->pitch, GFP_KERNEL); 613 + if (!buf) 614 + return -ENOMEM; 615 + } 616 + 617 + return 0; 618 + } 619 + 583 620 static void simpledrm_primary_plane_helper_atomic_update(struct drm_plane *plane, 584 621 struct drm_atomic_state *state) 585 622 { ··· 674 635 675 636 static const struct drm_plane_helper_funcs simpledrm_primary_plane_helper_funcs = { 676 637 DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, 677 - .atomic_check = drm_plane_helper_atomic_check, 638 + .atomic_check = simpledrm_primary_plane_helper_atomic_check, 678 639 .atomic_update = simpledrm_primary_plane_helper_atomic_update, 679 640 .atomic_disable = simpledrm_primary_plane_helper_atomic_disable, 680 641 };