Source-Changes-HG archive

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

[src/trunk]: src/sys/arch/arm/nvidia Use GEM for memory management. Fixes a c...



details:   https://anonhg.NetBSD.org/src/rev/2ac5c2df94fb
branches:  trunk
changeset: 811708:2ac5c2df94fb
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Thu Nov 12 00:43:52 2015 +0000

description:
Use GEM for memory management. Fixes a couple issues while here:
 - No longer needs to allocate 35MB (!) for framebuffer console.
 - Allows xrandr to switch to modes larger than the framebuffer console.
 - Removes hack that redirected mmap calls to wsdisplay0

diffstat:

 sys/arch/arm/nvidia/files.tegra      |    3 +-
 sys/arch/arm/nvidia/tegra_drm.c      |  122 +++++++++++---------------
 sys/arch/arm/nvidia/tegra_drm.h      |   30 +++++-
 sys/arch/arm/nvidia/tegra_drm_fb.c   |   67 +++++++++++---
 sys/arch/arm/nvidia/tegra_drm_gem.c  |  158 +++++++++++++++++++++++++++++++++++
 sys/arch/arm/nvidia/tegra_drm_mode.c |   42 +++++++-
 sys/arch/arm/nvidia/tegra_fb.c       |   15 +-
 7 files changed, 331 insertions(+), 106 deletions(-)

diffs (truncated from 753 to 300 lines):

diff -r eee5fe107945 -r 2ac5c2df94fb sys/arch/arm/nvidia/files.tegra
--- a/sys/arch/arm/nvidia/files.tegra   Wed Nov 11 21:52:45 2015 +0000
+++ b/sys/arch/arm/nvidia/files.tegra   Thu Nov 12 00:43:52 2015 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: files.tegra,v 1.20 2015/11/09 23:05:58 jmcneill Exp $
+#      $NetBSD: files.tegra,v 1.21 2015/11/12 00:43:52 jmcneill Exp $
 #
 # Configuration info for NVIDIA Tegra ARM Peripherals
 #
@@ -114,6 +114,7 @@
 file   arch/arm/nvidia/tegra_drm.c             tegra_drm
 file   arch/arm/nvidia/tegra_drm_mode.c        tegra_drm
 file   arch/arm/nvidia/tegra_drm_fb.c          tegra_drm
+file   arch/arm/nvidia/tegra_drm_gem.c         tegra_drm
 
 # Framebuffer console
 device tegrafb: tegrafbbus, drmfb, wsemuldisplaydev
