Commit 84e78fd3 authored by Stephen Hemminger's avatar Stephen Hemminger

[PATCH] (4/42) eth16i

NE28-eth16i
	* switched eth16i to dynamic allocation
	* eth16i: embedded ->priv
	* eth16i: fixed resource leaks on failure exits
parent fdc7e3e8
......@@ -54,7 +54,7 @@ extern struct net_device *eepro_probe(int unit);
extern int at1500_probe(struct net_device *);
extern int at1700_probe(struct net_device *);
extern int fmv18x_probe(struct net_device *);
extern int eth16i_probe(struct net_device *);
extern struct net_device *eth16i_probe(int unit);
extern struct net_device *i82596_probe(int unit);
extern struct net_device *ewrk3_probe(int unit);
extern struct net_device *el1_probe(int unit);
......@@ -246,14 +246,14 @@ static struct devprobe isa_probes[] __initdata = {
#endif
#ifdef CONFIG_FMV18X /* Fujitsu FMV-181/182 */
{fmv18x_probe, 0},
#endif
#ifdef CONFIG_ETH16I
{eth16i_probe, 0}, /* ICL EtherTeam 16i/32 */
#endif
{NULL, 0},
};
static struct devprobe2 isa_probes2[] __initdata = {
#ifdef CONFIG_ETH16I
{eth16i_probe, 0}, /* ICL EtherTeam 16i/32 */
#endif
#ifdef CONFIG_EEXPRESS /* Intel EtherExpress */
{express_probe, 0},
#endif
......
......@@ -369,7 +369,6 @@ static unsigned int eth32i_irqmap[] __initdata = { 3, 5, 7, 9, 10, 11, 12, 15, 0
#define NUM_OF_EISA_IRQS 8
static unsigned int eth16i_tx_buf_map[] = { 2048, 2048, 4096, 8192 };
static unsigned int boot = 1;
/* Use 0 for production, 1 for verification, >2 for debug */
#ifndef ETH16I_DEBUG
......@@ -395,8 +394,6 @@ struct eth16i_local {
/* Function prototypes */
extern int eth16i_probe(struct net_device *dev);
static int eth16i_probe1(struct net_device *dev, int ioaddr);
static int eth16i_check_signature(int ioaddr);
static int eth16i_probe_port(int ioaddr);
......@@ -418,7 +415,7 @@ static void eth16i_timeout(struct net_device *dev);
static void eth16i_skip_packet(struct net_device *dev);
static void eth16i_multicast(struct net_device *dev);
static void eth16i_select_regbank(unsigned char regbank, int ioaddr);
static void eth16i_initialize(struct net_device *dev);
static void eth16i_initialize(struct net_device *dev, int boot);
#if 0
static int eth16i_set_irq(struct net_device *dev);
......@@ -432,7 +429,7 @@ static struct net_device_stats *eth16i_get_stats(struct net_device *dev);
static char cardname[] __initdata = "ICL EtherTeam 16i/32";
int __init eth16i_probe(struct net_device *dev)
static int __init do_eth16i_probe(struct net_device *dev)
{
int i;
int ioaddr;
......@@ -461,14 +458,38 @@ int __init eth16i_probe(struct net_device *dev)
return -ENODEV;
}
struct net_device * __init eth16i_probe(int unit)
{
struct net_device *dev = alloc_etherdev(sizeof(struct eth16i_local));
int err;
if (!dev)
return ERR_PTR(-ENOMEM);
sprintf(dev->name, "eth%d", unit);
netdev_boot_setup_check(dev);
err = do_eth16i_probe(dev);
if (err)
goto out;
err = register_netdev(dev);
if (err)
goto out1;
return dev;
out1:
free_irq(dev->irq, dev);
release_region(dev->base_addr, ETH16I_IO_EXTENT);
out:
free_netdev(dev);
return ERR_PTR(err);
}
static int __init eth16i_probe1(struct net_device *dev, int ioaddr)
{
struct eth16i_local *lp;
struct eth16i_local *lp = dev->priv;
static unsigned version_printed;
int retval;
boot = 1; /* To inform initilization that we are in boot probe */
/* Let's grab the region */
if (!request_region(ioaddr, ETH16I_IO_EXTENT, dev->name))
return -EBUSY;
......@@ -531,22 +552,13 @@ static int __init eth16i_probe1(struct net_device *dev, int ioaddr)
eth16i_select_regbank(TRANSCEIVER_MODE_RB, ioaddr);
outb(0x38, ioaddr + TRANSCEIVER_MODE_REG);
eth16i_initialize(dev); /* Initialize rest of the chip's registers */
eth16i_initialize(dev, 1); /* Initialize rest of the chip's registers */
/* Now let's same some energy by shutting down the chip ;) */
BITCLR(ioaddr + CONFIG_REG_1, POWERUP);
/* Initialize the device structure */
if(dev->priv == NULL) {
dev->priv = kmalloc(sizeof(struct eth16i_local), GFP_KERNEL);
if(dev->priv == NULL) {
free_irq(dev->irq, dev);
retval = -ENOMEM;
goto out;
}
}
memset(dev->priv, 0, sizeof(struct eth16i_local));
memset(lp, 0, sizeof(struct eth16i_local));
dev->open = eth16i_open;
dev->stop = eth16i_close;
dev->hard_start_xmit = eth16i_tx;
......@@ -554,15 +566,7 @@ static int __init eth16i_probe1(struct net_device *dev, int ioaddr)
dev->set_multicast_list = eth16i_multicast;
dev->tx_timeout = eth16i_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
lp = (struct eth16i_local *)dev->priv;
spin_lock_init(&lp->lock);
/* Fill in the fields of the device structure with ethernet values. */
ether_setup(dev);
boot = 0;
return 0;
out:
release_region(ioaddr, ETH16I_IO_EXTENT);
......@@ -570,7 +574,7 @@ static int __init eth16i_probe1(struct net_device *dev, int ioaddr)
}
static void eth16i_initialize(struct net_device *dev)
static void eth16i_initialize(struct net_device *dev, int boot)
{
int ioaddr = dev->base_addr;
int i, node_w = 0;
......@@ -953,7 +957,7 @@ static int eth16i_open(struct net_device *dev)
outb(0xc0 | POWERUP, ioaddr + CONFIG_REG_1);
/* Initialize the chip */
eth16i_initialize(dev);
eth16i_initialize(dev, 0);
/* Set the transmit buffer size */
lp->tx_buf_size = eth16i_tx_buf_map[ETH16I_TX_BUF_SIZE & 0x03];
......@@ -1401,7 +1405,7 @@ static ushort eth16i_parse_mediatype(const char* s)
#define MAX_ETH16I_CARDS 4 /* Max number of Eth16i cards per module */
static struct net_device dev_eth16i[MAX_ETH16I_CARDS];
static struct net_device *dev_eth16i[MAX_ETH16I_CARDS];
static int io[MAX_ETH16I_CARDS];
#if 0
static int irq[MAX_ETH16I_CARDS];
......@@ -1431,14 +1435,14 @@ MODULE_PARM_DESC(debug, "eth16i debug level (0-6)");
int init_module(void)
{
int this_dev, found = 0;
struct net_device *dev;
for (this_dev = 0; this_dev < MAX_ETH16I_CARDS; this_dev++) {
dev = alloc_etherdev(sizeof(struct eth16i_local));
if (!dev)
break;
for(this_dev = 0; this_dev < MAX_ETH16I_CARDS; this_dev++)
{
struct net_device *dev = &dev_eth16i[this_dev];
dev->irq = 0; /* irq[this_dev]; */
dev->base_addr = io[this_dev];
dev->init = eth16i_probe;
if(debug != -1)
eth16i_debug = debug;
......@@ -1448,44 +1452,43 @@ int init_module(void)
dev->if_port = eth16i_parse_mediatype(mediatype[this_dev]);
if(io[this_dev] == 0)
{
if(this_dev != 0) break; /* Only autoprobe 1st one */
if(io[this_dev] == 0) {
if(this_dev != 0) /* Only autoprobe 1st one */
break;
printk(KERN_NOTICE "eth16i.c: Presently autoprobing (not recommended) for a single card.\n");
}
if(register_netdev(dev) != 0)
{
printk(KERN_WARNING "eth16i.c No Eth16i card found (i/o = 0x%x).\n",
io[this_dev]);
if(found != 0) return 0;
return -ENXIO;
if (do_eth16i_probe(dev) == 0) {
if (register_netdev(dev) == 0) {
dev_eth16i[found++] = dev;
continue;
}
free_irq(dev->irq, dev);
release_region(dev->base_addr, ETH16I_IO_EXTENT);
}
found++;
printk(KERN_WARNING "eth16i.c No Eth16i card found (i/o = 0x%x).\n",
io[this_dev]);
free_netdev(dev);
break;
}
return 0;
if (found)
return 0;
return -ENXIO;
}
void cleanup_module(void)
{
int this_dev;
for(this_dev = 0; this_dev < MAX_ETH16I_CARDS; this_dev++)
{
struct net_device* dev = &dev_eth16i[this_dev];
for(this_dev = 0; this_dev < MAX_ETH16I_CARDS; this_dev++) {
struct net_device *dev = dev_eth16i[this_dev];
if(dev->priv != NULL)
{
if(dev->priv) {
unregister_netdev(dev);
kfree(dev->priv);
dev->priv = NULL;
free_irq(dev->irq, dev);
release_region(dev->base_addr, ETH16I_IO_EXTENT);
free_netdev(dev);
}
}
}
......
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