summaryrefslogtreecommitdiff
path: root/sys/arch/i386
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/i386')
-rw-r--r--sys/arch/i386/i386/bus_dma.c29
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());