diff -r eee5fe107945 -r 2ac5c2df94fb sys/arch/arm/nvidia/tegra_drm.c
--- a/sys/arch/arm/nvidia/tegra_drm.c   Wed Nov 11 21:52:45 2015 +0000
+++ b/sys/arch/arm/nvidia/tegra_drm.c   Thu Nov 12 00:43:52 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: tegra_drm.c,v 1.2 2015/11/10 22:14:05 jmcneill Exp $ */
+/* $NetBSD: tegra_drm.c,v 1.3 2015/11/12 00:43:52 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2015 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -29,7 +29,7 @@
 #include "locators.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tegra_drm.c,v 1.2 2015/11/10 22:14:05 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tegra_drm.c,v 1.3 2015/11/12 00:43:52 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -57,27 +57,30 @@
 static int     tegra_drm_load(struct drm_device *, unsigned long);
 static int     tegra_drm_unload(struct drm_device *);
 
-static int     tegra_drm_mmap_object(struct drm_device *, off_t, size_t,
-                   vm_prot_t, struct uvm_object **, voff_t *, struct file *);
-
 static int     tegra_drm_dumb_create(struct drm_file *, struct drm_device *,
                    struct drm_mode_create_dumb *);
 static int     tegra_drm_dumb_map_offset(struct drm_file *,
                    struct drm_device *, uint32_t, uint64_t *);
-static int     tegra_drm_dumb_destroy(struct drm_file *, struct drm_device *,
-                   uint32_t);
+
+static const struct uvm_pagerops tegra_drm_gem_uvm_ops = {
+       .pgo_reference = drm_gem_pager_reference,
+       .pgo_detach = drm_gem_pager_detach,
+       .pgo_fault = tegra_drm_gem_fault,
+};
 
 static struct drm_driver tegra_drm_driver = {
-       .driver_features = DRIVER_MODESET,
+       .driver_features = DRIVER_MODESET | DRIVER_GEM,
        .dev_priv_size = 0,
        .load = tegra_drm_load,
        .unload = tegra_drm_unload,
 
-       .mmap_object = tegra_drm_mmap_object,
+       .gem_free_object = tegra_drm_gem_free_object,
+       .mmap_object = drm_gem_or_legacy_mmap_object,
+       .gem_uvm_ops = &tegra_drm_gem_uvm_ops,
 
        .dumb_create = tegra_drm_dumb_create,
        .dumb_map_offset = tegra_drm_dumb_map_offset,
-       .dumb_destroy = tegra_drm_dumb_destroy,
+       .dumb_destroy = drm_gem_dumb_destroy,
 
        .get_vblank_counter = tegra_drm_get_vblank_counter,
        .enable_vblank = tegra_drm_enable_vblank,
@@ -114,7 +117,7 @@
        prop_dictionary_t prop = device_properties(self);
        struct drm_driver * const driver = &tegra_drm_driver;
        const char *pin, *dev;
-       int error, nsegs;
+       int error;
 
        sc->sc_dev = self;
        sc->sc_dmat = tio->tio_dmat;
@@ -145,24 +148,6 @@
        aprint_naive("\n");
        aprint_normal("\n");
 
-        sc->sc_dmasize = 4096 * 2160 * 4;
-        error = bus_dmamem_alloc(sc->sc_dmat, sc->sc_dmasize, PAGE_SIZE, 0,
-            sc->sc_dmasegs, 1, &nsegs, BUS_DMA_WAITOK);
-        if (error)
-                goto failed;
-        error = bus_dmamem_map(sc->sc_dmat, sc->sc_dmasegs, nsegs,
-           sc->sc_dmasize, &sc->sc_dmap, BUS_DMA_WAITOK | BUS_DMA_COHERENT);
-        if (error)
-                goto free;
-        error = bus_dmamap_create(sc->sc_dmat, sc->sc_dmasize, 1,
-           sc->sc_dmasize, 0, BUS_DMA_WAITOK, &sc->sc_dmamap);
-        if (error)
-                goto unmap;
-        error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap, sc->sc_dmap,
-           sc->sc_dmasize, NULL, BUS_DMA_WAITOK);
-        if (error)
-                goto destroy;
-
        driver->bus = &tegra_drm_bus;
 
        sc->sc_ddev = drm_dev_alloc(driver, sc->sc_dev);
@@ -185,16 +170,6 @@
            driver->date, sc->sc_ddev->primary->index);
 
        return;
-
-destroy:
-        bus_dmamap_destroy(sc->sc_dmat, sc->sc_dmamap);
-unmap:
-        bus_dmamem_unmap(sc->sc_dmat, sc->sc_dmap, sc->sc_dmasize);
-free:
-        bus_dmamem_free(sc->sc_dmat, sc->sc_dmasegs, nsegs);
-failed:
-
-       aprint_error_dev(sc->sc_dev, "bus_dma setup failed\n");
 }
 
 static const char *
@@ -256,35 +231,31 @@
 }
 
 static int
-tegra_drm_mmap_object(struct drm_device *ddev, off_t offset, size_t size,
-    vm_prot_t prot, struct uvm_object **uobjp, voff_t *uoffsetp,
-    struct file *file)
-{
-       /* XXX */
-       extern const struct cdevsw wsdisplay_cdevsw;
-       devmajor_t maj = cdevsw_lookup_major(&wsdisplay_cdevsw);
-       dev_t devno = makedev(maj, 0);
-       struct uvm_object *uobj;
-
-       KASSERT(offset == (offset & ~(PAGE_SIZE-1)));
-
-       uobj = udv_attach(devno, prot, offset, size);
-       if (uobj == NULL)
-               return -EINVAL;
-
-       *uobjp = uobj;
-       *uoffsetp = offset;
-       return 0;
-}
-
-static int
 tegra_drm_dumb_create(struct drm_file *file_priv, struct drm_device *ddev,
     struct drm_mode_create_dumb *args)
 {
+       struct tegra_gem_object *obj;
+       uint32_t handle;
+       int error;
+
        args->pitch = args->width * ((args->bpp + 7) / 8);
        args->size = args->pitch * args->height;
+       args->size = roundup(args->size, PAGE_SIZE);
        args->handle = 0;
 
+       obj = tegra_drm_obj_alloc(ddev, args->size);
+       if (obj == NULL)
+               return -ENOMEM;
+
+       error = drm_gem_handle_create(file_priv, &obj->base, &handle);
+       drm_gem_object_unreference_unlocked(&obj->base);
+       if (error) {
+               tegra_drm_obj_free(obj);
+               return error;
+       }
+
+       args->handle = handle;
+
        return 0;
 }
 
@@ -292,13 +263,26 @@
 tegra_drm_dumb_map_offset(struct drm_file *file_priv,
     struct drm_device *ddev, uint32_t handle, uint64_t *offset)
 {
-       *offset = 0;
-       return 0;
-}
+       struct drm_gem_object *gem_obj;
+       struct tegra_gem_object *obj;
+       int error;
+
+       gem_obj = drm_gem_object_lookup(ddev, file_priv, handle);
+       if (gem_obj == NULL)
+               return -ENOENT;
+
+       obj = to_tegra_gem_obj(gem_obj);
 
