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/e69836f66546
branches: trunk
changeset: 341566:e69836f66546
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 638662ea2af8 -r e69836f66546 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 638662ea2af8 -r e69836f66546 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 638662ea2af8 -r e69836f66546 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 638662ea2af8 -r e69836f66546 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