Re: [PATCH v2 1/3] fbdev: Put mmap for deferred I/O into drivers

2022-04-26 Thread Thomas Zimmermann

Hi Sam

Am 25.04.22 um 19:46 schrieb Sam Ravnborg:

Hi Thomas,

On Mon, Apr 25, 2022 at 07:26:32PM +0200, Sam Ravnborg wrote:

Hi Thomas,


diff --git a/drivers/video/fbdev/core/fb_defio.c 
b/drivers/video/fbdev/core/fb_defio.c
index 6aaf6d0abf39..6924d489a289 100644
--- a/drivers/video/fbdev/core/fb_defio.c
+++ b/drivers/video/fbdev/core/fb_defio.c
@@ -181,6 +181,7 @@ int fb_deferred_io_mmap(struct fb_info *info, struct 
vm_area_struct *vma)
vma->vm_private_data = info;
return 0;
  }
+EXPORT_SYMBOL_GPL(fb_deferred_io_mmap);
  
  /* workqueue callback */

  static void fb_deferred_io_work(struct work_struct *work)
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
index 84427470367b..52440e3f8f69 100644
--- a/drivers/video/fbdev/core/fbmem.c
+++ b/drivers/video/fbdev/core/fbmem.c
@@ -1334,7 +1334,6 @@ static int
  fb_mmap(struct file *file, struct vm_area_struct * vma)
  {
struct fb_info *info = file_fb_info(file);
-   int (*fb_mmap_fn)(struct fb_info *info, struct vm_area_struct *vma);
unsigned long mmio_pgoff;
unsigned long start;
u32 len;
@@ -1343,14 +1342,7 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
return -ENODEV;
mutex_lock(>mm_lock);
  
-	fb_mmap_fn = info->fbops->fb_mmap;

-
-#if IS_ENABLED(CONFIG_FB_DEFERRED_IO)
-   if (info->fbdefio)
-   fb_mmap_fn = fb_deferred_io_mmap;
-#endif
-
-   if (fb_mmap_fn) {
+   if (info->fbops->fb_mmap) {
int res;
  
  		/*

@@ -1358,11 +1350,18 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
 * SME protection is removed ahead of the call
 */
vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot);
-   res = fb_mmap_fn(info, vma);
+   res = info->fbops->fb_mmap(info, vma);
mutex_unlock(>mm_lock);
return res;
}
  
+	/*

+* FB deferred I/O wants you to handle mmap in your drivers. At a
+* minimum, point struct fb_ops.fb_mmap to fb_deferred_io_mmap().
+*/
+   if (dev_WARN_ONCE(info->dev, info->fbdefio, "fbdev mmap not set up for 
defered I/O.\n"))
+   return -ENODEV;
+


If not configured - then why not just call fb_deferred_io_mmap(), as
this seems to be the default implementation anyway.
Then drivers that needs it can override - and the rest fallback to the
default.


Just to be clear - I already read:
"
Leave the mmap handling to drivers and expect them to call the
helper for deferred I/O by thmeselves.
"

But this does not help me understand why we need to explicit do what
could be a simple default implementation.
Chances are that I am stupid and it is obvious..


That's no stupid question. I didn't want to use a default implementation 
because there's no single one that severs all purposes. The current code 
all uses the same helper, but this will change with later patchsets. At 
some point, GEM is supposed to implement some of the logic for deferred 
I/O and will have to set it's own helpers. This can be seen in patches 8 
and 9 of [1]. I think it's better to clearly fail here than to provide a 
default implementation.


Best regards
Thomas

[1] 
https://lore.kernel.org/dri-devel/20220303205839.28484-1-tzimmerm...@suse.de/





Sam


--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Ivo Totev


OpenPGP_signature
Description: OpenPGP digital signature


Re: [PATCH v2 1/3] fbdev: Put mmap for deferred I/O into drivers

2022-04-25 Thread Sam Ravnborg
Hi Thomas,

On Mon, Apr 25, 2022 at 07:26:32PM +0200, Sam Ravnborg wrote:
> Hi Thomas,
> 
> > diff --git a/drivers/video/fbdev/core/fb_defio.c 
> > b/drivers/video/fbdev/core/fb_defio.c
> > index 6aaf6d0abf39..6924d489a289 100644
> > --- a/drivers/video/fbdev/core/fb_defio.c
> > +++ b/drivers/video/fbdev/core/fb_defio.c
> > @@ -181,6 +181,7 @@ int fb_deferred_io_mmap(struct fb_info *info, struct 
> > vm_area_struct *vma)
> > vma->vm_private_data = info;
> > return 0;
> >  }
> > +EXPORT_SYMBOL_GPL(fb_deferred_io_mmap);
> >  
> >  /* workqueue callback */
> >  static void fb_deferred_io_work(struct work_struct *work)
> > diff --git a/drivers/video/fbdev/core/fbmem.c 
> > b/drivers/video/fbdev/core/fbmem.c
> > index 84427470367b..52440e3f8f69 100644
> > --- a/drivers/video/fbdev/core/fbmem.c
> > +++ b/drivers/video/fbdev/core/fbmem.c
> > @@ -1334,7 +1334,6 @@ static int
> >  fb_mmap(struct file *file, struct vm_area_struct * vma)
> >  {
> > struct fb_info *info = file_fb_info(file);
> > -   int (*fb_mmap_fn)(struct fb_info *info, struct vm_area_struct *vma);
> > unsigned long mmio_pgoff;
> > unsigned long start;
> > u32 len;
> > @@ -1343,14 +1342,7 @@ fb_mmap(struct file *file, struct vm_area_struct * 
> > vma)
> > return -ENODEV;
> > mutex_lock(>mm_lock);
> >  
> > -   fb_mmap_fn = info->fbops->fb_mmap;
> > -
> > -#if IS_ENABLED(CONFIG_FB_DEFERRED_IO)
> > -   if (info->fbdefio)
> > -   fb_mmap_fn = fb_deferred_io_mmap;
> > -#endif
> > -
> > -   if (fb_mmap_fn) {
> > +   if (info->fbops->fb_mmap) {
> > int res;
> >  
> > /*
> > @@ -1358,11 +1350,18 @@ fb_mmap(struct file *file, struct vm_area_struct * 
> > vma)
> >  * SME protection is removed ahead of the call
> >  */
> > vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot);
> > -   res = fb_mmap_fn(info, vma);
> > +   res = info->fbops->fb_mmap(info, vma);
> > mutex_unlock(>mm_lock);
> > return res;
> > }
> >  
> > +   /*
> > +* FB deferred I/O wants you to handle mmap in your drivers. At a
> > +* minimum, point struct fb_ops.fb_mmap to fb_deferred_io_mmap().
> > +*/
> > +   if (dev_WARN_ONCE(info->dev, info->fbdefio, "fbdev mmap not set up for 
> > defered I/O.\n"))
> > +   return -ENODEV;
> > +
> 
> If not configured - then why not just call fb_deferred_io_mmap(), as
> this seems to be the default implementation anyway.
> Then drivers that needs it can override - and the rest fallback to the
> default.

Just to be clear - I already read:
"
Leave the mmap handling to drivers and expect them to call the
helper for deferred I/O by thmeselves.
"

But this does not help me understand why we need to explicit do what
could be a simple default implementation.
Chances are that I am stupid and it is obvious..

Sam


Re: [PATCH v2 1/3] fbdev: Put mmap for deferred I/O into drivers

2022-04-25 Thread Sam Ravnborg
Hi Thomas,

> diff --git a/drivers/video/fbdev/core/fb_defio.c 
> b/drivers/video/fbdev/core/fb_defio.c
> index 6aaf6d0abf39..6924d489a289 100644
> --- a/drivers/video/fbdev/core/fb_defio.c
> +++ b/drivers/video/fbdev/core/fb_defio.c
> @@ -181,6 +181,7 @@ int fb_deferred_io_mmap(struct fb_info *info, struct 
> vm_area_struct *vma)
>   vma->vm_private_data = info;
>   return 0;
>  }
> +EXPORT_SYMBOL_GPL(fb_deferred_io_mmap);
>  
>  /* workqueue callback */
>  static void fb_deferred_io_work(struct work_struct *work)
> diff --git a/drivers/video/fbdev/core/fbmem.c 
> b/drivers/video/fbdev/core/fbmem.c
> index 84427470367b..52440e3f8f69 100644
> --- a/drivers/video/fbdev/core/fbmem.c
> +++ b/drivers/video/fbdev/core/fbmem.c
> @@ -1334,7 +1334,6 @@ static int
>  fb_mmap(struct file *file, struct vm_area_struct * vma)
>  {
>   struct fb_info *info = file_fb_info(file);
> - int (*fb_mmap_fn)(struct fb_info *info, struct vm_area_struct *vma);
>   unsigned long mmio_pgoff;
>   unsigned long start;
>   u32 len;
> @@ -1343,14 +1342,7 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
>   return -ENODEV;
>   mutex_lock(>mm_lock);
>  
> - fb_mmap_fn = info->fbops->fb_mmap;
> -
> -#if IS_ENABLED(CONFIG_FB_DEFERRED_IO)
> - if (info->fbdefio)
> - fb_mmap_fn = fb_deferred_io_mmap;
> -#endif
> -
> - if (fb_mmap_fn) {
> + if (info->fbops->fb_mmap) {
>   int res;
>  
>   /*
> @@ -1358,11 +1350,18 @@ fb_mmap(struct file *file, struct vm_area_struct * 
> vma)
>* SME protection is removed ahead of the call
>*/
>   vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot);
> - res = fb_mmap_fn(info, vma);
> + res = info->fbops->fb_mmap(info, vma);
>   mutex_unlock(>mm_lock);
>   return res;
>   }
>  
> + /*
> +  * FB deferred I/O wants you to handle mmap in your drivers. At a
> +  * minimum, point struct fb_ops.fb_mmap to fb_deferred_io_mmap().
> +  */
> + if (dev_WARN_ONCE(info->dev, info->fbdefio, "fbdev mmap not set up for 
> defered I/O.\n"))
> + return -ENODEV;
> +

If not configured - then why not just call fb_deferred_io_mmap(), as
this seems to be the default implementation anyway.
Then drivers that needs it can override - and the rest fallback to the
default.

Sam


Re: [PATCH v2 1/3] fbdev: Put mmap for deferred I/O into drivers

2022-04-25 Thread kernel test robot
Hi Thomas,

I love your patch! Yet something to improve:

[auto build test ERROR on 0e7deff6446a4ba2c75f499a0bfa80cd6a15c129]

url:
https://github.com/intel-lab-lkp/linux/commits/Thomas-Zimmermann/fbdev-Decouple-deferred-I-O-from-struct-page/20220425-192955
base:   0e7deff6446a4ba2c75f499a0bfa80cd6a15c129
config: parisc-randconfig-r011-20220425 
(https://download.01.org/0day-ci/archive/20220425/202204252303.xu2n4l6y-...@intel.com/config)
compiler: hppa-linux-gcc (GCC) 11.3.0
reproduce (this is a W=1 build):
wget 
https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O 
~/bin/make.cross
chmod +x ~/bin/make.cross
# 
https://github.com/intel-lab-lkp/linux/commit/183267de16bfe1cd6ec119bcfdaf95e3706bf87e
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review 
Thomas-Zimmermann/fbdev-Decouple-deferred-I-O-from-struct-page/20220425-192955
git checkout 183267de16bfe1cd6ec119bcfdaf95e3706bf87e
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.3.0 make.cross W=1 
O=build_dir ARCH=parisc SHELL=/bin/bash drivers/video/fbdev/core/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot 

All errors (new ones prefixed by >>):

   In file included from include/linux/printk.h:11,
from include/linux/kernel.h:29,
from include/linux/cpumask.h:10,
from include/linux/mm_types_task.h:14,
from include/linux/mm_types.h:5,
from include/linux/buildid.h:5,
from include/linux/module.h:14,
from drivers/video/fbdev/core/fbmem.c:14:
   drivers/video/fbdev/core/fbmem.c: In function 'fb_mmap':
>> drivers/video/fbdev/core/fbmem.c:1362:42: error: 'struct fb_info' has no 
>> member named 'fbdefio'
1362 | if (dev_WARN_ONCE(info->dev, info->fbdefio, "fbdev mmap not 
set up for defered I/O.\n"))
 |  ^~
   include/linux/once_lite.h:15:41: note: in definition of macro 
'DO_ONCE_LITE_IF'
  15 | bool __ret_do_once = !!(condition);  
   \
 | ^
   include/linux/dev_printk.h:274:9: note: in expansion of macro 'WARN_ONCE'
 274 | WARN_ONCE(condition, "%s %s: " format, \
 | ^
   drivers/video/fbdev/core/fbmem.c:1362:13: note: in expansion of macro 
'dev_WARN_ONCE'
1362 | if (dev_WARN_ONCE(info->dev, info->fbdefio, "fbdev mmap not 
set up for defered I/O.\n"))
 | ^


vim +1362 drivers/video/fbdev/core/fbmem.c

  1332  
  1333  static int
  1334  fb_mmap(struct file *file, struct vm_area_struct * vma)
  1335  {
  1336  struct fb_info *info = file_fb_info(file);
  1337  unsigned long mmio_pgoff;
  1338  unsigned long start;
  1339  u32 len;
  1340  
  1341  if (!info)
  1342  return -ENODEV;
  1343  mutex_lock(>mm_lock);
  1344  
  1345  if (info->fbops->fb_mmap) {
  1346  int res;
  1347  
  1348  /*
  1349   * The framebuffer needs to be accessed decrypted, be 
sure
  1350   * SME protection is removed ahead of the call
  1351   */
  1352  vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot);
  1353  res = info->fbops->fb_mmap(info, vma);
  1354  mutex_unlock(>mm_lock);
  1355  return res;
  1356  }
  1357  
  1358  /*
  1359   * FB deferred I/O wants you to handle mmap in your drivers. At 
a
  1360   * minimum, point struct fb_ops.fb_mmap to 
fb_deferred_io_mmap().
  1361   */
> 1362  if (dev_WARN_ONCE(info->dev, info->fbdefio, "fbdev mmap not set 
> up for defered I/O.\n"))
  1363  return -ENODEV;
  1364  
  1365  /*
  1366   * Ugh. This can be either the frame buffer mapping, or
  1367   * if pgoff points past it, the mmio mapping.
  1368   */
  1369  start = info->fix.smem_start;
  1370  len = info->fix.smem_len;
  1371  mmio_pgoff = PAGE_ALIGN((start & ~PAGE_MASK) + len) >> 
PAGE_SHIFT;
  1372  if (vma->vm_pgoff >= mmio_pgoff) {
  1373  if (info->var.accel_flags) {
  1374  mutex_unlock(>mm_lock);
  1375  return -EINVAL;
  1376  }
  1377  
  1378  vma->vm_pgoff -= mmio_pgoff;
  1379  start = info->fix.mmio_start;
  1380  len = info->fix.mmio_len;
  1381  }
  1382  mutex_unlock(>mm_lock);
  1383  
  1384  vma->vm_page_prot = 

[PATCH v2 1/3] fbdev: Put mmap for deferred I/O into drivers

2022-04-25 Thread Thomas Zimmermann
The fbdev mmap function fb_mmap() unconditionally overrides the
driver's implementation if deferred I/O has been activated. This
makes it hard to implement mmap with anything but a vmalloc()'ed
software buffer. That is specifically a problem for DRM, where
video memory is maintained by a memory manager.

Leave the mmap handling to drivers and expect them to call the
helper for deferred I/O by thmeselves.

v2:
* print a helpful error message if the defio setup is
  incorrect (Javier)

Signed-off-by: Thomas Zimmermann 
Reviewed-by: Javier Martinez Canillas 
---
 drivers/gpu/drm/drm_fb_helper.c|  4 +++-
 drivers/gpu/drm/vmwgfx/vmwgfx_fb.c |  1 +
 drivers/hid/hid-picolcd_fb.c   |  1 +
 drivers/staging/fbtft/fbtft-core.c |  1 +
 drivers/video/fbdev/broadsheetfb.c |  1 +
 drivers/video/fbdev/core/fb_defio.c|  1 +
 drivers/video/fbdev/core/fbmem.c   | 19 +--
 drivers/video/fbdev/hecubafb.c |  1 +
 drivers/video/fbdev/hyperv_fb.c|  1 +
 drivers/video/fbdev/metronomefb.c  |  1 +
 drivers/video/fbdev/sh_mobile_lcdcfb.c |  6 ++
 drivers/video/fbdev/smscufx.c  |  3 +++
 drivers/video/fbdev/ssd1307fb.c|  1 +
 drivers/video/fbdev/udlfb.c|  3 +++
 drivers/video/fbdev/xen-fbfront.c  |  1 +
 15 files changed, 34 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index d265a73313c9..d06ce0e92d66 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -2118,7 +2118,9 @@ static int drm_fbdev_fb_mmap(struct fb_info *info, struct 
vm_area_struct *vma)
 {
struct drm_fb_helper *fb_helper = info->par;
 
-   if (fb_helper->dev->driver->gem_prime_mmap)
+   if (drm_fbdev_use_shadow_fb(fb_helper))
+   return fb_deferred_io_mmap(info, vma);
+   else if (fb_helper->dev->driver->gem_prime_mmap)
return 
fb_helper->dev->driver->gem_prime_mmap(fb_helper->buffer->gem, vma);
else
return -ENODEV;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
index adf17c740656..02a4a4fa3da3 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
@@ -619,6 +619,7 @@ static const struct fb_ops vmw_fb_ops = {
.fb_imageblit = vmw_fb_imageblit,
.fb_pan_display = vmw_fb_pan_display,
.fb_blank = vmw_fb_blank,
+   .fb_mmap = fb_deferred_io_mmap,
 };
 
 int vmw_fb_init(struct vmw_private *vmw_priv)
diff --git a/drivers/hid/hid-picolcd_fb.c b/drivers/hid/hid-picolcd_fb.c
index 33c102a60992..78515e6bacf0 100644
--- a/drivers/hid/hid-picolcd_fb.c
+++ b/drivers/hid/hid-picolcd_fb.c
@@ -428,6 +428,7 @@ static const struct fb_ops picolcdfb_ops = {
.fb_imageblit = picolcd_fb_imageblit,
.fb_check_var = picolcd_fb_check_var,
.fb_set_par   = picolcd_set_par,
+   .fb_mmap  = fb_deferred_io_mmap,
 };
 
 
diff --git a/drivers/staging/fbtft/fbtft-core.c 
b/drivers/staging/fbtft/fbtft-core.c
index 9c4d797e7ae4..d4e14f7c9d57 100644
--- a/drivers/staging/fbtft/fbtft-core.c
+++ b/drivers/staging/fbtft/fbtft-core.c
@@ -652,6 +652,7 @@ struct fb_info *fbtft_framebuffer_alloc(struct 
fbtft_display *display,
fbops->fb_imageblit =  fbtft_fb_imageblit;
fbops->fb_setcolreg =  fbtft_fb_setcolreg;
fbops->fb_blank =  fbtft_fb_blank;
+   fbops->fb_mmap  =  fb_deferred_io_mmap;
 
fbdefio->delay =   HZ / fps;
fbdefio->sort_pagelist =   true;
diff --git a/drivers/video/fbdev/broadsheetfb.c 
b/drivers/video/fbdev/broadsheetfb.c
index b9054f658838..528bc0902338 100644
--- a/drivers/video/fbdev/broadsheetfb.c
+++ b/drivers/video/fbdev/broadsheetfb.c
@@ -1055,6 +1055,7 @@ static const struct fb_ops broadsheetfb_ops = {
.fb_fillrect= broadsheetfb_fillrect,
.fb_copyarea= broadsheetfb_copyarea,
.fb_imageblit   = broadsheetfb_imageblit,
+   .fb_mmap= fb_deferred_io_mmap,
 };
 
 static struct fb_deferred_io broadsheetfb_defio = {
diff --git a/drivers/video/fbdev/core/fb_defio.c 
b/drivers/video/fbdev/core/fb_defio.c
index 6aaf6d0abf39..6924d489a289 100644
--- a/drivers/video/fbdev/core/fb_defio.c
+++ b/drivers/video/fbdev/core/fb_defio.c
@@ -181,6 +181,7 @@ int fb_deferred_io_mmap(struct fb_info *info, struct 
vm_area_struct *vma)
vma->vm_private_data = info;
return 0;
 }
+EXPORT_SYMBOL_GPL(fb_deferred_io_mmap);
 
 /* workqueue callback */
 static void fb_deferred_io_work(struct work_struct *work)
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
index 84427470367b..52440e3f8f69 100644
--- a/drivers/video/fbdev/core/fbmem.c
+++ b/drivers/video/fbdev/core/fbmem.c
@@ -1334,7 +1334,6 @@ static int
 fb_mmap(struct file *file, struct vm_area_struct * vma)
 {
struct fb_info *info = file_fb_info(file);
-   int