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

Modified Files:
        src/sys/external/bsd/drm2/drm [riastradh-drm2]: drm_module.c
        src/sys/external/bsd/drm2/include/linux [riastradh-drm2]: gfp.h
            highmem.h
        src/sys/modules/drm2 [riastradh-drm2]: Makefile
Added Files:
        src/sys/external/bsd/drm2/linux [riastradh-drm2]: linux_gfp.c
            linux_kmap.c

Log Message:
Implement Linux alloc_page/__free_page and kmap_atomic/kunmap_atomic.


To generate a diff of this commit:
cvs rdiff -u -r1.1.2.3 -r1.1.2.4 src/sys/external/bsd/drm2/drm/drm_module.c
cvs rdiff -u -r1.1.2.1 -r1.1.2.2 \
    src/sys/external/bsd/drm2/include/linux/gfp.h \
    src/sys/external/bsd/drm2/include/linux/highmem.h
cvs rdiff -u -r0 -r1.1.2.1 src/sys/external/bsd/drm2/linux/linux_gfp.c \
    src/sys/external/bsd/drm2/linux/linux_kmap.c
cvs rdiff -u -r1.1.2.35 -r1.1.2.36 src/sys/modules/drm2/Makefile

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/drm/drm_module.c
diff -u src/sys/external/bsd/drm2/drm/drm_module.c:1.1.2.3 src/sys/external/bsd/drm2/drm/drm_module.c:1.1.2.4
--- src/sys/external/bsd/drm2/drm/drm_module.c:1.1.2.3	Wed Jul 24 03:14:31 2013
+++ src/sys/external/bsd/drm2/drm/drm_module.c	Wed Jul 24 03:31:12 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: drm_module.c,v 1.1.2.3 2013/07/24 03:14:31 riastradh Exp $	*/
+/*	$NetBSD: drm_module.c,v 1.1.2.4 2013/07/24 03:31:12 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2013 The NetBSD Foundation, Inc.
@@ -30,13 +30,15 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: drm_module.c,v 1.1.2.3 2013/07/24 03:14:31 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: drm_module.c,v 1.1.2.4 2013/07/24 03:31:12 riastradh Exp $");
 
 #include <sys/types.h>
 #include <sys/device.h>
 #include <sys/module.h>
 #include <sys/systm.h>
 
+#include <linux/highmem.h>
+
 /*
  * XXX I2C stuff should be moved to a separate drm2edid module.
  *
@@ -63,12 +65,19 @@ drm_modcmd(modcmd_t cmd, void *arg __unu
 
 	switch (cmd) {
 	case MODULE_CMD_INIT:
+		error = linux_kmap_init();
+		if (error) {
+			aprint_error("drm: unable to initialize linux kmap:"
+			    " %d", error);
+			return error;
+		}
 #ifdef _MODULE
 		error = config_init_component(cfdriver_ioconf_drm,
 		    cfattach_ioconf_drm, cfdata_ioconf_drm);
 		if (error) {
 			aprint_error("drm: unable to init component: %d\n",
 			    error);
+			linux_kmap_fini();
 			return error;
 		}
 		error = devsw_attach("drm", NULL, &bmajor,
@@ -78,6 +87,7 @@ drm_modcmd(modcmd_t cmd, void *arg __unu
 			    error);
 			(void)config_fini_component(cfdriver_ioconf_drm,
 			    cfattach_ioconf_drm, cfdata_ioconf_drm);
+			linux_kmap_fini();
 			return error;
 		}
 #endif
@@ -94,6 +104,7 @@ drm_modcmd(modcmd_t cmd, void *arg __unu
 			/* XXX Now what?  Reattach the devsw?  */
 			return error;
 #endif
+		linux_kmap_fini();
 		return 0;
 
 	default:

Index: src/sys/external/bsd/drm2/include/linux/gfp.h
diff -u src/sys/external/bsd/drm2/include/linux/gfp.h:1.1.2.1 src/sys/external/bsd/drm2/include/linux/gfp.h:1.1.2.2
--- src/sys/external/bsd/drm2/include/linux/gfp.h:1.1.2.1	Wed Jul 24 03:30:42 2013
+++ src/sys/external/bsd/drm2/include/linux/gfp.h	Wed Jul 24 03:31:12 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: gfp.h,v 1.1.2.1 2013/07/24 03:30:42 riastradh Exp $	*/
+/*	$NetBSD: gfp.h,v 1.1.2.2 2013/07/24 03:31:12 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2013 The NetBSD Foundation, Inc.
@@ -61,8 +61,8 @@ typedef int gfp_t;
 #define	__GFP_ZERO		__BIT(12)
 
 /* XXX Make the nm output a little more greppable...  */
