diff options
author | Guennadi Liakhovetski <g.liakhovetski@gmx.de> | 2010-09-03 07:19:57 +0000 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2010-09-14 17:22:25 +0900 |
commit | 5ef6b505d9df45558402bdb823a078840a6a26c4 (patch) | |
tree | 9ce7965f1aff5195822962369ee2a2c671fcfdcf /drivers/video/sh_mobile_lcdcfb.c | |
parent | 6ee4845270d9b1e7ea348f9e3b6347f54f986abb (diff) |
fbdev: sh_mobile_lcdcfb: fix more error paths
This patch fixes the following two erroneous error paths:
hw_usecnt is allocated with a value of 0, therefore in an early error case,
calling sh_mobile_lcdc_clk_off() will wrongly conclude, that hw_usecnt has
already been incremented. Then sh_mobile_lcdc_runtime_suspend() will be called,
which will access uninitialised data fields and crash the kernel.
sh_mobile_lcdc_stop() can be called before framebuffer has been allocated, then
ch->info is NULL and dereferencing it will Oops too.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'drivers/video/sh_mobile_lcdcfb.c')
-rw-r--r-- | drivers/video/sh_mobile_lcdcfb.c | 4 |
1 files changed, 2 insertions, 2 deletions
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index 43132de3882..295bf4ba184 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c @@ -614,7 +614,7 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv) * flush frame, and wait for frame end interrupt * clean up deferred io and enable clock */ - if (ch->info->fbdefio) { + if (ch->info && ch->info->fbdefio) { ch->frame_end = 0; schedule_delayed_work(&ch->info->deferred_work, 0); wait_event(ch->frame_end_wait, ch->frame_end); @@ -704,7 +704,6 @@ static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev, return PTR_ERR(priv->dot_clk); } } - atomic_set(&priv->hw_usecnt, -1); /* Runtime PM support involves two step for this driver: * 1) Enable Runtime PM @@ -1055,6 +1054,7 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) priv->irq = i; pdata = pdev->dev.platform_data; + atomic_set(&priv->hw_usecnt, -1); j = 0; for (i = 0; i < ARRAY_SIZE(pdata->ch); i++) { |