Commit 4aba0acb authored by Alexander Viro's avatar Alexander Viro Committed by Stephen Hemminger

[netdrvr meth] use alloc_etherdev; fix leaks on error/cleanup

parent 58319497
...@@ -95,7 +95,6 @@ typedef struct meth_private { ...@@ -95,7 +95,6 @@ typedef struct meth_private {
spinlock_t meth_lock; spinlock_t meth_lock;
} meth_private; } meth_private;
extern struct net_device meth_devs[];
void meth_tx_timeout (struct net_device *dev); void meth_tx_timeout (struct net_device *dev);
void meth_interrupt(int irq, void *dev_id, struct pt_regs *pregs); void meth_interrupt(int irq, void *dev_id, struct pt_regs *pregs);
...@@ -762,17 +761,16 @@ struct net_device_stats *meth_stats(struct net_device *dev) ...@@ -762,17 +761,16 @@ struct net_device_stats *meth_stats(struct net_device *dev)
/* /*
* The init function (sometimes called probe). * The init function (sometimes called probe).
* It is invoked by register_netdev()
*/ */
int meth_init(struct net_device *dev) static struct net_device *meth_init(struct net_device *dev)
{ {
struct net_device *dev;
meth_private *priv; meth_private *priv;
int ret; int ret;
/*
* Then, assign other fields in dev, using ether_setup() and some dev = alloc_etherdev(sizeof(struct meth_private));
* hand assignments if (!dev)
*/ return ERR_PTR(-ENOMEM);
ether_setup(dev); /* assign some of the fields */
dev->open = meth_open; dev->open = meth_open;
dev->stop = meth_release; dev->stop = meth_release;
...@@ -787,16 +785,8 @@ int meth_init(struct net_device *dev) ...@@ -787,16 +785,8 @@ int meth_init(struct net_device *dev)
dev->irq = MACE_ETHERNET_IRQ; dev->irq = MACE_ETHERNET_IRQ;
SET_MODULE_OWNER(dev); SET_MODULE_OWNER(dev);
/* priv = dev->priv;
* Then, allocate the priv field. This encloses the statistics spin_lock_init(&priv->meth_lock);
* and a few private fields.
*/
priv = kmalloc(sizeof(struct meth_private), GFP_KERNEL);
if (priv == NULL)
return -ENOMEM;
dev->priv=priv;
memset(priv, 0, sizeof(struct meth_private));
spin_lock_init(&((struct meth_private *) dev->priv)->meth_lock);
/* /*
* Make the usual checks: check_region(), probe irq, ... -ENODEV * Make the usual checks: check_region(), probe irq, ... -ENODEV
* should be returned if no device found. No resource should be * should be returned if no device found. No resource should be
...@@ -807,28 +797,41 @@ int meth_init(struct net_device *dev) ...@@ -807,28 +797,41 @@ int meth_init(struct net_device *dev)
priv->phy_addr = -1; /* No phy is known yet... */ priv->phy_addr = -1; /* No phy is known yet... */
/* Initialize the hardware */ /* Initialize the hardware */
if((ret=meth_reset(dev)) < 0) ret = meth_reset(dev);
return ret; if (ret < 0)
goto out;
/* Allocate the ring buffers */ /* Allocate the ring buffers */
if((ret=meth_init_tx_ring(priv))<0||(ret=meth_init_rx_ring(priv))<0){ ret = meth_init_tx_ring(priv);
meth_free_tx_ring(priv); if (ret < 0)
meth_free_rx_ring(priv); goto out;
return ret;
} ret = meth_init_rx_ring(priv);
if (ret < 0)
goto out1;
ret = register_netdev(dev);
if (ret)
goto out2;
printk("SGI O2 Fast Ethernet rev. %ld\n", priv->regs->mac_ctrl >> 29); printk("SGI O2 Fast Ethernet rev. %ld\n", priv->regs->mac_ctrl >> 29);
return 0; return ret;
out2:
meth_free_rx_ring(priv);
out1:
meth_free_tx_ring(priv);
out:
free_netdev(dev);
return ERR_PTR(ret);
} }
/* /*
* The devices * The devices
*/ */
struct net_device meth_devs[1] = { struct net_device *meth_dev;
{ init: meth_init, } /* init, nothing more */
};
/* /*
* Finally, the module stuff * Finally, the module stuff
...@@ -836,23 +839,19 @@ struct net_device meth_devs[1] = { ...@@ -836,23 +839,19 @@ struct net_device meth_devs[1] = {
int meth_init_module(void) int meth_init_module(void)
{ {
int result, device_present = 0; meth_dev = meth_init();
if (IS_ERR(meth_dev))
strcpy(meth_devs[0].name, "eth%d"); return PTR_ERR(meth_dev);
return 0;
if ( (result = register_netdev(meth_devs)) )
printk("meth: error %i registering device \"%s\"\n",
result, meth_devs->name);
else device_present++;
return device_present ? 0 : -ENODEV;
} }
void meth_cleanup(void) void meth_cleanup(void)
{ {
kfree(meth_devs->priv); meth_private *priv = meth_dev->priv;
unregister_netdev(meth_devs); unregister_netdev(meth_dev);
return; meth_free_rx_ring(priv);
meth_free_tx_ring(priv);
free_netdev(meth_dev);
} }
module_init(meth_init_module); module_init(meth_init_module);
......
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