Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/riastradh-drm2]: src/sys Implement Linux alloc_page/__free_page and kmap...



details:   https://anonhg.NetBSD.org/src/rev/d7d33e4f1b6b
branches:  riastradh-drm2
changeset: 788379:d7d33e4f1b6b
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Wed Jul 24 03:31:12 2013 +0000

description:
Implement Linux alloc_page/__free_page and kmap_atomic/kunmap_atomic.

diffstat:

 sys/external/bsd/drm2/drm/drm_module.c        |   15 +++-
 sys/external/bsd/drm2/include/linux/gfp.h     |    6 +-
 sys/external/bsd/drm2/include/linux/highmem.h |   20 ++++-
 sys/external/bsd/drm2/linux/linux_gfp.c       |   76 +++++++++++++++++
 sys/external/bsd/drm2/linux/linux_kmap.c      |  112 ++++++++++++++++++++++++++
 sys/modules/drm2/Makefile                     |    4 +-
 6 files changed, 226 insertions(+), 7 deletions(-)

diffs (truncated from 328 to 300 lines):

diff -r 35e16cbad60d -r d7d33e4f1b6b sys/external/bsd/drm2/drm/drm_module.c
--- a/sys/external/bsd/drm2/drm/drm_module.c    Wed Jul 24 03:30:42 2013 +0000
+++ b/sys/external/bsd/drm2/drm/drm_module.c    Wed Jul 24 03:31:12 2013 +0000
@@ -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 @@
 
        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 @@
                            error);
                        (void)config_fini_component(cfdriver_ioconf_drm,
                            cfattach_ioconf_drm, cfdata_ioconf_drm);
+                       linux_kmap_fini();
                        return error;
                }
 #endif
@@ -94,6 +104,7 @@
                        /* XXX Now what?  Reattach the devsw?  */
                        return error;
 #endif
+               linux_kmap_fini();
                return 0;
 
        default:
diff -r 35e16cbad60d -r d7d33e4f1b6b sys/external/bsd/drm2/include/linux/gfp.h
--- a/sys/external/bsd/drm2/include/linux/gfp.h Wed Jul 24 03:30:42 2013 +0000
+++ b/sys/external/bsd/drm2/include/linux/gfp.h Wed Jul 24 03:31:12 2013 +0000
@@ -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 @@
 #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);
diff -r 35e16cbad60d -r d7d33e4f1b6b sys/external/bsd/drm2/include/linux/highmem.h
--- a/sys/external/bsd/drm2/include/linux/highmem.h     Wed Jul 24 03:30:42 2013 +0000
+++ b/sys/external/bsd/drm2/include/linux/highmem.h     Wed Jul 24 03:31:12 2013 +0000
@@ -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_ */
diff -r 35e16cbad60d -r d7d33e4f1b6b sys/external/bsd/drm2/linux/linux_gfp.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/external/bsd/drm2/linux/linux_gfp.c   Wed Jul 24 03:31:12 2013 +0000
@@ -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);
+}
diff -r 35e16cbad60d -r d7d33e4f1b6b sys/external/bsd/drm2/linux/linux_kmap.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/external/bsd/drm2/linux/linux_kmap.c  Wed Jul 24 03:31:12 2013 +0000
@@ -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)
+{



Home | Main Index | Thread Index | Old Index