Commit 59d27320 authored by Alexander Viro's avatar Alexander Viro Committed by Stephen Hemminger

[arcnet arc-rimi] use alloc_netdev; module params; fix bugs on error/cleanup

parent 7661326e
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/delay.h> #include <linux/delay.h>
...@@ -85,8 +86,6 @@ static void arcrimi_copy_from_card(struct net_device *dev, int bufnum, int offse ...@@ -85,8 +86,6 @@ static void arcrimi_copy_from_card(struct net_device *dev, int bufnum, int offse
*/ */
static int __init arcrimi_probe(struct net_device *dev) static int __init arcrimi_probe(struct net_device *dev)
{ {
int retval;
BUGLVL(D_NORMAL) printk(VERSION); BUGLVL(D_NORMAL) printk(VERSION);
BUGLVL(D_NORMAL) printk("E-mail me if you actually test the RIM I driver, please!\n"); BUGLVL(D_NORMAL) printk("E-mail me if you actually test the RIM I driver, please!\n");
...@@ -114,11 +113,7 @@ static int __init arcrimi_probe(struct net_device *dev) ...@@ -114,11 +113,7 @@ static int __init arcrimi_probe(struct net_device *dev)
"ID!\n"); "ID!\n");
return -ENODEV; return -ENODEV;
} }
retval = arcrimi_found(dev); return arcrimi_found(dev);
if (retval < 0) {
release_mem_region(dev->mem_start, BUFFER_SIZE);
}
return retval;
} }
...@@ -129,11 +124,13 @@ static int __init arcrimi_probe(struct net_device *dev) ...@@ -129,11 +124,13 @@ static int __init arcrimi_probe(struct net_device *dev)
static int __init arcrimi_found(struct net_device *dev) static int __init arcrimi_found(struct net_device *dev)
{ {
struct arcnet_local *lp; struct arcnet_local *lp;
u_long first_mirror, last_mirror, shmem; unsigned long first_mirror, last_mirror, shmem;
int mirror_size; int mirror_size;
int err;
/* reserve the irq */ /* reserve the irq */
if (request_irq(dev->irq, &arcnet_interrupt, 0, "arcnet (RIM I)", dev)) { if (request_irq(dev->irq, &arcnet_interrupt, 0, "arcnet (RIM I)", dev)) {
release_mem_region(dev->mem_start, BUFFER_SIZE);
BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", dev->irq); BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", dev->irq);
return -ENODEV; return -ENODEV;
} }
...@@ -168,11 +165,7 @@ static int __init arcrimi_found(struct net_device *dev) ...@@ -168,11 +165,7 @@ static int __init arcrimi_found(struct net_device *dev)
/* initialize the rest of the device structure. */ /* initialize the rest of the device structure. */
lp = dev->priv = kmalloc(sizeof(struct arcnet_local), GFP_KERNEL); lp = dev->priv;
if (!lp) {
BUGMSG(D_NORMAL, "Can't allocate device data!\n");
goto err_free_irq;
}
lp->card_name = "RIM I"; lp->card_name = "RIM I";
lp->hw.command = arcrimi_command; lp->hw.command = arcrimi_command;
lp->hw.status = arcrimi_status; lp->hw.status = arcrimi_status;
...@@ -181,18 +174,6 @@ static int __init arcrimi_found(struct net_device *dev) ...@@ -181,18 +174,6 @@ static int __init arcrimi_found(struct net_device *dev)
lp->hw.owner = THIS_MODULE; lp->hw.owner = THIS_MODULE;
lp->hw.copy_to_card = arcrimi_copy_to_card; lp->hw.copy_to_card = arcrimi_copy_to_card;
lp->hw.copy_from_card = arcrimi_copy_from_card; lp->hw.copy_from_card = arcrimi_copy_from_card;
lp->mem_start = ioremap(dev->mem_start, dev->mem_end - dev->mem_start + 1);
if (!lp->mem_start) {
BUGMSG(D_NORMAL, "Can't remap device memory!\n");
goto err_free_dev_priv;
}
/* Fill in the fields of the device structure with generic
* values.
*/
arcdev_setup(dev);
/* get and check the station ID from offset 1 in shmem */
dev->dev_addr[0] = readb(lp->mem_start + 1);
/* /*
* re-reserve the memory region - arcrimi_probe() alloced this reqion * re-reserve the memory region - arcrimi_probe() alloced this reqion
...@@ -200,25 +181,40 @@ static int __init arcrimi_found(struct net_device *dev) ...@@ -200,25 +181,40 @@ static int __init arcrimi_found(struct net_device *dev)
* with the correct size. There is a VERY slim chance this could * with the correct size. There is a VERY slim chance this could
* fail. * fail.
*/ */
release_mem_region(dev->mem_start, BUFFER_SIZE); release_mem_region(shmem, BUFFER_SIZE);
if (!request_mem_region(dev->mem_start, if (!request_mem_region(dev->mem_start,
dev->mem_end - dev->mem_start + 1, dev->mem_end - dev->mem_start + 1,
"arcnet (90xx)")) { "arcnet (90xx)")) {
BUGMSG(D_NORMAL, "Card memory already allocated\n"); BUGMSG(D_NORMAL, "Card memory already allocated\n");
goto err_free_dev_priv; goto err_free_irq;
}
lp->mem_start = ioremap(dev->mem_start, dev->mem_end - dev->mem_start + 1);
if (!lp->mem_start) {
BUGMSG(D_NORMAL, "Can't remap device memory!\n");
goto err_release_mem;
} }
/* get and check the station ID from offset 1 in shmem */
dev->dev_addr[0] = readb(lp->mem_start + 1);
BUGMSG(D_NORMAL, "ARCnet RIM I: station %02Xh found at IRQ %d, " BUGMSG(D_NORMAL, "ARCnet RIM I: station %02Xh found at IRQ %d, "
"ShMem %lXh (%ld*%d bytes).\n", "ShMem %lXh (%ld*%d bytes).\n",
dev->dev_addr[0], dev->dev_addr[0],
dev->irq, dev->mem_start, dev->irq, dev->mem_start,
(dev->mem_end - dev->mem_start + 1) / mirror_size, mirror_size); (dev->mem_end - dev->mem_start + 1) / mirror_size, mirror_size);
err = register_netdev(dev);
if (err)
goto err_unmap;
return 0; return 0;
err_free_dev_priv: err_unmap:
kfree(dev->priv); iounmap(lp->mem_start);
err_free_irq: err_release_mem:
release_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1);
err_free_irq:
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
return -EIO; return -EIO;
} }
...@@ -294,94 +290,81 @@ static void arcrimi_copy_from_card(struct net_device *dev, int bufnum, int offse ...@@ -294,94 +290,81 @@ static void arcrimi_copy_from_card(struct net_device *dev, int bufnum, int offse
TIME("memcpy_fromio", count, memcpy_fromio(buf, memaddr, count)); TIME("memcpy_fromio", count, memcpy_fromio(buf, memaddr, count));
} }
#ifdef MODULE static int node;
static int io; /* use the insmod io= irq= node= options */
static struct net_device *my_dev; static int irq;
static char device[9]; /* use eg. device=arc1 to change name */
/* Module parameters */
static int node = 0;
static int io = 0x0; /* <--- EDIT THESE LINES FOR YOUR CONFIGURATION */
static int irq = 0; /* or use the insmod io= irq= shmem= options */
static char *device; /* use eg. device="arc1" to change name */
MODULE_PARM(node, "i"); module_param(node, int, 0);
MODULE_PARM(io, "i"); module_param(io, int, 0);
MODULE_PARM(irq, "i"); module_param(irq, int, 0);
MODULE_PARM(device, "s"); module_param_string(device, device, sizeof(device), 0);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
int init_module(void) static struct net_device *my_dev;
static int __init arc_rimi_init(void)
{ {
struct net_device *dev; struct net_device *dev;
int err;
dev = dev_alloc(device ? : "arc%d", &err); dev = alloc_netdev(sizeof(struct arcnet_local),
device[0] ? device : "arc%d",
arcdev_setup);
if (!dev) if (!dev)
return err; return -ENOMEM;
if (node && node != 0xff) if (node && node != 0xff)
dev->dev_addr[0] = node; dev->dev_addr[0] = node;
dev->base_addr = io; dev->mem_start = io;
dev->irq = irq; dev->irq = irq;
if (dev->irq == 2) if (dev->irq == 2)
dev->irq = 9; dev->irq = 9;
if (arcrimi_probe(dev)) if (arcrimi_probe(dev)) {
free_netdev(dev);
return -EIO; return -EIO;
}
my_dev = dev; my_dev = dev;
return 0; return 0;
} }
void cleanup_module(void) static void __exit arc_rimi_exit(void)
{ {
struct net_device *dev = my_dev; struct net_device *dev = my_dev;
struct arcnet_local *lp = (struct arcnet_local *) dev->priv; struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
unregister_netdev(dev); unregister_netdev(dev);
free_irq(dev->irq, dev);
iounmap(lp->mem_start); iounmap(lp->mem_start);
release_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1); release_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1);
kfree(dev->priv); free_irq(dev->irq, dev);
free_netdev(dev); free_netdev(dev);
} }
#else #ifndef MODULE
static int __init arcrimi_setup(char *s) static int __init arcrimi_setup(char *s)
{ {
struct net_device *dev;
int ints[8]; int ints[8];
s = get_options(s, 8, ints); s = get_options(s, 8, ints);
if (!ints[0]) if (!ints[0])
return 1; return 1;
dev = alloc_bootmem(sizeof(struct net_device));
memset(dev, 0, sizeof(struct net_device));
dev->init = arcrimi_probe;
switch (ints[0]) { switch (ints[0]) {
default: /* ERROR */ default: /* ERROR */
printk("arcrimi: Too many arguments.\n"); printk("arcrimi: Too many arguments.\n");
case 3: /* Node ID */ case 3: /* Node ID */
dev->dev_addr[0] = ints[3]; node = ints[3];
case 2: /* IRQ */ case 2: /* IRQ */
dev->irq = ints[2]; irq = ints[2];
case 1: /* IO address */ case 1: /* IO address */
dev->mem_start = ints[1]; io = ints[1];
} }
if (*s) if (*s)
strncpy(dev->name, s, 9); snprintf(device, sizeof(device), "%s", s);
else
strcpy(dev->name, "arc%d");
if (register_netdev(dev))
printk(KERN_ERR "arc-rimi: Cannot register arcnet device\n");
return 1; return 1;
} }
__setup("arcrimi=", arcrimi_setup); __setup("arcrimi=", arcrimi_setup);
#endif /* MODULE */ #endif /* MODULE */
module_init(arc_rimi_init)
module_exit(arc_rimi_exit)
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