Commit e3fcad0f authored by Stephen Hemminger's avatar Stephen Hemminger

[PATCH] (06/12) Probe2 -- sk16

from viro NE17-sk16
	* switched sk_g16 to dynamic allocation
	* sk_g16: embedded ->priv
	* sk_g16: fixed buggy check for signature (|| instead of &&, somebody
	  forgot to replace it when inverting the test).
	* sk_g16: fixed use after kfree()
	* sk_g16: fixed init_etherdev() race
Additional:
	* add free_netdev
parent 65e9e2db
...@@ -72,7 +72,7 @@ extern struct net_device *ni5010_probe(int unit); ...@@ -72,7 +72,7 @@ extern struct net_device *ni5010_probe(int unit);
extern struct net_device *ni52_probe(int unit); extern struct net_device *ni52_probe(int unit);
extern struct net_device *ni65_probe(int unit); extern struct net_device *ni65_probe(int unit);
extern int sonic_probe(struct net_device *); extern int sonic_probe(struct net_device *);
extern int SK_init(struct net_device *); extern struct net_device *SK_init(int unit);
extern int seeq8005_probe(struct net_device *); extern int seeq8005_probe(struct net_device *);
extern int smc_init( struct net_device * ); extern int smc_init( struct net_device * );
extern int atarilance_probe(struct net_device *); extern int atarilance_probe(struct net_device *);
...@@ -276,14 +276,14 @@ static struct devprobe isa_probes[] __initdata = { ...@@ -276,14 +276,14 @@ static struct devprobe isa_probes[] __initdata = {
#endif #endif
#ifdef CONFIG_ELPLUS /* 3c505 */ #ifdef CONFIG_ELPLUS /* 3c505 */
{elplus_probe, 0}, {elplus_probe, 0},
#endif
#ifdef CONFIG_SK_G16
{SK_init, 0},
#endif #endif
{NULL, 0}, {NULL, 0},
}; };
static struct devprobe2 isa_probes2[] __initdata = { static struct devprobe2 isa_probes2[] __initdata = {
#ifdef CONFIG_SK_G16
{SK_init, 0},
#endif
#ifdef CONFIG_NI5010 #ifdef CONFIG_NI5010
{ni5010_probe, 0}, {ni5010_probe, 0},
#endif #endif
......
...@@ -457,8 +457,6 @@ struct priv ...@@ -457,8 +457,6 @@ struct priv
/* static variables */ /* static variables */
static SK_RAM *board; /* pointer to our memory mapped board components */ static SK_RAM *board; /* pointer to our memory mapped board components */
static struct net_device *SK_dev;
unsigned long SK_ioaddr;
static spinlock_t SK_lock = SPIN_LOCK_UNLOCKED; static spinlock_t SK_lock = SPIN_LOCK_UNLOCKED;
/* Macros */ /* Macros */
...@@ -472,7 +470,6 @@ static spinlock_t SK_lock = SPIN_LOCK_UNLOCKED; ...@@ -472,7 +470,6 @@ static spinlock_t SK_lock = SPIN_LOCK_UNLOCKED;
* See for short explanation of each function its definitions header. * See for short explanation of each function its definitions header.
*/ */
int SK_init(struct net_device *dev);
static int SK_probe(struct net_device *dev, short ioaddr); static int SK_probe(struct net_device *dev, short ioaddr);
static void SK_timeout(struct net_device *dev); static void SK_timeout(struct net_device *dev);
...@@ -530,84 +527,71 @@ void SK_print_ram(struct net_device *dev); ...@@ -530,84 +527,71 @@ void SK_print_ram(struct net_device *dev);
* YY/MM/DD uid Description * YY/MM/DD uid Description
-*/ -*/
static int io; /* 0 == probe */
/* /*
* Check for a network adaptor of this type, and return '0' if one exists. * Check for a network adaptor of this type, and return '0' if one exists.
* If dev->base_addr == 0, probe all likely locations. * If dev->base_addr == 0, probe all likely locations.
* If dev->base_addr == 1, always return failure. * If dev->base_addr == 1, always return failure.
*/ */
int __init SK_init(struct net_device *dev) struct net_device * __init SK_init(int unit)
{ {
int ioaddr; /* I/O port address used for POS regs */
int *port, ports[] = SK_IO_PORTS; /* SK_G16 supported ports */ int *port, ports[] = SK_IO_PORTS; /* SK_G16 supported ports */
static unsigned version_printed; static unsigned version_printed;
struct net_device *dev = alloc_etherdev(sizeof(struct priv));
int err = -ENODEV;
/* get preconfigured base_addr from dev which is done in Space.c */ if (!dev)
int base_addr = dev->base_addr; return ERR_PTR(-ENOMEM);
if (unit >= 0) {
sprintf(dev->name, "eth%d", unit);
netdev_boot_setup_check(dev);
io = dev->base_addr;
}
if (version_printed++ == 0) if (version_printed++ == 0)
PRINTK(("%s: %s", SK_NAME, rcsid)); PRINTK(("%s: %s", SK_NAME, rcsid));
if (base_addr > 0x0ff) /* Check a single specified address */ if (io > 0xff) { /* Check a single specified address */
{ err = -EBUSY;
int rc = -ENODEV;
ioaddr = base_addr;
/* Check if on specified address is a SK_G16 */ /* Check if on specified address is a SK_G16 */
if (!request_region(ioaddr, ETHERCARD_TOTAL_SIZE, "sk_g16")) if (request_region(io, ETHERCARD_TOTAL_SIZE, "sk_g16")) {
return -EBUSY; err = SK_probe(dev, io);
if (!err)
if ( (inb(SK_POS0) == SK_IDLOW) || goto got_it;
(inb(SK_POS1) == SK_IDHIGH) ) release_region(io, ETHERCARD_TOTAL_SIZE);
{ }
rc = SK_probe(dev, ioaddr); } else if (io > 0) { /* Don't probe at all */
} err = -ENXIO;
} else {
if (rc)
release_region(ioaddr, ETHERCARD_TOTAL_SIZE);
return rc;
}
else if (base_addr > 0) /* Don't probe at all */
{
return -ENXIO;
}
/* Autoprobe base_addr */ /* Autoprobe base_addr */
for (port = &ports[0]; *port; port++) {
for (port = &ports[0]; *port; port++) io = *port;
{
ioaddr = *port; /* we need ioaddr for accessing POS regs */
/* Check if I/O Port region is used by another board */ /* Check if I/O Port region is used by another board */
if (!request_region(io, ETHERCARD_TOTAL_SIZE, "sk_g16"))
if (!request_region(ioaddr, ETHERCARD_TOTAL_SIZE, "sk_g16"))
{
continue; /* Try next Port address */ continue; /* Try next Port address */
}
/* Check if at ioaddr is a SK_G16 */ /* Check if at ioaddr is a SK_G16 */
if (SK_probe(dev, io) == 0)
goto got_it;
if ( !(inb(SK_POS0) == SK_IDLOW) || release_region(io, ETHERCARD_TOTAL_SIZE);
!(inb(SK_POS1) == SK_IDHIGH) )
{
release_region(ioaddr, ETHERCARD_TOTAL_SIZE);
continue; /* Try next Port address */
} }
dev->base_addr = ioaddr; /* Set I/O Port Address */
if (SK_probe(dev, ioaddr) == 0)
{
return 0; /* Card found and initialized */
} }
err_out:
free_netdev(dev);
return ERR_PTR(err);
release_region(ioaddr, ETHERCARD_TOTAL_SIZE); got_it:
err = register_netdev(dev);
if (err) {
release_region(dev->base_addr, ETHERCARD_TOTAL_SIZE);
goto err_out;
} }
return dev;
dev->base_addr = base_addr; /* Write back original base_addr */
return -ENODEV; /* Failed to find or init driver */
} /* End of SK_init */ } /* End of SK_init */
...@@ -620,54 +604,22 @@ MODULE_PARM_DESC(io, "0 to probe common ports (unsafe), or the I/O base of the b ...@@ -620,54 +604,22 @@ MODULE_PARM_DESC(io, "0 to probe common ports (unsafe), or the I/O base of the b
#ifdef MODULE #ifdef MODULE
static int io; /* 0 == probe */
static int __init SK_init_module (void) static int __init SK_init_module (void)
{ {
int rc; SK_dev = SK_init(-1);
return IS_ERR(SK_dev) ? PTR_ERR(SK_dev) : 0;
SK_dev = init_etherdev (NULL, 0);
if (!SK_dev)
return -ENOMEM;
SK_dev->base_addr = io;
rc = SK_init (SK_dev);
if (rc) {
unregister_netdev (SK_dev);
kfree (SK_dev);
SK_dev = NULL;
}
return rc;
} }
#endif /* MODULE */
static void __exit SK_cleanup_module (void) static void __exit SK_cleanup_module (void)
{ {
if (SK_dev) {
if (SK_dev->priv) {
kfree(SK_dev->priv);
SK_dev->priv = NULL;
}
unregister_netdev(SK_dev); unregister_netdev(SK_dev);
release_region(SK_dev->base_addr, ETHERCARD_TOTAL_SIZE);
free_netdev(SK_dev); free_netdev(SK_dev);
SK_dev = NULL;
}
if (SK_ioaddr) {
release_region(SK_ioaddr, ETHERCARD_TOTAL_SIZE);
SK_ioaddr = 0;
}
} }
#ifdef MODULE
module_init(SK_init_module); module_init(SK_init_module);
#endif
module_exit(SK_cleanup_module); module_exit(SK_cleanup_module);
#endif
/*- /*-
...@@ -695,7 +647,11 @@ int __init SK_probe(struct net_device *dev, short ioaddr) ...@@ -695,7 +647,11 @@ int __init SK_probe(struct net_device *dev, short ioaddr)
int sk_addr_flag = 0; /* SK ADDR correct? 1 - no, 0 - yes */ int sk_addr_flag = 0; /* SK ADDR correct? 1 - no, 0 - yes */
unsigned int rom_addr; /* used to store RAM address used for POS_ADDR */ unsigned int rom_addr; /* used to store RAM address used for POS_ADDR */
struct priv *p; /* SK_G16 private structure */ struct priv *p = dev->priv; /* SK_G16 private structure */
if (inb(SK_POS0) != SK_IDLOW || inb(SK_POS1) != SK_IDHIGH)
return -ENODEV;
dev->base_addr = ioaddr;
if (SK_ADDR & 0x3fff || SK_ADDR < 0xa0000) if (SK_ADDR & 0x3fff || SK_ADDR < 0xa0000)
{ {
...@@ -837,12 +793,6 @@ int __init SK_probe(struct net_device *dev, short ioaddr) ...@@ -837,12 +793,6 @@ int __init SK_probe(struct net_device *dev, short ioaddr)
dev->dev_addr[4], dev->dev_addr[4],
dev->dev_addr[5]); dev->dev_addr[5]);
/* Allocate memory for private structure */
p = dev->priv = (void *) kmalloc(sizeof(struct priv), GFP_KERNEL);
if (p == NULL) {
printk("%s: ERROR - no memory for driver data!\n", dev->name);
return -ENOMEM;
}
memset((char *) dev->priv, 0, sizeof(struct priv)); /* clear memory */ memset((char *) dev->priv, 0, sizeof(struct priv)); /* clear memory */
/* Assign our Device Driver functions */ /* Assign our Device Driver functions */
...@@ -856,10 +806,6 @@ int __init SK_probe(struct net_device *dev, short ioaddr) ...@@ -856,10 +806,6 @@ int __init SK_probe(struct net_device *dev, short ioaddr)
dev->watchdog_timeo = HZ/7; dev->watchdog_timeo = HZ/7;
/* Set the generic fields of the device structure */
ether_setup(dev);
dev->flags &= ~IFF_MULTICAST; dev->flags &= ~IFF_MULTICAST;
/* Initialize private structure */ /* Initialize private structure */
...@@ -884,12 +830,7 @@ int __init SK_probe(struct net_device *dev, short ioaddr) ...@@ -884,12 +830,7 @@ int __init SK_probe(struct net_device *dev, short ioaddr)
SK_print_pos(dev, "End of SK_probe"); SK_print_pos(dev, "End of SK_probe");
SK_print_ram(dev); SK_print_ram(dev);
#endif #endif
SK_dev = dev;
SK_ioaddr = ioaddr;
return 0; /* Initialization done */ return 0; /* Initialization done */
} /* End of SK_probe() */ } /* End of SK_probe() */
...@@ -1280,7 +1221,7 @@ static int SK_send_packet(struct sk_buff *skb, struct net_device *dev) ...@@ -1280,7 +1221,7 @@ static int SK_send_packet(struct sk_buff *skb, struct net_device *dev)
memcpy_toio((tmdp->u.buffer & 0x00ffffff), skb->data, skb->len); memcpy_toio((tmdp->u.buffer & 0x00ffffff), skb->data, skb->len);
if (len != skb->len) if (len != skb->len)
memcpy_toio((tmdp->u.buffer & 0x00ffffff) + sb->len, pad, len-skb->len); memcpy_toio((tmdp->u.buffer & 0x00ffffff) + skb->len, pad, len-skb->len);
writew(-len, &tmdp->blen); /* set length to transmit */ writew(-len, &tmdp->blen); /* set length to transmit */
......
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