From: Rob Clark <robdclark@xxxxxxxxxxxx> Add DRM_CLIENT_CAP_SCHED_MODE so that userspace can control the scheduling mode for nonblocking atomic commits. Userspace such as android, which treats the display pipeline as realtime (SCHED_FIFO) should set DRM_CLIENT_CAP_SCHED_FIFO to prevent userspace components of the display pipeline (like surfaceflinger) from preempting atomic commit_work. This cap may only be set by the drm master, after setting the DRM_CLIENT_CAP_ATOMIC cap. The scheduling mode is returned to default (SCHED_NORMAL) after master is dropped. Signed-off-by: Rob Clark <robdclark@xxxxxxxxxxxx> --- drivers/gpu/drm/drm_auth.c | 4 ++++ drivers/gpu/drm/drm_crtc.c | 26 ++++++++++++++++++++++++++ drivers/gpu/drm/drm_ioctl.c | 13 +++++++++++++ include/drm/drm_crtc.h | 2 ++ include/uapi/drm/drm.h | 13 +++++++++++++ 5 files changed, 58 insertions(+) diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c index f2d46b7ac6f9..217f422389f9 100644 --- a/drivers/gpu/drm/drm_auth.c +++ b/drivers/gpu/drm/drm_auth.c @@ -31,6 +31,7 @@ #include <linux/slab.h> #include <drm/drm_auth.h> +#include <drm/drm_crtc.h> #include <drm/drm_drv.h> #include <drm/drm_file.h> #include <drm/drm_lease.h> @@ -335,6 +336,9 @@ void drm_master_release(struct drm_file *file_priv) drm_lease_revoke(master); } + if (drm_core_check_feature(dev, DRIVER_ATOMIC) && file_priv->is_master) + drm_crtc_set_sched_mode(dev, DRM_CLIENT_CAP_SCHED_NORMAL); + /* drop the master reference held by the file priv */ if (file_priv->master) drm_master_put(&file_priv->master); diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 4f7c0bfce0a3..02f2be0b1700 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -93,6 +93,32 @@ struct drm_crtc *drm_crtc_from_index(struct drm_device *dev, int idx) } EXPORT_SYMBOL(drm_crtc_from_index); +/** + * drm_crtc_set_sched_mode: + * @dev: DRM device + * @mode: one of DRM_CLIENT_CAP_SCHED_x + * + * Set the scheduling mode for per-CRTC kthread workers. This controls + * whether nonblocking atomic commits will run with SCHED_NORMAL or + * SCHED_FIFO (rt) priority. + */ +void drm_crtc_set_sched_mode(struct drm_device *dev, int mode) +{ + struct drm_crtc *crtc; + + drm_for_each_crtc(crtc, dev) { + switch (mode) { + case DRM_CLIENT_CAP_SCHED_NORMAL: + /* zero is default nice value for kthreads: */ + sched_set_normal(crtc->worker->task, 0); + break; + case DRM_CLIENT_CAP_SCHED_FIFO: + sched_set_fifo(crtc->worker->task); + break; + } + } +} + int drm_crtc_force_disable(struct drm_crtc *crtc) { struct drm_mode_set set = { diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index 789ee65ac1f5..44920621571c 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -362,6 +362,19 @@ drm_setclientcap(struct drm_device *dev, void *data, struct drm_file *file_priv) return -EINVAL; file_priv->writeback_connectors = req->value; break; + case DRM_CLIENT_CAP_SCHED_MODE: + if (!file_priv->is_master) + return -EPERM; + if (!file_priv->atomic) + return -EOPNOTSUPP; + switch (req->value) { + case DRM_CLIENT_CAP_SCHED_NORMAL: + case DRM_CLIENT_CAP_SCHED_FIFO: + drm_crtc_set_sched_mode(dev, req->value); + return 0; + default: + return -EINVAL; + } default: return -EINVAL; } diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 8964a3732bca..6dd4d01b7191 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -1245,6 +1245,8 @@ static inline uint32_t drm_crtc_mask(const struct drm_crtc *crtc) int drm_mode_set_config_internal(struct drm_mode_set *set); struct drm_crtc *drm_crtc_from_index(struct drm_device *dev, int idx); +void drm_crtc_set_sched_mode(struct drm_device *dev, int mode); + /** * drm_crtc_find - look up a CRTC object from its ID * @dev: DRM device diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h index 808b48a93330..989e007ef608 100644 --- a/include/uapi/drm/drm.h +++ b/include/uapi/drm/drm.h @@ -698,6 +698,19 @@ struct drm_get_cap { */ #define DRM_CLIENT_CAP_WRITEBACK_CONNECTORS 5 +/** + * DRM_CLIENT_CAP_SCHED_MODE + * + * Allow userspace to control the scheduling parameters for nonblocking + * commit. The default is SCHED_NORMAL/CFS. Userspace using SCHED_FIFO + * in the rendering/display pipeline should use DRM_CLIENT_CAP_SCHED_FIFO + * to prevent userspace portions of the display pipeline from preempting + * nonblocking commit_work. + */ +#define DRM_CLIENT_CAP_SCHED_MODE 6 +# define DRM_CLIENT_CAP_SCHED_NORMAL 0 +# define DRM_CLIENT_CAP_SCHED_FIFO 1 + /** DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */ struct drm_set_client_cap { __u64 capability; -- 2.26.2 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel