viafb: Fix various resource leaks during module_init()
The current code executed from module_init() in viafb does not have proper error checking and [partial] resoure release paths in case an error happens half way through driver initialization. This patch adresses the most obvious of those issues, such as a leftover i2c bus if module_init (and thus module load) fails. [jc: fixed merge conflicts] [jc: also restored -ENOMEM return on ioremap() fail] Cc: Florian Tobias Schandinat <FlorianSchandinat@gmx.de> Cc: ScottFang@viatech.com.cn Cc: JosephChan@via.com.tw Signed-off-by: Harald Welte <HaraldWelte@viatech.com>
This commit is contained in:
Родитель
2eaa9cfdf3
Коммит
109771a68b
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
|
||||
* Copyright 1998-2009 VIA Technologies, Inc. All Rights Reserved.
|
||||
* Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
|
||||
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
@ -1737,6 +1737,7 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
|
|||
u32 default_xres, default_yres;
|
||||
struct VideoModeTable *vmode_entry;
|
||||
struct fb_var_screeninfo default_var;
|
||||
int rc;
|
||||
u32 viafb_par_length;
|
||||
|
||||
DEBUG_MSG(KERN_INFO "VIAFB PCI Probe!!\n");
|
||||
|
@ -1751,7 +1752,7 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
|
|||
&pdev->dev);
|
||||
if (!viafbinfo) {
|
||||
printk(KERN_ERR"Could not allocate memory for viafb_info.\n");
|
||||
return -ENODEV;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
viaparinfo = (struct viafb_par *)viafbinfo->par;
|
||||
|
@ -1774,7 +1775,9 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
|
|||
viafb_dual_fb = 0;
|
||||
|
||||
/* Set up I2C bus stuff */
|
||||
viafb_create_i2c_bus(viaparinfo);
|
||||
rc = viafb_create_i2c_bus(viaparinfo);
|
||||
if (rc)
|
||||
goto out_fb_release;
|
||||
|
||||
viafb_init_chip_info(pdev, ent);
|
||||
viaparinfo->fbmem = pci_resource_start(pdev, 0);
|
||||
|
@ -1785,7 +1788,8 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
|
|||
viaparinfo->memsize);
|
||||
if (!viafbinfo->screen_base) {
|
||||
printk(KERN_INFO "ioremap failed\n");
|
||||
return -ENOMEM;
|
||||
rc = -ENOMEM;
|
||||
goto out_delete_i2c;
|
||||
}
|
||||
|
||||
viafbinfo->fix.mmio_start = pci_resource_start(pdev, 1);
|
||||
|
@ -1861,8 +1865,8 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
|
|||
if (!viafbinfo1) {
|
||||
printk(KERN_ERR
|
||||
"allocate the second framebuffer struct error\n");
|
||||
framebuffer_release(viafbinfo);
|
||||
return -ENOMEM;
|
||||
rc = -ENOMEM;
|
||||
goto out_delete_i2c;
|
||||
}
|
||||
viaparinfo1 = viafbinfo1->par;
|
||||
memcpy(viaparinfo1, viaparinfo, viafb_par_length);
|
||||
|
@ -1913,21 +1917,26 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
|
|||
viaparinfo->depth = fb_get_color_depth(&viafbinfo->var,
|
||||
&viafbinfo->fix);
|
||||
default_var.activate = FB_ACTIVATE_NOW;
|
||||
fb_alloc_cmap(&viafbinfo->cmap, 256, 0);
|
||||
rc = fb_alloc_cmap(&viafbinfo->cmap, 256, 0);
|
||||
if (rc)
|
||||
goto out_fb1_release;
|
||||
|
||||
if (viafb_dual_fb && (viafb_primary_dev == LCD_Device)
|
||||
&& (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)) {
|
||||
if (register_framebuffer(viafbinfo1) < 0)
|
||||
return -EINVAL;
|
||||
rc = register_framebuffer(viafbinfo1);
|
||||
if (rc)
|
||||
goto out_dealloc_cmap;
|
||||
}
|
||||
if (register_framebuffer(viafbinfo) < 0)
|
||||
return -EINVAL;
|
||||
rc = register_framebuffer(viafbinfo);
|
||||
if (rc)
|
||||
goto out_fb1_unreg_lcd_cle266;
|
||||
|
||||
if (viafb_dual_fb && ((viafb_primary_dev != LCD_Device)
|
||||
|| (viaparinfo->chip_info->gfx_chip_name !=
|
||||
UNICHROME_CLE266))) {
|
||||
if (register_framebuffer(viafbinfo1) < 0)
|
||||
return -EINVAL;
|
||||
rc = register_framebuffer(viafbinfo1);
|
||||
if (rc)
|
||||
goto out_fb_unreg;
|
||||
}
|
||||
DEBUG_MSG(KERN_INFO "fb%d: %s frame buffer device %dx%d-%dbpp\n",
|
||||
viafbinfo->node, viafbinfo->fix.id, default_var.xres,
|
||||
|
@ -1936,6 +1945,23 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
|
|||
viafb_init_proc(&viaparinfo->shared->proc_entry);
|
||||
viafb_init_dac(IGA2);
|
||||
return 0;
|
||||
|
||||
out_fb_unreg:
|
||||
unregister_framebuffer(viafbinfo);
|
||||
out_fb1_unreg_lcd_cle266:
|
||||
if (viafb_dual_fb && (viafb_primary_dev == LCD_Device)
|
||||
&& (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266))
|
||||
unregister_framebuffer(viafbinfo1);
|
||||
out_dealloc_cmap:
|
||||
fb_dealloc_cmap(&viafbinfo->cmap);
|
||||
out_fb1_release:
|
||||
if (viafbinfo1)
|
||||
framebuffer_release(viafbinfo1);
|
||||
out_delete_i2c:
|
||||
viafb_delete_i2c_buss(viaparinfo);
|
||||
out_fb_release:
|
||||
framebuffer_release(viafbinfo);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void __devexit via_pci_remove(struct pci_dev *pdev)
|
||||
|
|
Загрузка…
Ссылка в новой задаче