edid data from user should be allocated and copied into vidi context and also
freed with disconnection.

Signed-off-by: Inki Dae <inki.dae at samsung.com>
Signed-off-by: Seung-Woo Kim <sw0312.kim at samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
---
 drivers/gpu/drm/exynos/exynos_drm_vidi.c |   38 ++++++++++++++++++++++++-----
 1 files changed, 31 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c 
b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
index dbbf2fc..1d7d030 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -557,6 +557,8 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void 
*data,
        struct exynos_drm_manager *manager;
        struct exynos_drm_display_ops *display_ops;
        struct drm_exynos_vidi_connection *vidi = data;
+       struct edid *raw_edid;
+       int edid_len;

        DRM_DEBUG_KMS("%s\n", __FILE__);

@@ -565,11 +567,6 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void 
*data,
                return -EINVAL;
        }

-       if (!vidi->edid) {
-               DRM_DEBUG_KMS("edid data is null.\n");
-               return -EINVAL;
-       }
-
        if (vidi->connection > 1) {
                DRM_DEBUG_KMS("connection should be 0 or 1.\n");
                return -EINVAL;
@@ -596,8 +593,30 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void 
*data,
                return -EINVAL;
        }

-       if (vidi->connection)
-               ctx->raw_edid = (struct edid *)vidi->edid;
+       if (vidi->connection) {
+               if (!vidi->edid) {
+                       DRM_DEBUG_KMS("edid data is null.\n");
+                       return -EINVAL;
+               }
+               raw_edid = (struct edid *)vidi->edid;
+               edid_len = (1 + raw_edid->extensions) * EDID_LENGTH;
+               ctx->raw_edid = kzalloc(edid_len, GFP_KERNEL);
+               if (!ctx->raw_edid) {
+                       DRM_DEBUG_KMS("failed to allocate raw_edid.\n");
+                       return -ENOMEM;
+               }
+               memcpy(ctx->raw_edid, raw_edid, edid_len);
+       } else {
+               /*
+                * with connection = 0, free raw_edid
+                * only if raw edid data isn't same as fake data.
+                */
+               if (ctx->raw_edid && ctx->raw_edid !=
+                               (struct edid *)fake_edid_info) {
+                       kfree(ctx->raw_edid);
+                       ctx->raw_edid = NULL;
+               }
+       }

        ctx->connected = vidi->connection;
        drm_helper_hpd_irq_event(ctx->subdrv.drm_dev);
@@ -649,6 +668,11 @@ static int __devexit vidi_remove(struct platform_device 
*pdev)

        exynos_drm_subdrv_unregister(&ctx->subdrv);

+       if (ctx->raw_edid != (struct edid *)fake_edid_info) {
+               kfree(ctx->raw_edid);
+               ctx->raw_edid = NULL;
+       }
+
        kfree(ctx);

        return 0;
-- 
1.7.4.1

Reply via email to