Esempio n. 1
0
/**
 * drm_gem_create_mmap_offset - create a fake mmap offset for an object
 * @obj: obj in question
 *
 * GEM memory mapping works by handing back to userspace a fake mmap offset
 * it can use in a subsequent mmap(2) call.  The DRM core code then looks
 * up the object based on the offset and sets up the various memory mapping
 * structures.
 *
 * This routine allocates and attaches a fake offset for @obj.
 */
int
drm_gem_create_mmap_offset(struct drm_gem_object *obj)
{
    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 = 0;

    /* Set the object up for mmap'ing */
    list = &obj->map_list;
    list->map = kzalloc(sizeof(struct drm_map_list), GFP_KERNEL);
    if (!list->map)
        return -ENOMEM;

    map = list->map;
    map->type = _DRM_GEM;
    map->size = obj->size;
    map->handle = obj;

    /* Get a DRM GEM mmap offset allocated... */
    list->file_offset_node = drm_mm_search_free(&mm->offset_manager,
                             obj->size / PAGE_SIZE, 0, 0);

    if (!list->file_offset_node) {
        DRM_ERROR("failed to allocate offset for bo %d\n", obj->name);
        ret = -ENOSPC;
        goto out_free_list;
    }

    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 out_free_list;
    }

    list->hash.key = list->file_offset_node->start;
    ret = drm_ht_insert_item(&mm->offset_hash, &list->hash);
    if (ret) {
        DRM_ERROR("failed to add to map hash\n");
        goto out_free_mm;
    }

    return 0;

out_free_mm:
    drm_mm_put_block(list->file_offset_node);
out_free_list:
    kfree(list->map);
    list->map = NULL;

    return ret;
}
Esempio n. 2
0
/**
 * Inserts the given magic number into the hash table of used magic number
 * lists.
 */
static int drm_add_magic(struct drm_device *dev, struct drm_file *priv,
			 drm_magic_t magic)
{
	drm_magic_entry_t *entry;

	DRM_DEBUG("%d\n", magic);

	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
	if (!entry)
		return -ENOMEM;
	entry->priv = priv;
	entry->hash_item.key = (unsigned long)magic;
	mutex_lock(&dev->struct_mutex);
	drm_ht_insert_item(&dev->magiclist, &entry->hash_item);
	list_add_tail(&entry->head, &dev->magicfree);
	mutex_unlock(&dev->struct_mutex);

	return 0;
}
Esempio n. 3
0
int
drm_gem_create_mmap_offset(struct drm_gem_object *obj)
{
    struct drm_device *dev = obj->dev;
    struct drm_gem_mm *mm = dev->mm_private;
    int ret;

    if (obj->on_map)
        return 0;

    obj->map_list.key = alloc_unr(mm->idxunr);
    ret = drm_ht_insert_item(&mm->offset_hash, &obj->map_list);
    if (ret) {
        DRM_ERROR("failed to add to map hash\n");
        free_unr(mm->idxunr, obj->map_list.key);
        return ret;
    }
    obj->on_map = true;

    return 0;
}
Esempio n. 4
0
/*
 * Just insert an item and return any "bits" bit key that hasn't been
 * used before.
 */
int drm_ht_just_insert_please(struct drm_open_hash *ht, struct drm_hash_item *item,
			      unsigned long seed, int bits, int shift,
			      unsigned long add)
{
	int ret;
	unsigned long mask = (1 << bits) - 1;
	unsigned long first, unshifted_key = 0;

	unshifted_key = hash32_buf(&seed, sizeof(seed), unshifted_key);
	first = unshifted_key;
	do {
		item->key = (unshifted_key << shift) + add;
		ret = drm_ht_insert_item(ht, item);
		if (ret)
			unshifted_key = (unshifted_key + 1) & mask;
	} while(ret && (unshifted_key != first));

	if (ret) {
		DRM_ERROR("Available key bit space exhausted\n");
		return -EINVAL;
	}
	return 0;
}