@@ -84,9 +84,7 @@ static int etnaviv_unload(struct drm_device *dev)
flush_workqueue(priv->wq);
destroy_workqueue(priv->wq);
- mutex_lock(&dev->struct_mutex);
component_unbind_all(dev->dev, dev);
- mutex_unlock(&dev->struct_mutex);
dev->dev_private = NULL;
@@ -138,16 +136,12 @@ static int etnaviv_load(struct drm_device *dev, unsigned long flags)
platform_set_drvdata(pdev, dev);
- mutex_lock(&dev->struct_mutex);
-
err = component_bind_all(dev->dev, dev);
if (err < 0)
return err;
load_gpu(dev);
- mutex_unlock(&dev->struct_mutex);
-
return 0;
}
@@ -566,37 +566,26 @@ void etnaviv_gem_free_object(struct drm_gem_object *obj)
kfree(etnaviv_obj);
}
-/* convenience method to construct a GEM buffer object, and userspace handle */
-int etnaviv_gem_new_handle(struct drm_device *dev, struct drm_file *file,
- uint32_t size, uint32_t flags, uint32_t *handle)
+int etnaviv_gem_obj_add(struct drm_device *dev, struct drm_gem_object *obj)
{
- struct drm_gem_object *obj;
+ struct etnaviv_drm_private *priv = dev->dev_private;
+ struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
int ret;
- ret = mutex_lock_interruptible(&dev->struct_mutex);
+ ret = mutex_lock_killable(&dev->struct_mutex);
if (ret)
return ret;
- obj = etnaviv_gem_new(dev, size, flags);
-
+ list_add_tail(&etnaviv_obj->mm_list, &priv->inactive_list);
mutex_unlock(&dev->struct_mutex);
- if (IS_ERR(obj))
- return PTR_ERR(obj);
-
- ret = drm_gem_handle_create(file, obj, handle);
-
- /* drop reference from allocate - handle holds it now */
- drm_gem_object_unreference_unlocked(obj);
-
- return ret;
+ return 0;
}
static int etnaviv_gem_new_impl(struct drm_device *dev,
uint32_t size, uint32_t flags,
struct drm_gem_object **obj)
{
- struct etnaviv_drm_private *priv = dev->dev_private;
struct etnaviv_gem_object *etnaviv_obj;
unsigned sz = sizeof(*etnaviv_obj);
bool valid = true;
@@ -651,14 +640,12 @@ static int etnaviv_gem_new_impl(struct drm_device *dev,
return 0;
}
-struct drm_gem_object *etnaviv_gem_new(struct drm_device *dev,
+static struct drm_gem_object *__etnaviv_gem_new(struct drm_device *dev,
uint32_t size, uint32_t flags)
{
struct drm_gem_object *obj = NULL;
int ret;
- WARN_ON(!mutex_is_locked(&dev->struct_mutex));
-
size = PAGE_ALIGN(size);
ret = etnaviv_gem_new_impl(dev, size, flags, &obj);
@@ -681,11 +668,55 @@ struct drm_gem_object *etnaviv_gem_new(struct drm_device *dev,
fail:
if (obj)
- drm_gem_object_unreference(obj);
+ drm_gem_object_unreference_unlocked(obj);
return ERR_PTR(ret);
}
+/* convenience method to construct a GEM buffer object, and userspace handle */
+int etnaviv_gem_new_handle(struct drm_device *dev, struct drm_file *file,
+ uint32_t size, uint32_t flags, uint32_t *handle)
+{
+ struct drm_gem_object *obj;
+ int ret;
+
+ obj = __etnaviv_gem_new(dev, size, flags);
+ if (IS_ERR(obj))
+ return PTR_ERR(obj);
+
+ ret = etnaviv_gem_obj_add(dev, obj);
+ if (ret < 0) {
+ drm_gem_object_unreference_unlocked(obj);
+ return ret;
+ }
+
+ ret = drm_gem_handle_create(file, obj, handle);
+
+ /* drop reference from allocate - handle holds it now */
+ drm_gem_object_unreference_unlocked(obj);
+
+ return ret;
+}
+
+struct drm_gem_object *etnaviv_gem_new(struct drm_device *dev,
+ uint32_t size, uint32_t flags)
+{
+ struct drm_gem_object *obj;
+ int ret;
+
+ obj = __etnaviv_gem_new(dev, size, flags);
+ if (IS_ERR(obj))
+ return obj;
+
+ ret = etnaviv_gem_obj_add(dev, obj);
+ if (ret < 0) {
+ drm_gem_object_unreference_unlocked(obj);
+ return ERR_PTR(ret);
+ }
+
+ return obj;
+}
+
int etnaviv_gem_new_private(struct drm_device *dev, size_t size, uint32_t flags,
struct etnaviv_gem_object **res)
{
@@ -879,22 +910,21 @@ int etnaviv_gem_new_userptr(struct drm_device *dev, struct drm_file *file,
struct etnaviv_gem_object *etnaviv_obj;
int ret;
- ret = mutex_lock_interruptible(&dev->struct_mutex);
+ ret = etnaviv_gem_new_private(dev, size, ETNA_BO_CACHED, &etnaviv_obj);
if (ret)
return ret;
- ret = etnaviv_gem_new_private(dev, size, ETNA_BO_CACHED, &etnaviv_obj);
- if (ret == 0) {
- etnaviv_obj->ops = &etnaviv_gem_userptr_ops;
- etnaviv_obj->userptr.ptr = ptr;
- etnaviv_obj->userptr.task = current;
- etnaviv_obj->userptr.ro = !(flags & ETNA_USERPTR_WRITE);
- get_task_struct(current);
- }
- mutex_unlock(&dev->struct_mutex);
+ etnaviv_obj->ops = &etnaviv_gem_userptr_ops;
+ etnaviv_obj->userptr.ptr = ptr;
+ etnaviv_obj->userptr.task = current;
+ etnaviv_obj->userptr.ro = !(flags & ETNA_USERPTR_WRITE);
+ get_task_struct(current);
- if (ret)
+ ret = etnaviv_gem_obj_add(dev, &etnaviv_obj->base);
+ if (ret) {
+ drm_gem_object_unreference_unlocked(&etnaviv_obj->base);
return ret;
+ }
ret = drm_gem_handle_create(file, &etnaviv_obj->base, handle);
@@ -133,6 +133,7 @@ etnaviv_gem_get_vram_mapping(struct etnaviv_gem_object *obj,
struct etnaviv_iommu *mmu);
int etnaviv_gem_new_private(struct drm_device *dev, size_t size, uint32_t flags,
struct etnaviv_gem_object **res);
+int etnaviv_gem_obj_add(struct drm_device *dev, struct drm_gem_object *obj);
struct page **etnaviv_gem_get_pages(struct etnaviv_gem_object *obj);
void etnaviv_gem_put_pages(struct etnaviv_gem_object *obj);
@@ -108,6 +108,10 @@ struct drm_gem_object *etnaviv_gem_prime_import_sg_table(struct drm_device *dev,
if (ret)
goto fail;
+ ret = etnaviv_gem_obj_add(dev, &etnaviv_obj->base);
+ if (ret)
+ goto fail;
+
return &etnaviv_obj->base;
fail:
@@ -529,7 +529,9 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
}
/* Now program the hardware */
+ mutex_lock(&gpu->drm->struct_mutex);
etnaviv_gpu_hw_init(gpu);
+ mutex_unlock(&gpu->drm->struct_mutex);
pm_runtime_mark_last_busy(gpu->dev);
pm_runtime_put_autosuspend(gpu->dev);