[PATCH 6/7] drm: Add reference counting to blob properties

2015-05-07 Thread Daniel Vetter
On Mon, Apr 20, 2015 at 07:22:55PM +0100, Daniel Stone wrote:
> Reference-count drm_property_blob objects, changing the API to
> ref/unref.
> 
> Signed-off-by: Daniel Stone 

Merged up to this on (except patch 2) to topic/drm-misc.

Thanks, Daniel
> ---
>  drivers/gpu/drm/drm_crtc.c | 164 
> +
>  include/drm/drm_crtc.h |  17 ++---
>  2 files changed, 159 insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
> index 9947078..03245fb 100644
> --- a/drivers/gpu/drm/drm_crtc.c
> +++ b/drivers/gpu/drm/drm_crtc.c
> @@ -352,7 +352,9 @@ static struct drm_mode_object *_object_find(struct 
> drm_device *dev,
>   if (obj && obj->id != id)
>   obj = NULL;
>   /* don't leak out unref'd fb's */
> - if (obj && (obj->type == DRM_MODE_OBJECT_FB))
> + if (obj &&
> + (obj->type == DRM_MODE_OBJECT_FB ||
> +  obj->type == DRM_MODE_OBJECT_BLOB))
>   obj = NULL;
>   mutex_unlock(>mode_config.idr_mutex);
>  
> @@ -377,7 +379,7 @@ struct drm_mode_object *drm_mode_object_find(struct 
> drm_device *dev,
>  
>   /* Framebuffers are reference counted and need their own lookup
>* function.*/
> - WARN_ON(type == DRM_MODE_OBJECT_FB);
> + WARN_ON(type == DRM_MODE_OBJECT_FB || type == DRM_MODE_OBJECT_BLOB);
>   obj = _object_find(dev, id, type);
>   return obj;
>  }
> @@ -4200,7 +4202,7 @@ done:
>   return ret;
>  }
>  
> -static struct drm_property_blob *
> +struct drm_property_blob *
>  drm_property_create_blob(struct drm_device *dev, size_t length,
>const void *data)
>  {
> @@ -4215,6 +4217,7 @@ drm_property_create_blob(struct drm_device *dev, size_t 
> length,
>   return NULL;
>  
>   blob->length = length;
> + blob->dev = dev;
>  
>   memcpy(blob->data, data, length);
>  
> @@ -4227,25 +4230,148 @@ drm_property_create_blob(struct drm_device *dev, 
> size_t length,
>   return NULL;
>   }
>  
> + kref_init(>refcount);
> +
>   list_add_tail(>head, >mode_config.property_blob_list);
>  
>   mutex_unlock(>mode_config.blob_lock);
>  
>   return blob;
>  }
> +EXPORT_SYMBOL(drm_property_create_blob);
>  
> -static void drm_property_destroy_blob(struct drm_device *dev,
> -struct drm_property_blob *blob)
> +/**
> + * drm_property_free_blob - Blob property destructor
> + *
> + * Internal free function for blob properties; must not be used directly.
> + *
> + * @param kref Reference
> + */
> +static void drm_property_free_blob(struct kref *kref)
>  {
> - mutex_lock(>mode_config.blob_lock);
> - drm_mode_object_put(dev, >base);
> + struct drm_property_blob *blob =
> + container_of(kref, struct drm_property_blob, refcount);
> +
> + WARN_ON(!mutex_is_locked(>dev->mode_config.blob_lock));
> +
>   list_del(>head);
> - mutex_unlock(>mode_config.blob_lock);
> + drm_mode_object_put(blob->dev, >base);
>  
>   kfree(blob);
>  }
>  
>  /**
> + * drm_property_unreference_blob - Unreference a blob property
> + *
> + * Drop a reference on a blob property. May free the object.
> + *
> + * @param dev  Device the blob was created on
> + * @param blob Pointer to blob property
> + */
> +void drm_property_unreference_blob(struct drm_property_blob *blob)
> +{
> + struct drm_device *dev;
> +
> + if (!blob)
> + return;
> +
> + dev = blob->dev;
> +
> + DRM_DEBUG("%p: blob ID: %d (%d)\n", blob, blob->base.id, 
> atomic_read(>refcount.refcount));
> +
> + if (kref_put_mutex(>refcount, drm_property_free_blob,
> +>mode_config.blob_lock))
> + mutex_unlock(>dev->mode_config.blob_lock);
> + else
> + might_lock(>mode_config.blob_lock);
> +
> +}
> +EXPORT_SYMBOL(drm_property_unreference_blob);
> +
> +/**
> + * drm_property_unreference_blob_locked - Unreference a blob property with 
> blob_lock held
> + *
> + * Drop a reference on a blob property. May free the object. This must be
> + * called with blob_lock held.
> + *
> + * @param dev  Device the blob was created on
> + * @param blob Pointer to blob property
> + */
> +static void drm_property_unreference_blob_locked(struct drm_property_blob 
> *blob)
> +{
> + if (!blob)
> + return;
> +
> + DRM_DEBUG("%p: blob ID: %d (%d)\n", blob, blob->base.id, 
> atomic_read(>refcount.refcount));
> +
> + kref_put(>refcount, drm_property_free_blob);
> +}
> +
> +/**
> + * drm_property_reference_blob - Take a reference on an existing property
> + *
> + * Take a new reference on an existing blob property.
> + *
> + * @param blob Pointer to blob property
> + */
> +struct drm_property_blob *drm_property_reference_blob(struct 
> drm_property_blob *blob)
> +{
> + DRM_DEBUG("%p: blob ID: %d (%d)\n", blob, blob->base.id, 
> atomic_read(>refcount.refcount));
> + kref_get(>refcount);
> + return blob;
> 

[PATCH 6/7] drm: Add reference counting to blob properties

2015-04-20 Thread Daniel Stone
Reference-count drm_property_blob objects, changing the API to
ref/unref.

Signed-off-by: Daniel Stone 
---
 drivers/gpu/drm/drm_crtc.c | 164 +
 include/drm/drm_crtc.h |  17 ++---
 2 files changed, 159 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 9947078..03245fb 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -352,7 +352,9 @@ static struct drm_mode_object *_object_find(struct 
drm_device *dev,
if (obj && obj->id != id)
obj = NULL;
/* don't leak out unref'd fb's */
-   if (obj && (obj->type == DRM_MODE_OBJECT_FB))
+   if (obj &&
+   (obj->type == DRM_MODE_OBJECT_FB ||
+obj->type == DRM_MODE_OBJECT_BLOB))
obj = NULL;
mutex_unlock(>mode_config.idr_mutex);

@@ -377,7 +379,7 @@ struct drm_mode_object *drm_mode_object_find(struct 
drm_device *dev,

/* Framebuffers are reference counted and need their own lookup
 * function.*/
-   WARN_ON(type == DRM_MODE_OBJECT_FB);
+   WARN_ON(type == DRM_MODE_OBJECT_FB || type == DRM_MODE_OBJECT_BLOB);
obj = _object_find(dev, id, type);
return obj;
 }
@@ -4200,7 +4202,7 @@ done:
return ret;
 }

-static struct drm_property_blob *
+struct drm_property_blob *
 drm_property_create_blob(struct drm_device *dev, size_t length,
 const void *data)
 {
@@ -4215,6 +4217,7 @@ drm_property_create_blob(struct drm_device *dev, size_t 
length,
return NULL;

blob->length = length;
+   blob->dev = dev;

memcpy(blob->data, data, length);

@@ -4227,25 +4230,148 @@ drm_property_create_blob(struct drm_device *dev, 
size_t length,
return NULL;
}

+   kref_init(>refcount);
+
list_add_tail(>head, >mode_config.property_blob_list);

mutex_unlock(>mode_config.blob_lock);

return blob;
 }
+EXPORT_SYMBOL(drm_property_create_blob);

-static void drm_property_destroy_blob(struct drm_device *dev,
-  struct drm_property_blob *blob)
+/**
+ * drm_property_free_blob - Blob property destructor
+ *
+ * Internal free function for blob properties; must not be used directly.
+ *
+ * @param kref Reference
+ */
+static void drm_property_free_blob(struct kref *kref)
 {
-   mutex_lock(>mode_config.blob_lock);
-   drm_mode_object_put(dev, >base);
+   struct drm_property_blob *blob =
+   container_of(kref, struct drm_property_blob, refcount);
+
+   WARN_ON(!mutex_is_locked(>dev->mode_config.blob_lock));
+
list_del(>head);
-   mutex_unlock(>mode_config.blob_lock);
+   drm_mode_object_put(blob->dev, >base);

kfree(blob);
 }

 /**
+ * drm_property_unreference_blob - Unreference a blob property
+ *
+ * Drop a reference on a blob property. May free the object.
+ *
+ * @param dev  Device the blob was created on
+ * @param blob Pointer to blob property
+ */
+void drm_property_unreference_blob(struct drm_property_blob *blob)
+{
+   struct drm_device *dev;
+
+   if (!blob)
+   return;
+
+   dev = blob->dev;
+
+   DRM_DEBUG("%p: blob ID: %d (%d)\n", blob, blob->base.id, 
atomic_read(>refcount.refcount));
+
+   if (kref_put_mutex(>refcount, drm_property_free_blob,
+  >mode_config.blob_lock))
+   mutex_unlock(>dev->mode_config.blob_lock);
+   else
+   might_lock(>mode_config.blob_lock);
+
+}
+EXPORT_SYMBOL(drm_property_unreference_blob);
+
+/**
+ * drm_property_unreference_blob_locked - Unreference a blob property with 
blob_lock held
+ *
+ * Drop a reference on a blob property. May free the object. This must be
+ * called with blob_lock held.
+ *
+ * @param dev  Device the blob was created on
+ * @param blob Pointer to blob property
+ */
+static void drm_property_unreference_blob_locked(struct drm_property_blob 
*blob)
+{
+   if (!blob)
+   return;
+
+   DRM_DEBUG("%p: blob ID: %d (%d)\n", blob, blob->base.id, 
atomic_read(>refcount.refcount));
+
+   kref_put(>refcount, drm_property_free_blob);
+}
+
+/**
+ * drm_property_reference_blob - Take a reference on an existing property
+ *
+ * Take a new reference on an existing blob property.
+ *
+ * @param blob Pointer to blob property
+ */
+struct drm_property_blob *drm_property_reference_blob(struct drm_property_blob 
*blob)
+{
+   DRM_DEBUG("%p: blob ID: %d (%d)\n", blob, blob->base.id, 
atomic_read(>refcount.refcount));
+   kref_get(>refcount);
+   return blob;
+}
+EXPORT_SYMBOL(drm_property_reference_blob);
+
+/*
+ * Like drm_property_lookup_blob, but does not return an additional reference.
+ * Must be called with blob_lock held.
+ */
+static struct drm_property_blob *__drm_property_lookup_blob(struct drm_device 
*dev,
+   uint32_t id)
+{
+   struct