Commit 8538bf48 authored by Alexander Viro's avatar Alexander Viro Committed by Jeff Garzik

[PATCH] au1k leaks, allocation and free_netdev() fixes

	* fixes leaks on failed init
	* switches to sane allocation
	* fixes netdev freeing (kfree -> free_netdev)
	* fixes the idiocy with ->init() (from registger_netdev()) calling
unregister_netdevice() in case of failure - before we got anywhere past
the very beginning of register_netdev().

That's a part of NE* series that failed through the cracks (there were
pending irda patches, so that had been postponed, irda patches either
hadn't materialized in two months or hadn't touched that driver at all,
the latter being more likely).

Please, apply.
parent b105e2cf
...@@ -155,44 +155,39 @@ setup_hw_rings(struct au1k_private *aup, u32 rx_base, u32 tx_base) ...@@ -155,44 +155,39 @@ setup_hw_rings(struct au1k_private *aup, u32 rx_base, u32 tx_base)
} }
} }
/*
* Device has already been stopped at this point.
*/
static void au1k_irda_net_uninit(struct net_device *dev)
{
dev->hard_start_xmit = NULL;
dev->open = NULL;
dev->stop = NULL;
dev->do_ioctl = NULL;
dev->get_stats = NULL;
dev->priv = NULL;
}
static int au1k_irda_init(void) static int au1k_irda_init(void)
{ {
static unsigned version_printed = 0; static unsigned version_printed = 0;
struct au1k_private *aup;
struct net_device *dev; struct net_device *dev;
int err; int err;
if (version_printed++ == 0) printk(version); if (version_printed++ == 0) printk(version);
rtnl_lock(); dev = alloc_irdadev(sizeof(struct au1k_private));
dev = dev_alloc("irda%d", &err); if (!dev)
if (dev) { return -ENOMEM;
dev->irq = AU1000_IRDA_RX_INT; /* TX has its own interrupt */
dev->init = au1k_irda_net_init; dev->irq = AU1000_IRDA_RX_INT; /* TX has its own interrupt */
dev->uninit = au1k_irda_net_uninit; err = au1k_irda_net_init(dev);
err = register_netdevice(dev); if (err)
goto out;
if (err) err = register_netdev(dev);
kfree(dev); if (err)
else goto out1;
ir_devs[0] = dev; ir_devs[0] = dev;
printk(KERN_INFO "IrDA: Registered device %s\n", dev->name); printk(KERN_INFO "IrDA: Registered device %s\n", dev->name);
} return 0;
rtnl_unlock();
out1:
aup = dev->priv;
dma_free((void *)aup->db[0].vaddr,
MAX_BUF_SIZE * 2*NUM_IR_DESC);
dma_free((void *)aup->rx_ring[0],
2 * MAX_NUM_IR_DESC*(sizeof(ring_dest_t)));
kfree(aup->rx_buff.head);
out:
free_netdev(dev);
return err; return err;
} }
...@@ -210,22 +205,14 @@ static int au1k_irda_init_iobuf(iobuff_t *io, int size) ...@@ -210,22 +205,14 @@ static int au1k_irda_init_iobuf(iobuff_t *io, int size)
static int au1k_irda_net_init(struct net_device *dev) static int au1k_irda_net_init(struct net_device *dev)
{ {
struct au1k_private *aup = NULL; struct au1k_private *aup = dev->priv;
int i, retval = 0, err; int i, retval = 0, err;
db_dest_t *pDB, *pDBfree; db_dest_t *pDB, *pDBfree;
unsigned long temp; unsigned long temp;
dev->priv = kmalloc(sizeof(struct au1k_private), GFP_KERNEL);
if (dev->priv == NULL) {
retval = -ENOMEM;
goto out;
}
memset(dev->priv, 0, sizeof(struct au1k_private));
aup = dev->priv;
err = au1k_irda_init_iobuf(&aup->rx_buff, 14384); err = au1k_irda_init_iobuf(&aup->rx_buff, 14384);
if (err) if (err)
goto out; goto out1;
dev->open = au1k_irda_start; dev->open = au1k_irda_start;
dev->hard_start_xmit = au1k_irda_hard_xmit; dev->hard_start_xmit = au1k_irda_hard_xmit;
...@@ -234,7 +221,6 @@ static int au1k_irda_net_init(struct net_device *dev) ...@@ -234,7 +221,6 @@ static int au1k_irda_net_init(struct net_device *dev)
dev->do_ioctl = au1k_irda_ioctl; dev->do_ioctl = au1k_irda_ioctl;
dev->tx_timeout = au1k_tx_timeout; dev->tx_timeout = au1k_tx_timeout;
irda_device_setup(dev);
irda_init_max_qos_capabilies(&aup->qos); irda_init_max_qos_capabilies(&aup->qos);
/* The only value we must override it the baudrate */ /* The only value we must override it the baudrate */
...@@ -244,19 +230,20 @@ static int au1k_irda_net_init(struct net_device *dev) ...@@ -244,19 +230,20 @@ static int au1k_irda_net_init(struct net_device *dev)
aup->qos.min_turn_time.bits = qos_mtt_bits; aup->qos.min_turn_time.bits = qos_mtt_bits;
irda_qos_bits_to_value(&aup->qos); irda_qos_bits_to_value(&aup->qos);
retval = -ENOMEM;
/* Tx ring follows rx ring + 512 bytes */ /* Tx ring follows rx ring + 512 bytes */
/* we need a 1k aligned buffer */ /* we need a 1k aligned buffer */
aup->rx_ring[0] = (ring_dest_t *) aup->rx_ring[0] = (ring_dest_t *)
dma_alloc(2*MAX_NUM_IR_DESC*(sizeof(ring_dest_t)), &temp); dma_alloc(2*MAX_NUM_IR_DESC*(sizeof(ring_dest_t)), &temp);
if (!aup->rx_ring[0])
goto out2;
/* allocate the data buffers */ /* allocate the data buffers */
aup->db[0].vaddr = aup->db[0].vaddr =
(void *)dma_alloc(MAX_BUF_SIZE * 2*NUM_IR_DESC, &temp); (void *)dma_alloc(MAX_BUF_SIZE * 2*NUM_IR_DESC, &temp);
if (!aup->db[0].vaddr || !aup->rx_ring[0]) { if (!aup->db[0].vaddr)
retval = -ENOMEM; goto out3;
goto out;
}
setup_hw_rings(aup, (u32)aup->rx_ring[0], (u32)aup->rx_ring[0] + 512); setup_hw_rings(aup, (u32)aup->rx_ring[0], (u32)aup->rx_ring[0] + 512);
...@@ -296,19 +283,13 @@ static int au1k_irda_net_init(struct net_device *dev) ...@@ -296,19 +283,13 @@ static int au1k_irda_net_init(struct net_device *dev)
} }
return 0; return 0;
out: out3:
if (aup->db[0].vaddr) dma_free((void *)aup->rx_ring[0],
dma_free((void *)aup->db[0].vaddr, 2 * MAX_NUM_IR_DESC*(sizeof(ring_dest_t)));
MAX_BUF_SIZE * 2*NUM_IR_DESC); out2:
if (aup->rx_ring[0]) kfree(aup->rx_buff.head);
kfree((void *)aup->rx_ring[0]); out1:
if (aup->rx_buff.head) printk(KERN_ERR "au1k_init_module failed. Returns %d\n", retval);
kfree(aup->rx_buff.head);
if (dev->priv != NULL)
kfree(dev->priv);
unregister_netdevice(dev);
printk(KERN_ERR "%s: au1k_init_module failed. Returns %d\n",
dev->name, retval);
return retval; return retval;
} }
...@@ -427,24 +408,14 @@ static void __exit au1k_irda_exit(void) ...@@ -427,24 +408,14 @@ static void __exit au1k_irda_exit(void)
struct net_device *dev = ir_devs[0]; struct net_device *dev = ir_devs[0];
struct au1k_private *aup = (struct au1k_private *) dev->priv; struct au1k_private *aup = (struct au1k_private *) dev->priv;
if (!dev) { unregister_netdev(dev);
printk(KERN_ERR "au1k_ircc no dev found\n");
return; dma_free((void *)aup->db[0].vaddr,
} MAX_BUF_SIZE * 2*NUM_IR_DESC);
if (aup->db[0].vaddr) { dma_free((void *)aup->rx_ring[0],
dma_free((void *)aup->db[0].vaddr, 2 * MAX_NUM_IR_DESC*(sizeof(ring_dest_t)));
MAX_BUF_SIZE * 2*NUM_IR_DESC); kfree(aup->rx_buff.head);
aup->db[0].vaddr = 0; free_netdev(dev);
}
if (aup->rx_ring[0]) {
dma_free((void *)aup->rx_ring[0],
2*MAX_NUM_IR_DESC*(sizeof(ring_dest_t)));
aup->rx_ring[0] = 0;
}
rtnl_lock();
unregister_netdevice(dev);
rtnl_unlock();
ir_devs[0] = 0;
} }
......
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