drm/ssd130x: Preallocate format-conversion buffer in atomic_check
authorThomas Zimmermann <tzimmermann@suse.de>
Mon, 9 Oct 2023 14:06:36 +0000 (16:06 +0200)
committerThomas Zimmermann <tzimmermann@suse.de>
Tue, 14 Nov 2023 09:17:23 +0000 (10:17 +0100)
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.

v6:
* update patch for ssd132x support

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
Tested-by: Javier Martinez Canillas <javierm@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20231009141018.11291-8-tzimmermann@suse.de
drivers/gpu/drm/solomon/ssd130x.c

index ee0a06c506926128a3da2190577a948fc2ac2dce..bef293922b98f0ae46a753d1a5d05974ddd14091 100644 (file)
@@ -873,6 +873,7 @@ static int ssd130x_primary_plane_atomic_check(struct drm_plane *plane,
        struct ssd130x_device *ssd130x = drm_to_ssd130x(drm);
        struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
        struct ssd130x_plane_state *ssd130x_state = to_ssd130x_plane_state(plane_state);
+       struct drm_shadow_plane_state *shadow_plane_state = &ssd130x_state->base;
        struct drm_crtc *crtc = plane_state->crtc;
        struct drm_crtc_state *crtc_state = NULL;
        const struct drm_format_info *fi;
@@ -897,6 +898,16 @@ static int ssd130x_primary_plane_atomic_check(struct drm_plane *plane,
 
        pitch = drm_format_info_min_pitch(fi, 0, ssd130x->width);
 
+       if (plane_state->fb->format != fi) {
+               void *buf;
+
+               /* format conversion necessary; reserve buffer */
+               buf = drm_format_conv_state_reserve(&shadow_plane_state->fmtcnv_state,
+                                                   pitch, GFP_KERNEL);
+               if (!buf)
+                       return -ENOMEM;
+       }
+
        ssd130x_state->buffer = kcalloc(pitch, ssd130x->height, GFP_KERNEL);
        if (!ssd130x_state->buffer)
                return -ENOMEM;
@@ -911,6 +922,7 @@ static int ssd132x_primary_plane_atomic_check(struct drm_plane *plane,
        struct ssd130x_device *ssd130x = drm_to_ssd130x(drm);
        struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
        struct ssd130x_plane_state *ssd130x_state = to_ssd130x_plane_state(plane_state);
+       struct drm_shadow_plane_state *shadow_plane_state = &ssd130x_state->base;
        struct drm_crtc *crtc = plane_state->crtc;
        struct drm_crtc_state *crtc_state = NULL;
        const struct drm_format_info *fi;
@@ -935,6 +947,16 @@ static int ssd132x_primary_plane_atomic_check(struct drm_plane *plane,
 
        pitch = drm_format_info_min_pitch(fi, 0, ssd130x->width);
 
+       if (plane_state->fb->format != fi) {
+               void *buf;
+
+               /* format conversion necessary; reserve buffer */
+               buf = drm_format_conv_state_reserve(&shadow_plane_state->fmtcnv_state,
+                                                   pitch, GFP_KERNEL);
+               if (!buf)
+                       return -ENOMEM;
+       }
+
        ssd130x_state->buffer = kcalloc(pitch, ssd130x->height, GFP_KERNEL);
        if (!ssd130x_state->buffer)
                return -ENOMEM;