From mboxrd@z Thu Jan 1 00:00:00 1970 From: =?UTF-8?Q?Noralf_Tr=c3=b8nnes?= Date: Tue, 26 Apr 2016 16:24:54 +0000 Subject: Re: [PATCH v2 4/8] drm/fb-helper: Add fb_deferred_io support Message-Id: <571F9656.1090506@tronnes.org> List-Id: References: <1461530942-22485-1-git-send-email-noralf@tronnes.org> <1461530942-22485-5-git-send-email-noralf@tronnes.org> <20160425090957.GQ2510@phenom.ffwll.local> In-Reply-To: <20160425090957.GQ2510@phenom.ffwll.local> MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable To: dri-devel@lists.freedesktop.org, linux-fbdev@vger.kernel.org, laurent.pinchart@ideasonboard.com, tomi.valkeinen@ti.com, linux-kernel@vger.kernel.org Den 25.04.2016 11:09, skrev Daniel Vetter: > On Sun, Apr 24, 2016 at 10:48:58PM +0200, Noralf Tr=F8nnes wrote: >> This adds deferred io support if CONFIG_FB_DEFERRED_IO is enabled. >> The fbdev framebuffer changes are flushed using the callback >> (struct drm_framebuffer *)->funcs->dirty() by a dedicated worker >> ensuring that it always runs in process context. >> >> Signed-off-by: Noralf Tr=F8nnes >> --- >> >> Changes since v1: >> - Use a dedicated worker to run the framebuffer flushing like qxl does >> - Add parameter descriptions to drm_fb_helper_deferred_io >> >> drivers/gpu/drm/drm_fb_helper.c | 127 ++++++++++++++++++++++++++++++++= +++++++- >> include/drm/drm_fb_helper.h | 17 ++++++ >> 2 files changed, 143 insertions(+), 1 deletion(-) >> >> diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_he= lper.c >> index 855108e..46ee6f8 100644 >> --- a/drivers/gpu/drm/drm_fb_helper.c >> +++ b/drivers/gpu/drm/drm_fb_helper.c >> @@ -40,6 +40,7 @@ >> #include >> #include >> #include >> +#include >> >> static bool drm_fbdev_emulation =3D true; >> module_param_named(fbdev_emulation, drm_fbdev_emulation, bool, 0600); >> @@ -48,6 +49,10 @@ MODULE_PARM_DESC(fbdev_emulation, >> >> static LIST_HEAD(kernel_fb_helper_list); >> >> +static void drm_fb_helper_dirty_init(struct drm_fb_helper *helper); >> +static void drm_fb_helper_dirty(struct fb_info *info, u32 x, u32 y, >> + u32 width, u32 height); >> + >> /** >> * DOC: fbdev helpers >> * >> @@ -84,6 +89,16 @@ static LIST_HEAD(kernel_fb_helper_list); >> * and set up an initial configuration using the detected hardware, dr= ivers >> * should call drm_fb_helper_single_add_all_connectors() followed by >> * drm_fb_helper_initial_config(). >> + * >> + * If CONFIG_FB_DEFERRED_IO is enabled and >> + * (struct drm_framebuffer *)->funcs->dirty is set, the >> + * drm_fb_helper_{cfb,sys}_{write,fillrect,copyarea,imageblit} functions >> + * will accumulate changes and schedule (struct fb_helper).dirty_work t= o run >> + * right away. This worker then calls the dirty() function ensuring tha= t it >> + * will always run in process context since the fb_*() function could be >> + * running in atomic context. If drm_fb_helper_deferred_io() is used as= the >> + * deferred_io callback it will also schedule dirty_work with the damage >> + * collected from the mmap page writes. > One thing to consider (and personally I don't care either way) is whether > we shouldn't just select CONFIG_FB_DEFERRED_IO if the fbdev helpers are > enabled. Pushing that out to drivers is imo a bit fragile. > > But like I said I'm ok with either way. My concern was adding code and data that only a few drivers would actually use. But of course there's the tradeoff with complexity. I use this to enable it: select FB_DEFERRED_IO if DRM_KMS_FB_HELPER I guess the maintainer has to make this choice between size and=20 complexity :-) I can enable it by default if you want, drm is both huge and complex so I don't know what's best. As a sidenote, I have also put all the fbdev code in a file of it's own to make it simple with regards to the DRM_FBDEV_EMULATION user option: tinydrm-$(CONFIG_DRM_KMS_FB_HELPER) +=3D tinydrm-fbdev.o >> */ >> >> /** >> @@ -401,11 +416,14 @@ backoff: >> static int restore_fbdev_mode(struct drm_fb_helper *fb_helper) >> { >> struct drm_device *dev =3D fb_helper->dev; >> + struct fb_info *info =3D fb_helper->fbdev; >> struct drm_plane *plane; >> int i; >> >> drm_warn_on_modeset_not_all_locked(dev); >> >> + drm_fb_helper_dirty(info, 0, 0, info->var.xres, info->var.yres); > Why is this needed? If you do a modeset (or pageflip or whatever) drivers > are supposed to re-upload the entire screen. We've talked about adding a > dirty rectangle to atomic to allow userspace to optimize this, but there > should _never_ be a need to do a dirtyfb call around a modeset. Probably > just a driver bug in your panel drm drivers? Ok, in tinydrm I now set a flag in &drm_simple_display_pipe_funcs ->plane_update to indicate that the next dirty() should do the whole framebuffer which seems to work fine. Should I actually perform the update as well? If so I would need to add a worker in tinydrm to do that. Noralf. > With the above line removed: > > Reviewed-by: Daniel Vetter > >> + >> if (fb_helper->atomic) >> return restore_fbdev_mode_atomic(fb_helper); >> >> @@ -650,6 +668,7 @@ void drm_fb_helper_prepare(struct drm_device *dev, s= truct drm_fb_helper *helper, >> const struct drm_fb_helper_funcs *funcs) >> { >> INIT_LIST_HEAD(&helper->kernel_fb_list); >> + drm_fb_helper_dirty_init(helper); >> helper->funcs =3D funcs; >> helper->dev =3D dev; >> } >> @@ -834,6 +853,93 @@ void drm_fb_helper_unlink_fbi(struct drm_fb_helper = *fb_helper) >> } >> EXPORT_SYMBOL(drm_fb_helper_unlink_fbi); >> >> +#ifdef CONFIG_FB_DEFERRED_IO >> +static void drm_fb_helper_dirty_work(struct work_struct *work) >> +{ >> + struct drm_fb_helper *helper =3D container_of(work, struct drm_fb_help= er, >> + dirty_work); >> + struct drm_clip_rect clip; >> + unsigned long flags; >> + >> + spin_lock_irqsave(&helper->dirty_lock, flags); >> + clip =3D helper->dirty_clip; >> + drm_clip_rect_reset(&helper->dirty_clip); >> + spin_unlock_irqrestore(&helper->dirty_lock, flags); >> + >> + helper->fb->funcs->dirty(helper->fb, NULL, 0, 0, &clip, 1); >> +} >> + >> +static void drm_fb_helper_dirty_init(struct drm_fb_helper *helper) >> +{ >> + spin_lock_init(&helper->dirty_lock); >> + INIT_WORK(&helper->dirty_work, drm_fb_helper_dirty_work); >> +} >> + >> +static void drm_fb_helper_dirty(struct fb_info *info, u32 x, u32 y, >> + u32 width, u32 height) >> +{ >> + struct drm_fb_helper *helper =3D info->par; >> + struct drm_clip_rect clip; >> + unsigned long flags; >> + >> + if (!helper->fb->funcs->dirty) >> + return; >> + >> + clip.x1 =3D x; >> + clip.x2 =3D x + width; >> + clip.y1 =3D y; >> + clip.y2 =3D y + height; >> + >> + spin_lock_irqsave(&helper->dirty_lock, flags); >> + drm_clip_rect_merge(&helper->dirty_clip, &clip, 1, 0, 0, 0); >> + spin_unlock_irqrestore(&helper->dirty_lock, flags); >> + >> + schedule_work(&helper->dirty_work); >> +} >> + >> +/** >> + * drm_fb_helper_deferred_io() - fbdev deferred_io callback function >> + * @info: fb_info struct pointer >> + * @pagelist: list of dirty mmap framebuffer pages >> + * >> + * This function is used as the (struct fb_deferred_io *)->deferred_io >> + * callback function for flushing the fbdev mmap writes. >> + */ >> +void drm_fb_helper_deferred_io(struct fb_info *info, >> + struct list_head *pagelist) >> +{ >> + unsigned long start, end, min, max; >> + struct page *page; >> + u32 y1, y2; >> + >> + min =3D ULONG_MAX; >> + max =3D 0; >> + list_for_each_entry(page, pagelist, lru) { >> + start =3D page->index << PAGE_SHIFT; >> + end =3D start + PAGE_SIZE - 1; >> + min =3D min(min, start); >> + max =3D max(max, end); >> + } >> + >> + if (min < max) { >> + y1 =3D min / info->fix.line_length; >> + y2 =3D min_t(u32, max / info->fix.line_length, info->var.yres); >> + drm_fb_helper_dirty(info, 0, y1, info->var.xres, y2 - y1); >> + } >> +} >> +EXPORT_SYMBOL(drm_fb_helper_deferred_io); >> + >> +#else >> +static void drm_fb_helper_dirty_init(struct drm_fb_helper *helper) >> +{ >> +} >> + >> +static void drm_fb_helper_dirty(struct fb_info *info, u32 x, u32 y, >> + u32 width, u32 height) >> +{ >> +} >> +#endif /* CONFIG_FB_DEFERRED_IO */ >> + >> /** >> * drm_fb_helper_sys_read - wrapper around fb_sys_read >> * @info: fb_info struct pointer >> @@ -862,7 +968,14 @@ EXPORT_SYMBOL(drm_fb_helper_sys_read); >> ssize_t drm_fb_helper_sys_write(struct fb_info *info, const char __use= r *buf, >> size_t count, loff_t *ppos) >> { >> - return fb_sys_write(info, buf, count, ppos); >> + ssize_t ret; >> + >> + ret =3D fb_sys_write(info, buf, count, ppos); >> + if (ret > 0) >> + drm_fb_helper_dirty(info, 0, 0, info->var.xres, >> + info->var.yres); >> + >> + return ret; >> } >> EXPORT_SYMBOL(drm_fb_helper_sys_write); >> >> @@ -877,6 +990,8 @@ void drm_fb_helper_sys_fillrect(struct fb_info *info, >> const struct fb_fillrect *rect) >> { >> sys_fillrect(info, rect); >> + drm_fb_helper_dirty(info, rect->dx, rect->dy, >> + rect->width, rect->height); >> } >> EXPORT_SYMBOL(drm_fb_helper_sys_fillrect); >> >> @@ -891,6 +1006,8 @@ void drm_fb_helper_sys_copyarea(struct fb_info *inf= o, >> const struct fb_copyarea *area) >> { >> sys_copyarea(info, area); >> + drm_fb_helper_dirty(info, area->dx, area->dy, >> + area->width, area->height); >> } >> EXPORT_SYMBOL(drm_fb_helper_sys_copyarea); >> >> @@ -905,6 +1022,8 @@ void drm_fb_helper_sys_imageblit(struct fb_info *in= fo, >> const struct fb_image *image) >> { >> sys_imageblit(info, image); >> + drm_fb_helper_dirty(info, image->dx, image->dy, >> + image->width, image->height); >> } >> EXPORT_SYMBOL(drm_fb_helper_sys_imageblit); >> >> @@ -919,6 +1038,8 @@ void drm_fb_helper_cfb_fillrect(struct fb_info *inf= o, >> const struct fb_fillrect *rect) >> { >> cfb_fillrect(info, rect); >> + drm_fb_helper_dirty(info, rect->dx, rect->dy, >> + rect->width, rect->height); >> } >> EXPORT_SYMBOL(drm_fb_helper_cfb_fillrect); >> >> @@ -933,6 +1054,8 @@ void drm_fb_helper_cfb_copyarea(struct fb_info *inf= o, >> const struct fb_copyarea *area) >> { >> cfb_copyarea(info, area); >> + drm_fb_helper_dirty(info, area->dx, area->dy, >> + area->width, area->height); >> } >> EXPORT_SYMBOL(drm_fb_helper_cfb_copyarea); >> >> @@ -947,6 +1070,8 @@ void drm_fb_helper_cfb_imageblit(struct fb_info *in= fo, >> const struct fb_image *image) >> { >> cfb_imageblit(info, image); >> + drm_fb_helper_dirty(info, image->dx, image->dy, >> + image->width, image->height); >> } >> EXPORT_SYMBOL(drm_fb_helper_cfb_imageblit); >> >> diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h >> index 062723b..dde825c 100644 >> --- a/include/drm/drm_fb_helper.h >> +++ b/include/drm/drm_fb_helper.h >> @@ -172,6 +172,10 @@ struct drm_fb_helper_connector { >> * @funcs: driver callbacks for fb helper >> * @fbdev: emulated fbdev device info struct >> * @pseudo_palette: fake palette of 16 colors >> + * @dirty_clip: clip rectangle used with deferred_io to accumulate dama= ge to >> + * the screen buffer >> + * @dirty_lock: spinlock protecting @dirty_clip >> + * @dirty_work: worker used to flush the framebuffer >> * >> * This is the main structure used by the fbdev helpers. Drivers suppo= rting >> * fbdev emulation should embedded this into their overall driver stru= cture. >> @@ -189,6 +193,11 @@ struct drm_fb_helper { >> const struct drm_fb_helper_funcs *funcs; >> struct fb_info *fbdev; >> u32 pseudo_palette[17]; >> +#ifdef CONFIG_FB_DEFERRED_IO >> + struct drm_clip_rect dirty_clip; >> + spinlock_t dirty_lock; >> + struct work_struct dirty_work; >> +#endif >> >> /** >> * @kernel_fb_list: >> @@ -245,6 +254,9 @@ void drm_fb_helper_fill_fix(struct fb_info *info, ui= nt32_t pitch, >> >> void drm_fb_helper_unlink_fbi(struct drm_fb_helper *fb_helper); >> >> +void drm_fb_helper_deferred_io(struct fb_info *info, >> + struct list_head *pagelist); >> + >> ssize_t drm_fb_helper_sys_read(struct fb_info *info, char __user *buf, >> size_t count, loff_t *ppos); >> ssize_t drm_fb_helper_sys_write(struct fb_info *info, const char __use= r *buf, >> @@ -368,6 +380,11 @@ static inline void drm_fb_helper_unlink_fbi(struct = drm_fb_helper *fb_helper) >> { >> } >> >> +static inline void drm_fb_helper_deferred_io(struct fb_info *info, >> + struct list_head *pagelist) >> +{ >> +} >> + >> static inline ssize_t drm_fb_helper_sys_read(struct fb_info *info, >> char __user *buf, size_t count, >> loff_t *ppos) >> -- >> 2.2.2 >> From mboxrd@z Thu Jan 1 00:00:00 1970 From: =?UTF-8?Q?Noralf_Tr=c3=b8nnes?= Subject: Re: [PATCH v2 4/8] drm/fb-helper: Add fb_deferred_io support Date: Tue, 26 Apr 2016 18:24:54 +0200 Message-ID: <571F9656.1090506@tronnes.org> References: <1461530942-22485-1-git-send-email-noralf@tronnes.org> <1461530942-22485-5-git-send-email-noralf@tronnes.org> <20160425090957.GQ2510@phenom.ffwll.local> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8"; Format="flowed" Content-Transfer-Encoding: base64 Return-path: Received: from smtp.domeneshop.no (smtp.domeneshop.no [IPv6:2a01:5b40:0:3005::1]) by gabe.freedesktop.org (Postfix) with ESMTPS id 29EA66E877 for ; Tue, 26 Apr 2016 16:25:01 +0000 (UTC) In-Reply-To: <20160425090957.GQ2510@phenom.ffwll.local> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" To: dri-devel@lists.freedesktop.org, linux-fbdev@vger.kernel.org, laurent.pinchart@ideasonboard.com, tomi.valkeinen@ti.com, linux-kernel@vger.kernel.org List-Id: dri-devel@lists.freedesktop.org CkRlbiAyNS4wNC4yMDE2IDExOjA5LCBza3JldiBEYW5pZWwgVmV0dGVyOgo+IE9uIFN1biwgQXBy IDI0LCAyMDE2IGF0IDEwOjQ4OjU4UE0gKzAyMDAsIE5vcmFsZiBUcsO4bm5lcyB3cm90ZToKPj4g VGhpcyBhZGRzIGRlZmVycmVkIGlvIHN1cHBvcnQgaWYgQ09ORklHX0ZCX0RFRkVSUkVEX0lPIGlz IGVuYWJsZWQuCj4+IFRoZSBmYmRldiBmcmFtZWJ1ZmZlciBjaGFuZ2VzIGFyZSBmbHVzaGVkIHVz aW5nIHRoZSBjYWxsYmFjawo+PiAoc3RydWN0IGRybV9mcmFtZWJ1ZmZlciAqKS0+ZnVuY3MtPmRp cnR5KCkgYnkgYSBkZWRpY2F0ZWQgd29ya2VyCj4+IGVuc3VyaW5nIHRoYXQgaXQgYWx3YXlzIHJ1 bnMgaW4gcHJvY2VzcyBjb250ZXh0Lgo+Pgo+PiBTaWduZWQtb2ZmLWJ5OiBOb3JhbGYgVHLDuG5u ZXMgPG5vcmFsZkB0cm9ubmVzLm9yZz4KPj4gLS0tCj4+Cj4+IENoYW5nZXMgc2luY2UgdjE6Cj4+ IC0gVXNlIGEgZGVkaWNhdGVkIHdvcmtlciB0byBydW4gdGhlIGZyYW1lYnVmZmVyIGZsdXNoaW5n IGxpa2UgcXhsIGRvZXMKPj4gLSBBZGQgcGFyYW1ldGVyIGRlc2NyaXB0aW9ucyB0byBkcm1fZmJf aGVscGVyX2RlZmVycmVkX2lvCj4+Cj4+ICAgZHJpdmVycy9ncHUvZHJtL2RybV9mYl9oZWxwZXIu YyB8IDEyNyArKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKystCj4+ICAgaW5j bHVkZS9kcm0vZHJtX2ZiX2hlbHBlci5oICAgICB8ICAxNyArKysrKysKPj4gICAyIGZpbGVzIGNo YW5nZWQsIDE0MyBpbnNlcnRpb25zKCspLCAxIGRlbGV0aW9uKC0pCj4+Cj4+IGRpZmYgLS1naXQg YS9kcml2ZXJzL2dwdS9kcm0vZHJtX2ZiX2hlbHBlci5jIGIvZHJpdmVycy9ncHUvZHJtL2RybV9m Yl9oZWxwZXIuYwo+PiBpbmRleCA4NTUxMDhlLi40NmVlNmY4IDEwMDY0NAo+PiAtLS0gYS9kcml2 ZXJzL2dwdS9kcm0vZHJtX2ZiX2hlbHBlci5jCj4+ICsrKyBiL2RyaXZlcnMvZ3B1L2RybS9kcm1f ZmJfaGVscGVyLmMKPj4gQEAgLTQwLDYgKzQwLDcgQEAKPj4gICAjaW5jbHVkZSA8ZHJtL2RybV9j cnRjX2hlbHBlci5oPgo+PiAgICNpbmNsdWRlIDxkcm0vZHJtX2F0b21pYy5oPgo+PiAgICNpbmNs dWRlIDxkcm0vZHJtX2F0b21pY19oZWxwZXIuaD4KPj4gKyNpbmNsdWRlIDxkcm0vZHJtX3JlY3Qu aD4KPj4KPj4gICBzdGF0aWMgYm9vbCBkcm1fZmJkZXZfZW11bGF0aW9uID0gdHJ1ZTsKPj4gICBt b2R1bGVfcGFyYW1fbmFtZWQoZmJkZXZfZW11bGF0aW9uLCBkcm1fZmJkZXZfZW11bGF0aW9uLCBi b29sLCAwNjAwKTsKPj4gQEAgLTQ4LDYgKzQ5LDEwIEBAIE1PRFVMRV9QQVJNX0RFU0MoZmJkZXZf ZW11bGF0aW9uLAo+Pgo+PiAgIHN0YXRpYyBMSVNUX0hFQUQoa2VybmVsX2ZiX2hlbHBlcl9saXN0 KTsKPj4KPj4gK3N0YXRpYyB2b2lkIGRybV9mYl9oZWxwZXJfZGlydHlfaW5pdChzdHJ1Y3QgZHJt X2ZiX2hlbHBlciAqaGVscGVyKTsKPj4gK3N0YXRpYyB2b2lkIGRybV9mYl9oZWxwZXJfZGlydHko c3RydWN0IGZiX2luZm8gKmluZm8sIHUzMiB4LCB1MzIgeSwKPj4gKwkJCQl1MzIgd2lkdGgsIHUz MiBoZWlnaHQpOwo+PiArCj4+ICAgLyoqCj4+ICAgICogRE9DOiBmYmRldiBoZWxwZXJzCj4+ICAg ICoKPj4gQEAgLTg0LDYgKzg5LDE2IEBAIHN0YXRpYyBMSVNUX0hFQUQoa2VybmVsX2ZiX2hlbHBl cl9saXN0KTsKPj4gICAgKiBhbmQgc2V0IHVwIGFuIGluaXRpYWwgY29uZmlndXJhdGlvbiB1c2lu ZyB0aGUgZGV0ZWN0ZWQgaGFyZHdhcmUsIGRyaXZlcnMKPj4gICAgKiBzaG91bGQgY2FsbCBkcm1f ZmJfaGVscGVyX3NpbmdsZV9hZGRfYWxsX2Nvbm5lY3RvcnMoKSBmb2xsb3dlZCBieQo+PiAgICAq IGRybV9mYl9oZWxwZXJfaW5pdGlhbF9jb25maWcoKS4KPj4gKyAqCj4+ICsgKiBJZiBDT05GSUdf RkJfREVGRVJSRURfSU8gaXMgZW5hYmxlZCBhbmQKPj4gKyAqIChzdHJ1Y3QgZHJtX2ZyYW1lYnVm ZmVyICopLT5mdW5jcy0+ZGlydHkgaXMgc2V0LCB0aGUKPj4gKyAqIGRybV9mYl9oZWxwZXJfe2Nm YixzeXN9X3t3cml0ZSxmaWxscmVjdCxjb3B5YXJlYSxpbWFnZWJsaXR9IGZ1bmN0aW9ucwo+PiAr ICogd2lsbCBhY2N1bXVsYXRlIGNoYW5nZXMgYW5kIHNjaGVkdWxlIChzdHJ1Y3QgZmJfaGVscGVy KS5kaXJ0eV93b3JrIHRvIHJ1bgo+PiArICogcmlnaHQgYXdheS4gVGhpcyB3b3JrZXIgdGhlbiBj YWxscyB0aGUgZGlydHkoKSBmdW5jdGlvbiBlbnN1cmluZyB0aGF0IGl0Cj4+ICsgKiB3aWxsIGFs d2F5cyBydW4gaW4gcHJvY2VzcyBjb250ZXh0IHNpbmNlIHRoZSBmYl8qKCkgZnVuY3Rpb24gY291 bGQgYmUKPj4gKyAqIHJ1bm5pbmcgaW4gYXRvbWljIGNvbnRleHQuIElmIGRybV9mYl9oZWxwZXJf ZGVmZXJyZWRfaW8oKSBpcyB1c2VkIGFzIHRoZQo+PiArICogZGVmZXJyZWRfaW8gY2FsbGJhY2sg aXQgd2lsbCBhbHNvIHNjaGVkdWxlIGRpcnR5X3dvcmsgd2l0aCB0aGUgZGFtYWdlCj4+ICsgKiBj b2xsZWN0ZWQgZnJvbSB0aGUgbW1hcCBwYWdlIHdyaXRlcy4KPiBPbmUgdGhpbmcgdG8gY29uc2lk ZXIgKGFuZCBwZXJzb25hbGx5IEkgZG9uJ3QgY2FyZSBlaXRoZXIgd2F5KSBpcyB3aGV0aGVyCj4g d2Ugc2hvdWxkbid0IGp1c3Qgc2VsZWN0IENPTkZJR19GQl9ERUZFUlJFRF9JTyBpZiB0aGUgZmJk ZXYgaGVscGVycyBhcmUKPiBlbmFibGVkLiBQdXNoaW5nIHRoYXQgb3V0IHRvIGRyaXZlcnMgaXMg aW1vIGEgYml0IGZyYWdpbGUuCj4KPiBCdXQgbGlrZSBJIHNhaWQgSSdtIG9rIHdpdGggZWl0aGVy IHdheS4KCk15IGNvbmNlcm4gd2FzIGFkZGluZyBjb2RlIGFuZCBkYXRhIHRoYXQgb25seSBhIGZl dyBkcml2ZXJzIHdvdWxkCmFjdHVhbGx5IHVzZS4gQnV0IG9mIGNvdXJzZSB0aGVyZSdzIHRoZSB0 cmFkZW9mZiB3aXRoIGNvbXBsZXhpdHkuCkkgdXNlIHRoaXMgdG8gZW5hYmxlIGl0OgogICAgICAg ICBzZWxlY3QgRkJfREVGRVJSRURfSU8gaWYgRFJNX0tNU19GQl9IRUxQRVIKCkkgZ3Vlc3MgdGhl IG1haW50YWluZXIgaGFzIHRvIG1ha2UgdGhpcyBjaG9pY2UgYmV0d2VlbiBzaXplIGFuZCAKY29t cGxleGl0eSA6LSkKSSBjYW4gZW5hYmxlIGl0IGJ5IGRlZmF1bHQgaWYgeW91IHdhbnQsIGRybSBp cyBib3RoIGh1Z2UgYW5kIGNvbXBsZXggc28gSQpkb24ndCBrbm93IHdoYXQncyBiZXN0LgoKQXMg YSBzaWRlbm90ZSwgSSBoYXZlIGFsc28gcHV0IGFsbCB0aGUgZmJkZXYgY29kZSBpbiBhIGZpbGUg b2YgaXQncyBvd24gdG8KbWFrZSBpdCBzaW1wbGUgd2l0aCByZWdhcmRzIHRvIHRoZSBEUk1fRkJE RVZfRU1VTEFUSU9OIHVzZXIgb3B0aW9uOgp0aW55ZHJtLSQoQ09ORklHX0RSTV9LTVNfRkJfSEVM UEVSKSAgICAgKz0gdGlueWRybS1mYmRldi5vCgo+PiAgICAqLwo+Pgo+PiAgIC8qKgo+PiBAQCAt NDAxLDExICs0MTYsMTQgQEAgYmFja29mZjoKPj4gICBzdGF0aWMgaW50IHJlc3RvcmVfZmJkZXZf bW9kZShzdHJ1Y3QgZHJtX2ZiX2hlbHBlciAqZmJfaGVscGVyKQo+PiAgIHsKPj4gICAJc3RydWN0 IGRybV9kZXZpY2UgKmRldiA9IGZiX2hlbHBlci0+ZGV2Owo+PiArCXN0cnVjdCBmYl9pbmZvICpp bmZvID0gZmJfaGVscGVyLT5mYmRldjsKPj4gICAJc3RydWN0IGRybV9wbGFuZSAqcGxhbmU7Cj4+ ICAgCWludCBpOwo+Pgo+PiAgIAlkcm1fd2Fybl9vbl9tb2Rlc2V0X25vdF9hbGxfbG9ja2VkKGRl dik7Cj4+Cj4+ICsJZHJtX2ZiX2hlbHBlcl9kaXJ0eShpbmZvLCAwLCAwLCBpbmZvLT52YXIueHJl cywgaW5mby0+dmFyLnlyZXMpOwo+IFdoeSBpcyB0aGlzIG5lZWRlZD8gSWYgeW91IGRvIGEgbW9k ZXNldCAob3IgcGFnZWZsaXAgb3Igd2hhdGV2ZXIpIGRyaXZlcnMKPiBhcmUgc3VwcG9zZWQgdG8g cmUtdXBsb2FkIHRoZSBlbnRpcmUgc2NyZWVuLiBXZSd2ZSB0YWxrZWQgYWJvdXQgYWRkaW5nIGEK PiBkaXJ0eSByZWN0YW5nbGUgdG8gYXRvbWljIHRvIGFsbG93IHVzZXJzcGFjZSB0byBvcHRpbWl6 ZSB0aGlzLCBidXQgdGhlcmUKPiBzaG91bGQgX25ldmVyXyBiZSBhIG5lZWQgdG8gZG8gYSBkaXJ0 eWZiIGNhbGwgYXJvdW5kIGEgbW9kZXNldC4gUHJvYmFibHkKPiBqdXN0IGEgZHJpdmVyIGJ1ZyBp biB5b3VyIHBhbmVsIGRybSBkcml2ZXJzPwoKT2ssIGluIHRpbnlkcm0gSSBub3cgc2V0IGEgZmxh ZyBpbiAmZHJtX3NpbXBsZV9kaXNwbGF5X3BpcGVfZnVuY3MKLT5wbGFuZV91cGRhdGUgdG8gaW5k aWNhdGUgdGhhdCB0aGUgbmV4dCBkaXJ0eSgpIHNob3VsZCBkbyB0aGUgd2hvbGUKZnJhbWVidWZm ZXIgd2hpY2ggc2VlbXMgdG8gd29yayBmaW5lLgpTaG91bGQgSSBhY3R1YWxseSBwZXJmb3JtIHRo ZSB1cGRhdGUgYXMgd2VsbD8KSWYgc28gSSB3b3VsZCBuZWVkIHRvIGFkZCBhIHdvcmtlciBpbiB0 aW55ZHJtIHRvIGRvIHRoYXQuCgoKTm9yYWxmLgoKPiBXaXRoIHRoZSBhYm92ZSBsaW5lIHJlbW92 ZWQ6Cj4KPiBSZXZpZXdlZC1ieTogRGFuaWVsIFZldHRlciA8ZGFuaWVsLnZldHRlckBmZndsbC5j aD4KPgo+PiArCj4+ICAgCWlmIChmYl9oZWxwZXItPmF0b21pYykKPj4gICAJCXJldHVybiByZXN0 b3JlX2ZiZGV2X21vZGVfYXRvbWljKGZiX2hlbHBlcik7Cj4+Cj4+IEBAIC02NTAsNiArNjY4LDcg QEAgdm9pZCBkcm1fZmJfaGVscGVyX3ByZXBhcmUoc3RydWN0IGRybV9kZXZpY2UgKmRldiwgc3Ry dWN0IGRybV9mYl9oZWxwZXIgKmhlbHBlciwKPj4gICAJCQkgICBjb25zdCBzdHJ1Y3QgZHJtX2Zi X2hlbHBlcl9mdW5jcyAqZnVuY3MpCj4+ICAgewo+PiAgIAlJTklUX0xJU1RfSEVBRCgmaGVscGVy LT5rZXJuZWxfZmJfbGlzdCk7Cj4+ICsJZHJtX2ZiX2hlbHBlcl9kaXJ0eV9pbml0KGhlbHBlcik7 Cj4+ICAgCWhlbHBlci0+ZnVuY3MgPSBmdW5jczsKPj4gICAJaGVscGVyLT5kZXYgPSBkZXY7Cj4+ ICAgfQo+PiBAQCAtODM0LDYgKzg1Myw5MyBAQCB2b2lkIGRybV9mYl9oZWxwZXJfdW5saW5rX2Zi aShzdHJ1Y3QgZHJtX2ZiX2hlbHBlciAqZmJfaGVscGVyKQo+PiAgIH0KPj4gICBFWFBPUlRfU1lN Qk9MKGRybV9mYl9oZWxwZXJfdW5saW5rX2ZiaSk7Cj4+Cj4+ICsjaWZkZWYgQ09ORklHX0ZCX0RF RkVSUkVEX0lPCj4+ICtzdGF0aWMgdm9pZCBkcm1fZmJfaGVscGVyX2RpcnR5X3dvcmsoc3RydWN0 IHdvcmtfc3RydWN0ICp3b3JrKQo+PiArewo+PiArCXN0cnVjdCBkcm1fZmJfaGVscGVyICpoZWxw ZXIgPSBjb250YWluZXJfb2Yod29yaywgc3RydWN0IGRybV9mYl9oZWxwZXIsCj4+ICsJCQkJCQkg ICAgZGlydHlfd29yayk7Cj4+ICsJc3RydWN0IGRybV9jbGlwX3JlY3QgY2xpcDsKPj4gKwl1bnNp Z25lZCBsb25nIGZsYWdzOwo+PiArCj4+ICsJc3Bpbl9sb2NrX2lycXNhdmUoJmhlbHBlci0+ZGly dHlfbG9jaywgZmxhZ3MpOwo+PiArCWNsaXAgPSBoZWxwZXItPmRpcnR5X2NsaXA7Cj4+ICsJZHJt X2NsaXBfcmVjdF9yZXNldCgmaGVscGVyLT5kaXJ0eV9jbGlwKTsKPj4gKwlzcGluX3VubG9ja19p cnFyZXN0b3JlKCZoZWxwZXItPmRpcnR5X2xvY2ssIGZsYWdzKTsKPj4gKwo+PiArCWhlbHBlci0+ ZmItPmZ1bmNzLT5kaXJ0eShoZWxwZXItPmZiLCBOVUxMLCAwLCAwLCAmY2xpcCwgMSk7Cj4+ICt9 Cj4+ICsKPj4gK3N0YXRpYyB2b2lkIGRybV9mYl9oZWxwZXJfZGlydHlfaW5pdChzdHJ1Y3QgZHJt X2ZiX2hlbHBlciAqaGVscGVyKQo+PiArewo+PiArCXNwaW5fbG9ja19pbml0KCZoZWxwZXItPmRp cnR5X2xvY2spOwo+PiArCUlOSVRfV09SSygmaGVscGVyLT5kaXJ0eV93b3JrLCBkcm1fZmJfaGVs cGVyX2RpcnR5X3dvcmspOwo+PiArfQo+PiArCj4+ICtzdGF0aWMgdm9pZCBkcm1fZmJfaGVscGVy X2RpcnR5KHN0cnVjdCBmYl9pbmZvICppbmZvLCB1MzIgeCwgdTMyIHksCj4+ICsJCQkJdTMyIHdp ZHRoLCB1MzIgaGVpZ2h0KQo+PiArewo+PiArCXN0cnVjdCBkcm1fZmJfaGVscGVyICpoZWxwZXIg PSBpbmZvLT5wYXI7Cj4+ICsJc3RydWN0IGRybV9jbGlwX3JlY3QgY2xpcDsKPj4gKwl1bnNpZ25l ZCBsb25nIGZsYWdzOwo+PiArCj4+ICsJaWYgKCFoZWxwZXItPmZiLT5mdW5jcy0+ZGlydHkpCj4+ ICsJCXJldHVybjsKPj4gKwo+PiArCWNsaXAueDEgPSB4Owo+PiArCWNsaXAueDIgPSB4ICsgd2lk dGg7Cj4+ICsJY2xpcC55MSA9IHk7Cj4+ICsJY2xpcC55MiA9IHkgKyBoZWlnaHQ7Cj4+ICsKPj4g KwlzcGluX2xvY2tfaXJxc2F2ZSgmaGVscGVyLT5kaXJ0eV9sb2NrLCBmbGFncyk7Cj4+ICsJZHJt X2NsaXBfcmVjdF9tZXJnZSgmaGVscGVyLT5kaXJ0eV9jbGlwLCAmY2xpcCwgMSwgMCwgMCwgMCk7 Cj4+ICsJc3Bpbl91bmxvY2tfaXJxcmVzdG9yZSgmaGVscGVyLT5kaXJ0eV9sb2NrLCBmbGFncyk7 Cj4+ICsKPj4gKwlzY2hlZHVsZV93b3JrKCZoZWxwZXItPmRpcnR5X3dvcmspOwo+PiArfQo+PiAr Cj4+ICsvKioKPj4gKyAqIGRybV9mYl9oZWxwZXJfZGVmZXJyZWRfaW8oKSAtIGZiZGV2IGRlZmVy cmVkX2lvIGNhbGxiYWNrIGZ1bmN0aW9uCj4+ICsgKiBAaW5mbzogZmJfaW5mbyBzdHJ1Y3QgcG9p bnRlcgo+PiArICogQHBhZ2VsaXN0OiBsaXN0IG9mIGRpcnR5IG1tYXAgZnJhbWVidWZmZXIgcGFn ZXMKPj4gKyAqCj4+ICsgKiBUaGlzIGZ1bmN0aW9uIGlzIHVzZWQgYXMgdGhlIChzdHJ1Y3QgZmJf ZGVmZXJyZWRfaW8gKiktPmRlZmVycmVkX2lvCj4+ICsgKiBjYWxsYmFjayBmdW5jdGlvbiBmb3Ig Zmx1c2hpbmcgdGhlIGZiZGV2IG1tYXAgd3JpdGVzLgo+PiArICovCj4+ICt2b2lkIGRybV9mYl9o ZWxwZXJfZGVmZXJyZWRfaW8oc3RydWN0IGZiX2luZm8gKmluZm8sCj4+ICsJCQkgICAgICAgc3Ry dWN0IGxpc3RfaGVhZCAqcGFnZWxpc3QpCj4+ICt7Cj4+ICsJdW5zaWduZWQgbG9uZyBzdGFydCwg ZW5kLCBtaW4sIG1heDsKPj4gKwlzdHJ1Y3QgcGFnZSAqcGFnZTsKPj4gKwl1MzIgeTEsIHkyOwo+ PiArCj4+ICsJbWluID0gVUxPTkdfTUFYOwo+PiArCW1heCA9IDA7Cj4+ICsJbGlzdF9mb3JfZWFj aF9lbnRyeShwYWdlLCBwYWdlbGlzdCwgbHJ1KSB7Cj4+ICsJCXN0YXJ0ID0gcGFnZS0+aW5kZXgg PDwgUEFHRV9TSElGVDsKPj4gKwkJZW5kID0gc3RhcnQgKyBQQUdFX1NJWkUgLSAxOwo+PiArCQlt aW4gPSBtaW4obWluLCBzdGFydCk7Cj4+ICsJCW1heCA9IG1heChtYXgsIGVuZCk7Cj4+ICsJfQo+ PiArCj4+ICsJaWYgKG1pbiA8IG1heCkgewo+PiArCQl5MSA9IG1pbiAvIGluZm8tPmZpeC5saW5l X2xlbmd0aDsKPj4gKwkJeTIgPSBtaW5fdCh1MzIsIG1heCAvIGluZm8tPmZpeC5saW5lX2xlbmd0 aCwgaW5mby0+dmFyLnlyZXMpOwo+PiArCQlkcm1fZmJfaGVscGVyX2RpcnR5KGluZm8sIDAsIHkx LCBpbmZvLT52YXIueHJlcywgeTIgLSB5MSk7Cj4+ICsJfQo+PiArfQo+PiArRVhQT1JUX1NZTUJP TChkcm1fZmJfaGVscGVyX2RlZmVycmVkX2lvKTsKPj4gKwo+PiArI2Vsc2UKPj4gK3N0YXRpYyB2 b2lkIGRybV9mYl9oZWxwZXJfZGlydHlfaW5pdChzdHJ1Y3QgZHJtX2ZiX2hlbHBlciAqaGVscGVy KQo+PiArewo+PiArfQo+PiArCj4+ICtzdGF0aWMgdm9pZCBkcm1fZmJfaGVscGVyX2RpcnR5KHN0 cnVjdCBmYl9pbmZvICppbmZvLCB1MzIgeCwgdTMyIHksCj4+ICsJCQkJdTMyIHdpZHRoLCB1MzIg aGVpZ2h0KQo+PiArewo+PiArfQo+PiArI2VuZGlmIC8qIENPTkZJR19GQl9ERUZFUlJFRF9JTyAq Lwo+PiArCj4+ICAgLyoqCj4+ICAgICogZHJtX2ZiX2hlbHBlcl9zeXNfcmVhZCAtIHdyYXBwZXIg YXJvdW5kIGZiX3N5c19yZWFkCj4+ICAgICogQGluZm86IGZiX2luZm8gc3RydWN0IHBvaW50ZXIK Pj4gQEAgLTg2Miw3ICs5NjgsMTQgQEAgRVhQT1JUX1NZTUJPTChkcm1fZmJfaGVscGVyX3N5c19y ZWFkKTsKPj4gICBzc2l6ZV90IGRybV9mYl9oZWxwZXJfc3lzX3dyaXRlKHN0cnVjdCBmYl9pbmZv ICppbmZvLCBjb25zdCBjaGFyIF9fdXNlciAqYnVmLAo+PiAgIAkJCQlzaXplX3QgY291bnQsIGxv ZmZfdCAqcHBvcykKPj4gICB7Cj4+IC0JcmV0dXJuIGZiX3N5c193cml0ZShpbmZvLCBidWYsIGNv dW50LCBwcG9zKTsKPj4gKwlzc2l6ZV90IHJldDsKPj4gKwo+PiArCXJldCA9IGZiX3N5c193cml0 ZShpbmZvLCBidWYsIGNvdW50LCBwcG9zKTsKPj4gKwlpZiAocmV0ID4gMCkKPj4gKwkJZHJtX2Zi X2hlbHBlcl9kaXJ0eShpbmZvLCAwLCAwLCBpbmZvLT52YXIueHJlcywKPj4gKwkJCQkgICAgaW5m by0+dmFyLnlyZXMpOwo+PiArCj4+ICsJcmV0dXJuIHJldDsKPj4gICB9Cj4+ICAgRVhQT1JUX1NZ TUJPTChkcm1fZmJfaGVscGVyX3N5c193cml0ZSk7Cj4+Cj4+IEBAIC04NzcsNiArOTkwLDggQEAg dm9pZCBkcm1fZmJfaGVscGVyX3N5c19maWxscmVjdChzdHJ1Y3QgZmJfaW5mbyAqaW5mbywKPj4g ICAJCQkJY29uc3Qgc3RydWN0IGZiX2ZpbGxyZWN0ICpyZWN0KQo+PiAgIHsKPj4gICAJc3lzX2Zp bGxyZWN0KGluZm8sIHJlY3QpOwo+PiArCWRybV9mYl9oZWxwZXJfZGlydHkoaW5mbywgcmVjdC0+ ZHgsIHJlY3QtPmR5LAo+PiArCQkJICAgIHJlY3QtPndpZHRoLCByZWN0LT5oZWlnaHQpOwo+PiAg IH0KPj4gICBFWFBPUlRfU1lNQk9MKGRybV9mYl9oZWxwZXJfc3lzX2ZpbGxyZWN0KTsKPj4KPj4g QEAgLTg5MSw2ICsxMDA2LDggQEAgdm9pZCBkcm1fZmJfaGVscGVyX3N5c19jb3B5YXJlYShzdHJ1 Y3QgZmJfaW5mbyAqaW5mbywKPj4gICAJCQkJY29uc3Qgc3RydWN0IGZiX2NvcHlhcmVhICphcmVh KQo+PiAgIHsKPj4gICAJc3lzX2NvcHlhcmVhKGluZm8sIGFyZWEpOwo+PiArCWRybV9mYl9oZWxw ZXJfZGlydHkoaW5mbywgYXJlYS0+ZHgsIGFyZWEtPmR5LAo+PiArCQkJICAgIGFyZWEtPndpZHRo LCBhcmVhLT5oZWlnaHQpOwo+PiAgIH0KPj4gICBFWFBPUlRfU1lNQk9MKGRybV9mYl9oZWxwZXJf c3lzX2NvcHlhcmVhKTsKPj4KPj4gQEAgLTkwNSw2ICsxMDIyLDggQEAgdm9pZCBkcm1fZmJfaGVs cGVyX3N5c19pbWFnZWJsaXQoc3RydWN0IGZiX2luZm8gKmluZm8sCj4+ICAgCQkJCSBjb25zdCBz dHJ1Y3QgZmJfaW1hZ2UgKmltYWdlKQo+PiAgIHsKPj4gICAJc3lzX2ltYWdlYmxpdChpbmZvLCBp bWFnZSk7Cj4+ICsJZHJtX2ZiX2hlbHBlcl9kaXJ0eShpbmZvLCBpbWFnZS0+ZHgsIGltYWdlLT5k eSwKPj4gKwkJCSAgICBpbWFnZS0+d2lkdGgsIGltYWdlLT5oZWlnaHQpOwo+PiAgIH0KPj4gICBF WFBPUlRfU1lNQk9MKGRybV9mYl9oZWxwZXJfc3lzX2ltYWdlYmxpdCk7Cj4+Cj4+IEBAIC05MTks NiArMTAzOCw4IEBAIHZvaWQgZHJtX2ZiX2hlbHBlcl9jZmJfZmlsbHJlY3Qoc3RydWN0IGZiX2lu Zm8gKmluZm8sCj4+ICAgCQkJCWNvbnN0IHN0cnVjdCBmYl9maWxscmVjdCAqcmVjdCkKPj4gICB7 Cj4+ICAgCWNmYl9maWxscmVjdChpbmZvLCByZWN0KTsKPj4gKwlkcm1fZmJfaGVscGVyX2RpcnR5 KGluZm8sIHJlY3QtPmR4LCByZWN0LT5keSwKPj4gKwkJCSAgICByZWN0LT53aWR0aCwgcmVjdC0+ aGVpZ2h0KTsKPj4gICB9Cj4+ICAgRVhQT1JUX1NZTUJPTChkcm1fZmJfaGVscGVyX2NmYl9maWxs cmVjdCk7Cj4+Cj4+IEBAIC05MzMsNiArMTA1NCw4IEBAIHZvaWQgZHJtX2ZiX2hlbHBlcl9jZmJf Y29weWFyZWEoc3RydWN0IGZiX2luZm8gKmluZm8sCj4+ICAgCQkJCWNvbnN0IHN0cnVjdCBmYl9j b3B5YXJlYSAqYXJlYSkKPj4gICB7Cj4+ICAgCWNmYl9jb3B5YXJlYShpbmZvLCBhcmVhKTsKPj4g Kwlkcm1fZmJfaGVscGVyX2RpcnR5KGluZm8sIGFyZWEtPmR4LCBhcmVhLT5keSwKPj4gKwkJCSAg ICBhcmVhLT53aWR0aCwgYXJlYS0+aGVpZ2h0KTsKPj4gICB9Cj4+ICAgRVhQT1JUX1NZTUJPTChk cm1fZmJfaGVscGVyX2NmYl9jb3B5YXJlYSk7Cj4+Cj4+IEBAIC05NDcsNiArMTA3MCw4IEBAIHZv aWQgZHJtX2ZiX2hlbHBlcl9jZmJfaW1hZ2VibGl0KHN0cnVjdCBmYl9pbmZvICppbmZvLAo+PiAg IAkJCQkgY29uc3Qgc3RydWN0IGZiX2ltYWdlICppbWFnZSkKPj4gICB7Cj4+ICAgCWNmYl9pbWFn ZWJsaXQoaW5mbywgaW1hZ2UpOwo+PiArCWRybV9mYl9oZWxwZXJfZGlydHkoaW5mbywgaW1hZ2Ut PmR4LCBpbWFnZS0+ZHksCj4+ICsJCQkgICAgaW1hZ2UtPndpZHRoLCBpbWFnZS0+aGVpZ2h0KTsK Pj4gICB9Cj4+ICAgRVhQT1JUX1NZTUJPTChkcm1fZmJfaGVscGVyX2NmYl9pbWFnZWJsaXQpOwo+ Pgo+PiBkaWZmIC0tZ2l0IGEvaW5jbHVkZS9kcm0vZHJtX2ZiX2hlbHBlci5oIGIvaW5jbHVkZS9k cm0vZHJtX2ZiX2hlbHBlci5oCj4+IGluZGV4IDA2MjcyM2IuLmRkZTgyNWMgMTAwNjQ0Cj4+IC0t LSBhL2luY2x1ZGUvZHJtL2RybV9mYl9oZWxwZXIuaAo+PiArKysgYi9pbmNsdWRlL2RybS9kcm1f ZmJfaGVscGVyLmgKPj4gQEAgLTE3Miw2ICsxNzIsMTAgQEAgc3RydWN0IGRybV9mYl9oZWxwZXJf Y29ubmVjdG9yIHsKPj4gICAgKiBAZnVuY3M6IGRyaXZlciBjYWxsYmFja3MgZm9yIGZiIGhlbHBl cgo+PiAgICAqIEBmYmRldjogZW11bGF0ZWQgZmJkZXYgZGV2aWNlIGluZm8gc3RydWN0Cj4+ICAg ICogQHBzZXVkb19wYWxldHRlOiBmYWtlIHBhbGV0dGUgb2YgMTYgY29sb3JzCj4+ICsgKiBAZGly dHlfY2xpcDogY2xpcCByZWN0YW5nbGUgdXNlZCB3aXRoIGRlZmVycmVkX2lvIHRvIGFjY3VtdWxh dGUgZGFtYWdlIHRvCj4+ICsgKiAgICAgICAgICAgICAgdGhlIHNjcmVlbiBidWZmZXIKPj4gKyAq IEBkaXJ0eV9sb2NrOiBzcGlubG9jayBwcm90ZWN0aW5nIEBkaXJ0eV9jbGlwCj4+ICsgKiBAZGly dHlfd29yazogd29ya2VyIHVzZWQgdG8gZmx1c2ggdGhlIGZyYW1lYnVmZmVyCj4+ICAgICoKPj4g ICAgKiBUaGlzIGlzIHRoZSBtYWluIHN0cnVjdHVyZSB1c2VkIGJ5IHRoZSBmYmRldiBoZWxwZXJz LiBEcml2ZXJzIHN1cHBvcnRpbmcKPj4gICAgKiBmYmRldiBlbXVsYXRpb24gc2hvdWxkIGVtYmVk ZGVkIHRoaXMgaW50byB0aGVpciBvdmVyYWxsIGRyaXZlciBzdHJ1Y3R1cmUuCj4+IEBAIC0xODks NiArMTkzLDExIEBAIHN0cnVjdCBkcm1fZmJfaGVscGVyIHsKPj4gICAJY29uc3Qgc3RydWN0IGRy bV9mYl9oZWxwZXJfZnVuY3MgKmZ1bmNzOwo+PiAgIAlzdHJ1Y3QgZmJfaW5mbyAqZmJkZXY7Cj4+ ICAgCXUzMiBwc2V1ZG9fcGFsZXR0ZVsxN107Cj4+ICsjaWZkZWYgQ09ORklHX0ZCX0RFRkVSUkVE X0lPCj4+ICsJc3RydWN0IGRybV9jbGlwX3JlY3QgZGlydHlfY2xpcDsKPj4gKwlzcGlubG9ja190 IGRpcnR5X2xvY2s7Cj4+ICsJc3RydWN0IHdvcmtfc3RydWN0IGRpcnR5X3dvcms7Cj4+ICsjZW5k aWYKPj4KPj4gICAJLyoqCj4+ICAgCSAqIEBrZXJuZWxfZmJfbGlzdDoKPj4gQEAgLTI0NSw2ICsy NTQsOSBAQCB2b2lkIGRybV9mYl9oZWxwZXJfZmlsbF9maXgoc3RydWN0IGZiX2luZm8gKmluZm8s IHVpbnQzMl90IHBpdGNoLAo+Pgo+PiAgIHZvaWQgZHJtX2ZiX2hlbHBlcl91bmxpbmtfZmJpKHN0 cnVjdCBkcm1fZmJfaGVscGVyICpmYl9oZWxwZXIpOwo+Pgo+PiArdm9pZCBkcm1fZmJfaGVscGVy X2RlZmVycmVkX2lvKHN0cnVjdCBmYl9pbmZvICppbmZvLAo+PiArCQkJICAgICAgIHN0cnVjdCBs aXN0X2hlYWQgKnBhZ2VsaXN0KTsKPj4gKwo+PiAgIHNzaXplX3QgZHJtX2ZiX2hlbHBlcl9zeXNf cmVhZChzdHJ1Y3QgZmJfaW5mbyAqaW5mbywgY2hhciBfX3VzZXIgKmJ1ZiwKPj4gICAJCQkgICAg ICAgc2l6ZV90IGNvdW50LCBsb2ZmX3QgKnBwb3MpOwo+PiAgIHNzaXplX3QgZHJtX2ZiX2hlbHBl cl9zeXNfd3JpdGUoc3RydWN0IGZiX2luZm8gKmluZm8sIGNvbnN0IGNoYXIgX191c2VyICpidWYs Cj4+IEBAIC0zNjgsNiArMzgwLDExIEBAIHN0YXRpYyBpbmxpbmUgdm9pZCBkcm1fZmJfaGVscGVy X3VubGlua19mYmkoc3RydWN0IGRybV9mYl9oZWxwZXIgKmZiX2hlbHBlcikKPj4gICB7Cj4+ICAg fQo+Pgo+PiArc3RhdGljIGlubGluZSB2b2lkIGRybV9mYl9oZWxwZXJfZGVmZXJyZWRfaW8oc3Ry dWN0IGZiX2luZm8gKmluZm8sCj4+ICsJCQkJCSAgICAgc3RydWN0IGxpc3RfaGVhZCAqcGFnZWxp c3QpCj4+ICt7Cj4+ICt9Cj4+ICsKPj4gICBzdGF0aWMgaW5saW5lIHNzaXplX3QgZHJtX2ZiX2hl bHBlcl9zeXNfcmVhZChzdHJ1Y3QgZmJfaW5mbyAqaW5mbywKPj4gICAJCQkJCSAgICAgY2hhciBf X3VzZXIgKmJ1Ziwgc2l6ZV90IGNvdW50LAo+PiAgIAkJCQkJICAgICBsb2ZmX3QgKnBwb3MpCj4+ IC0tCj4+IDIuMi4yCj4+CgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fXwpkcmktZGV2ZWwgbWFpbGluZyBsaXN0CmRyaS1kZXZlbEBsaXN0cy5mcmVlZGVza3Rv cC5vcmcKaHR0cHM6Ly9saXN0cy5mcmVlZGVza3RvcC5vcmcvbWFpbG1hbi9saXN0aW5mby9kcmkt ZGV2ZWwK From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752258AbcDZQZE (ORCPT ); Tue, 26 Apr 2016 12:25:04 -0400 Received: from smtp.domeneshop.no ([194.63.252.55]:51393 "EHLO smtp.domeneshop.no" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751881AbcDZQZA (ORCPT ); Tue, 26 Apr 2016 12:25:00 -0400 Subject: Re: [PATCH v2 4/8] drm/fb-helper: Add fb_deferred_io support To: dri-devel@lists.freedesktop.org, linux-fbdev@vger.kernel.org, laurent.pinchart@ideasonboard.com, tomi.valkeinen@ti.com, linux-kernel@vger.kernel.org References: <1461530942-22485-1-git-send-email-noralf@tronnes.org> <1461530942-22485-5-git-send-email-noralf@tronnes.org> <20160425090957.GQ2510@phenom.ffwll.local> From: =?UTF-8?Q?Noralf_Tr=c3=b8nnes?= Message-ID: <571F9656.1090506@tronnes.org> Date: Tue, 26 Apr 2016 18:24:54 +0200 User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:38.0) Gecko/20100101 Thunderbird/38.7.1 MIME-Version: 1.0 In-Reply-To: <20160425090957.GQ2510@phenom.ffwll.local> Content-Type: text/plain; charset=windows-1252; format=flowed Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Den 25.04.2016 11:09, skrev Daniel Vetter: > On Sun, Apr 24, 2016 at 10:48:58PM +0200, Noralf Trønnes wrote: >> This adds deferred io support if CONFIG_FB_DEFERRED_IO is enabled. >> The fbdev framebuffer changes are flushed using the callback >> (struct drm_framebuffer *)->funcs->dirty() by a dedicated worker >> ensuring that it always runs in process context. >> >> Signed-off-by: Noralf Trønnes >> --- >> >> Changes since v1: >> - Use a dedicated worker to run the framebuffer flushing like qxl does >> - Add parameter descriptions to drm_fb_helper_deferred_io >> >> drivers/gpu/drm/drm_fb_helper.c | 127 +++++++++++++++++++++++++++++++++++++++- >> include/drm/drm_fb_helper.h | 17 ++++++ >> 2 files changed, 143 insertions(+), 1 deletion(-) >> >> diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c >> index 855108e..46ee6f8 100644 >> --- a/drivers/gpu/drm/drm_fb_helper.c >> +++ b/drivers/gpu/drm/drm_fb_helper.c >> @@ -40,6 +40,7 @@ >> #include >> #include >> #include >> +#include >> >> static bool drm_fbdev_emulation = true; >> module_param_named(fbdev_emulation, drm_fbdev_emulation, bool, 0600); >> @@ -48,6 +49,10 @@ MODULE_PARM_DESC(fbdev_emulation, >> >> static LIST_HEAD(kernel_fb_helper_list); >> >> +static void drm_fb_helper_dirty_init(struct drm_fb_helper *helper); >> +static void drm_fb_helper_dirty(struct fb_info *info, u32 x, u32 y, >> + u32 width, u32 height); >> + >> /** >> * DOC: fbdev helpers >> * >> @@ -84,6 +89,16 @@ static LIST_HEAD(kernel_fb_helper_list); >> * and set up an initial configuration using the detected hardware, drivers >> * should call drm_fb_helper_single_add_all_connectors() followed by >> * drm_fb_helper_initial_config(). >> + * >> + * If CONFIG_FB_DEFERRED_IO is enabled and >> + * (struct drm_framebuffer *)->funcs->dirty is set, the >> + * drm_fb_helper_{cfb,sys}_{write,fillrect,copyarea,imageblit} functions >> + * will accumulate changes and schedule (struct fb_helper).dirty_work to run >> + * right away. This worker then calls the dirty() function ensuring that it >> + * will always run in process context since the fb_*() function could be >> + * running in atomic context. If drm_fb_helper_deferred_io() is used as the >> + * deferred_io callback it will also schedule dirty_work with the damage >> + * collected from the mmap page writes. > One thing to consider (and personally I don't care either way) is whether > we shouldn't just select CONFIG_FB_DEFERRED_IO if the fbdev helpers are > enabled. Pushing that out to drivers is imo a bit fragile. > > But like I said I'm ok with either way. My concern was adding code and data that only a few drivers would actually use. But of course there's the tradeoff with complexity. I use this to enable it: select FB_DEFERRED_IO if DRM_KMS_FB_HELPER I guess the maintainer has to make this choice between size and complexity :-) I can enable it by default if you want, drm is both huge and complex so I don't know what's best. As a sidenote, I have also put all the fbdev code in a file of it's own to make it simple with regards to the DRM_FBDEV_EMULATION user option: tinydrm-$(CONFIG_DRM_KMS_FB_HELPER) += tinydrm-fbdev.o >> */ >> >> /** >> @@ -401,11 +416,14 @@ backoff: >> static int restore_fbdev_mode(struct drm_fb_helper *fb_helper) >> { >> struct drm_device *dev = fb_helper->dev; >> + struct fb_info *info = fb_helper->fbdev; >> struct drm_plane *plane; >> int i; >> >> drm_warn_on_modeset_not_all_locked(dev); >> >> + drm_fb_helper_dirty(info, 0, 0, info->var.xres, info->var.yres); > Why is this needed? If you do a modeset (or pageflip or whatever) drivers > are supposed to re-upload the entire screen. We've talked about adding a > dirty rectangle to atomic to allow userspace to optimize this, but there > should _never_ be a need to do a dirtyfb call around a modeset. Probably > just a driver bug in your panel drm drivers? Ok, in tinydrm I now set a flag in &drm_simple_display_pipe_funcs ->plane_update to indicate that the next dirty() should do the whole framebuffer which seems to work fine. Should I actually perform the update as well? If so I would need to add a worker in tinydrm to do that. Noralf. > With the above line removed: > > Reviewed-by: Daniel Vetter > >> + >> if (fb_helper->atomic) >> return restore_fbdev_mode_atomic(fb_helper); >> >> @@ -650,6 +668,7 @@ void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper, >> const struct drm_fb_helper_funcs *funcs) >> { >> INIT_LIST_HEAD(&helper->kernel_fb_list); >> + drm_fb_helper_dirty_init(helper); >> helper->funcs = funcs; >> helper->dev = dev; >> } >> @@ -834,6 +853,93 @@ void drm_fb_helper_unlink_fbi(struct drm_fb_helper *fb_helper) >> } >> EXPORT_SYMBOL(drm_fb_helper_unlink_fbi); >> >> +#ifdef CONFIG_FB_DEFERRED_IO >> +static void drm_fb_helper_dirty_work(struct work_struct *work) >> +{ >> + struct drm_fb_helper *helper = container_of(work, struct drm_fb_helper, >> + dirty_work); >> + struct drm_clip_rect clip; >> + unsigned long flags; >> + >> + spin_lock_irqsave(&helper->dirty_lock, flags); >> + clip = helper->dirty_clip; >> + drm_clip_rect_reset(&helper->dirty_clip); >> + spin_unlock_irqrestore(&helper->dirty_lock, flags); >> + >> + helper->fb->funcs->dirty(helper->fb, NULL, 0, 0, &clip, 1); >> +} >> + >> +static void drm_fb_helper_dirty_init(struct drm_fb_helper *helper) >> +{ >> + spin_lock_init(&helper->dirty_lock); >> + INIT_WORK(&helper->dirty_work, drm_fb_helper_dirty_work); >> +} >> + >> +static void drm_fb_helper_dirty(struct fb_info *info, u32 x, u32 y, >> + u32 width, u32 height) >> +{ >> + struct drm_fb_helper *helper = info->par; >> + struct drm_clip_rect clip; >> + unsigned long flags; >> + >> + if (!helper->fb->funcs->dirty) >> + return; >> + >> + clip.x1 = x; >> + clip.x2 = x + width; >> + clip.y1 = y; >> + clip.y2 = y + height; >> + >> + spin_lock_irqsave(&helper->dirty_lock, flags); >> + drm_clip_rect_merge(&helper->dirty_clip, &clip, 1, 0, 0, 0); >> + spin_unlock_irqrestore(&helper->dirty_lock, flags); >> + >> + schedule_work(&helper->dirty_work); >> +} >> + >> +/** >> + * drm_fb_helper_deferred_io() - fbdev deferred_io callback function >> + * @info: fb_info struct pointer >> + * @pagelist: list of dirty mmap framebuffer pages >> + * >> + * This function is used as the (struct fb_deferred_io *)->deferred_io >> + * callback function for flushing the fbdev mmap writes. >> + */ >> +void drm_fb_helper_deferred_io(struct fb_info *info, >> + struct list_head *pagelist) >> +{ >> + unsigned long start, end, min, max; >> + struct page *page; >> + u32 y1, y2; >> + >> + min = ULONG_MAX; >> + max = 0; >> + list_for_each_entry(page, pagelist, lru) { >> + start = page->index << PAGE_SHIFT; >> + end = start + PAGE_SIZE - 1; >> + min = min(min, start); >> + max = max(max, end); >> + } >> + >> + if (min < max) { >> + y1 = min / info->fix.line_length; >> + y2 = min_t(u32, max / info->fix.line_length, info->var.yres); >> + drm_fb_helper_dirty(info, 0, y1, info->var.xres, y2 - y1); >> + } >> +} >> +EXPORT_SYMBOL(drm_fb_helper_deferred_io); >> + >> +#else >> +static void drm_fb_helper_dirty_init(struct drm_fb_helper *helper) >> +{ >> +} >> + >> +static void drm_fb_helper_dirty(struct fb_info *info, u32 x, u32 y, >> + u32 width, u32 height) >> +{ >> +} >> +#endif /* CONFIG_FB_DEFERRED_IO */ >> + >> /** >> * drm_fb_helper_sys_read - wrapper around fb_sys_read >> * @info: fb_info struct pointer >> @@ -862,7 +968,14 @@ EXPORT_SYMBOL(drm_fb_helper_sys_read); >> ssize_t drm_fb_helper_sys_write(struct fb_info *info, const char __user *buf, >> size_t count, loff_t *ppos) >> { >> - return fb_sys_write(info, buf, count, ppos); >> + ssize_t ret; >> + >> + ret = fb_sys_write(info, buf, count, ppos); >> + if (ret > 0) >> + drm_fb_helper_dirty(info, 0, 0, info->var.xres, >> + info->var.yres); >> + >> + return ret; >> } >> EXPORT_SYMBOL(drm_fb_helper_sys_write); >> >> @@ -877,6 +990,8 @@ void drm_fb_helper_sys_fillrect(struct fb_info *info, >> const struct fb_fillrect *rect) >> { >> sys_fillrect(info, rect); >> + drm_fb_helper_dirty(info, rect->dx, rect->dy, >> + rect->width, rect->height); >> } >> EXPORT_SYMBOL(drm_fb_helper_sys_fillrect); >> >> @@ -891,6 +1006,8 @@ void drm_fb_helper_sys_copyarea(struct fb_info *info, >> const struct fb_copyarea *area) >> { >> sys_copyarea(info, area); >> + drm_fb_helper_dirty(info, area->dx, area->dy, >> + area->width, area->height); >> } >> EXPORT_SYMBOL(drm_fb_helper_sys_copyarea); >> >> @@ -905,6 +1022,8 @@ void drm_fb_helper_sys_imageblit(struct fb_info *info, >> const struct fb_image *image) >> { >> sys_imageblit(info, image); >> + drm_fb_helper_dirty(info, image->dx, image->dy, >> + image->width, image->height); >> } >> EXPORT_SYMBOL(drm_fb_helper_sys_imageblit); >> >> @@ -919,6 +1038,8 @@ void drm_fb_helper_cfb_fillrect(struct fb_info *info, >> const struct fb_fillrect *rect) >> { >> cfb_fillrect(info, rect); >> + drm_fb_helper_dirty(info, rect->dx, rect->dy, >> + rect->width, rect->height); >> } >> EXPORT_SYMBOL(drm_fb_helper_cfb_fillrect); >> >> @@ -933,6 +1054,8 @@ void drm_fb_helper_cfb_copyarea(struct fb_info *info, >> const struct fb_copyarea *area) >> { >> cfb_copyarea(info, area); >> + drm_fb_helper_dirty(info, area->dx, area->dy, >> + area->width, area->height); >> } >> EXPORT_SYMBOL(drm_fb_helper_cfb_copyarea); >> >> @@ -947,6 +1070,8 @@ void drm_fb_helper_cfb_imageblit(struct fb_info *info, >> const struct fb_image *image) >> { >> cfb_imageblit(info, image); >> + drm_fb_helper_dirty(info, image->dx, image->dy, >> + image->width, image->height); >> } >> EXPORT_SYMBOL(drm_fb_helper_cfb_imageblit); >> >> diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h >> index 062723b..dde825c 100644 >> --- a/include/drm/drm_fb_helper.h >> +++ b/include/drm/drm_fb_helper.h >> @@ -172,6 +172,10 @@ struct drm_fb_helper_connector { >> * @funcs: driver callbacks for fb helper >> * @fbdev: emulated fbdev device info struct >> * @pseudo_palette: fake palette of 16 colors >> + * @dirty_clip: clip rectangle used with deferred_io to accumulate damage to >> + * the screen buffer >> + * @dirty_lock: spinlock protecting @dirty_clip >> + * @dirty_work: worker used to flush the framebuffer >> * >> * This is the main structure used by the fbdev helpers. Drivers supporting >> * fbdev emulation should embedded this into their overall driver structure. >> @@ -189,6 +193,11 @@ struct drm_fb_helper { >> const struct drm_fb_helper_funcs *funcs; >> struct fb_info *fbdev; >> u32 pseudo_palette[17]; >> +#ifdef CONFIG_FB_DEFERRED_IO >> + struct drm_clip_rect dirty_clip; >> + spinlock_t dirty_lock; >> + struct work_struct dirty_work; >> +#endif >> >> /** >> * @kernel_fb_list: >> @@ -245,6 +254,9 @@ void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch, >> >> void drm_fb_helper_unlink_fbi(struct drm_fb_helper *fb_helper); >> >> +void drm_fb_helper_deferred_io(struct fb_info *info, >> + struct list_head *pagelist); >> + >> ssize_t drm_fb_helper_sys_read(struct fb_info *info, char __user *buf, >> size_t count, loff_t *ppos); >> ssize_t drm_fb_helper_sys_write(struct fb_info *info, const char __user *buf, >> @@ -368,6 +380,11 @@ static inline void drm_fb_helper_unlink_fbi(struct drm_fb_helper *fb_helper) >> { >> } >> >> +static inline void drm_fb_helper_deferred_io(struct fb_info *info, >> + struct list_head *pagelist) >> +{ >> +} >> + >> static inline ssize_t drm_fb_helper_sys_read(struct fb_info *info, >> char __user *buf, size_t count, >> loff_t *ppos) >> -- >> 2.2.2 >>