Commit bb694da8 authored by Alexander Viro's avatar Alexander Viro Committed by Stephen Hemminger

[wan sdla] Fixed leaks and double-free

parent 12ea7c9d
...@@ -1339,6 +1339,8 @@ int sdla_set_config(struct net_device *dev, struct ifmap *map) ...@@ -1339,6 +1339,8 @@ int sdla_set_config(struct net_device *dev, struct ifmap *map)
struct frad_local *flp; struct frad_local *flp;
int i; int i;
char byte; char byte;
unsigned base;
int err = -EINVAL;
flp = dev->priv; flp = dev->priv;
...@@ -1352,108 +1354,90 @@ int sdla_set_config(struct net_device *dev, struct ifmap *map) ...@@ -1352,108 +1354,90 @@ int sdla_set_config(struct net_device *dev, struct ifmap *map)
if (i == sizeof(valid_port) / sizeof(int)) if (i == sizeof(valid_port) / sizeof(int))
return(-EINVAL); return(-EINVAL);
dev->base_addr = map->base_addr; if (!request_region(map->base_addr, SDLA_IO_EXTENTS, dev->name)){
if (!request_region(dev->base_addr, SDLA_IO_EXTENTS, dev->name)){
printk(KERN_WARNING "SDLA: io-port 0x%04lx in use \n", dev->base_addr); printk(KERN_WARNING "SDLA: io-port 0x%04lx in use \n", dev->base_addr);
return(-EINVAL); return(-EINVAL);
} }
base = map->base_addr;
/* test for card types, S502A, S502E, S507, S508 */ /* test for card types, S502A, S502E, S507, S508 */
/* these tests shut down the card completely, so clear the state */ /* these tests shut down the card completely, so clear the state */
flp->type = SDLA_UNKNOWN; flp->type = SDLA_UNKNOWN;
flp->state = 0; flp->state = 0;
for(i=1;i<SDLA_IO_EXTENTS;i++) for(i=1;i<SDLA_IO_EXTENTS;i++)
if (inb(dev->base_addr + i) != 0xFF) if (inb(base + i) != 0xFF)
break; break;
if (i == SDLA_IO_EXTENTS) if (i == SDLA_IO_EXTENTS) {
{ outb(SDLA_HALT, base + SDLA_REG_Z80_CONTROL);
outb(SDLA_HALT, dev->base_addr + SDLA_REG_Z80_CONTROL); if ((inb(base + SDLA_S502_STS) & 0x0F) == 0x08) {
if ((inb(dev->base_addr + SDLA_S502_STS) & 0x0F) == 0x08) outb(SDLA_S502E_INTACK, base + SDLA_REG_CONTROL);
{ if ((inb(base + SDLA_S502_STS) & 0x0F) == 0x0C) {
outb(SDLA_S502E_INTACK, dev->base_addr + SDLA_REG_CONTROL); outb(SDLA_HALT, base + SDLA_REG_CONTROL);
if ((inb(dev->base_addr + SDLA_S502_STS) & 0x0F) == 0x0C)
{
outb(SDLA_HALT, dev->base_addr + SDLA_REG_CONTROL);
flp->type = SDLA_S502E; flp->type = SDLA_S502E;
goto got_type;
} }
} }
} }
if (flp->type == SDLA_UNKNOWN) for(byte=inb(base),i=0;i<SDLA_IO_EXTENTS;i++)
{ if (inb(base + i) != byte)
for(byte=inb(dev->base_addr),i=0;i<SDLA_IO_EXTENTS;i++) break;
if (inb(dev->base_addr + i) != byte)
break;
if (i == SDLA_IO_EXTENTS) if (i == SDLA_IO_EXTENTS) {
{ outb(SDLA_HALT, base + SDLA_REG_CONTROL);
outb(SDLA_HALT, dev->base_addr + SDLA_REG_CONTROL); if ((inb(base + SDLA_S502_STS) & 0x7E) == 0x30) {
if ((inb(dev->base_addr + SDLA_S502_STS) & 0x7E) == 0x30) outb(SDLA_S507_ENABLE, base + SDLA_REG_CONTROL);
{ if ((inb(base + SDLA_S502_STS) & 0x7E) == 0x32) {
outb(SDLA_S507_ENABLE, dev->base_addr + SDLA_REG_CONTROL); outb(SDLA_HALT, base + SDLA_REG_CONTROL);
if ((inb(dev->base_addr + SDLA_S502_STS) & 0x7E) == 0x32) flp->type = SDLA_S507;
{ goto got_type;
outb(SDLA_HALT, dev->base_addr + SDLA_REG_CONTROL);
flp->type = SDLA_S507;
}
} }
} }
} }
if (flp->type == SDLA_UNKNOWN) outb(SDLA_HALT, base + SDLA_REG_CONTROL);
{ if ((inb(base + SDLA_S508_STS) & 0x3F) == 0x00) {
outb(SDLA_HALT, dev->base_addr + SDLA_REG_CONTROL); outb(SDLA_S508_INTEN, base + SDLA_REG_CONTROL);
if ((inb(dev->base_addr + SDLA_S508_STS) & 0x3F) == 0x00) if ((inb(base + SDLA_S508_STS) & 0x3F) == 0x10) {
{ outb(SDLA_HALT, base + SDLA_REG_CONTROL);
outb(SDLA_S508_INTEN, dev->base_addr + SDLA_REG_CONTROL); flp->type = SDLA_S508;
if ((inb(dev->base_addr + SDLA_S508_STS) & 0x3F) == 0x10) goto got_type;
{
outb(SDLA_HALT, dev->base_addr + SDLA_REG_CONTROL);
flp->type = SDLA_S508;
}
} }
} }
if (flp->type == SDLA_UNKNOWN) outb(SDLA_S502A_HALT, base + SDLA_REG_CONTROL);
{ if (inb(base + SDLA_S502_STS) == 0x40) {
outb(SDLA_S502A_HALT, dev->base_addr + SDLA_REG_CONTROL); outb(SDLA_S502A_START, base + SDLA_REG_CONTROL);
if (inb(dev->base_addr + SDLA_S502_STS) == 0x40) if (inb(base + SDLA_S502_STS) == 0x40) {
{ outb(SDLA_S502A_INTEN, base + SDLA_REG_CONTROL);
outb(SDLA_S502A_START, dev->base_addr + SDLA_REG_CONTROL); if (inb(base + SDLA_S502_STS) == 0x44) {
if (inb(dev->base_addr + SDLA_S502_STS) == 0x40) outb(SDLA_S502A_START, base + SDLA_REG_CONTROL);
{ flp->type = SDLA_S502A;
outb(SDLA_S502A_INTEN, dev->base_addr + SDLA_REG_CONTROL); goto got_type;
if (inb(dev->base_addr + SDLA_S502_STS) == 0x44)
{
outb(SDLA_S502A_START, dev->base_addr + SDLA_REG_CONTROL);
flp->type = SDLA_S502A;
}
} }
} }
} }
if (flp->type == SDLA_UNKNOWN) printk(KERN_NOTICE "%s: Unknown card type\n", dev->name);
{ err = -ENODEV;
printk(KERN_NOTICE "%s: Unknown card type\n", dev->name); goto fail;
return(-ENODEV);
}
switch(dev->base_addr) got_type:
{ switch(base) {
case 0x270: case 0x270:
case 0x280: case 0x280:
case 0x380: case 0x380:
case 0x390: case 0x390:
if ((flp->type != SDLA_S508) && (flp->type != SDLA_S507)) if (flp->type != SDLA_S508 && flp->type != SDLA_S507)
return(-EINVAL); goto fail;
} }
switch (map->irq) switch (map->irq) {
{
case 2: case 2:
if (flp->type != SDLA_S502E) if (flp->type != SDLA_S502E)
return(-EINVAL); goto fail;
break; break;
case 10: case 10:
...@@ -1461,28 +1445,26 @@ int sdla_set_config(struct net_device *dev, struct ifmap *map) ...@@ -1461,28 +1445,26 @@ int sdla_set_config(struct net_device *dev, struct ifmap *map)
case 12: case 12:
case 15: case 15:
case 4: case 4:
if ((flp->type != SDLA_S508) && (flp->type != SDLA_S507)) if (flp->type != SDLA_S508 && flp->type != SDLA_S507)
return(-EINVAL); goto fail;
break;
case 3: case 3:
case 5: case 5:
case 7: case 7:
if (flp->type == SDLA_S502A) if (flp->type == SDLA_S502A)
return(-EINVAL); goto fail;
break; break;
default: default:
return(-EINVAL); goto fail;
} }
dev->irq = map->irq;
err = -EAGAIN;
if (request_irq(dev->irq, &sdla_isr, 0, dev->name, dev)) if (request_irq(dev->irq, &sdla_isr, 0, dev->name, dev))
return(-EAGAIN); goto fail;
if (flp->type == SDLA_S507) if (flp->type == SDLA_S507) {
{ switch(dev->irq) {
switch(dev->irq)
{
case 3: case 3:
flp->state = SDLA_S507_IRQ3; flp->state = SDLA_S507_IRQ3;
break; break;
...@@ -1514,35 +1496,25 @@ int sdla_set_config(struct net_device *dev, struct ifmap *map) ...@@ -1514,35 +1496,25 @@ int sdla_set_config(struct net_device *dev, struct ifmap *map)
if (valid_mem[i] == map->mem_start) if (valid_mem[i] == map->mem_start)
break; break;
err = -EINVAL;
if (i == sizeof(valid_mem) / sizeof(int)) if (i == sizeof(valid_mem) / sizeof(int))
/* goto fail2;
* FIXME:
* BUG BUG BUG: MUST RELEASE THE IRQ WE ALLOCATED IN
* ALL THESE CASES
*
*/
return(-EINVAL);
if ((flp->type == SDLA_S502A) && (((map->mem_start & 0xF000) >> 12) == 0x0E)) if (flp->type == SDLA_S502A && (map->mem_start & 0xF000) >> 12 == 0x0E)
return(-EINVAL); goto fail2;
if ((flp->type != SDLA_S507) && ((map->mem_start >> 16) == 0x0B)) if (flp->type != SDLA_S507 && map->mem_start >> 16 == 0x0B)
return(-EINVAL); goto fail2;
if ((flp->type == SDLA_S507) && ((map->mem_start >> 16) == 0x0D)) if (flp->type == SDLA_S507 && map->mem_start >> 16 == 0x0D)
return(-EINVAL); goto fail2;
dev->mem_start = map->mem_start;
dev->mem_end = dev->mem_start + 0x2000;
byte = flp->type != SDLA_S508 ? SDLA_8K_WINDOW : 0; byte = flp->type != SDLA_S508 ? SDLA_8K_WINDOW : 0;
byte |= (map->mem_start & 0xF000) >> (12 + (flp->type == SDLA_S508 ? 1 : 0)); byte |= (map->mem_start & 0xF000) >> (12 + (flp->type == SDLA_S508 ? 1 : 0));
switch(flp->type) switch(flp->type) {
{
case SDLA_S502A: case SDLA_S502A:
case SDLA_S502E: case SDLA_S502E:
switch (map->mem_start >> 16) switch (map->mem_start >> 16) {
{
case 0x0A: case 0x0A:
byte |= SDLA_S502_SEG_A; byte |= SDLA_S502_SEG_A;
break; break;
...@@ -1558,8 +1530,7 @@ int sdla_set_config(struct net_device *dev, struct ifmap *map) ...@@ -1558,8 +1530,7 @@ int sdla_set_config(struct net_device *dev, struct ifmap *map)
} }
break; break;
case SDLA_S507: case SDLA_S507:
switch (map->mem_start >> 16) switch (map->mem_start >> 16) {
{
case 0x0A: case 0x0A:
byte |= SDLA_S507_SEG_A; byte |= SDLA_S507_SEG_A;
break; break;
...@@ -1575,8 +1546,7 @@ int sdla_set_config(struct net_device *dev, struct ifmap *map) ...@@ -1575,8 +1546,7 @@ int sdla_set_config(struct net_device *dev, struct ifmap *map)
} }
break; break;
case SDLA_S508: case SDLA_S508:
switch (map->mem_start >> 16) switch (map->mem_start >> 16) {
{
case 0x0A: case 0x0A:
byte |= SDLA_S508_SEG_A; byte |= SDLA_S508_SEG_A;
break; break;
...@@ -1594,7 +1564,7 @@ int sdla_set_config(struct net_device *dev, struct ifmap *map) ...@@ -1594,7 +1564,7 @@ int sdla_set_config(struct net_device *dev, struct ifmap *map)
} }
/* set the memory bits, and enable access */ /* set the memory bits, and enable access */
outb(byte, dev->base_addr + SDLA_REG_PC_WINDOW); outb(byte, base + SDLA_REG_PC_WINDOW);
switch(flp->type) switch(flp->type)
{ {
...@@ -1608,10 +1578,20 @@ int sdla_set_config(struct net_device *dev, struct ifmap *map) ...@@ -1608,10 +1578,20 @@ int sdla_set_config(struct net_device *dev, struct ifmap *map)
flp->state = SDLA_MEMEN; flp->state = SDLA_MEMEN;
break; break;
} }
outb(flp->state, dev->base_addr + SDLA_REG_CONTROL); outb(flp->state, base + SDLA_REG_CONTROL);
dev->irq = map->irq;
dev->base_addr = base;
dev->mem_start = map->mem_start;
dev->mem_end = dev->mem_start + 0x2000;
flp->initialized = 1; flp->initialized = 1;
return(0); return 0;
fail2:
free_irq(map->irq, dev);
fail:
release_region(base, SDLA_IO_EXTENTS);
return err;
} }
static struct net_device_stats *sdla_stats(struct net_device *dev) static struct net_device_stats *sdla_stats(struct net_device *dev)
...@@ -1676,13 +1656,13 @@ static int __init init_sdla(void) ...@@ -1676,13 +1656,13 @@ static int __init init_sdla(void)
static void __exit exit_sdla(void) static void __exit exit_sdla(void)
{ {
struct frad_local *flp; struct frad_local *flp = sdla->priv;
unregister_netdev(sdla); unregister_netdev(sdla);
if (sdla->irq) if (flp->initialized) {
free_irq(sdla->irq, sdla); free_irq(sdla->irq, sdla);
release_region(sdla->base_addr, SDLA_IO_EXTENTS);
flp = sdla->priv; }
del_timer_sync(&flp->timer); del_timer_sync(&flp->timer);
free_netdev(sdla); free_netdev(sdla);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment