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