Commit 308a2bca authored by Stephen Hemminger's avatar Stephen Hemminger

[PATCH] (2/42) eepro

Patch from viro: NE26-eepro
	* switched eepro to dynamic allocation
	* eepro: embedded ->priv
	* eepro: fixed clobbering on autoprobe
	* eepro: fixed IO before request_region()
	* eepro: fixed resource leaks on failure exits
parent 4eb1b94b
...@@ -50,7 +50,7 @@ extern int ne_probe(struct net_device *dev); ...@@ -50,7 +50,7 @@ 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 int express_probe(struct net_device *);
extern int eepro_probe(struct net_device *); 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 *);
extern int fmv18x_probe(struct net_device *); extern int fmv18x_probe(struct net_device *);
...@@ -252,14 +252,14 @@ static struct devprobe isa_probes[] __initdata = { ...@@ -252,14 +252,14 @@ static struct devprobe isa_probes[] __initdata = {
#endif #endif
#ifdef CONFIG_EEXPRESS /* Intel EtherExpress */ #ifdef CONFIG_EEXPRESS /* Intel EtherExpress */
{express_probe, 0}, {express_probe, 0},
#endif
#ifdef CONFIG_EEXPRESS_PRO /* Intel EtherExpress Pro/10 */
{eepro_probe, 0},
#endif #endif
{NULL, 0}, {NULL, 0},
}; };
static struct devprobe2 isa_probes2[] __initdata = { static struct devprobe2 isa_probes2[] __initdata = {
#ifdef CONFIG_EEXPRESS_PRO /* Intel EtherExpress Pro/10 */
{eepro_probe, 0},
#endif
#ifdef CONFIG_EWRK3 /* DEC EtherWORKS 3 */ #ifdef CONFIG_EWRK3 /* DEC EtherWORKS 3 */
{ewrk3_probe, 0}, {ewrk3_probe, 0},
#endif #endif
......
...@@ -302,9 +302,7 @@ struct eepro_local { ...@@ -302,9 +302,7 @@ struct eepro_local {
/* Index to functions, as function prototypes. */ /* Index to functions, as function prototypes. */
extern int eepro_probe(struct net_device *dev); static int eepro_probe1(struct net_device *dev, int autoprobe);
static int eepro_probe1(struct net_device *dev, short ioaddr);
static int eepro_open(struct net_device *dev); static int eepro_open(struct net_device *dev);
static int eepro_send_packet(struct sk_buff *skb, struct net_device *dev); static int eepro_send_packet(struct sk_buff *skb, struct net_device *dev);
static irqreturn_t eepro_interrupt(int irq, void *dev_id, struct pt_regs *regs); static irqreturn_t eepro_interrupt(int irq, void *dev_id, struct pt_regs *regs);
...@@ -527,10 +525,11 @@ buffer (transmit-buffer = 32K - receive-buffer). ...@@ -527,10 +525,11 @@ buffer (transmit-buffer = 32K - receive-buffer).
If dev->base_addr == 2, allocate space for the device and return success If dev->base_addr == 2, allocate space for the device and return success
(detachable devices only). (detachable devices only).
*/ */
int __init eepro_probe(struct net_device *dev) static int __init do_eepro_probe(struct net_device *dev)
{ {
int i; int i;
int base_addr = dev->base_addr; int base_addr = dev->base_addr;
int irq = dev->irq;
SET_MODULE_OWNER(dev); SET_MODULE_OWNER(dev);
...@@ -563,24 +562,48 @@ int __init eepro_probe(struct net_device *dev) ...@@ -563,24 +562,48 @@ int __init eepro_probe(struct net_device *dev)
#endif #endif
if (base_addr > 0x1ff) /* Check a single specified location. */ if (base_addr > 0x1ff) /* Check a single specified location. */
return eepro_probe1(dev, base_addr); return eepro_probe1(dev, 0);
else if (base_addr != 0) /* Don't probe at all. */ else if (base_addr != 0) /* Don't probe at all. */
return -ENXIO; return -ENXIO;
for (i = 0; eepro_portlist[i]; i++) { for (i = 0; eepro_portlist[i]; i++) {
int ioaddr = eepro_portlist[i]; dev->base_addr = eepro_portlist[i];
dev->irq = irq;
if (check_region(ioaddr, EEPRO_IO_EXTENT)) if (eepro_probe1(dev, 1) == 0)
continue;
if (eepro_probe1(dev, ioaddr) == 0)
return 0; return 0;
} }
return -ENODEV; return -ENODEV;
} }
struct net_device * __init eepro_probe(int unit)
{
struct net_device *dev = alloc_etherdev(sizeof(struct eepro_local));
int err;
if (!dev)
return ERR_PTR(-ENODEV);
SET_MODULE_OWNER(dev);
sprintf(dev->name, "eth%d", unit);
netdev_boot_setup_check(dev);
err = do_eepro_probe(dev);
if (err)
goto out;
err = register_netdev(dev);
if (err)
goto out1;
return dev;
out1:
release_region(dev->base_addr, EEPRO_IO_EXTENT);
out:
free_netdev(dev);
return ERR_PTR(err);
}
static void __init printEEPROMInfo(short ioaddr, struct net_device *dev) static void __init printEEPROMInfo(short ioaddr, struct net_device *dev)
{ {
unsigned short Word; unsigned short Word;
...@@ -713,51 +736,46 @@ static void eepro_print_info (struct net_device *dev) ...@@ -713,51 +736,46 @@ static void eepro_print_info (struct net_device *dev)
probes on the ISA bus. A good device probe avoids doing writes, and probes on the ISA bus. A good device probe avoids doing writes, and
verifies that the correct device exists and functions. */ verifies that the correct device exists and functions. */
static int __init eepro_probe1(struct net_device *dev, short ioaddr) static int __init eepro_probe1(struct net_device *dev, int autoprobe)
{ {
unsigned short station_addr[6], id, counter; unsigned short station_addr[6], id, counter;
int i, j, irqMask, retval = 0; int i;
struct eepro_local *lp; struct eepro_local *lp;
enum iftype { AUI=0, BNC=1, TPE=2 }; enum iftype { AUI=0, BNC=1, TPE=2 };
int ioaddr = dev->base_addr;
/* Grab the region so we can find another board if autoIRQ fails. */
if (!request_region(ioaddr, EEPRO_IO_EXTENT, dev->name)) {
if (!autoprobe)
printk(KERN_WARNING "EEPRO: io-port 0x%04x in use \n",
ioaddr);
return -EBUSY;
}
/* Now, we are going to check for the signature of the /* Now, we are going to check for the signature of the
ID_REG (register 2 of bank 0) */ ID_REG (register 2 of bank 0) */
id=inb(ioaddr + ID_REG); id = inb(ioaddr + ID_REG);
if (((id) & ID_REG_MASK) != ID_REG_SIG) { if ((id & ID_REG_MASK) != ID_REG_SIG)
retval = -ENODEV;
goto exit; goto exit;
}
/* We seem to have the 82595 signature, let's /* We seem to have the 82595 signature, let's
play with its counter (last 2 bits of play with its counter (last 2 bits of
register 2 of bank 0) to be sure. */ register 2 of bank 0) to be sure. */
counter = (id & R_ROBIN_BITS); counter = id & R_ROBIN_BITS;
if (((id=inb(ioaddr+ID_REG)) & R_ROBIN_BITS)!=(counter + 0x40)) { if ((inb(ioaddr + ID_REG) & R_ROBIN_BITS) != (counter + 0x40))
retval = -ENODEV;
goto exit; goto exit;
}
/* Initialize the device structure */
dev->priv = kmalloc(sizeof(struct eepro_local), GFP_KERNEL);
if (!dev->priv) {
retval = -ENOMEM;
goto exit;
}
memset(dev->priv, 0, sizeof(struct eepro_local));
lp = (struct eepro_local *)dev->priv; lp = (struct eepro_local *)dev->priv;
memset(lp, 0, sizeof(struct eepro_local));
/* default values */
lp->eepro = 0;
lp->xmt_bar = XMT_BAR_PRO; lp->xmt_bar = XMT_BAR_PRO;
lp->xmt_lower_limit_reg = XMT_LOWER_LIMIT_REG_PRO; lp->xmt_lower_limit_reg = XMT_LOWER_LIMIT_REG_PRO;
lp->xmt_upper_limit_reg = XMT_UPPER_LIMIT_REG_PRO; lp->xmt_upper_limit_reg = XMT_UPPER_LIMIT_REG_PRO;
lp->eeprom_reg = EEPROM_REG_PRO; lp->eeprom_reg = EEPROM_REG_PRO;
spin_lock_init(&lp->lock);
/* Now, get the ethernet hardware address from /* Now, get the ethernet hardware address from
the EEPROM */ the EEPROM */
...@@ -766,8 +784,7 @@ static int __init eepro_probe1(struct net_device *dev, short ioaddr) ...@@ -766,8 +784,7 @@ static int __init eepro_probe1(struct net_device *dev, short ioaddr)
/* FIXME - find another way to know that we've found /* FIXME - find another way to know that we've found
* an Etherexpress 10 * an Etherexpress 10
*/ */
if (station_addr[0] == 0x0000 || if (station_addr[0] == 0x0000 || station_addr[0] == 0xffff) {
station_addr[0] == 0xffff) {
lp->eepro = LAN595FX_10ISA; lp->eepro = LAN595FX_10ISA;
lp->eeprom_reg = EEPROM_REG_10; lp->eeprom_reg = EEPROM_REG_10;
lp->xmt_lower_limit_reg = XMT_LOWER_LIMIT_REG_10; lp->xmt_lower_limit_reg = XMT_LOWER_LIMIT_REG_10;
...@@ -786,8 +803,6 @@ static int __init eepro_probe1(struct net_device *dev, short ioaddr) ...@@ -786,8 +803,6 @@ static int __init eepro_probe1(struct net_device *dev, short ioaddr)
} }
/* Fill in the 'dev' fields. */ /* Fill in the 'dev' fields. */
dev->base_addr = ioaddr;
for (i=0; i < 6; i++) for (i=0; i < 6; i++)
dev->dev_addr[i] = ((unsigned char *) station_addr)[5-i]; dev->dev_addr[i] = ((unsigned char *) station_addr)[5-i];
...@@ -798,40 +813,31 @@ static int __init eepro_probe1(struct net_device *dev, short ioaddr) ...@@ -798,40 +813,31 @@ static int __init eepro_probe1(struct net_device *dev, short ioaddr)
/* calculate {xmt,rcv}_{lower,upper}_limit */ /* calculate {xmt,rcv}_{lower,upper}_limit */
eepro_recalc(dev); eepro_recalc(dev);
if (GetBit( read_eeprom(ioaddr, 5, dev),ee_BNC_TPE)) if (GetBit( read_eeprom(ioaddr, 5, dev),ee_BNC_TPE))
dev->if_port = BNC; dev->if_port = BNC;
else else
dev->if_port = TPE; dev->if_port = TPE;
if ((dev->irq < 2) && (lp->eepro!=0)) { if (dev->irq < 2 && lp->eepro != 0) {
i = read_eeprom(ioaddr, 1, dev); /* Mask off INT number */
irqMask = read_eeprom(ioaddr, 7, dev); int count = read_eeprom(ioaddr, 1, dev) & 7;
i &= 0x07; /* Mask off INT number */ unsigned irqMask = read_eeprom(ioaddr, 7, dev);
while (count--)
irqMask &= irqMask - 1;
count = ffs(irqMask);
if (count)
dev->irq = count - 1;
for (j=0; ((j<16) && (i>=0)); j++) {
if ((irqMask & (1<<j))!=0) {
if (i==0) {
dev->irq = j;
break; /* found bit corresponding to irq */
}
i--; /* count bits set in irqMask */
}
}
if (dev->irq < 2) { if (dev->irq < 2) {
printk(KERN_ERR " Duh! invalid interrupt vector stored in EEPROM.\n"); printk(KERN_ERR " Duh! illegal interrupt vector stored in EEPROM.\n");
retval = -ENODEV; goto exit;
goto freeall; } else if (dev->irq == 2) {
} else dev->irq = 9;
if (dev->irq==2) dev->irq = 9;
} }
/* Grab the region so we can find another board if autoIRQ fails. */
if (!request_region(ioaddr, EEPRO_IO_EXTENT, dev->name)) {
printk(KERN_WARNING "EEPRO: io-port 0x%04x in use \n", ioaddr);
goto freeall;
} }
((struct eepro_local *)dev->priv)->lock = SPIN_LOCK_UNLOCKED;
dev->open = eepro_open; dev->open = eepro_open;
dev->stop = eepro_close; dev->stop = eepro_close;
...@@ -841,22 +847,15 @@ static int __init eepro_probe1(struct net_device *dev, short ioaddr) ...@@ -841,22 +847,15 @@ static int __init eepro_probe1(struct net_device *dev, short ioaddr)
dev->tx_timeout = eepro_tx_timeout; dev->tx_timeout = eepro_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT; dev->watchdog_timeo = TX_TIMEOUT;
/* Fill in the fields of the device structure with
ethernet generic values */
ether_setup(dev);
/* print boot time info */ /* print boot time info */
eepro_print_info(dev); eepro_print_info(dev);
/* reset 82595 */ /* reset 82595 */
eepro_reset(ioaddr); eepro_reset(ioaddr);
return 0;
exit: exit:
return retval; release_region(dev->base_addr, EEPRO_IO_EXTENT);
freeall: return -ENODEV;
kfree(dev->priv);
goto exit;
} }
/* Open/initialize the board. This is called (in the current kernel) /* Open/initialize the board. This is called (in the current kernel)
...@@ -1701,7 +1700,7 @@ eepro_transmit_interrupt(struct net_device *dev) ...@@ -1701,7 +1700,7 @@ eepro_transmit_interrupt(struct net_device *dev)
#ifdef MODULE #ifdef MODULE
#define MAX_EEPRO 8 #define MAX_EEPRO 8
static struct net_device dev_eepro[MAX_EEPRO]; static struct net_device *dev_eepro[MAX_EEPRO];
static int io[MAX_EEPRO]; static int io[MAX_EEPRO];
static int irq[MAX_EEPRO]; static int irq[MAX_EEPRO];
...@@ -1729,6 +1728,7 @@ MODULE_PARM_DESC(autodetect, "EtherExpress Pro/10 force board(s) detection (0-1) ...@@ -1729,6 +1728,7 @@ MODULE_PARM_DESC(autodetect, "EtherExpress Pro/10 force board(s) detection (0-1)
int int
init_module(void) init_module(void)
{ {
struct net_device *dev;
int i; int i;
if (io[0] == 0 && autodetect == 0) { if (io[0] == 0 && autodetect == 0) {
printk(KERN_WARNING "eepro_init_module: Probe is very dangerous in ISA boards!\n"); printk(KERN_WARNING "eepro_init_module: Probe is very dangerous in ISA boards!\n");
...@@ -1743,15 +1743,22 @@ init_module(void) ...@@ -1743,15 +1743,22 @@ init_module(void)
} }
for (i = 0; i < MAX_EEPRO; i++) { for (i = 0; i < MAX_EEPRO; i++) {
struct net_device *d = &dev_eepro[n_eepro]; dev = alloc_etherdev(sizeof(struct eepro_local));
d->mem_end = mem[i]; if (!dev)
d->base_addr = io[i]; break;
d->irq = irq[i];
d->init = eepro_probe; dev->mem_end = mem[i];
dev->base_addr = io[i];
if (register_netdev(d) == 0) dev->irq = irq[i];
n_eepro++;
else if (do_eepro_probe(dev) == 0) {
if (register_netdev(dev) == 0) {
dev_eepro[n_eepro++] = dev;
continue;
}
release_region(dev->base_addr, EEPRO_IO_EXTENT);
}
free_netdev(dev);
break; break;
} }
...@@ -1767,15 +1774,10 @@ cleanup_module(void) ...@@ -1767,15 +1774,10 @@ cleanup_module(void)
int i; int i;
for (i=0; i<n_eepro; i++) { for (i=0; i<n_eepro; i++) {
struct net_device *d = &dev_eepro[i]; struct net_device *dev = dev_eepro[i];
unregister_netdev(d); unregister_netdev(dev);
release_region(dev->base_addr, EEPRO_IO_EXTENT);
kfree(d->priv); free_netdev(dev);
d->priv=NULL;
/* If we don't do this, we can't re-insmod it later. */
release_region(d->base_addr, EEPRO_IO_EXTENT);
} }
} }
#endif /* MODULE */ #endif /* 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