Skip to contentSkip to conversation

gma500: Don't try and take a GEM handle of a non GEM fb

PATCH New Alan Cox 1 participant 2 messages May 13, 2011 Staging

lore
Share & tools
lore

Alan Cox

author
#0 lore raw

PATCH 1/2 gma500: Don't try and take a GEM handle of a non GEM fb

The initial GMA500 framebuffer is not GEM but stolen memory. We can't therefore take a GEM handle of it. Stop anyone trying to do this and causing a crash.

Ideally we need a way to have GEM handles to non GEM objects but it's not clear how and if GEM and the modesetting/fb interfaces it provides are supposed to or indeed if they can handle it.

---

 drivers/staging/gma500/psb_fb.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
drivers/staging/gma500/psb_fb.c +2 -0
index 32d3ea3..5028459 100644
@@ -667,6 +667,8 @@ static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb,
 {
         struct psb_framebuffer *psbfb = to_psb_fb(fb);
         struct gtt_range *r = psbfb->gtt;
+        if (r->stolen)
+                return -EOPNOTSUPP;
         return drm_gem_handle_create(file_priv, &r->gem, handle);
 }
 
author
#1 lore raw

PATCH 2/2 gma500: finish off the fault handler

GEM wants to mmap the object through the GTT (which avoids aliasing) so we need to put the object into the GTT before we provide the fault mapping for it.

While we are at it update the pin interface so that it digs dev out of the GEM object itself. This provides a rather cleaner API and call environment. Fix th refcount/on-off confusion in the pin API.

At this point we get a bit further with modetest but if we write to the new GEM mapping we hang solid and as yet I don't know why.

---

 drivers/staging/gma500/psb_gem.c           |   35 ++++++++++++++++-
 drivers/staging/gma500/psb_gtt.c           |   59 +++++++++++++++++++++++-----
 drivers/staging/gma500/psb_gtt.h           |    5 +-
 drivers/staging/gma500/psb_intel_display.c |   14 +++----
 4 files changed, 93 insertions(+), 20 deletions(-)
drivers/staging/gma500/psb_gem.c +34 -1
index 2132fe9..76ff7ba 100644
@@ -1,5 +1,5 @@
 /*
- *  psb backlight interface
+ *  psb GEM interface
  *
  * Copyright (c) 2011, Intel Corporation.
  *
@@ -251,6 +251,14 @@ int psb_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev,
  *	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.
+ *
+ *	To avoid aliasing and cache funnies we want to map the object
+ *	through the GART. For the moment this is slightly hackish. It would
+ *	be nicer if GEM provided mmap opened/closed hooks for us giving
+ *	the object so that we could track things nicely. That needs changes
+ *	to the core GEM code so must be tackled post staging
+ *
+ *	FIXME
  */
 int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
@@ -259,10 +267,28 @@ int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 	int ret;
 	unsigned long pfn;
 	pgoff_t page_offset;
+	struct drm_device *dev;
 
 	obj = vma->vm_private_data;	/* GEM object */
+	dev = obj->dev;
+
 	r = container_of(obj, struct gtt_range, gem);	/* Get the gtt range */
 
+	/* Make sure we don't parallel update on a fault, nor move or remove
+	   something from beneath our feet */
+	mutex_lock(&dev->struct_mutex);
+
+	/* For now the mmap pins the object and it stays pinned. As things
+	   stand that will do us no harm */
+	if (r->mmapping == 0) {
+		ret = psb_gtt_pin(r);
+		if (ret < 0) {
+		        DRM_ERROR("gma500: pin failed: %d\n", ret);
+		        goto fail;
+                }
+		r->mmapping = 1;
+	}
+
 	/* FIXME: Locking. We may also need to repack the GART sometimes */
 
 	/* Page relative to the VMA start */
@@ -273,7 +299,14 @@ int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 	/* Assumes gtt allocations are page aligned */
 	pfn = (r->resource.start >> PAGE_SHIFT) + page_offset;
 
+	pr_debug("Object GTT base at %p\n", (void *)(r->resource.start));
+	pr_debug("Inserting %p pfn %lx, pa %lx\n", vmf->virtual_address,
+	        pfn, pfn << PAGE_SHIFT);
+
 	ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn);
+
+fail:
+        mutex_unlock(&dev->struct_mutex);
 	switch (ret) {
 	case 0:
 	case -ERESTARTSYS:
drivers/staging/gma500/psb_gtt.c +49 -10

132 lines not on this page · raw message

drivers/staging/gma500/psb_gtt.h +3 -2
index dc553e0..535ae00 100644
@@ -47,6 +47,7 @@ struct gtt_range {
 	struct drm_gem_object gem;	/* GEM high level stuff */
 	int in_gart;			/* Currently in the GART (ref ct) */
         bool stolen;			/* Backed from stolen RAM */
+        bool mmapping;			/* Is mmappable */
 	struct page **pages;		/* Backing pages if present */
 };
 
@@ -54,7 +55,7 @@ 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);
+extern int psb_gtt_pin(struct gtt_range *gt);
+extern void psb_gtt_unpin(struct gtt_range *gt);
 
 #endif
drivers/staging/gma500/psb_intel_display.c +7 -7
index c56ab82..c3e9d28 100644
@@ -363,7 +363,7 @@ int psb_intel_pipe_set_base(struct drm_crtc *crtc,
 
 	/* We are displaying this buffer, make sure it is actually loaded
 	   into the GTT */
-	ret = psb_gtt_pin(dev, psbfb->gtt);
+	ret = psb_gtt_pin(psbfb->gtt);
 	if (ret < 0)
 		goto psb_intel_pipe_set_base_exit;
 	start = psbfb->gtt->offset;
@@ -392,7 +392,7 @@ 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);
+		psb_gtt_unpin(psbfb->gtt);
 		goto psb_intel_pipe_set_base_exit;
 	}
 	REG_WRITE(dspcntr_reg, dspcntr);
@@ -411,7 +411,7 @@ int psb_intel_pipe_set_base(struct drm_crtc *crtc,
 
 	/* 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_gtt_unpin(to_psb_fb(old_fb)->gtt);
 
 psb_intel_pipe_set_base_exit:
 	gma_power_end(dev);
@@ -1057,7 +1057,7 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
 		if (psb_intel_crtc->cursor_obj) {
 			gt = container_of(psb_intel_crtc->cursor_obj,
 							struct gtt_range, gem);
-			psb_gtt_unpin(crtc->dev, gt);
+			psb_gtt_unpin(gt);
 			drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
 			psb_intel_crtc->cursor_obj = NULL;
 		}
@@ -1083,7 +1083,7 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
 	gt = container_of(obj, struct gtt_range, gem);
 
 	/* Pin the memory into the GTT */
-	ret = psb_gtt_pin(crtc->dev, gt);
+	ret = psb_gtt_pin(gt);
 	if (ret) {
 		DRM_ERROR("Can not pin down handle 0x%x\n", handle);
 		return ret;
@@ -1109,7 +1109,7 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
 	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);
+		psb_gtt_unpin(gt);
 		drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
 		psb_intel_crtc->cursor_obj = obj;
 	}
@@ -1318,7 +1318,7 @@ static void psb_intel_crtc_destroy(struct drm_crtc *crtc)
 	if (psb_intel_crtc->cursor_obj) {
 		gt = container_of(psb_intel_crtc->cursor_obj,
 						struct gtt_range, gem);
-		psb_gtt_unpin(crtc->dev, gt);
+		psb_gtt_unpin(gt);
 		drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
 		psb_intel_crtc->cursor_obj = NULL;
 	}