aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorJesper Juhl <jesper.juhl@gmail.com>2007-08-11 05:29:59 -0400
committerRichard Purdie <rpurdie@rpsys.net>2007-10-11 17:24:12 -0400
commit0b75f2dfa2a67012ff6996b322117e1d7e45abe1 (patch)
tree70107b3dad3aec2da9f7bacdc3b35cbd73226705 /drivers/video
parent0ad90efde278866a4ba7510e6e1fbd9626da1689 (diff)
backlight: Fix cr_bllcd allocations and error paths
After fixing the too small memory allocation in cr_backlight_probe() from drivers/video/backlight/cr_bllcd.c (commit e3bbb3f05339de438faf54124f25c92e6fe4ac2e) I noticed that the Coverity checker also thought there were a few memory leaks in there. I took a closer look and confirmed that there were indeed several leaks. At the start of the function we allocate storage for a 'struct cr_panel' and store the pointer in a variable named 'crp'. Then we call pci_get_device() and pci_read_config_byte() and if either of them fail we return without freeing the memory allocated for the 'struct cr_panel'. These two leaks are easy to fix since we don't even use 'crp' for anything up to this point, so I simply moved the allocation further down in the function so it only happens just before we actually need it. A bit further down we call backlight_device_register() and store the result in 'crp->cr_backlight_device'. In case of error we return 'crp->cr_backlight_device' from the function, thus leaking 'crp' itself. The same thing happens with the call to lcd_device_register(). To fix these two leaks I declare two new pointers to hold the return values, so that in case of error we can return the pointer (as before) but without leaking 'crp'. This version of the patch also adds missing backlight_device_unregister() / lcd_device_unregister() / pci_dev_put() calls to error paths. Thanks to Richard Purdie <rpurdie@rpsys.net> for noticing. Signed-off-by: Jesper Juhl <jesper.juhl@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Richard Purdie <rpurdie@rpsys.net>
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/backlight/cr_bllcd.c35
1 files changed, 20 insertions, 15 deletions
diff --git a/drivers/video/backlight/cr_bllcd.c b/drivers/video/backlight/cr_bllcd.c
index b7904da51b23..92e201e81fbd 100644
--- a/drivers/video/backlight/cr_bllcd.c
+++ b/drivers/video/backlight/cr_bllcd.c
@@ -171,13 +171,11 @@ static struct lcd_ops cr_lcd_ops = {
171 171
172static int cr_backlight_probe(struct platform_device *pdev) 172static int cr_backlight_probe(struct platform_device *pdev)
173{ 173{
174 struct backlight_device *bdp;
175 struct lcd_device *ldp;
174 struct cr_panel *crp; 176 struct cr_panel *crp;
175 u8 dev_en; 177 u8 dev_en;
176 178
177 crp = kzalloc(sizeof(*crp), GFP_KERNEL);
178 if (crp == NULL)
179 return -ENOMEM;
180
181 lpc_dev = pci_get_device(PCI_VENDOR_ID_INTEL, 179 lpc_dev = pci_get_device(PCI_VENDOR_ID_INTEL,
182 CRVML_DEVICE_LPC, NULL); 180 CRVML_DEVICE_LPC, NULL);
183 if (!lpc_dev) { 181 if (!lpc_dev) {
@@ -193,27 +191,34 @@ static int cr_backlight_probe(struct platform_device *pdev)
193 return -ENODEV; 191 return -ENODEV;
194 } 192 }
195 193
196 crp->cr_backlight_device = backlight_device_register("cr-backlight", 194 bdp = backlight_device_register("cr-backlight",
197 &pdev->dev, NULL, 195 &pdev->dev, NULL, &cr_backlight_ops);
198 &cr_backlight_ops); 196 if (IS_ERR(bdp)) {
199 if (IS_ERR(crp->cr_backlight_device)) {
200 pci_dev_put(lpc_dev); 197 pci_dev_put(lpc_dev);
201 return PTR_ERR(crp->cr_backlight_device); 198 return PTR_ERR(bdp);
202 } 199 }
203 200
204 crp->cr_lcd_device = lcd_device_register("cr-lcd", 201 ldp = lcd_device_register("cr-lcd", &pdev->dev, NULL, &cr_lcd_ops);
205 &pdev->dev, NULL, 202 if (IS_ERR(ldp)) {
206 &cr_lcd_ops); 203 backlight_device_unregister(bdp);
207
208 if (IS_ERR(crp->cr_lcd_device)) {
209 pci_dev_put(lpc_dev); 204 pci_dev_put(lpc_dev);
210 return PTR_ERR(crp->cr_backlight_device); 205 return PTR_ERR(bdp);
211 } 206 }
212 207
213 pci_read_config_dword(lpc_dev, CRVML_REG_GPIOBAR, 208 pci_read_config_dword(lpc_dev, CRVML_REG_GPIOBAR,
214 &gpio_bar); 209 &gpio_bar);
215 gpio_bar &= ~0x3F; 210 gpio_bar &= ~0x3F;
216 211
212 crp = kzalloc(sizeof(*crp), GFP_KERNEL);
213 if (!crp) {
214 lcd_device_unregister(ldp);
215 backlight_device_unregister(bdp);
216 pci_dev_put(lpc_dev);
217 return -ENOMEM;
218 }
219
220 crp->cr_backlight_device = bdp;
221 crp->cr_lcd_device = ldp;
217 crp->cr_backlight_device->props.power = FB_BLANK_UNBLANK; 222 crp->cr_backlight_device->props.power = FB_BLANK_UNBLANK;
218 crp->cr_backlight_device->props.brightness = 0; 223 crp->cr_backlight_device->props.brightness = 0;
219 crp->cr_backlight_device->props.max_brightness = 0; 224 crp->cr_backlight_device->props.max_brightness = 0;