diff options
author | Harald Welte <laforge@gnumonks.org> | 2009-05-19 05:12:58 -0400 |
---|---|---|
committer | Jonathan Corbet <corbet@lwn.net> | 2010-04-20 16:23:18 -0400 |
commit | 109771a68bedda77606500dc14455eca92df6769 (patch) | |
tree | 1ab712aaac8db6de0acadc16e14f2cb9595e1746 /drivers/video/via | |
parent | 2eaa9cfdf33b8d7fb7aff27792192e0019ae8fc6 (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')
-rw-r--r-- | drivers/video/via/viafbdev.c | 52 |
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 | |||
1949 | out_fb_unreg: | ||
1950 | unregister_framebuffer(viafbinfo); | ||
1951 | out_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); | ||
1955 | out_dealloc_cmap: | ||
1956 | fb_dealloc_cmap(&viafbinfo->cmap); | ||
1957 | out_fb1_release: | ||
1958 | if (viafbinfo1) | ||
1959 | framebuffer_release(viafbinfo1); | ||
1960 | out_delete_i2c: | ||
1961 | viafb_delete_i2c_buss(viaparinfo); | ||
1962 | out_fb_release: | ||
1963 | framebuffer_release(viafbinfo); | ||
1964 | return rc; | ||
1939 | } | 1965 | } |
1940 | 1966 | ||
1941 | static void __devexit via_pci_remove(struct pci_dev *pdev) | 1967 | static void __devexit via_pci_remove(struct pci_dev *pdev) |