Track named objects in /proc/dri/0/gem_names.
Track total object count in /proc/dri/0/gem_objects.
Initialize device gem data.
return -ENODEV for gem ioctls if the driver doesn't support gem.
Call unlock_page when unbinding from gtt.
Add numerous misssing calls to drm_gem_object_unreference.
/*@{ */
spinlock_t object_name_lock;
struct idr object_name_idr;
+ atomic_t object_count;
/*@} */
};
return block->mm;
}
+int
+drm_gem_init (struct drm_device *dev);
+
void
drm_gem_object_free (struct kref *kref);
* up at a later data, and as our interface with shmfs for memory allocation.
*/
+/**
+ * Initialize the GEM device fields
+ */
+
+int
+drm_gem_init (struct drm_device *dev)
+{
+ spin_lock_init (&dev->object_name_lock);
+ idr_init (&dev->object_name_idr);
+ atomic_set (&dev->object_count, 0);
+ return 0;
+}
+
+/**
+ * Allocate a GEM object of the specified size with shmfs backing store
+ */
static struct drm_gem_object *
drm_gem_object_alloc(struct drm_device *dev, size_t size)
{
kfree(obj);
return NULL;
}
+ atomic_inc (&dev->object_count);
return obj;
}
*/
again:
/* ensure there is space available to allocate a handle */
- if (idr_pre_get(&file_priv->object_idr, GFP_KERNEL) == 0) {
- kfree(obj);
+ if (idr_pre_get(&file_priv->object_idr, GFP_KERNEL) == 0)
return -ENOMEM;
- }
+
/* do the allocation under our spinlock */
spin_lock (&file_priv->table_lock);
ret = idr_get_new_above(&file_priv->object_idr, obj, 1, handlep);
struct drm_gem_object *obj;
int handle, ret;
+ if (!(dev->driver->driver_features & DRIVER_GEM))
+ return -ENODEV;
+
/* Round requested size up to page size */
args->size = (args->size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
struct drm_gem_unreference *args = data;
int ret;
+ if (!(dev->driver->driver_features & DRIVER_GEM))
+ return -ENODEV;
+
ret = drm_gem_handle_delete(file_priv, args->handle);
return ret;
ssize_t read;
loff_t offset;
+ if (!(dev->driver->driver_features & DRIVER_GEM))
+ return -ENODEV;
+
obj = drm_gem_object_lookup(dev, file_priv, args->handle);
if (obj == NULL)
return -EINVAL;
struct drm_gem_object *obj;
loff_t offset;
+ if (!(dev->driver->driver_features & DRIVER_GEM))
+ return -ENODEV;
+
obj = drm_gem_object_lookup(dev, file_priv, args->handle);
if (obj == NULL)
return -EINVAL;
ssize_t written;
loff_t offset;
+ if (!(dev->driver->driver_features & DRIVER_GEM))
+ return -ENODEV;
+
obj = drm_gem_object_lookup(dev, file_priv, args->handle);
if (obj == NULL)
return -EINVAL;
struct drm_gem_object *obj;
int ret;
+ if (!(dev->driver->driver_features & DRIVER_GEM))
+ return -ENODEV;
+
obj = drm_gem_object_lookup(dev, file_priv, args->handle);
if (obj == NULL)
return -EINVAL;
int ret;
int handle;
+ if (!(dev->driver->driver_features & DRIVER_GEM))
+ return -ENODEV;
+
spin_lock (&dev->object_name_lock);
obj = idr_find (&dev->object_name_idr, (int) args->name);
if (obj)
drm_gem_open(struct drm_device *dev, struct drm_file *file_private)
{
idr_init(&file_private->object_idr);
+ spin_lock_init (&file_private->table_lock);
}
/** Called at device close to release the file's handle references on objects. */
dev->driver->gem_free_object(obj);
fput(obj->filp);
-
+ atomic_dec (&dev->object_count);
kfree(obj);
}
EXPORT_SYMBOL(drm_gem_object_free);
int request, int *eof, void *data);
static int drm_objects_info(char *buf, char **start, off_t offset,
int request, int *eof, void *data);
+static int drm_gem_name_info(char *buf, char **start, off_t offset,
+ int request, int *eof, void *data);
+static int drm_gem_object_info(char *buf, char **start, off_t offset,
+ int request, int *eof, void *data);
#if DRM_DEBUG_CODE
static int drm_vma_info(char *buf, char **start, off_t offset,
int request, int *eof, void *data);
{"queues", drm_queues_info},
{"bufs", drm_bufs_info},
{"objects", drm_objects_info},
+ {"gem_names", drm_gem_name_info},
+ {"gem_objects", drm_gem_object_info},
#if DRM_DEBUG_CODE
{"vma", drm_vma_info},
#endif
return ret;
}
+struct drm_gem_name_info_data {
+ int len;
+ char *buf;
+ int eof;
+};
+
+static int drm_gem_one_name_info (int id, void *ptr, void *data)
+{
+ struct drm_gem_object *obj = ptr;
+ struct drm_gem_name_info_data *nid = data;
+
+ DRM_INFO ("name %d size %d\n", obj->name, obj->size);
+ if (nid->eof)
+ return 0;
+
+ nid->len += sprintf (&nid->buf[nid->len],
+ "%6d%9d%8d%9d\n",
+ obj->name, obj->size,
+ atomic_read(&obj->handlecount.refcount),
+ atomic_read(&obj->refcount.refcount));
+ if (nid->len > DRM_PROC_LIMIT) {
+ nid->eof = 1;
+ return 0;
+ }
+ return 0;
+}
+
+static int drm_gem_name_info(char *buf, char **start, off_t offset,
+ int request, int *eof, void *data)
+{
+ struct drm_minor *minor = (struct drm_minor *) data;
+ struct drm_device *dev = minor->dev;
+ struct drm_gem_name_info_data nid;
+
+ if (offset > DRM_PROC_LIMIT) {
+ *eof = 1;
+ return 0;
+ }
+
+ nid.len = sprintf (buf, " name size handles refcount\n");
+ nid.buf = buf;
+ nid.eof = 0;
+ idr_for_each (&dev->object_name_idr, drm_gem_one_name_info, &nid);
+
+ *start = &buf[offset];
+ *eof = 0;
+ if (nid.len > request + offset)
+ return request;
+ *eof = 1;
+ return nid.len - offset;
+}
+
+static int drm_gem_object_info(char *buf, char **start, off_t offset,
+ int request, int *eof, void *data)
+{
+ struct drm_minor *minor = (struct drm_minor *) data;
+ struct drm_device *dev = minor->dev;
+ int len = 0;
+
+ if (offset > DRM_PROC_LIMIT) {
+ *eof = 1;
+ return 0;
+ }
+
+ *start = &buf[offset];
+ *eof = 0;
+ DRM_PROC_PRINT ("%d objects\n", atomic_read (&dev->object_count));
+ if (len > request + offset)
+ return request;
+ *eof = 1;
+ return len - offset;
+}
+
#if DRM_DEBUG_CODE
static int drm__vma_info(char *buf, char **start, off_t offset, int request,
goto error_out_unreg;
}
+ if (driver->driver_features & DRIVER_GEM) {
+ retcode = drm_gem_init (dev);
+ if (retcode) {
+ DRM_ERROR("Cannot initialize graphics execution manager (GEM)\n");
+ goto error_out_unreg;
+ }
+ }
+
drm_fence_manager_init(dev);
+
return 0;
error_out_unreg:
*/
.driver_features =
DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | /* DRIVER_USE_MTRR | */
- DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
+ DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM,
.load = i915_driver_load,
.unload = i915_driver_unload,
.firstopen = i915_driver_firstopen,
if (obj_priv->page_list == NULL)
return;
- for (i = 0; i < obj->size / PAGE_SIZE; i++) {
- if (obj_priv->page_list[i] == NULL)
- put_page(obj_priv->page_list[i]);
+
+ for (i = 0; i < page_count; i++) {
+ if (obj_priv->page_list[i] != NULL) {
+ unlock_page (obj_priv->page_list[i]);
+ page_cache_release (obj_priv->page_list[i]);
+ }
}
-
drm_free(obj_priv->page_list,
page_count * sizeof(struct page *),
DRM_MEM_DRIVER);
if (target_obj_priv->gtt_space == NULL) {
DRM_ERROR("No GTT space found for object %d\n",
reloc.target_handle);
+ drm_gem_object_unreference (target_obj);
return -EINVAL;
}
if (reloc.offset > obj->size - 4) {
DRM_ERROR("Relocation beyond object bounds.\n");
+ drm_gem_object_unreference (target_obj);
return -EINVAL;
}
if (reloc.offset & 3) {
DRM_ERROR("Relocation not 4-byte aligned.\n");
+ drm_gem_object_unreference (target_obj);
return -EINVAL;
}
(reloc.offset & ~(PAGE_SIZE - 1)),
PAGE_SIZE);
if (reloc_page == NULL)
+ {
+ drm_gem_object_unreference (target_obj);
return -ENOMEM;
+ }
reloc_entry = (uint32_t *)((char *)reloc_page +
(reloc.offset & (PAGE_SIZE - 1)));
*reloc_entry = reloc_val;
iounmap(reloc_page);
+ drm_gem_object_unreference (target_obj);
}
return 0;
return -EINVAL;
}
- ret = i915_gem_object_bind_to_gtt(obj, (unsigned) args->alignment);
- if (ret != 0) {
- DRM_ERROR("Failure to bind in i915_gem_pin_ioctl(): %d\n",
- ret);
- return ret;
+ obj_priv = obj->driver_private;
+ if (obj_priv->gtt_space == NULL)
+ {
+ ret = i915_gem_object_bind_to_gtt(obj, (unsigned) args->alignment);
+ if (ret != 0) {
+ DRM_ERROR("Failure to bind in i915_gem_pin_ioctl(): %d\n",
+ ret);
+ drm_gem_object_unreference (obj);
+ return ret;
+ }
}
- obj_priv = obj->driver_private;
obj_priv->pin_count++;
args->offset = obj_priv->gtt_offset;
+ drm_gem_object_unreference (obj);
return 0;
}
obj_priv = obj->driver_private;
obj_priv->pin_count--;
-
+ drm_gem_object_unreference (obj);
return 0;
}