diff options
author | Jiri Slaby <jirislaby@gmail.com> | 2006-12-08 05:39:10 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-08 11:28:59 -0500 |
commit | 3b85b3413df1feb2b4ef17d829c1ee895fc64075 (patch) | |
tree | 9c968e4554ca6494e413e43d953f34a335c3ad0f | |
parent | fefaf9a789607d3a997d3d05bd2a72586ae0c901 (diff) |
[PATCH] Char: stallion, implement fail paths
This driver expect everything to work. Implement fail paths logic to release
regions, irq hangler, memory... if something is in bad state.
Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | drivers/char/stallion.c | 199 |
1 files changed, 128 insertions, 71 deletions
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index bc2911396b7e..24bdb48310c2 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c | |||
@@ -779,7 +779,8 @@ static void __init stl_argbrds(void) | |||
779 | brdp->ioaddr2 = conf.ioaddr2; | 779 | brdp->ioaddr2 = conf.ioaddr2; |
780 | brdp->irq = conf.irq; | 780 | brdp->irq = conf.irq; |
781 | brdp->irqtype = conf.irqtype; | 781 | brdp->irqtype = conf.irqtype; |
782 | stl_brdinit(brdp); | 782 | if (stl_brdinit(brdp)) |
783 | kfree(brdp); | ||
783 | } | 784 | } |
784 | } | 785 | } |
785 | 786 | ||
@@ -1965,6 +1966,29 @@ static int __init stl_initports(struct stlbrd *brdp, struct stlpanel *panelp) | |||
1965 | return(0); | 1966 | return(0); |
1966 | } | 1967 | } |
1967 | 1968 | ||
1969 | static void stl_cleanup_panels(struct stlbrd *brdp) | ||
1970 | { | ||
1971 | struct stlpanel *panelp; | ||
1972 | struct stlport *portp; | ||
1973 | unsigned int j, k; | ||
1974 | |||
1975 | for (j = 0; j < STL_MAXPANELS; j++) { | ||
1976 | panelp = brdp->panels[j]; | ||
1977 | if (panelp == NULL) | ||
1978 | continue; | ||
1979 | for (k = 0; k < STL_PORTSPERPANEL; k++) { | ||
1980 | portp = panelp->ports[k]; | ||
1981 | if (portp == NULL) | ||
1982 | continue; | ||
1983 | if (portp->tty != NULL) | ||
1984 | stl_hangup(portp->tty); | ||
1985 | kfree(portp->tx.buf); | ||
1986 | kfree(portp); | ||
1987 | } | ||
1988 | kfree(panelp); | ||
1989 | } | ||
1990 | } | ||
1991 | |||
1968 | /*****************************************************************************/ | 1992 | /*****************************************************************************/ |
1969 | 1993 | ||
1970 | /* | 1994 | /* |
@@ -1976,7 +2000,7 @@ static int __init stl_initeio(struct stlbrd *brdp) | |||
1976 | struct stlpanel *panelp; | 2000 | struct stlpanel *panelp; |
1977 | unsigned int status; | 2001 | unsigned int status; |
1978 | char *name; | 2002 | char *name; |
1979 | int rc; | 2003 | int retval; |
1980 | 2004 | ||
1981 | pr_debug("stl_initeio(brdp=%p)\n", brdp); | 2005 | pr_debug("stl_initeio(brdp=%p)\n", brdp); |
1982 | 2006 | ||
@@ -2003,18 +2027,20 @@ static int __init stl_initeio(struct stlbrd *brdp) | |||
2003 | (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) { | 2027 | (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) { |
2004 | printk("STALLION: invalid irq=%d for brd=%d\n", | 2028 | printk("STALLION: invalid irq=%d for brd=%d\n", |
2005 | brdp->irq, brdp->brdnr); | 2029 | brdp->irq, brdp->brdnr); |
2006 | return(-EINVAL); | 2030 | retval = -EINVAL; |
2031 | goto err; | ||
2007 | } | 2032 | } |
2008 | outb((stl_vecmap[brdp->irq] | EIO_0WS | | 2033 | outb((stl_vecmap[brdp->irq] | EIO_0WS | |
2009 | ((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)), | 2034 | ((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)), |
2010 | brdp->ioctrl); | 2035 | brdp->ioctrl); |
2011 | } | 2036 | } |
2012 | 2037 | ||
2038 | retval = -EBUSY; | ||
2013 | if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) { | 2039 | if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) { |
2014 | printk(KERN_WARNING "STALLION: Warning, board %d I/O address " | 2040 | printk(KERN_WARNING "STALLION: Warning, board %d I/O address " |
2015 | "%x conflicts with another device\n", brdp->brdnr, | 2041 | "%x conflicts with another device\n", brdp->brdnr, |
2016 | brdp->ioaddr1); | 2042 | brdp->ioaddr1); |
2017 | return(-EBUSY); | 2043 | goto err; |
2018 | } | 2044 | } |
2019 | 2045 | ||
2020 | if (brdp->iosize2 > 0) | 2046 | if (brdp->iosize2 > 0) |
@@ -2025,8 +2051,7 @@ static int __init stl_initeio(struct stlbrd *brdp) | |||
2025 | printk(KERN_WARNING "STALLION: Warning, also " | 2051 | printk(KERN_WARNING "STALLION: Warning, also " |
2026 | "releasing board %d I/O address %x \n", | 2052 | "releasing board %d I/O address %x \n", |
2027 | brdp->brdnr, brdp->ioaddr1); | 2053 | brdp->brdnr, brdp->ioaddr1); |
2028 | release_region(brdp->ioaddr1, brdp->iosize1); | 2054 | goto err_rel1; |
2029 | return(-EBUSY); | ||
2030 | } | 2055 | } |
2031 | 2056 | ||
2032 | /* | 2057 | /* |
@@ -2035,6 +2060,7 @@ static int __init stl_initeio(struct stlbrd *brdp) | |||
2035 | brdp->clk = CD1400_CLK; | 2060 | brdp->clk = CD1400_CLK; |
2036 | brdp->isr = stl_eiointr; | 2061 | brdp->isr = stl_eiointr; |
2037 | 2062 | ||
2063 | retval = -ENODEV; | ||
2038 | switch (status & EIO_IDBITMASK) { | 2064 | switch (status & EIO_IDBITMASK) { |
2039 | case EIO_8PORTM: | 2065 | case EIO_8PORTM: |
2040 | brdp->clk = CD1400_CLK8M; | 2066 | brdp->clk = CD1400_CLK8M; |
@@ -2058,11 +2084,11 @@ static int __init stl_initeio(struct stlbrd *brdp) | |||
2058 | brdp->nrports = 16; | 2084 | brdp->nrports = 16; |
2059 | break; | 2085 | break; |
2060 | default: | 2086 | default: |
2061 | return(-ENODEV); | 2087 | goto err_rel2; |
2062 | } | 2088 | } |
2063 | break; | 2089 | break; |
2064 | default: | 2090 | default: |
2065 | return(-ENODEV); | 2091 | goto err_rel2; |
2066 | } | 2092 | } |
2067 | 2093 | ||
2068 | /* | 2094 | /* |
@@ -2074,7 +2100,8 @@ static int __init stl_initeio(struct stlbrd *brdp) | |||
2074 | if (!panelp) { | 2100 | if (!panelp) { |
2075 | printk(KERN_WARNING "STALLION: failed to allocate memory " | 2101 | printk(KERN_WARNING "STALLION: failed to allocate memory " |
2076 | "(size=%Zd)\n", sizeof(struct stlpanel)); | 2102 | "(size=%Zd)\n", sizeof(struct stlpanel)); |
2077 | return -ENOMEM; | 2103 | retval = -ENOMEM; |
2104 | goto err_rel2; | ||
2078 | } | 2105 | } |
2079 | 2106 | ||
2080 | panelp->magic = STL_PANELMAGIC; | 2107 | panelp->magic = STL_PANELMAGIC; |
@@ -2098,11 +2125,20 @@ static int __init stl_initeio(struct stlbrd *brdp) | |||
2098 | if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) { | 2125 | if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) { |
2099 | printk("STALLION: failed to register interrupt " | 2126 | printk("STALLION: failed to register interrupt " |
2100 | "routine for %s irq=%d\n", name, brdp->irq); | 2127 | "routine for %s irq=%d\n", name, brdp->irq); |
2101 | rc = -ENODEV; | 2128 | retval = -ENODEV; |
2102 | } else { | 2129 | goto err_fr; |
2103 | rc = 0; | ||
2104 | } | 2130 | } |
2105 | return rc; | 2131 | |
2132 | return 0; | ||
2133 | err_fr: | ||
2134 | stl_cleanup_panels(brdp); | ||
2135 | err_rel2: | ||
2136 | if (brdp->iosize2 > 0) | ||
2137 | release_region(brdp->ioaddr2, brdp->iosize2); | ||
2138 | err_rel1: | ||
2139 | release_region(brdp->ioaddr1, brdp->iosize1); | ||
2140 | err: | ||
2141 | return retval; | ||
2106 | } | 2142 | } |
2107 | 2143 | ||
2108 | /*****************************************************************************/ | 2144 | /*****************************************************************************/ |
@@ -2116,7 +2152,7 @@ static int __init stl_initech(struct stlbrd *brdp) | |||
2116 | { | 2152 | { |
2117 | struct stlpanel *panelp; | 2153 | struct stlpanel *panelp; |
2118 | unsigned int status, nxtid, ioaddr, conflict; | 2154 | unsigned int status, nxtid, ioaddr, conflict; |
2119 | int panelnr, banknr, i; | 2155 | int panelnr, banknr, i, retval; |
2120 | char *name; | 2156 | char *name; |
2121 | 2157 | ||
2122 | pr_debug("stl_initech(brdp=%p)\n", brdp); | 2158 | pr_debug("stl_initech(brdp=%p)\n", brdp); |
@@ -2136,13 +2172,16 @@ static int __init stl_initech(struct stlbrd *brdp) | |||
2136 | brdp->ioctrl = brdp->ioaddr1 + 1; | 2172 | brdp->ioctrl = brdp->ioaddr1 + 1; |
2137 | brdp->iostatus = brdp->ioaddr1 + 1; | 2173 | brdp->iostatus = brdp->ioaddr1 + 1; |
2138 | status = inb(brdp->iostatus); | 2174 | status = inb(brdp->iostatus); |
2139 | if ((status & ECH_IDBITMASK) != ECH_ID) | 2175 | if ((status & ECH_IDBITMASK) != ECH_ID) { |
2140 | return(-ENODEV); | 2176 | retval = -ENODEV; |
2177 | goto err; | ||
2178 | } | ||
2141 | if ((brdp->irq < 0) || (brdp->irq > 15) || | 2179 | if ((brdp->irq < 0) || (brdp->irq > 15) || |
2142 | (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) { | 2180 | (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) { |
2143 | printk("STALLION: invalid irq=%d for brd=%d\n", | 2181 | printk("STALLION: invalid irq=%d for brd=%d\n", |
2144 | brdp->irq, brdp->brdnr); | 2182 | brdp->irq, brdp->brdnr); |
2145 | return(-EINVAL); | 2183 | retval = -EINVAL; |
2184 | goto err; | ||
2146 | } | 2185 | } |
2147 | status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1); | 2186 | status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1); |
2148 | status |= (stl_vecmap[brdp->irq] << 1); | 2187 | status |= (stl_vecmap[brdp->irq] << 1); |
@@ -2162,13 +2201,16 @@ static int __init stl_initech(struct stlbrd *brdp) | |||
2162 | brdp->ioctrl = brdp->ioaddr1 + 0x20; | 2201 | brdp->ioctrl = brdp->ioaddr1 + 0x20; |
2163 | brdp->iostatus = brdp->ioctrl; | 2202 | brdp->iostatus = brdp->ioctrl; |
2164 | status = inb(brdp->iostatus); | 2203 | status = inb(brdp->iostatus); |
2165 | if ((status & ECH_IDBITMASK) != ECH_ID) | 2204 | if ((status & ECH_IDBITMASK) != ECH_ID) { |
2166 | return(-ENODEV); | 2205 | retval = -ENODEV; |
2206 | goto err; | ||
2207 | } | ||
2167 | if ((brdp->irq < 0) || (brdp->irq > 15) || | 2208 | if ((brdp->irq < 0) || (brdp->irq > 15) || |
2168 | (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) { | 2209 | (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) { |
2169 | printk("STALLION: invalid irq=%d for brd=%d\n", | 2210 | printk("STALLION: invalid irq=%d for brd=%d\n", |
2170 | brdp->irq, brdp->brdnr); | 2211 | brdp->irq, brdp->brdnr); |
2171 | return(-EINVAL); | 2212 | retval = -EINVAL; |
2213 | goto err; | ||
2172 | } | 2214 | } |
2173 | outb(ECHMC_BRDRESET, brdp->ioctrl); | 2215 | outb(ECHMC_BRDRESET, brdp->ioctrl); |
2174 | outb(ECHMC_INTENABLE, brdp->ioctrl); | 2216 | outb(ECHMC_INTENABLE, brdp->ioctrl); |
@@ -2195,19 +2237,20 @@ static int __init stl_initech(struct stlbrd *brdp) | |||
2195 | 2237 | ||
2196 | default: | 2238 | default: |
2197 | printk("STALLION: unknown board type=%d\n", brdp->brdtype); | 2239 | printk("STALLION: unknown board type=%d\n", brdp->brdtype); |
2198 | return(-EINVAL); | 2240 | retval = -EINVAL; |
2199 | break; | 2241 | goto err; |
2200 | } | 2242 | } |
2201 | 2243 | ||
2202 | /* | 2244 | /* |
2203 | * Check boards for possible IO address conflicts and return fail status | 2245 | * Check boards for possible IO address conflicts and return fail status |
2204 | * if an IO conflict found. | 2246 | * if an IO conflict found. |
2205 | */ | 2247 | */ |
2248 | retval = -EBUSY; | ||
2206 | if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) { | 2249 | if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) { |
2207 | printk(KERN_WARNING "STALLION: Warning, board %d I/O address " | 2250 | printk(KERN_WARNING "STALLION: Warning, board %d I/O address " |
2208 | "%x conflicts with another device\n", brdp->brdnr, | 2251 | "%x conflicts with another device\n", brdp->brdnr, |
2209 | brdp->ioaddr1); | 2252 | brdp->ioaddr1); |
2210 | return(-EBUSY); | 2253 | goto err; |
2211 | } | 2254 | } |
2212 | 2255 | ||
2213 | if (brdp->iosize2 > 0) | 2256 | if (brdp->iosize2 > 0) |
@@ -2218,8 +2261,7 @@ static int __init stl_initech(struct stlbrd *brdp) | |||
2218 | printk(KERN_WARNING "STALLION: Warning, also " | 2261 | printk(KERN_WARNING "STALLION: Warning, also " |
2219 | "releasing board %d I/O address %x \n", | 2262 | "releasing board %d I/O address %x \n", |
2220 | brdp->brdnr, brdp->ioaddr1); | 2263 | brdp->brdnr, brdp->ioaddr1); |
2221 | release_region(brdp->ioaddr1, brdp->iosize1); | 2264 | goto err_rel1; |
2222 | return(-EBUSY); | ||
2223 | } | 2265 | } |
2224 | 2266 | ||
2225 | /* | 2267 | /* |
@@ -2241,12 +2283,12 @@ static int __init stl_initech(struct stlbrd *brdp) | |||
2241 | } | 2283 | } |
2242 | status = inb(ioaddr + ECH_PNLSTATUS); | 2284 | status = inb(ioaddr + ECH_PNLSTATUS); |
2243 | if ((status & ECH_PNLIDMASK) != nxtid) | 2285 | if ((status & ECH_PNLIDMASK) != nxtid) |
2244 | break; | 2286 | goto err_fr; |
2245 | panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL); | 2287 | panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL); |
2246 | if (!panelp) { | 2288 | if (!panelp) { |
2247 | printk("STALLION: failed to allocate memory " | 2289 | printk("STALLION: failed to allocate memory " |
2248 | "(size=%Zd)\n", sizeof(struct stlpanel)); | 2290 | "(size=%Zd)\n", sizeof(struct stlpanel)); |
2249 | break; | 2291 | goto err_fr; |
2250 | } | 2292 | } |
2251 | panelp->magic = STL_PANELMAGIC; | 2293 | panelp->magic = STL_PANELMAGIC; |
2252 | panelp->brdnr = brdp->brdnr; | 2294 | panelp->brdnr = brdp->brdnr; |
@@ -2294,7 +2336,7 @@ static int __init stl_initech(struct stlbrd *brdp) | |||
2294 | brdp->panels[panelnr++] = panelp; | 2336 | brdp->panels[panelnr++] = panelp; |
2295 | if ((brdp->brdtype != BRD_ECHPCI) && | 2337 | if ((brdp->brdtype != BRD_ECHPCI) && |
2296 | (ioaddr >= (brdp->ioaddr2 + brdp->iosize2))) | 2338 | (ioaddr >= (brdp->ioaddr2 + brdp->iosize2))) |
2297 | break; | 2339 | goto err_fr; |
2298 | } | 2340 | } |
2299 | 2341 | ||
2300 | brdp->nrpanels = panelnr; | 2342 | brdp->nrpanels = panelnr; |
@@ -2306,12 +2348,19 @@ static int __init stl_initech(struct stlbrd *brdp) | |||
2306 | if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) { | 2348 | if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) { |
2307 | printk("STALLION: failed to register interrupt " | 2349 | printk("STALLION: failed to register interrupt " |
2308 | "routine for %s irq=%d\n", name, brdp->irq); | 2350 | "routine for %s irq=%d\n", name, brdp->irq); |
2309 | i = -ENODEV; | 2351 | retval = -ENODEV; |
2310 | } else { | 2352 | goto err_fr; |
2311 | i = 0; | ||
2312 | } | 2353 | } |
2313 | 2354 | ||
2314 | return(i); | 2355 | return 0; |
2356 | err_fr: | ||
2357 | stl_cleanup_panels(brdp); | ||
2358 | if (brdp->iosize2 > 0) | ||
2359 | release_region(brdp->ioaddr2, brdp->iosize2); | ||
2360 | err_rel1: | ||
2361 | release_region(brdp->ioaddr1, brdp->iosize1); | ||
2362 | err: | ||
2363 | return retval; | ||
2315 | } | 2364 | } |
2316 | 2365 | ||
2317 | /*****************************************************************************/ | 2366 | /*****************************************************************************/ |
@@ -2325,25 +2374,30 @@ static int __init stl_initech(struct stlbrd *brdp) | |||
2325 | 2374 | ||
2326 | static int __init stl_brdinit(struct stlbrd *brdp) | 2375 | static int __init stl_brdinit(struct stlbrd *brdp) |
2327 | { | 2376 | { |
2328 | int i; | 2377 | int i, retval; |
2329 | 2378 | ||
2330 | pr_debug("stl_brdinit(brdp=%p)\n", brdp); | 2379 | pr_debug("stl_brdinit(brdp=%p)\n", brdp); |
2331 | 2380 | ||
2332 | switch (brdp->brdtype) { | 2381 | switch (brdp->brdtype) { |
2333 | case BRD_EASYIO: | 2382 | case BRD_EASYIO: |
2334 | case BRD_EASYIOPCI: | 2383 | case BRD_EASYIOPCI: |
2335 | stl_initeio(brdp); | 2384 | retval = stl_initeio(brdp); |
2385 | if (retval) | ||
2386 | goto err; | ||
2336 | break; | 2387 | break; |
2337 | case BRD_ECH: | 2388 | case BRD_ECH: |
2338 | case BRD_ECHMC: | 2389 | case BRD_ECHMC: |
2339 | case BRD_ECHPCI: | 2390 | case BRD_ECHPCI: |
2340 | case BRD_ECH64PCI: | 2391 | case BRD_ECH64PCI: |
2341 | stl_initech(brdp); | 2392 | retval = stl_initech(brdp); |
2393 | if (retval) | ||
2394 | goto err; | ||
2342 | break; | 2395 | break; |
2343 | default: | 2396 | default: |
2344 | printk("STALLION: board=%d is unknown board type=%d\n", | 2397 | printk("STALLION: board=%d is unknown board type=%d\n", |
2345 | brdp->brdnr, brdp->brdtype); | 2398 | brdp->brdnr, brdp->brdtype); |
2346 | return(ENODEV); | 2399 | retval = -ENODEV; |
2400 | goto err; | ||
2347 | } | 2401 | } |
2348 | 2402 | ||
2349 | stl_brds[brdp->brdnr] = brdp; | 2403 | stl_brds[brdp->brdnr] = brdp; |
@@ -2351,7 +2405,7 @@ static int __init stl_brdinit(struct stlbrd *brdp) | |||
2351 | printk("STALLION: %s board not found, board=%d io=%x irq=%d\n", | 2405 | printk("STALLION: %s board not found, board=%d io=%x irq=%d\n", |
2352 | stl_brdnames[brdp->brdtype], brdp->brdnr, | 2406 | stl_brdnames[brdp->brdtype], brdp->brdnr, |
2353 | brdp->ioaddr1, brdp->irq); | 2407 | brdp->ioaddr1, brdp->irq); |
2354 | return(ENODEV); | 2408 | goto err_free; |
2355 | } | 2409 | } |
2356 | 2410 | ||
2357 | for (i = 0; (i < STL_MAXPANELS); i++) | 2411 | for (i = 0; (i < STL_MAXPANELS); i++) |
@@ -2362,7 +2416,20 @@ static int __init stl_brdinit(struct stlbrd *brdp) | |||
2362 | "nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype], | 2416 | "nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype], |
2363 | brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels, | 2417 | brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels, |
2364 | brdp->nrports); | 2418 | brdp->nrports); |
2365 | return(0); | 2419 | |
2420 | return 0; | ||
2421 | err_free: | ||
2422 | free_irq(brdp->irq, brdp); | ||
2423 | |||
2424 | stl_cleanup_panels(brdp); | ||
2425 | |||
2426 | release_region(brdp->ioaddr1, brdp->iosize1); | ||
2427 | if (brdp->iosize2 > 0) | ||
2428 | release_region(brdp->ioaddr2, brdp->iosize2); | ||
2429 | |||
2430 | stl_brds[brdp->brdnr] = NULL; | ||
2431 | err: | ||
2432 | return retval; | ||
2366 | } | 2433 | } |
2367 | 2434 | ||
2368 | /*****************************************************************************/ | 2435 | /*****************************************************************************/ |
@@ -2385,29 +2452,6 @@ static int __init stl_getbrdnr(void) | |||
2385 | return(-1); | 2452 | return(-1); |
2386 | } | 2453 | } |
2387 | 2454 | ||
2388 | static void stl_cleanup_panels(struct stlbrd *brdp) | ||
2389 | { | ||
2390 | struct stlpanel *panelp; | ||
2391 | struct stlport *portp; | ||
2392 | unsigned int j, k; | ||
2393 | |||
2394 | for (j = 0; j < STL_MAXPANELS; j++) { | ||
2395 | panelp = brdp->panels[j]; | ||
2396 | if (panelp == NULL) | ||
2397 | continue; | ||
2398 | for (k = 0; k < STL_PORTSPERPANEL; k++) { | ||
2399 | portp = panelp->ports[k]; | ||
2400 | if (portp == NULL) | ||
2401 | continue; | ||
2402 | if (portp->tty != NULL) | ||
2403 | stl_hangup(portp->tty); | ||
2404 | kfree(portp->tx.buf); | ||
2405 | kfree(portp); | ||
2406 | } | ||
2407 | kfree(panelp); | ||
2408 | } | ||
2409 | } | ||
2410 | |||
2411 | /*****************************************************************************/ | 2455 | /*****************************************************************************/ |
2412 | /* | 2456 | /* |
2413 | * We have a Stallion board. Allocate a board structure and | 2457 | * We have a Stallion board. Allocate a board structure and |
@@ -2420,21 +2464,27 @@ static int __devinit stl_pciprobe(struct pci_dev *pdev, | |||
2420 | { | 2464 | { |
2421 | struct stlbrd *brdp; | 2465 | struct stlbrd *brdp; |
2422 | unsigned int brdtype = ent->driver_data; | 2466 | unsigned int brdtype = ent->driver_data; |
2467 | int retval = -ENODEV; | ||
2423 | 2468 | ||
2424 | if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) | 2469 | if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) |
2425 | return -ENODEV; | 2470 | goto err; |
2426 | 2471 | ||
2427 | dev_info(&pdev->dev, "please, report this to LKML: %x/%x/%x\n", | 2472 | dev_info(&pdev->dev, "please, report this to LKML: %x/%x/%x\n", |
2428 | pdev->vendor, pdev->device, pdev->class); | 2473 | pdev->vendor, pdev->device, pdev->class); |
2429 | 2474 | ||
2430 | if (pci_enable_device(pdev)) | 2475 | retval = pci_enable_device(pdev); |
2431 | return(-EIO); | 2476 | if (retval) |
2432 | if ((brdp = stl_allocbrd()) == NULL) | 2477 | goto err; |
2433 | return(-ENOMEM); | 2478 | brdp = stl_allocbrd(); |
2434 | if ((brdp->brdnr = stl_getbrdnr()) < 0) { | 2479 | if (brdp == NULL) { |
2480 | retval = -ENOMEM; | ||
2481 | goto err; | ||
2482 | } | ||
2483 | brdp->brdnr = stl_getbrdnr(); | ||
2484 | if (brdp->brdnr < 0) { | ||
2435 | dev_err(&pdev->dev, "too many boards found, " | 2485 | dev_err(&pdev->dev, "too many boards found, " |
2436 | "maximum supported %d\n", STL_MAXBRDS); | 2486 | "maximum supported %d\n", STL_MAXBRDS); |
2437 | return(0); | 2487 | goto err_fr; |
2438 | } | 2488 | } |
2439 | brdp->brdtype = brdtype; | 2489 | brdp->brdtype = brdtype; |
2440 | 2490 | ||
@@ -2461,11 +2511,17 @@ static int __devinit stl_pciprobe(struct pci_dev *pdev, | |||
2461 | } | 2511 | } |
2462 | 2512 | ||
2463 | brdp->irq = pdev->irq; | 2513 | brdp->irq = pdev->irq; |
2464 | stl_brdinit(brdp); | 2514 | retval = stl_brdinit(brdp); |
2515 | if (retval) | ||
2516 | goto err_fr; | ||
2465 | 2517 | ||
2466 | pci_set_drvdata(pdev, brdp); | 2518 | pci_set_drvdata(pdev, brdp); |
2467 | 2519 | ||
2468 | return(0); | 2520 | return 0; |
2521 | err_fr: | ||
2522 | kfree(brdp); | ||
2523 | err: | ||
2524 | return retval; | ||
2469 | } | 2525 | } |
2470 | 2526 | ||
2471 | static void __devexit stl_pciremove(struct pci_dev *pdev) | 2527 | static void __devexit stl_pciremove(struct pci_dev *pdev) |
@@ -2528,7 +2584,8 @@ static int __init stl_initbrds(void) | |||
2528 | brdp->ioaddr2 = confp->ioaddr2; | 2584 | brdp->ioaddr2 = confp->ioaddr2; |
2529 | brdp->irq = confp->irq; | 2585 | brdp->irq = confp->irq; |
2530 | brdp->irqtype = confp->irqtype; | 2586 | brdp->irqtype = confp->irqtype; |
2531 | stl_brdinit(brdp); | 2587 | if (stl_brdinit(brdp)) |
2588 | kfree(brdp); | ||
2532 | } | 2589 | } |
2533 | 2590 | ||
2534 | /* | 2591 | /* |