-#define	alloc_page	linux_gfp_alloc_page
-#define	__free_page	linux_gfp___free_page
+#define	alloc_page	linux_alloc_page
+#define	__free_page	linux___free_page
 
 struct page;
 struct page *	alloc_page(gfp_t);
Index: src/sys/external/bsd/drm2/include/linux/highmem.h
diff -u src/sys/external/bsd/drm2/include/linux/highmem.h:1.1.2.1 src/sys/external/bsd/drm2/include/linux/highmem.h:1.1.2.2
--- src/sys/external/bsd/drm2/include/linux/highmem.h:1.1.2.1	Wed Jul 24 00:33:12 2013
+++ src/sys/external/bsd/drm2/include/linux/highmem.h	Wed Jul 24 03:31:12 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: highmem.h,v 1.1.2.1 2013/07/24 00:33:12 riastradh Exp $	*/
+/*	$NetBSD: highmem.h,v 1.1.2.2 2013/07/24 03:31:12 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2013 The NetBSD Foundation, Inc.
@@ -32,4 +32,22 @@
 #ifndef _LINUX_HIGHMEM_H_
 #define _LINUX_HIGHMEM_H_
 
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <linux/kernel.h>
+#include <linux/mm_types.h>
+
+/* XXX Make the nm output a little more greppable...  */
+#define	kmap_atomic	linux_kmap_atomic
+#define	kunmap_atomic	linux_kunmap_atomic
+
+int	linux_kmap_init(void);
+void	linux_kmap_fini(void);
+
+void *	kmap_atomic(struct page *);
+void	kunmap_atomic(void *);
+
 #endif  /* _LINUX_HIGHMEM_H_ */

Index: src/sys/modules/drm2/Makefile
diff -u src/sys/modules/drm2/Makefile:1.1.2.35 src/sys/modules/drm2/Makefile:1.1.2.36
--- src/sys/modules/drm2/Makefile:1.1.2.35	Wed Jul 24 03:11:44 2013
+++ src/sys/modules/drm2/Makefile	Wed Jul 24 03:31:12 2013
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.1.2.35 2013/07/24 03:11:44 riastradh Exp $
+# $NetBSD: Makefile,v 1.1.2.36 2013/07/24 03:31:12 riastradh Exp $
 
 .include "../Makefile.inc"
 .include "Makefile.inc"
@@ -51,6 +51,8 @@ SRCS+=	drm_module.c
 
 # XXX The following should be in a separate Linux compatibility module,
 # or modules.
+SRCS+=	linux_gfp.c
+SRCS+=	linux_kmap.c
 SRCS+=	linux_i2c.c
 SRCS+=	linux_idr.c
 SRCS+=	linux_list_sort.c

Added files:

