diff options
Diffstat (limited to 'sys/arch/i386')
-rw-r--r-- | sys/arch/i386/i386/bus_dma.c | 29 |
1 files changed, 24 insertions, 5 deletions
diff --git a/sys/arch/i386/i386/bus_dma.c b/sys/arch/i386/i386/bus_dma.c index 973bf82a706..27cf4d36317 100644 --- a/sys/arch/i386/i386/bus_dma.c +++ b/sys/arch/i386/i386/bus_dma.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bus_dma.c,v 1.20 2010/03/25 22:44:57 oga Exp $ */ +/* $OpenBSD: bus_dma.c,v 1.21 2010/03/27 00:37:15 oga Exp $ */ /*- * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc. * All rights reserved. @@ -416,9 +416,10 @@ int _bus_dmamem_map(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs, size_t size, caddr_t *kvap, int flags) { - vaddr_t va; + vaddr_t va, sva; + size_t ssize; bus_addr_t addr; - int curseg, pmapflags = 0; + int curseg, pmapflags = 0, ret; if (flags & BUS_DMA_NOCACHE) pmapflags |= PMAP_NOCACHE; @@ -430,15 +431,33 @@ _bus_dmamem_map(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs, *kvap = (caddr_t)va; + sva = va; + ssize = size; for (curseg = 0; curseg < nsegs; curseg++) { for (addr = segs[curseg].ds_addr; addr < (segs[curseg].ds_addr + segs[curseg].ds_len); addr += PAGE_SIZE, va += PAGE_SIZE, size -= PAGE_SIZE) { if (size == 0) panic("_bus_dmamem_map: size botch"); - pmap_enter(pmap_kernel(), va, addr | pmapflags, + /* + * we don't want pmap to panic here if it can't + * alloc + */ + ret = pmap_enter(pmap_kernel(), va, addr | pmapflags, VM_PROT_READ | VM_PROT_WRITE, VM_PROT_READ | - VM_PROT_WRITE | PMAP_WIRED); + VM_PROT_WRITE | PMAP_WIRED | PMAP_CANFAIL); + if (ret) { + /* + * Clean up after ourselves. + * XXX uvm_wait on WAITOK + */ + pmap_remove(pmap_kernel(), sva, va - PAGE_SIZE); + pmap_update(pmap_kernel()); + + uvm_km_free(kernel_map, va, ssize); + return (ret); + } + } } pmap_update(pmap_kernel()); |