diff options
| author | Geert Uytterhoeven <geert+renesas@glider.be> | 2015-04-03 08:50:28 -0400 |
|---|---|---|
| committer | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2015-04-07 09:24:15 -0400 |
| commit | 7374ccc0c322a6dc55f783a1a9c816c6f308d990 (patch) | |
| tree | 6a7942db78afc0a47d55ed8a7e823a65e27d8c7b /drivers/video | |
| parent | 14048ffed0145a425a8d3114ce8ff48172460238 (diff) | |
fbdev: sh_mobile_lcdc: Fix destruction of uninitialized mutex
If sh_mobile_lcdc_probe() fails after the allocation of driver-private
data, but before the initialization of all channels, a warning will be
printed due to the destruction of an uninitialized mutex:
WARNING: CPU: 0 PID: 1 at kernel/locking/mutex-debug.c:116 mutex_destroy+0x5c/0x7c()
DEBUG_LOCKS_WARN_ON(mutex_is_locked(lock))
...
Backtrace:
...
[<c00425b4>] (mutex_destroy) from [<c01d5858>] (sh_mobile_lcdc_remove+0x1bc/0x230)
r4:df6a4800 r3:00000000
[<c01d569c>] (sh_mobile_lcdc_remove) from [<c01d6620>] (sh_mobile_lcdc_probe+0xd54/0xe28)
Move the initialization of the mutexes from sh_mobile_lcdc_channel_init()
to immediately after the allocation of driver-private data to fix this.
Note that the interrupt number is moved to a new variable "irq", so we
can reuse the existing variable "i" for iterating over the channels.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'drivers/video')
| -rw-r--r-- | drivers/video/fbdev/sh_mobile_lcdcfb.c | 13 |
1 files changed, 7 insertions, 6 deletions
diff --git a/drivers/video/fbdev/sh_mobile_lcdcfb.c b/drivers/video/fbdev/sh_mobile_lcdcfb.c index 23421ec1c4e4..82c0a8caa9b8 100644 --- a/drivers/video/fbdev/sh_mobile_lcdcfb.c +++ b/drivers/video/fbdev/sh_mobile_lcdcfb.c | |||
| @@ -2605,7 +2605,6 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch) | |||
| 2605 | unsigned int max_size; | 2605 | unsigned int max_size; |
| 2606 | unsigned int i; | 2606 | unsigned int i; |
| 2607 | 2607 | ||
| 2608 | mutex_init(&ch->open_lock); | ||
| 2609 | ch->notify = sh_mobile_lcdc_display_notify; | 2608 | ch->notify = sh_mobile_lcdc_display_notify; |
| 2610 | 2609 | ||
| 2611 | /* Validate the format. */ | 2610 | /* Validate the format. */ |
| @@ -2704,7 +2703,7 @@ static int sh_mobile_lcdc_probe(struct platform_device *pdev) | |||
| 2704 | struct resource *res; | 2703 | struct resource *res; |
| 2705 | int num_channels; | 2704 | int num_channels; |
| 2706 | int error; | 2705 | int error; |
| 2707 | int i; | 2706 | int irq, i; |
| 2708 | 2707 | ||
| 2709 | if (!pdata) { | 2708 | if (!pdata) { |
| 2710 | dev_err(&pdev->dev, "no platform data defined\n"); | 2709 | dev_err(&pdev->dev, "no platform data defined\n"); |
| @@ -2712,8 +2711,8 @@ static int sh_mobile_lcdc_probe(struct platform_device *pdev) | |||
| 2712 | } | 2711 | } |
| 2713 | 2712 | ||
| 2714 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 2713 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 2715 | i = platform_get_irq(pdev, 0); | 2714 | irq = platform_get_irq(pdev, 0); |
| 2716 | if (!res || i < 0) { | 2715 | if (!res || irq < 0) { |
| 2717 | dev_err(&pdev->dev, "cannot get platform resources\n"); | 2716 | dev_err(&pdev->dev, "cannot get platform resources\n"); |
| 2718 | return -ENOENT; | 2717 | return -ENOENT; |
| 2719 | } | 2718 | } |
| @@ -2726,16 +2725,18 @@ static int sh_mobile_lcdc_probe(struct platform_device *pdev) | |||
| 2726 | 2725 | ||
| 2727 | priv->dev = &pdev->dev; | 2726 | priv->dev = &pdev->dev; |
| 2728 | priv->meram_dev = pdata->meram_dev; | 2727 | priv->meram_dev = pdata->meram_dev; |
| 2728 | for (i = 0; i < ARRAY_SIZE(priv->ch); i++) | ||
| 2729 | mutex_init(&priv->ch[i].open_lock); | ||
| 2729 | platform_set_drvdata(pdev, priv); | 2730 | platform_set_drvdata(pdev, priv); |
| 2730 | 2731 | ||
| 2731 | error = request_irq(i, sh_mobile_lcdc_irq, 0, | 2732 | error = request_irq(irq, sh_mobile_lcdc_irq, 0, |
| 2732 | dev_name(&pdev->dev), priv); | 2733 | dev_name(&pdev->dev), priv); |
| 2733 | if (error) { | 2734 | if (error) { |
| 2734 | dev_err(&pdev->dev, "unable to request irq\n"); | 2735 | dev_err(&pdev->dev, "unable to request irq\n"); |
| 2735 | goto err1; | 2736 | goto err1; |
| 2736 | } | 2737 | } |
| 2737 | 2738 | ||
| 2738 | priv->irq = i; | 2739 | priv->irq = irq; |
| 2739 | atomic_set(&priv->hw_usecnt, -1); | 2740 | atomic_set(&priv->hw_usecnt, -1); |
| 2740 | 2741 | ||
| 2741 | for (i = 0, num_channels = 0; i < ARRAY_SIZE(pdata->ch); i++) { | 2742 | for (i = 0, num_channels = 0; i < ARRAY_SIZE(pdata->ch); i++) { |
