[PATCH] arcnet probing cleanups and fixes

make arcnet probing do request_mem_region() for all iomem it's going to
access, clean the code up.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
Al Viro
2005-12-02 03:54:44 -05:00
parent 3ee68c4af3
commit d0f6ecad39
2 changed files with 143 additions and 57 deletions

View File

@@ -97,25 +97,44 @@ static int __init arcrimi_probe(struct net_device *dev)
"must specify the shmem and irq!\n"); "must specify the shmem and irq!\n");
return -ENODEV; return -ENODEV;
} }
if (dev->dev_addr[0] == 0) {
BUGMSG(D_NORMAL, "You need to specify your card's station "
"ID!\n");
return -ENODEV;
}
/* /*
* Grab the memory region at mem_start for BUFFER_SIZE bytes. * Grab the memory region at mem_start for MIRROR_SIZE bytes.
* Later in arcrimi_found() the real size will be determined * Later in arcrimi_found() the real size will be determined
* and this reserve will be released and the correct size * and this reserve will be released and the correct size
* will be taken. * will be taken.
*/ */
if (!request_mem_region(dev->mem_start, BUFFER_SIZE, "arcnet (90xx)")) { if (!request_mem_region(dev->mem_start, MIRROR_SIZE, "arcnet (90xx)")) {
BUGMSG(D_NORMAL, "Card memory already allocated\n"); BUGMSG(D_NORMAL, "Card memory already allocated\n");
return -ENODEV; return -ENODEV;
} }
if (dev->dev_addr[0] == 0) {
release_mem_region(dev->mem_start, BUFFER_SIZE);
BUGMSG(D_NORMAL, "You need to specify your card's station "
"ID!\n");
return -ENODEV;
}
return arcrimi_found(dev); return arcrimi_found(dev);
} }
static int check_mirror(unsigned long addr, size_t size)
{
void __iomem *p;
int res = -1;
if (!request_mem_region(addr, size, "arcnet (90xx)"))
return -1;
p = ioremap(addr, size);
if (p) {
if (readb(p) == TESTvalue)
res = 1;
else
res = 0;
iounmap(p);
}
release_mem_region(addr, size);
return res;
}
/* /*
* Set up the struct net_device associated with this card. Called after * Set up the struct net_device associated with this card. Called after
@@ -125,19 +144,28 @@ static int __init arcrimi_found(struct net_device *dev)
{ {
struct arcnet_local *lp; struct arcnet_local *lp;
unsigned long first_mirror, last_mirror, shmem; unsigned long first_mirror, last_mirror, shmem;
void __iomem *p;
int mirror_size; int mirror_size;
int err; int err;
p = ioremap(dev->mem_start, MIRROR_SIZE);
if (!p) {
release_mem_region(dev->mem_start, MIRROR_SIZE);
BUGMSG(D_NORMAL, "Can't ioremap\n");
return -ENODEV;
}
/* 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); iounmap(p);
release_mem_region(dev->mem_start, MIRROR_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;
} }
shmem = dev->mem_start; shmem = dev->mem_start;
isa_writeb(TESTvalue, shmem); writeb(TESTvalue, p);
isa_writeb(dev->dev_addr[0], shmem + 1); /* actually the node ID */ writeb(dev->dev_addr[0], p + 1); /* actually the node ID */
/* find the real shared memory start/end points, including mirrors */ /* find the real shared memory start/end points, including mirrors */
@@ -146,17 +174,18 @@ static int __init arcrimi_found(struct net_device *dev)
* 2k (or there are no mirrors at all) but on some, it's 4k. * 2k (or there are no mirrors at all) but on some, it's 4k.
*/ */
mirror_size = MIRROR_SIZE; mirror_size = MIRROR_SIZE;
if (isa_readb(shmem) == TESTvalue if (readb(p) == TESTvalue
&& isa_readb(shmem - mirror_size) != TESTvalue && check_mirror(shmem - MIRROR_SIZE, MIRROR_SIZE) == 0
&& isa_readb(shmem - 2 * mirror_size) == TESTvalue) && check_mirror(shmem - 2 * MIRROR_SIZE, MIRROR_SIZE) == 1)
mirror_size *= 2; mirror_size = 2 * MIRROR_SIZE;
first_mirror = last_mirror = shmem; first_mirror = shmem - mirror_size;
while (isa_readb(first_mirror) == TESTvalue) while (check_mirror(first_mirror, mirror_size) == 1)
first_mirror -= mirror_size; first_mirror -= mirror_size;
first_mirror += mirror_size; first_mirror += mirror_size;
while (isa_readb(last_mirror) == TESTvalue) last_mirror = shmem + mirror_size;
while (check_mirror(last_mirror, mirror_size) == 1)
last_mirror += mirror_size; last_mirror += mirror_size;
last_mirror -= mirror_size; last_mirror -= mirror_size;
@@ -181,7 +210,8 @@ 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(shmem, BUFFER_SIZE); iounmap(p);
release_mem_region(shmem, MIRROR_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)")) {

