On Sun, Jan 31, 2010 at 09:41:14AM +1000, David Gwynne wrote:
> pmap_enter in this situation should fail, not panic. the error would be
> handled properly as the stack unwinds up to ami_allocmem.
>
> i can change ami_allocmem to take a NOWAIT etc as an argument rather than
> just assume it, so callers with process context (like the sensor refresh
> shown below) can sleep waiting for mappings.
here's such a change.
i havent even compiled this, let alone tested it.
Index: ami.c
===================================================================
RCS file: /cvs/src/sys/dev/ic/ami.c,v
retrieving revision 1.199
diff -u -p -r1.199 ami.c
--- ami.c 9 Jan 2010 23:15:06 -0000 1.199
+++ ami.c 30 Jan 2010 23:49:09 -0000
@@ -124,7 +124,7 @@ void ami_write(struct ami_softc *, bus_
void ami_copyhds(struct ami_softc *, const u_int32_t *,
const u_int8_t *, const u_int8_t *);
-struct ami_mem *ami_allocmem(struct ami_softc *, size_t);
+struct ami_mem *ami_allocmem(struct ami_softc *, size_t, int);
void ami_freemem(struct ami_softc *, struct ami_mem *);
int ami_alloc_ccbs(struct ami_softc *, int);
@@ -256,31 +256,33 @@ ami_write(struct ami_softc *sc, bus_size
}
struct ami_mem *
-ami_allocmem(struct ami_softc *sc, size_t size)
+ami_allocmem(struct ami_softc *sc, size_t size, int nowait)
{
struct ami_mem *am;
int nsegs;
- am = malloc(sizeof(struct ami_mem), M_DEVBUF, M_NOWAIT|M_ZERO);
+ am = malloc(sizeof(struct ami_mem), M_DEVBUF, M_ZERO |
+ nowait ? M_NOWAIT : 0);
if (am == NULL)
return (NULL);
am->am_size = size;
+ nowait = nowait ? BUS_DMA_NOWAIT : 0;
if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
- BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &am->am_map) != 0)
+ nowait | BUS_DMA_ALLOCNOW, &am->am_map) != 0)
goto amfree;
if (bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &am->am_seg, 1,
- &nsegs, BUS_DMA_NOWAIT) != 0)
+ &nsegs, nowait) != 0)
goto destroy;
if (bus_dmamem_map(sc->sc_dmat, &am->am_seg, nsegs, size, &am->am_kva,
- BUS_DMA_NOWAIT) != 0)
+ nowait) != 0)
goto free;
if (bus_dmamap_load(sc->sc_dmat, am->am_map, am->am_kva, size, NULL,
- BUS_DMA_NOWAIT) != 0)
+ nowait) != 0)
goto unmap;
memset(am->am_kva, 0, size);
@@ -337,7 +339,8 @@ ami_alloc_ccbs(struct ami_softc *sc, int
return (1);
}
- sc->sc_ccbmem_am = ami_allocmem(sc, sizeof(struct ami_ccbmem) * nccbs);
+ sc->sc_ccbmem_am = ami_allocmem(sc,
+ sizeof(struct ami_ccbmem) * nccbs, 1);
if (sc->sc_ccbmem_am == NULL) {
printf(": unable to allocate ccb dmamem\n");
goto free_ccbs;
@@ -413,14 +416,14 @@ ami_attach(struct ami_softc *sc)
paddr_t pa;
int s;
- am = ami_allocmem(sc, NBPG);
+ am = ami_allocmem(sc, NBPG, 1);
if (am == NULL) {
printf(": unable to allocate init data\n");
return (1);
}
pa = htole32(AMIMEM_DVA(am));
- sc->sc_mbox_am = ami_allocmem(sc, sizeof(struct ami_iocmd));
+ sc->sc_mbox_am = ami_allocmem(sc, sizeof(struct ami_iocmd), 1);
if (sc->sc_mbox_am == NULL) {
printf(": unable to allocate mbox\n");
goto free_idata;
@@ -1914,7 +1917,7 @@ ami_mgmt(struct ami_softc *sc, u_int8_t
}
if (size) {
- if ((am = ami_allocmem(sc, size)) == NULL) {
+ if ((am = ami_allocmem(sc, size, 0)) == NULL) {
error = ENOMEM;
goto memerr;
}