--- /dev/null
+From c1d4b38c93069dca6b419a3b88907e01e2c3abf7 Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
+Date: Mon, 28 Sep 2015 18:39:53 +0300
+Subject: drm: rcar-du: Perform initialization/cleanup at probe/remove time
+
+From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
+
+commit c1d4b38c93069dca6b419a3b88907e01e2c3abf7 upstream.
+
+The drm driver .load() operation is prone to race conditions as it
+initializes the driver after registering the device nodes. Its usage is
+deprecated, inline it in the probe function and call drm_dev_alloc() and
+drm_dev_register() explicitly.
+
+For consistency inline the .unload() handler in the remove function as
+well.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
+Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Signed-off-by: Thong Ho <thong.ho.px@rvc.renesas.com>
+Signed-off-by: Nhan Nguyen <nhan.nguyen.yb@renesas.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/rcar-du/rcar_du_drv.c | 187 ++++++++++++++++--------------
+ drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c | 11 -
+ drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c | 11 -
+ drivers/gpu/drm/rcar-du/rcar_du_vgacon.c | 11 -
+ 4 files changed, 106 insertions(+), 114 deletions(-)
+
+--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
++++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+@@ -144,82 +144,6 @@ MODULE_DEVICE_TABLE(of, rcar_du_of_table
+ * DRM operations
+ */
+
+-static int rcar_du_unload(struct drm_device *dev)
+-{
+- struct rcar_du_device *rcdu = dev->dev_private;
+-
+- if (rcdu->fbdev)
+- drm_fbdev_cma_fini(rcdu->fbdev);
+-
+- drm_kms_helper_poll_fini(dev);
+- drm_mode_config_cleanup(dev);
+- drm_vblank_cleanup(dev);
+-
+- dev->irq_enabled = 0;
+- dev->dev_private = NULL;
+-
+- return 0;
+-}
+-
+-static int rcar_du_load(struct drm_device *dev, unsigned long flags)
+-{
+- struct platform_device *pdev = dev->platformdev;
+- struct device_node *np = pdev->dev.of_node;
+- struct rcar_du_device *rcdu;
+- struct resource *mem;
+- int ret;
+-
+- if (np == NULL) {
+- dev_err(dev->dev, "no platform data\n");
+- return -ENODEV;
+- }
+-
+- rcdu = devm_kzalloc(&pdev->dev, sizeof(*rcdu), GFP_KERNEL);
+- if (rcdu == NULL) {
+- dev_err(dev->dev, "failed to allocate private data\n");
+- return -ENOMEM;
+- }
+-
+- init_waitqueue_head(&rcdu->commit.wait);
+-
+- rcdu->dev = &pdev->dev;
+- rcdu->info = of_match_device(rcar_du_of_table, rcdu->dev)->data;
+- rcdu->ddev = dev;
+- dev->dev_private = rcdu;
+-
+- /* I/O resources */
+- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+- rcdu->mmio = devm_ioremap_resource(&pdev->dev, mem);
+- if (IS_ERR(rcdu->mmio))
+- return PTR_ERR(rcdu->mmio);
+-
+- /* Initialize vertical blanking interrupts handling. Start with vblank
+- * disabled for all CRTCs.
+- */
+- ret = drm_vblank_init(dev, (1 << rcdu->info->num_crtcs) - 1);
+- if (ret < 0) {
+- dev_err(&pdev->dev, "failed to initialize vblank\n");
+- goto done;
+- }
+-
+- /* DRM/KMS objects */
+- ret = rcar_du_modeset_init(rcdu);
+- if (ret < 0) {
+- dev_err(&pdev->dev, "failed to initialize DRM/KMS (%d)\n", ret);
+- goto done;
+- }
+-
+- dev->irq_enabled = 1;
+-
+- platform_set_drvdata(pdev, rcdu);
+-
+-done:
+- if (ret)
+- rcar_du_unload(dev);
+-
+- return ret;
+-}
+-
+ static void rcar_du_lastclose(struct drm_device *dev)
+ {
+ struct rcar_du_device *rcdu = dev->dev_private;
+@@ -260,10 +184,7 @@ static const struct file_operations rcar
+ static struct drm_driver rcar_du_driver = {
+ .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME
+ | DRIVER_ATOMIC,
+- .load = rcar_du_load,
+- .unload = rcar_du_unload,
+ .lastclose = rcar_du_lastclose,
+- .set_busid = drm_platform_set_busid,
+ .get_vblank_counter = drm_vblank_no_hw_counter,
+ .enable_vblank = rcar_du_enable_vblank,
+ .disable_vblank = rcar_du_disable_vblank,
+@@ -323,18 +244,116 @@ static const struct dev_pm_ops rcar_du_p
+ * Platform driver
+ */
+
+-static int rcar_du_probe(struct platform_device *pdev)
++static int rcar_du_remove(struct platform_device *pdev)
+ {
+- return drm_platform_init(&rcar_du_driver, pdev);
++ struct rcar_du_device *rcdu = platform_get_drvdata(pdev);
++ struct drm_device *ddev = rcdu->ddev;
++
++ mutex_lock(&ddev->mode_config.mutex);
++ drm_connector_unplug_all(ddev);
++ mutex_unlock(&ddev->mode_config.mutex);
++
++ drm_dev_unregister(ddev);
++
++ if (rcdu->fbdev)
++ drm_fbdev_cma_fini(rcdu->fbdev);
++
++ drm_kms_helper_poll_fini(ddev);
++ drm_mode_config_cleanup(ddev);
++ drm_vblank_cleanup(ddev);
++
++ drm_dev_unref(ddev);
++
++ return 0;
+ }
+
+-static int rcar_du_remove(struct platform_device *pdev)
++static int rcar_du_probe(struct platform_device *pdev)
+ {
+- struct rcar_du_device *rcdu = platform_get_drvdata(pdev);
++ struct device_node *np = pdev->dev.of_node;
++ struct rcar_du_device *rcdu;
++ struct drm_connector *connector;
++ struct drm_device *ddev;
++ struct resource *mem;
++ int ret;
++
++ if (np == NULL) {
++ dev_err(&pdev->dev, "no device tree node\n");
++ return -ENODEV;
++ }
++
++ /* Allocate and initialize the DRM and R-Car device structures. */
++ rcdu = devm_kzalloc(&pdev->dev, sizeof(*rcdu), GFP_KERNEL);
++ if (rcdu == NULL)
++ return -ENOMEM;
++
++ init_waitqueue_head(&rcdu->commit.wait);
++
++ rcdu->dev = &pdev->dev;
++ rcdu->info = of_match_device(rcar_du_of_table, rcdu->dev)->data;
++
++ ddev = drm_dev_alloc(&rcar_du_driver, &pdev->dev);
++ if (!ddev)
++ return -ENOMEM;
++
++ drm_dev_set_unique(ddev, dev_name(&pdev->dev));
++
++ rcdu->ddev = ddev;
++ ddev->dev_private = rcdu;
+
+- drm_put_dev(rcdu->ddev);
++ platform_set_drvdata(pdev, rcdu);
++
++ /* I/O resources */
++ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ rcdu->mmio = devm_ioremap_resource(&pdev->dev, mem);
++ if (IS_ERR(rcdu->mmio)) {
++ ret = PTR_ERR(rcdu->mmio);
++ goto error;
++ }
++
++ /* Initialize vertical blanking interrupts handling. Start with vblank
++ * disabled for all CRTCs.
++ */
++ ret = drm_vblank_init(ddev, (1 << rcdu->info->num_crtcs) - 1);
++ if (ret < 0) {
++ dev_err(&pdev->dev, "failed to initialize vblank\n");
++ goto error;
++ }
++
++ /* DRM/KMS objects */
++ ret = rcar_du_modeset_init(rcdu);
++ if (ret < 0) {
++ dev_err(&pdev->dev, "failed to initialize DRM/KMS (%d)\n", ret);
++ goto error;
++ }
++
++ ddev->irq_enabled = 1;
++
++ /* Register the DRM device with the core and the connectors with
++ * sysfs.
++ */
++ ret = drm_dev_register(ddev, 0);
++ if (ret)
++ goto error;
++
++ mutex_lock(&ddev->mode_config.mutex);
++ drm_for_each_connector(connector, ddev) {
++ ret = drm_connector_register(connector);
++ if (ret < 0)
++ break;
++ }
++ mutex_unlock(&ddev->mode_config.mutex);
++
++ if (ret < 0)
++ goto error;
++
++ DRM_INFO("Device %s probed\n", dev_name(&pdev->dev));
+
+ return 0;
++
++error:
++ rcar_du_remove(pdev);
++
++ return ret;
+ }
+
+ static struct platform_driver rcar_du_platform_driver = {
+--- a/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c
++++ b/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c
+@@ -55,12 +55,6 @@ static const struct drm_connector_helper
+ .best_encoder = rcar_du_connector_best_encoder,
+ };
+
+-static void rcar_du_hdmi_connector_destroy(struct drm_connector *connector)
+-{
+- drm_connector_unregister(connector);
+- drm_connector_cleanup(connector);
+-}
+-
+ static enum drm_connector_status
+ rcar_du_hdmi_connector_detect(struct drm_connector *connector, bool force)
+ {
+@@ -79,7 +73,7 @@ static const struct drm_connector_funcs
+ .reset = drm_atomic_helper_connector_reset,
+ .detect = rcar_du_hdmi_connector_detect,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+- .destroy = rcar_du_hdmi_connector_destroy,
++ .destroy = drm_connector_cleanup,
+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+ };
+@@ -108,9 +102,6 @@ int rcar_du_hdmi_connector_init(struct r
+ return ret;
+
+ drm_connector_helper_add(connector, &connector_helper_funcs);
+- ret = drm_connector_register(connector);
+- if (ret < 0)
+- return ret;
+
+ connector->dpms = DRM_MODE_DPMS_OFF;
+ drm_object_property_set_value(&connector->base,
+--- a/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c
++++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c
+@@ -62,12 +62,6 @@ static const struct drm_connector_helper
+ .best_encoder = rcar_du_connector_best_encoder,
+ };
+
+-static void rcar_du_lvds_connector_destroy(struct drm_connector *connector)
+-{
+- drm_connector_unregister(connector);
+- drm_connector_cleanup(connector);
+-}
+-
+ static enum drm_connector_status
+ rcar_du_lvds_connector_detect(struct drm_connector *connector, bool force)
+ {
+@@ -79,7 +73,7 @@ static const struct drm_connector_funcs
+ .reset = drm_atomic_helper_connector_reset,
+ .detect = rcar_du_lvds_connector_detect,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+- .destroy = rcar_du_lvds_connector_destroy,
++ .destroy = drm_connector_cleanup,
+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+ };
+@@ -117,9 +111,6 @@ int rcar_du_lvds_connector_init(struct r
+ return ret;
+
+ drm_connector_helper_add(connector, &connector_helper_funcs);
+- ret = drm_connector_register(connector);
+- if (ret < 0)
+- return ret;
+
+ connector->dpms = DRM_MODE_DPMS_OFF;
+ drm_object_property_set_value(&connector->base,
+--- a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
++++ b/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
+@@ -31,12 +31,6 @@ static const struct drm_connector_helper
+ .best_encoder = rcar_du_connector_best_encoder,
+ };
+
+-static void rcar_du_vga_connector_destroy(struct drm_connector *connector)
+-{
+- drm_connector_unregister(connector);
+- drm_connector_cleanup(connector);
+-}
+-
+ static enum drm_connector_status
+ rcar_du_vga_connector_detect(struct drm_connector *connector, bool force)
+ {
+@@ -48,7 +42,7 @@ static const struct drm_connector_funcs
+ .reset = drm_atomic_helper_connector_reset,
+ .detect = rcar_du_vga_connector_detect,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+- .destroy = rcar_du_vga_connector_destroy,
++ .destroy = drm_connector_cleanup,
+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+ };
+@@ -76,9 +70,6 @@ int rcar_du_vga_connector_init(struct rc
+ return ret;
+
+ drm_connector_helper_add(connector, &connector_helper_funcs);
+- ret = drm_connector_register(connector);
+- if (ret < 0)
+- return ret;
+
+ connector->dpms = DRM_MODE_DPMS_OFF;
+ drm_object_property_set_value(&connector->base,
--- /dev/null
+From 4f7b0d263833928e947e172eff2d2997179c5cb9 Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
+Date: Wed, 19 Oct 2016 00:51:35 +0300
+Subject: drm: rcar-du: Simplify and fix probe error handling
+
+From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
+
+commit 4f7b0d263833928e947e172eff2d2997179c5cb9 upstream.
+
+It isn't safe to call drm_dev_unregister() without first initializing
+mode setting with drm_mode_config_init(). This leads to a crash if
+either IO memory can't be remapped or vblank initialization fails.
+
+Fix this by reordering the initialization sequence. Move vblank
+initialization after the drm_mode_config_init() call, and move IO
+remapping before drm_dev_alloc() to avoid the need to perform clean up
+in case of failure.
+
+While at it remove the explicit drm_vblank_cleanup() call from
+rcar_du_remove() as the drm_dev_unregister() function already cleans up
+vblank.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
+Signed-off-by: thongsyho <thong.ho.px@rvc.renesas.com>
+Signed-off-by: Nhan Nguyen <nhan.nguyen.yb@renesas.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/rcar-du/rcar_du_drv.c | 30 +++++++++---------------------
+ drivers/gpu/drm/rcar-du/rcar_du_kms.c | 7 +++++++
+ 2 files changed, 16 insertions(+), 21 deletions(-)
+
+--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
++++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+@@ -260,7 +260,6 @@ static int rcar_du_remove(struct platfor
+
+ drm_kms_helper_poll_fini(ddev);
+ drm_mode_config_cleanup(ddev);
+- drm_vblank_cleanup(ddev);
+
+ drm_dev_unref(ddev);
+
+@@ -291,6 +290,15 @@ static int rcar_du_probe(struct platform
+ rcdu->dev = &pdev->dev;
+ rcdu->info = of_match_device(rcar_du_of_table, rcdu->dev)->data;
+
++ platform_set_drvdata(pdev, rcdu);
++
++ /* I/O resources */
++ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ rcdu->mmio = devm_ioremap_resource(&pdev->dev, mem);
++ if (IS_ERR(rcdu->mmio))
++ ret = PTR_ERR(rcdu->mmio);
++
++ /* DRM/KMS objects */
+ ddev = drm_dev_alloc(&rcar_du_driver, &pdev->dev);
+ if (!ddev)
+ return -ENOMEM;
+@@ -300,26 +308,6 @@ static int rcar_du_probe(struct platform
+ rcdu->ddev = ddev;
+ ddev->dev_private = rcdu;
+
+- platform_set_drvdata(pdev, rcdu);
+-
+- /* I/O resources */
+- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+- rcdu->mmio = devm_ioremap_resource(&pdev->dev, mem);
+- if (IS_ERR(rcdu->mmio)) {
+- ret = PTR_ERR(rcdu->mmio);
+- goto error;
+- }
+-
+- /* Initialize vertical blanking interrupts handling. Start with vblank
+- * disabled for all CRTCs.
+- */
+- ret = drm_vblank_init(ddev, (1 << rcdu->info->num_crtcs) - 1);
+- if (ret < 0) {
+- dev_err(&pdev->dev, "failed to initialize vblank\n");
+- goto error;
+- }
+-
+- /* DRM/KMS objects */
+ ret = rcar_du_modeset_init(rcdu);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to initialize DRM/KMS (%d)\n", ret);
+--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
++++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+@@ -761,6 +761,13 @@ int rcar_du_modeset_init(struct rcar_du_
+ if (ret < 0)
+ return ret;
+
++ /* Initialize vertical blanking interrupts handling. Start with vblank
++ * disabled for all CRTCs.
++ */
++ ret = drm_vblank_init(dev, (1 << rcdu->info->num_crtcs) - 1);
++ if (ret < 0)
++ return ret;
++
+ /* Initialize the groups. */
+ num_groups = DIV_ROUND_UP(rcdu->num_crtcs, 2);
+
--- /dev/null
+From 0a346629f5304a8390004a91e8d4f1206b87792b Mon Sep 17 00:00:00 2001
+From: Daniel Vetter <daniel.vetter@ffwll.ch>
+Date: Mon, 25 Jan 2016 22:16:51 +0100
+Subject: drm/rcar: Nuke preclose hook
+
+From: Daniel Vetter <daniel.vetter@ffwll.ch>
+
+commit 0a346629f5304a8390004a91e8d4f1206b87792b upstream.
+
+Again since the drm core takes care of event unlinking/disarming this
+is now just needless code.
+
+Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Acked-by: Daniel Stone <daniels@collabora.com>
+Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
+Link: http://patchwork.freedesktop.org/patch/msgid/1453756616-28942-10-git-send-email-daniel.vetter@ffwll.ch
+Signed-off-by: Nhan Nguyen <nhan.nguyen.yb@renesas.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 20 --------------------
+ drivers/gpu/drm/rcar-du/rcar_du_crtc.h | 2 --
+ drivers/gpu/drm/rcar-du/rcar_du_drv.c | 10 ----------
+ 3 files changed, 32 deletions(-)
+
+--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
++++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+@@ -282,26 +282,6 @@ static void rcar_du_crtc_update_planes(s
+ * Page Flip
+ */
+
+-void rcar_du_crtc_cancel_page_flip(struct rcar_du_crtc *rcrtc,
+- struct drm_file *file)
+-{
+- struct drm_pending_vblank_event *event;
+- struct drm_device *dev = rcrtc->crtc.dev;
+- unsigned long flags;
+-
+- /* Destroy the pending vertical blanking event associated with the
+- * pending page flip, if any, and disable vertical blanking interrupts.
+- */
+- spin_lock_irqsave(&dev->event_lock, flags);
+- event = rcrtc->event;
+- if (event && event->base.file_priv == file) {
+- rcrtc->event = NULL;
+- event->base.destroy(&event->base);
+- drm_crtc_vblank_put(&rcrtc->crtc);
+- }
+- spin_unlock_irqrestore(&dev->event_lock, flags);
+-}
+-
+ static void rcar_du_crtc_finish_page_flip(struct rcar_du_crtc *rcrtc)
+ {
+ struct drm_pending_vblank_event *event;
+--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
++++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
+@@ -67,8 +67,6 @@ enum rcar_du_output {
+
+ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index);
+ void rcar_du_crtc_enable_vblank(struct rcar_du_crtc *rcrtc, bool enable);
+-void rcar_du_crtc_cancel_page_flip(struct rcar_du_crtc *rcrtc,
+- struct drm_file *file);
+ void rcar_du_crtc_suspend(struct rcar_du_crtc *rcrtc);
+ void rcar_du_crtc_resume(struct rcar_du_crtc *rcrtc);
+
+--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
++++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+@@ -220,15 +220,6 @@ done:
+ return ret;
+ }
+
+-static void rcar_du_preclose(struct drm_device *dev, struct drm_file *file)
+-{
+- struct rcar_du_device *rcdu = dev->dev_private;
+- unsigned int i;
+-
+- for (i = 0; i < rcdu->num_crtcs; ++i)
+- rcar_du_crtc_cancel_page_flip(&rcdu->crtcs[i], file);
+-}
+-
+ static void rcar_du_lastclose(struct drm_device *dev)
+ {
+ struct rcar_du_device *rcdu = dev->dev_private;
+@@ -271,7 +262,6 @@ static struct drm_driver rcar_du_driver
+ | DRIVER_ATOMIC,
+ .load = rcar_du_load,
+ .unload = rcar_du_unload,
+- .preclose = rcar_du_preclose,
+ .lastclose = rcar_du_lastclose,
+ .set_busid = drm_platform_set_busid,
+ .get_vblank_counter = drm_vblank_no_hw_counter,
--- /dev/null
+From f952eaceb089b691eba7c4e13686e742a8f26bf5 Mon Sep 17 00:00:00 2001
+From: Adrian Hunter <adrian.hunter@intel.com>
+Date: Fri, 26 May 2017 11:17:07 +0300
+Subject: perf intel-pt: Ensure never to set 'last_ip' when packet 'count' is zero
+
+From: Adrian Hunter <adrian.hunter@intel.com>
+
+commit f952eaceb089b691eba7c4e13686e742a8f26bf5 upstream.
+
+Intel PT uses IP compression based on the last IP. For decoding purposes,
+'last IP' is not updated when a branch target has been suppressed, which is
+indicated by IPBytes == 0. IPBytes is stored in the packet 'count', so
+ensure never to set 'last_ip' when packet 'count' is zero.
+
+Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Andi Kleen <ak@linux.intel.com>
+Link: http://lkml.kernel.org/r/1495786658-18063-7-git-send-email-adrian.hunter@intel.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ tools/perf/util/intel-pt-decoder/intel-pt-decoder.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
++++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+@@ -1438,7 +1438,8 @@ static int intel_pt_walk_psbend(struct i
+
+ case INTEL_PT_FUP:
+ decoder->pge = true;
+- intel_pt_set_last_ip(decoder);
++ if (decoder->packet.count)
++ intel_pt_set_last_ip(decoder);
+ break;
+
+ case INTEL_PT_MODE_TSX:
+@@ -1724,8 +1725,9 @@ next:
+
+ static inline bool intel_pt_have_ip(struct intel_pt_decoder *decoder)
+ {
+- return decoder->have_last_ip || decoder->packet.count == 0 ||
+- decoder->packet.count == 3 || decoder->packet.count == 6;
++ return decoder->packet.count &&
++ (decoder->have_last_ip || decoder->packet.count == 3 ||
++ decoder->packet.count == 6);
+ }
+
+ /* Walk PSB+ packets to get in sync. */
--- /dev/null
+From e1717e0485af4f47fc4da1e979ac817f9ad61b0f Mon Sep 17 00:00:00 2001
+From: Adrian Hunter <adrian.hunter@intel.com>
+Date: Wed, 20 Jul 2016 12:00:06 +0300
+Subject: perf intel-pt: Fix ip compression
+
+From: Adrian Hunter <adrian.hunter@intel.com>
+
+commit e1717e0485af4f47fc4da1e979ac817f9ad61b0f upstream.
+
+The June 2015 Intel SDM introduced IP Compression types 4 and 6. Refer
+to section 36.4.2.2 Target IP (TIP) Packet - IP Compression.
+
+Existing Intel PT packet decoder did not support type 4, and got type 6
+wrong. Because type 3 and type 4 have the same number of bytes, the
+packet 'count' has been changed from being the number of ip bytes to
+being the type code. That allows the Intel PT decoder to correctly
+decide whether to sign-extend or use the last ip. However that also
+meant the code had to be adjusted in a number of places.
+
+Currently hardware is not using the new compression types, so this fix
+has no effect on existing hardware.
+
+Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Jiri Olsa <jolsa@redhat.com>
+Link: http://lkml.kernel.org/r/1469005206-3049-1-git-send-email-adrian.hunter@intel.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ tools/perf/util/intel-pt-decoder/intel-pt-decoder.c | 44 ++++++++--------
+ tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c | 24 ++++++--
+ 2 files changed, 40 insertions(+), 28 deletions(-)
+
+--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
++++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+@@ -145,8 +145,6 @@ struct intel_pt_decoder {
+ bool have_calc_cyc_to_tsc;
+ int exec_mode;
+ unsigned int insn_bytes;
+- uint64_t sign_bit;
+- uint64_t sign_bits;
+ uint64_t period;
+ enum intel_pt_period_type period_type;
+ uint64_t tot_insn_cnt;
+@@ -214,9 +212,6 @@ struct intel_pt_decoder *intel_pt_decode
+ decoder->data = params->data;
+ decoder->return_compression = params->return_compression;
+
+- decoder->sign_bit = (uint64_t)1 << 47;
+- decoder->sign_bits = ~(((uint64_t)1 << 48) - 1);
+-
+ decoder->period = params->period;
+ decoder->period_type = params->period_type;
+
+@@ -385,21 +380,30 @@ int intel_pt__strerror(int code, char *b
+ return 0;
+ }
+
+-static uint64_t intel_pt_calc_ip(struct intel_pt_decoder *decoder,
+- const struct intel_pt_pkt *packet,
++static uint64_t intel_pt_calc_ip(const struct intel_pt_pkt *packet,
+ uint64_t last_ip)
+ {
+ uint64_t ip;
+
+ switch (packet->count) {
+- case 2:
++ case 1:
+ ip = (last_ip & (uint64_t)0xffffffffffff0000ULL) |
+ packet->payload;
+ break;
+- case 4:
++ case 2:
+ ip = (last_ip & (uint64_t)0xffffffff00000000ULL) |
+ packet->payload;
+ break;
++ case 3:
++ ip = packet->payload;
++ /* Sign-extend 6-byte ip */
++ if (ip & (uint64_t)0x800000000000ULL)
++ ip |= (uint64_t)0xffff000000000000ULL;
++ break;
++ case 4:
++ ip = (last_ip & (uint64_t)0xffff000000000000ULL) |
++ packet->payload;
++ break;
+ case 6:
+ ip = packet->payload;
+ break;
+@@ -407,16 +411,12 @@ static uint64_t intel_pt_calc_ip(struct
+ return 0;
+ }
+
+- if (ip & decoder->sign_bit)
+- return ip | decoder->sign_bits;
+-
+ return ip;
+ }
+
+ static inline void intel_pt_set_last_ip(struct intel_pt_decoder *decoder)
+ {
+- decoder->last_ip = intel_pt_calc_ip(decoder, &decoder->packet,
+- decoder->last_ip);
++ decoder->last_ip = intel_pt_calc_ip(&decoder->packet, decoder->last_ip);
+ }
+
+ static inline void intel_pt_set_ip(struct intel_pt_decoder *decoder)
+@@ -1718,6 +1718,12 @@ next:
+ }
+ }
+
++static inline bool intel_pt_have_ip(struct intel_pt_decoder *decoder)
++{
++ return decoder->last_ip || decoder->packet.count == 0 ||
++ decoder->packet.count == 3 || decoder->packet.count == 6;
++}
++
+ /* Walk PSB+ packets to get in sync. */
+ static int intel_pt_walk_psb(struct intel_pt_decoder *decoder)
+ {
+@@ -1739,8 +1745,7 @@ static int intel_pt_walk_psb(struct inte
+
+ case INTEL_PT_FUP:
+ decoder->pge = true;
+- if (decoder->last_ip || decoder->packet.count == 6 ||
+- decoder->packet.count == 0) {
++ if (intel_pt_have_ip(decoder)) {
+ uint64_t current_ip = decoder->ip;
+
+ intel_pt_set_ip(decoder);
+@@ -1832,8 +1837,7 @@ static int intel_pt_walk_to_ip(struct in
+ case INTEL_PT_TIP_PGE:
+ case INTEL_PT_TIP:
+ decoder->pge = decoder->packet.type != INTEL_PT_TIP_PGD;
+- if (decoder->last_ip || decoder->packet.count == 6 ||
+- decoder->packet.count == 0)
++ if (intel_pt_have_ip(decoder))
+ intel_pt_set_ip(decoder);
+ if (decoder->ip)
+ return 0;
+@@ -1841,9 +1845,7 @@ static int intel_pt_walk_to_ip(struct in
+
+ case INTEL_PT_FUP:
+ if (decoder->overflow) {
+- if (decoder->last_ip ||
+- decoder->packet.count == 6 ||
+- decoder->packet.count == 0)
++ if (intel_pt_have_ip(decoder))
+ intel_pt_set_ip(decoder);
+ if (decoder->ip)
+ return 0;
+--- a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c
++++ b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c
+@@ -293,36 +293,46 @@ static int intel_pt_get_ip(enum intel_pt
+ const unsigned char *buf, size_t len,
+ struct intel_pt_pkt *packet)
+ {
+- switch (byte >> 5) {
++ int ip_len;
++
++ packet->count = byte >> 5;
++
++ switch (packet->count) {
+ case 0:
+- packet->count = 0;
++ ip_len = 0;
+ break;
+ case 1:
+ if (len < 3)
+ return INTEL_PT_NEED_MORE_BYTES;
+- packet->count = 2;
++ ip_len = 2;
+ packet->payload = le16_to_cpu(*(uint16_t *)(buf + 1));
+ break;
+ case 2:
+ if (len < 5)
+ return INTEL_PT_NEED_MORE_BYTES;
+- packet->count = 4;
++ ip_len = 4;
+ packet->payload = le32_to_cpu(*(uint32_t *)(buf + 1));
+ break;
+ case 3:
+- case 6:
++ case 4:
+ if (len < 7)
+ return INTEL_PT_NEED_MORE_BYTES;
+- packet->count = 6;
++ ip_len = 6;
+ memcpy_le64(&packet->payload, buf + 1, 6);
+ break;
++ case 6:
++ if (len < 9)
++ return INTEL_PT_NEED_MORE_BYTES;
++ ip_len = 8;
++ packet->payload = le64_to_cpu(*(uint64_t *)(buf + 1));
++ break;
+ default:
+ return INTEL_PT_BAD_PACKET;
+ }
+
+ packet->type = type;
+
+- return packet->count + 1;
++ return ip_len + 1;
+ }
+
+ static int intel_pt_get_mode(const unsigned char *buf, size_t len,
--- /dev/null
+From ee14ac0ef6827cd6f9a572cc83dd0191ea17812c Mon Sep 17 00:00:00 2001
+From: Adrian Hunter <adrian.hunter@intel.com>
+Date: Fri, 26 May 2017 11:17:06 +0300
+Subject: perf intel-pt: Fix last_ip usage
+
+From: Adrian Hunter <adrian.hunter@intel.com>
+
+commit ee14ac0ef6827cd6f9a572cc83dd0191ea17812c upstream.
+
+Intel PT uses IP compression based on the last IP. For decoding
+purposes, 'last IP' is considered to be reset to zero whenever there is
+a synchronization packet (PSB). The decoder wasn't doing that, and was
+treating the zero value to mean that there was no last IP, whereas
+compression can be done against the zero value. Fix by setting last_ip
+to zero when a PSB is received and keep track of have_last_ip.
+
+Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Andi Kleen <ak@linux.intel.com>
+Link: http://lkml.kernel.org/r/1495786658-18063-6-git-send-email-adrian.hunter@intel.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ tools/perf/util/intel-pt-decoder/intel-pt-decoder.c | 13 +++++++++++--
+ 1 file changed, 11 insertions(+), 2 deletions(-)
+
+--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
++++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+@@ -110,6 +110,7 @@ struct intel_pt_decoder {
+ bool have_tma;
+ bool have_cyc;
+ bool fixup_last_mtc;
++ bool have_last_ip;
+ uint64_t pos;
+ uint64_t last_ip;
+ uint64_t ip;
+@@ -417,6 +418,7 @@ static uint64_t intel_pt_calc_ip(const s
+ static inline void intel_pt_set_last_ip(struct intel_pt_decoder *decoder)
+ {
+ decoder->last_ip = intel_pt_calc_ip(&decoder->packet, decoder->last_ip);
++ decoder->have_last_ip = true;
+ }
+
+ static inline void intel_pt_set_ip(struct intel_pt_decoder *decoder)
+@@ -1640,6 +1642,8 @@ next:
+ break;
+
+ case INTEL_PT_PSB:
++ decoder->last_ip = 0;
++ decoder->have_last_ip = true;
+ intel_pt_clear_stack(&decoder->stack);
+ err = intel_pt_walk_psbend(decoder);
+ if (err == -EAGAIN)
+@@ -1720,7 +1724,7 @@ next:
+
+ static inline bool intel_pt_have_ip(struct intel_pt_decoder *decoder)
+ {
+- return decoder->last_ip || decoder->packet.count == 0 ||
++ return decoder->have_last_ip || decoder->packet.count == 0 ||
+ decoder->packet.count == 3 || decoder->packet.count == 6;
+ }
+
+@@ -1850,7 +1854,7 @@ static int intel_pt_walk_to_ip(struct in
+ if (decoder->ip)
+ return 0;
+ }
+- if (decoder->packet.count)
++ if (decoder->packet.count && decoder->have_last_ip)
+ intel_pt_set_last_ip(decoder);
+ break;
+
+@@ -1900,6 +1904,8 @@ static int intel_pt_walk_to_ip(struct in
+ break;
+
+ case INTEL_PT_PSB:
++ decoder->last_ip = 0;
++ decoder->have_last_ip = true;
+ intel_pt_clear_stack(&decoder->stack);
+ err = intel_pt_walk_psb(decoder);
+ if (err)
+@@ -2036,6 +2042,7 @@ static int intel_pt_sync(struct intel_pt
+
+ decoder->pge = false;
+ decoder->continuous_period = false;
++ decoder->have_last_ip = false;
+ decoder->last_ip = 0;
+ decoder->ip = 0;
+ intel_pt_clear_stack(&decoder->stack);
+@@ -2044,6 +2051,7 @@ static int intel_pt_sync(struct intel_pt
+ if (err)
+ return err;
+
++ decoder->have_last_ip = true;
+ decoder->pkt_state = INTEL_PT_STATE_NO_IP;
+
+ err = intel_pt_walk_psb(decoder);
+@@ -2086,6 +2094,7 @@ const struct intel_pt_state *intel_pt_de
+ err = intel_pt_sync(decoder);
+ break;
+ case INTEL_PT_STATE_NO_IP:
++ decoder->have_last_ip = false;
+ decoder->last_ip = 0;
+ decoder->ip = 0;
+ /* Fall through */
--- /dev/null
+From 622b7a47b843c78626f40c1d1aeef8483383fba2 Mon Sep 17 00:00:00 2001
+From: Adrian Hunter <adrian.hunter@intel.com>
+Date: Fri, 26 May 2017 11:17:08 +0300
+Subject: perf intel-pt: Use FUP always when scanning for an IP
+
+From: Adrian Hunter <adrian.hunter@intel.com>
+
+commit 622b7a47b843c78626f40c1d1aeef8483383fba2 upstream.
+
+The decoder will try to use branch packets to find an IP to start decoding
+or to recover from errors. Currently the FUP packet is used only in the
+case of an overflow, however there is no reason for that to be a special
+case. So just use FUP always when scanning for an IP.
+
+Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Andi Kleen <ak@linux.intel.com>
+Link: http://lkml.kernel.org/r/1495786658-18063-8-git-send-email-adrian.hunter@intel.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ tools/perf/util/intel-pt-decoder/intel-pt-decoder.c | 12 ++++--------
+ 1 file changed, 4 insertions(+), 8 deletions(-)
+
+--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
++++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+@@ -1848,14 +1848,10 @@ static int intel_pt_walk_to_ip(struct in
+ break;
+
+ case INTEL_PT_FUP:
+- if (decoder->overflow) {
+- if (intel_pt_have_ip(decoder))
+- intel_pt_set_ip(decoder);
+- if (decoder->ip)
+- return 0;
+- }
+- if (decoder->packet.count && decoder->have_last_ip)
+- intel_pt_set_last_ip(decoder);
++ if (intel_pt_have_ip(decoder))
++ intel_pt_set_ip(decoder);
++ if (decoder->ip)
++ return 0;
+ break;
+
+ case INTEL_PT_MTC:
kvm-ppc-book3s-hv-save-restore-host-values-of-debug-registers.patch
revert-powerpc-numa-fix-percpu-allocations-to-be-numa-aware.patch
staging-comedi-comedi_fops-avoid-orphaned-proc-entry.patch
+drm-rcar-nuke-preclose-hook.patch
+drm-rcar-du-perform-initialization-cleanup-at-probe-remove-time.patch
+drm-rcar-du-simplify-and-fix-probe-error-handling.patch
+perf-intel-pt-fix-ip-compression.patch
+perf-intel-pt-fix-last_ip-usage.patch
+perf-intel-pt-use-fup-always-when-scanning-for-an-ip.patch
+perf-intel-pt-ensure-never-to-set-last_ip-when-packet-count-is-zero.patch
+xfs-don-t-bug-on-mixed-direct-and-mapped-i-o.patch
--- /dev/null
+From 04197b341f23b908193308b8d63d17ff23232598 Mon Sep 17 00:00:00 2001
+From: Brian Foster <bfoster@redhat.com>
+Date: Tue, 8 Nov 2016 12:54:14 +1100
+Subject: xfs: don't BUG() on mixed direct and mapped I/O
+
+From: Brian Foster <bfoster@redhat.com>
+
+commit 04197b341f23b908193308b8d63d17ff23232598 upstream.
+
+We've had reports of generic/095 causing XFS to BUG() in
+__xfs_get_blocks() due to the existence of delalloc blocks on a
+direct I/O read. generic/095 issues a mix of various types of I/O,
+including direct and memory mapped I/O to a single file. This is
+clearly not supported behavior and is known to lead to such
+problems. E.g., the lack of exclusion between the direct I/O and
+write fault paths means that a write fault can allocate delalloc
+blocks in a region of a file that was previously a hole after the
+direct read has attempted to flush/inval the file range, but before
+it actually reads the block mapping. In turn, the direct read
+discovers a delalloc extent and cannot proceed.
+
+While the appropriate solution here is to not mix direct and memory
+mapped I/O to the same regions of the same file, the current
+BUG_ON() behavior is probably overkill as it can crash the entire
+system. Instead, localize the failure to the I/O in question by
+returning an error for a direct I/O that cannot be handled safely
+due to delalloc blocks. Be careful to allow the case of a direct
+write to post-eof delalloc blocks. This can occur due to speculative
+preallocation and is safe as post-eof blocks are not accompanied by
+dirty pages in pagecache (conversely, preallocation within eof must
+have been zeroed, and thus dirtied, before the inode size could have
+been increased beyond said blocks).
+
+Finally, provide an additional warning if a direct I/O write occurs
+while the file is memory mapped. This may not catch all problematic
+scenarios, but provides a hint that some known-to-be-problematic I/O
+methods are in use.
+
+Signed-off-by: Brian Foster <bfoster@redhat.com>
+Reviewed-by: Dave Chinner <dchinner@redhat.com>
+Signed-off-by: Dave Chinner <david@fromorbit.com>
+Signed-off-by: Nikolay Borisov <nborisov@suse.com>
+Acked-by: Darrick J. Wong <darrick.wong@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+
+---
+ fs/xfs/xfs_aops.c | 21 ++++++++++++++++++++-
+ 1 file changed, 20 insertions(+), 1 deletion(-)
+
+--- a/fs/xfs/xfs_aops.c
++++ b/fs/xfs/xfs_aops.c
+@@ -1426,6 +1426,26 @@ __xfs_get_blocks(
+ if (error)
+ goto out_unlock;
+
++ /*
++ * The only time we can ever safely find delalloc blocks on direct I/O
++ * is a dio write to post-eof speculative preallocation. All other
++ * scenarios are indicative of a problem or misuse (such as mixing
++ * direct and mapped I/O).
++ *
++ * The file may be unmapped by the time we get here so we cannot
++ * reliably fail the I/O based on mapping. Instead, fail the I/O if this
++ * is a read or a write within eof. Otherwise, carry on but warn as a
++ * precuation if the file happens to be mapped.
++ */
++ if (direct && imap.br_startblock == DELAYSTARTBLOCK) {
++ if (!create || offset < i_size_read(VFS_I(ip))) {
++ WARN_ON_ONCE(1);
++ error = -EIO;
++ goto out_unlock;
++ }
++ WARN_ON_ONCE(mapping_mapped(VFS_I(ip)->i_mapping));
++ }
++
+ /* for DAX, we convert unwritten extents directly */
+ if (create &&
+ (!nimaps ||
+@@ -1525,7 +1545,6 @@ __xfs_get_blocks(
+ set_buffer_new(bh_result);
+
+ if (imap.br_startblock == DELAYSTARTBLOCK) {
+- BUG_ON(direct);
+ if (create) {
+ set_buffer_uptodate(bh_result);
+ set_buffer_mapped(bh_result);