From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751921AbcDUHll (ORCPT ); Thu, 21 Apr 2016 03:41:41 -0400 Received: from mail-wm0-f41.google.com ([74.125.82.41]:38387 "EHLO mail-wm0-f41.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751633AbcDUHlj (ORCPT ); Thu, 21 Apr 2016 03:41:39 -0400 Date: Thu, 21 Apr 2016 09:41:34 +0200 From: Daniel Vetter To: Noralf =?iso-8859-1?Q?Tr=F8nnes?= Cc: dri-devel@lists.freedesktop.org, linux-fbdev@vger.kernel.org, laurent.pinchart@ideasonboard.com, tomi.valkeinen@ti.com, linux-kernel@vger.kernel.org Subject: Re: [PATCH 7/8] drm/qxl: Use drm_fb_helper deferred_io support Message-ID: <20160421074134.GY2510@phenom.ffwll.local> Mail-Followup-To: Noralf =?iso-8859-1?Q?Tr=F8nnes?= , dri-devel@lists.freedesktop.org, linux-fbdev@vger.kernel.org, laurent.pinchart@ideasonboard.com, tomi.valkeinen@ti.com, linux-kernel@vger.kernel.org References: <1461165929-11344-1-git-send-email-noralf@tronnes.org> <1461165929-11344-8-git-send-email-noralf@tronnes.org> <20160420174710.GR2510@phenom.ffwll.local> <5717D2C6.7060806@tronnes.org> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <5717D2C6.7060806@tronnes.org> X-Operating-System: Linux phenom 4.4.0-1-amd64 User-Agent: Mutt/1.5.24 (2015-08-30) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Wed, Apr 20, 2016 at 09:04:38PM +0200, Noralf Trønnes wrote: > > Den 20.04.2016 19:47, skrev Daniel Vetter: > >On Wed, Apr 20, 2016 at 05:25:28PM +0200, Noralf Trønnes wrote: > >>Use the fbdev deferred io support in drm_fb_helper. > >>The (struct fb_ops *)->fb_{fillrect,copyarea,imageblit} functions will > >>now be deferred in the same way that mmap damage is, instead of being > >>flushed directly. > >>This patch has only been compile tested. > >> > >>Signed-off-by: Noralf Trønnes > >>--- > >> drivers/gpu/drm/qxl/qxl_display.c | 9 +- > >> drivers/gpu/drm/qxl/qxl_drv.h | 7 +- > >> drivers/gpu/drm/qxl/qxl_fb.c | 220 ++++++++++---------------------------- > >> drivers/gpu/drm/qxl/qxl_kms.c | 4 - > >> 4 files changed, 62 insertions(+), 178 deletions(-) > >> > >>diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c > >>index 030409a..9a03524 100644 > >>--- a/drivers/gpu/drm/qxl/qxl_display.c > >>+++ b/drivers/gpu/drm/qxl/qxl_display.c > >>@@ -465,7 +465,7 @@ static const struct drm_crtc_funcs qxl_crtc_funcs = { > >> .page_flip = qxl_crtc_page_flip, > >> }; > >>-static void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb) > >>+void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb) > >> { > >> struct qxl_framebuffer *qxl_fb = to_qxl_framebuffer(fb); > >>@@ -527,12 +527,13 @@ int > >> qxl_framebuffer_init(struct drm_device *dev, > >> struct qxl_framebuffer *qfb, > >> const struct drm_mode_fb_cmd2 *mode_cmd, > >>- struct drm_gem_object *obj) > >>+ struct drm_gem_object *obj, > >>+ const struct drm_framebuffer_funcs *funcs) > >There should be no need at all to have a separate fb funcs table for the > >fbdev fb. Both /should/ be able to use the exact same (already existing) > >->dirty() callback. We need this only in CMA because CMA is a midlayer > >used by multiple drivers. > > I don't see how I can avoid it. > > fbdev framebuffer flushing: > > static void qxl_fb_dirty_flush(struct fb_info *info) > { > qxl_fb_image_init(&qxl_fb_image, qdev, info, NULL); > qxl_draw_opaque_fb(&qxl_fb_image, stride); > } > > drm framebuffer flushing: > > static int qxl_framebuffer_surface_dirty(...) > { > qxl_draw_dirty_fb(...); > } > > qxl_draw_opaque_fb() and qxl_draw_dirty_fb() differ so much that it's way > over my head to see if they can be combined. > Here's an online diff of the two functions: > https://www.diffchecker.com/jqbbalux Imo nuke the fbdev one entirely. If it breaks then it's either a bug in your generic fbdefio code, or the qxl ->dirty implementation has a bug. It should work ;-) Ok, slightly more seriously the difference seems to be that the fbdev one support paletted mode too. But since qxl has 0 pixel format checking anywhere I have no idea whether that's dead code (i.e. broken) or actually working. I guess keeping the split is ok, if we add a big FIXME comment to it that this is very fishy. -Daniel > > > > > >With that change you should be able to condense this patch down to pretty > >much just removing lines. Which is Good (tm). > > > >Cheers, Daniel > > > >> { > >> int ret; > >> qfb->obj = obj; > >>- ret = drm_framebuffer_init(dev, &qfb->base, &qxl_fb_funcs); > >>+ ret = drm_framebuffer_init(dev, &qfb->base, funcs); > >> if (ret) { > >> qfb->obj = NULL; > >> return ret; > >>@@ -999,7 +1000,7 @@ qxl_user_framebuffer_create(struct drm_device *dev, > >> if (qxl_fb == NULL) > >> return NULL; > >>- ret = qxl_framebuffer_init(dev, qxl_fb, mode_cmd, obj); > >>+ ret = qxl_framebuffer_init(dev, qxl_fb, mode_cmd, obj, &qxl_fb_funcs); > >> if (ret) { > >> kfree(qxl_fb); > >> drm_gem_object_unreference_unlocked(obj); > >>diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h > >>index 3f3897e..3ad6604 100644 > >>--- a/drivers/gpu/drm/qxl/qxl_drv.h > >>+++ b/drivers/gpu/drm/qxl/qxl_drv.h > >>@@ -324,8 +324,6 @@ struct qxl_device { > >> struct workqueue_struct *gc_queue; > >> struct work_struct gc_work; > >>- struct work_struct fb_work; > >>- > >> struct drm_property *hotplug_mode_update_property; > >> int monitors_config_width; > >> int monitors_config_height; > >>@@ -389,11 +387,13 @@ int qxl_get_handle_for_primary_fb(struct qxl_device *qdev, > >> void qxl_fbdev_set_suspend(struct qxl_device *qdev, int state); > >> /* qxl_display.c */ > >>+void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb); > >> int > >> qxl_framebuffer_init(struct drm_device *dev, > >> struct qxl_framebuffer *rfb, > >> const struct drm_mode_fb_cmd2 *mode_cmd, > >>- struct drm_gem_object *obj); > >>+ struct drm_gem_object *obj, > >>+ const struct drm_framebuffer_funcs *funcs); > >> void qxl_display_read_client_monitors_config(struct qxl_device *qdev); > >> void qxl_send_monitors_config(struct qxl_device *qdev); > >> int qxl_create_monitors_object(struct qxl_device *qdev); > >>@@ -553,7 +553,6 @@ int qxl_irq_init(struct qxl_device *qdev); > >> irqreturn_t qxl_irq_handler(int irq, void *arg); > >> /* qxl_fb.c */ > >>-int qxl_fb_init(struct qxl_device *qdev); > >> bool qxl_fbdev_qobj_is_fb(struct qxl_device *qdev, struct qxl_bo *qobj); > >> int qxl_debugfs_add_files(struct qxl_device *qdev, > >>diff --git a/drivers/gpu/drm/qxl/qxl_fb.c b/drivers/gpu/drm/qxl/qxl_fb.c > >>index 06f032d..090dcee 100644 > >>--- a/drivers/gpu/drm/qxl/qxl_fb.c > >>+++ b/drivers/gpu/drm/qxl/qxl_fb.c > >>@@ -30,6 +30,7 @@ > >> #include "drm/drm.h" > >> #include "drm/drm_crtc.h" > >> #include "drm/drm_crtc_helper.h" > >>+#include "drm/drm_rect.h" > >> #include "qxl_drv.h" > >> #include "qxl_object.h" > >>@@ -46,15 +47,6 @@ struct qxl_fbdev { > >> struct list_head delayed_ops; > >> void *shadow; > >> int size; > >>- > >>- /* dirty memory logging */ > >>- struct { > >>- spinlock_t lock; > >>- unsigned x1; > >>- unsigned y1; > >>- unsigned x2; > >>- unsigned y2; > >>- } dirty; > >> }; > >> static void qxl_fb_image_init(struct qxl_fb_image *qxl_fb_image, > >>@@ -82,169 +74,18 @@ static void qxl_fb_image_init(struct qxl_fb_image *qxl_fb_image, > >> } > >> } > >>-static void qxl_fb_dirty_flush(struct fb_info *info) > >>-{ > >>- struct qxl_fbdev *qfbdev = info->par; > >>- struct qxl_device *qdev = qfbdev->qdev; > >>- struct qxl_fb_image qxl_fb_image; > >>- struct fb_image *image = &qxl_fb_image.fb_image; > >>- unsigned long flags; > >>- u32 x1, x2, y1, y2; > >>- > >>- /* TODO: hard coding 32 bpp */ > >>- int stride = qfbdev->qfb.base.pitches[0]; > >>- > >>- spin_lock_irqsave(&qfbdev->dirty.lock, flags); > >>- > >>- x1 = qfbdev->dirty.x1; > >>- x2 = qfbdev->dirty.x2; > >>- y1 = qfbdev->dirty.y1; > >>- y2 = qfbdev->dirty.y2; > >>- qfbdev->dirty.x1 = 0; > >>- qfbdev->dirty.x2 = 0; > >>- qfbdev->dirty.y1 = 0; > >>- qfbdev->dirty.y2 = 0; > >>- > >>- spin_unlock_irqrestore(&qfbdev->dirty.lock, flags); > >>- > >>- /* > >>- * we are using a shadow draw buffer, at qdev->surface0_shadow > >>- */ > >>- qxl_io_log(qdev, "dirty x[%d, %d], y[%d, %d]", x1, x2, y1, y2); > >>- image->dx = x1; > >>- image->dy = y1; > >>- image->width = x2 - x1 + 1; > >>- image->height = y2 - y1 + 1; > >>- image->fg_color = 0xffffffff; /* unused, just to avoid uninitialized > >>- warnings */ > >>- image->bg_color = 0; > >>- image->depth = 32; /* TODO: take from somewhere? */ > >>- image->cmap.start = 0; > >>- image->cmap.len = 0; > >>- image->cmap.red = NULL; > >>- image->cmap.green = NULL; > >>- image->cmap.blue = NULL; > >>- image->cmap.transp = NULL; > >>- image->data = qfbdev->shadow + (x1 * 4) + (stride * y1); > >>- > >>- qxl_fb_image_init(&qxl_fb_image, qdev, info, NULL); > >>- qxl_draw_opaque_fb(&qxl_fb_image, stride); > >>-} > >>- > >>-static void qxl_dirty_update(struct qxl_fbdev *qfbdev, > >>- int x, int y, int width, int height) > >>-{ > >>- struct qxl_device *qdev = qfbdev->qdev; > >>- unsigned long flags; > >>- int x2, y2; > >>- > >>- x2 = x + width - 1; > >>- y2 = y + height - 1; > >>- > >>- spin_lock_irqsave(&qfbdev->dirty.lock, flags); > >>- > >>- if ((qfbdev->dirty.y2 - qfbdev->dirty.y1) && > >>- (qfbdev->dirty.x2 - qfbdev->dirty.x1)) { > >>- if (qfbdev->dirty.y1 < y) > >>- y = qfbdev->dirty.y1; > >>- if (qfbdev->dirty.y2 > y2) > >>- y2 = qfbdev->dirty.y2; > >>- if (qfbdev->dirty.x1 < x) > >>- x = qfbdev->dirty.x1; > >>- if (qfbdev->dirty.x2 > x2) > >>- x2 = qfbdev->dirty.x2; > >>- } > >>- > >>- qfbdev->dirty.x1 = x; > >>- qfbdev->dirty.x2 = x2; > >>- qfbdev->dirty.y1 = y; > >>- qfbdev->dirty.y2 = y2; > >>- > >>- spin_unlock_irqrestore(&qfbdev->dirty.lock, flags); > >>- > >>- schedule_work(&qdev->fb_work); > >>-} > >>- > >>-static void qxl_deferred_io(struct fb_info *info, > >>- struct list_head *pagelist) > >>-{ > >>- struct qxl_fbdev *qfbdev = info->par; > >>- unsigned long start, end, min, max; > >>- struct page *page; > >>- int 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 = (max / info->fix.line_length) + 1; > >>- qxl_dirty_update(qfbdev, 0, y1, info->var.xres, y2 - y1); > >>- } > >>-}; > >>- > >> static struct fb_deferred_io qxl_defio = { > >> .delay = QXL_DIRTY_DELAY, > >>- .deferred_io = qxl_deferred_io, > >>+ .deferred_io = drm_fb_helper_deferred_io, > >> }; > >>-static void qxl_fb_fillrect(struct fb_info *info, > >>- const struct fb_fillrect *rect) > >>-{ > >>- struct qxl_fbdev *qfbdev = info->par; > >>- > >>- sys_fillrect(info, rect); > >>- qxl_dirty_update(qfbdev, rect->dx, rect->dy, rect->width, > >>- rect->height); > >>-} > >>- > >>-static void qxl_fb_copyarea(struct fb_info *info, > >>- const struct fb_copyarea *area) > >>-{ > >>- struct qxl_fbdev *qfbdev = info->par; > >>- > >>- sys_copyarea(info, area); > >>- qxl_dirty_update(qfbdev, area->dx, area->dy, area->width, > >>- area->height); > >>-} > >>- > >>-static void qxl_fb_imageblit(struct fb_info *info, > >>- const struct fb_image *image) > >>-{ > >>- struct qxl_fbdev *qfbdev = info->par; > >>- > >>- sys_imageblit(info, image); > >>- qxl_dirty_update(qfbdev, image->dx, image->dy, image->width, > >>- image->height); > >>-} > >>- > >>-static void qxl_fb_work(struct work_struct *work) > >>-{ > >>- struct qxl_device *qdev = container_of(work, struct qxl_device, fb_work); > >>- struct qxl_fbdev *qfbdev = qdev->mode_info.qfbdev; > >>- > >>- qxl_fb_dirty_flush(qfbdev->helper.fbdev); > >>-} > >>- > >>-int qxl_fb_init(struct qxl_device *qdev) > >>-{ > >>- INIT_WORK(&qdev->fb_work, qxl_fb_work); > >>- return 0; > >>-} > >>- > >> static struct fb_ops qxlfb_ops = { > >> .owner = THIS_MODULE, > >> .fb_check_var = drm_fb_helper_check_var, > >> .fb_set_par = drm_fb_helper_set_par, /* TODO: copy vmwgfx */ > >>- .fb_fillrect = qxl_fb_fillrect, > >>- .fb_copyarea = qxl_fb_copyarea, > >>- .fb_imageblit = qxl_fb_imageblit, > >>+ .fb_fillrect = drm_fb_helper_sys_fillrect, > >>+ .fb_copyarea = drm_fb_helper_sys_copyarea, > >>+ .fb_imageblit = drm_fb_helper_sys_imageblit, > >> .fb_pan_display = drm_fb_helper_pan_display, > >> .fb_blank = drm_fb_helper_blank, > >> .fb_setcmap = drm_fb_helper_setcmap, > >>@@ -338,6 +179,53 @@ out_unref: > >> return ret; > >> } > >>+static int qxlfb_framebuffer_dirty(struct drm_framebuffer *fb, > >>+ struct drm_file *file_priv, > >>+ unsigned flags, unsigned color, > >>+ struct drm_clip_rect *clips, > >>+ unsigned num_clips) > >>+{ > >>+ struct qxl_device *qdev = fb->dev->dev_private; > >>+ struct fb_info *info = qdev->fbdev_info; > >>+ struct qxl_fbdev *qfbdev = info->par; > >>+ struct qxl_fb_image qxl_fb_image; > >>+ struct fb_image *image = &qxl_fb_image.fb_image; > >>+ > >>+ /* TODO: hard coding 32 bpp */ > >>+ int stride = qfbdev->qfb.base.pitches[0]; > >>+ > >>+ /* > >>+ * we are using a shadow draw buffer, at qdev->surface0_shadow > >>+ */ > >>+ qxl_io_log(qdev, "dirty x[%d, %d], y[%d, %d]", clips->x1, clips->x2, > >>+ clips->y1, clips->y2); > >>+ image->dx = clips->x1; > >>+ image->dy = clips->y1; > >>+ image->width = drm_clip_rect_width(clips); > >>+ image->height = drm_clip_rect_height(clips); > >>+ image->fg_color = 0xffffffff; /* unused, just to avoid uninitialized > >>+ warnings */ > >>+ image->bg_color = 0; > >>+ image->depth = 32; /* TODO: take from somewhere? */ > >>+ image->cmap.start = 0; > >>+ image->cmap.len = 0; > >>+ image->cmap.red = NULL; > >>+ image->cmap.green = NULL; > >>+ image->cmap.blue = NULL; > >>+ image->cmap.transp = NULL; > >>+ image->data = qfbdev->shadow + (clips->x1 * 4) + (stride * clips->y1); > >>+ > >>+ qxl_fb_image_init(&qxl_fb_image, qdev, info, NULL); > >>+ qxl_draw_opaque_fb(&qxl_fb_image, stride); > >>+ > >>+ return 0; > >>+} > >>+ > >>+static const struct drm_framebuffer_funcs qxlfb_fb_funcs = { > >>+ .destroy = qxl_user_framebuffer_destroy, > >>+ .dirty = qxlfb_framebuffer_dirty, > >>+}; > >>+ > >> static int qxlfb_create(struct qxl_fbdev *qfbdev, > >> struct drm_fb_helper_surface_size *sizes) > >> { > >>@@ -383,7 +271,8 @@ static int qxlfb_create(struct qxl_fbdev *qfbdev, > >> info->par = qfbdev; > >>- qxl_framebuffer_init(qdev->ddev, &qfbdev->qfb, &mode_cmd, gobj); > >>+ qxl_framebuffer_init(qdev->ddev, &qfbdev->qfb, &mode_cmd, gobj, > >>+ &qxlfb_fb_funcs); > >> fb = &qfbdev->qfb.base; > >>@@ -504,7 +393,6 @@ int qxl_fbdev_init(struct qxl_device *qdev) > >> qfbdev->qdev = qdev; > >> qdev->mode_info.qfbdev = qfbdev; > >> spin_lock_init(&qfbdev->delayed_ops_lock); > >>- spin_lock_init(&qfbdev->dirty.lock); > >> INIT_LIST_HEAD(&qfbdev->delayed_ops); > >> drm_fb_helper_prepare(qdev->ddev, &qfbdev->helper, > >>diff --git a/drivers/gpu/drm/qxl/qxl_kms.c b/drivers/gpu/drm/qxl/qxl_kms.c > >>index b2977a1..2319800 100644 > >>--- a/drivers/gpu/drm/qxl/qxl_kms.c > >>+++ b/drivers/gpu/drm/qxl/qxl_kms.c > >>@@ -261,10 +261,6 @@ static int qxl_device_init(struct qxl_device *qdev, > >> qdev->gc_queue = create_singlethread_workqueue("qxl_gc"); > >> INIT_WORK(&qdev->gc_work, qxl_gc_work); > >>- r = qxl_fb_init(qdev); > >>- if (r) > >>- return r; > >>- > >> return 0; > >> } > >>-- > >>2.2.2 > >> > > _______________________________________________ > dri-devel mailing list > dri-devel@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/dri-devel -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch From mboxrd@z Thu Jan 1 00:00:00 1970 From: Daniel Vetter Date: Thu, 21 Apr 2016 07:41:34 +0000 Subject: Re: [PATCH 7/8] drm/qxl: Use drm_fb_helper deferred_io support Message-Id: <20160421074134.GY2510@phenom.ffwll.local> List-Id: References: <1461165929-11344-1-git-send-email-noralf@tronnes.org> <1461165929-11344-8-git-send-email-noralf@tronnes.org> <20160420174710.GR2510@phenom.ffwll.local> <5717D2C6.7060806@tronnes.org> In-Reply-To: <5717D2C6.7060806@tronnes.org> MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable To: Noralf =?iso-8859-1?Q?Tr=F8nnes?= Cc: linux-fbdev@vger.kernel.org, tomi.valkeinen@ti.com, laurent.pinchart@ideasonboard.com, dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org On Wed, Apr 20, 2016 at 09:04:38PM +0200, Noralf Tr=F8nnes wrote: >=20 > Den 20.04.2016 19:47, skrev Daniel Vetter: > >On Wed, Apr 20, 2016 at 05:25:28PM +0200, Noralf Tr=F8nnes wrote: > >>Use the fbdev deferred io support in drm_fb_helper. > >>The (struct fb_ops *)->fb_{fillrect,copyarea,imageblit} functions will > >>now be deferred in the same way that mmap damage is, instead of being > >>flushed directly. > >>This patch has only been compile tested. > >> > >>Signed-off-by: Noralf Tr=F8nnes > >>--- > >> drivers/gpu/drm/qxl/qxl_display.c | 9 +- > >> drivers/gpu/drm/qxl/qxl_drv.h | 7 +- > >> drivers/gpu/drm/qxl/qxl_fb.c | 220 ++++++++++-------------------= --------- > >> drivers/gpu/drm/qxl/qxl_kms.c | 4 - > >> 4 files changed, 62 insertions(+), 178 deletions(-) > >> > >>diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qx= l_display.c > >>index 030409a..9a03524 100644 > >>--- a/drivers/gpu/drm/qxl/qxl_display.c > >>+++ b/drivers/gpu/drm/qxl/qxl_display.c > >>@@ -465,7 +465,7 @@ static const struct drm_crtc_funcs qxl_crtc_funcs = =3D { > >> .page_flip =3D qxl_crtc_page_flip, > >> }; > >>-static void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb) > >>+void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb) > >> { > >> struct qxl_framebuffer *qxl_fb =3D to_qxl_framebuffer(fb); > >>@@ -527,12 +527,13 @@ int > >> qxl_framebuffer_init(struct drm_device *dev, > >> struct qxl_framebuffer *qfb, > >> const struct drm_mode_fb_cmd2 *mode_cmd, > >>- struct drm_gem_object *obj) > >>+ struct drm_gem_object *obj, > >>+ const struct drm_framebuffer_funcs *funcs) > >There should be no need at all to have a separate fb funcs table for the > >fbdev fb. Both /should/ be able to use the exact same (already existing) > >->dirty() callback. We need this only in CMA because CMA is a midlayer > >used by multiple drivers. >=20 > I don't see how I can avoid it. >=20 > fbdev framebuffer flushing: >=20 > static void qxl_fb_dirty_flush(struct fb_info *info) > { > qxl_fb_image_init(&qxl_fb_image, qdev, info, NULL); > qxl_draw_opaque_fb(&qxl_fb_image, stride); > } >=20 > drm framebuffer flushing: >=20 > static int qxl_framebuffer_surface_dirty(...) > { > qxl_draw_dirty_fb(...); > } >=20 > qxl_draw_opaque_fb() and qxl_draw_dirty_fb() differ so much that it's way > over my head to see if they can be combined. > Here's an online diff of the two functions: > https://www.diffchecker.com/jqbbalux Imo nuke the fbdev one entirely. If it breaks then it's either a bug in your generic fbdefio code, or the qxl ->dirty implementation has a bug. It should work ;-) Ok, slightly more seriously the difference seems to be that the fbdev one support paletted mode too. But since qxl has 0 pixel format checking anywhere I have no idea whether that's dead code (i.e. broken) or actually working. I guess keeping the split is ok, if we add a big FIXME comment to it that this is very fishy. -Daniel >=20 >=20 > > > >With that change you should be able to condense this patch down to pretty > >much just removing lines. Which is Good (tm). > > > >Cheers, Daniel > > > >> { > >> int ret; > >> qfb->obj =3D obj; > >>- ret =3D drm_framebuffer_init(dev, &qfb->base, &qxl_fb_funcs); > >>+ ret =3D drm_framebuffer_init(dev, &qfb->base, funcs); > >> if (ret) { > >> qfb->obj =3D NULL; > >> return ret; > >>@@ -999,7 +1000,7 @@ qxl_user_framebuffer_create(struct drm_device *dev, > >> if (qxl_fb =3D NULL) > >> return NULL; > >>- ret =3D qxl_framebuffer_init(dev, qxl_fb, mode_cmd, obj); > >>+ ret =3D qxl_framebuffer_init(dev, qxl_fb, mode_cmd, obj, &qxl_fb_func= s); > >> if (ret) { > >> kfree(qxl_fb); > >> drm_gem_object_unreference_unlocked(obj); > >>diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_dr= v.h > >>index 3f3897e..3ad6604 100644 > >>--- a/drivers/gpu/drm/qxl/qxl_drv.h > >>+++ b/drivers/gpu/drm/qxl/qxl_drv.h > >>@@ -324,8 +324,6 @@ struct qxl_device { > >> struct workqueue_struct *gc_queue; > >> struct work_struct gc_work; > >>- struct work_struct fb_work; > >>- > >> struct drm_property *hotplug_mode_update_property; > >> int monitors_config_width; > >> int monitors_config_height; > >>@@ -389,11 +387,13 @@ int qxl_get_handle_for_primary_fb(struct qxl_devi= ce *qdev, > >> void qxl_fbdev_set_suspend(struct qxl_device *qdev, int state); > >> /* qxl_display.c */ > >>+void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb); > >> int > >> qxl_framebuffer_init(struct drm_device *dev, > >> struct qxl_framebuffer *rfb, > >> const struct drm_mode_fb_cmd2 *mode_cmd, > >>- struct drm_gem_object *obj); > >>+ struct drm_gem_object *obj, > >>+ const struct drm_framebuffer_funcs *funcs); > >> void qxl_display_read_client_monitors_config(struct qxl_device *qdev); > >> void qxl_send_monitors_config(struct qxl_device *qdev); > >> int qxl_create_monitors_object(struct qxl_device *qdev); > >>@@ -553,7 +553,6 @@ int qxl_irq_init(struct qxl_device *qdev); > >> irqreturn_t qxl_irq_handler(int irq, void *arg); > >> /* qxl_fb.c */ > >>-int qxl_fb_init(struct qxl_device *qdev); > >> bool qxl_fbdev_qobj_is_fb(struct qxl_device *qdev, struct qxl_bo *qob= j); > >> int qxl_debugfs_add_files(struct qxl_device *qdev, > >>diff --git a/drivers/gpu/drm/qxl/qxl_fb.c b/drivers/gpu/drm/qxl/qxl_fb.c > >>index 06f032d..090dcee 100644 > >>--- a/drivers/gpu/drm/qxl/qxl_fb.c > >>+++ b/drivers/gpu/drm/qxl/qxl_fb.c > >>@@ -30,6 +30,7 @@ > >> #include "drm/drm.h" > >> #include "drm/drm_crtc.h" > >> #include "drm/drm_crtc_helper.h" > >>+#include "drm/drm_rect.h" > >> #include "qxl_drv.h" > >> #include "qxl_object.h" > >>@@ -46,15 +47,6 @@ struct qxl_fbdev { > >> struct list_head delayed_ops; > >> void *shadow; > >> int size; > >>- > >>- /* dirty memory logging */ > >>- struct { > >>- spinlock_t lock; > >>- unsigned x1; > >>- unsigned y1; > >>- unsigned x2; > >>- unsigned y2; > >>- } dirty; > >> }; > >> static void qxl_fb_image_init(struct qxl_fb_image *qxl_fb_image, > >>@@ -82,169 +74,18 @@ static void qxl_fb_image_init(struct qxl_fb_image = *qxl_fb_image, > >> } > >> } > >>-static void qxl_fb_dirty_flush(struct fb_info *info) > >>-{ > >>- struct qxl_fbdev *qfbdev =3D info->par; > >>- struct qxl_device *qdev =3D qfbdev->qdev; > >>- struct qxl_fb_image qxl_fb_image; > >>- struct fb_image *image =3D &qxl_fb_image.fb_image; > >>- unsigned long flags; > >>- u32 x1, x2, y1, y2; > >>- > >>- /* TODO: hard coding 32 bpp */ > >>- int stride =3D qfbdev->qfb.base.pitches[0]; > >>- > >>- spin_lock_irqsave(&qfbdev->dirty.lock, flags); > >>- > >>- x1 =3D qfbdev->dirty.x1; > >>- x2 =3D qfbdev->dirty.x2; > >>- y1 =3D qfbdev->dirty.y1; > >>- y2 =3D qfbdev->dirty.y2; > >>- qfbdev->dirty.x1 =3D 0; > >>- qfbdev->dirty.x2 =3D 0; > >>- qfbdev->dirty.y1 =3D 0; > >>- qfbdev->dirty.y2 =3D 0; > >>- > >>- spin_unlock_irqrestore(&qfbdev->dirty.lock, flags); > >>- > >>- /* > >>- * we are using a shadow draw buffer, at qdev->surface0_shadow > >>- */ > >>- qxl_io_log(qdev, "dirty x[%d, %d], y[%d, %d]", x1, x2, y1, y2); > >>- image->dx =3D x1; > >>- image->dy =3D y1; > >>- image->width =3D x2 - x1 + 1; > >>- image->height =3D y2 - y1 + 1; > >>- image->fg_color =3D 0xffffffff; /* unused, just to avoid uninitialized > >>- warnings */ > >>- image->bg_color =3D 0; > >>- image->depth =3D 32; /* TODO: take from somewhere? */ > >>- image->cmap.start =3D 0; > >>- image->cmap.len =3D 0; > >>- image->cmap.red =3D NULL; > >>- image->cmap.green =3D NULL; > >>- image->cmap.blue =3D NULL; > >>- image->cmap.transp =3D NULL; > >>- image->data =3D qfbdev->shadow + (x1 * 4) + (stride * y1); > >>- > >>- qxl_fb_image_init(&qxl_fb_image, qdev, info, NULL); > >>- qxl_draw_opaque_fb(&qxl_fb_image, stride); > >>-} > >>- > >>-static void qxl_dirty_update(struct qxl_fbdev *qfbdev, > >>- int x, int y, int width, int height) > >>-{ > >>- struct qxl_device *qdev =3D qfbdev->qdev; > >>- unsigned long flags; > >>- int x2, y2; > >>- > >>- x2 =3D x + width - 1; > >>- y2 =3D y + height - 1; > >>- > >>- spin_lock_irqsave(&qfbdev->dirty.lock, flags); > >>- > >>- if ((qfbdev->dirty.y2 - qfbdev->dirty.y1) && > >>- (qfbdev->dirty.x2 - qfbdev->dirty.x1)) { > >>- if (qfbdev->dirty.y1 < y) > >>- y =3D qfbdev->dirty.y1; > >>- if (qfbdev->dirty.y2 > y2) > >>- y2 =3D qfbdev->dirty.y2; > >>- if (qfbdev->dirty.x1 < x) > >>- x =3D qfbdev->dirty.x1; > >>- if (qfbdev->dirty.x2 > x2) > >>- x2 =3D qfbdev->dirty.x2; > >>- } > >>- > >>- qfbdev->dirty.x1 =3D x; > >>- qfbdev->dirty.x2 =3D x2; > >>- qfbdev->dirty.y1 =3D y; > >>- qfbdev->dirty.y2 =3D y2; > >>- > >>- spin_unlock_irqrestore(&qfbdev->dirty.lock, flags); > >>- > >>- schedule_work(&qdev->fb_work); > >>-} > >>- > >>-static void qxl_deferred_io(struct fb_info *info, > >>- struct list_head *pagelist) > >>-{ > >>- struct qxl_fbdev *qfbdev =3D info->par; > >>- unsigned long start, end, min, max; > >>- struct page *page; > >>- int 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 (max / info->fix.line_length) + 1; > >>- qxl_dirty_update(qfbdev, 0, y1, info->var.xres, y2 - y1); > >>- } > >>-}; > >>- > >> static struct fb_deferred_io qxl_defio =3D { > >> .delay =3D QXL_DIRTY_DELAY, > >>- .deferred_io =3D qxl_deferred_io, > >>+ .deferred_io =3D drm_fb_helper_deferred_io, > >> }; > >>-static void qxl_fb_fillrect(struct fb_info *info, > >>- const struct fb_fillrect *rect) > >>-{ > >>- struct qxl_fbdev *qfbdev =3D info->par; > >>- > >>- sys_fillrect(info, rect); > >>- qxl_dirty_update(qfbdev, rect->dx, rect->dy, rect->width, > >>- rect->height); > >>-} > >>- > >>-static void qxl_fb_copyarea(struct fb_info *info, > >>- const struct fb_copyarea *area) > >>-{ > >>- struct qxl_fbdev *qfbdev =3D info->par; > >>- > >>- sys_copyarea(info, area); > >>- qxl_dirty_update(qfbdev, area->dx, area->dy, area->width, > >>- area->height); > >>-} > >>- > >>-static void qxl_fb_imageblit(struct fb_info *info, > >>- const struct fb_image *image) > >>-{ > >>- struct qxl_fbdev *qfbdev =3D info->par; > >>- > >>- sys_imageblit(info, image); > >>- qxl_dirty_update(qfbdev, image->dx, image->dy, image->width, > >>- image->height); > >>-} > >>- > >>-static void qxl_fb_work(struct work_struct *work) > >>-{ > >>- struct qxl_device *qdev =3D container_of(work, struct qxl_device, fb_= work); > >>- struct qxl_fbdev *qfbdev =3D qdev->mode_info.qfbdev; > >>- > >>- qxl_fb_dirty_flush(qfbdev->helper.fbdev); > >>-} > >>- > >>-int qxl_fb_init(struct qxl_device *qdev) > >>-{ > >>- INIT_WORK(&qdev->fb_work, qxl_fb_work); > >>- return 0; > >>-} > >>- > >> static struct fb_ops qxlfb_ops =3D { > >> .owner =3D THIS_MODULE, > >> .fb_check_var =3D drm_fb_helper_check_var, > >> .fb_set_par =3D drm_fb_helper_set_par, /* TODO: copy vmwgfx */ > >>- .fb_fillrect =3D qxl_fb_fillrect, > >>- .fb_copyarea =3D qxl_fb_copyarea, > >>- .fb_imageblit =3D qxl_fb_imageblit, > >>+ .fb_fillrect =3D drm_fb_helper_sys_fillrect, > >>+ .fb_copyarea =3D drm_fb_helper_sys_copyarea, > >>+ .fb_imageblit =3D drm_fb_helper_sys_imageblit, > >> .fb_pan_display =3D drm_fb_helper_pan_display, > >> .fb_blank =3D drm_fb_helper_blank, > >> .fb_setcmap =3D drm_fb_helper_setcmap, > >>@@ -338,6 +179,53 @@ out_unref: > >> return ret; > >> } > >>+static int qxlfb_framebuffer_dirty(struct drm_framebuffer *fb, > >>+ struct drm_file *file_priv, > >>+ unsigned flags, unsigned color, > >>+ struct drm_clip_rect *clips, > >>+ unsigned num_clips) > >>+{ > >>+ struct qxl_device *qdev =3D fb->dev->dev_private; > >>+ struct fb_info *info =3D qdev->fbdev_info; > >>+ struct qxl_fbdev *qfbdev =3D info->par; > >>+ struct qxl_fb_image qxl_fb_image; > >>+ struct fb_image *image =3D &qxl_fb_image.fb_image; > >>+ > >>+ /* TODO: hard coding 32 bpp */ > >>+ int stride =3D qfbdev->qfb.base.pitches[0]; > >>+ > >>+ /* > >>+ * we are using a shadow draw buffer, at qdev->surface0_shadow > >>+ */ > >>+ qxl_io_log(qdev, "dirty x[%d, %d], y[%d, %d]", clips->x1, clips->x2, > >>+ clips->y1, clips->y2); > >>+ image->dx =3D clips->x1; > >>+ image->dy =3D clips->y1; > >>+ image->width =3D drm_clip_rect_width(clips); > >>+ image->height =3D drm_clip_rect_height(clips); > >>+ image->fg_color =3D 0xffffffff; /* unused, just to avoid uninitialized > >>+ warnings */ > >>+ image->bg_color =3D 0; > >>+ image->depth =3D 32; /* TODO: take from somewhere? */ > >>+ image->cmap.start =3D 0; > >>+ image->cmap.len =3D 0; > >>+ image->cmap.red =3D NULL; > >>+ image->cmap.green =3D NULL; > >>+ image->cmap.blue =3D NULL; > >>+ image->cmap.transp =3D NULL; > >>+ image->data =3D qfbdev->shadow + (clips->x1 * 4) + (stride * clips->y= 1); > >>+ > >>+ qxl_fb_image_init(&qxl_fb_image, qdev, info, NULL); > >>+ qxl_draw_opaque_fb(&qxl_fb_image, stride); > >>+ > >>+ return 0; > >>+} > >>+ > >>+static const struct drm_framebuffer_funcs qxlfb_fb_funcs =3D { > >>+ .destroy =3D qxl_user_framebuffer_destroy, > >>+ .dirty =3D qxlfb_framebuffer_dirty, > >>+}; > >>+ > >> static int qxlfb_create(struct qxl_fbdev *qfbdev, > >> struct drm_fb_helper_surface_size *sizes) > >> { > >>@@ -383,7 +271,8 @@ static int qxlfb_create(struct qxl_fbdev *qfbdev, > >> info->par =3D qfbdev; > >>- qxl_framebuffer_init(qdev->ddev, &qfbdev->qfb, &mode_cmd, gobj); > >>+ qxl_framebuffer_init(qdev->ddev, &qfbdev->qfb, &mode_cmd, gobj, > >>+ &qxlfb_fb_funcs); > >> fb =3D &qfbdev->qfb.base; > >>@@ -504,7 +393,6 @@ int qxl_fbdev_init(struct qxl_device *qdev) > >> qfbdev->qdev =3D qdev; > >> qdev->mode_info.qfbdev =3D qfbdev; > >> spin_lock_init(&qfbdev->delayed_ops_lock); > >>- spin_lock_init(&qfbdev->dirty.lock); > >> INIT_LIST_HEAD(&qfbdev->delayed_ops); > >> drm_fb_helper_prepare(qdev->ddev, &qfbdev->helper, > >>diff --git a/drivers/gpu/drm/qxl/qxl_kms.c b/drivers/gpu/drm/qxl/qxl_km= s.c > >>index b2977a1..2319800 100644 > >>--- a/drivers/gpu/drm/qxl/qxl_kms.c > >>+++ b/drivers/gpu/drm/qxl/qxl_kms.c > >>@@ -261,10 +261,6 @@ static int qxl_device_init(struct qxl_device *qdev, > >> qdev->gc_queue =3D create_singlethread_workqueue("qxl_gc"); > >> INIT_WORK(&qdev->gc_work, qxl_gc_work); > >>- r =3D qxl_fb_init(qdev); > >>- if (r) > >>- return r; > >>- > >> return 0; > >> } > >>--=20 > >>2.2.2 > >> >=20 > _______________________________________________ > dri-devel mailing list > dri-devel@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/dri-devel --=20 Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch From mboxrd@z Thu Jan 1 00:00:00 1970 From: Daniel Vetter Subject: Re: [PATCH 7/8] drm/qxl: Use drm_fb_helper deferred_io support Date: Thu, 21 Apr 2016 09:41:34 +0200 Message-ID: <20160421074134.GY2510@phenom.ffwll.local> References: <1461165929-11344-1-git-send-email-noralf@tronnes.org> <1461165929-11344-8-git-send-email-noralf@tronnes.org> <20160420174710.GR2510@phenom.ffwll.local> <5717D2C6.7060806@tronnes.org> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: Received: from mail-wm0-x22c.google.com (mail-wm0-x22c.google.com [IPv6:2a00:1450:400c:c09::22c]) by gabe.freedesktop.org (Postfix) with ESMTPS id 2578C6EBF3 for ; Thu, 21 Apr 2016 07:41:39 +0000 (UTC) Received: by mail-wm0-x22c.google.com with SMTP id e201so76145188wme.0 for ; Thu, 21 Apr 2016 00:41:39 -0700 (PDT) Content-Disposition: inline In-Reply-To: <5717D2C6.7060806@tronnes.org> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" To: Noralf =?iso-8859-1?Q?Tr=F8nnes?= Cc: linux-fbdev@vger.kernel.org, tomi.valkeinen@ti.com, laurent.pinchart@ideasonboard.com, dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org List-Id: dri-devel@lists.freedesktop.org T24gV2VkLCBBcHIgMjAsIDIwMTYgYXQgMDk6MDQ6MzhQTSArMDIwMCwgTm9yYWxmIFRyw7hubmVz IHdyb3RlOgo+IAo+IERlbiAyMC4wNC4yMDE2IDE5OjQ3LCBza3JldiBEYW5pZWwgVmV0dGVyOgo+ ID5PbiBXZWQsIEFwciAyMCwgMjAxNiBhdCAwNToyNToyOFBNICswMjAwLCBOb3JhbGYgVHLDuG5u ZXMgd3JvdGU6Cj4gPj5Vc2UgdGhlIGZiZGV2IGRlZmVycmVkIGlvIHN1cHBvcnQgaW4gZHJtX2Zi X2hlbHBlci4KPiA+PlRoZSAoc3RydWN0IGZiX29wcyAqKS0+ZmJfe2ZpbGxyZWN0LGNvcHlhcmVh LGltYWdlYmxpdH0gZnVuY3Rpb25zIHdpbGwKPiA+Pm5vdyBiZSBkZWZlcnJlZCBpbiB0aGUgc2Ft ZSB3YXkgdGhhdCBtbWFwIGRhbWFnZSBpcywgaW5zdGVhZCBvZiBiZWluZwo+ID4+Zmx1c2hlZCBk aXJlY3RseS4KPiA+PlRoaXMgcGF0Y2ggaGFzIG9ubHkgYmVlbiBjb21waWxlIHRlc3RlZC4KPiA+ Pgo+ID4+U2lnbmVkLW9mZi1ieTogTm9yYWxmIFRyw7hubmVzIDxub3JhbGZAdHJvbm5lcy5vcmc+ Cj4gPj4tLS0KPiA+PiAgZHJpdmVycy9ncHUvZHJtL3F4bC9xeGxfZGlzcGxheS5jIHwgICA5ICst Cj4gPj4gIGRyaXZlcnMvZ3B1L2RybS9xeGwvcXhsX2Rydi5oICAgICB8ICAgNyArLQo+ID4+ICBk cml2ZXJzL2dwdS9kcm0vcXhsL3F4bF9mYi5jICAgICAgfCAyMjAgKysrKysrKysrKy0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0KPiA+PiAgZHJpdmVycy9ncHUvZHJtL3F4bC9xeGxfa21zLmMg ICAgIHwgICA0IC0KPiA+PiAgNCBmaWxlcyBjaGFuZ2VkLCA2MiBpbnNlcnRpb25zKCspLCAxNzgg ZGVsZXRpb25zKC0pCj4gPj4KPiA+PmRpZmYgLS1naXQgYS9kcml2ZXJzL2dwdS9kcm0vcXhsL3F4 bF9kaXNwbGF5LmMgYi9kcml2ZXJzL2dwdS9kcm0vcXhsL3F4bF9kaXNwbGF5LmMKPiA+PmluZGV4 IDAzMDQwOWEuLjlhMDM1MjQgMTAwNjQ0Cj4gPj4tLS0gYS9kcml2ZXJzL2dwdS9kcm0vcXhsL3F4 bF9kaXNwbGF5LmMKPiA+PisrKyBiL2RyaXZlcnMvZ3B1L2RybS9xeGwvcXhsX2Rpc3BsYXkuYwo+ ID4+QEAgLTQ2NSw3ICs0NjUsNyBAQCBzdGF0aWMgY29uc3Qgc3RydWN0IGRybV9jcnRjX2Z1bmNz IHF4bF9jcnRjX2Z1bmNzID0gewo+ID4+ICAJLnBhZ2VfZmxpcCA9IHF4bF9jcnRjX3BhZ2VfZmxp cCwKPiA+PiAgfTsKPiA+Pi1zdGF0aWMgdm9pZCBxeGxfdXNlcl9mcmFtZWJ1ZmZlcl9kZXN0cm95 KHN0cnVjdCBkcm1fZnJhbWVidWZmZXIgKmZiKQo+ID4+K3ZvaWQgcXhsX3VzZXJfZnJhbWVidWZm ZXJfZGVzdHJveShzdHJ1Y3QgZHJtX2ZyYW1lYnVmZmVyICpmYikKPiA+PiAgewo+ID4+ICAJc3Ry dWN0IHF4bF9mcmFtZWJ1ZmZlciAqcXhsX2ZiID0gdG9fcXhsX2ZyYW1lYnVmZmVyKGZiKTsKPiA+ PkBAIC01MjcsMTIgKzUyNywxMyBAQCBpbnQKPiA+PiAgcXhsX2ZyYW1lYnVmZmVyX2luaXQoc3Ry dWN0IGRybV9kZXZpY2UgKmRldiwKPiA+PiAgCQkgICAgIHN0cnVjdCBxeGxfZnJhbWVidWZmZXIg KnFmYiwKPiA+PiAgCQkgICAgIGNvbnN0IHN0cnVjdCBkcm1fbW9kZV9mYl9jbWQyICptb2RlX2Nt ZCwKPiA+Pi0JCSAgICAgc3RydWN0IGRybV9nZW1fb2JqZWN0ICpvYmopCj4gPj4rCQkgICAgIHN0 cnVjdCBkcm1fZ2VtX29iamVjdCAqb2JqLAo+ID4+KwkJICAgICBjb25zdCBzdHJ1Y3QgZHJtX2Zy YW1lYnVmZmVyX2Z1bmNzICpmdW5jcykKPiA+VGhlcmUgc2hvdWxkIGJlIG5vIG5lZWQgYXQgYWxs IHRvIGhhdmUgYSBzZXBhcmF0ZSBmYiBmdW5jcyB0YWJsZSBmb3IgdGhlCj4gPmZiZGV2IGZiLiBC b3RoIC9zaG91bGQvIGJlIGFibGUgdG8gdXNlIHRoZSBleGFjdCBzYW1lIChhbHJlYWR5IGV4aXN0 aW5nKQo+ID4tPmRpcnR5KCkgY2FsbGJhY2suIFdlIG5lZWQgdGhpcyBvbmx5IGluIENNQSBiZWNh dXNlIENNQSBpcyBhIG1pZGxheWVyCj4gPnVzZWQgYnkgbXVsdGlwbGUgZHJpdmVycy4KPiAKPiBJ IGRvbid0IHNlZSBob3cgSSBjYW4gYXZvaWQgaXQuCj4gCj4gZmJkZXYgZnJhbWVidWZmZXIgZmx1 c2hpbmc6Cj4gCj4gc3RhdGljIHZvaWQgcXhsX2ZiX2RpcnR5X2ZsdXNoKHN0cnVjdCBmYl9pbmZv ICppbmZvKQo+IHsKPiAgICAgICAgIHF4bF9mYl9pbWFnZV9pbml0KCZxeGxfZmJfaW1hZ2UsIHFk ZXYsIGluZm8sIE5VTEwpOwo+ICAgICAgICAgcXhsX2RyYXdfb3BhcXVlX2ZiKCZxeGxfZmJfaW1h Z2UsIHN0cmlkZSk7Cj4gfQo+IAo+IGRybSBmcmFtZWJ1ZmZlciBmbHVzaGluZzoKPiAKPiBzdGF0 aWMgaW50IHF4bF9mcmFtZWJ1ZmZlcl9zdXJmYWNlX2RpcnR5KC4uLikKPiB7Cj4gICAgICAgICBx eGxfZHJhd19kaXJ0eV9mYiguLi4pOwo+IH0KPiAKPiBxeGxfZHJhd19vcGFxdWVfZmIoKSBhbmQg cXhsX2RyYXdfZGlydHlfZmIoKSBkaWZmZXIgc28gbXVjaCB0aGF0IGl0J3Mgd2F5Cj4gb3ZlciBt eSBoZWFkIHRvIHNlZSBpZiB0aGV5IGNhbiBiZSBjb21iaW5lZC4KPiBIZXJlJ3MgYW4gb25saW5l IGRpZmYgb2YgdGhlIHR3byBmdW5jdGlvbnM6Cj4gaHR0cHM6Ly93d3cuZGlmZmNoZWNrZXIuY29t L2pxYmJhbHV4CgpJbW8gbnVrZSB0aGUgZmJkZXYgb25lIGVudGlyZWx5LiBJZiBpdCBicmVha3Mg dGhlbiBpdCdzIGVpdGhlciBhIGJ1ZyBpbgp5b3VyIGdlbmVyaWMgZmJkZWZpbyBjb2RlLCBvciB0 aGUgcXhsIC0+ZGlydHkgaW1wbGVtZW50YXRpb24gaGFzIGEgYnVnLiBJdApzaG91bGQgd29yayA7 LSkKCk9rLCBzbGlnaHRseSBtb3JlIHNlcmlvdXNseSB0aGUgZGlmZmVyZW5jZSBzZWVtcyB0byBi ZSB0aGF0IHRoZSBmYmRldiBvbmUKc3VwcG9ydCBwYWxldHRlZCBtb2RlIHRvby4gQnV0IHNpbmNl IHF4bCBoYXMgMCBwaXhlbCBmb3JtYXQgY2hlY2tpbmcKYW55d2hlcmUgSSBoYXZlIG5vIGlkZWEg d2hldGhlciB0aGF0J3MgZGVhZCBjb2RlIChpLmUuIGJyb2tlbikgb3IgYWN0dWFsbHkKd29ya2lu Zy4gSSBndWVzcyBrZWVwaW5nIHRoZSBzcGxpdCBpcyBvaywgaWYgd2UgYWRkIGEgYmlnIEZJWE1F IGNvbW1lbnQgdG8KaXQgdGhhdCB0aGlzIGlzIHZlcnkgZmlzaHkuCi1EYW5pZWwKCgo+IAo+IAo+ ID4KPiA+V2l0aCB0aGF0IGNoYW5nZSB5b3Ugc2hvdWxkIGJlIGFibGUgdG8gY29uZGVuc2UgdGhp cyBwYXRjaCBkb3duIHRvIHByZXR0eQo+ID5tdWNoIGp1c3QgcmVtb3ZpbmcgbGluZXMuIFdoaWNo IGlzIEdvb2QgKHRtKS4KPiA+Cj4gPkNoZWVycywgRGFuaWVsCj4gPgo+ID4+ICB7Cj4gPj4gIAlp bnQgcmV0Owo+ID4+ICAJcWZiLT5vYmogPSBvYmo7Cj4gPj4tCXJldCA9IGRybV9mcmFtZWJ1ZmZl cl9pbml0KGRldiwgJnFmYi0+YmFzZSwgJnF4bF9mYl9mdW5jcyk7Cj4gPj4rCXJldCA9IGRybV9m cmFtZWJ1ZmZlcl9pbml0KGRldiwgJnFmYi0+YmFzZSwgZnVuY3MpOwo+ID4+ICAJaWYgKHJldCkg ewo+ID4+ICAJCXFmYi0+b2JqID0gTlVMTDsKPiA+PiAgCQlyZXR1cm4gcmV0Owo+ID4+QEAgLTk5 OSw3ICsxMDAwLDcgQEAgcXhsX3VzZXJfZnJhbWVidWZmZXJfY3JlYXRlKHN0cnVjdCBkcm1fZGV2 aWNlICpkZXYsCj4gPj4gIAlpZiAocXhsX2ZiID09IE5VTEwpCj4gPj4gIAkJcmV0dXJuIE5VTEw7 Cj4gPj4tCXJldCA9IHF4bF9mcmFtZWJ1ZmZlcl9pbml0KGRldiwgcXhsX2ZiLCBtb2RlX2NtZCwg b2JqKTsKPiA+PisJcmV0ID0gcXhsX2ZyYW1lYnVmZmVyX2luaXQoZGV2LCBxeGxfZmIsIG1vZGVf Y21kLCBvYmosICZxeGxfZmJfZnVuY3MpOwo+ID4+ICAJaWYgKHJldCkgewo+ID4+ICAJCWtmcmVl KHF4bF9mYik7Cj4gPj4gIAkJZHJtX2dlbV9vYmplY3RfdW5yZWZlcmVuY2VfdW5sb2NrZWQob2Jq KTsKPiA+PmRpZmYgLS1naXQgYS9kcml2ZXJzL2dwdS9kcm0vcXhsL3F4bF9kcnYuaCBiL2RyaXZl cnMvZ3B1L2RybS9xeGwvcXhsX2Rydi5oCj4gPj5pbmRleCAzZjM4OTdlLi4zYWQ2NjA0IDEwMDY0 NAo+ID4+LS0tIGEvZHJpdmVycy9ncHUvZHJtL3F4bC9xeGxfZHJ2LmgKPiA+PisrKyBiL2RyaXZl cnMvZ3B1L2RybS9xeGwvcXhsX2Rydi5oCj4gPj5AQCAtMzI0LDggKzMyNCw2IEBAIHN0cnVjdCBx eGxfZGV2aWNlIHsKPiA+PiAgCXN0cnVjdCB3b3JrcXVldWVfc3RydWN0ICpnY19xdWV1ZTsKPiA+ PiAgCXN0cnVjdCB3b3JrX3N0cnVjdCBnY193b3JrOwo+ID4+LQlzdHJ1Y3Qgd29ya19zdHJ1Y3Qg ZmJfd29yazsKPiA+Pi0KPiA+PiAgCXN0cnVjdCBkcm1fcHJvcGVydHkgKmhvdHBsdWdfbW9kZV91 cGRhdGVfcHJvcGVydHk7Cj4gPj4gIAlpbnQgbW9uaXRvcnNfY29uZmlnX3dpZHRoOwo+ID4+ICAJ aW50IG1vbml0b3JzX2NvbmZpZ19oZWlnaHQ7Cj4gPj5AQCAtMzg5LDExICszODcsMTMgQEAgaW50 IHF4bF9nZXRfaGFuZGxlX2Zvcl9wcmltYXJ5X2ZiKHN0cnVjdCBxeGxfZGV2aWNlICpxZGV2LAo+ ID4+ICB2b2lkIHF4bF9mYmRldl9zZXRfc3VzcGVuZChzdHJ1Y3QgcXhsX2RldmljZSAqcWRldiwg aW50IHN0YXRlKTsKPiA+PiAgLyogcXhsX2Rpc3BsYXkuYyAqLwo+ID4+K3ZvaWQgcXhsX3VzZXJf ZnJhbWVidWZmZXJfZGVzdHJveShzdHJ1Y3QgZHJtX2ZyYW1lYnVmZmVyICpmYik7Cj4gPj4gIGlu dAo+ID4+ICBxeGxfZnJhbWVidWZmZXJfaW5pdChzdHJ1Y3QgZHJtX2RldmljZSAqZGV2LAo+ID4+ ICAJCSAgICAgc3RydWN0IHF4bF9mcmFtZWJ1ZmZlciAqcmZiLAo+ID4+ICAJCSAgICAgY29uc3Qg c3RydWN0IGRybV9tb2RlX2ZiX2NtZDIgKm1vZGVfY21kLAo+ID4+LQkJICAgICBzdHJ1Y3QgZHJt X2dlbV9vYmplY3QgKm9iaik7Cj4gPj4rCQkgICAgIHN0cnVjdCBkcm1fZ2VtX29iamVjdCAqb2Jq LAo+ID4+KwkJICAgICBjb25zdCBzdHJ1Y3QgZHJtX2ZyYW1lYnVmZmVyX2Z1bmNzICpmdW5jcyk7 Cj4gPj4gIHZvaWQgcXhsX2Rpc3BsYXlfcmVhZF9jbGllbnRfbW9uaXRvcnNfY29uZmlnKHN0cnVj dCBxeGxfZGV2aWNlICpxZGV2KTsKPiA+PiAgdm9pZCBxeGxfc2VuZF9tb25pdG9yc19jb25maWco c3RydWN0IHF4bF9kZXZpY2UgKnFkZXYpOwo+ID4+ICBpbnQgcXhsX2NyZWF0ZV9tb25pdG9yc19v YmplY3Qoc3RydWN0IHF4bF9kZXZpY2UgKnFkZXYpOwo+ID4+QEAgLTU1Myw3ICs1NTMsNiBAQCBp bnQgcXhsX2lycV9pbml0KHN0cnVjdCBxeGxfZGV2aWNlICpxZGV2KTsKPiA+PiAgaXJxcmV0dXJu X3QgcXhsX2lycV9oYW5kbGVyKGludCBpcnEsIHZvaWQgKmFyZyk7Cj4gPj4gIC8qIHF4bF9mYi5j ICovCj4gPj4taW50IHF4bF9mYl9pbml0KHN0cnVjdCBxeGxfZGV2aWNlICpxZGV2KTsKPiA+PiAg Ym9vbCBxeGxfZmJkZXZfcW9ial9pc19mYihzdHJ1Y3QgcXhsX2RldmljZSAqcWRldiwgc3RydWN0 IHF4bF9ibyAqcW9iaik7Cj4gPj4gIGludCBxeGxfZGVidWdmc19hZGRfZmlsZXMoc3RydWN0IHF4 bF9kZXZpY2UgKnFkZXYsCj4gPj5kaWZmIC0tZ2l0IGEvZHJpdmVycy9ncHUvZHJtL3F4bC9xeGxf ZmIuYyBiL2RyaXZlcnMvZ3B1L2RybS9xeGwvcXhsX2ZiLmMKPiA+PmluZGV4IDA2ZjAzMmQuLjA5 MGRjZWUgMTAwNjQ0Cj4gPj4tLS0gYS9kcml2ZXJzL2dwdS9kcm0vcXhsL3F4bF9mYi5jCj4gPj4r KysgYi9kcml2ZXJzL2dwdS9kcm0vcXhsL3F4bF9mYi5jCj4gPj5AQCAtMzAsNiArMzAsNyBAQAo+ ID4+ICAjaW5jbHVkZSAiZHJtL2RybS5oIgo+ID4+ICAjaW5jbHVkZSAiZHJtL2RybV9jcnRjLmgi Cj4gPj4gICNpbmNsdWRlICJkcm0vZHJtX2NydGNfaGVscGVyLmgiCj4gPj4rI2luY2x1ZGUgImRy bS9kcm1fcmVjdC5oIgo+ID4+ICAjaW5jbHVkZSAicXhsX2Rydi5oIgo+ID4+ICAjaW5jbHVkZSAi cXhsX29iamVjdC5oIgo+ID4+QEAgLTQ2LDE1ICs0Nyw2IEBAIHN0cnVjdCBxeGxfZmJkZXYgewo+ ID4+ICAJc3RydWN0IGxpc3RfaGVhZCBkZWxheWVkX29wczsKPiA+PiAgCXZvaWQgKnNoYWRvdzsK PiA+PiAgCWludCBzaXplOwo+ID4+LQo+ID4+LQkvKiBkaXJ0eSBtZW1vcnkgbG9nZ2luZyAqLwo+ ID4+LQlzdHJ1Y3Qgewo+ID4+LQkJc3BpbmxvY2tfdCBsb2NrOwo+ID4+LQkJdW5zaWduZWQgeDE7 Cj4gPj4tCQl1bnNpZ25lZCB5MTsKPiA+Pi0JCXVuc2lnbmVkIHgyOwo+ID4+LQkJdW5zaWduZWQg eTI7Cj4gPj4tCX0gZGlydHk7Cj4gPj4gIH07Cj4gPj4gIHN0YXRpYyB2b2lkIHF4bF9mYl9pbWFn ZV9pbml0KHN0cnVjdCBxeGxfZmJfaW1hZ2UgKnF4bF9mYl9pbWFnZSwKPiA+PkBAIC04MiwxNjkg Kzc0LDE4IEBAIHN0YXRpYyB2b2lkIHF4bF9mYl9pbWFnZV9pbml0KHN0cnVjdCBxeGxfZmJfaW1h Z2UgKnF4bF9mYl9pbWFnZSwKPiA+PiAgCX0KPiA+PiAgfQo+ID4+LXN0YXRpYyB2b2lkIHF4bF9m Yl9kaXJ0eV9mbHVzaChzdHJ1Y3QgZmJfaW5mbyAqaW5mbykKPiA+Pi17Cj4gPj4tCXN0cnVjdCBx eGxfZmJkZXYgKnFmYmRldiA9IGluZm8tPnBhcjsKPiA+Pi0Jc3RydWN0IHF4bF9kZXZpY2UgKnFk ZXYgPSBxZmJkZXYtPnFkZXY7Cj4gPj4tCXN0cnVjdCBxeGxfZmJfaW1hZ2UgcXhsX2ZiX2ltYWdl Owo+ID4+LQlzdHJ1Y3QgZmJfaW1hZ2UgKmltYWdlID0gJnF4bF9mYl9pbWFnZS5mYl9pbWFnZTsK PiA+Pi0JdW5zaWduZWQgbG9uZyBmbGFnczsKPiA+Pi0JdTMyIHgxLCB4MiwgeTEsIHkyOwo+ID4+ LQo+ID4+LQkvKiBUT0RPOiBoYXJkIGNvZGluZyAzMiBicHAgKi8KPiA+Pi0JaW50IHN0cmlkZSA9 IHFmYmRldi0+cWZiLmJhc2UucGl0Y2hlc1swXTsKPiA+Pi0KPiA+Pi0Jc3Bpbl9sb2NrX2lycXNh dmUoJnFmYmRldi0+ZGlydHkubG9jaywgZmxhZ3MpOwo+ID4+LQo+ID4+LQl4MSA9IHFmYmRldi0+ ZGlydHkueDE7Cj4gPj4tCXgyID0gcWZiZGV2LT5kaXJ0eS54MjsKPiA+Pi0JeTEgPSBxZmJkZXYt PmRpcnR5LnkxOwo+ID4+LQl5MiA9IHFmYmRldi0+ZGlydHkueTI7Cj4gPj4tCXFmYmRldi0+ZGly dHkueDEgPSAwOwo+ID4+LQlxZmJkZXYtPmRpcnR5LngyID0gMDsKPiA+Pi0JcWZiZGV2LT5kaXJ0 eS55MSA9IDA7Cj4gPj4tCXFmYmRldi0+ZGlydHkueTIgPSAwOwo+ID4+LQo+ID4+LQlzcGluX3Vu bG9ja19pcnFyZXN0b3JlKCZxZmJkZXYtPmRpcnR5LmxvY2ssIGZsYWdzKTsKPiA+Pi0KPiA+Pi0J LyoKPiA+Pi0JICogd2UgYXJlIHVzaW5nIGEgc2hhZG93IGRyYXcgYnVmZmVyLCBhdCBxZGV2LT5z dXJmYWNlMF9zaGFkb3cKPiA+Pi0JICovCj4gPj4tCXF4bF9pb19sb2cocWRldiwgImRpcnR5IHhb JWQsICVkXSwgeVslZCwgJWRdIiwgeDEsIHgyLCB5MSwgeTIpOwo+ID4+LQlpbWFnZS0+ZHggPSB4 MTsKPiA+Pi0JaW1hZ2UtPmR5ID0geTE7Cj4gPj4tCWltYWdlLT53aWR0aCA9IHgyIC0geDEgKyAx Owo+ID4+LQlpbWFnZS0+aGVpZ2h0ID0geTIgLSB5MSArIDE7Cj4gPj4tCWltYWdlLT5mZ19jb2xv ciA9IDB4ZmZmZmZmZmY7IC8qIHVudXNlZCwganVzdCB0byBhdm9pZCB1bmluaXRpYWxpemVkCj4g Pj4tCQkJCQkgd2FybmluZ3MgKi8KPiA+Pi0JaW1hZ2UtPmJnX2NvbG9yID0gMDsKPiA+Pi0JaW1h Z2UtPmRlcHRoID0gMzI7CSAgICAgLyogVE9ETzogdGFrZSBmcm9tIHNvbWV3aGVyZT8gKi8KPiA+ Pi0JaW1hZ2UtPmNtYXAuc3RhcnQgPSAwOwo+ID4+LQlpbWFnZS0+Y21hcC5sZW4gPSAwOwo+ID4+ LQlpbWFnZS0+Y21hcC5yZWQgPSBOVUxMOwo+ID4+LQlpbWFnZS0+Y21hcC5ncmVlbiA9IE5VTEw7 Cj4gPj4tCWltYWdlLT5jbWFwLmJsdWUgPSBOVUxMOwo+ID4+LQlpbWFnZS0+Y21hcC50cmFuc3Ag PSBOVUxMOwo+ID4+LQlpbWFnZS0+ZGF0YSA9IHFmYmRldi0+c2hhZG93ICsgKHgxICogNCkgKyAo c3RyaWRlICogeTEpOwo+ID4+LQo+ID4+LQlxeGxfZmJfaW1hZ2VfaW5pdCgmcXhsX2ZiX2ltYWdl LCBxZGV2LCBpbmZvLCBOVUxMKTsKPiA+Pi0JcXhsX2RyYXdfb3BhcXVlX2ZiKCZxeGxfZmJfaW1h Z2UsIHN0cmlkZSk7Cj4gPj4tfQo+ID4+LQo+ID4+LXN0YXRpYyB2b2lkIHF4bF9kaXJ0eV91cGRh dGUoc3RydWN0IHF4bF9mYmRldiAqcWZiZGV2LAo+ID4+LQkJCSAgICAgaW50IHgsIGludCB5LCBp bnQgd2lkdGgsIGludCBoZWlnaHQpCj4gPj4tewo+ID4+LQlzdHJ1Y3QgcXhsX2RldmljZSAqcWRl diA9IHFmYmRldi0+cWRldjsKPiA+Pi0JdW5zaWduZWQgbG9uZyBmbGFnczsKPiA+Pi0JaW50IHgy LCB5MjsKPiA+Pi0KPiA+Pi0JeDIgPSB4ICsgd2lkdGggLSAxOwo+ID4+LQl5MiA9IHkgKyBoZWln aHQgLSAxOwo+ID4+LQo+ID4+LQlzcGluX2xvY2tfaXJxc2F2ZSgmcWZiZGV2LT5kaXJ0eS5sb2Nr LCBmbGFncyk7Cj4gPj4tCj4gPj4tCWlmICgocWZiZGV2LT5kaXJ0eS55MiAtIHFmYmRldi0+ZGly dHkueTEpICYmCj4gPj4tCSAgICAocWZiZGV2LT5kaXJ0eS54MiAtIHFmYmRldi0+ZGlydHkueDEp KSB7Cj4gPj4tCQlpZiAocWZiZGV2LT5kaXJ0eS55MSA8IHkpCj4gPj4tCQkJeSA9IHFmYmRldi0+ ZGlydHkueTE7Cj4gPj4tCQlpZiAocWZiZGV2LT5kaXJ0eS55MiA+IHkyKQo+ID4+LQkJCXkyID0g cWZiZGV2LT5kaXJ0eS55MjsKPiA+Pi0JCWlmIChxZmJkZXYtPmRpcnR5LngxIDwgeCkKPiA+Pi0J CQl4ID0gcWZiZGV2LT5kaXJ0eS54MTsKPiA+Pi0JCWlmIChxZmJkZXYtPmRpcnR5LngyID4geDIp Cj4gPj4tCQkJeDIgPSBxZmJkZXYtPmRpcnR5LngyOwo+ID4+LQl9Cj4gPj4tCj4gPj4tCXFmYmRl di0+ZGlydHkueDEgPSB4Owo+ID4+LQlxZmJkZXYtPmRpcnR5LngyID0geDI7Cj4gPj4tCXFmYmRl di0+ZGlydHkueTEgPSB5Owo+ID4+LQlxZmJkZXYtPmRpcnR5LnkyID0geTI7Cj4gPj4tCj4gPj4t CXNwaW5fdW5sb2NrX2lycXJlc3RvcmUoJnFmYmRldi0+ZGlydHkubG9jaywgZmxhZ3MpOwo+ID4+ LQo+ID4+LQlzY2hlZHVsZV93b3JrKCZxZGV2LT5mYl93b3JrKTsKPiA+Pi19Cj4gPj4tCj4gPj4t c3RhdGljIHZvaWQgcXhsX2RlZmVycmVkX2lvKHN0cnVjdCBmYl9pbmZvICppbmZvLAo+ID4+LQkJ CSAgICBzdHJ1Y3QgbGlzdF9oZWFkICpwYWdlbGlzdCkKPiA+Pi17Cj4gPj4tCXN0cnVjdCBxeGxf ZmJkZXYgKnFmYmRldiA9IGluZm8tPnBhcjsKPiA+Pi0JdW5zaWduZWQgbG9uZyBzdGFydCwgZW5k LCBtaW4sIG1heDsKPiA+Pi0Jc3RydWN0IHBhZ2UgKnBhZ2U7Cj4gPj4tCWludCB5MSwgeTI7Cj4g Pj4tCj4gPj4tCW1pbiA9IFVMT05HX01BWDsKPiA+Pi0JbWF4ID0gMDsKPiA+Pi0JbGlzdF9mb3Jf ZWFjaF9lbnRyeShwYWdlLCBwYWdlbGlzdCwgbHJ1KSB7Cj4gPj4tCQlzdGFydCA9IHBhZ2UtPmlu ZGV4IDw8IFBBR0VfU0hJRlQ7Cj4gPj4tCQllbmQgPSBzdGFydCArIFBBR0VfU0laRSAtIDE7Cj4g Pj4tCQltaW4gPSBtaW4obWluLCBzdGFydCk7Cj4gPj4tCQltYXggPSBtYXgobWF4LCBlbmQpOwo+ ID4+LQl9Cj4gPj4tCj4gPj4tCWlmIChtaW4gPCBtYXgpIHsKPiA+Pi0JCXkxID0gbWluIC8gaW5m by0+Zml4LmxpbmVfbGVuZ3RoOwo+ID4+LQkJeTIgPSAobWF4IC8gaW5mby0+Zml4LmxpbmVfbGVu Z3RoKSArIDE7Cj4gPj4tCQlxeGxfZGlydHlfdXBkYXRlKHFmYmRldiwgMCwgeTEsIGluZm8tPnZh ci54cmVzLCB5MiAtIHkxKTsKPiA+Pi0JfQo+ID4+LX07Cj4gPj4tCj4gPj4gIHN0YXRpYyBzdHJ1 Y3QgZmJfZGVmZXJyZWRfaW8gcXhsX2RlZmlvID0gewo+ID4+ICAJLmRlbGF5CQk9IFFYTF9ESVJU WV9ERUxBWSwKPiA+Pi0JLmRlZmVycmVkX2lvCT0gcXhsX2RlZmVycmVkX2lvLAo+ID4+KwkuZGVm ZXJyZWRfaW8JPSBkcm1fZmJfaGVscGVyX2RlZmVycmVkX2lvLAo+ID4+ICB9Owo+ID4+LXN0YXRp YyB2b2lkIHF4bF9mYl9maWxscmVjdChzdHJ1Y3QgZmJfaW5mbyAqaW5mbywKPiA+Pi0JCQkgICAg Y29uc3Qgc3RydWN0IGZiX2ZpbGxyZWN0ICpyZWN0KQo+ID4+LXsKPiA+Pi0Jc3RydWN0IHF4bF9m YmRldiAqcWZiZGV2ID0gaW5mby0+cGFyOwo+ID4+LQo+ID4+LQlzeXNfZmlsbHJlY3QoaW5mbywg cmVjdCk7Cj4gPj4tCXF4bF9kaXJ0eV91cGRhdGUocWZiZGV2LCByZWN0LT5keCwgcmVjdC0+ZHks IHJlY3QtPndpZHRoLAo+ID4+LQkJCSByZWN0LT5oZWlnaHQpOwo+ID4+LX0KPiA+Pi0KPiA+Pi1z dGF0aWMgdm9pZCBxeGxfZmJfY29weWFyZWEoc3RydWN0IGZiX2luZm8gKmluZm8sCj4gPj4tCQkJ ICAgIGNvbnN0IHN0cnVjdCBmYl9jb3B5YXJlYSAqYXJlYSkKPiA+Pi17Cj4gPj4tCXN0cnVjdCBx eGxfZmJkZXYgKnFmYmRldiA9IGluZm8tPnBhcjsKPiA+Pi0KPiA+Pi0Jc3lzX2NvcHlhcmVhKGlu Zm8sIGFyZWEpOwo+ID4+LQlxeGxfZGlydHlfdXBkYXRlKHFmYmRldiwgYXJlYS0+ZHgsIGFyZWEt PmR5LCBhcmVhLT53aWR0aCwKPiA+Pi0JCQkgYXJlYS0+aGVpZ2h0KTsKPiA+Pi19Cj4gPj4tCj4g Pj4tc3RhdGljIHZvaWQgcXhsX2ZiX2ltYWdlYmxpdChzdHJ1Y3QgZmJfaW5mbyAqaW5mbywKPiA+ Pi0JCQkgICAgIGNvbnN0IHN0cnVjdCBmYl9pbWFnZSAqaW1hZ2UpCj4gPj4tewo+ID4+LQlzdHJ1 Y3QgcXhsX2ZiZGV2ICpxZmJkZXYgPSBpbmZvLT5wYXI7Cj4gPj4tCj4gPj4tCXN5c19pbWFnZWJs aXQoaW5mbywgaW1hZ2UpOwo+ID4+LQlxeGxfZGlydHlfdXBkYXRlKHFmYmRldiwgaW1hZ2UtPmR4 LCBpbWFnZS0+ZHksIGltYWdlLT53aWR0aCwKPiA+Pi0JCQkgaW1hZ2UtPmhlaWdodCk7Cj4gPj4t fQo+ID4+LQo+ID4+LXN0YXRpYyB2b2lkIHF4bF9mYl93b3JrKHN0cnVjdCB3b3JrX3N0cnVjdCAq d29yaykKPiA+Pi17Cj4gPj4tCXN0cnVjdCBxeGxfZGV2aWNlICpxZGV2ID0gY29udGFpbmVyX29m KHdvcmssIHN0cnVjdCBxeGxfZGV2aWNlLCBmYl93b3JrKTsKPiA+Pi0Jc3RydWN0IHF4bF9mYmRl diAqcWZiZGV2ID0gcWRldi0+bW9kZV9pbmZvLnFmYmRldjsKPiA+Pi0KPiA+Pi0JcXhsX2ZiX2Rp cnR5X2ZsdXNoKHFmYmRldi0+aGVscGVyLmZiZGV2KTsKPiA+Pi19Cj4gPj4tCj4gPj4taW50IHF4 bF9mYl9pbml0KHN0cnVjdCBxeGxfZGV2aWNlICpxZGV2KQo+ID4+LXsKPiA+Pi0JSU5JVF9XT1JL KCZxZGV2LT5mYl93b3JrLCBxeGxfZmJfd29yayk7Cj4gPj4tCXJldHVybiAwOwo+ID4+LX0KPiA+ Pi0KPiA+PiAgc3RhdGljIHN0cnVjdCBmYl9vcHMgcXhsZmJfb3BzID0gewo+ID4+ICAJLm93bmVy ID0gVEhJU19NT0RVTEUsCj4gPj4gIAkuZmJfY2hlY2tfdmFyID0gZHJtX2ZiX2hlbHBlcl9jaGVj a192YXIsCj4gPj4gIAkuZmJfc2V0X3BhciA9IGRybV9mYl9oZWxwZXJfc2V0X3BhciwgLyogVE9E TzogY29weSB2bXdnZnggKi8KPiA+Pi0JLmZiX2ZpbGxyZWN0ID0gcXhsX2ZiX2ZpbGxyZWN0LAo+ ID4+LQkuZmJfY29weWFyZWEgPSBxeGxfZmJfY29weWFyZWEsCj4gPj4tCS5mYl9pbWFnZWJsaXQg PSBxeGxfZmJfaW1hZ2VibGl0LAo+ID4+KwkuZmJfZmlsbHJlY3QgPSBkcm1fZmJfaGVscGVyX3N5 c19maWxscmVjdCwKPiA+PisJLmZiX2NvcHlhcmVhID0gZHJtX2ZiX2hlbHBlcl9zeXNfY29weWFy ZWEsCj4gPj4rCS5mYl9pbWFnZWJsaXQgPSBkcm1fZmJfaGVscGVyX3N5c19pbWFnZWJsaXQsCj4g Pj4gIAkuZmJfcGFuX2Rpc3BsYXkgPSBkcm1fZmJfaGVscGVyX3Bhbl9kaXNwbGF5LAo+ID4+ICAJ LmZiX2JsYW5rID0gZHJtX2ZiX2hlbHBlcl9ibGFuaywKPiA+PiAgCS5mYl9zZXRjbWFwID0gZHJt X2ZiX2hlbHBlcl9zZXRjbWFwLAo+ID4+QEAgLTMzOCw2ICsxNzksNTMgQEAgb3V0X3VucmVmOgo+ ID4+ICAJcmV0dXJuIHJldDsKPiA+PiAgfQo+ID4+K3N0YXRpYyBpbnQgcXhsZmJfZnJhbWVidWZm ZXJfZGlydHkoc3RydWN0IGRybV9mcmFtZWJ1ZmZlciAqZmIsCj4gPj4rCQkJCSAgIHN0cnVjdCBk cm1fZmlsZSAqZmlsZV9wcml2LAo+ID4+KwkJCQkgICB1bnNpZ25lZCBmbGFncywgdW5zaWduZWQg Y29sb3IsCj4gPj4rCQkJCSAgIHN0cnVjdCBkcm1fY2xpcF9yZWN0ICpjbGlwcywKPiA+PisJCQkJ ICAgdW5zaWduZWQgbnVtX2NsaXBzKQo+ID4+K3sKPiA+PisJc3RydWN0IHF4bF9kZXZpY2UgKnFk ZXYgPSBmYi0+ZGV2LT5kZXZfcHJpdmF0ZTsKPiA+PisJc3RydWN0IGZiX2luZm8gKmluZm8gPSBx ZGV2LT5mYmRldl9pbmZvOwo+ID4+KwlzdHJ1Y3QgcXhsX2ZiZGV2ICpxZmJkZXYgPSBpbmZvLT5w YXI7Cj4gPj4rCXN0cnVjdCBxeGxfZmJfaW1hZ2UgcXhsX2ZiX2ltYWdlOwo+ID4+KwlzdHJ1Y3Qg ZmJfaW1hZ2UgKmltYWdlID0gJnF4bF9mYl9pbWFnZS5mYl9pbWFnZTsKPiA+PisKPiA+PisJLyog VE9ETzogaGFyZCBjb2RpbmcgMzIgYnBwICovCj4gPj4rCWludCBzdHJpZGUgPSBxZmJkZXYtPnFm Yi5iYXNlLnBpdGNoZXNbMF07Cj4gPj4rCj4gPj4rCS8qCj4gPj4rCSAqIHdlIGFyZSB1c2luZyBh IHNoYWRvdyBkcmF3IGJ1ZmZlciwgYXQgcWRldi0+c3VyZmFjZTBfc2hhZG93Cj4gPj4rCSAqLwo+ ID4+KwlxeGxfaW9fbG9nKHFkZXYsICJkaXJ0eSB4WyVkLCAlZF0sIHlbJWQsICVkXSIsIGNsaXBz LT54MSwgY2xpcHMtPngyLAo+ID4+KwkJICAgY2xpcHMtPnkxLCBjbGlwcy0+eTIpOwo+ID4+Kwlp bWFnZS0+ZHggPSBjbGlwcy0+eDE7Cj4gPj4rCWltYWdlLT5keSA9IGNsaXBzLT55MTsKPiA+PisJ aW1hZ2UtPndpZHRoID0gZHJtX2NsaXBfcmVjdF93aWR0aChjbGlwcyk7Cj4gPj4rCWltYWdlLT5o ZWlnaHQgPSBkcm1fY2xpcF9yZWN0X2hlaWdodChjbGlwcyk7Cj4gPj4rCWltYWdlLT5mZ19jb2xv ciA9IDB4ZmZmZmZmZmY7IC8qIHVudXNlZCwganVzdCB0byBhdm9pZCB1bmluaXRpYWxpemVkCj4g Pj4rCQkJCQkgd2FybmluZ3MgKi8KPiA+PisJaW1hZ2UtPmJnX2NvbG9yID0gMDsKPiA+PisJaW1h Z2UtPmRlcHRoID0gMzI7CSAgICAgLyogVE9ETzogdGFrZSBmcm9tIHNvbWV3aGVyZT8gKi8KPiA+ PisJaW1hZ2UtPmNtYXAuc3RhcnQgPSAwOwo+ID4+KwlpbWFnZS0+Y21hcC5sZW4gPSAwOwo+ID4+ KwlpbWFnZS0+Y21hcC5yZWQgPSBOVUxMOwo+ID4+KwlpbWFnZS0+Y21hcC5ncmVlbiA9IE5VTEw7 Cj4gPj4rCWltYWdlLT5jbWFwLmJsdWUgPSBOVUxMOwo+ID4+KwlpbWFnZS0+Y21hcC50cmFuc3Ag PSBOVUxMOwo+ID4+KwlpbWFnZS0+ZGF0YSA9IHFmYmRldi0+c2hhZG93ICsgKGNsaXBzLT54MSAq IDQpICsgKHN0cmlkZSAqIGNsaXBzLT55MSk7Cj4gPj4rCj4gPj4rCXF4bF9mYl9pbWFnZV9pbml0 KCZxeGxfZmJfaW1hZ2UsIHFkZXYsIGluZm8sIE5VTEwpOwo+ID4+KwlxeGxfZHJhd19vcGFxdWVf ZmIoJnF4bF9mYl9pbWFnZSwgc3RyaWRlKTsKPiA+PisKPiA+PisJcmV0dXJuIDA7Cj4gPj4rfQo+ ID4+Kwo+ID4+K3N0YXRpYyBjb25zdCBzdHJ1Y3QgZHJtX2ZyYW1lYnVmZmVyX2Z1bmNzIHF4bGZi X2ZiX2Z1bmNzID0gewo+ID4+KwkuZGVzdHJveSA9IHF4bF91c2VyX2ZyYW1lYnVmZmVyX2Rlc3Ry b3ksCj4gPj4rCS5kaXJ0eSA9IHF4bGZiX2ZyYW1lYnVmZmVyX2RpcnR5LAo+ID4+K307Cj4gPj4r Cj4gPj4gIHN0YXRpYyBpbnQgcXhsZmJfY3JlYXRlKHN0cnVjdCBxeGxfZmJkZXYgKnFmYmRldiwK PiA+PiAgCQkJc3RydWN0IGRybV9mYl9oZWxwZXJfc3VyZmFjZV9zaXplICpzaXplcykKPiA+PiAg ewo+ID4+QEAgLTM4Myw3ICsyNzEsOCBAQCBzdGF0aWMgaW50IHF4bGZiX2NyZWF0ZShzdHJ1Y3Qg cXhsX2ZiZGV2ICpxZmJkZXYsCj4gPj4gIAlpbmZvLT5wYXIgPSBxZmJkZXY7Cj4gPj4tCXF4bF9m cmFtZWJ1ZmZlcl9pbml0KHFkZXYtPmRkZXYsICZxZmJkZXYtPnFmYiwgJm1vZGVfY21kLCBnb2Jq KTsKPiA+PisJcXhsX2ZyYW1lYnVmZmVyX2luaXQocWRldi0+ZGRldiwgJnFmYmRldi0+cWZiLCAm bW9kZV9jbWQsIGdvYmosCj4gPj4rCQkJICAgICAmcXhsZmJfZmJfZnVuY3MpOwo+ID4+ICAJZmIg PSAmcWZiZGV2LT5xZmIuYmFzZTsKPiA+PkBAIC01MDQsNyArMzkzLDYgQEAgaW50IHF4bF9mYmRl dl9pbml0KHN0cnVjdCBxeGxfZGV2aWNlICpxZGV2KQo+ID4+ICAJcWZiZGV2LT5xZGV2ID0gcWRl djsKPiA+PiAgCXFkZXYtPm1vZGVfaW5mby5xZmJkZXYgPSBxZmJkZXY7Cj4gPj4gIAlzcGluX2xv Y2tfaW5pdCgmcWZiZGV2LT5kZWxheWVkX29wc19sb2NrKTsKPiA+Pi0Jc3Bpbl9sb2NrX2luaXQo JnFmYmRldi0+ZGlydHkubG9jayk7Cj4gPj4gIAlJTklUX0xJU1RfSEVBRCgmcWZiZGV2LT5kZWxh eWVkX29wcyk7Cj4gPj4gIAlkcm1fZmJfaGVscGVyX3ByZXBhcmUocWRldi0+ZGRldiwgJnFmYmRl di0+aGVscGVyLAo+ID4+ZGlmZiAtLWdpdCBhL2RyaXZlcnMvZ3B1L2RybS9xeGwvcXhsX2ttcy5j IGIvZHJpdmVycy9ncHUvZHJtL3F4bC9xeGxfa21zLmMKPiA+PmluZGV4IGIyOTc3YTEuLjIzMTk4 MDAgMTAwNjQ0Cj4gPj4tLS0gYS9kcml2ZXJzL2dwdS9kcm0vcXhsL3F4bF9rbXMuYwo+ID4+Kysr IGIvZHJpdmVycy9ncHUvZHJtL3F4bC9xeGxfa21zLmMKPiA+PkBAIC0yNjEsMTAgKzI2MSw2IEBA IHN0YXRpYyBpbnQgcXhsX2RldmljZV9pbml0KHN0cnVjdCBxeGxfZGV2aWNlICpxZGV2LAo+ID4+ ICAJcWRldi0+Z2NfcXVldWUgPSBjcmVhdGVfc2luZ2xldGhyZWFkX3dvcmtxdWV1ZSgicXhsX2dj Iik7Cj4gPj4gIAlJTklUX1dPUksoJnFkZXYtPmdjX3dvcmssIHF4bF9nY193b3JrKTsKPiA+Pi0J ciA9IHF4bF9mYl9pbml0KHFkZXYpOwo+ID4+LQlpZiAocikKPiA+Pi0JCXJldHVybiByOwo+ID4+ LQo+ID4+ICAJcmV0dXJuIDA7Cj4gPj4gIH0KPiA+Pi0tIAo+ID4+Mi4yLjIKPiA+Pgo+IAo+IF9f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fCj4gZHJpLWRldmVs IG1haWxpbmcgbGlzdAo+IGRyaS1kZXZlbEBsaXN0cy5mcmVlZGVza3RvcC5vcmcKPiBodHRwczov L2xpc3RzLmZyZWVkZXNrdG9wLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2RyaS1kZXZlbAoKLS0gCkRh bmllbCBWZXR0ZXIKU29mdHdhcmUgRW5naW5lZXIsIEludGVsIENvcnBvcmF0aW9uCmh0dHA6Ly9i bG9nLmZmd2xsLmNoCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fCmRyaS1kZXZlbCBtYWlsaW5nIGxpc3QKZHJpLWRldmVsQGxpc3RzLmZyZWVkZXNrdG9wLm9y ZwpodHRwczovL2xpc3RzLmZyZWVkZXNrdG9wLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2RyaS1kZXZl bAo=