Subject: kern/6669: pcic_chip_mem_alloc() can't handle large requests
To: None <gnats-bugs@gnats.netbsd.org>
From: None <eramer@era-t.ericsson.se>
List: netbsd-bugs
Date: 12/28/1998 17:34:09
>Number: 6669
>Category: kern
>Synopsis: pcic_chip_mem_alloc() can't handle large requests
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: kern-bug-people (Kernel Bug People)
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Mon Dec 28 08:35:01 1998
>Last-Modified:
>Originator: Michael Eriksson
>Organization:
Michael Eriksson <eramer@era-t.ericsson.se>
>Release: 981130
>Environment:
System: NetBSD burken 1.3I NetBSD 1.3I (HEMPC) #0: Fri Dec 4 22:36:15 CET 1998 eramer@burken:/usr/src/sys-981130/arch/i386/compile/HEMPC i386
>Description:
The pcic_chip_mem_alloc() function has some problems:
1. It hangs (for as long as it takes to count to ~2^31) if the
requested size is larger than (PCIC_MEM_PAGES + 1) pages, since the
loop condition is bogus.
2. Even if the loop condition was correct, it's still can't handle
larger I/O ranges than PCIC_MEM_PAGES (PCIC_MEM_PAGES is only the
default, and it's possible to request larger iosize in the kernel
config file).
3. The "region found" check of the loop variable is bogus (the loop
variable is compared to a bogus expresion).
>How-To-Repeat:
Try to use a PCMCIA card which needs 32 k of memory space.
>Fix:
--- dev/ic/i82365.c.orig Sat Nov 28 13:13:17 1998
+++ dev/ic/i82365.c Fri Dec 25 13:59:25 1998
@@ -700,13 +700,15 @@
/* convert size to PCIC pages */
sizepg = (size + (PCIC_MEM_ALIGN - 1)) / PCIC_MEM_ALIGN;
+ if (sizepg > PCIC_MAX_MEM_PAGES)
+ return (1);
mask = (1 << sizepg) - 1;
addr = 0; /* XXX gcc -Wuninitialized */
mhandle = 0; /* XXX gcc -Wuninitialized */
- for (i = 0; i < (PCIC_MEM_PAGES + 1 - sizepg); i++) {
+ for (i = 0; i <= PCIC_MAX_MEM_PAGES - sizepg; i++) {
if ((h->sc->subregionmask & (mask << i)) == (mask << i)) {
if (bus_space_subregion(h->sc->memt, h->sc->memh,
i * PCIC_MEM_PAGESIZE,
@@ -715,24 +717,17 @@
mhandle = mask << i;
addr = h->sc->membase + (i * PCIC_MEM_PAGESIZE);
h->sc->subregionmask &= ~(mhandle);
- break;
+ pcmhp->memt = h->sc->memt;
+ pcmhp->memh = memh;
+ pcmhp->addr = addr;
+ pcmhp->size = size;
+ pcmhp->mhandle = mhandle;
+ pcmhp->realsize = sizepg * PCIC_MEM_PAGESIZE;
+ return (0);
}
}
- if (i == (PCIC_MEM_PAGES + 1 - size))
- return (1);
-
- DPRINTF(("pcic_chip_mem_alloc bus addr 0x%lx+0x%lx\n", (u_long) addr,
- (u_long) size));
-
- pcmhp->memt = h->sc->memt;
- pcmhp->memh = memh;
- pcmhp->addr = addr;
- pcmhp->size = size;
- pcmhp->mhandle = mhandle;
- pcmhp->realsize = sizepg * PCIC_MEM_PAGESIZE;
-
- return (0);
+ return (1);
}
void
--- dev/ic/i82365var.h.orig Tue Nov 17 13:14:33 1998
+++ dev/ic/i82365var.h Wed Dec 23 13:46:52 1998
@@ -106,6 +106,7 @@
/* this needs to be large enough to hold PCIC_MEM_PAGES bits */
int subregionmask;
+#define PCIC_MAX_MEM_PAGES (8 * sizeof(int))
/* used by memory window mapping functions */
bus_addr_t membase;
>Audit-Trail:
>Unformatted: