Module Name:    src
Committed By:   riastradh
Date:           Wed Jul 24 03:12:33 UTC 2013

Modified Files:
        src/sys/external/bsd/drm2/dist/include/drm [riastradh-drm2]: drmP.h
        src/sys/external/bsd/drm2/drm [riastradh-drm2]: drm_memory.c

Log Message:
Add drm_limit_dma_space to limit the memory available for DMA.

Designed as a compatibility stub to replace dma_set_coherent_mask in
Linux.  Not exactly the same, but probably close enough for all uses
of dma_set_coherent_mask in Linux.


To generate a diff of this commit:
cvs rdiff -u -r1.1.1.1.2.43 -r1.1.1.1.2.44 \
    src/sys/external/bsd/drm2/dist/include/drm/drmP.h
cvs rdiff -u -r1.1.2.5 -r1.1.2.6 src/sys/external/bsd/drm2/drm/drm_memory.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/external/bsd/drm2/dist/include/drm/drmP.h
diff -u src/sys/external/bsd/drm2/dist/include/drm/drmP.h:1.1.1.1.2.43 src/sys/external/bsd/drm2/dist/include/drm/drmP.h:1.1.1.1.2.44
--- src/sys/external/bsd/drm2/dist/include/drm/drmP.h:1.1.1.1.2.43	Wed Jul 24 03:04:34 2013
+++ src/sys/external/bsd/drm2/dist/include/drm/drmP.h	Wed Jul 24 03:12:33 2013
@@ -1359,7 +1359,11 @@ struct drm_device {
 	/* XXX What does this have to do with AGP?  */
 	struct drm_bus_map *agp_maps;
 	size_t agp_nmaps;
+	bus_dma_tag_t bus_dmat;
 	bus_dma_tag_t dmat;
+	bool dmat_subregion_p;
+	bus_addr_t dmat_subregion_min;
+	bus_addr_t dmat_subregion_max;
 #endif
 
 	struct drm_sg_mem *sg;	/**< Scatter gather memory */
@@ -1526,6 +1530,8 @@ extern int drm_unbind_agp(DRM_AGP_MEM * 
 #ifdef __NetBSD__
 extern void *drm_ioremap(struct drm_device *dev, struct drm_local_map *map);
 extern void drm_iounmap(struct drm_device *dev, struct drm_local_map *map);
+extern int drm_limit_dma_space(struct drm_device *, resource_size_t,
+    resource_size_t);
 #endif
 
 				/* Misc. IOCTL support (drm_ioctl.h) */

Index: src/sys/external/bsd/drm2/drm/drm_memory.c
diff -u src/sys/external/bsd/drm2/drm/drm_memory.c:1.1.2.5 src/sys/external/bsd/drm2/drm/drm_memory.c:1.1.2.6
--- src/sys/external/bsd/drm2/drm/drm_memory.c:1.1.2.5	Wed Jul 24 03:02:21 2013
+++ src/sys/external/bsd/drm2/drm/drm_memory.c	Wed Jul 24 03:12:33 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: drm_memory.c,v 1.1.2.5 2013/07/24 03:02:21 riastradh Exp $	*/
+/*	$NetBSD: drm_memory.c,v 1.1.2.6 2013/07/24 03:12:33 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2013 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: drm_memory.c,v 1.1.2.5 2013/07/24 03:02:21 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: drm_memory.c,v 1.1.2.6 2013/07/24 03:12:33 riastradh Exp $");
 
 /* XXX Cargo-culted from the old drm_memory.c.  */
 
@@ -331,3 +331,56 @@ drm_pci_free(struct drm_device *dev, str
 	dmah->dmah_tag = NULL;	/* XXX paranoia */
 	kmem_free(dmah, sizeof(*dmah));
 }
+
+/*
+ * Make sure the DMA-safe memory allocated for dev lies between
+ * min_addr and max_addr.  Can be used multiple times to restrict the
+ * bounds further, but never to expand the bounds again.
+ *
+ * XXX Caller must guarantee nobody has used the tag yet,
+ * i.e. allocated any DMA memory.
+ */
+int
+drm_limit_dma_space(struct drm_device *dev, resource_size_t min_addr,
+    resource_size_t max_addr)
+{
+	int error;
+
+	KASSERT(min_addr <= max_addr);
+
+	/*
+	 * Limit it further if we have already limited it, and destroy
+	 * the old subregion DMA tag.
+	 */
+	if (dev->dmat_subregion_p) {
+		min_addr = MAX(min_addr, dev->dmat_subregion_min);
+		max_addr = MIN(max_addr, dev->dmat_subregion_max);
+		bus_dmatag_destroy(dev->dmat);
+	}
+
+	/*
+	 * Create a DMA tag for a subregion from the bus's DMA tag.  If
+	 * that fails, restore dev->dmat to the whole region so that we
+	 * need not worry about dev->dmat being uninitialized (not that
+	 * the caller should try to allocate DMA-safe memory on failure
+	 * anyway, but...paranoia).
+	 */
+	error = bus_dmatag_subregion(dev->bus_dmat, min_addr, max_addr,
+	    &dev->dmat, BUS_DMA_WAITOK);
+	if (error) {
+		dev->dmat = dev->bus_dmat;
+		return error;
+	}
+
+	/*
+	 * Remember that we have a subregion tag so that we know to
+	 * destroy it later, and record the bounds in case we need to
+	 * limit them again.
+	 */
+	dev->dmat_subregion_p = true;
+	dev->dmat_subregion_min = min_addr;
+	dev->dmat_subregion_max = max_addr;
+
+	/* Success!  */
+	return 0;
+}

Reply via email to