summaryrefslogtreecommitdiff
path: root/sys/arch/i386
diff options
context:
space:
mode:
authorOwain Ainsworth <oga@cvs.openbsd.org>2010-04-08 01:26:45 +0000
committerOwain Ainsworth <oga@cvs.openbsd.org>2010-04-08 01:26:45 +0000
commit41e65217cf647a392a1ee8701db8e35a5a2e4a85 (patch)
treeecaf1795a505d41830ae6836d784ff65b8b7a65b /sys/arch/i386
parent8d29d4182b507adfa3eef84e51b3fe8848024326 (diff)
Fill in the bus_dma_sync for intagp to use clflush instead of wbinvd()
if supported. When we do memory management on intel this would lead to a LOT of wbinvd() to deal with gpu->cpu incoherency. no one wants that. Needed for sanity of inteldrm memory management which is coming up next.
Diffstat (limited to 'sys/arch/i386')
-rw-r--r--sys/arch/i386/pci/agp_machdep.c81
1 files changed, 77 insertions, 4 deletions
diff --git a/sys/arch/i386/pci/agp_machdep.c b/sys/arch/i386/pci/agp_machdep.c
index 87bedfc6cd7..e63e00cc243 100644
--- a/sys/arch/i386/pci/agp_machdep.c
+++ b/sys/arch/i386/pci/agp_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: agp_machdep.c,v 1.10 2009/06/06 06:02:44 oga Exp $ */
+/* $OpenBSD: agp_machdep.c,v 1.11 2010/04/08 01:26:44 oga Exp $ */
/*
* Copyright (c) 2008 - 2009 Owain G. Ainsworth <oga@openbsd.org>
@@ -54,6 +54,8 @@
#include <machine/cpufunc.h>
#include <machine/bus.h>
+#include <uvm/uvm.h>
+
#include "intagp.h"
/* bus_dma functions */
@@ -69,6 +71,12 @@ agp_flush_cache(void)
wbinvd();
}
+void
+agp_flush_cache_range(vaddr_t va, vsize_t sz)
+{
+ pmap_flush_cache(va, sz);
+}
+
/*
* functions for bus_dma used by drm for GEM
*
@@ -140,12 +148,21 @@ void
agp_bus_dma_destroy(struct agp_softc *sc, bus_dma_tag_t dmat)
{
struct sg_cookie *cookie = dmat->_cookie;
+ bus_addr_t offset;
/*
* XXX clear up blocker queue
*/
+ /*
+ * some backends use a dummy page to avoid errors on prefetching, etc.
+ * make sure that all of them are clean.
+ */
+ for (offset = cookie->sg_ex->ex_start;
+ offset < cookie->sg_ex->ex_end; offset += PAGE_SIZE)
+ sc->sc_methods->unbind_page(sc->sc_chipc, offset);
+
sg_dmatag_destroy(cookie);
free(dmat, M_DEVBUF);
}
@@ -157,7 +174,6 @@ agp_bus_dma_set_alignment(bus_dma_tag_t tag, bus_dmamap_t dmam,
sg_dmamap_set_alignment(tag, dmam, alignment);
}
-
/*
* ick ick ick. However, the rest of this driver is supposedly MI (though
* they only exist on x86), so this can't be in dev/pci.
@@ -183,6 +199,12 @@ void
intagp_dma_sync(bus_dma_tag_t tag, bus_dmamap_t dmam,
bus_addr_t offset, bus_size_t size, int ops)
{
+ bus_dma_segment_t *segp;
+ struct sg_page_map *spm;
+ void *addr;
+ paddr_t pa;
+ bus_addr_t poff, endoff, soff;
+
#ifdef DIAGNOSTIC
if ((ops & (BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE)) != 0 &&
(ops & (BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE)) != 0)
@@ -213,9 +235,60 @@ intagp_dma_sync(bus_dma_tag_t tag, bus_dmamap_t dmam,
* The chipset also may need flushing, but that fits badly into
* bus_dma and it done in the driver.
*/
+ soff = trunc_page(offset);
+ endoff = round_page(offset + size);
if (ops & BUS_DMASYNC_POSTREAD || ops & BUS_DMASYNC_PREREAD ||
ops & BUS_DMASYNC_PREWRITE) {
- wbinvd();
+ if (curcpu()->ci_cflushsz == 0) {
+ /* save some wbinvd()s. we're MD anyway so it's ok */
+ wbinvd();
+ return;
+ }
+
+ mfence();
+ spm = dmam->_dm_cookie;
+ switch (spm->spm_buftype) {
+ case BUS_BUFTYPE_LINEAR:
+ addr = spm->spm_origbuf + soff;
+ while (soff < endoff) {
+ pmap_flush_cache((vaddr_t)addr, PAGE_SIZE);
+ soff += PAGE_SIZE;
+ addr += PAGE_SIZE;
+ } break;
+ case BUS_BUFTYPE_RAW:
+ segp = (bus_dma_segment_t *)spm->spm_origbuf;
+ poff = 0;
+
+ while (poff < soff) {
+ if (poff + segp->ds_len > soff)
+ break;
+ poff += segp->ds_len;
+ segp++;
+ }
+ /* first time round may not start at seg beginning */
+ pa = segp->ds_addr + (soff - poff);
+ while (poff < endoff) {
+ for (; pa < segp->ds_addr + segp->ds_len &&
+ poff < endoff; pa += PAGE_SIZE) {
+ pmap_flush_page(pa);
+ poff += PAGE_SIZE;
+ }
+ segp++;
+ if (poff < endoff)
+ pa = segp->ds_addr;
+ }
+ break;
+ /* You do not want to load mbufs or uios onto a graphics card */
+ case BUS_BUFTYPE_MBUF:
+ /* FALLTHROUGH */
+ case BUS_BUFTYPE_UIO:
+ /* FALLTHROUGH */
+ default:
+ panic("intagp_dmamap_sync: bad buftype %d",
+ spm->spm_buftype);
+
+ }
+ mfence();
}
}
-#endif
+#endif /* NINTAGP > 0 */