Re: [PATCH 1/2] drm/udl: Fixed problem with UDL adpater reconnection

2017-10-13 Thread Alex Deucher
On Thu, Oct 12, 2017 at 8:13 PM, Robert Tarasov
 wrote:
> Fixed problem with DisplayLink and DisplayLink certified adapers in drm/udl
> driver when adapter doesn't want to work if it was initialized with
> disconnected DVI cable by enabling drm connectot polling and updating
> current connector's state.
>
> Signed-off-by: Robert Tarasov 

Reviewed-by: Alex Deucher 

> ---
>  drivers/gpu/drm/udl/udl_connector.c | 76 
> -
>  drivers/gpu/drm/udl/udl_connector.h | 13 +++
>  drivers/gpu/drm/udl/udl_drv.c   |  4 ++
>  drivers/gpu/drm/udl/udl_main.c  |  5 +++
>  4 files changed, 72 insertions(+), 26 deletions(-)
>  create mode 100644 drivers/gpu/drm/udl/udl_connector.h
>
> diff --git a/drivers/gpu/drm/udl/udl_connector.c 
> b/drivers/gpu/drm/udl/udl_connector.c
> index 091ca81658eb..6a9250ac8f29 100644
> --- a/drivers/gpu/drm/udl/udl_connector.c
> +++ b/drivers/gpu/drm/udl/udl_connector.c
> @@ -14,6 +14,7 @@
>  #include 
>  #include 
>  #include 
> +#include "udl_connector.h"
>  #include "udl_drv.h"
>
>  /* dummy connector to just get EDID,
> @@ -56,28 +57,15 @@ static u8 *udl_get_edid(struct udl_device *udl)
>
>  static int udl_get_modes(struct drm_connector *connector)
>  {
> -   struct udl_device *udl = connector->dev->dev_private;
> -   struct edid *edid;
> -   int ret;
> -
> -   edid = (struct edid *)udl_get_edid(udl);
> -   if (!edid) {
> -   drm_mode_connector_update_edid_property(connector, NULL);
> -   return 0;
> -   }
> -
> -   /*
> -* We only read the main block, but if the monitor reports extension
> -* blocks then the drm edid code expects them to be present, so patch
> -* the extension count to 0.
> -*/
> -   edid->checksum += edid->extensions;
> -   edid->extensions = 0;
> -
> -   drm_mode_connector_update_edid_property(connector, edid);
> -   ret = drm_add_edid_modes(connector, edid);
> -   kfree(edid);
> -   return ret;
> +   struct udl_drm_connector *udl_connector =
> +   container_of(connector,
> +   struct udl_drm_connector,
> +   connector);
> +
> +   drm_mode_connector_update_edid_property(connector, 
> udl_connector->edid);
> +   if (udl_connector->edid)
> +   return drm_add_edid_modes(connector, udl_connector->edid);
> +   return 0;
>  }
>
>  static int udl_mode_valid(struct drm_connector *connector,
> @@ -96,8 +84,33 @@ static int udl_mode_valid(struct drm_connector *connector,
>  static enum drm_connector_status
>  udl_detect(struct drm_connector *connector, bool force)
>  {
> -   if (drm_dev_is_unplugged(connector->dev))
> +   struct edid *edid;
> +   struct udl_device *udl = connector->dev->dev_private;
> +   struct udl_drm_connector *udl_connector =
> +   container_of(connector,
> +   struct udl_drm_connector,
> +   connector);
> +
> +   if (udl_connector->edid != NULL) {
> +   kfree(udl_connector->edid);
> +   udl_connector->edid = NULL;
> +   }
> +
> +   edid = (struct edid *)udl_get_edid(udl);
> +   if (!edid || !memchr_inv(edid, 0, EDID_LENGTH))
> return connector_status_disconnected;
> +
> +   udl_connector->edid = edid;
> +
> +   /*
> +* We only read the main block, but if the monitor reports extension
> +* blocks then the drm edid code expects them to be present, so patch
> +* the extension count to 0.
> +*/
> +   udl_connector->edid->checksum +=
> +   udl_connector->edid->extensions;
> +   udl_connector->edid->extensions = 0;
> +
> return connector_status_connected;
>  }
>
> @@ -117,8 +130,14 @@ static int udl_connector_set_property(struct 
> drm_connector *connector,
>
>  static void udl_connector_destroy(struct drm_connector *connector)
>  {
> +   struct udl_drm_connector *udl_connector =
> +   container_of(connector,
> +   struct udl_drm_connector,
> +   connector);
> +
> drm_connector_unregister(connector);
> drm_connector_cleanup(connector);
> +   kfree(udl_connector->edid);
> kfree(connector);
>  }
>
> @@ -138,17 +157,22 @@ static const struct drm_connector_funcs 
> udl_connector_funcs = {
>
>  int udl_connector_init(struct drm_device *dev, struct drm_encoder *encoder)
>  {
> +   struct udl_drm_connector *udl_connector;
> struct drm_connector *connector;
>
> -   connector = kzalloc(sizeof(struct drm_connector), GFP_KERNEL);
> -   if (!connector)
> +   udl_connector = kzalloc(sizeof(struct 

[PATCH 1/2] drm/udl: Fixed problem with UDL adpater reconnection

2017-10-13 Thread Robert Tarasov
Fixed problem with DisplayLink and DisplayLink certified adapers in drm/udl
driver when adapter doesn't want to work if it was initialized with
disconnected DVI cable by enabling drm connectot polling and updating
current connector's state.

Signed-off-by: Robert Tarasov 
---
 drivers/gpu/drm/udl/udl_connector.c | 76 -
 drivers/gpu/drm/udl/udl_connector.h | 13 +++
 drivers/gpu/drm/udl/udl_drv.c   |  4 ++
 drivers/gpu/drm/udl/udl_main.c  |  5 +++
 4 files changed, 72 insertions(+), 26 deletions(-)
 create mode 100644 drivers/gpu/drm/udl/udl_connector.h

diff --git a/drivers/gpu/drm/udl/udl_connector.c 
b/drivers/gpu/drm/udl/udl_connector.c
index 091ca81658eb..6a9250ac8f29 100644
--- a/drivers/gpu/drm/udl/udl_connector.c
+++ b/drivers/gpu/drm/udl/udl_connector.c
@@ -14,6 +14,7 @@
 #include 
 #include 
 #include 
+#include "udl_connector.h"
 #include "udl_drv.h"
 
 /* dummy connector to just get EDID,
@@ -56,28 +57,15 @@ static u8 *udl_get_edid(struct udl_device *udl)
 
 static int udl_get_modes(struct drm_connector *connector)
 {
-   struct udl_device *udl = connector->dev->dev_private;
-   struct edid *edid;
-   int ret;
-
-   edid = (struct edid *)udl_get_edid(udl);
-   if (!edid) {
-   drm_mode_connector_update_edid_property(connector, NULL);
-   return 0;
-   }
-
-   /*
-* We only read the main block, but if the monitor reports extension
-* blocks then the drm edid code expects them to be present, so patch
-* the extension count to 0.
-*/
-   edid->checksum += edid->extensions;
-   edid->extensions = 0;
-
-   drm_mode_connector_update_edid_property(connector, edid);
-   ret = drm_add_edid_modes(connector, edid);
-   kfree(edid);
-   return ret;
+   struct udl_drm_connector *udl_connector =
+   container_of(connector,
+   struct udl_drm_connector,
+   connector);
+
+   drm_mode_connector_update_edid_property(connector, udl_connector->edid);
+   if (udl_connector->edid)
+   return drm_add_edid_modes(connector, udl_connector->edid);
+   return 0;
 }
 
 static int udl_mode_valid(struct drm_connector *connector,
@@ -96,8 +84,33 @@ static int udl_mode_valid(struct drm_connector *connector,
 static enum drm_connector_status
 udl_detect(struct drm_connector *connector, bool force)
 {
-   if (drm_dev_is_unplugged(connector->dev))
+   struct edid *edid;
+   struct udl_device *udl = connector->dev->dev_private;
+   struct udl_drm_connector *udl_connector =
+   container_of(connector,
+   struct udl_drm_connector,
+   connector);
+
+   if (udl_connector->edid != NULL) {
+   kfree(udl_connector->edid);
+   udl_connector->edid = NULL;
+   }
+
+   edid = (struct edid *)udl_get_edid(udl);
+   if (!edid || !memchr_inv(edid, 0, EDID_LENGTH))
return connector_status_disconnected;
+
+   udl_connector->edid = edid;
+
+   /*
+* We only read the main block, but if the monitor reports extension
+* blocks then the drm edid code expects them to be present, so patch
+* the extension count to 0.
+*/
+   udl_connector->edid->checksum +=
+   udl_connector->edid->extensions;
+   udl_connector->edid->extensions = 0;
+
return connector_status_connected;
 }
 
@@ -117,8 +130,14 @@ static int udl_connector_set_property(struct drm_connector 
*connector,
 
 static void udl_connector_destroy(struct drm_connector *connector)
 {
+   struct udl_drm_connector *udl_connector =
+   container_of(connector,
+   struct udl_drm_connector,
+   connector);
+
drm_connector_unregister(connector);
drm_connector_cleanup(connector);
+   kfree(udl_connector->edid);
kfree(connector);
 }
 
@@ -138,17 +157,22 @@ static const struct drm_connector_funcs 
udl_connector_funcs = {
 
 int udl_connector_init(struct drm_device *dev, struct drm_encoder *encoder)
 {
+   struct udl_drm_connector *udl_connector;
struct drm_connector *connector;
 
-   connector = kzalloc(sizeof(struct drm_connector), GFP_KERNEL);
-   if (!connector)
+   udl_connector = kzalloc(sizeof(struct udl_drm_connector), GFP_KERNEL);
+   if (!udl_connector)
return -ENOMEM;
 
-   drm_connector_init(dev, connector, _connector_funcs, 
DRM_MODE_CONNECTOR_DVII);
+   connector = _connector->connector;
+   drm_connector_init(dev, connector, _connector_funcs,
+  DRM_MODE_CONNECTOR_DVII);
drm_connector_helper_add(connector,