Similar to rmfb but does not have the side effect of shutting down any pipes that are scanning out the fb. Advantages compared to rmfb: * slightly easier userspace, it doesn't have to track fb-id's until they come of the screen * it might be desirable to keep existing layers on screen across process restart (for crashing or upgrading the compositor) Disadvantages: * depending on userspace architecture, layers left on screen could be considered an information leak, ie. new incoming master process has access to buffers that are still being scanned out. Signed-off-by: Rob Clark <robdclark@xxxxxxxxx> --- drivers/gpu/drm/drm_crtc_internal.h | 2 ++ drivers/gpu/drm/drm_framebuffer.c | 66 +++++++++++++++++++++++++++---------- drivers/gpu/drm/drm_ioctl.c | 1 + include/uapi/drm/drm.h | 1 + include/uapi/drm/drm_mode.h | 20 +++++++++++ 5 files changed, 72 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h index 8c04275..dafa17b 100644 --- a/drivers/gpu/drm/drm_crtc_internal.h +++ b/drivers/gpu/drm/drm_crtc_internal.h @@ -167,6 +167,8 @@ int drm_mode_addfb2(struct drm_device *dev, void *data, struct drm_file *file_priv); int drm_mode_rmfb(struct drm_device *dev, void *data, struct drm_file *file_priv); +int drm_mode_unref_fb(struct drm_device *dev, + void *data, struct drm_file *file_priv); int drm_mode_getfb(struct drm_device *dev, void *data, struct drm_file *file_priv); int drm_mode_dirtyfb_ioctl(struct drm_device *dev, diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c index e8f9c13..8f2afdf 100644 --- a/drivers/gpu/drm/drm_framebuffer.c +++ b/drivers/gpu/drm/drm_framebuffer.c @@ -356,31 +356,17 @@ static void drm_mode_rmfb_work_fn(struct work_struct *w) } } -/** - * drm_mode_rmfb - remove an FB from the configuration - * @dev: drm device for the ioctl - * @data: data pointer for the ioctl - * @file_priv: drm file for the ioctl call - * - * Remove the FB specified by the user. - * - * Called by the user via ioctl. - * - * Returns: - * Zero on success, negative errno on failure. - */ -int drm_mode_rmfb(struct drm_device *dev, - void *data, struct drm_file *file_priv) +static int __rmfb(struct drm_device *dev, struct drm_file *file_priv, + uint32_t fb_id, bool rmfb) { struct drm_framebuffer *fb = NULL; struct drm_framebuffer *fbl = NULL; - uint32_t *id = data; int found = 0; if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -EINVAL; - fb = drm_framebuffer_lookup(dev, *id); + fb = drm_framebuffer_lookup(dev, fb_id); if (!fb) return -ENOENT; @@ -406,7 +392,7 @@ int drm_mode_rmfb(struct drm_device *dev, * 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. */ - if (drm_framebuffer_read_refcount(fb) > 1) { + if (rmfb && drm_framebuffer_read_refcount(fb) > 1) { struct drm_mode_rmfb_work arg; INIT_WORK_ONSTACK(&arg.work, drm_mode_rmfb_work_fn); @@ -427,6 +413,50 @@ int drm_mode_rmfb(struct drm_device *dev, } /** + * drm_mode_rmfb - remove an FB from the configuration + * @dev: drm device for the ioctl + * @data: data pointer for the ioctl + * @file_priv: drm file for the ioctl call + * + * Remove the FB specified by the user. + * + * Called by the user via ioctl. + * + * Returns: + * Zero on success, negative errno on failure. + */ +int drm_mode_rmfb(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + uint32_t *id = data; + return __rmfb(dev, file_priv, *id, true); +} + +/** + * drm_mode_unref_fb - unreference an FB + * @dev: drm device for the ioctl + * @data: data pointer for the ioctl + * @file_priv: drm file for the ioctl call + * + * Unreference the FB specified by the user. + * + * Called by the user via ioctl. + * + * Returns: + * Zero on success, negative errno on failure. + */ +int drm_mode_unref_fb(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_mode_unref_fb *r = data; + + if (r->pad) + return -EINVAL; + + return __rmfb(dev, file_priv, r->fb_id, false); +} + +/** * drm_mode_getfb - get FB info * @dev: drm device for the ioctl * @data: data pointer for the ioctl diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index 7d6deaa..a113972 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -642,6 +642,7 @@ static const struct drm_ioctl_desc drm_ioctls[] = { DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATOMIC, drm_mode_atomic_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATEPROPBLOB, drm_mode_createblob_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROYPROPBLOB, drm_mode_destroyblob_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_UNREFFB, drm_mode_unref_fb, DRM_CONTROL_ALLOW|DRM_UNLOCKED), }; #define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h index b2c5284..b485253 100644 --- a/include/uapi/drm/drm.h +++ b/include/uapi/drm/drm.h @@ -813,6 +813,7 @@ extern "C" { #define DRM_IOCTL_MODE_ATOMIC DRM_IOWR(0xBC, struct drm_mode_atomic) #define DRM_IOCTL_MODE_CREATEPROPBLOB DRM_IOWR(0xBD, struct drm_mode_create_blob) #define DRM_IOCTL_MODE_DESTROYPROPBLOB DRM_IOWR(0xBE, struct drm_mode_destroy_blob) +#define DRM_IOCTL_MODE_UNREFFB DRM_IOR( 0xBF, struct drm_mode_unref_fb) /** * Device specific ioctls should only be in their respective headers diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index 8c67fc0..1804b2d 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -685,6 +685,26 @@ struct drm_mode_destroy_blob { __u32 blob_id; }; +/** + * Similar to rmfb but does not have the side effect of shutting down any + * pipes that are scanning out the fb. + * + * Advantages compared to rmfb: + * * slightly easier userspace, it doesn't have to track fb-id's until + * they come of the screen + * * it might be desirable to keep existing layers on screen across + * process restart (for crashing or upgrading the compositor) + * + * Disadvantages: + * * depending on userspace architecture, layers left on screen could + * be considered an information leak, ie. new incoming master process + * has access to buffers that are still being scanned out. + */ +struct drm_mode_unref_fb { + __u32 pad; /* must be zero for now.. */ + __u32 fb_id; +}; + #if defined(__cplusplus) } #endif -- 2.9.3 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel