This begins to put meaningful code into the buffer management. It's in theory
pretty much all there now but needs a fair bit of debug before it'll actually
do anything useful. We also strip out a lot of the old GTT code we no longer
need and the last remnants of the TTM stuff.
---
Alan Cox (8):
gma500: allow non stolen page backed framebuffer
gma500: prune some unused variables
gma500: GEM - now we have the basics we shall stick pins in it
gma500: GEMify the frame buffer base bits
gma500: Begin the GEMification of the cursor code
gma500: Add support for inserting and removing pages from the GART
gma500: begin adding GEM
gma500: add the ability to request backed space or not
drivers/staging/gma500/Makefile | 2
drivers/staging/gma500/mrst_crtc.c | 15
drivers/staging/gma500/psb_2d.c | 4
drivers/staging/gma500/psb_drm.h | 11
drivers/staging/gma500/psb_drv.c | 46 +
drivers/staging/gma500/psb_drv.h | 25 -
drivers/staging/gma500/psb_fb.c | 301 +++----
drivers/staging/gma500/psb_fb.h | 5
drivers/staging/gma500/psb_gem.c | 209 +++++
drivers/staging/gma500/psb_gtt.c | 1215 ++++++++--------------------
drivers/staging/gma500/psb_gtt.h | 70 --
drivers/staging/gma500/psb_intel_display.c | 116 +--
drivers/staging/gma500/psb_intel_drv.h | 13
drivers/staging/gma500/psb_intel_lvds.c | 14
drivers/staging/gma500/psb_powermgmt.c | 5
drivers/staging/gma500/psb_pvr_glue.c | 73 --
drivers/staging/gma500/psb_pvr_glue.h | 25 -
17 files changed, 801 insertions(+), 1348 deletions(-)
create mode 100644 drivers/staging/gma500/psb_gem.c
delete mode 100644 drivers/staging/gma500/psb_pvr_glue.c
delete mode 100644 drivers/staging/gma500/psb_pvr_glue.h
--
Carry on carry on, there's nothing to be done on days like these
In the ruins and the rage, planting flowers for new days
In the ruins and the rage, we carry on
We will will need this for doing a GEM allocator. It should also avoid any
crashes with the current code if the stolen area is too small.
Signed-off-by: Alan Cox <[email protected]>
---
drivers/staging/gma500/psb_fb.c | 4 ++--
drivers/staging/gma500/psb_gtt.c | 17 ++++++++++++++---
drivers/staging/gma500/psb_gtt.h | 2 +-
3 files changed, 17 insertions(+), 6 deletions(-)
diff --git a/drivers/staging/gma500/psb_fb.c b/drivers/staging/gma500/psb_fb.c
index 0bad4e0..e06365b 100644
--- a/drivers/staging/gma500/psb_fb.c
+++ b/drivers/staging/gma500/psb_fb.c
@@ -479,8 +479,8 @@ static int psbfb_create(struct psb_fbdev *fbdev,
size = mode_cmd.pitch * mode_cmd.height;
aligned_size = ALIGN(size, PAGE_SIZE);
- /* Allocate the framebuffer in the GTT */
- backing = psb_gtt_alloc_range(dev, aligned_size, "fb");
+ /* Allocate the framebuffer in the GTT with stolen page backing */
+ backing = psb_gtt_alloc_range(dev, aligned_size, "fb", 1);
if (backing == NULL)
return -ENOMEM;
diff --git a/drivers/staging/gma500/psb_gtt.c b/drivers/staging/gma500/psb_gtt.c
index a97e7be..69323f9 100644
--- a/drivers/staging/gma500/psb_gtt.c
+++ b/drivers/staging/gma500/psb_gtt.c
@@ -972,6 +972,7 @@ struct gtt_range *psb_gtt_lookup_handle(struct drm_device *dev, int handle)
* @dev: Our DRM device
* @len: length (bytes) of address space required
* @name: resource name
+ * @backed: resource should be backed by stolen pages
*
* Ask the kernel core to find us a suitable range of addresses
* to use for a GTT mapping.
@@ -981,12 +982,23 @@ struct gtt_range *psb_gtt_lookup_handle(struct drm_device *dev, int handle)
* as in use.
*/
struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
- const char *name)
+ const char *name, int backed)
{
struct drm_psb_private *dev_priv = dev->dev_private;
struct gtt_range *gt;
struct resource *r = dev_priv->gtt_mem;
int ret;
+ unsigned long start, end;
+
+ if (backed) {
+ /* The start of the GTT is the stolen pages */
+ start = r->start;
+ end = r->start + dev_priv->pg->stolen_size - 1;
+ } else {
+ /* The rest we will use for GEM backed objects */
+ start = r->start + dev_priv->pg->stolen_size;
+ end = -1;
+ }
gt = kzalloc(sizeof(struct gtt_range), GFP_KERNEL);
if (gt == NULL)
@@ -996,8 +1008,7 @@ struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
kref_init(>->kref);
ret = allocate_resource(dev_priv->gtt_mem, >->resource,
- len, 0, -1, /*r->start, r->end - 1, */
- PAGE_SIZE, NULL, NULL);
+ len, start, end, PAGE_SIZE, NULL, NULL);
if (ret == 0) {
gt->offset = gt->resource.start - r->start;
return gt;
diff --git a/drivers/staging/gma500/psb_gtt.h b/drivers/staging/gma500/psb_gtt.h
index 010ef70..dc2259c 100644
--- a/drivers/staging/gma500/psb_gtt.h
+++ b/drivers/staging/gma500/psb_gtt.h
@@ -105,7 +105,7 @@ extern int psb_gtt_release_handle(struct drm_device *dev, struct gtt_range *gt);
extern struct gtt_range *psb_gtt_lookup_handle(struct drm_device *dev,
int handle);
extern struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
- const char *name);
+ const char *name, int backed);
extern void psb_gtt_kref_put(struct gtt_range *gt);
extern void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt);
This puts in place the infrastructure for GEM allocators. Our implementation
is fairly simplistic at this point and we don't deal with things like
evicting objects from the GART to make space, nor compaction.
We extent our gtt_range struct to include a GEM object and that allows GEM
to do all the handle management and most of the memory mapping work for us.
This patch also doesn't load GEM pages into the GART so the GEM side isn't
very useful. Before we can do that a fair bit of work is needed reworking the
internal GTT code.
Signed-off-by: Alan Cox <[email protected]>
---
drivers/staging/gma500/Makefile | 1
drivers/staging/gma500/psb_drv.c | 18 +++
drivers/staging/gma500/psb_drv.h | 16 +++
drivers/staging/gma500/psb_fb.c | 198 ++++++++++++++----------------------
drivers/staging/gma500/psb_gem.c | 207 ++++++++++++++++++++++++++++++++++++++
drivers/staging/gma500/psb_gtt.c | 85 +---------------
drivers/staging/gma500/psb_gtt.h | 17 +--
7 files changed, 318 insertions(+), 224 deletions(-)
create mode 100644 drivers/staging/gma500/psb_gem.c
diff --git a/drivers/staging/gma500/Makefile b/drivers/staging/gma500/Makefile
index e00557e..0c4f7b6 100644
--- a/drivers/staging/gma500/Makefile
+++ b/drivers/staging/gma500/Makefile
@@ -5,6 +5,7 @@ ccflags-y += -Iinclude/drm
psb_gfx-y += psb_bl.o \
psb_drv.o \
+ psb_gem.o \
psb_fb.o \
psb_2d.o \
psb_gtt.o \
diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c
index d87e00d..d871061 100644
--- a/drivers/staging/gma500/psb_drv.c
+++ b/drivers/staging/gma500/psb_drv.c
@@ -1405,9 +1405,15 @@ static const struct dev_pm_ops psb_pm_ops = {
.runtime_idle = psb_runtime_idle,
};
+static struct vm_operations_struct psb_gem_vm_ops = {
+ .fault = psb_gem_fault,
+ .open = drm_gem_vm_open,
+ .close = drm_gem_vm_close,
+};
+
static struct drm_driver driver = {
.driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | \
- DRIVER_IRQ_VBL | DRIVER_MODESET,
+ DRIVER_IRQ_VBL | DRIVER_MODESET| DRIVER_GEM ,
.load = psb_driver_load,
.unload = psb_driver_unload,
@@ -1421,13 +1427,19 @@ static struct drm_driver driver = {
.enable_vblank = psb_enable_vblank,
.disable_vblank = psb_disable_vblank,
.get_vblank_counter = psb_get_vblank_counter,
- .firstopen = NULL,
.lastclose = psb_lastclose,
.open = psb_driver_open,
+ .preclose = psb_driver_preclose,
.postclose = psb_driver_close,
.reclaim_buffers = drm_core_reclaim_buffers,
- .preclose = psb_driver_preclose,
+ .gem_init_object = psb_gem_init_object,
+ .gem_free_object = psb_gem_free_object,
+ .gem_vm_ops = &psb_gem_vm_ops,
+ .dumb_create = psb_gem_dumb_create,
+ .dumb_map_offset = psb_gem_dumb_map_gtt,
+ .dumb_destroy = psb_gem_dumb_destroy,
+
.fops = {
.owner = THIS_MODULE,
.open = psb_open,
diff --git a/drivers/staging/gma500/psb_drv.h b/drivers/staging/gma500/psb_drv.h
index 9da6a33..aa68ae7 100644
--- a/drivers/staging/gma500/psb_drv.h
+++ b/drivers/staging/gma500/psb_drv.h
@@ -243,7 +243,6 @@ struct drm_psb_private {
struct mutex gtt_mutex;
struct resource *gtt_mem; /* Our PCI resource */
- struct gtt_range *gtt_handles[GTT_MAX];
struct psb_mmu_driver *mmu;
struct psb_mmu_pd *pf_pd;
@@ -627,9 +626,22 @@ extern const struct drm_connector_helper_funcs
psb_intel_lvds_connector_helper_funcs;
extern const struct drm_connector_funcs psb_intel_lvds_connector_funcs;
+/* psb_gem.c */
+extern int psb_gem_init_object(struct drm_gem_object *obj);
+extern void psb_gem_free_object(struct drm_gem_object *obj);
+extern int psb_gem_get_aperture(struct drm_device *dev, void *data,
+ struct drm_file *file);
+extern int psb_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
+ struct drm_mode_create_dumb *args);
+extern int psb_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev,
+ uint32_t handle);
+extern int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev,
+ uint32_t handle, uint64_t *offset);
+extern int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
+
/*
- *Debug print bits setting
+ * Debug print bits setting
*/
#define PSB_D_GENERAL (1 << 0)
#define PSB_D_INIT (1 << 1)
diff --git a/drivers/staging/gma500/psb_fb.c b/drivers/staging/gma500/psb_fb.c
index e06365b..ffbbbb6 100644
--- a/drivers/staging/gma500/psb_fb.c
+++ b/drivers/staging/gma500/psb_fb.c
@@ -264,7 +264,7 @@ static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
VM_MIXEDMAP | VM_DONTEXPAND;
} else {
/* GTT memory backed by kernel/user pages, needs a different
- approach ? */
+ approach ? - GEM ? */
}
return 0;
@@ -337,122 +337,13 @@ err:
return NULL;
}
-static struct drm_framebuffer *psb_user_framebuffer_create
- (struct drm_device *dev, struct drm_file *filp,
- struct drm_mode_fb_cmd *r)
-{
- return NULL;
-#if 0
- struct ttm_buffer_object *bo = NULL;
- uint64_t size;
-
- bo = ttm_buffer_object_lookup(psb_fpriv(filp)->tfile, r->handle);
- if (!bo)
- return NULL;
-
- /* JB: TODO not drop, make smarter */
- size = ((uint64_t) bo->num_pages) << PAGE_SHIFT;
- if (size < r->width * r->height * 4)
- return NULL;
-
- /* JB: TODO not drop, refcount buffer */
- return psb_framebuffer_create(dev, r, bo);
-
- struct psb_framebuffer *psbfb;
- struct drm_framebuffer *fb;
- struct fb_info *info;
- void *psKernelMemInfo = NULL;
- void * hKernelMemInfo = (void *)r->handle;
- struct drm_psb_private *dev_priv
- = (struct drm_psb_private *)dev->dev_private;
- struct psb_fbdev *fbdev = dev_priv->fbdev;
- struct psb_gtt *pg = dev_priv->pg;
- int ret;
- uint32_t offset;
- uint64_t size;
-
- ret = psb_get_meminfo_by_handle(hKernelMemInfo, &psKernelMemInfo);
- if (ret) {
- DRM_ERROR("Cannot get meminfo for handle 0x%x\n",
- (u32)hKernelMemInfo);
- return NULL;
- }
-
- DRM_DEBUG("Got Kernel MemInfo for handle %lx\n",
- (u32)hKernelMemInfo);
-
- /* JB: TODO not drop, make smarter */
- size = psKernelMemInfo->ui32AllocSize;
- if (size < r->height * r->pitch)
- return NULL;
-
- /* JB: TODO not drop, refcount buffer */
- /* return psb_framebuffer_create(dev, r, bo); */
-
- fb = psb_framebuffer_create(dev, r, (void *)psKernelMemInfo);
- if (!fb) {
- DRM_ERROR("failed to allocate fb.\n");
- return NULL;
- }
-
- psbfb = to_psb_fb(fb);
- psbfb->size = size;
- psbfb->hKernelMemInfo = hKernelMemInfo;
-
- DRM_DEBUG("Mapping to gtt..., KernelMemInfo %p\n", psKernelMemInfo);
-
- /*if not VRAM, map it into tt aperture*/
- if (psKernelMemInfo->pvLinAddrKM != pg->vram_addr) {
- ret = psb_gtt_map_meminfo(dev, hKernelMemInfo, &offset);
- if (ret) {
- DRM_ERROR("map meminfo for 0x%x failed\n",
- (u32)hKernelMemInfo);
- return NULL;
- }
- psbfb->offset = (offset << PAGE_SHIFT);
- } else {
- psbfb->offset = 0;
- }
- info = framebuffer_alloc(0, &dev->pdev->dev);
- if (!info)
- return NULL;
-
- strcpy(info->fix.id, "psbfb");
-
- info->flags = FBINFO_DEFAULT;
- info->fix.accel = FB_ACCEL_I830; /*FIXMEAC*/
- info->fbops = &psbfb_ops;
-
- info->fix.smem_start = dev->mode_config.fb_base;
- info->fix.smem_len = size;
-
- info->screen_base = psKernelMemInfo->pvLinAddrKM;
- info->screen_size = size;
-
- drm_fb_helper_fill_fix(info, fb->pitch, fb->depth);
- drm_fb_helper_fill_var(info, &fbdev->psb_fb_helper,
- fb->width, fb->height);
-
- info->fix.mmio_start = pci_resource_start(dev->pdev, 0);
- info->fix.mmio_len = pci_resource_len(dev->pdev, 0);
-
- info->pixmap.size = 64 * 1024;
- info->pixmap.buf_align = 8;
- info->pixmap.access_align = 32;
- info->pixmap.flags = FB_PIXMAP_SYSTEM;
- info->pixmap.scan_align = 1;
-
- psbfb->fbdev = info;
- fbdev->pfb = psbfb;
-
- fbdev->psb_fb_helper.fb = fb;
- fbdev->psb_fb_helper.fbdev = info;
- MRSTLFBHandleChangeFB(dev, psbfb);
-
- return fb;
-#endif
-}
-
+/**
+ * psbfb_create - create a framebuffer
+ * @fbdev: the framebuffer device
+ * @sizes: specification of the layout
+ *
+ * Create a framebuffer to the specifications provided
+ */
static int psbfb_create(struct psb_fbdev *fbdev,
struct drm_fb_helper_surface_size *sizes)
{
@@ -552,6 +443,47 @@ out_err1:
return ret;
}
+/**
+ * psb_user_framebuffer_create - create framebuffer
+ * @dev: our DRM device
+ * @filp: client file
+ * @cmd: mode request
+ *
+ * Create a new framebuffer backed by a userspace GEM object
+ */
+static struct drm_framebuffer *psb_user_framebuffer_create
+ (struct drm_device *dev, struct drm_file *filp,
+ struct drm_mode_fb_cmd *cmd)
+{
+ struct gtt_range *r;
+ struct drm_gem_object *obj;
+ struct psb_framebuffer *psbfb;
+
+ /* Find the GEM object and thus the gtt range object that is
+ to back this space */
+ obj = drm_gem_object_lookup(dev, filp, cmd->handle);
+ if (obj == NULL)
+ return ERR_PTR(-ENOENT);
+
+ /* Allocate a framebuffer */
+ psbfb = kzalloc(sizeof(*psbfb), GFP_KERNEL);
+ if (psbfb == NULL) {
+ drm_gem_object_unreference_unlocked(obj);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ /* Let the core code do all the work */
+ r = container_of(obj, struct gtt_range, gem);
+ if (psb_framebuffer_create(dev, cmd, r) == NULL) {
+ drm_gem_object_unreference_unlocked(obj);
+ kfree(psbfb);
+ return ERR_PTR(-EINVAL);
+ }
+ /* Return the drm_framebuffer contained within the psb fbdev which
+ has been initialized by the framebuffer creation */
+ return &psbfb->base;
+}
+
static void psbfb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
u16 blue, int regno)
{
@@ -667,28 +599,46 @@ int psbfb_remove(struct drm_device *dev, struct drm_framebuffer *fb)
}
/*EXPORT_SYMBOL(psbfb_remove); */
+/**
+ * psb_user_framebuffer_create_handle - add hamdle to a framebuffer
+ * @fb: framebuffer
+ * @file_priv: our DRM file
+ * @handle: returned handle
+ *
+ * Our framebuffer object is a GTT range which also contains a GEM
+ * object. We need to turn it into a handle for userspace. GEM will do
+ * the work for us
+ */
static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb,
struct drm_file *file_priv,
unsigned int *handle)
{
- /* JB: TODO currently we can't go from a bo to a handle with ttm */
- (void) file_priv;
- *handle = 0;
- return 0;
+ struct psb_framebuffer *psbfb = to_psb_fb(fb);
+ struct gtt_range *r = psbfb->mem;
+ return drm_gem_handle_create(file_priv, &r->gem, handle);
}
+/**
+ * psb_user_framebuffer_destroy - destruct user created fb
+ * @fb: framebuffer
+ *
+ * User framebuffers are backed by GEM objects so all we have to do is
+ * clean up a bit and drop the reference, GEM will handle the fallout
+ */
static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb)
{
struct drm_device *dev = fb->dev;
struct psb_framebuffer *psbfb = to_psb_fb(fb);
+ struct gtt_range *r = psbfb->mem;
- /*ummap gtt pages*/
- psb_gtt_unmap_meminfo(dev, psbfb->hKernelMemInfo);
if (psbfb->fbdev)
psbfb_remove(dev, fb);
- /* JB: TODO not drop, refcount buffer */
+ /* Let DRM do its clean up */
drm_framebuffer_cleanup(fb);
+ /* We are no longer using the resource in GEM */
+ drm_gem_object_unreference_unlocked(&r->gem);
+
kfree(fb);
}
diff --git a/drivers/staging/gma500/psb_gem.c b/drivers/staging/gma500/psb_gem.c
new file mode 100644
index 0000000..0438bf4
--- /dev/null
+++ b/drivers/staging/gma500/psb_gem.c
@@ -0,0 +1,207 @@
+/*
+ * psb backlight interface
+ *
+ * Copyright (c) 2011, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors: Alan Cox
+ *
+ * TODO:
+ * - we don't actually put GEM objects into the GART yet
+ * - we need to work out if the MMU is relevant as well (eg for
+ * accelerated operations on a GEM object)
+ * - cache coherency
+ *
+ * ie this is just an initial framework to get us going.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include "psb_drm.h"
+#include "psb_drv.h"
+
+int psb_gem_init_object(struct drm_gem_object *obj)
+{
+ return -EINVAL;
+}
+
+void psb_gem_free_object(struct drm_gem_object *obj)
+{
+ drm_gem_object_release(obj);
+}
+
+int psb_gem_get_aperture(struct drm_device *dev, void *data,
+ struct drm_file *file)
+{
+ return -EINVAL;
+}
+
+/**
+ * psb_gem_dumb_map_gtt - buffer mapping for dumb interface
+ * @file: our drm client file
+ * @dev: drm device
+ * @handle: GEM handle to the object (from dumb_create)
+ *
+ * Do the necessary setup to allow the mapping of the frame buffer
+ * into user memory. We don't have to do much here at the moment.
+ */
+int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev,
+ uint32_t handle, uint64_t *offset)
+{
+ struct drm_gem_object *obj;
+ if (!(dev->driver->driver_features & DRIVER_GEM))
+ return -ENODEV;
+ /* GEM does all our handle to object mapping */
+ obj = drm_gem_object_lookup(dev, file, handle);
+ if (obj == NULL)
+ return -ENOENT;
+ /* What validation is needed here ? */
+
+ /* GEM works out the hash offsets for us */
+ *offset = (u64)obj->map_list.hash.key << PAGE_SHIFT;
+ drm_gem_object_unreference(obj);
+ return 0;
+}
+
+/**
+ * psb_gem_create - create a mappable object
+ * @file: the DRM file of the client
+ * @dev: our device
+ * @size: the size requested
+ * @handlep: returned handle (opaque number)
+ *
+ * Create a GEM object, fill in the boilerplate and attach a handle to
+ * it so that userspace can speak about it. This does the core work
+ * for the various methods that do/will create GEM objects for things
+ */
+static int psb_gem_create(struct drm_file *file,
+ struct drm_device *dev, uint64_t size, uint32_t *handlep)
+{
+ struct gtt_range *r;
+ int ret;
+ u32 handle;
+
+ size = roundup(size, PAGE_SIZE);
+
+ /* Allocate our object - for now a direct gtt range which is not
+ stolen memory backed */
+ r = psb_gtt_alloc_range(dev, size, "gem", 0);
+ if (IS_ERR(r))
+ return PTR_ERR(r);
+ /* Initialize the extra goodies GEM needs to do all the hard work */
+ if (drm_gem_object_init(dev, &r->gem, size) != 0) {
+ psb_gtt_free_range(dev, r);
+ /* GEM doesn't give an error code and we don't have an
+ EGEMSUCKS so make something up for now - FIXME */
+ return -ENOMEM;
+ }
+ /* Give the object a handle so we can carry it more easily */
+ ret = drm_gem_handle_create(file, &r->gem, &handle);
+ if (ret) {
+ drm_gem_object_release(&r->gem);
+ psb_gtt_free_range(dev, r);
+ return ret;
+ }
+ /* We have the initial and handle reference but need only one now */
+ drm_gem_object_unreference(&r->gem);
+ *handlep = handle;
+ return 0;
+}
+
+/**
+ * psb_gem_dumb_create - create a dumb buffer
+ * @drm_file: our client file
+ * @dev: our device
+ * @args: the requested arguments copied from userspace
+ *
+ * Allocate a buffer suitable for use for a frame buffer of the
+ * form described by user space. Give userspace a handle by which
+ * to reference it.
+ */
+int psb_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
+ struct drm_mode_create_dumb *args)
+{
+ args->pitch = ALIGN(args->width & ((args->bpp + 1) / 8), 64);
+ args->size = args->pitch * args->height;
+ return psb_gem_create(file, dev, args->size, &args->handle);
+}
+
+/**
+ * psb_gem_dumb_destroy - destroy a dumb buffer
+ * @file: client file
+ * @dev: our DRM device
+ * @handle: the object handle
+ *
+ * Destroy a handle that was created via psb_gem_dumb_create, at least
+ * we hope it was created that way. i915 seems to assume the caller
+ * does the checking but that might be worth review ! FIXME
+ */
+int psb_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev,
+ uint32_t handle)
+{
+ /* No special work needed, drop the reference and see what falls out */
+ return drm_gem_handle_delete(file, handle);
+}
+
+/**
+ * psb_gem_fault - pagefault handler for GEM objects
+ * @vma: the VMA of the GEM object
+ * @vmf: fault detail
+ *
+ * Invoked when a fault occurs on an mmap of a GEM managed area. GEM
+ * does most of the work for us including the actual map/unmap calls
+ * but we need to do the actual page work.
+ *
+ * This code eventually needs to handle faulting objects in and out
+ * of the GART and repacking it when we run out of space. We can put
+ * that off for now and for our simple uses
+ *
+ * The VMA was set up by GEM. In doing so it also ensured that the
+ * vma->vm_private_data points to the GEM object that is backing this
+ * mapping.
+ */
+int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+ struct drm_gem_object *obj;
+ struct gtt_range *r;
+ int ret;
+ unsigned long pfn;
+ pgoff_t page_offset;
+
+ obj = vma->vm_private_data; /* GEM object */
+ r = container_of(obj, struct gtt_range, gem); /* Get the gtt range */
+
+ /* FIXME: Locking. We may also need to repack the GART sometimes */
+
+ /* Page relative to the VMA start */
+ page_offset = ((unsigned long) vmf->virtual_address - vma->vm_start)
+ >> PAGE_SHIFT;
+
+ /* Bus address of the page is gart + object offset + page offset */
+ /* Assumes gtt allocations are page aligned */
+ pfn = (r->resource.start >> PAGE_SHIFT) + page_offset;
+
+ ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn);
+ switch (ret) {
+ case 0:
+ case -ERESTARTSYS:
+ case -EINTR:
+ return VM_FAULT_NOPAGE;
+ case -ENOMEM:
+ return VM_FAULT_OOM;
+ default:
+ return VM_FAULT_SIGBUS;
+ }
+}
diff --git a/drivers/staging/gma500/psb_gtt.c b/drivers/staging/gma500/psb_gtt.c
index 69323f9..4846fef 100644
--- a/drivers/staging/gma500/psb_gtt.c
+++ b/drivers/staging/gma500/psb_gtt.c
@@ -887,87 +887,10 @@ int psb_gtt_unmap_meminfo(struct drm_device *dev, void * hKernelMemInfo)
}
/*
- * GTT resource allocator
+ * GTT resource allocator - allocate and manage GTT address space
*/
/**
- * psb_gtt_alloc_handle - allocate a handle to a GTT map
- * @dev: our DRM device
- * @gt: Our GTT range
- *
- * Assign a handle to a gtt range object. For the moment we use a very
- * simplistic interface.
- */
-int psb_gtt_alloc_handle(struct drm_device *dev, struct gtt_range *gt)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- int h;
-
- mutex_lock(&dev_priv->gtt_mutex);
- for (h = 0; h < GTT_MAX; h++) {
- if (dev_priv->gtt_handles[h] == NULL) {
- dev_priv->gtt_handles[h] = gt;
- gt->handle = h;
- kref_get(>->kref);
- mutex_unlock(&dev_priv->gtt_mutex);
- return h;
- }
- }
- mutex_unlock(&dev_priv->gtt_mutex);
- return -ENOSPC;
-}
-
-/**
- * psb_gtt_release_handle - release a handle to a GTT map
- * @dev: our DRM device
- * @gt: Our GTT range
- *
- * Remove the handle from a gtt range object
- */
-int psb_gtt_release_handle(struct drm_device *dev, struct gtt_range *gt)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- if (gt->handle < 0 || gt->handle >= GTT_MAX) {
- gt->handle = -1;
- WARN_ON(1);
- return -EINVAL;
- }
- mutex_lock(&dev_priv->gtt_mutex);
- dev_priv->gtt_handles[gt->handle] = NULL;
- gt->handle = -1;
- mutex_unlock(&dev_priv->gtt_mutex);
- psb_gtt_kref_put(gt);
- return 0;
-}
-
-/**
- * psb_gtt_lookup_handle - look up a GTT handle
- * @dev: our DRM device
- * @handle: our handle
- *
- * Look up a gtt handle and return the gtt or NULL. The object returned
- * has a reference held so the caller must drop this when finished.
- */
-struct gtt_range *psb_gtt_lookup_handle(struct drm_device *dev, int handle)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct gtt_range *gt;
-
- if (handle < 0 || handle > GTT_MAX)
- return ERR_PTR(-EINVAL);
-
- mutex_lock(&dev_priv->gtt_mutex);
- gt = dev_priv->gtt_handles[handle];
- kref_get(>->kref);
- mutex_unlock(&dev_priv->gtt_mutex);
-
- if (gt == NULL)
- return ERR_PTR(-ENOENT);
- return gt;
-}
-
-/**
* psb_gtt_alloc_range - allocate GTT address space
* @dev: Our DRM device
* @len: length (bytes) of address space required
@@ -1003,8 +926,9 @@ struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
gt = kzalloc(sizeof(struct gtt_range), GFP_KERNEL);
if (gt == NULL)
return NULL;
- gt->handle = -1;
gt->resource.name = name;
+ gt->stolen = backed;
+ gt->in_gart = backed;
kref_init(>->kref);
ret = allocate_resource(dev_priv->gtt_mem, >->resource,
@@ -1020,6 +944,7 @@ struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
static void psb_gtt_destroy(struct kref *kref)
{
struct gtt_range *gt = container_of(kref, struct gtt_range, kref);
+ WARN_ON(gt->in_gart && !gt->stolen);
release_resource(>->resource);
kfree(gt);
}
@@ -1044,7 +969,5 @@ void psb_gtt_kref_put(struct gtt_range *gt)
*/
void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt)
{
- if (gt->handle != -1)
- psb_gtt_release_handle(dev, gt);
psb_gtt_kref_put(gt);
}
diff --git a/drivers/staging/gma500/psb_gtt.h b/drivers/staging/gma500/psb_gtt.h
index dc2259c..1b5bec0 100644
--- a/drivers/staging/gma500/psb_gtt.h
+++ b/drivers/staging/gma500/psb_gtt.h
@@ -87,23 +87,12 @@ extern void psb_gtt_mm_takedown(void);
struct gtt_range {
struct resource resource;
u32 offset;
- int handle;
struct kref kref;
+ struct drm_gem_object gem; /* GEM high level stuff */
+ int in_gart; /* Currently in the GART */
+ int stolen; /* Backed from stolen RAM */
};
-/* Most GTT handles we allow allocation of - for now five is fine: we need
- - Two framebuffers
- - Maybe an upload area
- - One cursor (eventually)
- - One fence page (possibly)
-*/
-
-#define GTT_MAX 5
-
-extern int psb_gtt_alloc_handle(struct drm_device *dev, struct gtt_range *gt);
-extern int psb_gtt_release_handle(struct drm_device *dev, struct gtt_range *gt);
-extern struct gtt_range *psb_gtt_lookup_handle(struct drm_device *dev,
- int handle);
extern struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
const char *name, int backed);
extern void psb_gtt_kref_put(struct gtt_range *gt);
There are two chunks of code we need to do this. The first one is the code
to insert and remove the pages from the GART, the second is the code to build
page table lists from the GEM object. Surprisingly this latter one doesn't seem
to have a nice GEM helper.
While we are at it we can begin dismantling the semi redundant struct pg,
and finish pruning out the old now unused gtt code as well as the last bits
of helper glue from the old driver base.
Signed-off-by: Alan Cox <[email protected]>
---
drivers/staging/gma500/Makefile | 1
drivers/staging/gma500/psb_drv.c | 24 -
drivers/staging/gma500/psb_drv.h | 7
drivers/staging/gma500/psb_fb.c | 34 -
drivers/staging/gma500/psb_gtt.c | 1108 ++++++++--------------------
drivers/staging/gma500/psb_gtt.h | 52 -
drivers/staging/gma500/psb_intel_display.c | 7
drivers/staging/gma500/psb_powermgmt.c | 5
drivers/staging/gma500/psb_pvr_glue.c | 73 --
drivers/staging/gma500/psb_pvr_glue.h | 25 -
10 files changed, 338 insertions(+), 998 deletions(-)
delete mode 100644 drivers/staging/gma500/psb_pvr_glue.c
delete mode 100644 drivers/staging/gma500/psb_pvr_glue.h
diff --git a/drivers/staging/gma500/Makefile b/drivers/staging/gma500/Makefile
index 0c4f7b6..db73ec6 100644
--- a/drivers/staging/gma500/Makefile
+++ b/drivers/staging/gma500/Makefile
@@ -17,7 +17,6 @@ psb_gfx-y += psb_bl.o \
psb_intel_modes.o \
psb_intel_sdvo.o \
psb_lid.o \
- psb_pvr_glue.o \
psb_mmu.o \
psb_powermgmt.o \
psb_irq.o \
diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c
index d871061..f501cd7 100644
--- a/drivers/staging/gma500/psb_drv.c
+++ b/drivers/staging/gma500/psb_drv.c
@@ -499,15 +499,15 @@ static int psb_driver_unload(struct drm_device *dev)
down_read(&pg->sem);
psb_mmu_remove_pfn_sequence(
- psb_mmu_get_default_pd
- (dev_priv->mmu),
- pg->mmu_gatt_start,
- pg->vram_stolen_size >> PAGE_SHIFT);
+ psb_mmu_get_default_pd
+ (dev_priv->mmu),
+ pg->mmu_gatt_start,
+ dev_priv->vram_stolen_size >> PAGE_SHIFT);
up_read(&pg->sem);
psb_mmu_driver_takedown(dev_priv->mmu);
dev_priv->mmu = NULL;
}
- psb_gtt_takedown(dev_priv->pg, 1);
+ psb_gtt_takedown(dev);
if (dev_priv->scratch_page) {
__free_page(dev_priv->scratch_page);
dev_priv->scratch_page = NULL;
@@ -592,15 +592,7 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
set_pages_uc(dev_priv->scratch_page, 1);
- dev_priv->pg = psb_gtt_alloc(dev);
- if (!dev_priv->pg)
- goto out_err;
-
- ret = psb_gtt_init(dev_priv->pg, 0);
- if (ret)
- goto out_err;
-
- ret = psb_gtt_mm_init(dev_priv->pg);
+ ret = psb_gtt_init(dev, 0);
if (ret)
goto out_err;
@@ -955,8 +947,8 @@ static int psb_stolen_memory_ioctl(struct drm_device *dev, void *data,
struct drm_psb_private *dev_priv = psb_priv(dev);
struct drm_psb_stolen_memory_arg *arg = data;
- arg->base = dev_priv->pg->stolen_base;
- arg->size = dev_priv->pg->vram_stolen_size;
+ arg->base = dev_priv->stolen_base;
+ arg->size = dev_priv->vram_stolen_size;
return 0;
}
diff --git a/drivers/staging/gma500/psb_drv.h b/drivers/staging/gma500/psb_drv.h
index aa68ae7..4c983ff 100644
--- a/drivers/staging/gma500/psb_drv.h
+++ b/drivers/staging/gma500/psb_drv.h
@@ -240,6 +240,13 @@ struct drm_psb_private {
/* GTT Memory manager */
struct psb_gtt_mm *gtt_mm;
struct page *scratch_page;
+ u32 *gtt_map;
+ uint32_t stolen_base;
+ void *vram_addr;
+ unsigned long vram_stolen_size;
+ int gtt_initialized;
+ u16 gmch_ctrl; /* Saved GTT setup */
+ u32 pge_ctl;
struct mutex gtt_mutex;
struct resource *gtt_mem; /* Our PCI resource */
diff --git a/drivers/staging/gma500/psb_fb.c b/drivers/staging/gma500/psb_fb.c
index ffbbbb6..eaf960e 100644
--- a/drivers/staging/gma500/psb_fb.c
+++ b/drivers/staging/gma500/psb_fb.c
@@ -37,7 +37,6 @@
#include "psb_intel_reg.h"
#include "psb_intel_drv.h"
#include "psb_fb.h"
-#include "psb_pvr_glue.h"
static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb);
static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb,
@@ -191,8 +190,7 @@ static int psbfb_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
struct psb_framebuffer *psbfb = vma->vm_private_data;
struct drm_device *dev = psbfb->base.dev;
struct drm_psb_private *dev_priv = dev->dev_private;
- struct psb_gtt *pg = dev_priv->pg;
- unsigned long phys_addr = (unsigned long)pg->stolen_base;
+ unsigned long phys_addr = (unsigned long)dev_priv->stolen_base;
page_num = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
@@ -241,7 +239,6 @@ static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
char *fb_screen_base = NULL;
struct drm_device *dev = psbfb->base.dev;
struct drm_psb_private *dev_priv = dev->dev_private;
- struct psb_gtt *pg = dev_priv->pg;
if (vma->vm_pgoff != 0)
return -EINVAL;
@@ -254,10 +251,11 @@ static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
fb_screen_base = (char *)info->screen_base;
DRM_DEBUG("vm_pgoff 0x%lx, screen base %p vram_addr %p\n",
- vma->vm_pgoff, fb_screen_base, pg->vram_addr);
+ vma->vm_pgoff, fb_screen_base,
+ dev_priv->vram_addr);
/* FIXME: ultimately this needs to become 'if entirely stolen memory' */
- if (1 || fb_screen_base == pg->vram_addr) {
+ if (1 || fb_screen_base == dev_priv->vram_addr) {
vma->vm_ops = &psbfb_vm_ops;
vma->vm_private_data = (void *)psbfb;
vma->vm_flags |= VM_RESERVED | VM_IO |
@@ -349,7 +347,6 @@ static int psbfb_create(struct psb_fbdev *fbdev,
{
struct drm_device *dev = fbdev->psb_fb_helper.dev;
struct drm_psb_private *dev_priv = dev->dev_private;
- struct psb_gtt *pg = dev_priv->pg;
struct fb_info *info;
struct drm_framebuffer *fb;
struct psb_framebuffer *psbfb;
@@ -409,7 +406,7 @@ static int psbfb_create(struct psb_fbdev *fbdev,
/* Accessed via stolen memory directly, This only works for stolem
memory however. Need to address this once we start using gtt
pages we allocate */
- info->screen_base = (char *)pg->vram_addr + backing->offset;
+ info->screen_base = (char *)dev_priv->vram_addr + backing->offset;
info->screen_size = size;
memset(info->screen_base, 0, size);
@@ -735,32 +732,19 @@ static void psb_setup_outputs(struct drm_device *dev)
}
}
+/* FIXME: rewrite these in terms of the gtt_range and GEM objects
+ rather than faking them as we do now */
+
static void *psb_bo_from_handle(struct drm_device *dev,
struct drm_file *file_priv,
unsigned int handle)
{
- void *psKernelMemInfo = NULL;
- void * hKernelMemInfo = (void *)handle;
- int ret;
-
- ret = psb_get_meminfo_by_handle(hKernelMemInfo, &psKernelMemInfo);
- if (ret) {
- DRM_ERROR("Cannot get meminfo for handle 0x%x\n",
- (u32)hKernelMemInfo);
- return NULL;
- }
-
- return (void *)psKernelMemInfo;
+ return NULL;
}
static size_t psb_bo_size(struct drm_device *dev, void *bof)
{
-#if 0
- void *psKernelMemInfo = (void *)bof;
- return (size_t)psKernelMemInfo->ui32AllocSize;
-#else
return 0;
-#endif
}
static size_t psb_bo_offset(struct drm_device *dev, void *bof)
diff --git a/drivers/staging/gma500/psb_gtt.c b/drivers/staging/gma500/psb_gtt.c
index 4846fef..090d30e 100644
--- a/drivers/staging/gma500/psb_gtt.c
+++ b/drivers/staging/gma500/psb_gtt.c
@@ -16,12 +16,24 @@
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*
* Authors: Thomas Hellstrom <thomas-at-tungstengraphics.com>
+ * Alan Cox <[email protected]>
*/
#include <drm/drmP.h>
#include "psb_drv.h"
-#include "psb_pvr_glue.h"
+
+/*
+ * GTT resource allocator - manage page mappings in GTT space
+ */
+
+/**
+ * psb_gtt_mask_pte - generate GART pte entry
+ * @pfn: page number to encode
+ * @type: type of memory in the GART
+ *
+ * Set the GART entry for the appropriate memory type.
+ */
static inline uint32_t psb_gtt_mask_pte(uint32_t pfn, int type)
{
uint32_t mask = PSB_PTE_VALID;
@@ -36,854 +48,162 @@ static inline uint32_t psb_gtt_mask_pte(uint32_t pfn, int type)
return (pfn << PAGE_SHIFT) | mask;
}
-struct psb_gtt *psb_gtt_alloc(struct drm_device *dev)
-{
- struct psb_gtt *tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
-
- if (!tmp)
- return NULL;
-
- init_rwsem(&tmp->sem);
- tmp->dev = dev;
-
- return tmp;
-}
-
-void psb_gtt_takedown(struct psb_gtt *pg, int free)
-{
- struct drm_psb_private *dev_priv = pg->dev->dev_private;
-
- if (!pg)
- return;
-
- if (pg->gtt_map) {
- iounmap(pg->gtt_map);
- pg->gtt_map = NULL;
- }
- if (pg->initialized) {
- pci_write_config_word(pg->dev->pdev, PSB_GMCH_CTRL,
- pg->gmch_ctrl);
- PSB_WVDC32(pg->pge_ctl, PSB_PGETBL_CTL);
- (void) PSB_RVDC32(PSB_PGETBL_CTL);
- }
- if (free)
- kfree(pg);
-}
-
-int psb_gtt_init(struct psb_gtt *pg, int resume)
-{
- struct drm_device *dev = pg->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- unsigned gtt_pages;
- unsigned long stolen_size, vram_stolen_size;
- unsigned i, num_pages;
- unsigned pfn_base;
- uint32_t vram_pages;
- uint32_t tt_pages;
- uint32_t *ttm_gtt_map;
- uint32_t dvmt_mode = 0;
-
- int ret = 0;
- uint32_t pte;
-
- pci_read_config_word(dev->pdev, PSB_GMCH_CTRL, &pg->gmch_ctrl);
- pci_write_config_word(dev->pdev, PSB_GMCH_CTRL,
- pg->gmch_ctrl | _PSB_GMCH_ENABLED);
-
- pg->pge_ctl = PSB_RVDC32(PSB_PGETBL_CTL);
- PSB_WVDC32(pg->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL);
- (void) PSB_RVDC32(PSB_PGETBL_CTL);
-
- /* The root resource we allocate address space from */
- dev_priv->gtt_mem = &dev->pdev->resource[PSB_GATT_RESOURCE];
-
- pg->initialized = 1;
- pg->gtt_phys_start = pg->pge_ctl & PAGE_MASK;
-
- pg->gatt_start = pci_resource_start(dev->pdev, PSB_GATT_RESOURCE);
- /* fix me: video mmu has hw bug to access 0x0D0000000,
- * then make gatt start at 0x0e000,0000 */
- pg->mmu_gatt_start = 0xE0000000;
- pg->gtt_start = pci_resource_start(dev->pdev, PSB_GTT_RESOURCE);
- gtt_pages =
- pci_resource_len(dev->pdev, PSB_GTT_RESOURCE) >> PAGE_SHIFT;
- pg->gatt_pages = pci_resource_len(dev->pdev, PSB_GATT_RESOURCE)
- >> PAGE_SHIFT;
-
- pci_read_config_dword(dev->pdev, PSB_BSM, &pg->stolen_base);
- vram_stolen_size = pg->gtt_phys_start - pg->stolen_base - PAGE_SIZE;
-
- stolen_size = vram_stolen_size;
-
- printk(KERN_INFO"GMMADR(region 0) start: 0x%08x (%dM).\n",
- pg->gatt_start, pg->gatt_pages/256);
- printk(KERN_INFO"GTTADR(region 3) start: 0x%08x (can map %dM RAM), and actual RAM base 0x%08x.\n",
- pg->gtt_start, gtt_pages * 4, pg->gtt_phys_start);
- printk(KERN_INFO "Stolen memory information\n");
- printk(KERN_INFO " base in RAM: 0x%x\n", pg->stolen_base);
- printk(KERN_INFO " size: %luK, calculated by (GTT RAM base) - (Stolen base), seems wrong\n",
- vram_stolen_size/1024);
- dvmt_mode = (pg->gmch_ctrl >> 4) & 0x7;
- printk(KERN_INFO " the correct size should be: %dM(dvmt mode=%d)\n",
- (dvmt_mode == 1) ? 1 : (2 << (dvmt_mode - 1)), dvmt_mode);
-
- if (resume && (gtt_pages != pg->gtt_pages) &&
- (stolen_size != pg->stolen_size)) {
- DRM_ERROR("GTT resume error.\n");
- ret = -EINVAL;
- goto out_err;
- }
-
- pg->gtt_pages = gtt_pages;
- pg->stolen_size = stolen_size;
- pg->vram_stolen_size = vram_stolen_size;
- pg->gtt_map =
- ioremap_nocache(pg->gtt_phys_start, gtt_pages << PAGE_SHIFT);
- if (!pg->gtt_map) {
- DRM_ERROR("Failure to map gtt.\n");
- ret = -ENOMEM;
- goto out_err;
- }
-
- pg->vram_addr = ioremap_wc(pg->stolen_base, stolen_size);
- if (!pg->vram_addr) {
- DRM_ERROR("Failure to map stolen base.\n");
- ret = -ENOMEM;
- goto out_err;
- }
-
- DRM_DEBUG("%s: vram kernel virtual address %p\n", pg->vram_addr);
-
- tt_pages = (pg->gatt_pages < PSB_TT_PRIV0_PLIMIT) ?
- (pg->gatt_pages) : PSB_TT_PRIV0_PLIMIT;
-
- ttm_gtt_map = pg->gtt_map + tt_pages / 2;
-
- /*
- * insert vram stolen pages.
- */
-
- pfn_base = pg->stolen_base >> PAGE_SHIFT;
- vram_pages = num_pages = vram_stolen_size >> PAGE_SHIFT;
- printk(KERN_INFO"Set up %d stolen pages starting at 0x%08x, GTT offset %dK\n",
- num_pages, pfn_base, 0);
- for (i = 0; i < num_pages; ++i) {
- pte = psb_gtt_mask_pte(pfn_base + i, 0);
- iowrite32(pte, pg->gtt_map + i);
- }
-
- /*
- * Init rest of gtt managed by IMG.
- */
- pfn_base = page_to_pfn(dev_priv->scratch_page);
- pte = psb_gtt_mask_pte(pfn_base, 0);
- for (; i < tt_pages / 2 - 1; ++i)
- iowrite32(pte, pg->gtt_map + i);
-
- /*
- * Init rest of gtt managed by TTM.
- */
-
- pfn_base = page_to_pfn(dev_priv->scratch_page);
- pte = psb_gtt_mask_pte(pfn_base, 0);
- PSB_DEBUG_INIT("Initializing the rest of a total "
- "of %d gtt pages.\n", pg->gatt_pages);
-
- for (; i < pg->gatt_pages - tt_pages / 2; ++i)
- iowrite32(pte, ttm_gtt_map + i);
- (void) ioread32(pg->gtt_map + i - 1);
-
- return 0;
-
-out_err:
- psb_gtt_takedown(pg, 0);
- return ret;
-}
-
-int psb_gtt_insert_pages(struct psb_gtt *pg, struct page **pages,
- unsigned offset_pages, unsigned num_pages,
- unsigned desired_tile_stride,
- unsigned hw_tile_stride, int type)
-{
- unsigned rows = 1;
- unsigned add;
- unsigned row_add;
- unsigned i;
- unsigned j;
- uint32_t *cur_page = NULL;
- uint32_t pte;
-
- if (hw_tile_stride)
- rows = num_pages / desired_tile_stride;
- else
- desired_tile_stride = num_pages;
-
- add = desired_tile_stride;
- row_add = hw_tile_stride;
-
- down_read(&pg->sem);
- for (i = 0; i < rows; ++i) {
- cur_page = pg->gtt_map + offset_pages;
- for (j = 0; j < desired_tile_stride; ++j) {
- pte =
- psb_gtt_mask_pte(page_to_pfn(*pages++), type);
- iowrite32(pte, cur_page++);
- }
- offset_pages += add;
- }
- (void) ioread32(cur_page - 1);
- up_read(&pg->sem);
-
- return 0;
-}
-
-int psb_gtt_insert_phys_addresses(struct psb_gtt *pg, dma_addr_t *pPhysFrames,
- unsigned offset_pages, unsigned num_pages, int type)
-{
- unsigned j;
- uint32_t *cur_page = NULL;
- uint32_t pte;
- u32 ba;
-
- down_read(&pg->sem);
- cur_page = pg->gtt_map + offset_pages;
- for (j = 0; j < num_pages; ++j) {
- ba = *pPhysFrames++;
- pte = psb_gtt_mask_pte(ba >> PAGE_SHIFT, type);
- iowrite32(pte, cur_page++);
- }
- (void) ioread32(cur_page - 1);
- up_read(&pg->sem);
- return 0;
-}
-
-int psb_gtt_remove_pages(struct psb_gtt *pg, unsigned offset_pages,
- unsigned num_pages, unsigned desired_tile_stride,
- unsigned hw_tile_stride, int rc_prot)
-{
- struct drm_psb_private *dev_priv = pg->dev->dev_private;
- unsigned rows = 1;
- unsigned add;
- unsigned row_add;
- unsigned i;
- unsigned j;
- uint32_t *cur_page = NULL;
- unsigned pfn_base = page_to_pfn(dev_priv->scratch_page);
- uint32_t pte = psb_gtt_mask_pte(pfn_base, 0);
-
- if (hw_tile_stride)
- rows = num_pages / desired_tile_stride;
- else
- desired_tile_stride = num_pages;
-
- add = desired_tile_stride;
- row_add = hw_tile_stride;
-
- if (rc_prot)
- down_read(&pg->sem);
- for (i = 0; i < rows; ++i) {
- cur_page = pg->gtt_map + offset_pages;
- for (j = 0; j < desired_tile_stride; ++j)
- iowrite32(pte, cur_page++);
-
- offset_pages += add;
- }
- (void) ioread32(cur_page - 1);
- if (rc_prot)
- up_read(&pg->sem);
-
- return 0;
-}
-
-int psb_gtt_mm_init(struct psb_gtt *pg)
-{
- struct psb_gtt_mm *gtt_mm;
- struct drm_psb_private *dev_priv = pg->dev->dev_private;
- struct drm_open_hash *ht;
- struct drm_mm *mm;
- int ret;
- uint32_t tt_start;
- uint32_t tt_size;
-
- if (!pg || !pg->initialized) {
- DRM_DEBUG("Invalid gtt struct\n");
- return -EINVAL;
- }
-
- gtt_mm = kzalloc(sizeof(struct psb_gtt_mm), GFP_KERNEL);
- if (!gtt_mm)
- return -ENOMEM;
-
- spin_lock_init(>t_mm->lock);
-
- ht = >t_mm->hash;
- ret = drm_ht_create(ht, 20);
- if (ret) {
- DRM_DEBUG("Create hash table failed(%d)\n", ret);
- goto err_free;
- }
-
- tt_start = (pg->stolen_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
- tt_start = (tt_start < pg->gatt_pages) ? tt_start : pg->gatt_pages;
- tt_size = (pg->gatt_pages < PSB_TT_PRIV0_PLIMIT) ?
- (pg->gatt_pages) : PSB_TT_PRIV0_PLIMIT;
-
- mm = >t_mm->base;
-
- /*will use tt_start ~ 128M for IMG TT buffers*/
- ret = drm_mm_init(mm, tt_start, ((tt_size / 2) - tt_start));
- if (ret) {
- DRM_DEBUG("drm_mm_int error(%d)\n", ret);
- goto err_mm_init;
- }
-
- gtt_mm->count = 0;
-
- dev_priv->gtt_mm = gtt_mm;
-
- DRM_INFO("PSB GTT mem manager ready, tt_start %ld, tt_size %ld pages\n",
- (unsigned long)tt_start,
- (unsigned long)((tt_size / 2) - tt_start));
- return 0;
-err_mm_init:
- drm_ht_remove(ht);
-
-err_free:
- kfree(gtt_mm);
- return ret;
-}
-
/**
- * Delete all hash entries;
+ * psb_gtt_entry - find the GART entries for a gtt_range
+ * @dev: our DRM device
+ * @r: our GTT range
+ *
+ * Given a gtt_range object return the GART offset of the page table
+ * entries for this gtt_range
*/
-void psb_gtt_mm_takedown(void)
-{
- return;
-}
-
-static int psb_gtt_mm_get_ht_by_pid_locked(struct psb_gtt_mm *mm,
- u32 tgid,
- struct psb_gtt_hash_entry **hentry)
+u32 *psb_gtt_entry(struct drm_device *dev, struct gtt_range *r)
{
- struct drm_hash_item *entry;
- struct psb_gtt_hash_entry *psb_entry;
- int ret;
-
- ret = drm_ht_find_item(&mm->hash, tgid, &entry);
- if (ret) {
- DRM_DEBUG("Cannot find entry pid=%ld\n", tgid);
- return ret;
- }
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ unsigned long offset;
- psb_entry = container_of(entry, struct psb_gtt_hash_entry, item);
- if (!psb_entry) {
- DRM_DEBUG("Invalid entry");
- return -EINVAL;
- }
+ offset = r->resource.start - dev_priv->gtt_mem->start;
- *hentry = psb_entry;
- return 0;
+ return dev_priv->gtt_map + (offset >> PAGE_SHIFT);
}
-static int psb_gtt_mm_insert_ht_locked(struct psb_gtt_mm *mm,
- u32 tgid,
- struct psb_gtt_hash_entry *hentry)
-{
- struct drm_hash_item *item;
- int ret;
-
- if (!hentry) {
- DRM_DEBUG("Invalid parameters\n");
- return -EINVAL;
- }
-
- item = &hentry->item;
- item->key = tgid;
-
- /**
- * NOTE: drm_ht_insert_item will perform such a check
- ret = psb_gtt_mm_get_ht_by_pid(mm, tgid, &tmp);
- if (!ret) {
- DRM_DEBUG("Entry already exists for pid %ld\n", tgid);
- return -EAGAIN;
- }
- */
-
- /*Insert the given entry*/
- ret = drm_ht_insert_item(&mm->hash, item);
- if (ret) {
- DRM_DEBUG("Insert failure\n");
- return ret;
- }
-
- mm->count++;
-
- return 0;
-}
-
-static int psb_gtt_mm_alloc_insert_ht(struct psb_gtt_mm *mm,
- u32 tgid,
- struct psb_gtt_hash_entry **entry)
+/**
+ * psb_gtt_insert - put an object into the GART
+ * @dev: our DRM device
+ * @r: our GTT range
+ *
+ * Take our preallocated GTT range and insert the GEM object into
+ * the GART.
+ *
+ * FIXME: gtt lock ?
+ */
+int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r)
{
- struct psb_gtt_hash_entry *hentry;
- int ret;
+ u32 *gtt_slot, pte;
+ int numpages = (r->resource.end + 1 - r->resource.start) >> PAGE_SHIFT;
+ struct page **pages;
+ int i;
- /*if the hentry for this tgid exists, just get it and return*/
- spin_lock(&mm->lock);
- ret = psb_gtt_mm_get_ht_by_pid_locked(mm, tgid, &hentry);
- if (!ret) {
- DRM_DEBUG("Entry for tgid %ld exist, hentry %p\n",
- tgid, hentry);
- *entry = hentry;
- spin_unlock(&mm->lock);
+ if (r->stolen)
return 0;
- }
- spin_unlock(&mm->lock);
-
- DRM_DEBUG("Entry for tgid %ld doesn't exist, will create it\n", tgid);
-
- hentry = kzalloc(sizeof(struct psb_gtt_hash_entry), GFP_KERNEL);
- if (!hentry) {
- DRM_DEBUG("Kmalloc failled\n");
- return -ENOMEM;
- }
-
- ret = drm_ht_create(&hentry->ht, 20);
- if (ret) {
- DRM_DEBUG("Create hash table failed\n");
- return ret;
- }
-
- spin_lock(&mm->lock);
- ret = psb_gtt_mm_insert_ht_locked(mm, tgid, hentry);
- spin_unlock(&mm->lock);
-
- if (!ret)
- *entry = hentry;
-
- return ret;
-}
-
-static struct psb_gtt_hash_entry *
-psb_gtt_mm_remove_ht_locked(struct psb_gtt_mm *mm, u32 tgid)
-{
- struct psb_gtt_hash_entry *tmp;
- int ret;
-
- ret = psb_gtt_mm_get_ht_by_pid_locked(mm, tgid, &tmp);
- if (ret) {
- DRM_DEBUG("Cannot find entry pid %ld\n", tgid);
- return NULL;
- }
-
- /*remove it from ht*/
- drm_ht_remove_item(&mm->hash, &tmp->item);
-
- mm->count--;
-
- return tmp;
-}
-
-static int psb_gtt_mm_remove_free_ht_locked(struct psb_gtt_mm *mm, u32 tgid)
-{
- struct psb_gtt_hash_entry *entry;
-
- entry = psb_gtt_mm_remove_ht_locked(mm, tgid);
-
- if (!entry) {
- DRM_DEBUG("Invalid entry");
+ if (r->pages == NULL) {
+ WARN_ON(1);
return -EINVAL;
}
- /*delete ht*/
- drm_ht_remove(&entry->ht);
+ WARN_ON(r->in_gart); /* refcount these maybe ? */
- /*free this entry*/
- kfree(entry);
- return 0;
-}
+ gtt_slot = psb_gtt_entry(dev, r);
+ pages = r->pages;
-static int
-psb_gtt_mm_get_mem_mapping_locked(struct drm_open_hash *ht,
- u32 key,
- struct psb_gtt_mem_mapping **hentry)
-{
- struct drm_hash_item *entry;
- struct psb_gtt_mem_mapping *mapping;
- int ret;
-
- ret = drm_ht_find_item(ht, key, &entry);
- if (ret) {
- DRM_DEBUG("Cannot find key %ld\n", key);
- return ret;
+ /* Write our page entries into the GART itself */
+ for (i = 0; i < numpages; i++) {
+ pte = psb_gtt_mask_pte(page_to_pfn(*pages++), 0/*type*/);
+ iowrite32(pte, gtt_slot++);
}
-
- mapping = container_of(entry, struct psb_gtt_mem_mapping, item);
- if (!mapping) {
- DRM_DEBUG("Invalid entry\n");
- return -EINVAL;
- }
-
- *hentry = mapping;
- return 0;
-}
-
-static int
-psb_gtt_mm_insert_mem_mapping_locked(struct drm_open_hash *ht,
- u32 key,
- struct psb_gtt_mem_mapping *hentry)
-{
- struct drm_hash_item *item;
- struct psb_gtt_hash_entry *entry;
- int ret;
-
- if (!hentry) {
- DRM_DEBUG("hentry is NULL\n");
- return -EINVAL;
- }
-
- item = &hentry->item;
- item->key = key;
-
- ret = drm_ht_insert_item(ht, item);
- if (ret) {
- DRM_DEBUG("insert_item failed\n");
- return ret;
- }
-
- entry = container_of(ht, struct psb_gtt_hash_entry, ht);
- if (entry)
- entry->count++;
+ /* Make sure all the entries are set before we return */
+ ioread32(gtt_slot - 1);
+
+ r->in_gart = 1;
return 0;
}
-static int
-psb_gtt_mm_alloc_insert_mem_mapping(struct psb_gtt_mm *mm,
- struct drm_open_hash *ht,
- u32 key,
- struct drm_mm_node *node,
- struct psb_gtt_mem_mapping **entry)
-{
- struct psb_gtt_mem_mapping *mapping;
- int ret;
-
- if (!node || !ht) {
- DRM_DEBUG("parameter error\n");
- return -EINVAL;
- }
-
- /*try to get this mem_map */
- spin_lock(&mm->lock);
- ret = psb_gtt_mm_get_mem_mapping_locked(ht, key, &mapping);
- if (!ret) {
- DRM_DEBUG("mapping entry for key %ld exists, entry %p\n",
- key, mapping);
- *entry = mapping;
- spin_unlock(&mm->lock);
- return 0;
- }
- spin_unlock(&mm->lock);
-
- DRM_DEBUG("Mapping entry for key %ld doesn't exist, will create it\n",
- key);
-
- mapping = kzalloc(sizeof(struct psb_gtt_mem_mapping), GFP_KERNEL);
- if (!mapping) {
- DRM_DEBUG("kmalloc failed\n");
- return -ENOMEM;
- }
-
- mapping->node = node;
-
- spin_lock(&mm->lock);
- ret = psb_gtt_mm_insert_mem_mapping_locked(ht, key, mapping);
- spin_unlock(&mm->lock);
-
- if (!ret)
- *entry = mapping;
-
- return ret;
-}
-
-static struct psb_gtt_mem_mapping *
-psb_gtt_mm_remove_mem_mapping_locked(struct drm_open_hash *ht, u32 key)
-{
- struct psb_gtt_mem_mapping *tmp;
- struct psb_gtt_hash_entry *entry;
- int ret;
-
- ret = psb_gtt_mm_get_mem_mapping_locked(ht, key, &tmp);
- if (ret) {
- DRM_DEBUG("Cannot find key %ld\n", key);
- return NULL;
- }
-
- drm_ht_remove_item(ht, &tmp->item);
-
- entry = container_of(ht, struct psb_gtt_hash_entry, ht);
- if (entry)
- entry->count--;
-
- return tmp;
-}
-
-static int psb_gtt_mm_remove_free_mem_mapping_locked(struct drm_open_hash *ht,
- u32 key,
- struct drm_mm_node **node)
-{
- struct psb_gtt_mem_mapping *entry;
-
- entry = psb_gtt_mm_remove_mem_mapping_locked(ht, key);
- if (!entry) {
- DRM_DEBUG("entry is NULL\n");
- return -EINVAL;
- }
-
- *node = entry->node;
-
- kfree(entry);
- return 0;
-}
+/**
+ * psb_gtt_remove - remove an object from the GART
+ * @dev: our DRM device
+ * @r: our GTT range
+ *
+ * Remove a preallocated GTT range from the GART. Overwrite all the
+ * page table entries with the dummy page
+ */
-static int psb_gtt_add_node(struct psb_gtt_mm *mm,
- u32 tgid,
- u32 key,
- struct drm_mm_node *node,
- struct psb_gtt_mem_mapping **entry)
+void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r)
{
- struct psb_gtt_hash_entry *hentry;
- struct psb_gtt_mem_mapping *mapping;
- int ret;
-
- ret = psb_gtt_mm_alloc_insert_ht(mm, tgid, &hentry);
- if (ret) {
- DRM_DEBUG("alloc_insert failed\n");
- return ret;
- }
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ u32 *gtt_slot, pte;
+ int numpages = (r->resource.end + 1 - r->resource.start) >> PAGE_SHIFT;
+ int i;
- ret = psb_gtt_mm_alloc_insert_mem_mapping(mm,
- &hentry->ht,
- key,
- node,
- &mapping);
- if (ret) {
- DRM_DEBUG("mapping alloc_insert failed\n");
- return ret;
- }
+ if (r->stolen)
+ return;
+ WARN_ON(!r->in_gart);
- *entry = mapping;
+ gtt_slot = psb_gtt_entry(dev, r);
+ pte = psb_gtt_mask_pte(page_to_pfn(dev_priv->scratch_page), 0);;
- return 0;
+ for (i = 0; i < numpages; i++)
+ iowrite32(pte, gtt_slot++);
+ ioread32(gtt_slot - 1);
+
+ r->in_gart = 0;
}
-static int psb_gtt_remove_node(struct psb_gtt_mm *mm,
- u32 tgid,
- u32 key,
- struct drm_mm_node **node)
+/**
+ * psb_gtt_attach_pages - attach and pin GEM pages
+ * @gt: the gtt range
+ *
+ * Pin and build an in kernel list of the pages that back our GEM object.
+ * While we hold this the pages cannot be swapped out
+ */
+int psb_gtt_attach_pages(struct gtt_range *gt)
{
- struct psb_gtt_hash_entry *hentry;
- struct drm_mm_node *tmp;
- int ret;
-
- spin_lock(&mm->lock);
- ret = psb_gtt_mm_get_ht_by_pid_locked(mm, tgid, &hentry);
- if (ret) {
- DRM_DEBUG("Cannot find entry for pid %ld\n", tgid);
- spin_unlock(&mm->lock);
- return ret;
- }
- spin_unlock(&mm->lock);
-
- /*remove mapping entry*/
- spin_lock(&mm->lock);
- ret = psb_gtt_mm_remove_free_mem_mapping_locked(&hentry->ht,
- key,
- &tmp);
- if (ret) {
- DRM_DEBUG("remove_free failed\n");
- spin_unlock(&mm->lock);
- return ret;
- }
+ struct inode *inode;
+ struct address_space *mapping;
+ int i;
+ struct page *p;
+ int pages = (gt->resource.end + 1 - gt->resource.start) >> PAGE_SHIFT;
- *node = tmp;
+ WARN_ON(gt->pages);
- /*check the count of mapping entry*/
- if (!hentry->count) {
- DRM_DEBUG("count of mapping entry is zero, tgid=%ld\n", tgid);
- psb_gtt_mm_remove_free_ht_locked(mm, tgid);
- }
-
- spin_unlock(&mm->lock);
-
- return 0;
-}
-
-static int psb_gtt_mm_alloc_mem(struct psb_gtt_mm *mm,
- uint32_t pages,
- uint32_t align,
- struct drm_mm_node **node)
-{
- struct drm_mm_node *tmp_node;
- int ret;
+ /* This is the shared memory object that backs the GEM resource */
+ inode = gt->gem.filp->f_path.dentry->d_inode;
+ mapping = inode->i_mapping;
- do {
- ret = drm_mm_pre_get(&mm->base);
- if (unlikely(ret)) {
- DRM_DEBUG("drm_mm_pre_get error\n");
- return ret;
- }
-
- spin_lock(&mm->lock);
- tmp_node = drm_mm_search_free(&mm->base, pages, align, 1);
- if (unlikely(!tmp_node)) {
- DRM_DEBUG("No free node found\n");
- spin_unlock(&mm->lock);
- break;
- }
-
- tmp_node = drm_mm_get_block_atomic(tmp_node, pages, align);
- spin_unlock(&mm->lock);
- } while (!tmp_node);
-
- if (!tmp_node) {
- DRM_DEBUG("Node allocation failed\n");
+ gt->pages = kmalloc(pages * sizeof(struct page *), GFP_KERNEL);
+ if (gt->pages == NULL)
return -ENOMEM;
+ for (i = 0; i < pages; i++) {
+ /* FIXME: review flags later */
+ p = read_cache_page_gfp(mapping, i,
+ __GFP_COLD | GFP_KERNEL);
+ if (IS_ERR(p))
+ goto err;
+ gt->pages[i] = p;
}
-
- *node = tmp_node;
return 0;
-}
-static void psb_gtt_mm_free_mem(struct psb_gtt_mm *mm, struct drm_mm_node *node)
-{
- spin_lock(&mm->lock);
- drm_mm_put_block(node);
- spin_unlock(&mm->lock);
+err:
+ while (i--)
+ page_cache_release(gt->pages[i]);
+ kfree(gt->pages);
+ gt->pages = NULL;
+ return PTR_ERR(p);
}
-int psb_gtt_map_meminfo(struct drm_device *dev,
- void *hKernelMemInfo,
- uint32_t *offset)
+/**
+ * psb_gtt_detach_pages - attach and pin GEM pages
+ * @gt: the gtt range
+ *
+ * Undo the effect of psb_gtt_attach_pages. At this point the pages
+ * must have been removed from the GART as they could now be paged out
+ * and move bus address.
+ */
+void psb_gtt_detach_pages(struct gtt_range *gt)
{
- return -EINVAL;
- /* FIXMEAC */
-#if 0
- struct drm_psb_private *dev_priv
- = (struct drm_psb_private *)dev->dev_private;
- void *psKernelMemInfo;
- struct psb_gtt_mm *mm = dev_priv->gtt_mm;
- struct psb_gtt *pg = dev_priv->pg;
- uint32_t size, pages, offset_pages;
- void *kmem;
- struct drm_mm_node *node;
- struct page **page_list;
- struct psb_gtt_mem_mapping *mapping = NULL;
- int ret;
-
- ret = psb_get_meminfo_by_handle(hKernelMemInfo, &psKernelMemInfo);
- if (ret) {
- DRM_DEBUG("Cannot find kernelMemInfo handle %ld\n",
- hKernelMemInfo);
- return -EINVAL;
- }
-
- DRM_DEBUG("Got psKernelMemInfo %p for handle %lx\n",
- psKernelMemInfo, (u32)hKernelMemInfo);
- size = psKernelMemInfo->ui32AllocSize;
- kmem = psKernelMemInfo->pvLinAddrKM;
- pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
-
- DRM_DEBUG("KerMemInfo size %ld, cpuVadr %lx, pages %ld, osMemHdl %lx\n",
- size, kmem, pages, psKernelMemInfo->sMemBlk.hOSMemHandle);
-
- if (!kmem)
- DRM_DEBUG("kmem is NULL");
-
- /*get pages*/
- ret = psb_get_pages_by_mem_handle(psKernelMemInfo->sMemBlk.hOSMemHandle,
- &page_list);
- if (ret) {
- DRM_DEBUG("get pages error\n");
- return ret;
- }
+ int i;
+ int pages = (gt->resource.end + 1 - gt->resource.start) >> PAGE_SHIFT;
- DRM_DEBUG("get %ld pages\n", pages);
+ WARN_ON(gt->in_gart);
- /*alloc memory in TT apeture*/
- ret = psb_gtt_mm_alloc_mem(mm, pages, 0, &node);
- if (ret) {
- DRM_DEBUG("alloc TT memory error\n");
- goto failed_pages_alloc;
+ for (i = 0; i < pages; i++) {
+ /* FIXME: do we need to force dirty */
+ set_page_dirty(gt->pages[i]);
+ /* Undo the reference we took when populating the table */
+ page_cache_release(gt->pages[i]);
}
-
- /*update psb_gtt_mm*/
- ret = psb_gtt_add_node(mm,
- task_tgid_nr(current),
- (u32)hKernelMemInfo,
- node,
- &mapping);
- if (ret) {
- DRM_DEBUG("add_node failed");
- goto failed_add_node;
- }
-
- node = mapping->node;
- offset_pages = node->start;
-
- DRM_DEBUG("get free node for %ld pages, offset %ld pages",
- pages, offset_pages);
-
- /*update gtt*/
- psb_gtt_insert_pages(pg, page_list,
- (unsigned)offset_pages,
- (unsigned)pages,
- 0,
- 0,
- 0);
-
- *offset = offset_pages;
- return 0;
-
-failed_add_node:
- psb_gtt_mm_free_mem(mm, node);
-failed_pages_alloc:
- kfree(page_list);
- return ret;
-#endif
-}
-
-int psb_gtt_unmap_meminfo(struct drm_device *dev, void * hKernelMemInfo)
-{
- struct drm_psb_private *dev_priv
- = (struct drm_psb_private *)dev->dev_private;
- struct psb_gtt_mm *mm = dev_priv->gtt_mm;
- struct psb_gtt *pg = dev_priv->pg;
- uint32_t pages, offset_pages;
- struct drm_mm_node *node;
- int ret;
-
- ret = psb_gtt_remove_node(mm,
- task_tgid_nr(current),
- (u32)hKernelMemInfo,
- &node);
- if (ret) {
- DRM_DEBUG("remove node failed\n");
- return ret;
- }
-
- /*remove gtt entries*/
- offset_pages = node->start;
- pages = node->size;
-
- psb_gtt_remove_pages(pg, offset_pages, pages, 0, 0, 1);
-
-
- /*free tt node*/
-
- psb_gtt_mm_free_mem(mm, node);
- return 0;
+ kfree(gt->pages);
+ gt->pages = NULL;
}
/*
@@ -941,10 +261,14 @@ struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
return NULL;
}
+
static void psb_gtt_destroy(struct kref *kref)
{
struct gtt_range *gt = container_of(kref, struct gtt_range, kref);
- WARN_ON(gt->in_gart && !gt->stolen);
+ if (gt->in_gart && !gt->stolen)
+ psb_gtt_remove(gt->gem.dev, gt);
+ if (gt->pages)
+ psb_gtt_detach_pages(gt);
release_resource(>->resource);
kfree(gt);
}
@@ -971,3 +295,171 @@ void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt)
{
psb_gtt_kref_put(gt);
}
+
+
+struct psb_gtt *psb_gtt_alloc(struct drm_device *dev)
+{
+ struct psb_gtt *tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
+
+ if (!tmp)
+ return NULL;
+
+ init_rwsem(&tmp->sem);
+ tmp->dev = dev;
+
+ return tmp;
+}
+
+void psb_gtt_takedown(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+
+ /* FIXME: iounmap dev_priv->vram_addr etc */
+ if (dev_priv->gtt_map) {
+ iounmap(dev_priv->gtt_map);
+ dev_priv->gtt_map = NULL;
+ }
+ if (dev_priv->gtt_initialized) {
+ pci_write_config_word(dev->pdev, PSB_GMCH_CTRL,
+ dev_priv->gmch_ctrl);
+ PSB_WVDC32(dev_priv->pge_ctl, PSB_PGETBL_CTL);
+ (void) PSB_RVDC32(PSB_PGETBL_CTL);
+ }
+ kfree(dev_priv->pg);
+ dev_priv->pg = NULL;
+}
+
+int psb_gtt_init(struct drm_device *dev, int resume)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ unsigned gtt_pages;
+ unsigned long stolen_size, vram_stolen_size;
+ unsigned i, num_pages;
+ unsigned pfn_base;
+ uint32_t vram_pages;
+ uint32_t tt_pages;
+ uint32_t *ttm_gtt_map;
+ uint32_t dvmt_mode = 0;
+ struct psb_gtt *pg;
+
+ int ret = 0;
+ uint32_t pte;
+
+ dev_priv->pg = pg = psb_gtt_alloc(dev);
+ if (pg == NULL)
+ return -ENOMEM;
+
+ pci_read_config_word(dev->pdev, PSB_GMCH_CTRL, &dev_priv->gmch_ctrl);
+ pci_write_config_word(dev->pdev, PSB_GMCH_CTRL,
+ dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED);
+
+ dev_priv->pge_ctl = PSB_RVDC32(PSB_PGETBL_CTL);
+ PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL);
+ (void) PSB_RVDC32(PSB_PGETBL_CTL);
+
+ /* The root resource we allocate address space from */
+ dev_priv->gtt_mem = &dev->pdev->resource[PSB_GATT_RESOURCE];
+
+ dev_priv->gtt_initialized = 1;
+
+ pg->gtt_phys_start = dev_priv->pge_ctl & PAGE_MASK;
+
+ pg->gatt_start = pci_resource_start(dev->pdev, PSB_GATT_RESOURCE);
+ /* fix me: video mmu has hw bug to access 0x0D0000000,
+ * then make gatt start at 0x0e000,0000 */
+ pg->mmu_gatt_start = 0xE0000000;
+ pg->gtt_start = pci_resource_start(dev->pdev, PSB_GTT_RESOURCE);
+ gtt_pages =
+ pci_resource_len(dev->pdev, PSB_GTT_RESOURCE) >> PAGE_SHIFT;
+ pg->gatt_pages = pci_resource_len(dev->pdev, PSB_GATT_RESOURCE)
+ >> PAGE_SHIFT;
+
+ pci_read_config_dword(dev->pdev, PSB_BSM, &dev_priv->stolen_base);
+ vram_stolen_size = pg->gtt_phys_start - dev_priv->stolen_base - PAGE_SIZE;
+
+ stolen_size = vram_stolen_size;
+
+ printk(KERN_INFO"GMMADR(region 0) start: 0x%08x (%dM).\n",
+ pg->gatt_start, pg->gatt_pages/256);
+ printk(KERN_INFO"GTTADR(region 3) start: 0x%08x (can map %dM RAM), and actual RAM base 0x%08x.\n",
+ pg->gtt_start, gtt_pages * 4, pg->gtt_phys_start);
+ printk(KERN_INFO "Stolen memory information\n");
+ printk(KERN_INFO " base in RAM: 0x%x\n", dev_priv->stolen_base);
+ printk(KERN_INFO " size: %luK, calculated by (GTT RAM base) - (Stolen base), seems wrong\n",
+ vram_stolen_size/1024);
+ dvmt_mode = (dev_priv->gmch_ctrl >> 4) & 0x7;
+ printk(KERN_INFO " the correct size should be: %dM(dvmt mode=%d)\n",
+ (dvmt_mode == 1) ? 1 : (2 << (dvmt_mode - 1)), dvmt_mode);
+
+ if (resume && (gtt_pages != pg->gtt_pages) &&
+ (stolen_size != pg->stolen_size)) {
+ DRM_ERROR("GTT resume error.\n");
+ ret = -EINVAL;
+ goto out_err;
+ }
+
+ pg->gtt_pages = gtt_pages;
+ pg->stolen_size = stolen_size;
+ dev_priv->vram_stolen_size = vram_stolen_size;
+ dev_priv->gtt_map =
+ ioremap_nocache(pg->gtt_phys_start, gtt_pages << PAGE_SHIFT);
+ if (!dev_priv->gtt_map) {
+ DRM_ERROR("Failure to map gtt.\n");
+ ret = -ENOMEM;
+ goto out_err;
+ }
+
+ dev_priv->vram_addr = ioremap_wc(dev_priv->stolen_base, stolen_size);
+ if (!dev_priv->vram_addr) {
+ DRM_ERROR("Failure to map stolen base.\n");
+ ret = -ENOMEM;
+ goto out_err;
+ }
+
+ DRM_DEBUG("%s: vram kernel virtual address %p\n", dev_priv->vram_addr);
+
+ tt_pages = (pg->gatt_pages < PSB_TT_PRIV0_PLIMIT) ?
+ (pg->gatt_pages) : PSB_TT_PRIV0_PLIMIT;
+
+ ttm_gtt_map = dev_priv->gtt_map + tt_pages / 2;
+
+ /*
+ * insert vram stolen pages.
+ */
+
+ pfn_base = dev_priv->stolen_base >> PAGE_SHIFT;
+ vram_pages = num_pages = vram_stolen_size >> PAGE_SHIFT;
+ printk(KERN_INFO"Set up %d stolen pages starting at 0x%08x, GTT offset %dK\n",
+ num_pages, pfn_base, 0);
+ for (i = 0; i < num_pages; ++i) {
+ pte = psb_gtt_mask_pte(pfn_base + i, 0);
+ iowrite32(pte, dev_priv->gtt_map + i);
+ }
+
+ /*
+ * Init rest of gtt managed by IMG.
+ */
+ pfn_base = page_to_pfn(dev_priv->scratch_page);
+ pte = psb_gtt_mask_pte(pfn_base, 0);
+ for (; i < tt_pages / 2 - 1; ++i)
+ iowrite32(pte, dev_priv->gtt_map + i);
+
+ /*
+ * Init rest of gtt managed by TTM.
+ */
+
+ pfn_base = page_to_pfn(dev_priv->scratch_page);
+ pte = psb_gtt_mask_pte(pfn_base, 0);
+ PSB_DEBUG_INIT("Initializing the rest of a total "
+ "of %d gtt pages.\n", pg->gatt_pages);
+
+ for (; i < pg->gatt_pages - tt_pages / 2; ++i)
+ iowrite32(pte, ttm_gtt_map + i);
+ (void) ioread32(dev_priv->gtt_map + i - 1);
+
+ return 0;
+
+out_err:
+ psb_gtt_takedown(dev);
+ return ret;
+}
diff --git a/drivers/staging/gma500/psb_gtt.h b/drivers/staging/gma500/psb_gtt.h
index 1b5bec0..b5d6530 100644
--- a/drivers/staging/gma500/psb_gtt.h
+++ b/drivers/staging/gma500/psb_gtt.h
@@ -22,66 +22,22 @@
#include <drm/drmP.h>
-/*#include "img_types.h"*/
-
struct psb_gtt {
struct drm_device *dev;
- int initialized;
uint32_t gatt_start;
uint32_t mmu_gatt_start;
uint32_t gtt_start;
uint32_t gtt_phys_start;
unsigned gtt_pages;
unsigned gatt_pages;
- uint32_t stolen_base;
- void *vram_addr;
- uint32_t pge_ctl;
- u16 gmch_ctrl;
unsigned long stolen_size;
unsigned long vram_stolen_size;
- uint32_t *gtt_map;
struct rw_semaphore sem;
};
-struct psb_gtt_mm {
- struct drm_mm base;
- struct drm_open_hash hash;
- uint32_t count;
- spinlock_t lock;
-};
-
-struct psb_gtt_hash_entry {
- struct drm_open_hash ht;
- uint32_t count;
- struct drm_hash_item item;
-};
-
-struct psb_gtt_mem_mapping {
- struct drm_mm_node *node;
- struct drm_hash_item item;
-};
-
/*Exported functions*/
-extern int psb_gtt_init(struct psb_gtt *pg, int resume);
-extern int psb_gtt_insert_pages(struct psb_gtt *pg, struct page **pages,
- unsigned offset_pages, unsigned num_pages,
- unsigned desired_tile_stride,
- unsigned hw_tile_stride, int type);
-extern int psb_gtt_remove_pages(struct psb_gtt *pg, unsigned offset_pages,
- unsigned num_pages,
- unsigned desired_tile_stride,
- unsigned hw_tile_stride,
- int rc_prot);
-
-extern struct psb_gtt *psb_gtt_alloc(struct drm_device *dev);
-extern void psb_gtt_takedown(struct psb_gtt *pg, int free);
-extern int psb_gtt_map_meminfo(struct drm_device *dev,
- void * hKernelMemInfo,
- uint32_t *offset);
-extern int psb_gtt_unmap_meminfo(struct drm_device *dev,
- void * hKernelMemInfo);
-extern int psb_gtt_mm_init(struct psb_gtt *pg);
-extern void psb_gtt_mm_takedown(void);
+extern int psb_gtt_init(struct drm_device *dev, int resume);
+extern void psb_gtt_takedown(struct drm_device *dev);
/* Each gtt_range describes an allocation in the GTT area */
struct gtt_range {
@@ -91,8 +47,12 @@ struct gtt_range {
struct drm_gem_object gem; /* GEM high level stuff */
int in_gart; /* Currently in the GART */
int stolen; /* Backed from stolen RAM */
+ struct page **pages; /* Backing pages if present */
};
+extern int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r);
+extern void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r);
+
extern struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
const char *name, int backed);
extern void psb_gtt_kref_put(struct gtt_range *gt);
diff --git a/drivers/staging/gma500/psb_intel_display.c b/drivers/staging/gma500/psb_intel_display.c
index b462f32..6e14657 100644
--- a/drivers/staging/gma500/psb_intel_display.c
+++ b/drivers/staging/gma500/psb_intel_display.c
@@ -1014,6 +1014,8 @@ static void psb_intel_crtc_restore(struct drm_crtc *crtc)
REG_WRITE(paletteReg + (i << 2), crtc_state->savePalette[i]);
}
+#if 0
+/* FIXME */
static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
struct drm_file *file_priv,
uint32_t handle,
@@ -1092,7 +1094,7 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
addr = page_offset << PAGE_SHIFT;
- addr += pg->stolen_base;
+ addr += dev_priv->stolen_base;
psb_intel_crtc->cursor_addr = addr;
@@ -1146,6 +1148,7 @@ static int psb_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
}
return 0;
}
+#endif
static void psb_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red,
u16 *green, u16 *blue, uint32_t type, uint32_t size)
@@ -1329,8 +1332,10 @@ static const struct drm_crtc_helper_funcs psb_intel_helper_funcs = {
const struct drm_crtc_funcs psb_intel_crtc_funcs = {
.save = psb_intel_crtc_save,
.restore = psb_intel_crtc_restore,
+/* FIXME
.cursor_set = psb_intel_crtc_cursor_set,
.cursor_move = psb_intel_crtc_cursor_move,
+*/
.gamma_set = psb_intel_crtc_gamma_set,
.set_config = psb_crtc_set_config,
.destroy = psb_intel_crtc_destroy,
diff --git a/drivers/staging/gma500/psb_powermgmt.c b/drivers/staging/gma500/psb_powermgmt.c
index fc0ed7a..1495415 100644
--- a/drivers/staging/gma500/psb_powermgmt.c
+++ b/drivers/staging/gma500/psb_powermgmt.c
@@ -269,7 +269,6 @@ static void gma_resume_display(struct pci_dev *pdev)
{
struct drm_device *dev = pci_get_drvdata(pdev);
struct drm_psb_private *dev_priv = dev->dev_private;
- struct psb_gtt *pg = dev_priv->pg;
if (dev_priv->suspended == false)
return;
@@ -277,9 +276,9 @@ static void gma_resume_display(struct pci_dev *pdev)
/* turn on the display power island */
power_up(dev);
- PSB_WVDC32(pg->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL);
+ PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL);
pci_write_config_word(pdev, PSB_GMCH_CTRL,
- pg->gmch_ctrl | _PSB_GMCH_ENABLED);
+ dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED);
/* Don't reinitialize the GTT as it is unnecessary. The gtt is
* stored in memory so it will automatically be restored. All
diff --git a/drivers/staging/gma500/psb_pvr_glue.c b/drivers/staging/gma500/psb_pvr_glue.c
deleted file mode 100644
index da78946..0000000
--- a/drivers/staging/gma500/psb_pvr_glue.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2009, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include "psb_pvr_glue.h"
-
-/**
- * FIXME: should NOT use these file under env/linux directly
- */
-
-int psb_get_meminfo_by_handle(void *hKernelMemInfo,
- void **ppsKernelMemInfo)
-{
- return -EINVAL;
-#if 0
- void *psKernelMemInfo = IMG_NULL;
- PVRSRV_PER_PROCESS_DATA *psPerProc = IMG_NULL;
- PVRSRV_ERROR eError;
-
- psPerProc = PVRSRVPerProcessData(task_tgid_nr(current));
- eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
- (IMG_VOID *)&psKernelMemInfo,
- hKernelMemInfo,
- PVRSRV_HANDLE_TYPE_MEM_INFO);
- if (eError != PVRSRV_OK) {
- DRM_ERROR("Cannot find kernel meminfo for handle 0x%x\n",
- (u32)hKernelMemInfo);
- return -EINVAL;
- }
-
- *ppsKernelMemInfo = psKernelMemInfo;
-
- DRM_DEBUG("Got Kernel MemInfo for handle %lx\n",
- (u32)hKernelMemInfo);
- return 0;
-#endif
-}
-
-int psb_get_pages_by_mem_handle(void *hOSMemHandle, struct page ***pages)
-{
- return -EINVAL;
-#if 0
- LinuxMemArea *psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
- struct page **page_list;
- if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_ALLOC_PAGES) {
- DRM_ERROR("MemArea type is not LINUX_MEM_AREA_ALLOC_PAGES\n");
- return -EINVAL;
- }
-
- page_list = psLinuxMemArea->uData.sPageList.pvPageList;
- if (!page_list) {
- DRM_DEBUG("Page List is NULL\n");
- return -ENOMEM;
- }
-
- *pages = page_list;
- return 0;
-#endif
-}
diff --git a/drivers/staging/gma500/psb_pvr_glue.h b/drivers/staging/gma500/psb_pvr_glue.h
deleted file mode 100644
index dee8cb2..0000000
--- a/drivers/staging/gma500/psb_pvr_glue.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2009, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include "psb_drv.h"
-
-extern int psb_get_meminfo_by_handle(void * hKernelMemInfo,
- void **ppsKernelMemInfo);
-extern u32 psb_get_tgid(void);
-extern int psb_get_pages_by_mem_handle(void * hOSMemHandle,
- struct page ***pages);
This then kills off the old bo_ interfaces
Signed-off-by: Alan Cox <[email protected]>
---
drivers/staging/gma500/mrst_crtc.c | 15 +++++++--------
drivers/staging/gma500/psb_2d.c | 4 ++--
drivers/staging/gma500/psb_drm.h | 11 -----------
drivers/staging/gma500/psb_drv.c | 4 ++--
drivers/staging/gma500/psb_drv.h | 2 --
drivers/staging/gma500/psb_fb.c | 24 +++++-------------------
drivers/staging/gma500/psb_fb.h | 5 +----
drivers/staging/gma500/psb_intel_display.c | 14 +++++++-------
8 files changed, 24 insertions(+), 55 deletions(-)
diff --git a/drivers/staging/gma500/mrst_crtc.c b/drivers/staging/gma500/mrst_crtc.c
index 664d0e7..e4a0c03 100644
--- a/drivers/staging/gma500/mrst_crtc.c
+++ b/drivers/staging/gma500/mrst_crtc.c
@@ -530,9 +530,8 @@ int mrst_pipe_set_base(struct drm_crtc *crtc,
/* struct drm_i915_master_private *master_priv; */
struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
- struct psb_intel_mode_device *mode_dev = psb_intel_crtc->mode_dev;
int pipe = psb_intel_crtc->pipe;
- unsigned long Start, Offset;
+ unsigned long start, offset;
/* FIXME: check if we need this surely MRST is pipe 0 only */
int dspbase = (pipe == 0 ? DSPALINOFF : DSPBBASE);
int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF);
@@ -552,8 +551,8 @@ int mrst_pipe_set_base(struct drm_crtc *crtc,
if (!gma_power_begin(dev, true))
return 0;
- Start = mode_dev->bo_offset(dev, psbfb);
- Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
+ start = psbfb->gtt->offset;
+ offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
REG_WRITE(dspstride, crtc->fb->pitch);
@@ -581,14 +580,14 @@ int mrst_pipe_set_base(struct drm_crtc *crtc,
}
REG_WRITE(dspcntr_reg, dspcntr);
- DRM_DEBUG("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y);
+ DRM_DEBUG("Writing base %08lX %08lX %d %d\n", start, offset, x, y);
if (0 /* FIXMEAC - check what PSB needs */) {
- REG_WRITE(dspbase, Offset);
+ REG_WRITE(dspbase, offset);
REG_READ(dspbase);
- REG_WRITE(dspsurf, Start);
+ REG_WRITE(dspsurf, start);
REG_READ(dspsurf);
} else {
- REG_WRITE(dspbase, Start + Offset);
+ REG_WRITE(dspbase, start + offset);
REG_READ(dspbase);
}
diff --git a/drivers/staging/gma500/psb_2d.c b/drivers/staging/gma500/psb_2d.c
index 29959de..0bd834c 100644
--- a/drivers/staging/gma500/psb_2d.c
+++ b/drivers/staging/gma500/psb_2d.c
@@ -160,7 +160,7 @@ static void psbfb_fillrect_accel(struct fb_info *info,
if (!fb)
return;
- offset = psbfb->offset;
+ offset = psbfb->gtt->offset;
stride = fb->pitch;
switch (fb->depth) {
@@ -303,7 +303,7 @@ static void psbfb_copyarea_accel(struct fb_info *info,
if (!fb)
return;
- offset = psbfb->offset;
+ offset = psbfb->gtt->offset;
stride = fb->pitch;
switch (fb->depth) {
diff --git a/drivers/staging/gma500/psb_drm.h b/drivers/staging/gma500/psb_drm.h
index 28862c7..49ffdd5 100644
--- a/drivers/staging/gma500/psb_drm.h
+++ b/drivers/staging/gma500/psb_drm.h
@@ -219,17 +219,6 @@ struct drm_psb_register_rw_arg {
u32 subpicture_disable_mask;
};
-struct psb_gtt_mapping_arg {
- void *hKernelMemInfo;
- u32 offset_pages;
-};
-
-struct drm_psb_getpageaddrs_arg {
- u32 handle;
- unsigned long *page_addrs;
- unsigned long gtt_offset;
-};
-
/* Controlling the kernel modesetting buffers */
#define DRM_PSB_KMS_OFF 0x00
diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c
index f501cd7..01f6ed7 100644
--- a/drivers/staging/gma500/psb_drv.c
+++ b/drivers/staging/gma500/psb_drv.c
@@ -870,11 +870,11 @@ static int psb_mode_operation_ioctl(struct drm_device *dev, void *data,
psb_fb = to_psb_fb(drm_fb);
if (gma_power_begin(dev, 0)) {
- REG_WRITE(DSPASURF, psb_fb->offset);
+ REG_WRITE(DSPASURF, psb_fb->gtt->offset);
REG_READ(DSPASURF);
gma_power_end(dev);
} else {
- dev_priv->saveDSPASURF = psb_fb->offset;
+ dev_priv->saveDSPASURF = psb_fb->gtt->offset;
}
return 0;
diff --git a/drivers/staging/gma500/psb_drv.h b/drivers/staging/gma500/psb_drv.h
index 4c983ff..e19a454 100644
--- a/drivers/staging/gma500/psb_drv.h
+++ b/drivers/staging/gma500/psb_drv.h
@@ -35,8 +35,6 @@
/*Append new drm mode definition here, align with libdrm definition*/
#define DRM_MODE_SCALE_NO_SCALE 2
-extern struct ttm_bo_driver psb_ttm_bo_driver;
-
enum {
CHIP_PSB_8108 = 0,
CHIP_PSB_8109 = 1,
diff --git a/drivers/staging/gma500/psb_fb.c b/drivers/staging/gma500/psb_fb.c
index 4ea39d6..f36e83f 100644
--- a/drivers/staging/gma500/psb_fb.c
+++ b/drivers/staging/gma500/psb_fb.c
@@ -310,7 +310,7 @@ static struct fb_ops psbfb_ops = {
static struct drm_framebuffer *psb_framebuffer_create
(struct drm_device *dev, struct drm_mode_fb_cmd *r,
- void *mm_private)
+ struct gtt_range *gt)
{
struct psb_framebuffer *fb;
int ret;
@@ -326,7 +326,7 @@ static struct drm_framebuffer *psb_framebuffer_create
drm_helper_mode_fill_fb_struct(&fb->base, r);
- fb->mem = mm_private;
+ fb->gtt = gt;
return &fb->base;
@@ -380,7 +380,6 @@ static int psbfb_create(struct psb_fbdev *fbdev,
goto out_err1;
}
psbfb = to_psb_fb(fb);
- psbfb->size = size;
info = framebuffer_alloc(sizeof(struct psb_fbdev), device);
if (!info) {
@@ -524,7 +523,7 @@ int psb_fbdev_destroy(struct drm_device *dev, struct psb_fbdev *fbdev)
if (fbdev->psb_fb_helper.fbdev) {
info = fbdev->psb_fb_helper.fbdev;
- psb_gtt_free_range(dev, psbfb->mem);
+ psb_gtt_free_range(dev, psbfb->gtt);
unregister_framebuffer(info);
iounmap(info->screen_base);
framebuffer_release(info);
@@ -611,7 +610,7 @@ static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb,
unsigned int *handle)
{
struct psb_framebuffer *psbfb = to_psb_fb(fb);
- struct gtt_range *r = psbfb->mem;
+ struct gtt_range *r = psbfb->gtt;
return drm_gem_handle_create(file_priv, &r->gem, handle);
}
@@ -626,7 +625,7 @@ static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb)
{
struct drm_device *dev = fb->dev;
struct psb_framebuffer *psbfb = to_psb_fb(fb);
- struct gtt_range *r = psbfb->mem;
+ struct gtt_range *r = psbfb->gtt;
if (psbfb->fbdev)
psbfb_remove(dev, fb);
@@ -732,17 +731,6 @@ static void psb_setup_outputs(struct drm_device *dev)
}
}
-/* FIXME: rewrite this in terms of the gtt_range and GEM objects
- rather than faking them as we do now */
-
-static size_t psb_bo_offset(struct drm_device *dev, void *obj)
-{
- struct psb_framebuffer *psbfb
- = (struct psb_framebuffer *)obj;
-
- return (size_t)psbfb->offset;
-}
-
void psb_modeset_init(struct drm_device *dev)
{
struct drm_psb_private *dev_priv =
@@ -751,8 +739,6 @@ void psb_modeset_init(struct drm_device *dev)
int i;
PSB_DEBUG_ENTRY("\n");
- /* Init mm functions */
- mode_dev->bo_offset = psb_bo_offset;
drm_mode_config_init(dev);
diff --git a/drivers/staging/gma500/psb_fb.h b/drivers/staging/gma500/psb_fb.h
index b943a9f..c8ec0d6 100644
--- a/drivers/staging/gma500/psb_fb.h
+++ b/drivers/staging/gma500/psb_fb.h
@@ -32,10 +32,7 @@ struct psb_framebuffer {
struct drm_framebuffer base;
struct address_space *addr_space;
struct fb_info *fbdev;
- struct gtt_range *mem;
- void * hKernelMemInfo;
- uint32_t size;
- uint32_t offset;
+ struct gtt_range *gtt;
};
struct psb_fbdev {
diff --git a/drivers/staging/gma500/psb_intel_display.c b/drivers/staging/gma500/psb_intel_display.c
index 697e1c3..4d384d5 100644
--- a/drivers/staging/gma500/psb_intel_display.c
+++ b/drivers/staging/gma500/psb_intel_display.c
@@ -343,7 +343,7 @@ int psb_intel_pipe_set_base(struct drm_crtc *crtc,
struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
struct psb_intel_mode_device *mode_dev = psb_intel_crtc->mode_dev;
int pipe = psb_intel_crtc->pipe;
- unsigned long Start, Offset;
+ unsigned long start, offset;
int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE);
int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF);
int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE;
@@ -362,8 +362,8 @@ int psb_intel_pipe_set_base(struct drm_crtc *crtc,
if (!gma_power_begin(dev, true))
return 0;
- Start = mode_dev->bo_offset(dev, psbfb);
- Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
+ start = psbfb->gtt->offset;
+ offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
REG_WRITE(dspstride, crtc->fb->pitch);
@@ -391,14 +391,14 @@ int psb_intel_pipe_set_base(struct drm_crtc *crtc,
}
REG_WRITE(dspcntr_reg, dspcntr);
- DRM_DEBUG("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y);
+ DRM_DEBUG("Writing base %08lX %08lX %d %d\n", start, offset, x, y);
if (0 /* FIXMEAC - check what PSB needs */) {
- REG_WRITE(dspbase, Offset);
+ REG_WRITE(dspbase, offset);
REG_READ(dspbase);
- REG_WRITE(dspsurf, Start);
+ REG_WRITE(dspsurf, start);
REG_READ(dspsurf);
} else {
- REG_WRITE(dspbase, Start + Offset);
+ REG_WRITE(dspbase, start + offset);
REG_READ(dspbase);
}
Do a first pass over the cursor code and rework it to use GEM objects for
the cursor buffer as we need.
Signed-off-by: Alan Cox <[email protected]>
---
drivers/staging/gma500/psb_fb.c | 32 ++--------------
drivers/staging/gma500/psb_intel_display.c | 56 +++++++++++-----------------
drivers/staging/gma500/psb_intel_drv.h | 13 +------
3 files changed, 26 insertions(+), 75 deletions(-)
diff --git a/drivers/staging/gma500/psb_fb.c b/drivers/staging/gma500/psb_fb.c
index eaf960e..4ea39d6 100644
--- a/drivers/staging/gma500/psb_fb.c
+++ b/drivers/staging/gma500/psb_fb.c
@@ -732,39 +732,17 @@ static void psb_setup_outputs(struct drm_device *dev)
}
}
-/* FIXME: rewrite these in terms of the gtt_range and GEM objects
+/* FIXME: rewrite this in terms of the gtt_range and GEM objects
rather than faking them as we do now */
-static void *psb_bo_from_handle(struct drm_device *dev,
- struct drm_file *file_priv,
- unsigned int handle)
-{
- return NULL;
-}
-
-static size_t psb_bo_size(struct drm_device *dev, void *bof)
-{
- return 0;
-}
-
-static size_t psb_bo_offset(struct drm_device *dev, void *bof)
+static size_t psb_bo_offset(struct drm_device *dev, void *obj)
{
struct psb_framebuffer *psbfb
- = (struct psb_framebuffer *)bof;
+ = (struct psb_framebuffer *)obj;
return (size_t)psbfb->offset;
}
-static int psb_bo_pin_for_scanout(struct drm_device *dev, void *bo)
-{
- return 0;
-}
-
-static int psb_bo_unpin_for_scanout(struct drm_device *dev, void *bo)
-{
- return 0;
-}
-
void psb_modeset_init(struct drm_device *dev)
{
struct drm_psb_private *dev_priv =
@@ -774,11 +752,7 @@ void psb_modeset_init(struct drm_device *dev)
PSB_DEBUG_ENTRY("\n");
/* Init mm functions */
- mode_dev->bo_from_handle = psb_bo_from_handle;
- mode_dev->bo_size = psb_bo_size;
mode_dev->bo_offset = psb_bo_offset;
- mode_dev->bo_pin_for_scanout = psb_bo_pin_for_scanout;
- mode_dev->bo_unpin_for_scanout = psb_bo_unpin_for_scanout;
drm_mode_config_init(dev);
diff --git a/drivers/staging/gma500/psb_intel_display.c b/drivers/staging/gma500/psb_intel_display.c
index 6e14657..697e1c3 100644
--- a/drivers/staging/gma500/psb_intel_display.c
+++ b/drivers/staging/gma500/psb_intel_display.c
@@ -1014,8 +1014,6 @@ static void psb_intel_crtc_restore(struct drm_crtc *crtc)
REG_WRITE(paletteReg + (i << 2), crtc_state->savePalette[i]);
}
-#if 0
-/* FIXME */
static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
struct drm_file *file_priv,
uint32_t handle,
@@ -1024,17 +1022,14 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
struct drm_device *dev = crtc->dev;
struct drm_psb_private *dev_priv =
(struct drm_psb_private *)dev->dev_private;
- struct psb_gtt *pg = dev_priv->pg;
struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- struct psb_intel_mode_device *mode_dev = psb_intel_crtc->mode_dev;
int pipe = psb_intel_crtc->pipe;
uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR;
uint32_t base = (pipe == 0) ? CURABASE : CURBBASE;
uint32_t temp;
size_t addr = 0;
- uint32_t page_offset;
- size_t size;
- void *bo;
+ struct gtt_range *gt;
+ struct drm_gem_object *obj;
int ret;
DRM_DEBUG("\n");
@@ -1043,8 +1038,7 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
if (!handle) {
DRM_DEBUG("cursor off\n");
/* turn off the cursor */
- temp = 0;
- temp |= CURSOR_MODE_DISABLE;
+ temp = CURSOR_MODE_DISABLE;
if (gma_power_begin(dev, false)) {
REG_WRITE(control, temp);
@@ -1052,12 +1046,10 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
gma_power_end(dev);
}
- /* unpin the old bo */
- if (psb_intel_crtc->cursor_bo) {
- mode_dev->bo_unpin_for_scanout(dev,
- psb_intel_crtc->
- cursor_bo);
- psb_intel_crtc->cursor_bo = NULL;
+ /* Unpin the old GEM object */
+ if (psb_intel_crtc->cursor_obj) {
+ drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
+ psb_intel_crtc->cursor_obj = NULL;
}
return 0;
@@ -1069,15 +1061,11 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
return -EINVAL;
}
- bo = mode_dev->bo_from_handle(dev, file_priv, handle);
- if (!bo)
+ obj = drm_gem_object_lookup(dev, file_priv, handle);
+ if (!obj)
return -ENOENT;
- ret = mode_dev->bo_pin_for_scanout(dev, bo);
- if (ret)
- return ret;
- size = mode_dev->bo_size(dev, bo);
- if (size < width * height * 4) {
+ if (obj->size < width * height * 4) {
DRM_ERROR("buffer is to small\n");
return -ENOMEM;
}
@@ -1086,15 +1074,15 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
DRM_DEBUG("%s: map meminfo for hw cursor. handle %x\n",
__func__, handle);
- ret = psb_gtt_map_meminfo(dev, (void *)handle, &page_offset);
+/* Pin : FIXME
if (ret) {
DRM_ERROR("Can not map meminfo to GTT. handle 0x%x\n", handle);
return ret;
}
+*/
+ gt = container_of(obj, struct gtt_range, gem);
- addr = page_offset << PAGE_SHIFT;
-
- addr += dev_priv->stolen_base;
+ addr = gt->resource.start;
psb_intel_crtc->cursor_addr = addr;
@@ -1110,9 +1098,9 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
}
/* unpin the old bo */
- if (psb_intel_crtc->cursor_bo && psb_intel_crtc->cursor_bo != bo) {
- mode_dev->bo_unpin_for_scanout(dev, psb_intel_crtc->cursor_bo);
- psb_intel_crtc->cursor_bo = bo;
+ if (psb_intel_crtc->cursor_obj && psb_intel_crtc->cursor_obj != obj) {
+ drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
+ psb_intel_crtc->cursor_obj = obj;
}
return 0;
@@ -1124,7 +1112,7 @@ static int psb_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
int pipe = psb_intel_crtc->pipe;
uint32_t temp = 0;
- uint32_t adder;
+ uint32_t addr;
if (x < 0) {
@@ -1139,16 +1127,15 @@ static int psb_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT);
temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
- adder = psb_intel_crtc->cursor_addr;
+ addr = psb_intel_crtc->cursor_addr;
if (gma_power_begin(dev, false)) {
REG_WRITE((pipe == 0) ? CURAPOS : CURBPOS, temp);
- REG_WRITE((pipe == 0) ? CURABASE : CURBBASE, adder);
+ REG_WRITE((pipe == 0) ? CURABASE : CURBBASE, addr);
gma_power_end(dev);
}
return 0;
}
-#endif
static void psb_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red,
u16 *green, u16 *blue, uint32_t type, uint32_t size)
@@ -1315,6 +1302,7 @@ static void psb_intel_crtc_destroy(struct drm_crtc *crtc)
{
struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+ /* FIXME: do we need to put the final GEM cursor ? */
kfree(psb_intel_crtc->crtc_state);
drm_crtc_cleanup(crtc);
kfree(psb_intel_crtc);
@@ -1332,10 +1320,8 @@ static const struct drm_crtc_helper_funcs psb_intel_helper_funcs = {
const struct drm_crtc_funcs psb_intel_crtc_funcs = {
.save = psb_intel_crtc_save,
.restore = psb_intel_crtc_restore,
-/* FIXME
.cursor_set = psb_intel_crtc_cursor_set,
.cursor_move = psb_intel_crtc_cursor_move,
-*/
.gamma_set = psb_intel_crtc_gamma_set,
.set_config = psb_crtc_set_config,
.destroy = psb_intel_crtc_destroy,
diff --git a/drivers/staging/gma500/psb_intel_drv.h b/drivers/staging/gma500/psb_intel_drv.h
index f6229c5..6006ddd 100644
--- a/drivers/staging/gma500/psb_intel_drv.h
+++ b/drivers/staging/gma500/psb_intel_drv.h
@@ -76,13 +76,7 @@ struct psb_intel_mode_device {
/*
* Abstracted memory manager operations
*/
- void *(*bo_from_handle) (struct drm_device *dev,
- struct drm_file *file_priv,
- unsigned int handle);
- size_t(*bo_size) (struct drm_device *dev, void *bo);
size_t(*bo_offset) (struct drm_device *dev, void *bo);
- int (*bo_pin_for_scanout) (struct drm_device *dev, void *bo);
- int (*bo_unpin_for_scanout) (struct drm_device *dev, void *bo);
/*
* Cursor
@@ -156,11 +150,8 @@ struct psb_intel_crtc {
/* a mode_set for fbdev users on this crtc */
struct drm_mode_set mode_set;
- /* current bo we scanout from */
- void *scanout_bo;
-
- /* current bo we cursor from */
- void *cursor_bo;
+ /* GEM object that holds our cursor */
+ struct drm_gem_object *cursor_obj;
struct drm_display_mode saved_mode;
struct drm_display_mode saved_adjusted_mode;
Signed-off-by: Alan Cox <[email protected]>
---
drivers/staging/gma500/psb_gtt.c | 70 +++++++++++++++++++++-------
drivers/staging/gma500/psb_gtt.h | 13 ++---
drivers/staging/gma500/psb_intel_display.c | 33 ++++++++-----
3 files changed, 80 insertions(+), 36 deletions(-)
diff --git a/drivers/staging/gma500/psb_gtt.c b/drivers/staging/gma500/psb_gtt.c
index 090d30e..a991c12 100644
--- a/drivers/staging/gma500/psb_gtt.c
+++ b/drivers/staging/gma500/psb_gtt.c
@@ -66,7 +66,6 @@ u32 *psb_gtt_entry(struct drm_device *dev, struct gtt_range *r)
return dev_priv->gtt_map + (offset >> PAGE_SHIFT);
}
-
/**
* psb_gtt_insert - put an object into the GART
* @dev: our DRM device
@@ -77,21 +76,19 @@ u32 *psb_gtt_entry(struct drm_device *dev, struct gtt_range *r)
*
* FIXME: gtt lock ?
*/
-int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r)
+static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r)
{
u32 *gtt_slot, pte;
int numpages = (r->resource.end + 1 - r->resource.start) >> PAGE_SHIFT;
struct page **pages;
int i;
- if (r->stolen)
- return 0;
if (r->pages == NULL) {
WARN_ON(1);
return -EINVAL;
}
- WARN_ON(r->in_gart); /* refcount these maybe ? */
+ WARN_ON(r->stolen); /* refcount these maybe ? */
gtt_slot = psb_gtt_entry(dev, r);
pages = r->pages;
@@ -118,16 +115,14 @@ int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r)
* page table entries with the dummy page
*/
-void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r)
+static void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r)
{
struct drm_psb_private *dev_priv = dev->dev_private;
u32 *gtt_slot, pte;
int numpages = (r->resource.end + 1 - r->resource.start) >> PAGE_SHIFT;
int i;
- if (r->stolen)
- return;
- WARN_ON(!r->in_gart);
+ WARN_ON(r->stolen);
gtt_slot = psb_gtt_entry(dev, r);
pte = psb_gtt_mask_pte(page_to_pfn(dev_priv->scratch_page), 0);;
@@ -146,7 +141,7 @@ void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r)
* Pin and build an in kernel list of the pages that back our GEM object.
* While we hold this the pages cannot be swapped out
*/
-int psb_gtt_attach_pages(struct gtt_range *gt)
+static int psb_gtt_attach_pages(struct gtt_range *gt)
{
struct inode *inode;
struct address_space *mapping;
@@ -189,13 +184,11 @@ err:
* must have been removed from the GART as they could now be paged out
* and move bus address.
*/
-void psb_gtt_detach_pages(struct gtt_range *gt)
+static void psb_gtt_detach_pages(struct gtt_range *gt)
{
int i;
int pages = (gt->resource.end + 1 - gt->resource.start) >> PAGE_SHIFT;
- WARN_ON(gt->in_gart);
-
for (i = 0; i < pages; i++) {
/* FIXME: do we need to force dirty */
set_page_dirty(gt->pages[i]);
@@ -207,6 +200,50 @@ void psb_gtt_detach_pages(struct gtt_range *gt)
}
/*
+ * Manage pinning of resources into the GART
+ */
+
+int psb_gtt_pin(struct drm_device *dev, struct gtt_range *gt)
+{
+ int ret;
+ struct drm_psb_private *dev_priv = dev->dev_private;
+
+ mutex_lock(&dev_priv->gtt_mutex);
+
+ if (gt->in_gart == 0 && gt->stolen == 0) {
+ ret = psb_gtt_attach_pages(gt);
+ if (ret < 0)
+ goto out;
+ ret = psb_gtt_insert(dev, gt);
+ if (ret < 0) {
+ psb_gtt_detach_pages(gt);
+ goto out;
+ }
+ }
+ gt->in_gart++;
+out:
+ mutex_unlock(&dev_priv->gtt_mutex);
+ return ret;
+}
+
+void psb_gtt_unpin(struct drm_device *dev, struct gtt_range *gt)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+
+ mutex_lock(&dev_priv->gtt_mutex);
+
+ WARN_ON(!gt->in_gart);
+
+ gt->in_gart--;
+ if (gt->in_gart == 0 && gt->stolen == 0) {
+ psb_gtt_remove(dev, gt);
+ psb_gtt_detach_pages(gt);
+ }
+
+ mutex_unlock(&dev_priv->gtt_mutex);
+}
+
+/*
* GTT resource allocator - allocate and manage GTT address space
*/
@@ -265,10 +302,7 @@ struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
static void psb_gtt_destroy(struct kref *kref)
{
struct gtt_range *gt = container_of(kref, struct gtt_range, kref);
- if (gt->in_gart && !gt->stolen)
- psb_gtt_remove(gt->gem.dev, gt);
- if (gt->pages)
- psb_gtt_detach_pages(gt);
+ WARN_ON(gt->in_gart && !gt->stolen);
release_resource(>->resource);
kfree(gt);
}
@@ -345,6 +379,8 @@ int psb_gtt_init(struct drm_device *dev, int resume)
int ret = 0;
uint32_t pte;
+ mutex_init(&dev_priv->gtt_mutex);
+
dev_priv->pg = pg = psb_gtt_alloc(dev);
if (pg == NULL)
return -ENOMEM;
diff --git a/drivers/staging/gma500/psb_gtt.h b/drivers/staging/gma500/psb_gtt.h
index b5d6530..dc553e0 100644
--- a/drivers/staging/gma500/psb_gtt.h
+++ b/drivers/staging/gma500/psb_gtt.h
@@ -44,18 +44,17 @@ struct gtt_range {
struct resource resource;
u32 offset;
struct kref kref;
- struct drm_gem_object gem; /* GEM high level stuff */
- int in_gart; /* Currently in the GART */
- int stolen; /* Backed from stolen RAM */
- struct page **pages; /* Backing pages if present */
+ struct drm_gem_object gem; /* GEM high level stuff */
+ int in_gart; /* Currently in the GART (ref ct) */
+ bool stolen; /* Backed from stolen RAM */
+ struct page **pages; /* Backing pages if present */
};
-extern int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r);
-extern void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r);
-
extern struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
const char *name, int backed);
extern void psb_gtt_kref_put(struct gtt_range *gt);
extern void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt);
+extern int psb_gtt_pin(struct drm_device *dev, struct gtt_range *gt);
+extern void psb_gtt_unpin(struct drm_device *dev, struct gtt_range *gt);
#endif
diff --git a/drivers/staging/gma500/psb_intel_display.c b/drivers/staging/gma500/psb_intel_display.c
index 4d384d5..b5a36d2 100644
--- a/drivers/staging/gma500/psb_intel_display.c
+++ b/drivers/staging/gma500/psb_intel_display.c
@@ -341,7 +341,6 @@ int psb_intel_pipe_set_base(struct drm_crtc *crtc,
/* struct drm_i915_master_private *master_priv; */
struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
- struct psb_intel_mode_device *mode_dev = psb_intel_crtc->mode_dev;
int pipe = psb_intel_crtc->pipe;
unsigned long start, offset;
int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE);
@@ -1020,8 +1019,6 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
uint32_t width, uint32_t height)
{
struct drm_device *dev = crtc->dev;
- struct drm_psb_private *dev_priv =
- (struct drm_psb_private *)dev->dev_private;
struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
int pipe = psb_intel_crtc->pipe;
uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR;
@@ -1048,6 +1045,9 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
/* Unpin the old GEM object */
if (psb_intel_crtc->cursor_obj) {
+ gt = container_of(psb_intel_crtc->cursor_obj,
+ struct gtt_range, gem);
+ psb_gtt_unpin(crtc->dev, gt);
drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
psb_intel_crtc->cursor_obj = NULL;
}
@@ -1070,19 +1070,17 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
return -ENOMEM;
}
- /*insert this bo into gtt*/
- DRM_DEBUG("%s: map meminfo for hw cursor. handle %x\n",
- __func__, handle);
+ gt = container_of(obj, struct gtt_range, gem);
-/* Pin : FIXME
+ /* Pin the memory into the GTT */
+ ret = psb_gtt_pin(crtc->dev, gt);
if (ret) {
- DRM_ERROR("Can not map meminfo to GTT. handle 0x%x\n", handle);
+ DRM_ERROR("Can not pin down handle 0x%x\n", handle);
return ret;
}
-*/
- gt = container_of(obj, struct gtt_range, gem);
- addr = gt->resource.start;
+
+ addr = gt->offset; /* Or resource.start ??? */
psb_intel_crtc->cursor_addr = addr;
@@ -1099,6 +1097,9 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
/* unpin the old bo */
if (psb_intel_crtc->cursor_obj && psb_intel_crtc->cursor_obj != obj) {
+ gt = container_of(psb_intel_crtc->cursor_obj,
+ struct gtt_range, gem);
+ psb_gtt_unpin(crtc->dev, gt);
drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
psb_intel_crtc->cursor_obj = obj;
}
@@ -1301,8 +1302,16 @@ struct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev,
static void psb_intel_crtc_destroy(struct drm_crtc *crtc)
{
struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+ struct gtt_range *gt;
- /* FIXME: do we need to put the final GEM cursor ? */
+ /* Unpin the old GEM object */
+ if (psb_intel_crtc->cursor_obj) {
+ gt = container_of(psb_intel_crtc->cursor_obj,
+ struct gtt_range, gem);
+ psb_gtt_unpin(crtc->dev, gt);
+ drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
+ psb_intel_crtc->cursor_obj = NULL;
+ }
kfree(psb_intel_crtc->crtc_state);
drm_crtc_cleanup(crtc);
kfree(psb_intel_crtc);
Signed-off-by: Alan Cox <[email protected]>
---
drivers/staging/gma500/psb_intel_lvds.c | 14 +++++---------
1 files changed, 5 insertions(+), 9 deletions(-)
diff --git a/drivers/staging/gma500/psb_intel_lvds.c b/drivers/staging/gma500/psb_intel_lvds.c
index 28e04a3..b0a225b 100644
--- a/drivers/staging/gma500/psb_intel_lvds.c
+++ b/drivers/staging/gma500/psb_intel_lvds.c
@@ -32,13 +32,6 @@
#include "psb_powermgmt.h"
#include <linux/pm_runtime.h>
-/* MRST defines start */
-uint8_t blc_freq;
-uint8_t blc_minbrightness;
-uint8_t blc_i2caddr;
-uint8_t blc_brightnesscmd;
-int lvds_backlight; /* restore backlight to this value */
-
u32 CoreClock;
u32 PWMControlRegFreq;
@@ -97,8 +90,11 @@ static u32 psb_intel_lvds_get_max_backlight(struct drm_device *dev)
return retVal;
}
-/**
+/*
* Set LVDS backlight level by I2C command
+ *
+ * FIXME: at some point we need to both track this for PM and also
+ * disable runtime pm on MRST if the brightness is nil (ie blanked)
*/
static int psb_lvds_i2c_set_brightness(struct drm_device *dev,
unsigned int level)
@@ -131,7 +127,7 @@ static int psb_lvds_i2c_set_brightness(struct drm_device *dev,
if (i2c_transfer(&lvds_i2c_bus->adapter, msgs, 1) == 1) {
DRM_DEBUG("I2C set brightness.(command, value) (%d, %d)\n",
- blc_brightnesscmd,
+ dev_priv->lvds_bl->brightnesscmd,
blc_i2c_brightness);
return 0;
}
For Moorestown at least we may not have stolen RAM with which to back the
initial framebuffer. Allow a GEM backing.
At this point we should have all the bits in place needed to make it work once
it has been debugged.
Signed-off-by: Alan Cox <[email protected]>
---
drivers/staging/gma500/psb_fb.c | 43 ++++++++++++++++++++++++++--
drivers/staging/gma500/psb_gem.c | 2 +
drivers/staging/gma500/psb_gtt.c | 1 -
drivers/staging/gma500/psb_intel_display.c | 36 +++++++++++++++--------
4 files changed, 65 insertions(+), 17 deletions(-)
diff --git a/drivers/staging/gma500/psb_fb.c b/drivers/staging/gma500/psb_fb.c
index f36e83f..ae097cd 100644
--- a/drivers/staging/gma500/psb_fb.c
+++ b/drivers/staging/gma500/psb_fb.c
@@ -336,6 +336,38 @@ err:
}
/**
+ * psbfb_alloc - allocate frame buffer memory
+ * @dev: the DRM device
+ * @aligned_size: space needed
+ *
+ * Allocate the frame buffer. In the usual case we get a GTT range that
+ * is stolen memory backed and life is simple. If there isn't sufficient
+ * stolen memory or the system has no stolen memory we allocate a range
+ * and back it with a GEM object.
+ *
+ * In this case the GEM object has no handle.
+ */
+static struct gtt_range *psbfb_alloc(struct drm_device *dev, int aligned_size)
+{
+ struct gtt_range *backing;
+ /* Begin by trying to use stolen memory backing */
+ backing = psb_gtt_alloc_range(dev, aligned_size, "fb", 1);
+ if (backing)
+ return backing;
+ /* Next try using GEM host memory */
+ backing = psb_gtt_alloc_range(dev, aligned_size, "fb(gem)", 0);
+ if (backing == NULL)
+ return NULL;
+
+ /* Now back it with an object */
+ if (drm_gem_object_init(dev, &backing->gem, aligned_size) != 0) {
+ psb_gtt_free_range(dev, backing);
+ return NULL;
+ }
+ return backing;
+}
+
+/**
* psbfb_create - create a framebuffer
* @fbdev: the framebuffer device
* @sizes: specification of the layout
@@ -368,7 +400,7 @@ static int psbfb_create(struct psb_fbdev *fbdev,
aligned_size = ALIGN(size, PAGE_SIZE);
/* Allocate the framebuffer in the GTT with stolen page backing */
- backing = psb_gtt_alloc_range(dev, aligned_size, "fb", 1);
+ backing = psbfb_alloc(dev, aligned_size);
if (backing == NULL)
return -ENOMEM;
@@ -523,7 +555,13 @@ int psb_fbdev_destroy(struct drm_device *dev, struct psb_fbdev *fbdev)
if (fbdev->psb_fb_helper.fbdev) {
info = fbdev->psb_fb_helper.fbdev;
- psb_gtt_free_range(dev, psbfb->gtt);
+ /* FIXME: this is a bit more inside knowledge than I'd like
+ but I don't see how to make a fake GEM object of the
+ stolen space nicely */
+ if (psbfb->gtt->stolen)
+ psb_gtt_free_range(dev, psbfb->gtt);
+ else
+ drm_gem_object_unreference(&psbfb->gtt->gem);
unregister_framebuffer(info);
iounmap(info->screen_base);
framebuffer_release(info);
@@ -571,7 +609,6 @@ void psb_fbdev_fini(struct drm_device *dev)
dev_priv->fbdev = NULL;
}
-
static void psbfb_output_poll_changed(struct drm_device *dev)
{
struct drm_psb_private *dev_priv = dev->dev_private;
diff --git a/drivers/staging/gma500/psb_gem.c b/drivers/staging/gma500/psb_gem.c
index 0438bf4..d47c187 100644
--- a/drivers/staging/gma500/psb_gem.c
+++ b/drivers/staging/gma500/psb_gem.c
@@ -39,6 +39,8 @@ int psb_gem_init_object(struct drm_gem_object *obj)
void psb_gem_free_object(struct drm_gem_object *obj)
{
+ struct gtt_range *gtt = container_of(obj, struct gtt_range, gem);
+ psb_gtt_free_range(obj->dev, gtt);
drm_gem_object_release(obj);
}
diff --git a/drivers/staging/gma500/psb_gtt.c b/drivers/staging/gma500/psb_gtt.c
index a991c12..10d772a 100644
--- a/drivers/staging/gma500/psb_gtt.c
+++ b/drivers/staging/gma500/psb_gtt.c
@@ -298,7 +298,6 @@ struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
return NULL;
}
-
static void psb_gtt_destroy(struct kref *kref)
{
struct gtt_range *gt = container_of(kref, struct gtt_range, kref);
diff --git a/drivers/staging/gma500/psb_intel_display.c b/drivers/staging/gma500/psb_intel_display.c
index b5a36d2..9e1446f 100644
--- a/drivers/staging/gma500/psb_intel_display.c
+++ b/drivers/staging/gma500/psb_intel_display.c
@@ -361,7 +361,13 @@ int psb_intel_pipe_set_base(struct drm_crtc *crtc,
if (!gma_power_begin(dev, true))
return 0;
+ /* We are displaying this buffer, make sure it is actually loaded
+ into the GTT */
+ ret = psb_gtt_pin(dev, psbfb->gtt);
+ if (ret < 0)
+ goto psb_intel_pipe_set_base_exit;
start = psbfb->gtt->offset;
+
offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
REG_WRITE(dspstride, crtc->fb->pitch);
@@ -386,10 +392,12 @@ int psb_intel_pipe_set_base(struct drm_crtc *crtc,
default:
DRM_ERROR("Unknown color depth\n");
ret = -EINVAL;
+ psb_gtt_unpin(dev, psbfb->gtt);
goto psb_intel_pipe_set_base_exit;
}
REG_WRITE(dspcntr_reg, dspcntr);
+
DRM_DEBUG("Writing base %08lX %08lX %d %d\n", start, offset, x, y);
if (0 /* FIXMEAC - check what PSB needs */) {
REG_WRITE(dspbase, offset);
@@ -401,10 +409,12 @@ int psb_intel_pipe_set_base(struct drm_crtc *crtc,
REG_READ(dspbase);
}
-psb_intel_pipe_set_base_exit:
+ /* If there was a previous display we can now unpin it */
+ if (old_fb)
+ psb_gtt_unpin(dev, to_psb_fb(old_fb)->gtt);
+psb_intel_pipe_set_base_exit:
gma_power_end(dev);
-
return ret;
}
@@ -1037,7 +1047,7 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
/* turn off the cursor */
temp = CURSOR_MODE_DISABLE;
- if (gma_power_begin(dev, false)) {
+ if (gma_power_begin(dev, false)) {
REG_WRITE(control, temp);
REG_WRITE(base, 0);
gma_power_end(dev);
@@ -1045,8 +1055,8 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
/* Unpin the old GEM object */
if (psb_intel_crtc->cursor_obj) {
- gt = container_of(psb_intel_crtc->cursor_obj,
- struct gtt_range, gem);
+ gt = container_of(psb_intel_crtc->cursor_obj,
+ struct gtt_range, gem);
psb_gtt_unpin(crtc->dev, gt);
drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
psb_intel_crtc->cursor_obj = NULL;
@@ -1089,7 +1099,7 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
temp |= (pipe << 28);
temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
- if (gma_power_begin(dev, false)) {
+ if (gma_power_begin(dev, false)) {
REG_WRITE(control, temp);
REG_WRITE(base, addr);
gma_power_end(dev);
@@ -1097,8 +1107,8 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
/* unpin the old bo */
if (psb_intel_crtc->cursor_obj && psb_intel_crtc->cursor_obj != obj) {
- gt = container_of(psb_intel_crtc->cursor_obj,
- struct gtt_range, gem);
+ gt = container_of(psb_intel_crtc->cursor_obj,
+ struct gtt_range, gem);
psb_gtt_unpin(crtc->dev, gt);
drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
psb_intel_crtc->cursor_obj = obj;
@@ -1130,7 +1140,7 @@ static int psb_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
addr = psb_intel_crtc->cursor_addr;
- if (gma_power_begin(dev, false)) {
+ if (gma_power_begin(dev, false)) {
REG_WRITE((pipe == 0) ? CURAPOS : CURBPOS, temp);
REG_WRITE((pipe == 0) ? CURABASE : CURBBASE, addr);
gma_power_end(dev);
@@ -1183,7 +1193,7 @@ static int psb_intel_crtc_clock_get(struct drm_device *dev,
bool is_lvds;
struct drm_psb_private *dev_priv = dev->dev_private;
- if (gma_power_begin(dev, false)) {
+ if (gma_power_begin(dev, false)) {
dpll = REG_READ((pipe == 0) ? DPLL_A : DPLL_B);
if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
fp = REG_READ((pipe == 0) ? FPA0 : FPB0);
@@ -1262,7 +1272,7 @@ struct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev,
int vsync;
struct drm_psb_private *dev_priv = dev->dev_private;
- if (gma_power_begin(dev, false)) {
+ if (gma_power_begin(dev, false)) {
htot = REG_READ((pipe == 0) ? HTOTAL_A : HTOTAL_B);
hsync = REG_READ((pipe == 0) ? HSYNC_A : HSYNC_B);
vtot = REG_READ((pipe == 0) ? VTOTAL_A : VTOTAL_B);
@@ -1387,10 +1397,10 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe,
psb_intel_crtc->cursor_addr = 0;
if (IS_MRST(dev))
- drm_crtc_helper_add(&psb_intel_crtc->base,
+ drm_crtc_helper_add(&psb_intel_crtc->base,
&mrst_helper_funcs);
else
- drm_crtc_helper_add(&psb_intel_crtc->base,
+ drm_crtc_helper_add(&psb_intel_crtc->base,
&psb_intel_helper_funcs);
/* Setup the array of drm_connector pointer array */
On Tue, Apr 19, 2011 at 03:27:10PM +0100, Alan Cox wrote:
> We will will need this for doing a GEM allocator. It should also avoid any
> crashes with the current code if the stolen area is too small.
>
> Signed-off-by: Alan Cox <[email protected]>
What tree did you make this against?
When applying it, I get the following error from git:
Applying: gma500: add the ability to request backed space or not
/home/linux/linux/work/staging-2.6/.git/rebase-apply/patch:47: trailing whitespace.
error: patch failed: drivers/staging/gma500/psb_fb.c:479
error: drivers/staging/gma500/psb_fb.c: patch does not apply
error: patch failed: drivers/staging/gma500/psb_gtt.c:972
error: drivers/staging/gma500/psb_gtt.c: patch does not apply
error: patch failed: drivers/staging/gma500/psb_gtt.h:105
error: drivers/staging/gma500/psb_gtt.h: patch does not apply
Patch failed at 0001 gma500: add the ability to request backed space or not
Care to redo this series and resend them so I can apply them?
thanks,
greg k-h
On Wed, 20 Apr 2011 13:31:17 -0700
Greg KH <[email protected]> wrote:
> On Tue, Apr 19, 2011 at 03:27:10PM +0100, Alan Cox wrote:
> > We will will need this for doing a GEM allocator. It should also avoid any
> > crashes with the current code if the stolen area is too small.
> >
> > Signed-off-by: Alan Cox <[email protected]>
>
> What tree did you make this against?
Against -next and the previous patches I sent you. Have you been
stripping white space automatically again. That will break follow up
patches if so.
I'll try and take a look at it at some point but it may well be mid May.
Alan
On Wed, Apr 20, 2011 at 10:21:08PM +0100, Alan Cox wrote:
> On Wed, 20 Apr 2011 13:31:17 -0700
> Greg KH <[email protected]> wrote:
>
> > On Tue, Apr 19, 2011 at 03:27:10PM +0100, Alan Cox wrote:
> > > We will will need this for doing a GEM allocator. It should also avoid any
> > > crashes with the current code if the stolen area is too small.
> > >
> > > Signed-off-by: Alan Cox <[email protected]>
> >
> > What tree did you make this against?
>
> Against -next and the previous patches I sent you. Have you been
> stripping white space automatically again. That will break follow up
> patches if so.
Ok, I'm stupid, I missed that you sent me patches already for this
driver, and didn't apply them first. Sorry about that, I'll try it
again tomorrow when I have more sleep...
thanks,
greg k-h
On Wed, Apr 20, 2011 at 10:21:08PM +0100, Alan Cox wrote:
> On Wed, 20 Apr 2011 13:31:17 -0700
> Greg KH <[email protected]> wrote:
>
> > On Tue, Apr 19, 2011 at 03:27:10PM +0100, Alan Cox wrote:
> > > We will will need this for doing a GEM allocator. It should also avoid any
> > > crashes with the current code if the stolen area is too small.
> > >
> > > Signed-off-by: Alan Cox <[email protected]>
> >
> > What tree did you make this against?
>
> Against -next and the previous patches I sent you. Have you been
> stripping white space automatically again. That will break follow up
> patches if so.
No, I have not stripped any more whitespace since the first problems
that this caused on the driver.
thanks,
greg k-h
> > Against -next and the previous patches I sent you. Have you been
> > stripping white space automatically again. That will break follow up
> > patches if so.
>
> Ok, I'm stupid, I missed that you sent me patches already for this
ITYAM "my superhero powers seem to have faded slightly today"
> driver, and didn't apply them first. Sorry about that, I'll try it
> again tomorrow when I have more sleep...
Ok cool - that would explain it.
Alan
On Thu, Apr 21, 2011 at 09:49:09AM +0100, Alan Cox wrote:
> > > Against -next and the previous patches I sent you. Have you been
> > > stripping white space automatically again. That will break follow up
> > > patches if so.
> >
> > Ok, I'm stupid, I missed that you sent me patches already for this
>
> ITYAM "my superhero powers seem to have faded slightly today"
>
> > driver, and didn't apply them first. Sorry about that, I'll try it
> > again tomorrow when I have more sleep...
>
> Ok cool - that would explain it.
Yes, it worked when I applied the first round of patches first, they
should now all be queued up.
sorry for the noise,
greg k-h