]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 8 Sep 2017 07:24:41 +0000 (09:24 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 8 Sep 2017 07:24:41 +0000 (09:24 +0200)
added patches:
drm-adv7511-really-enable-interrupts-for-edid-detection.patch
drm-bridge-adv7511-fix-mutex-deadlock-when-interrupts-are-disabled.patch
drm-bridge-adv7511-re-write-the-i2c-address-before-edid-probing.patch
drm-bridge-adv7511-switch-to-using-drm_kms_helper_hotplug_event.patch
drm-bridge-adv7511-use-work_struct-to-defer-hotplug-handing-to-out-of-irq-context.patch

queue-4.4/drm-adv7511-really-enable-interrupts-for-edid-detection.patch [new file with mode: 0644]
queue-4.4/drm-bridge-adv7511-fix-mutex-deadlock-when-interrupts-are-disabled.patch [new file with mode: 0644]
queue-4.4/drm-bridge-adv7511-re-write-the-i2c-address-before-edid-probing.patch [new file with mode: 0644]
queue-4.4/drm-bridge-adv7511-switch-to-using-drm_kms_helper_hotplug_event.patch [new file with mode: 0644]
queue-4.4/drm-bridge-adv7511-use-work_struct-to-defer-hotplug-handing-to-out-of-irq-context.patch [new file with mode: 0644]
queue-4.4/series

diff --git a/queue-4.4/drm-adv7511-really-enable-interrupts-for-edid-detection.patch b/queue-4.4/drm-adv7511-really-enable-interrupts-for-edid-detection.patch
new file mode 100644 (file)
index 0000000..176fd1f
--- /dev/null
@@ -0,0 +1,70 @@
+From d0be8584b01160eb6f49e77f8e9c1da286bb4ffb Mon Sep 17 00:00:00 2001
+From: Wolfram Sang <wsa+renesas@sang-engineering.com>
+Date: Mon, 4 Jan 2016 03:33:45 +0100
+Subject: drm: adv7511: really enable interrupts for EDID detection
+
+From: Wolfram Sang <wsa+renesas@sang-engineering.com>
+
+commit d0be8584b01160eb6f49e77f8e9c1da286bb4ffb upstream.
+
+The interrupts for EDID_READY or DDC_ERROR were never enabled in this
+driver, so reading EDID always timed out when chip was powered down and
+interrupts were used. Fix this and also remove clearing the interrupt
+flags, they are cleared in POWER_DOWN mode anyhow (unlike the interrupt
+enable flags) according to docs and my tests.
+
+Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
+Tested-by: Archit Taneja <architt@codeaurora.org>
+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/i2c/adv7511.c |   25 +++++++++++++++++--------
+ 1 file changed, 17 insertions(+), 8 deletions(-)
+
+--- a/drivers/gpu/drm/i2c/adv7511.c
++++ b/drivers/gpu/drm/i2c/adv7511.c
+@@ -362,12 +362,19 @@ static void adv7511_power_on(struct adv7
+ {
+       adv7511->current_edid_segment = -1;
+-      regmap_write(adv7511->regmap, ADV7511_REG_INT(0),
+-                   ADV7511_INT0_EDID_READY);
+-      regmap_write(adv7511->regmap, ADV7511_REG_INT(1),
+-                   ADV7511_INT1_DDC_ERROR);
+       regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER,
+                          ADV7511_POWER_POWER_DOWN, 0);
++      if (adv7511->i2c_main->irq) {
++              /*
++               * Documentation says the INT_ENABLE registers are reset in
++               * POWER_DOWN mode. My 7511w preserved the bits, however.
++               * Still, let's be safe and stick to the documentation.
++               */
++              regmap_write(adv7511->regmap, ADV7511_REG_INT_ENABLE(0),
++                           ADV7511_INT0_EDID_READY);
++              regmap_write(adv7511->regmap, ADV7511_REG_INT_ENABLE(1),
++                           ADV7511_INT1_DDC_ERROR);
++      }
+       /*
+        * Per spec it is allowed to pulse the HDP signal to indicate that the
+@@ -567,12 +574,14 @@ static int adv7511_get_modes(struct drm_
+       /* Reading the EDID only works if the device is powered */
+       if (!adv7511->powered) {
+-              regmap_write(adv7511->regmap, ADV7511_REG_INT(0),
+-                           ADV7511_INT0_EDID_READY);
+-              regmap_write(adv7511->regmap, ADV7511_REG_INT(1),
+-                           ADV7511_INT1_DDC_ERROR);
+               regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER,
+                                  ADV7511_POWER_POWER_DOWN, 0);
++              if (adv7511->i2c_main->irq) {
++                      regmap_write(adv7511->regmap, ADV7511_REG_INT_ENABLE(0),
++                                   ADV7511_INT0_EDID_READY);
++                      regmap_write(adv7511->regmap, ADV7511_REG_INT_ENABLE(1),
++                                   ADV7511_INT1_DDC_ERROR);
++              }
+               adv7511->current_edid_segment = -1;
+       }
diff --git a/queue-4.4/drm-bridge-adv7511-fix-mutex-deadlock-when-interrupts-are-disabled.patch b/queue-4.4/drm-bridge-adv7511-fix-mutex-deadlock-when-interrupts-are-disabled.patch
new file mode 100644 (file)
index 0000000..54ee141
--- /dev/null
@@ -0,0 +1,75 @@
+From f0bfcc22d9822947b0ad3095e8363eab5261864c Mon Sep 17 00:00:00 2001
+From: Archit Taneja <architt@codeaurora.org>
+Date: Wed, 15 Jun 2016 16:20:45 +0530
+Subject: drm/bridge: adv7511: Fix mutex deadlock when interrupts are disabled
+
+From: Archit Taneja <architt@codeaurora.org>
+
+commit f0bfcc22d9822947b0ad3095e8363eab5261864c upstream.
+
+When the adv7511 i2c client doesn't have an interrupt line, we observe a
+deadlock on caused by trying to lock drm device's mode_config.mutex twice
+in the same context.
+
+Here is the sequence that causes it:
+
+ioctl DRM_IOCTL_MODE_GETCONNECTOR from userspace
+  drm_mode_getconnector (acquires mode_config mutex)
+    connector->fill_modes()
+    drm_helper_probe_single_connector_modes
+      connector_funcs->get_modes
+       adv7511_encoder_get_modes
+         adv7511_get_edid_block
+           adv7511_irq_process
+             drm_helper_hpd_irq_event (acquires mode_config mutex again)
+
+In adv7511_irq_process, don't call drm_helper_hpd_irq_event when not
+called from the interrupt handler. It doesn't serve any purpose there
+anyway.
+
+Signed-off-by: Archit Taneja <architt@codeaurora.org>
+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/i2c/adv7511.c |    8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/gpu/drm/i2c/adv7511.c
++++ b/drivers/gpu/drm/i2c/adv7511.c
+@@ -429,7 +429,7 @@ static bool adv7511_hpd(struct adv7511 *
+       return false;
+ }
+-static int adv7511_irq_process(struct adv7511 *adv7511)
++static int adv7511_irq_process(struct adv7511 *adv7511, bool process_hpd)
+ {
+       unsigned int irq0, irq1;
+       int ret;
+@@ -445,7 +445,7 @@ static int adv7511_irq_process(struct ad
+       regmap_write(adv7511->regmap, ADV7511_REG_INT(0), irq0);
+       regmap_write(adv7511->regmap, ADV7511_REG_INT(1), irq1);
+-      if (irq0 & ADV7511_INT0_HDP && adv7511->encoder)
++      if (process_hpd && irq0 & ADV7511_INT0_HDP && adv7511->encoder)
+               drm_helper_hpd_irq_event(adv7511->encoder->dev);
+       if (irq0 & ADV7511_INT0_EDID_READY || irq1 & ADV7511_INT1_DDC_ERROR) {
+@@ -463,7 +463,7 @@ static irqreturn_t adv7511_irq_handler(i
+       struct adv7511 *adv7511 = devid;
+       int ret;
+-      ret = adv7511_irq_process(adv7511);
++      ret = adv7511_irq_process(adv7511, true);
+       return ret < 0 ? IRQ_NONE : IRQ_HANDLED;
+ }
+@@ -480,7 +480,7 @@ static int adv7511_wait_for_edid(struct
+                               adv7511->edid_read, msecs_to_jiffies(timeout));
+       } else {
+               for (; timeout > 0; timeout -= 25) {
+-                      ret = adv7511_irq_process(adv7511);
++                      ret = adv7511_irq_process(adv7511, false);
+                       if (ret < 0)
+                               break;
diff --git a/queue-4.4/drm-bridge-adv7511-re-write-the-i2c-address-before-edid-probing.patch b/queue-4.4/drm-bridge-adv7511-re-write-the-i2c-address-before-edid-probing.patch
new file mode 100644 (file)
index 0000000..51ea633
--- /dev/null
@@ -0,0 +1,73 @@
+From 3587c856675c45809010c2cee5b21096f6e8e938 Mon Sep 17 00:00:00 2001
+From: John Stultz <john.stultz@linaro.org>
+Date: Mon, 16 Jan 2017 16:52:52 -0800
+Subject: drm/bridge: adv7511: Re-write the i2c address before EDID probing
+
+From: John Stultz <john.stultz@linaro.org>
+
+commit 3587c856675c45809010c2cee5b21096f6e8e938 upstream.
+
+I've found that by just turning the chip on and off via the
+POWER_DOWN register, I end up getting i2c_transfer errors on
+HiKey.
+
+Investigating further, it turns out that some of the register
+state in hardware is getting lost, as the device registers are
+reset when the chip is powered down.
+
+Thus this patch simply re-writes the i2c address to the
+ADV7511_REG_EDID_I2C_ADDR register to ensure its properly set
+before we try to read the EDID data.
+
+Cc: David Airlie <airlied@linux.ie>
+Cc: Archit Taneja <architt@codeaurora.org>
+Cc: Wolfram Sang <wsa+renesas@sang-engineering.com>
+Cc: Lars-Peter Clausen <lars@metafoo.de>
+Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Cc: dri-devel@lists.freedesktop.org
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Tested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: John Stultz <john.stultz@linaro.org>
+Signed-off-by: Archit Taneja <architt@codeaurora.org>
+Link: http://patchwork.freedesktop.org/patch/msgid/1484614372-15342-7-git-send-email-john.stultz@linaro.org
+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/i2c/adv7511.c |   11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+--- a/drivers/gpu/drm/i2c/adv7511.c
++++ b/drivers/gpu/drm/i2c/adv7511.c
+@@ -51,6 +51,10 @@ struct adv7511 {
+       struct gpio_desc *gpio_pd;
+ };
++static const int edid_i2c_addr = 0x7e;
++static const int packet_i2c_addr = 0x70;
++static const int cec_i2c_addr = 0x78;
++
+ static struct adv7511 *encoder_to_adv7511(struct drm_encoder *encoder)
+ {
+       return to_encoder_slave(encoder)->slave_priv;
+@@ -606,6 +610,9 @@ static int adv7511_get_modes(struct drm_
+                                    ADV7511_INT1_DDC_ERROR);
+               }
+               adv7511->current_edid_segment = -1;
++              /* Reset the EDID_I2C_ADDR register as it might be cleared */
++              regmap_write(adv7511->regmap, ADV7511_REG_EDID_I2C_ADDR,
++                              edid_i2c_addr);
+       }
+       edid = drm_do_get_edid(connector, adv7511_get_edid_block, adv7511);
+@@ -881,10 +888,6 @@ static int adv7511_parse_dt(struct devic
+       return 0;
+ }
+-static const int edid_i2c_addr = 0x7e;
+-static const int packet_i2c_addr = 0x70;
+-static const int cec_i2c_addr = 0x78;
+-
+ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
+ {
+       struct adv7511_link_config link_config;
diff --git a/queue-4.4/drm-bridge-adv7511-switch-to-using-drm_kms_helper_hotplug_event.patch b/queue-4.4/drm-bridge-adv7511-switch-to-using-drm_kms_helper_hotplug_event.patch
new file mode 100644 (file)
index 0000000..5d7e088
--- /dev/null
@@ -0,0 +1,63 @@
+From 6d5104c5a6b56385426e15047050584794bb6254 Mon Sep 17 00:00:00 2001
+From: John Stultz <john.stultz@linaro.org>
+Date: Mon, 16 Jan 2017 16:52:48 -0800
+Subject: drm/bridge: adv7511: Switch to using drm_kms_helper_hotplug_event()
+
+From: John Stultz <john.stultz@linaro.org>
+
+commit 6d5104c5a6b56385426e15047050584794bb6254 upstream.
+
+In chasing down a previous issue with EDID probing from calling
+drm_helper_hpd_irq_event() from irq context, Laurent noticed
+that the DRM documentation suggests that
+drm_kms_helper_hotplug_event() should be used instead.
+
+Thus this patch replaces drm_helper_hpd_irq_event() with
+drm_kms_helper_hotplug_event(), which requires we update the
+connector.status entry and only call _hotplug_event() when the
+status changes.
+
+Cc: David Airlie <airlied@linux.ie>
+Cc: Archit Taneja <architt@codeaurora.org>
+Cc: Wolfram Sang <wsa+renesas@sang-engineering.com>
+Cc: Lars-Peter Clausen <lars@metafoo.de>
+Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Cc: dri-devel@lists.freedesktop.org
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Tested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: John Stultz <john.stultz@linaro.org>
+Signed-off-by: Archit Taneja <architt@codeaurora.org>
+Link: http://patchwork.freedesktop.org/patch/msgid/1484614372-15342-3-git-send-email-john.stultz@linaro.org
+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/i2c/adv7511.c |   15 ++++++++++++++-
+ 1 file changed, 14 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/i2c/adv7511.c
++++ b/drivers/gpu/drm/i2c/adv7511.c
+@@ -435,8 +435,21 @@ static bool adv7511_hpd(struct adv7511 *
+ static void adv7511_hpd_work(struct work_struct *work)
+ {
+       struct adv7511 *adv7511 = container_of(work, struct adv7511, hpd_work);
++      enum drm_connector_status status;
++      unsigned int val;
++      int ret;
++      ret = regmap_read(adv7511->regmap, ADV7511_REG_STATUS, &val);
++      if (ret < 0)
++              status = connector_status_disconnected;
++      else if (val & ADV7511_STATUS_HPD)
++              status = connector_status_connected;
++      else
++              status = connector_status_disconnected;
+-      drm_helper_hpd_irq_event(adv7511->connector.dev);
++      if (adv7511->connector.status != status) {
++              adv7511->connector.status = status;
++              drm_kms_helper_hotplug_event(adv7511->connector.dev);
++      }
+ }
+ static int adv7511_irq_process(struct adv7511 *adv7511, bool process_hpd)
diff --git a/queue-4.4/drm-bridge-adv7511-use-work_struct-to-defer-hotplug-handing-to-out-of-irq-context.patch b/queue-4.4/drm-bridge-adv7511-use-work_struct-to-defer-hotplug-handing-to-out-of-irq-context.patch
new file mode 100644 (file)
index 0000000..1f769e1
--- /dev/null
@@ -0,0 +1,87 @@
+From 518cb7057a59b9441336d2e88a396d52b6ab0cce Mon Sep 17 00:00:00 2001
+From: John Stultz <john.stultz@linaro.org>
+Date: Mon, 16 Jan 2017 16:52:47 -0800
+Subject: drm/bridge: adv7511: Use work_struct to defer hotplug handing to out of irq context
+
+From: John Stultz <john.stultz@linaro.org>
+
+commit 518cb7057a59b9441336d2e88a396d52b6ab0cce upstream.
+
+I was recently seeing issues with EDID probing, where
+the logic to wait for the EDID read bit to be set by the
+IRQ wasn't happening and the code would time out and fail.
+
+Digging deeper, I found this was due to the fact that
+IRQs were disabled as we were running in IRQ context from
+the HPD signal.
+
+Thus this patch changes the logic to handle the HPD signal
+via a work_struct so we can be out of irq context.
+
+With this patch, the EDID probing on hotplug does not time
+out.
+
+Cc: David Airlie <airlied@linux.ie>
+Cc: Archit Taneja <architt@codeaurora.org>
+Cc: Wolfram Sang <wsa+renesas@sang-engineering.com>
+Cc: Lars-Peter Clausen <lars@metafoo.de>
+Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Cc: dri-devel@lists.freedesktop.org
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Tested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: John Stultz <john.stultz@linaro.org>
+Signed-off-by: Archit Taneja <architt@codeaurora.org>
+Link: http://patchwork.freedesktop.org/patch/msgid/1484614372-15342-2-git-send-email-john.stultz@linaro.org
+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/i2c/adv7511.c |   14 +++++++++++++-
+ 1 file changed, 13 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/i2c/adv7511.c
++++ b/drivers/gpu/drm/i2c/adv7511.c
+@@ -36,7 +36,10 @@ struct adv7511 {
+       bool edid_read;
+       wait_queue_head_t wq;
++      struct work_struct hpd_work;
++
+       struct drm_encoder *encoder;
++      struct drm_connector connector;
+       bool embedded_sync;
+       enum adv7511_sync_polarity vsync_polarity;
+@@ -429,6 +432,13 @@ static bool adv7511_hpd(struct adv7511 *
+       return false;
+ }
++static void adv7511_hpd_work(struct work_struct *work)
++{
++      struct adv7511 *adv7511 = container_of(work, struct adv7511, hpd_work);
++
++      drm_helper_hpd_irq_event(adv7511->connector.dev);
++}
++
+ static int adv7511_irq_process(struct adv7511 *adv7511, bool process_hpd)
+ {
+       unsigned int irq0, irq1;
+@@ -446,7 +456,7 @@ static int adv7511_irq_process(struct ad
+       regmap_write(adv7511->regmap, ADV7511_REG_INT(1), irq1);
+       if (process_hpd && irq0 & ADV7511_INT0_HDP && adv7511->encoder)
+-              drm_helper_hpd_irq_event(adv7511->encoder->dev);
++              schedule_work(&adv7511->hpd_work);
+       if (irq0 & ADV7511_INT0_EDID_READY || irq1 & ADV7511_INT1_DDC_ERROR) {
+               adv7511->edid_read = true;
+@@ -922,6 +932,8 @@ static int adv7511_probe(struct i2c_clie
+       if (!adv7511->i2c_edid)
+               return -ENOMEM;
++      INIT_WORK(&adv7511->hpd_work, adv7511_hpd_work);
++
+       if (i2c->irq) {
+               init_waitqueue_head(&adv7511->wq);
index da8a8bdd291b383131a135f4a6da3d2f568f0270..386912a961f71a20d66c46198eb042c2b68f382c 100644 (file)
@@ -18,3 +18,8 @@ workqueue-fix-flag-collision.patch
 cs5536-add-support-for-ide-controller-variant.patch
 scsi-sg-protect-against-races-between-mmap-and-sg_set_reserved_size.patch
 scsi-sg-recheck-mmap_io-request-length-with-lock-held.patch
+drm-adv7511-really-enable-interrupts-for-edid-detection.patch
+drm-bridge-adv7511-fix-mutex-deadlock-when-interrupts-are-disabled.patch
+drm-bridge-adv7511-use-work_struct-to-defer-hotplug-handing-to-out-of-irq-context.patch
+drm-bridge-adv7511-switch-to-using-drm_kms_helper_hotplug_event.patch
+drm-bridge-adv7511-re-write-the-i2c-address-before-edid-probing.patch