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
+ add free_netdev
diff -Nru a/drivers/net/Space.c b/drivers/net/Space.c
--- a/drivers/net/Space.c Thu Sep 25 16:30:45 2003
+++ b/drivers/net/Space.c Thu Sep 25 16:30:45 2003
@@ -73,7 +73,7 @@
extern struct net_device *ni52_probe(int unit);
extern struct net_device *ni65_probe(int unit);
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 smc_init( struct net_device * );
extern int atarilance_probe(struct net_device *);
@@ -281,13 +281,13 @@
#ifdef CONFIG_ELPLUS /* 3c505 */
{elplus_probe, 0},
#endif
-#ifdef CONFIG_SK_G16
- {SK_init, 0},
-#endif
{NULL, 0},
};
static struct devprobe2 isa_probes2[] __initdata = {
+#ifdef CONFIG_SK_G16
+ {SK_init, 0},
+#endif
#ifdef CONFIG_NI5010
{ni5010_probe, 0},
#endif
diff -Nru a/drivers/net/sk_g16.c b/drivers/net/sk_g16.c
--- a/drivers/net/sk_g16.c Thu Sep 25 16:30:45 2003
+++ b/drivers/net/sk_g16.c Thu Sep 25 16:30:45 2003
@@ -457,8 +457,6 @@
/* static variables */
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;
/* Macros */
@@ -472,7 +470,6 @@
* 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 void SK_timeout(struct net_device *dev);
@@ -530,84 +527,71 @@
* YY/MM/DD uid Description
-*/
+static int io; /* 0 == probe */
+
/*
* 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 == 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 */
static unsigned version_printed;
+ struct net_device *dev = alloc_etherdev(sizeof(struct priv));
+ int err = -ENODEV;
+
+ if (!dev)
+ return ERR_PTR(-ENOMEM);
- /* get preconfigured base_addr from dev which is done in Space.c */
- int base_addr = dev->base_addr;
+ if (unit >= 0) {
+ sprintf(dev->name, "eth%d", unit);
+ netdev_boot_setup_check(dev);
+ io = dev->base_addr;
+ }
if (version_printed++ == 0)
PRINTK(("%s: %s", SK_NAME, rcsid));
- if (base_addr > 0x0ff) /* Check a single specified address */
- {
- int rc = -ENODEV;
-
- ioaddr = base_addr;
+ if (io > 0xff) { /* Check a single specified address */
+ err = -EBUSY;
+ /* Check if on specified address is a SK_G16 */
+ if (request_region(io, ETHERCARD_TOTAL_SIZE, "sk_g16")) {
+ err = SK_probe(dev, io);
+ if (!err)
+ goto got_it;
+ release_region(io, ETHERCARD_TOTAL_SIZE);
+ }
+ } else if (io > 0) { /* Don't probe at all */
+ err = -ENXIO;
+ } else {
+ /* Autoprobe base_addr */
+ for (port = &ports[0]; *port; port++) {
+ io = *port;
+
+ /* Check if I/O Port region is used by another board */
+ if (!request_region(io, ETHERCARD_TOTAL_SIZE, "sk_g16"))
+ continue; /* Try next Port address */
+
+ /* Check if at ioaddr is a SK_G16 */
+ if (SK_probe(dev, io) == 0)
+ goto got_it;
- /* Check if on specified address is a SK_G16 */
- if (!request_region(ioaddr, ETHERCARD_TOTAL_SIZE, "sk_g16"))
- return -EBUSY;
-
- if ( (inb(SK_POS0) == SK_IDLOW) ||
- (inb(SK_POS1) == SK_IDHIGH) )
- {
- rc = SK_probe(dev, ioaddr);
- }
-
- if (rc)
- release_region(ioaddr, ETHERCARD_TOTAL_SIZE);
- return rc;
+ release_region(io, ETHERCARD_TOTAL_SIZE);
+ }
}
- else if (base_addr > 0) /* Don't probe at all */
- {
- return -ENXIO;
+err_out:
+ free_netdev(dev);
+ return ERR_PTR(err);
+
+got_it:
+ err = register_netdev(dev);
+ if (err) {
+ release_region(dev->base_addr, ETHERCARD_TOTAL_SIZE);
+ goto err_out;
}
-
- /* Autoprobe base_addr */
-
- for (port = &ports[0]; *port; port++)
- {
- ioaddr = *port; /* we need ioaddr for accessing POS regs
*/
-
- /* Check if I/O Port region is used by another board */
-
- if (!request_region(ioaddr, ETHERCARD_TOTAL_SIZE, "sk_g16"))
- {
- continue; /* Try next Port address */
- }
-
- /* Check if at ioaddr is a SK_G16 */
-
- if ( !(inb(SK_POS0) == SK_IDLOW) ||
- !(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 */
- }
-
- release_region(ioaddr, ETHERCARD_TOTAL_SIZE);
- }
-
- dev->base_addr = base_addr; /* Write back original base_addr */
-
- return -ENODEV; /* Failed to find or init driver */
+ return dev;
} /* End of SK_init */
@@ -620,54 +604,22 @@
#ifdef MODULE
-static int io; /* 0 == probe */
-
static int __init SK_init_module (void)
{
- int rc;
-
- 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;
+ SK_dev = SK_init(-1);
+ return IS_ERR(SK_dev) ? PTR_ERR(SK_dev) : 0;
}
-#endif /* MODULE */
-
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);
- free_netdev(SK_dev);
- SK_dev = NULL;
- }
- if (SK_ioaddr) {
- release_region(SK_ioaddr, ETHERCARD_TOTAL_SIZE);
- SK_ioaddr = 0;
- }
-
+ unregister_netdev(SK_dev);
+ release_region(SK_dev->base_addr, ETHERCARD_TOTAL_SIZE);
+ free_netdev(SK_dev);
}
-
-#ifdef MODULE
module_init(SK_init_module);
-#endif
module_exit(SK_cleanup_module);
-
+#endif
/*-
@@ -695,7 +647,11 @@
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 */
- 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)
{
@@ -837,12 +793,6 @@
dev->dev_addr[4],
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 */
/* Assign our Device Driver functions */
@@ -856,10 +806,6 @@
dev->watchdog_timeo = HZ/7;
- /* Set the generic fields of the device structure */
-
- ether_setup(dev);
-
dev->flags &= ~IFF_MULTICAST;
/* Initialize private structure */
@@ -884,12 +830,7 @@
SK_print_pos(dev, "End of SK_probe");
SK_print_ram(dev);
#endif
-
- SK_dev = dev;
- SK_ioaddr = ioaddr;
-
return 0; /* Initialization done */
-
} /* End of SK_probe() */
@@ -1280,7 +1221,7 @@
memcpy_toio((tmdp->u.buffer & 0x00ffffff), skb->data, 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 */
|