Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d0f37cf6 authored by Dave Airlie's avatar Dave Airlie
Browse files

drm/mode: move framebuffer reference into object.



This is the initial code to add references to some mode objects.
In the future we need to start reference counting connectors so
firstly I want to reorganise the code so the framebuffer ref counting
uses the same paths.

This patch shouldn't change any functionality, just moves the kref.

[airlied: move kerneldoc as well]
Reviewed-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 747a598f
Loading
Loading
Loading
Loading
+38 −34
Original line number Original line Diff line number Diff line
@@ -275,7 +275,8 @@ EXPORT_SYMBOL(drm_get_format_name);
static int drm_mode_object_get_reg(struct drm_device *dev,
static int drm_mode_object_get_reg(struct drm_device *dev,
				   struct drm_mode_object *obj,
				   struct drm_mode_object *obj,
				   uint32_t obj_type,
				   uint32_t obj_type,
				   bool register_obj)
				   bool register_obj,
				   void (*obj_free_cb)(struct kref *kref))
{
{
	int ret;
	int ret;


@@ -288,6 +289,10 @@ static int drm_mode_object_get_reg(struct drm_device *dev,
		 */
		 */
		obj->id = ret;
		obj->id = ret;
		obj->type = obj_type;
		obj->type = obj_type;
		if (obj_free_cb) {
			obj->free_cb = obj_free_cb;
			kref_init(&obj->refcount);
		}
	}
	}
	mutex_unlock(&dev->mode_config.idr_mutex);
	mutex_unlock(&dev->mode_config.idr_mutex);


@@ -311,7 +316,7 @@ static int drm_mode_object_get_reg(struct drm_device *dev,
int drm_mode_object_get(struct drm_device *dev,
int drm_mode_object_get(struct drm_device *dev,
			struct drm_mode_object *obj, uint32_t obj_type)
			struct drm_mode_object *obj, uint32_t obj_type)
{
{
	return drm_mode_object_get_reg(dev, obj, obj_type, true);
	return drm_mode_object_get_reg(dev, obj, obj_type, true, NULL);
}
}


static void drm_mode_object_register(struct drm_device *dev,
static void drm_mode_object_register(struct drm_device *dev,
@@ -389,10 +394,35 @@ struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
}
}
EXPORT_SYMBOL(drm_mode_object_find);
EXPORT_SYMBOL(drm_mode_object_find);


void drm_mode_object_unreference(struct drm_mode_object *obj)
{
	if (obj->free_cb) {
		DRM_DEBUG("OBJ ID: %d (%d)\n", obj->id, atomic_read(&obj->refcount.refcount));
		kref_put(&obj->refcount, obj->free_cb);
	}
}
EXPORT_SYMBOL(drm_mode_object_unreference);

/**
 * drm_mode_object_reference - incr the fb refcnt
 * @obj: mode_object
 *
 * This function operates only on refcounted objects.
 * This functions increments the object's refcount.
 */
void drm_mode_object_reference(struct drm_mode_object *obj)
{
	if (obj->free_cb) {
		DRM_DEBUG("OBJ ID: %d (%d)\n", obj->id, atomic_read(&obj->refcount.refcount));
		kref_get(&obj->refcount);
	}
}
EXPORT_SYMBOL(drm_mode_object_reference);

static void drm_framebuffer_free(struct kref *kref)
static void drm_framebuffer_free(struct kref *kref)
{
{
	struct drm_framebuffer *fb =
	struct drm_framebuffer *fb =
			container_of(kref, struct drm_framebuffer, refcount);
			container_of(kref, struct drm_framebuffer, base.refcount);
	struct drm_device *dev = fb->dev;
	struct drm_device *dev = fb->dev;


	/*
	/*
@@ -430,12 +460,12 @@ int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb,
	int ret;
	int ret;


	mutex_lock(&dev->mode_config.fb_lock);
	mutex_lock(&dev->mode_config.fb_lock);
	kref_init(&fb->refcount);
	INIT_LIST_HEAD(&fb->filp_head);
	INIT_LIST_HEAD(&fb->filp_head);
	fb->dev = dev;
	fb->dev = dev;
	fb->funcs = funcs;
	fb->funcs = funcs;


	ret = drm_mode_object_get(dev, &fb->base, DRM_MODE_OBJECT_FB);
	ret = drm_mode_object_get_reg(dev, &fb->base, DRM_MODE_OBJECT_FB,
				      true, drm_framebuffer_free);
	if (ret)
	if (ret)
		goto out;
		goto out;


@@ -482,7 +512,7 @@ struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev,
	mutex_lock(&dev->mode_config.fb_lock);
	mutex_lock(&dev->mode_config.fb_lock);
	fb = __drm_framebuffer_lookup(dev, id);
	fb = __drm_framebuffer_lookup(dev, id);
	if (fb) {
	if (fb) {
		if (!kref_get_unless_zero(&fb->refcount))
		if (!kref_get_unless_zero(&fb->base.refcount))
			fb = NULL;
			fb = NULL;
	}
	}
	mutex_unlock(&dev->mode_config.fb_lock);
	mutex_unlock(&dev->mode_config.fb_lock);
@@ -491,32 +521,6 @@ struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev,
}
}
EXPORT_SYMBOL(drm_framebuffer_lookup);
EXPORT_SYMBOL(drm_framebuffer_lookup);


/**
 * drm_framebuffer_unreference - unref a framebuffer
 * @fb: framebuffer to unref
 *
 * This functions decrements the fb's refcount and frees it if it drops to zero.
 */
void drm_framebuffer_unreference(struct drm_framebuffer *fb)
{
	DRM_DEBUG("%p: FB ID: %d (%d)\n", fb, fb->base.id, atomic_read(&fb->refcount.refcount));
	kref_put(&fb->refcount, drm_framebuffer_free);
}
EXPORT_SYMBOL(drm_framebuffer_unreference);

/**
 * drm_framebuffer_reference - incr the fb refcnt
 * @fb: framebuffer
 *
 * This functions increments the fb's refcount.
 */
void drm_framebuffer_reference(struct drm_framebuffer *fb)
{
	DRM_DEBUG("%p: FB ID: %d (%d)\n", fb, fb->base.id, atomic_read(&fb->refcount.refcount));
	kref_get(&fb->refcount);
}
EXPORT_SYMBOL(drm_framebuffer_reference);

/**
/**
 * drm_framebuffer_unregister_private - unregister a private fb from the lookup idr
 * drm_framebuffer_unregister_private - unregister a private fb from the lookup idr
 * @fb: fb to unregister
 * @fb: fb to unregister
@@ -902,7 +906,7 @@ int drm_connector_init(struct drm_device *dev,


	drm_modeset_lock_all(dev);
	drm_modeset_lock_all(dev);


	ret = drm_mode_object_get_reg(dev, &connector->base, DRM_MODE_OBJECT_CONNECTOR, false);
	ret = drm_mode_object_get_reg(dev, &connector->base, DRM_MODE_OBJECT_CONNECTOR, false, NULL);
	if (ret)
	if (ret)
		goto out_unlock;
		goto out_unlock;


@@ -5971,7 +5975,7 @@ void drm_mode_config_cleanup(struct drm_device *dev)
	 */
	 */
	WARN_ON(!list_empty(&dev->mode_config.fb_list));
	WARN_ON(!list_empty(&dev->mode_config.fb_list));
	list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) {
	list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) {
		drm_framebuffer_free(&fb->refcount);
		drm_framebuffer_free(&fb->base.refcount);
	}
	}


	ida_destroy(&dev->mode_config.connector_ida);
	ida_destroy(&dev->mode_config.connector_ida);
+28 −4
Original line number Original line Diff line number Diff line
@@ -49,6 +49,8 @@ struct drm_mode_object {
	uint32_t id;
	uint32_t id;
	uint32_t type;
	uint32_t type;
	struct drm_object_properties *properties;
	struct drm_object_properties *properties;
	struct kref refcount;
	void (*free_cb)(struct kref *kref);
};
};


#define DRM_OBJECT_MAX_PROPERTY 24
#define DRM_OBJECT_MAX_PROPERTY 24
@@ -223,8 +225,8 @@ struct drm_framebuffer {
	 * should be deferred.  In cases like this, the driver would like to
	 * should be deferred.  In cases like this, the driver would like to
	 * hold a ref to the fb even though it has already been removed from
	 * hold a ref to the fb even though it has already been removed from
	 * userspace perspective.
	 * userspace perspective.
	 * The refcount is stored inside the mode object.
	 */
	 */
	struct kref refcount;
	/*
	/*
	 * Place on the dev->mode_config.fb_list, access protected by
	 * Place on the dev->mode_config.fb_list, access protected by
	 * dev->mode_config.fb_lock.
	 * dev->mode_config.fb_lock.
@@ -2377,8 +2379,6 @@ extern int drm_framebuffer_init(struct drm_device *dev,
				const struct drm_framebuffer_funcs *funcs);
				const struct drm_framebuffer_funcs *funcs);
extern struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev,
extern struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev,
						      uint32_t id);
						      uint32_t id);
extern void drm_framebuffer_unreference(struct drm_framebuffer *fb);
extern void drm_framebuffer_reference(struct drm_framebuffer *fb);
extern void drm_framebuffer_remove(struct drm_framebuffer *fb);
extern void drm_framebuffer_remove(struct drm_framebuffer *fb);
extern void drm_framebuffer_cleanup(struct drm_framebuffer *fb);
extern void drm_framebuffer_cleanup(struct drm_framebuffer *fb);
extern void drm_framebuffer_unregister_private(struct drm_framebuffer *fb);
extern void drm_framebuffer_unregister_private(struct drm_framebuffer *fb);
@@ -2436,6 +2436,8 @@ extern int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,
					 int gamma_size);
					 int gamma_size);
extern struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
extern struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
		uint32_t id, uint32_t type);
		uint32_t id, uint32_t type);
void drm_mode_object_reference(struct drm_mode_object *obj);
void drm_mode_object_unreference(struct drm_mode_object *obj);


/* IOCTLs */
/* IOCTLs */
extern int drm_mode_getresources(struct drm_device *dev,
extern int drm_mode_getresources(struct drm_device *dev,
@@ -2605,6 +2607,28 @@ static inline uint32_t drm_color_lut_extract(uint32_t user_input,
	return clamp_val(val, 0, max);
	return clamp_val(val, 0, max);
}
}


/*
 * drm_framebuffer_reference - incr the fb refcnt
 * @fb: framebuffer
 *
 * This functions increments the fb's refcount.
 */
static inline void drm_framebuffer_reference(struct drm_framebuffer *fb)
{
	drm_mode_object_reference(&fb->base);
}

/**
 * drm_framebuffer_unreference - unref a framebuffer
 * @fb: framebuffer to unref
 *
 * This functions decrements the fb's refcount and frees it if it drops to zero.
 */
static inline void drm_framebuffer_unreference(struct drm_framebuffer *fb)
{
	drm_mode_object_unreference(&fb->base);
}

/**
/**
 * drm_framebuffer_read_refcount - read the framebuffer reference count.
 * drm_framebuffer_read_refcount - read the framebuffer reference count.
 * @fb: framebuffer
 * @fb: framebuffer
@@ -2613,7 +2637,7 @@ static inline uint32_t drm_color_lut_extract(uint32_t user_input,
 */
 */
static inline uint32_t drm_framebuffer_read_refcount(struct drm_framebuffer *fb)
static inline uint32_t drm_framebuffer_read_refcount(struct drm_framebuffer *fb)
{
{
	return atomic_read(&fb->refcount.refcount);
	return atomic_read(&fb->base.refcount.refcount);
}
}


/* Plane list iterator for legacy (overlay only) planes. */
/* Plane list iterator for legacy (overlay only) planes. */