gma500: GEM - now we have the basics we shall stick pins in it
authorAlan Cox <alan@linux.jf.intel.com>
Tue, 19 Apr 2011 14:28:21 +0000 (15:28 +0100)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 26 Apr 2011 00:13:49 +0000 (17:13 -0700)
Signed-off-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/staging/gma500/psb_gtt.c
drivers/staging/gma500/psb_gtt.h
drivers/staging/gma500/psb_intel_display.c

index 090d30e216430823b439bb11e0ea3ec616a14c80..a991c12315ce4e5717729f7a67346d63b07b2e94 100644 (file)
@@ -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]);
@@ -206,6 +199,50 @@ void psb_gtt_detach_pages(struct gtt_range *gt)
        gt->pages = NULL;
 }
 
+/*
+ *     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(&gt->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;
index b5d653088bc30c01d6139364892563d350900feb..dc553e07a9dec9eb4e42acbd446d78cdd71b72ea 100644 (file)
@@ -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
index 4d384d592e09033e54887755fa6baea0a54d9e86..b5a36d20d0ba8ff61328dacab180c0e2772261e8 100644 (file)
@@ -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);