Commit 0226ba39 authored by Simon Ser's avatar Simon Ser

drm: extract closefb logic in separate function

drm_mode_rmfb performs two operations: drop the FB from the
file_priv->fbs list, and make sure the FB is no longer used on a
plane.

In the next commit an IOCTL which only does so former will be
introduced, so let's split it into a separate function.

No functional change, only refactoring.

v2: no change
Signed-off-by: default avatarSimon Ser <contact@emersion.fr>
Cc: Hans de Goede <hdegoede@redhat.com>
Cc: Dennis Filder <d.filder@web.de>
Cc: Daniel Vetter <daniel@ffwll.ch>
Cc: Pekka Paalanen <ppaalanen@gmail.com>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Sean Paul <seanpaul@chromium.org>
Reviewed-by: default avatarDaniel Stone <daniels@collabora.com>
Reviewed-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20231020101926.145327-1-contact@emersion.fr
parent 80683bf4
...@@ -394,6 +394,31 @@ static void drm_mode_rmfb_work_fn(struct work_struct *w) ...@@ -394,6 +394,31 @@ static void drm_mode_rmfb_work_fn(struct work_struct *w)
} }
} }
static int drm_mode_closefb(struct drm_framebuffer *fb,
struct drm_file *file_priv)
{
struct drm_framebuffer *fbl;
bool found = false;
mutex_lock(&file_priv->fbs_lock);
list_for_each_entry(fbl, &file_priv->fbs, filp_head)
if (fb == fbl)
found = true;
if (!found) {
mutex_unlock(&file_priv->fbs_lock);
return -ENOENT;
}
list_del_init(&fb->filp_head);
mutex_unlock(&file_priv->fbs_lock);
/* Drop the reference that was stored in the fbs list */
drm_framebuffer_put(fb);
return 0;
}
/** /**
* drm_mode_rmfb - remove an FB from the configuration * drm_mode_rmfb - remove an FB from the configuration
* @dev: drm device * @dev: drm device
...@@ -410,9 +435,8 @@ static void drm_mode_rmfb_work_fn(struct work_struct *w) ...@@ -410,9 +435,8 @@ static void drm_mode_rmfb_work_fn(struct work_struct *w)
int drm_mode_rmfb(struct drm_device *dev, u32 fb_id, int drm_mode_rmfb(struct drm_device *dev, u32 fb_id,
struct drm_file *file_priv) struct drm_file *file_priv)
{ {
struct drm_framebuffer *fb = NULL; struct drm_framebuffer *fb;
struct drm_framebuffer *fbl = NULL; int ret;
int found = 0;
if (!drm_core_check_feature(dev, DRIVER_MODESET)) if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -421,24 +445,13 @@ int drm_mode_rmfb(struct drm_device *dev, u32 fb_id, ...@@ -421,24 +445,13 @@ int drm_mode_rmfb(struct drm_device *dev, u32 fb_id,
if (!fb) if (!fb)
return -ENOENT; return -ENOENT;
mutex_lock(&file_priv->fbs_lock); ret = drm_mode_closefb(fb, file_priv);
list_for_each_entry(fbl, &file_priv->fbs, filp_head) if (ret != 0) {
if (fb == fbl)
found = 1;
if (!found) {
mutex_unlock(&file_priv->fbs_lock);
goto fail_unref;
}
list_del_init(&fb->filp_head);
mutex_unlock(&file_priv->fbs_lock);
/* drop the reference we picked up in framebuffer lookup */
drm_framebuffer_put(fb); drm_framebuffer_put(fb);
return ret;
}
/* /*
* we now own the reference that was stored in the fbs list
*
* drm_framebuffer_remove may fail with -EINTR on pending signals, * drm_framebuffer_remove may fail with -EINTR on pending signals,
* so run this in a separate stack as there's no way to correctly * so run this in a separate stack as there's no way to correctly
* handle this after the fb is already removed from the lookup table. * handle this after the fb is already removed from the lookup table.
...@@ -457,10 +470,6 @@ int drm_mode_rmfb(struct drm_device *dev, u32 fb_id, ...@@ -457,10 +470,6 @@ int drm_mode_rmfb(struct drm_device *dev, u32 fb_id,
drm_framebuffer_put(fb); drm_framebuffer_put(fb);
return 0; return 0;
fail_unref:
drm_framebuffer_put(fb);
return -ENOENT;
} }
int drm_mode_rmfb_ioctl(struct drm_device *dev, int drm_mode_rmfb_ioctl(struct drm_device *dev,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment