Commit e1684a04 authored by Alan Cox's avatar Alan Cox Committed by Greg Kroah-Hartman

gma500: GEM - now we have the basics we shall stick pins in it

Signed-off-by: default avatarAlan Cox <alan@linux.intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent ed7ea13e
...@@ -66,7 +66,6 @@ u32 *psb_gtt_entry(struct drm_device *dev, struct gtt_range *r) ...@@ -66,7 +66,6 @@ u32 *psb_gtt_entry(struct drm_device *dev, struct gtt_range *r)
return dev_priv->gtt_map + (offset >> PAGE_SHIFT); return dev_priv->gtt_map + (offset >> PAGE_SHIFT);
} }
/** /**
* psb_gtt_insert - put an object into the GART * psb_gtt_insert - put an object into the GART
* @dev: our DRM device * @dev: our DRM device
...@@ -77,21 +76,19 @@ u32 *psb_gtt_entry(struct drm_device *dev, struct gtt_range *r) ...@@ -77,21 +76,19 @@ u32 *psb_gtt_entry(struct drm_device *dev, struct gtt_range *r)
* *
* FIXME: gtt lock ? * 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; u32 *gtt_slot, pte;
int numpages = (r->resource.end + 1 - r->resource.start) >> PAGE_SHIFT; int numpages = (r->resource.end + 1 - r->resource.start) >> PAGE_SHIFT;
struct page **pages; struct page **pages;
int i; int i;
if (r->stolen)
return 0;
if (r->pages == NULL) { if (r->pages == NULL) {
WARN_ON(1); WARN_ON(1);
return -EINVAL; return -EINVAL;
} }
WARN_ON(r->in_gart); /* refcount these maybe ? */ WARN_ON(r->stolen); /* refcount these maybe ? */
gtt_slot = psb_gtt_entry(dev, r); gtt_slot = psb_gtt_entry(dev, r);
pages = r->pages; pages = r->pages;
...@@ -118,16 +115,14 @@ int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r) ...@@ -118,16 +115,14 @@ int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r)
* page table entries with the dummy page * 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; struct drm_psb_private *dev_priv = dev->dev_private;
u32 *gtt_slot, pte; u32 *gtt_slot, pte;
int numpages = (r->resource.end + 1 - r->resource.start) >> PAGE_SHIFT; int numpages = (r->resource.end + 1 - r->resource.start) >> PAGE_SHIFT;
int i; int i;
if (r->stolen) WARN_ON(r->stolen);
return;
WARN_ON(!r->in_gart);
gtt_slot = psb_gtt_entry(dev, r); gtt_slot = psb_gtt_entry(dev, r);
pte = psb_gtt_mask_pte(page_to_pfn(dev_priv->scratch_page), 0);; 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) ...@@ -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. * 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 * 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 inode *inode;
struct address_space *mapping; struct address_space *mapping;
...@@ -189,13 +184,11 @@ int psb_gtt_attach_pages(struct gtt_range *gt) ...@@ -189,13 +184,11 @@ int psb_gtt_attach_pages(struct gtt_range *gt)
* must have been removed from the GART as they could now be paged out * must have been removed from the GART as they could now be paged out
* and move bus address. * 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 i;
int pages = (gt->resource.end + 1 - gt->resource.start) >> PAGE_SHIFT; int pages = (gt->resource.end + 1 - gt->resource.start) >> PAGE_SHIFT;
WARN_ON(gt->in_gart);
for (i = 0; i < pages; i++) { for (i = 0; i < pages; i++) {
/* FIXME: do we need to force dirty */ /* FIXME: do we need to force dirty */
set_page_dirty(gt->pages[i]); set_page_dirty(gt->pages[i]);
...@@ -206,6 +199,50 @@ void psb_gtt_detach_pages(struct gtt_range *gt) ...@@ -206,6 +199,50 @@ void psb_gtt_detach_pages(struct gtt_range *gt)
gt->pages = NULL; 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 * 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, ...@@ -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) static void psb_gtt_destroy(struct kref *kref)
{ {
struct gtt_range *gt = container_of(kref, struct gtt_range, kref); struct gtt_range *gt = container_of(kref, struct gtt_range, kref);
if (gt->in_gart && !gt->stolen) WARN_ON(gt->in_gart && !gt->stolen);
psb_gtt_remove(gt->gem.dev, gt);
if (gt->pages)
psb_gtt_detach_pages(gt);
release_resource(&gt->resource); release_resource(&gt->resource);
kfree(gt); kfree(gt);
} }
...@@ -345,6 +379,8 @@ int psb_gtt_init(struct drm_device *dev, int resume) ...@@ -345,6 +379,8 @@ int psb_gtt_init(struct drm_device *dev, int resume)
int ret = 0; int ret = 0;
uint32_t pte; uint32_t pte;
mutex_init(&dev_priv->gtt_mutex);
dev_priv->pg = pg = psb_gtt_alloc(dev); dev_priv->pg = pg = psb_gtt_alloc(dev);
if (pg == NULL) if (pg == NULL)
return -ENOMEM; return -ENOMEM;
......
...@@ -44,18 +44,17 @@ struct gtt_range { ...@@ -44,18 +44,17 @@ struct gtt_range {
struct resource resource; struct resource resource;
u32 offset; u32 offset;
struct kref kref; struct kref kref;
struct drm_gem_object gem; /* GEM high level stuff */ struct drm_gem_object gem; /* GEM high level stuff */
int in_gart; /* Currently in the GART */ int in_gart; /* Currently in the GART (ref ct) */
int stolen; /* Backed from stolen RAM */ bool stolen; /* Backed from stolen RAM */
struct page **pages; /* Backing pages if present */ 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, extern struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
const char *name, int backed); const char *name, int backed);
extern void psb_gtt_kref_put(struct gtt_range *gt); 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 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 #endif
...@@ -341,7 +341,6 @@ int psb_intel_pipe_set_base(struct drm_crtc *crtc, ...@@ -341,7 +341,6 @@ int psb_intel_pipe_set_base(struct drm_crtc *crtc,
/* struct drm_i915_master_private *master_priv; */ /* struct drm_i915_master_private *master_priv; */
struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb); 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; int pipe = psb_intel_crtc->pipe;
unsigned long start, offset; unsigned long start, offset;
int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE); int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE);
...@@ -1020,8 +1019,6 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc, ...@@ -1020,8 +1019,6 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
uint32_t width, uint32_t height) uint32_t width, uint32_t height)
{ {
struct drm_device *dev = crtc->dev; 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); struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
int pipe = psb_intel_crtc->pipe; int pipe = psb_intel_crtc->pipe;
uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR; uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR;
...@@ -1048,6 +1045,9 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc, ...@@ -1048,6 +1045,9 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
/* Unpin the old GEM object */ /* Unpin the old GEM object */
if (psb_intel_crtc->cursor_obj) { 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); drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
psb_intel_crtc->cursor_obj = NULL; psb_intel_crtc->cursor_obj = NULL;
} }
...@@ -1070,19 +1070,17 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc, ...@@ -1070,19 +1070,17 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
return -ENOMEM; return -ENOMEM;
} }
/*insert this bo into gtt*/ gt = container_of(obj, struct gtt_range, gem);
DRM_DEBUG("%s: map meminfo for hw cursor. handle %x\n",
__func__, handle);
/* Pin : FIXME /* Pin the memory into the GTT */
ret = psb_gtt_pin(crtc->dev, gt);
if (ret) { 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; 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; psb_intel_crtc->cursor_addr = addr;
...@@ -1099,6 +1097,9 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc, ...@@ -1099,6 +1097,9 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
/* unpin the old bo */ /* unpin the old bo */
if (psb_intel_crtc->cursor_obj && psb_intel_crtc->cursor_obj != obj) { 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); drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
psb_intel_crtc->cursor_obj = obj; psb_intel_crtc->cursor_obj = obj;
} }
...@@ -1301,8 +1302,16 @@ struct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev, ...@@ -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) static void psb_intel_crtc_destroy(struct drm_crtc *crtc)
{ {
struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_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); kfree(psb_intel_crtc->crtc_state);
drm_crtc_cleanup(crtc); drm_crtc_cleanup(crtc);
kfree(psb_intel_crtc); kfree(psb_intel_crtc);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment