On Thu, Nov 03, 2011 at 06:20:58PM +0000, Alan Cox wrote: > From: Alan Cox <alan@xxxxxxxxxxxxxxx> > > The driver uses GEM along with a couple of small bits of wrapping of its > own. The only real oddity here is the support for using the 'stolen' memory > rather than wasting several MB. > > We use a simple resource manager as we don't need to manage our space > intensively at all as we only do 2D work. We also have a GTT which is > entirely GPU facing so in the Cedarview case are not even allocating from > host address space. > > Signed-off-by: Alan Cox <alan@xxxxxxxxxxxxxxx> One tiny comment below (has no effect on the actual code) and your drm_glue.c is already merged through some patches from Rob Clarke. Reviewed-by: Signed-Off-by: Daniel Vetter <daniel.vetter@xxxxxxxx> [snip] > +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 (r == NULL) { > + dev_err(dev->dev, "no memory for %lld byte GEM object\n", size); > + return -ENOSPC; > + } > + /* 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 */ > + dev_err(dev->dev, "GEM init failed for %lld\n", size); > + return -ENOMEM; Actually my drm_gem_object_init here returns -ENOMEM in the (currently only) failure case ... > + } > + /* Give the object a handle so we can carry it more easily */ > + ret = drm_gem_handle_create(file, &r->gem, &handle); > + if (ret) { > + dev_err(dev->dev, "GEM handle failed for %p, %lld\n", > + &r->gem, size); > + 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; > +} [snip] > diff --git a/drivers/gpu/drm/gma500/gem_glue.c b/drivers/gpu/drm/gma500/gem_glue.c > new file mode 100644 > index 0000000..daac121 > --- /dev/null > +++ b/drivers/gpu/drm/gma500/gem_glue.c > @@ -0,0 +1,89 @@ > +/************************************************************************** > + * Copyright (c) 2011, Intel Corporation. > + * All Rights Reserved. > + * > + * 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 <drm/drmP.h> > +#include <drm/drm.h> > + > +void drm_gem_object_release_wrap(struct drm_gem_object *obj) > +{ > + /* Remove the list map if one is present */ > + if (obj->map_list.map) { > + struct drm_gem_mm *mm = obj->dev->mm_private; > + struct drm_map_list *list = &obj->map_list; > + drm_ht_remove_item(&mm->offset_hash, &list->hash); > + drm_mm_put_block(list->file_offset_node); > + kfree(list->map); > + list->map = NULL; drm_gem_free_mmap_offset from Rob Clarke does that for you. > + } > + drm_gem_object_release(obj); > +} > + > +/** > + * gem_create_mmap_offset - invent an mmap offset > + * @obj: our object > + * > + * Standard implementation of offset generation for mmap as is > + * duplicated in several drivers. This belongs in GEM. > + */ > +int gem_create_mmap_offset(struct drm_gem_object *obj) Already merged. > +{ > + struct drm_device *dev = obj->dev; > + struct drm_gem_mm *mm = dev->mm_private; > + struct drm_map_list *list; > + struct drm_local_map *map; > + int ret; > + > + list = &obj->map_list; > + list->map = kzalloc(sizeof(struct drm_map_list), GFP_KERNEL); > + if (list->map == NULL) > + return -ENOMEM; > + map = list->map; > + map->type = _DRM_GEM; > + map->size = obj->size; > + map->handle = obj; > + > + list->file_offset_node = drm_mm_search_free(&mm->offset_manager, > + obj->size / PAGE_SIZE, 0, 0); > + if (!list->file_offset_node) { > + dev_err(dev->dev, "failed to allocate offset for bo %d\n", > + obj->name); > + ret = -ENOSPC; > + goto free_it; > + } > + list->file_offset_node = drm_mm_get_block(list->file_offset_node, > + obj->size / PAGE_SIZE, 0); > + if (!list->file_offset_node) { > + ret = -ENOMEM; > + goto free_it; > + } > + list->hash.key = list->file_offset_node->start; > + ret = drm_ht_insert_item(&mm->offset_hash, &list->hash); > + if (ret) { > + dev_err(dev->dev, "failed to add to map hash\n"); > + goto free_mm; > + } > + return 0; > + > +free_mm: > + drm_mm_put_block(list->file_offset_node); > +free_it: > + kfree(list->map); > + list->map = NULL; > + return ret; > +} > diff --git a/drivers/gpu/drm/gma500/gem_glue.h b/drivers/gpu/drm/gma500/gem_glue.h > new file mode 100644 > index 0000000..ce5ce30 > --- /dev/null > +++ b/drivers/gpu/drm/gma500/gem_glue.h > @@ -0,0 +1,2 @@ > +extern void drm_gem_object_release_wrap(struct drm_gem_object *obj); > +extern int gem_create_mmap_offset(struct drm_gem_object *obj); > > _______________________________________________ > dri-devel mailing list > dri-devel@xxxxxxxxxxxxxxxxxxxxx > http://lists.freedesktop.org/mailman/listinfo/dri-devel -- Daniel Vetter Mail: daniel@xxxxxxxx Mobile: +41 (0)79 365 57 48 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel