aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/via/viafbdev.c
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2009-05-19 05:12:58 -0400
committerJonathan Corbet <corbet@lwn.net>2010-04-20 16:23:18 -0400
commit109771a68bedda77606500dc14455eca92df6769 (patch)
tree1ab712aaac8db6de0acadc16e14f2cb9595e1746 /drivers/video/via/viafbdev.c
parent2eaa9cfdf33b8d7fb7aff27792192e0019ae8fc6 (diff)
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>
Diffstat (limited to 'drivers/video/via/viafbdev.c')
-rw-r--r--drivers/video/via/viafbdev.c52
1 files changed, 39 insertions, 13 deletions
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
index ce7783b63f6a..b7018ef69778 100644
--- a/drivers/video/via/viafbdev.c
+++ b/drivers/video/via/viafbdev.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. 2 * Copyright 1998-2009 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. 3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4 4
5 * This program is free software; you can redistribute it and/or 5 * 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,
1737 u32 default_xres, default_yres; 1737 u32 default_xres, default_yres;
1738 struct VideoModeTable *vmode_entry; 1738 struct VideoModeTable *vmode_entry;
1739 struct fb_var_screeninfo default_var; 1739 struct fb_var_screeninfo default_var;
1740 int rc;
1740 u32 viafb_par_length; 1741 u32 viafb_par_length;
1741 1742
1742 DEBUG_MSG(KERN_INFO "VIAFB PCI Probe!!\n"); 1743 DEBUG_MSG(KERN_INFO "VIAFB PCI Probe!!\n");
@@ -1751,7 +1752,7 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
1751 &pdev->dev); 1752 &pdev->dev);
1752 if (!viafbinfo) { 1753 if (!viafbinfo) {
1753 printk(KERN_ERR"Could not allocate memory for viafb_info.\n"); 1754 printk(KERN_ERR"Could not allocate memory for viafb_info.\n");
1754 return -ENODEV; 1755 return -ENOMEM;
1755 } 1756 }
1756 1757
1757 viaparinfo = (struct viafb_par *)viafbinfo->par; 1758 viaparinfo = (struct viafb_par *)viafbinfo->par;
@@ -1774,7 +1775,9 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
1774 viafb_dual_fb = 0; 1775 viafb_dual_fb = 0;
1775 1776
1776 /* Set up I2C bus stuff */ 1777 /* Set up I2C bus stuff */
1777 viafb_create_i2c_bus(viaparinfo); 1778 rc = viafb_create_i2c_bus(viaparinfo);
1779 if (rc)
1780 goto out_fb_release;
1778 1781
1779 viafb_init_chip_info(pdev, ent); 1782 viafb_init_chip_info(pdev, ent);
1780 viaparinfo->fbmem = pci_resource_start(pdev, 0); 1783 viaparinfo->fbmem = pci_resource_start(pdev, 0);
@@ -1785,7 +1788,8 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
1785 viaparinfo->memsize); 1788 viaparinfo->memsize);
1786 if (!viafbinfo->screen_base) { 1789 if (!viafbinfo->screen_base) {
1787 printk(KERN_INFO "ioremap failed\n"); 1790 printk(KERN_INFO "ioremap failed\n");
1788 return -ENOMEM; 1791 rc = -ENOMEM;
1792 goto out_delete_i2c;
1789 } 1793 }
1790 1794
1791 viafbinfo->fix.mmio_start = pci_resource_start(pdev, 1); 1795 viafbinfo->fix.mmio_start = pci_resource_start(pdev, 1);
@@ -1861,8 +1865,8 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
1861 if (!viafbinfo1) { 1865 if (!viafbinfo1) {
1862 printk(KERN_ERR 1866 printk(KERN_ERR
1863 "allocate the second framebuffer struct error\n"); 1867 "allocate the second framebuffer struct error\n");
1864 framebuffer_release(viafbinfo); 1868 rc = -ENOMEM;
1865 return -ENOMEM; 1869 goto out_delete_i2c;
1866 } 1870 }
1867 viaparinfo1 = viafbinfo1->par; 1871 viaparinfo1 = viafbinfo1->par;
1868 memcpy(viaparinfo1, viaparinfo, viafb_par_length); 1872 memcpy(viaparinfo1, viaparinfo, viafb_par_length);
@@ -1913,21 +1917,26 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
1913 viaparinfo->depth = fb_get_color_depth(&viafbinfo->var, 1917 viaparinfo->depth = fb_get_color_depth(&viafbinfo->var,
1914 &viafbinfo->fix); 1918 &viafbinfo->fix);
1915 default_var.activate = FB_ACTIVATE_NOW; 1919 default_var.activate = FB_ACTIVATE_NOW;
1916 fb_alloc_cmap(&viafbinfo->cmap, 256, 0); 1920 rc = fb_alloc_cmap(&viafbinfo->cmap, 256, 0);
1921 if (rc)
1922 goto out_fb1_release;
1917 1923
1918 if (viafb_dual_fb && (viafb_primary_dev == LCD_Device) 1924 if (viafb_dual_fb && (viafb_primary_dev == LCD_Device)
1919 && (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)) { 1925 && (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)) {
1920 if (register_framebuffer(viafbinfo1) < 0) 1926 rc = register_framebuffer(viafbinfo1);
1921 return -EINVAL; 1927 if (rc)
1928 goto out_dealloc_cmap;
1922 } 1929 }
1923 if (register_framebuffer(viafbinfo) < 0) 1930 rc = register_framebuffer(viafbinfo);
1924 return -EINVAL; 1931 if (rc)
1932 goto out_fb1_unreg_lcd_cle266;
1925 1933
1926 if (viafb_dual_fb && ((viafb_primary_dev != LCD_Device) 1934 if (viafb_dual_fb && ((viafb_primary_dev != LCD_Device)
1927 || (viaparinfo->chip_info->gfx_chip_name != 1935 || (viaparinfo->chip_info->gfx_chip_name !=
1928 UNICHROME_CLE266))) { 1936 UNICHROME_CLE266))) {
1929 if (register_framebuffer(viafbinfo1) < 0) 1937 rc = register_framebuffer(viafbinfo1);
1930 return -EINVAL; 1938 if (rc)
1939 goto out_fb_unreg;
1931 } 1940 }
1932 DEBUG_MSG(KERN_INFO "fb%d: %s frame buffer device %dx%d-%dbpp\n", 1941 DEBUG_MSG(KERN_INFO "fb%d: %s frame buffer device %dx%d-%dbpp\n",
1933 viafbinfo->node, viafbinfo->fix.id, default_var.xres, 1942 viafbinfo->node, viafbinfo->fix.id, default_var.xres,
@@ -1936,6 +1945,23 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
1936 viafb_init_proc(&viaparinfo->shared->proc_entry); 1945 viafb_init_proc(&viaparinfo->shared->proc_entry);
1937 viafb_init_dac(IGA2); 1946 viafb_init_dac(IGA2);
1938 return 0; 1947 return 0;
1948
1949out_fb_unreg:
1950 unregister_framebuffer(viafbinfo);
1951out_fb1_unreg_lcd_cle266:
1952 if (viafb_dual_fb && (viafb_primary_dev == LCD_Device)
1953 && (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266))
1954 unregister_framebuffer(viafbinfo1);
1955out_dealloc_cmap:
1956 fb_dealloc_cmap(&viafbinfo->cmap);
1957out_fb1_release:
1958 if (viafbinfo1)
1959 framebuffer_release(viafbinfo1);
1960out_delete_i2c:
1961 viafb_delete_i2c_buss(viaparinfo);
1962out_fb_release:
1963 framebuffer_release(viafbinfo);
1964 return rc;
1939} 1965}
1940 1966
1941static void __devexit via_pci_remove(struct pci_dev *pdev) 1967static void __devexit via_pci_remove(struct pci_dev *pdev)