From: Greg Kroah-Hartman Date: Thu, 3 Aug 2017 21:56:39 +0000 (-0700) Subject: 4.4-stable patches X-Git-Tag: v4.12.5~35 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=90cc6ea8ca49eb61bb5f0e4d5dafc315d3be432f;p=thirdparty%2Fkernel%2Fstable-queue.git 4.4-stable patches added patches: drm-rcar-du-perform-initialization-cleanup-at-probe-remove-time.patch drm-rcar-du-simplify-and-fix-probe-error-handling.patch drm-rcar-nuke-preclose-hook.patch perf-intel-pt-ensure-never-to-set-last_ip-when-packet-count-is-zero.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 xfs-don-t-bug-on-mixed-direct-and-mapped-i-o.patch --- diff --git a/queue-4.4/drm-rcar-du-perform-initialization-cleanup-at-probe-remove-time.patch b/queue-4.4/drm-rcar-du-perform-initialization-cleanup-at-probe-remove-time.patch new file mode 100644 index 00000000000..1ec89a49904 --- /dev/null +++ b/queue-4.4/drm-rcar-du-perform-initialization-cleanup-at-probe-remove-time.patch @@ -0,0 +1,350 @@ +From c1d4b38c93069dca6b419a3b88907e01e2c3abf7 Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart +Date: Mon, 28 Sep 2015 18:39:53 +0300 +Subject: drm: rcar-du: Perform initialization/cleanup at probe/remove time + +From: Laurent Pinchart + +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 +Acked-by: Daniel Vetter +Signed-off-by: Thong Ho +Signed-off-by: Nhan Nguyen +Signed-off-by: Greg Kroah-Hartman + +--- + 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, diff --git a/queue-4.4/drm-rcar-du-simplify-and-fix-probe-error-handling.patch b/queue-4.4/drm-rcar-du-simplify-and-fix-probe-error-handling.patch new file mode 100644 index 00000000000..eb07408a372 --- /dev/null +++ b/queue-4.4/drm-rcar-du-simplify-and-fix-probe-error-handling.patch @@ -0,0 +1,100 @@ +From 4f7b0d263833928e947e172eff2d2997179c5cb9 Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart +Date: Wed, 19 Oct 2016 00:51:35 +0300 +Subject: drm: rcar-du: Simplify and fix probe error handling + +From: Laurent Pinchart + +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 +Signed-off-by: thongsyho +Signed-off-by: Nhan Nguyen +Signed-off-by: Greg Kroah-Hartman +--- + 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); + diff --git a/queue-4.4/drm-rcar-nuke-preclose-hook.patch b/queue-4.4/drm-rcar-nuke-preclose-hook.patch new file mode 100644 index 00000000000..d19b7e9545d --- /dev/null +++ b/queue-4.4/drm-rcar-nuke-preclose-hook.patch @@ -0,0 +1,93 @@ +From 0a346629f5304a8390004a91e8d4f1206b87792b Mon Sep 17 00:00:00 2001 +From: Daniel Vetter +Date: Mon, 25 Jan 2016 22:16:51 +0100 +Subject: drm/rcar: Nuke preclose hook + +From: Daniel Vetter + +commit 0a346629f5304a8390004a91e8d4f1206b87792b upstream. + +Again since the drm core takes care of event unlinking/disarming this +is now just needless code. + +Cc: Laurent Pinchart +Acked-by: Daniel Stone +Reviewed-by: Alex Deucher +Reviewed-by: Laurent Pinchart +Signed-off-by: Daniel Vetter +Link: http://patchwork.freedesktop.org/patch/msgid/1453756616-28942-10-git-send-email-daniel.vetter@ffwll.ch +Signed-off-by: Nhan Nguyen +Signed-off-by: Greg Kroah-Hartman + +--- + 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, diff --git a/queue-4.4/perf-intel-pt-ensure-never-to-set-last_ip-when-packet-count-is-zero.patch b/queue-4.4/perf-intel-pt-ensure-never-to-set-last_ip-when-packet-count-is-zero.patch new file mode 100644 index 00000000000..b828a1dda4b --- /dev/null +++ b/queue-4.4/perf-intel-pt-ensure-never-to-set-last_ip-when-packet-count-is-zero.patch @@ -0,0 +1,48 @@ +From f952eaceb089b691eba7c4e13686e742a8f26bf5 Mon Sep 17 00:00:00 2001 +From: Adrian Hunter +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 + +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 +Cc: Andi Kleen +Link: http://lkml.kernel.org/r/1495786658-18063-7-git-send-email-adrian.hunter@intel.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: Greg Kroah-Hartman + +--- + 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. */ diff --git a/queue-4.4/perf-intel-pt-fix-ip-compression.patch b/queue-4.4/perf-intel-pt-fix-ip-compression.patch new file mode 100644 index 00000000000..d4c8743653c --- /dev/null +++ b/queue-4.4/perf-intel-pt-fix-ip-compression.patch @@ -0,0 +1,207 @@ +From e1717e0485af4f47fc4da1e979ac817f9ad61b0f Mon Sep 17 00:00:00 2001 +From: Adrian Hunter +Date: Wed, 20 Jul 2016 12:00:06 +0300 +Subject: perf intel-pt: Fix ip compression + +From: Adrian Hunter + +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 +Cc: Jiri Olsa +Link: http://lkml.kernel.org/r/1469005206-3049-1-git-send-email-adrian.hunter@intel.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: Greg Kroah-Hartman + +--- + 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, diff --git a/queue-4.4/perf-intel-pt-fix-last_ip-usage.patch b/queue-4.4/perf-intel-pt-fix-last_ip-usage.patch new file mode 100644 index 00000000000..e511ac9d2ee --- /dev/null +++ b/queue-4.4/perf-intel-pt-fix-last_ip-usage.patch @@ -0,0 +1,104 @@ +From ee14ac0ef6827cd6f9a572cc83dd0191ea17812c Mon Sep 17 00:00:00 2001 +From: Adrian Hunter +Date: Fri, 26 May 2017 11:17:06 +0300 +Subject: perf intel-pt: Fix last_ip usage + +From: Adrian Hunter + +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 +Cc: Andi Kleen +Link: http://lkml.kernel.org/r/1495786658-18063-6-git-send-email-adrian.hunter@intel.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: Greg Kroah-Hartman + +--- + 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 */ diff --git a/queue-4.4/perf-intel-pt-use-fup-always-when-scanning-for-an-ip.patch b/queue-4.4/perf-intel-pt-use-fup-always-when-scanning-for-an-ip.patch new file mode 100644 index 00000000000..a2c4abec333 --- /dev/null +++ b/queue-4.4/perf-intel-pt-use-fup-always-when-scanning-for-an-ip.patch @@ -0,0 +1,45 @@ +From 622b7a47b843c78626f40c1d1aeef8483383fba2 Mon Sep 17 00:00:00 2001 +From: Adrian Hunter +Date: Fri, 26 May 2017 11:17:08 +0300 +Subject: perf intel-pt: Use FUP always when scanning for an IP + +From: Adrian Hunter + +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 +Cc: Andi Kleen +Link: http://lkml.kernel.org/r/1495786658-18063-8-git-send-email-adrian.hunter@intel.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: Greg Kroah-Hartman + +--- + 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: diff --git a/queue-4.4/series b/queue-4.4/series index af4684d0f28..b4568493ea7 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -12,3 +12,11 @@ kvm-ppc-book3s-hv-reload-htm-registers-explicitly.patch 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 diff --git a/queue-4.4/xfs-don-t-bug-on-mixed-direct-and-mapped-i-o.patch b/queue-4.4/xfs-don-t-bug-on-mixed-direct-and-mapped-i-o.patch new file mode 100644 index 00000000000..b3cc50526e3 --- /dev/null +++ b/queue-4.4/xfs-don-t-bug-on-mixed-direct-and-mapped-i-o.patch @@ -0,0 +1,87 @@ +From 04197b341f23b908193308b8d63d17ff23232598 Mon Sep 17 00:00:00 2001 +From: Brian Foster +Date: Tue, 8 Nov 2016 12:54:14 +1100 +Subject: xfs: don't BUG() on mixed direct and mapped I/O + +From: Brian Foster + +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 +Reviewed-by: Dave Chinner +Signed-off-by: Dave Chinner +Signed-off-by: Nikolay Borisov +Acked-by: Darrick J. Wong +Signed-off-by: Greg Kroah-Hartman + + +--- + 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);