Add a bit of /proc/dri/*/gem support. Clean up some refcount/pagelock issues.
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.main
parent
39e20bcd5f
commit
ab3549d133
|
@ -937,6 +937,7 @@ struct drm_device {
|
|||
/*@{ */
|
||||
spinlock_t object_name_lock;
|
||||
struct idr object_name_idr;
|
||||
atomic_t object_count;
|
||||
/*@} */
|
||||
};
|
||||
|
||||
|
@ -1320,6 +1321,9 @@ static inline struct drm_memrange *drm_get_mm(struct drm_memrange_node *block)
|
|||
return block->mm;
|
||||
}
|
||||
|
||||
int
|
||||
drm_gem_init (struct drm_device *dev);
|
||||
|
||||
void
|
||||
drm_gem_object_free (struct kref *kref);
|
||||
|
||||
|
|
|
@ -64,6 +64,22 @@
|
|||
* 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)
|
||||
{
|
||||
|
@ -90,6 +106,7 @@ drm_gem_object_alloc(struct drm_device *dev, size_t size)
|
|||
kfree(obj);
|
||||
return NULL;
|
||||
}
|
||||
atomic_inc (&dev->object_count);
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
@ -145,10 +162,9 @@ drm_gem_handle_create (struct drm_file *file_priv,
|
|||
*/
|
||||
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);
|
||||
|
@ -198,6 +214,9 @@ drm_gem_alloc_ioctl(struct drm_device *dev, void *data,
|
|||
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);
|
||||
|
||||
|
@ -227,6 +246,9 @@ drm_gem_unreference_ioctl(struct drm_device *dev, void *data,
|
|||
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;
|
||||
|
@ -246,6 +268,9 @@ drm_gem_pread_ioctl(struct drm_device *dev, void *data,
|
|||
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;
|
||||
|
@ -282,6 +307,9 @@ drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
|
|||
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;
|
||||
|
@ -313,6 +341,9 @@ drm_gem_pwrite_ioctl(struct drm_device *dev, void *data,
|
|||
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;
|
||||
|
@ -348,6 +379,9 @@ drm_gem_name_ioctl(struct drm_device *dev, void *data,
|
|||
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;
|
||||
|
@ -396,6 +430,9 @@ drm_gem_open_ioctl(struct drm_device *dev, void *data,
|
|||
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)
|
||||
|
@ -423,6 +460,7 @@ void
|
|||
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. */
|
||||
|
@ -464,7 +502,7 @@ drm_gem_object_free (struct kref *kref)
|
|||
dev->driver->gem_free_object(obj);
|
||||
|
||||
fput(obj->filp);
|
||||
|
||||
atomic_dec (&dev->object_count);
|
||||
kfree(obj);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_gem_object_free);
|
||||
|
|
|
@ -51,6 +51,10 @@ static int drm_bufs_info(char *buf, char **start, off_t offset,
|
|||
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);
|
||||
|
@ -70,6 +74,8 @@ static struct drm_proc_list {
|
|||
{"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
|
||||
|
@ -582,6 +588,79 @@ static int drm_clients_info(char *buf, char **start, off_t offset,
|
|||
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,
|
||||
|
|
|
@ -163,7 +163,16 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
|
|||
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:
|
||||
|
|
|
@ -566,7 +566,7 @@ static struct drm_driver driver = {
|
|||
*/
|
||||
.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,
|
||||
|
|
|
@ -58,11 +58,13 @@ i915_gem_object_free_page_list(struct drm_gem_object *obj)
|
|||
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);
|
||||
|
@ -212,15 +214,18 @@ i915_gem_reloc_and_validate_object(struct drm_gem_object *obj,
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -231,7 +236,10 @@ i915_gem_reloc_and_validate_object(struct drm_gem_object *obj,
|
|||
(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)));
|
||||
|
@ -242,6 +250,7 @@ i915_gem_reloc_and_validate_object(struct drm_gem_object *obj,
|
|||
*reloc_entry = reloc_val;
|
||||
|
||||
iounmap(reloc_page);
|
||||
drm_gem_object_unreference (target_obj);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -372,16 +381,21 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data,
|
|||
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;
|
||||
}
|
||||
|
@ -403,7 +417,7 @@ i915_gem_unpin_ioctl(struct drm_device *dev, void *data,
|
|||
|
||||
obj_priv = obj->driver_private;
|
||||
obj_priv->pin_count--;
|
||||
|
||||
drm_gem_object_unreference (obj);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue