]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 3 Aug 2017 21:56:39 +0000 (14:56 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 3 Aug 2017 21:56:39 +0000 (14:56 -0700)
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

queue-4.4/drm-rcar-du-perform-initialization-cleanup-at-probe-remove-time.patch [new file with mode: 0644]
queue-4.4/drm-rcar-du-simplify-and-fix-probe-error-handling.patch [new file with mode: 0644]
queue-4.4/drm-rcar-nuke-preclose-hook.patch [new file with mode: 0644]
queue-4.4/perf-intel-pt-ensure-never-to-set-last_ip-when-packet-count-is-zero.patch [new file with mode: 0644]
queue-4.4/perf-intel-pt-fix-ip-compression.patch [new file with mode: 0644]
queue-4.4/perf-intel-pt-fix-last_ip-usage.patch [new file with mode: 0644]
queue-4.4/perf-intel-pt-use-fup-always-when-scanning-for-an-ip.patch [new file with mode: 0644]
queue-4.4/series
queue-4.4/xfs-don-t-bug-on-mixed-direct-and-mapped-i-o.patch [new file with mode: 0644]

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 (file)
index 0000000..1ec89a4
--- /dev/null
@@ -0,0 +1,350 @@
+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,
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 (file)
index 0000000..eb07408
--- /dev/null
@@ -0,0 +1,100 @@
+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);
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 (file)
index 0000000..d19b7e9
--- /dev/null
@@ -0,0 +1,93 @@
+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,
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 (file)
index 0000000..b828a1d
--- /dev/null
@@ -0,0 +1,48 @@
+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. */
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 (file)
index 0000000..d4c8743
--- /dev/null
@@ -0,0 +1,207 @@
+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,
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 (file)
index 0000000..e511ac9
--- /dev/null
@@ -0,0 +1,104 @@
+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 */
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 (file)
index 0000000..a2c4abe
--- /dev/null
@@ -0,0 +1,45 @@
+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:
index af4684d0f287575d593c673b0d763b8ca4834c08..b4568493ea7005c1b67bd009220c6f50f0770340 100644 (file)
@@ -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 (file)
index 0000000..b3cc505
--- /dev/null
@@ -0,0 +1,87 @@
+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);