drm/exynos: Move irq request after drm_dev assignment
authorSean Paul <seanpaul@chromium.org>
Tue, 26 Feb 2013 21:39:55 +0000 (16:39 -0500)
committerChromeBot <chrome-bot@google.com>
Tue, 26 Feb 2013 22:48:12 +0000 (14:48 -0800)
There's a race between requesting the irq and dereferencing drm_dev in
the irq handler. Moving the request_irq until after drm_dev has been
assigned eliminates this race.

BUG=chrome-os-partner:17557
TEST=Builds, tested on snow

Change-Id: I8d29aad2c73cb70b24a693e768ffdb2752a48b57
Signed-off-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Vincent Palatin <vpalatin@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/44087

drivers/gpu/drm/exynos/exynos_dp_core.c
drivers/gpu/drm/exynos/exynos_dp_core.h

index 6d5046b..67f28b1 100644 (file)
@@ -1068,9 +1068,19 @@ static bool exynos_dp_is_connected(void *ctx)
 static int exynos_dp_subdrv_probe(void *ctx, struct drm_device *drm_dev)
 {
        struct exynos_dp_device *dp = ctx;
+       int ret;
 
        dp->drm_dev = drm_dev;
 
+       if (dp->irq >= 0) {
+               ret = request_irq(dp->irq, exynos_dp_irq_handler, dp->irq_flags,
+                               "exynos-dp", dp);
+               if (ret) {
+                       dev_err(dp->dev, "failed to request irq\n");
+                       return ret;
+               }
+       }
+
        exynos_dp_dpms(dp, DRM_MODE_DPMS_ON);
 
        return 0;
@@ -1090,7 +1100,6 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
        struct exynos_dp_platdata *pdata;
 
        int ret = 0;
-       int irqflags;
 
        pdata = pdev->dev.platform_data;
        if (!pdata) {
@@ -1153,11 +1162,11 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
                s3c_gpio_cfgpin(dp->hpd_gpio, S3C_GPIO_SFN(0xf));
 #endif
                dp->irq = gpio_to_irq(dp->hpd_gpio);
-               irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
+               dp->irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
        } else {
                dp->hpd_gpio = -ENODEV;
                dp->irq = platform_get_irq(pdev, 0);
-               irqflags = 0;
+               dp->irq_flags = 0;
        }
 
        dp->training_type = pdata->training_type;
@@ -1172,15 +1181,6 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
 
        INIT_WORK(&dp->hotplug_work, exynos_dp_hotplug);
 
-       if (dp->irq >= 0) {
-               ret = request_irq(dp->irq, exynos_dp_irq_handler, irqflags,
-                               "exynos-dp", dp);
-               if (ret) {
-                       dev_err(&pdev->dev, "failed to request irq\n");
-                       goto err_gpio;
-               }
-       }
-
        platform_set_drvdata(pdev, dp);
 
        exynos_display_attach_panel(EXYNOS_DRM_DISPLAY_TYPE_FIMD, &dp_panel_ops,
index e62b625..6bdac38 100644 (file)
@@ -44,6 +44,7 @@ struct exynos_dp_device {
        struct resource         *res;
        struct clk              *clock;
        int                     irq;
+       int                     irq_flags;
        void __iomem            *reg_base;
        int                     hpd_gpio;
        bool                    force_connected;