Commit fdc7e3e8 authored by Stephen Hemminger's avatar Stephen Hemminger

[PATCH] (3/42) eexpress

Based on viro NE27-eexpress
	* switched eexpress to dynamic allocation
	* eexpress: embedded ->priv
	* eexpress: fixed clobbering on autoprobe
	* eexpress: fixed IO without request_region()
	* eexpress: fixed resource leaks on failure exits
parent 308a2bca
...@@ -49,7 +49,7 @@ extern int el2_probe(struct net_device *dev); ...@@ -49,7 +49,7 @@ extern int el2_probe(struct net_device *dev);
extern int ne_probe(struct net_device *dev); extern int ne_probe(struct net_device *dev);
extern int hp_probe(struct net_device *dev); extern int hp_probe(struct net_device *dev);
extern int hp_plus_probe(struct net_device *dev); extern int hp_plus_probe(struct net_device *dev);
extern int express_probe(struct net_device *); extern struct net_device *express_probe(int unit);
extern struct net_device *eepro_probe(int unit); extern struct net_device *eepro_probe(int unit);
extern int at1500_probe(struct net_device *); extern int at1500_probe(struct net_device *);
extern int at1700_probe(struct net_device *); extern int at1700_probe(struct net_device *);
...@@ -249,14 +249,14 @@ static struct devprobe isa_probes[] __initdata = { ...@@ -249,14 +249,14 @@ static struct devprobe isa_probes[] __initdata = {
#endif #endif
#ifdef CONFIG_ETH16I #ifdef CONFIG_ETH16I
{eth16i_probe, 0}, /* ICL EtherTeam 16i/32 */ {eth16i_probe, 0}, /* ICL EtherTeam 16i/32 */
#endif
#ifdef CONFIG_EEXPRESS /* Intel EtherExpress */
{express_probe, 0},
#endif #endif
{NULL, 0}, {NULL, 0},
}; };
static struct devprobe2 isa_probes2[] __initdata = { static struct devprobe2 isa_probes2[] __initdata = {
#ifdef CONFIG_EEXPRESS /* Intel EtherExpress */
{express_probe, 0},
#endif
#ifdef CONFIG_EEXPRESS_PRO /* Intel EtherExpress Pro/10 */ #ifdef CONFIG_EEXPRESS_PRO /* Intel EtherExpress Pro/10 */
{eepro_probe, 0}, {eepro_probe, 0},
#endif #endif
......
...@@ -244,7 +244,6 @@ static char mca_irqmap[] = { 12, 9, 3, 4, 5, 10, 11, 15 }; ...@@ -244,7 +244,6 @@ static char mca_irqmap[] = { 12, 9, 3, 4, 5, 10, 11, 15 };
* Prototypes for Linux interface * Prototypes for Linux interface
*/ */
extern int express_probe(struct net_device *dev);
static int eexp_open(struct net_device *dev); static int eexp_open(struct net_device *dev);
static int eexp_close(struct net_device *dev); static int eexp_close(struct net_device *dev);
static void eexp_timeout(struct net_device *dev); static void eexp_timeout(struct net_device *dev);
...@@ -334,11 +333,13 @@ static inline unsigned short int SHADOW(short int addr) ...@@ -334,11 +333,13 @@ static inline unsigned short int SHADOW(short int addr)
* checks for presence of EtherExpress card * checks for presence of EtherExpress card
*/ */
int __init express_probe(struct net_device *dev) static int __init do_express_probe(struct net_device *dev)
{ {
unsigned short *port; unsigned short *port;
static unsigned short ports[] = { 0x240,0x300,0x310,0x270,0x320,0x340,0 }; static unsigned short ports[] = { 0x240,0x300,0x310,0x270,0x320,0x340,0 };
unsigned short ioaddr = dev->base_addr; unsigned short ioaddr = dev->base_addr;
int dev_irq = dev->irq;
int err;
SET_MODULE_OWNER(dev); SET_MODULE_OWNER(dev);
...@@ -391,27 +392,58 @@ int __init express_probe(struct net_device *dev) ...@@ -391,27 +392,58 @@ int __init express_probe(struct net_device *dev)
} }
} }
#endif #endif
if (ioaddr&0xfe00) if (ioaddr&0xfe00) {
return eexp_hw_probe(dev,ioaddr); if (!request_region(ioaddr, EEXP_IO_EXTENT, "EtherExpress"))
else if (ioaddr) return -EBUSY;
err = eexp_hw_probe(dev,ioaddr);
release_region(ioaddr, EEXP_IO_EXTENT);
return err;
} else if (ioaddr)
return -ENXIO; return -ENXIO;
for (port=&ports[0] ; *port ; port++ ) for (port=&ports[0] ; *port ; port++ )
{ {
unsigned short sum = 0; unsigned short sum = 0;
int i; int i;
if (!request_region(*port, EEXP_IO_EXTENT, "EtherExpress"))
continue;
for ( i=0 ; i<4 ; i++ ) for ( i=0 ; i<4 ; i++ )
{ {
unsigned short t; unsigned short t;
t = inb(*port + ID_PORT); t = inb(*port + ID_PORT);
sum |= (t>>4) << ((t & 0x03)<<2); sum |= (t>>4) << ((t & 0x03)<<2);
} }
if (sum==0xbaba && !eexp_hw_probe(dev,*port)) if (sum==0xbaba && !eexp_hw_probe(dev,*port)) {
release_region(*port, EEXP_IO_EXTENT);
return 0; return 0;
}
release_region(*port, EEXP_IO_EXTENT);
dev->irq = dev_irq;
} }
return -ENODEV; return -ENODEV;
} }
struct net_device * __init express_probe(int unit)
{
struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
int err;
if (!dev)
return ERR_PTR(-ENOMEM);
sprintf(dev->name, "eth%d", unit);
netdev_boot_setup_check(dev);
err = do_express_probe(dev);
if (!err) {
err = register_netdev(dev);
if (!err)
return dev;
}
free_netdev(dev);
return ERR_PTR(err);
}
/* /*
* open and initialize the adapter, ready for use * open and initialize the adapter, ready for use
*/ */
...@@ -1058,7 +1090,7 @@ static int __init eexp_hw_probe(struct net_device *dev, unsigned short ioaddr) ...@@ -1058,7 +1090,7 @@ static int __init eexp_hw_probe(struct net_device *dev, unsigned short ioaddr)
unsigned int memory_size; unsigned int memory_size;
int i; int i;
unsigned short xsum = 0; unsigned short xsum = 0;
struct net_local *lp; struct net_local *lp = dev->priv;
printk("%s: EtherExpress 16 at %#x ",dev->name,ioaddr); printk("%s: EtherExpress 16 at %#x ",dev->name,ioaddr);
...@@ -1108,17 +1140,18 @@ static int __init eexp_hw_probe(struct net_device *dev, unsigned short ioaddr) ...@@ -1108,17 +1140,18 @@ static int __init eexp_hw_probe(struct net_device *dev, unsigned short ioaddr)
buswidth = !((setupval & 0x400) >> 10); buswidth = !((setupval & 0x400) >> 10);
} }
dev->priv = lp = kmalloc(sizeof(struct net_local), GFP_KERNEL); memset(lp, 0, sizeof(struct net_local));
if (!dev->priv)
return -ENOMEM;
memset(dev->priv, 0, sizeof(struct net_local));
spin_lock_init(&lp->lock); spin_lock_init(&lp->lock);
printk("(IRQ %d, %s connector, %d-bit bus", dev->irq, printk("(IRQ %d, %s connector, %d-bit bus", dev->irq,
eexp_ifmap[dev->if_port], buswidth?8:16); eexp_ifmap[dev->if_port], buswidth?8:16);
if (!request_region(dev->base_addr + 0x300e, 1, "EtherExpress"))
return -EBUSY;
eexp_hw_set_interface(dev); eexp_hw_set_interface(dev);
release_region(dev->base_addr + 0x300e, 1);
/* Find out how much RAM we have on the card */ /* Find out how much RAM we have on the card */
outw(0, dev->base_addr + WRITE_PTR); outw(0, dev->base_addr + WRITE_PTR);
...@@ -1156,7 +1189,6 @@ static int __init eexp_hw_probe(struct net_device *dev, unsigned short ioaddr) ...@@ -1156,7 +1189,6 @@ static int __init eexp_hw_probe(struct net_device *dev, unsigned short ioaddr)
break; break;
default: default:
printk(") bad memory size (%dk).\n", memory_size); printk(") bad memory size (%dk).\n", memory_size);
kfree(dev->priv);
return -ENODEV; return -ENODEV;
break; break;
} }
...@@ -1171,7 +1203,6 @@ static int __init eexp_hw_probe(struct net_device *dev, unsigned short ioaddr) ...@@ -1171,7 +1203,6 @@ static int __init eexp_hw_probe(struct net_device *dev, unsigned short ioaddr)
dev->set_multicast_list = &eexp_set_multicast; dev->set_multicast_list = &eexp_set_multicast;
dev->tx_timeout = eexp_timeout; dev->tx_timeout = eexp_timeout;
dev->watchdog_timeo = 2*HZ; dev->watchdog_timeo = 2*HZ;
ether_setup(dev);
return 0; return 0;
} }
...@@ -1654,7 +1685,7 @@ eexp_set_multicast(struct net_device *dev) ...@@ -1654,7 +1685,7 @@ eexp_set_multicast(struct net_device *dev)
#define EEXP_MAX_CARDS 4 /* max number of cards to support */ #define EEXP_MAX_CARDS 4 /* max number of cards to support */
static struct net_device dev_eexp[EEXP_MAX_CARDS]; static struct net_device *dev_eexp[EEXP_MAX_CARDS];
static int irq[EEXP_MAX_CARDS]; static int irq[EEXP_MAX_CARDS];
static int io[EEXP_MAX_CARDS]; static int io[EEXP_MAX_CARDS];
...@@ -1671,25 +1702,30 @@ MODULE_LICENSE("GPL"); ...@@ -1671,25 +1702,30 @@ MODULE_LICENSE("GPL");
*/ */
int init_module(void) int init_module(void)
{ {
struct net_device *dev;
int this_dev, found = 0; int this_dev, found = 0;
for (this_dev = 0; this_dev < EEXP_MAX_CARDS; this_dev++) { for (this_dev = 0; this_dev < EEXP_MAX_CARDS; this_dev++) {
struct net_device *dev = &dev_eexp[this_dev]; dev = alloc_etherdev(sizeof(struct net_local));
dev->irq = irq[this_dev]; dev->irq = irq[this_dev];
dev->base_addr = io[this_dev]; dev->base_addr = io[this_dev];
dev->init = express_probe;
if (io[this_dev] == 0) { if (io[this_dev] == 0) {
if (this_dev) break; if (this_dev)
break;
printk(KERN_NOTICE "eexpress.c: Module autoprobe not recommended, give io=xx.\n"); printk(KERN_NOTICE "eexpress.c: Module autoprobe not recommended, give io=xx.\n");
} }
if (register_netdev(dev) != 0) { if (do_express_probe(dev) == 0 && register_netdev(dev) == 0) {
printk(KERN_WARNING "eexpress.c: Failed to register card at 0x%x.\n", io[this_dev]); dev_eexp[this_dev] = dev;
if (found != 0) return 0; found++;
return -ENXIO; continue;
} }
found++; printk(KERN_WARNING "eexpress.c: Failed to register card at 0x%x.\n", io[this_dev]);
free_netdev(dev);
break;
} }
return 0; if (found)
return 0;
return -ENXIO;
} }
void cleanup_module(void) void cleanup_module(void)
...@@ -1697,11 +1733,10 @@ void cleanup_module(void) ...@@ -1697,11 +1733,10 @@ void cleanup_module(void)
int this_dev; int this_dev;
for (this_dev = 0; this_dev < EEXP_MAX_CARDS; this_dev++) { for (this_dev = 0; this_dev < EEXP_MAX_CARDS; this_dev++) {
struct net_device *dev = &dev_eexp[this_dev]; struct net_device *dev = dev_eexp[this_dev];
if (dev->priv != NULL) { if (dev) {
unregister_netdev(dev); unregister_netdev(dev);
kfree(dev->priv); free_netdev(dev);
dev->priv = NULL;
} }
} }
} }
......
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