diff options
author | Alan Cox | 2011-04-19 16:28:21 +0200 |
---|---|---|
committer | Greg Kroah-Hartman | 2011-04-26 02:13:49 +0200 |
commit | e1684a048b709f886dcd996901580f8a65b18391 (patch) | |
tree | aa54a847980be16cdbcde4d0b4e893f6ea8d40a2 /drivers/staging/gma500/psb_gtt.c | |
parent | gma500: GEMify the frame buffer base bits (diff) | |
download | kernel-qcow2-linux-e1684a048b709f886dcd996901580f8a65b18391.tar.gz kernel-qcow2-linux-e1684a048b709f886dcd996901580f8a65b18391.tar.xz kernel-qcow2-linux-e1684a048b709f886dcd996901580f8a65b18391.zip |
gma500: GEM - now we have the basics we shall stick pins in it
Signed-off-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/gma500/psb_gtt.c')
-rw-r--r-- | drivers/staging/gma500/psb_gtt.c | 70 |
1 files changed, 53 insertions, 17 deletions
diff --git a/drivers/staging/gma500/psb_gtt.c b/drivers/staging/gma500/psb_gtt.c index 090d30e21643..a991c12315ce 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; |