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

Configure Feed

Select the types of activity you want to include in your feed.

drm/client: Add client free callback to unprepare fb_helper

Add free callback to struct drm_client_funcs. Invoke function to
free the client memory as part of the release process. Implement
free for fbdev emulation.

Fbdev emulation allocates and prepares client memory in
drm_fbdev_client_setup(). The release happens in fb_destroy from
struct fb_ops. Multiple implementations of this callback exist in
the various drivers that provide an fbdev implementation. Each of
them needs to follow the implementation details of the fbdev setup
code.

Adding a free callback for the client puts the unprepare and release
of the fbdev client in a single place.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com> # core, msm
Acked-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> # omapdrm
Acked-by: Patrik Jakobsson <patrik.r.jakobsson@gmail.com> # gma500
Acked-by: Alex Deucher <alexander.deucher@amd.com>
Link: https://lore.kernel.org/r/20251009132006.45834-2-tzimmermann@suse.de

+29 -27
-2
drivers/gpu/drm/armada/armada_fbdev.c
··· 28 28 fbh->fb->funcs->destroy(fbh->fb); 29 29 30 30 drm_client_release(&fbh->client); 31 - drm_fb_helper_unprepare(fbh); 32 - kfree(fbh); 33 31 } 34 32 35 33 static const struct fb_ops armada_fb_ops = {
+15 -2
drivers/gpu/drm/clients/drm_fbdev_client.c
··· 13 13 * struct drm_client_funcs 14 14 */ 15 15 16 + static void drm_fbdev_client_free(struct drm_client_dev *client) 17 + { 18 + struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client); 19 + 20 + drm_fb_helper_unprepare(fb_helper); 21 + kfree(fb_helper); 22 + } 23 + 16 24 static void drm_fbdev_client_unregister(struct drm_client_dev *client) 17 25 { 18 26 struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client); 19 27 20 28 if (fb_helper->info) { 29 + /* 30 + * Fully probed framebuffer device 31 + */ 21 32 drm_fb_helper_unregister_info(fb_helper); 22 33 } else { 34 + /* 35 + * Partially initialized client, no framebuffer device yet 36 + */ 23 37 drm_client_release(&fb_helper->client); 24 - drm_fb_helper_unprepare(fb_helper); 25 - kfree(fb_helper); 26 38 } 27 39 } 28 40 ··· 94 82 95 83 static const struct drm_client_funcs drm_fbdev_client_funcs = { 96 84 .owner = THIS_MODULE, 85 + .free = drm_fbdev_client_free, 97 86 .unregister = drm_fbdev_client_unregister, 98 87 .restore = drm_fbdev_client_restore, 99 88 .hotplug = drm_fbdev_client_hotplug,
+4
drivers/gpu/drm/drm_client.c
··· 168 168 169 169 drm_client_modeset_free(client); 170 170 drm_client_close(client); 171 + 172 + if (client->funcs && client->funcs->free) 173 + client->funcs->free(client); 174 + 171 175 drm_dev_put(dev); 172 176 } 173 177 EXPORT_SYMBOL(drm_client_release);
-4
drivers/gpu/drm/drm_fbdev_dma.c
··· 57 57 drm_client_buffer_vunmap(fb_helper->buffer); 58 58 drm_client_framebuffer_delete(fb_helper->buffer); 59 59 drm_client_release(&fb_helper->client); 60 - drm_fb_helper_unprepare(fb_helper); 61 - kfree(fb_helper); 62 60 } 63 61 64 62 static const struct fb_ops drm_fbdev_dma_fb_ops = { ··· 90 92 drm_client_buffer_vunmap(fb_helper->buffer); 91 93 drm_client_framebuffer_delete(fb_helper->buffer); 92 94 drm_client_release(&fb_helper->client); 93 - drm_fb_helper_unprepare(fb_helper); 94 - kfree(fb_helper); 95 95 } 96 96 97 97 static const struct fb_ops drm_fbdev_dma_shadowed_fb_ops = {
-2
drivers/gpu/drm/drm_fbdev_shmem.c
··· 65 65 drm_client_buffer_vunmap(fb_helper->buffer); 66 66 drm_client_framebuffer_delete(fb_helper->buffer); 67 67 drm_client_release(&fb_helper->client); 68 - drm_fb_helper_unprepare(fb_helper); 69 - kfree(fb_helper); 70 68 } 71 69 72 70 static const struct fb_ops drm_fbdev_shmem_fb_ops = {
-2
drivers/gpu/drm/drm_fbdev_ttm.c
··· 53 53 drm_client_framebuffer_delete(fb_helper->buffer); 54 54 55 55 drm_client_release(&fb_helper->client); 56 - drm_fb_helper_unprepare(fb_helper); 57 - kfree(fb_helper); 58 56 } 59 57 60 58 static const struct fb_ops drm_fbdev_ttm_fb_ops = {
-2
drivers/gpu/drm/exynos/exynos_drm_fbdev.c
··· 42 42 drm_framebuffer_remove(fb); 43 43 44 44 drm_client_release(&fb_helper->client); 45 - drm_fb_helper_unprepare(fb_helper); 46 - kfree(fb_helper); 47 45 } 48 46 49 47 static const struct fb_ops exynos_drm_fb_ops = {
-3
drivers/gpu/drm/gma500/fbdev.c
··· 84 84 drm_gem_object_put(obj); 85 85 86 86 drm_client_release(&fb_helper->client); 87 - 88 - drm_fb_helper_unprepare(fb_helper); 89 - kfree(fb_helper); 90 87 } 91 88 92 89 static const struct fb_ops psb_fbdev_fb_ops = {
-2
drivers/gpu/drm/i915/display/intel_fbdev.c
··· 146 146 drm_framebuffer_remove(fb_helper->fb); 147 147 148 148 drm_client_release(&fb_helper->client); 149 - drm_fb_helper_unprepare(fb_helper); 150 - kfree(fb_helper); 151 149 } 152 150 153 151 __diag_push();
-2
drivers/gpu/drm/msm/msm_fbdev.c
··· 52 52 drm_framebuffer_remove(fb); 53 53 54 54 drm_client_release(&helper->client); 55 - drm_fb_helper_unprepare(helper); 56 - kfree(helper); 57 55 } 58 56 59 57 static const struct fb_ops msm_fb_ops = {
-2
drivers/gpu/drm/omapdrm/omap_fbdev.c
··· 103 103 drm_framebuffer_remove(fb); 104 104 105 105 drm_client_release(&helper->client); 106 - drm_fb_helper_unprepare(helper); 107 - kfree(helper); 108 106 } 109 107 110 108 /*
-2
drivers/gpu/drm/radeon/radeon_fbdev.c
··· 184 184 radeon_fbdev_destroy_pinned_object(gobj); 185 185 186 186 drm_client_release(&fb_helper->client); 187 - drm_fb_helper_unprepare(fb_helper); 188 - kfree(fb_helper); 189 187 } 190 188 191 189 static const struct fb_ops radeon_fbdev_fb_ops = {
-2
drivers/gpu/drm/tegra/fbdev.c
··· 53 53 drm_framebuffer_remove(fb); 54 54 55 55 drm_client_release(&helper->client); 56 - drm_fb_helper_unprepare(helper); 57 - kfree(helper); 58 56 } 59 57 60 58 static const struct fb_ops tegra_fb_ops = {
+10
include/drm/drm_client.h
··· 29 29 struct module *owner; 30 30 31 31 /** 32 + * @free: 33 + * 34 + * Called when the client gets unregistered. Implementations should 35 + * release all client-specific data and free the memory. 36 + * 37 + * This callback is optional. 38 + */ 39 + void (*free)(struct drm_client_dev *client); 40 + 41 + /** 32 42 * @unregister: 33 43 * 34 44 * Called when &drm_device is unregistered. The client should respond by