aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorNoralf Trønnes <noralf@tronnes.org>2017-12-15 12:51:17 -0500
committerNoralf Trønnes <noralf@tronnes.org>2017-12-20 08:52:22 -0500
commit48c9571c34b153abc1c4f2b431fa74490b671943 (patch)
tree26ae43819c573a3be597c208e3cb9853edd1de87 /drivers
parent95b0137f28a420ac02826e674286bc363dd7c196 (diff)
drm/fb-helper: Add drm_fb_helper_defio_init()
Add helper for initializing fbdev deferred I/O. The cleanup could have happened in drm_fb_helper_fini(), but that would have required me to set fb_info->fbdefio to NULL in a couple of drivers before they call _fini() to avoid double defio cleanup. The problem is that one of those is vboxvideo which lives in Greg's staging tree. So I put the cleanup in drm_fb_helper_fbdev_teardown(), not perfect but not that bad either. Signed-off-by: Noralf Trønnes <noralf@tronnes.org> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20171215175119.36181-6-noralf@tronnes.org
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c54
1 files changed, 53 insertions, 1 deletions
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index e3eb3c9a98e3..4a61e1aef41b 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -107,7 +107,8 @@ static DEFINE_MUTEX(kernel_fb_helper_lock);
107 * always run in process context since the fb_*() function could be running in 107 * always run in process context since the fb_*() function could be running in
108 * atomic context. If drm_fb_helper_deferred_io() is used as the deferred_io 108 * atomic context. If drm_fb_helper_deferred_io() is used as the deferred_io
109 * callback it will also schedule dirty_work with the damage collected from the 109 * callback it will also schedule dirty_work with the damage collected from the
110 * mmap page writes. 110 * mmap page writes. Drivers can use drm_fb_helper_defio_init() to setup
111 * deferred I/O (coupled with drm_fb_helper_fbdev_teardown()).
111 */ 112 */
112 113
113#define drm_fb_helper_for_each_connector(fbh, i__) \ 114#define drm_fb_helper_for_each_connector(fbh, i__) \
@@ -1029,6 +1030,49 @@ void drm_fb_helper_deferred_io(struct fb_info *info,
1029EXPORT_SYMBOL(drm_fb_helper_deferred_io); 1030EXPORT_SYMBOL(drm_fb_helper_deferred_io);
1030 1031
1031/** 1032/**
1033 * drm_fb_helper_defio_init - fbdev deferred I/O initialization
1034 * @fb_helper: driver-allocated fbdev helper
1035 *
1036 * This function allocates &fb_deferred_io, sets callback to
1037 * drm_fb_helper_deferred_io(), delay to 50ms and calls fb_deferred_io_init().
1038 * It should be called from the &drm_fb_helper_funcs->fb_probe callback.
1039 * drm_fb_helper_fbdev_teardown() cleans up deferred I/O.
1040 *
1041 * NOTE: A copy of &fb_ops is made and assigned to &info->fbops. This is done
1042 * because fb_deferred_io_cleanup() clears &fbops->fb_mmap and would thereby
1043 * affect other instances of that &fb_ops.
1044 *
1045 * Returns:
1046 * 0 on success or a negative error code on failure.
1047 */
1048int drm_fb_helper_defio_init(struct drm_fb_helper *fb_helper)
1049{
1050 struct fb_info *info = fb_helper->fbdev;
1051 struct fb_deferred_io *fbdefio;
1052 struct fb_ops *fbops;
1053
1054 fbdefio = kzalloc(sizeof(*fbdefio), GFP_KERNEL);
1055 fbops = kzalloc(sizeof(*fbops), GFP_KERNEL);
1056 if (!fbdefio || !fbops) {
1057 kfree(fbdefio);
1058 kfree(fbops);
1059 return -ENOMEM;
1060 }
1061
1062 info->fbdefio = fbdefio;
1063 fbdefio->delay = msecs_to_jiffies(50);
1064 fbdefio->deferred_io = drm_fb_helper_deferred_io;
1065
1066 *fbops = *info->fbops;
1067 info->fbops = fbops;
1068
1069 fb_deferred_io_init(info);
1070
1071 return 0;
1072}
1073EXPORT_SYMBOL(drm_fb_helper_defio_init);
1074
1075/**
1032 * drm_fb_helper_sys_read - wrapper around fb_sys_read 1076 * drm_fb_helper_sys_read - wrapper around fb_sys_read
1033 * @info: fb_info struct pointer 1077 * @info: fb_info struct pointer
1034 * @buf: userspace buffer to read from framebuffer memory 1078 * @buf: userspace buffer to read from framebuffer memory
@@ -2824,6 +2868,7 @@ EXPORT_SYMBOL(drm_fb_helper_fbdev_setup);
2824void drm_fb_helper_fbdev_teardown(struct drm_device *dev) 2868void drm_fb_helper_fbdev_teardown(struct drm_device *dev)
2825{ 2869{
2826 struct drm_fb_helper *fb_helper = dev->fb_helper; 2870 struct drm_fb_helper *fb_helper = dev->fb_helper;
2871 struct fb_ops *fbops = NULL;
2827 2872
2828 if (!fb_helper) 2873 if (!fb_helper)
2829 return; 2874 return;
@@ -2832,7 +2877,14 @@ void drm_fb_helper_fbdev_teardown(struct drm_device *dev)
2832 if (fb_helper->fbdev && fb_helper->fbdev->dev) 2877 if (fb_helper->fbdev && fb_helper->fbdev->dev)
2833 drm_fb_helper_unregister_fbi(fb_helper); 2878 drm_fb_helper_unregister_fbi(fb_helper);
2834 2879
2880 if (fb_helper->fbdev && fb_helper->fbdev->fbdefio) {
2881 fb_deferred_io_cleanup(fb_helper->fbdev);
2882 kfree(fb_helper->fbdev->fbdefio);
2883 fbops = fb_helper->fbdev->fbops;
2884 }
2885
2835 drm_fb_helper_fini(fb_helper); 2886 drm_fb_helper_fini(fb_helper);
2887 kfree(fbops);
2836 2888
2837 if (fb_helper->fb) 2889 if (fb_helper->fb)
2838 drm_framebuffer_remove(fb_helper->fb); 2890 drm_framebuffer_remove(fb_helper->fb);