-static int
-tegra_drm_dumb_destroy(struct drm_file *file_priv, struct drm_device *ddev,
-    uint32_t handle)
-{
-       return 0;
+       if (drm_vma_node_has_offset(&obj->base.vma_node) == 0) {
+               error = drm_gem_create_mmap_offset(&obj->base);
+               if (error)
+                       goto done;
+       }
+
+       *offset = drm_vma_node_offset_addr(&obj->base.vma_node);
+
+done:
+       drm_gem_object_unreference_unlocked(&obj->base);
+
+       return error;
 }
diff -r eee5fe107945 -r 2ac5c2df94fb sys/arch/arm/nvidia/tegra_drm.h
--- a/sys/arch/arm/nvidia/tegra_drm.h   Wed Nov 11 21:52:45 2015 +0000
+++ b/sys/arch/arm/nvidia/tegra_drm.h   Thu Nov 12 00:43:52 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: tegra_drm.h,v 1.2 2015/11/10 22:14:05 jmcneill Exp $ */
+/* $NetBSD: tegra_drm.h,v 1.3 2015/11/12 00:43:52 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2015 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -48,6 +48,7 @@
        struct drm_device       *sc_ddev;
 
        bus_space_tag_t         sc_bst;
+       bus_dma_tag_t           sc_dmat;
 
        device_t                sc_ddcdev;
        struct tegra_gpio_pin   *sc_pin_hpd;
@@ -56,12 +57,6 @@
 
        bool                    sc_force_dvi;
 
-       bus_dma_tag_t           sc_dmat;
-       bus_dma_segment_t       sc_dmasegs[1];
-       bus_size_t              sc_dmasize;
-       bus_dmamap_t            sc_dmamap;
-       void                    *sc_dmap;
-
        uint32_t                sc_vbl_received[2];
 };
 
@@ -93,14 +88,25 @@
 struct tegra_connector {
        struct drm_connector    base;
        device_t                ddcdev;
+       struct i2c_adapter      *adapter;
        struct tegra_gpio_pin   *hpd;
 
        bool                    has_hdmi_sink;
        bool                    has_audio;
 };
 
+struct tegra_gem_object {
+       struct drm_gem_object   base;
+       bus_dma_tag_t           dmat;
+       bus_dma_segment_t       dmasegs[1];
+       bus_size_t              dmasize;
+       bus_dmamap_t            dmamap;
+       void                    *dmap;
+};
+
 struct tegra_framebuffer {
        struct drm_framebuffer  base;
+       struct tegra_gem_object *obj;
 };
 
 struct tegra_fbdev {
@@ -129,11 +135,21 @@
 #define to_tegra_connector(x)  container_of(x, struct tegra_connector, base)
 #define to_tegra_framebuffer(x)        container_of(x, struct tegra_framebuffer, base)
 #define to_tegra_fbdev(x)      container_of(x, struct tegra_fbdev, helper)
+#define to_tegra_gem_obj(x)    container_of(x, struct tegra_gem_object, base)
 
 int    tegra_drm_mode_init(struct drm_device *);
 int    tegra_drm_fb_init(struct drm_device *);
 u32    tegra_drm_get_vblank_counter(struct drm_device *, int);
 int    tegra_drm_enable_vblank(struct drm_device *, int);
 void   tegra_drm_disable_vblank(struct drm_device *, int);
+int    tegra_drm_framebuffer_init(struct drm_device *,
+           struct tegra_framebuffer *);
+
+struct tegra_gem_object *tegra_drm_obj_alloc(struct drm_device *, size_t);
+void   tegra_drm_obj_free(struct tegra_gem_object *);
+
+int    tegra_drm_gem_fault(struct uvm_faultinfo *, vaddr_t, struct vm_page **,
+           int, int, vm_prot_t, int);
+void   tegra_drm_gem_free_object(struct drm_gem_object *);
 
 #endif /* _ARM_TEGRA_DRM_H */
diff -r eee5fe107945 -r 2ac5c2df94fb sys/arch/arm/nvidia/tegra_drm_fb.c
--- a/sys/arch/arm/nvidia/tegra_drm_fb.c        Wed Nov 11 21:52:45 2015 +0000
+++ b/sys/arch/arm/nvidia/tegra_drm_fb.c        Thu Nov 12 00:43:52 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: tegra_drm_fb.c,v 1.1 2015/11/09 23:05:58 jmcneill Exp $ */
+/* $NetBSD: tegra_drm_fb.c,v 1.2 2015/11/12 00:43:52 jmcneill Exp $ */
 
 /*-



Home | Main Index | Thread Index | Old Index