Index: src/sys/external/bsd/drm2/linux/linux_gfp.c
diff -u /dev/null src/sys/external/bsd/drm2/linux/linux_gfp.c:1.1.2.1
--- /dev/null	Wed Jul 24 03:31:12 2013
+++ src/sys/external/bsd/drm2/linux/linux_gfp.c	Wed Jul 24 03:31:12 2013
@@ -0,0 +1,76 @@
+/*	$NetBSD: linux_gfp.c,v 1.1.2.1 2013/07/24 03:31:12 riastradh Exp $	*/
+
+/*-
+ * Copyright (c) 2013 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Taylor R. Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: linux_gfp.c,v 1.1.2.1 2013/07/24 03:31:12 riastradh Exp $");
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <linux/gfp.h>
+#include <linux/kernel.h>
+#include <linux/mm_types.h>
+
+struct page *
+alloc_page(gfp_t gfp)
+{
+	paddr_t low = 0;
+	paddr_t high = ~(paddr_t)0;
+	struct pglist pglist;
+	struct vm_page *vm_page;
+	int error;
+
+	if (ISSET(gfp, __GFP_DMA32))
+		high = 0xffffffff;
+
+	error = uvm_pglistalloc(PAGE_SIZE, low, high, PAGE_SIZE, PAGE_SIZE,
+	    &pglist, 1, ISSET(gfp, __GFP_WAIT));
+	if (error)
+		return NULL;
+
+	vm_page = TAILQ_FIRST(&pglist);
+	TAILQ_REMOVE(&pglist, vm_page, pageq.queue);	/* paranoia */
+	KASSERT(TAILQ_EMPTY(&pglist));
+
+	return container_of(vm_page, struct page, p_vmp);
+}
+
+void
+__free_page(struct page *page)
+{
+	struct pglist pglist = TAILQ_HEAD_INITIALIZER(pglist);
+
+	TAILQ_INSERT_TAIL(&pglist, &page->p_vmp, pageq.queue);
+
+	uvm_pglistfree(&pglist);
+}
Index: src/sys/external/bsd/drm2/linux/linux_kmap.c
diff -u /dev/null src/sys/external/bsd/drm2/linux/linux_kmap.c:1.1.2.1
--- /dev/null	Wed Jul 24 03:31:12 2013
+++ src/sys/external/bsd/drm2/linux/linux_kmap.c	Wed Jul 24 03:31:12 2013
@@ -0,0 +1,112 @@
+/*	$NetBSD: linux_kmap.c,v 1.1.2.1 2013/07/24 03:31:12 riastradh Exp $	*/
+
+/*-
+ * Copyright (c) 2013 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Taylor R. Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: linux_kmap.c,v 1.1.2.1 2013/07/24 03:31:12 riastradh Exp $");
+
+#include <sys/types.h>
+#include <sys/mutex.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <linux/highmem.h>
+
+/*
+ * XXX Kludgerific implementation of Linux kmap_atomic, which is
+ * required not to fail.  To accomodate this, we reserve one page of
+ * kva at boot (or load) and limit the system to at most kmap_atomic in
+ * use at a time.
+ */
+
+static kmutex_t linux_kmap_atomic_lock;
+static vaddr_t linux_kmap_atomic_vaddr;
+
+int
+linux_kmap_init(void)
+{
+
+	/* IPL_VM is needed to block pmap_kenter_pa.  */
+	mutex_init(&linux_kmap_atomic_lock, MUTEX_DEFAULT, IPL_VM);
+
+	linux_kmap_atomic_vaddr = uvm_km_alloc(kernel_map, PAGE_SIZE, 0,
+	    (UVM_KMF_VAONLY | UVM_KMF_WAITVA));
+
+	KASSERT(linux_kmap_atomic_vaddr != 0);
+	KASSERT(!pmap_extract(pmap_kernel(), linux_kmap_atomic_vaddr, NULL));
+
+	return 0;
+}
+
+void
+linux_kmap_fini(void)
+{
+
+	KASSERT(linux_kmap_atomic_vaddr != 0);
+	KASSERT(!pmap_extract(pmap_kernel(), linux_kmap_atomic_vaddr, NULL));
+
+	uvm_km_free(kernel_map, linux_kmap_atomic_vaddr, PAGE_SIZE,
+	    (UVM_KMF_VAONLY | UVM_KMF_WAITVA));
+
+	mutex_destroy(&linux_kmap_atomic_lock);
+}
+
+void *
+kmap_atomic(struct page *page)
+{
+
+	mutex_spin_enter(&linux_kmap_atomic_lock);
+
+	KASSERT(linux_kmap_atomic_vaddr != 0);
+	KASSERT(!pmap_extract(pmap_kernel(), linux_kmap_atomic_vaddr, NULL));
+
+	const vaddr_t vaddr = linux_kmap_atomic_vaddr;
+	const paddr_t paddr = uvm_vm_page_to_phys(&page->p_vmp);
+	const int prot = (VM_PROT_READ | VM_PROT_WRITE);
+	const int flags = 0;
+	pmap_kenter_pa(vaddr, paddr, prot, flags);
+	pmap_update(pmap_kernel());
+
+	return (void *)vaddr;
+}
+
+void
+kunmap_atomic(void *addr)
+{
+	const vaddr_t vaddr = (vaddr_t)addr;
+
+	KASSERT(linux_kmap_atomic_vaddr == vaddr);
+	KASSERT(pmap_extract(pmap_kernel(), vaddr, NULL));
+
+	pmap_kremove(vaddr, PAGE_SIZE);
+	pmap_update(pmap_kernel());
+
+	mutex_spin_exit(&linux_kmap_atomic_lock);
+}

Reply via email to