View File

@@ -53,7 +53,7 @@
/* Internal function declarations */ /* Internal function declarations */
static int com90xx_found(int ioaddr, int airq, u_long shmem); static int com90xx_found(int ioaddr, int airq, u_long shmem, void __iomem *);
static void com90xx_command(struct net_device *dev, int command); static void com90xx_command(struct net_device *dev, int command);
static int com90xx_status(struct net_device *dev); static int com90xx_status(struct net_device *dev);
static void com90xx_setmask(struct net_device *dev, int mask); static void com90xx_setmask(struct net_device *dev, int mask);
@@ -116,14 +116,26 @@ static void __init com90xx_probe(void)
unsigned long airqmask; unsigned long airqmask;
int ports[(0x3f0 - 0x200) / 16 + 1] = int ports[(0x3f0 - 0x200) / 16 + 1] =
{0}; {0};
u_long shmems[(0xFF800 - 0xA0000) / 2048 + 1] = unsigned long *shmems;
{0}; void __iomem **iomem;
int numports, numshmems, *port; int numports, numshmems, *port;
u_long *p; u_long *p;
int index;
if (!io && !irq && !shmem && !*device && com90xx_skip_probe) if (!io && !irq && !shmem && !*device && com90xx_skip_probe)
return; return;
shmems = kzalloc(((0x10000-0xa0000) / 0x800) * sizeof(unsigned long),
GFP_KERNEL);
if (!shmems)
return;
iomem = kzalloc(((0x10000-0xa0000) / 0x800) * sizeof(void __iomem *),
GFP_KERNEL);
if (!iomem) {
kfree(shmems);
return;
}
BUGLVL(D_NORMAL) printk(VERSION); BUGLVL(D_NORMAL) printk(VERSION);
/* set up the arrays where we'll store the possible probe addresses */ /* set up the arrays where we'll store the possible probe addresses */
@@ -179,6 +191,8 @@ static void __init com90xx_probe(void)
if (!numports) { if (!numports) {
BUGMSG2(D_NORMAL, "S1: No ARCnet cards found.\n"); BUGMSG2(D_NORMAL, "S1: No ARCnet cards found.\n");
kfree(shmems);
kfree(iomem);
return; return;
} }
/* Stage 2: we have now reset any possible ARCnet cards, so we can't /* Stage 2: we have now reset any possible ARCnet cards, so we can't
@@ -202,8 +216,8 @@ static void __init com90xx_probe(void)
* 0xD1 byte in the right place, or are read-only. * 0xD1 byte in the right place, or are read-only.
*/ */
numprint = -1; numprint = -1;
for (p = &shmems[0]; p < shmems + numshmems; p++) { for (index = 0, p = &shmems[0]; index < numshmems; p++, index++) {
u_long ptr = *p; void __iomem *base;
numprint++; numprint++;
numprint %= 8; numprint %= 8;
@@ -213,38 +227,49 @@ static void __init com90xx_probe(void)
} }
BUGMSG2(D_INIT, "%lXh ", *p); BUGMSG2(D_INIT, "%lXh ", *p);
if (!request_mem_region(*p, BUFFER_SIZE, "arcnet (90xx)")) { if (!request_mem_region(*p, MIRROR_SIZE, "arcnet (90xx)")) {
BUGMSG2(D_INIT_REASONS, "(request_mem_region)\n"); BUGMSG2(D_INIT_REASONS, "(request_mem_region)\n");
BUGMSG2(D_INIT_REASONS, "Stage 3: "); BUGMSG2(D_INIT_REASONS, "Stage 3: ");
BUGLVL(D_INIT_REASONS) numprint = 0; BUGLVL(D_INIT_REASONS) numprint = 0;
*p-- = shmems[--numshmems]; goto out;
continue;
} }
if (isa_readb(ptr) != TESTvalue) { base = ioremap(*p, MIRROR_SIZE);
if (!base) {
BUGMSG2(D_INIT_REASONS, "(ioremap)\n");
BUGMSG2(D_INIT_REASONS, "Stage 3: ");
BUGLVL(D_INIT_REASONS) numprint = 0;
goto out1;
}
if (readb(base) != TESTvalue) {
BUGMSG2(D_INIT_REASONS, "(%02Xh != %02Xh)\n", BUGMSG2(D_INIT_REASONS, "(%02Xh != %02Xh)\n",
isa_readb(ptr), TESTvalue); readb(base), TESTvalue);
BUGMSG2(D_INIT_REASONS, "S3: "); BUGMSG2(D_INIT_REASONS, "S3: ");
BUGLVL(D_INIT_REASONS) numprint = 0; BUGLVL(D_INIT_REASONS) numprint = 0;
release_mem_region(*p, BUFFER_SIZE); goto out2;
*p-- = shmems[--numshmems];
continue;
} }
/* By writing 0x42 to the TESTvalue location, we also make /* By writing 0x42 to the TESTvalue location, we also make
* sure no "mirror" shmem areas show up - if they occur * sure no "mirror" shmem areas show up - if they occur
* in another pass through this loop, they will be discarded * in another pass through this loop, they will be discarded
* because *cptr != TESTvalue. * because *cptr != TESTvalue.
*/ */
isa_writeb(0x42, ptr); writeb(0x42, base);
if (isa_readb(ptr) != 0x42) { if (readb(base) != 0x42) {
BUGMSG2(D_INIT_REASONS, "(read only)\n"); BUGMSG2(D_INIT_REASONS, "(read only)\n");
BUGMSG2(D_INIT_REASONS, "S3: "); BUGMSG2(D_INIT_REASONS, "S3: ");
release_mem_region(*p, BUFFER_SIZE); goto out2;
*p-- = shmems[--numshmems];
continue;
} }
BUGMSG2(D_INIT_REASONS, "\n"); BUGMSG2(D_INIT_REASONS, "\n");
BUGMSG2(D_INIT_REASONS, "S3: "); BUGMSG2(D_INIT_REASONS, "S3: ");
BUGLVL(D_INIT_REASONS) numprint = 0; BUGLVL(D_INIT_REASONS) numprint = 0;
iomem[index] = base;
continue;
out2:
iounmap(base);
out1:
release_mem_region(*p, MIRROR_SIZE);
out:
*p-- = shmems[--numshmems];
index--;
} }
BUGMSG2(D_INIT, "\n"); BUGMSG2(D_INIT, "\n");
@@ -252,6 +277,8 @@ static void __init com90xx_probe(void)
BUGMSG2(D_NORMAL, "S3: No ARCnet cards found.\n"); BUGMSG2(D_NORMAL, "S3: No ARCnet cards found.\n");
for (port = &ports[0]; port < ports + numports; port++) for (port = &ports[0]; port < ports + numports; port++)
release_region(*port, ARCNET_TOTAL_SIZE); release_region(*port, ARCNET_TOTAL_SIZE);
kfree(shmems);
kfree(iomem);
return; return;
} }
/* Stage 4: something of a dummy, to report the shmems that are /* Stage 4: something of a dummy, to report the shmems that are
@@ -351,30 +378,32 @@ static void __init com90xx_probe(void)
mdelay(RESETtime); mdelay(RESETtime);
} else { } else {
/* just one shmem and port, assume they match */ /* just one shmem and port, assume they match */
isa_writeb(TESTvalue, shmems[0]); writeb(TESTvalue, iomem[0]);
} }
#else #else
inb(_RESET); inb(_RESET);
mdelay(RESETtime); mdelay(RESETtime);
#endif #endif
for (p = &shmems[0]; p < shmems + numshmems; p++) { for (index = 0; index < numshmems; index++) {
u_long ptr = *p; u_long ptr = shmems[index];
void __iomem *base = iomem[index];
if (isa_readb(ptr) == TESTvalue) { /* found one */ if (readb(base) == TESTvalue) { /* found one */
BUGMSG2(D_INIT, "%lXh)\n", *p); BUGMSG2(D_INIT, "%lXh)\n", *p);
openparen = 0; openparen = 0;
/* register the card */ /* register the card */
if (com90xx_found(*port, airq, *p) == 0) if (com90xx_found(*port, airq, ptr, base) == 0)
found = 1; found = 1;
numprint = -1; numprint = -1;
/* remove shmem from the list */ /* remove shmem from the list */
*p = shmems[--numshmems]; shmems[index] = shmems[--numshmems];
iomem[index] = iomem[numshmems];
break; /* go to the next I/O port */ break; /* go to the next I/O port */
} else { } else {
BUGMSG2(D_INIT_REASONS, "%Xh-", isa_readb(ptr)); BUGMSG2(D_INIT_REASONS, "%Xh-", readb(base));
} }
} }
@@ -391,17 +420,40 @@ static void __init com90xx_probe(void)
BUGLVL(D_INIT_REASONS) printk("\n"); BUGLVL(D_INIT_REASONS) printk("\n");
/* Now put back TESTvalue on all leftover shmems. */ /* Now put back TESTvalue on all leftover shmems. */
for (p = &shmems[0]; p < shmems + numshmems; p++) { for (index = 0; index < numshmems; index++) {
isa_writeb(TESTvalue, *p); writeb(TESTvalue, iomem[index]);
release_mem_region(*p, BUFFER_SIZE); iounmap(iomem[index]);
release_mem_region(shmems[index], MIRROR_SIZE);
} }
kfree(shmems);
kfree(iomem);
} }
static int check_mirror(unsigned long addr, size_t size)
{
void __iomem *p;
int res = -1;
if (!request_mem_region(addr, size, "arcnet (90xx)"))
return -1;
p = ioremap(addr, size);
if (p) {
if (readb(p) == TESTvalue)
res = 1;
else
res = 0;
iounmap(p);
}
release_mem_region(addr, size);
return res;
}
/* Set up the struct net_device associated with this card. Called after /* Set up the struct net_device associated with this card. Called after
* probing succeeds. * probing succeeds.
*/ */
static int __init com90xx_found(int ioaddr, int airq, u_long shmem) static int __init com90xx_found(int ioaddr, int airq, u_long shmem, void __iomem *p)
{ {
struct net_device *dev = NULL; struct net_device *dev = NULL;
struct arcnet_local *lp; struct arcnet_local *lp;
@@ -412,7 +464,8 @@ static int __init com90xx_found(int ioaddr, int airq, u_long shmem)
dev = alloc_arcdev(device); dev = alloc_arcdev(device);
if (!dev) { if (!dev) {
BUGMSG2(D_NORMAL, "com90xx: Can't allocate device!\n"); BUGMSG2(D_NORMAL, "com90xx: Can't allocate device!\n");
release_mem_region(shmem, BUFFER_SIZE); iounmap(p);
release_mem_region(shmem, MIRROR_SIZE);
return -ENOMEM; return -ENOMEM;
} }
lp = dev->priv; lp = dev->priv;
@@ -423,24 +476,27 @@ static int __init com90xx_found(int ioaddr, int airq, u_long shmem)
* 2k (or there are no mirrors at all) but on some, it's 4k. * 2k (or there are no mirrors at all) but on some, it's 4k.
*/ */
mirror_size = MIRROR_SIZE; mirror_size = MIRROR_SIZE;
if (isa_readb(shmem) == TESTvalue if (readb(p) == TESTvalue &&
&& isa_readb(shmem - mirror_size) != TESTvalue check_mirror(shmem - MIRROR_SIZE, MIRROR_SIZE) == 0 &&
&& isa_readb(shmem - 2 * mirror_size) == TESTvalue) check_mirror(shmem - 2 * MIRROR_SIZE, MIRROR_SIZE) == 1)
mirror_size *= 2; mirror_size = 2 * MIRROR_SIZE;
first_mirror = last_mirror = shmem; first_mirror = shmem - mirror_size;
while (isa_readb(first_mirror) == TESTvalue) while (check_mirror(first_mirror, mirror_size) == 1)
first_mirror -= mirror_size; first_mirror -= mirror_size;
first_mirror += mirror_size; first_mirror += mirror_size;
while (isa_readb(last_mirror) == TESTvalue) last_mirror = shmem + mirror_size;
while (check_mirror(last_mirror, mirror_size) == 1)
last_mirror += mirror_size; last_mirror += mirror_size;
last_mirror -= mirror_size; last_mirror -= mirror_size;
dev->mem_start = first_mirror; dev->mem_start = first_mirror;
dev->mem_end = last_mirror + MIRROR_SIZE - 1; dev->mem_end = last_mirror + MIRROR_SIZE - 1;
release_mem_region(shmem, BUFFER_SIZE); iounmap(p);
release_mem_region(shmem, MIRROR_SIZE);
if (!request_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1, "arcnet (90xx)")) if (!request_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1, "arcnet (90xx)"))
goto err_free_dev; goto err_free_dev;