From 3c12568271e294825df2f5377e1993a4a26a8bc0 Mon Sep 17 00:00:00 2001 From: Jeykumar Sankaran Date: Fri, 14 Dec 2018 15:57:51 -0800 Subject: drm/msm/dpu: use kthread_destroy_worker to release msm workers use kthread_destroy_worker to destroy workers and release their associated kthreads. changes in v3: - introduced in the series changes in v4: - none changes in v5: - none Signed-off-by: Jeykumar Sankaran Signed-off-by: Sean Paul --- drivers/gpu/drm/msm/msm_drv.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/msm/msm_drv.c') diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index d2cdc7b553fe..5f859653442d 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -291,14 +291,12 @@ static int msm_drm_uninit(struct device *dev) /* clean up display commit/event worker threads */ for (i = 0; i < priv->num_crtcs; i++) { if (priv->disp_thread[i].thread) { - kthread_flush_worker(&priv->disp_thread[i].worker); - kthread_stop(priv->disp_thread[i].thread); + kthread_destroy_worker(&priv->disp_thread[i].worker); priv->disp_thread[i].thread = NULL; } if (priv->event_thread[i].thread) { - kthread_flush_worker(&priv->event_thread[i].worker); - kthread_stop(priv->event_thread[i].thread); + kthread_destroy_worker(&priv->event_thread[i].worker); priv->event_thread[i].thread = NULL; } } -- cgit v1.2.3 From 5aeb66563fe22e7ce2e7b403b531630865a87446 Mon Sep 17 00:00:00 2001 From: Jeykumar Sankaran Date: Fri, 14 Dec 2018 15:57:52 -0800 Subject: drm/msm/dpu: use msm wq for vblank events DPU was using one thread per display to dispatch async commits and vblank requests. Since clean up already happened in msm to use the common thread for all the display commits, display threads are only used to cater vblank requests. Since a single thread is sufficient to do the job without any performance hits, use msm workqueue to queue requests. A separate patch is submitted later in this series to remove the display threads altogether. changes in v2: - switch to system wq before removing disp threads (Sean Paul) changes in v3: - none changes in v4: - use msm wq for vblank events changes in v5: - none Signed-off-by: Jeykumar Sankaran Signed-off-by: Sean Paul --- drivers/gpu/drm/msm/msm_drv.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/msm/msm_drv.c') diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 5f859653442d..6c311f92c11d 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -213,7 +213,7 @@ struct vblank_event { bool enable; }; -static void vblank_ctrl_worker(struct kthread_work *work) +static void vblank_ctrl_worker(struct work_struct *work) { struct msm_vblank_ctrl *vbl_ctrl = container_of(work, struct msm_vblank_ctrl, work); @@ -261,8 +261,7 @@ static int vblank_ctrl_queue_work(struct msm_drm_private *priv, list_add_tail(&vbl_ev->node, &vbl_ctrl->event_list); spin_unlock_irqrestore(&vbl_ctrl->lock, flags); - kthread_queue_work(&priv->disp_thread[crtc_id].worker, - &vbl_ctrl->work); + queue_work(priv->wq, &vbl_ctrl->work); return 0; } @@ -282,7 +281,7 @@ static int msm_drm_uninit(struct device *dev) * work before drm_irq_uninstall() to avoid work re-enabling an * irq after uninstall has disabled it. */ - kthread_flush_work(&vbl_ctrl->work); + flush_work(&vbl_ctrl->work); list_for_each_entry_safe(vbl_ev, tmp, &vbl_ctrl->event_list, node) { list_del(&vbl_ev->node); kfree(vbl_ev); @@ -489,7 +488,7 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv) INIT_LIST_HEAD(&priv->inactive_list); INIT_LIST_HEAD(&priv->vblank_ctrl.event_list); - kthread_init_work(&priv->vblank_ctrl.work, vblank_ctrl_worker); + INIT_WORK(&priv->vblank_ctrl.work, vblank_ctrl_worker); spin_lock_init(&priv->vblank_ctrl.lock); drm_mode_config_init(ddev); -- cgit v1.2.3 From d9db30ce7d04515d5d09a2517f5559c6f2f03c52 Mon Sep 17 00:00:00 2001 From: Jeykumar Sankaran Date: Fri, 14 Dec 2018 15:57:54 -0800 Subject: drm/msm: clean up display thread Since there are no clients using these threads, cleaning it up. changes in v2: - switch all the dependent clients to use system wq before removing the disp_threads (Sean Paul) changes in v3: - none changes in v4: - none changes in v5: - Rebase on latest tip with [1] (Sean Paul) [1] https://patchwork.freedesktop.org/patch/255105/ Signed-off-by: Jeykumar Sankaran Signed-off-by: Sean Paul --- drivers/gpu/drm/msm/msm_drv.c | 35 +---------------------------------- 1 file changed, 1 insertion(+), 34 deletions(-) (limited to 'drivers/gpu/drm/msm/msm_drv.c') diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 6c311f92c11d..a8a0b246e3a9 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -287,13 +287,8 @@ static int msm_drm_uninit(struct device *dev) kfree(vbl_ev); } - /* clean up display commit/event worker threads */ + /* clean up event worker threads */ for (i = 0; i < priv->num_crtcs; i++) { - if (priv->disp_thread[i].thread) { - kthread_destroy_worker(&priv->disp_thread[i].worker); - priv->disp_thread[i].thread = NULL; - } - if (priv->event_thread[i].thread) { kthread_destroy_worker(&priv->event_thread[i].worker); priv->event_thread[i].thread = NULL; @@ -551,27 +546,6 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv) */ param.sched_priority = 16; for (i = 0; i < priv->num_crtcs; i++) { - - /* initialize display thread */ - priv->disp_thread[i].crtc_id = priv->crtcs[i]->base.id; - kthread_init_worker(&priv->disp_thread[i].worker); - priv->disp_thread[i].dev = ddev; - priv->disp_thread[i].thread = - kthread_run(kthread_worker_fn, - &priv->disp_thread[i].worker, - "crtc_commit:%d", priv->disp_thread[i].crtc_id); - if (IS_ERR(priv->disp_thread[i].thread)) { - DRM_DEV_ERROR(dev, "failed to create crtc_commit kthread\n"); - priv->disp_thread[i].thread = NULL; - goto err_msm_uninit; - } - - ret = sched_setscheduler(priv->disp_thread[i].thread, - SCHED_FIFO, ¶m); - if (ret) - dev_warn(dev, "disp_thread set priority failed: %d\n", - ret); - /* initialize event thread */ priv->event_thread[i].crtc_id = priv->crtcs[i]->base.id; kthread_init_worker(&priv->event_thread[i].worker); @@ -586,13 +560,6 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv) goto err_msm_uninit; } - /** - * event thread should also run at same priority as disp_thread - * because it is handling frame_done events. A lower priority - * event thread and higher priority disp_thread can causes - * frame_pending counters beyond 2. This can lead to commit - * failure at crtc commit level. - */ ret = sched_setscheduler(priv->event_thread[i].thread, SCHED_FIFO, ¶m); if (ret) -- cgit v1.2.3 From 48d1d28eec5cd7ebb8bb30009078feb438172cf2 Mon Sep 17 00:00:00 2001 From: Jeykumar Sankaran Date: Fri, 14 Dec 2018 15:57:55 -0800 Subject: drm/msm: subclass work object for vblank events msm maintains a separate structure to define vblank work definitions and a list to track events submitted to the workqueue. We can avoid this redundant list and its protection mechanism, if we subclass the work object to encapsulate vblank event parameters. changes in v2: - subclass optimization on system wq (Sean Paul) changes in v3: - none changes in v4: - move flush_workqueue before irq uninstall changes in v5: - none Signed-off-by: Jeykumar Sankaran Signed-off-by: Sean Paul --- drivers/gpu/drm/msm/msm_drv.c | 71 ++++++++++++++----------------------------- 1 file changed, 22 insertions(+), 49 deletions(-) (limited to 'drivers/gpu/drm/msm/msm_drv.c') diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index a8a0b246e3a9..5e7b5fa01401 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -207,61 +207,44 @@ u32 msm_readl(const void __iomem *addr) return val; } -struct vblank_event { - struct list_head node; +struct msm_vblank_work { + struct work_struct work; int crtc_id; bool enable; + struct msm_drm_private *priv; }; static void vblank_ctrl_worker(struct work_struct *work) { - struct msm_vblank_ctrl *vbl_ctrl = container_of(work, - struct msm_vblank_ctrl, work); - struct msm_drm_private *priv = container_of(vbl_ctrl, - struct msm_drm_private, vblank_ctrl); + struct msm_vblank_work *vbl_work = container_of(work, + struct msm_vblank_work, work); + struct msm_drm_private *priv = vbl_work->priv; struct msm_kms *kms = priv->kms; - struct vblank_event *vbl_ev, *tmp; - unsigned long flags; - - spin_lock_irqsave(&vbl_ctrl->lock, flags); - list_for_each_entry_safe(vbl_ev, tmp, &vbl_ctrl->event_list, node) { - list_del(&vbl_ev->node); - spin_unlock_irqrestore(&vbl_ctrl->lock, flags); - - if (vbl_ev->enable) - kms->funcs->enable_vblank(kms, - priv->crtcs[vbl_ev->crtc_id]); - else - kms->funcs->disable_vblank(kms, - priv->crtcs[vbl_ev->crtc_id]); - - kfree(vbl_ev); - spin_lock_irqsave(&vbl_ctrl->lock, flags); - } + if (vbl_work->enable) + kms->funcs->enable_vblank(kms, priv->crtcs[vbl_work->crtc_id]); + else + kms->funcs->disable_vblank(kms, priv->crtcs[vbl_work->crtc_id]); - spin_unlock_irqrestore(&vbl_ctrl->lock, flags); + kfree(vbl_work); } static int vblank_ctrl_queue_work(struct msm_drm_private *priv, int crtc_id, bool enable) { - struct msm_vblank_ctrl *vbl_ctrl = &priv->vblank_ctrl; - struct vblank_event *vbl_ev; - unsigned long flags; + struct msm_vblank_work *vbl_work; - vbl_ev = kzalloc(sizeof(*vbl_ev), GFP_ATOMIC); - if (!vbl_ev) + vbl_work = kzalloc(sizeof(*vbl_work), GFP_ATOMIC); + if (!vbl_work) return -ENOMEM; - vbl_ev->crtc_id = crtc_id; - vbl_ev->enable = enable; + INIT_WORK(&vbl_work->work, vblank_ctrl_worker); - spin_lock_irqsave(&vbl_ctrl->lock, flags); - list_add_tail(&vbl_ev->node, &vbl_ctrl->event_list); - spin_unlock_irqrestore(&vbl_ctrl->lock, flags); + vbl_work->crtc_id = crtc_id; + vbl_work->enable = enable; + vbl_work->priv = priv; - queue_work(priv->wq, &vbl_ctrl->work); + queue_work(priv->wq, &vbl_work->work); return 0; } @@ -273,19 +256,15 @@ static int msm_drm_uninit(struct device *dev) struct msm_drm_private *priv = ddev->dev_private; struct msm_kms *kms = priv->kms; struct msm_mdss *mdss = priv->mdss; - struct msm_vblank_ctrl *vbl_ctrl = &priv->vblank_ctrl; - struct vblank_event *vbl_ev, *tmp; int i; /* We must cancel and cleanup any pending vblank enable/disable * work before drm_irq_uninstall() to avoid work re-enabling an * irq after uninstall has disabled it. */ - flush_work(&vbl_ctrl->work); - list_for_each_entry_safe(vbl_ev, tmp, &vbl_ctrl->event_list, node) { - list_del(&vbl_ev->node); - kfree(vbl_ev); - } + + flush_workqueue(priv->wq); + destroy_workqueue(priv->wq); /* clean up event worker threads */ for (i = 0; i < priv->num_crtcs; i++) { @@ -315,9 +294,6 @@ static int msm_drm_uninit(struct device *dev) drm_irq_uninstall(ddev); pm_runtime_put_sync(dev); - flush_workqueue(priv->wq); - destroy_workqueue(priv->wq); - if (kms && kms->funcs) kms->funcs->destroy(kms); @@ -482,9 +458,6 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv) priv->wq = alloc_ordered_workqueue("msm", 0); INIT_LIST_HEAD(&priv->inactive_list); - INIT_LIST_HEAD(&priv->vblank_ctrl.event_list); - INIT_WORK(&priv->vblank_ctrl.work, vblank_ctrl_worker); - spin_lock_init(&priv->vblank_ctrl.lock); drm_mode_config_init(ddev); -- cgit v1.2.3 From 7cce8e4efe5e782e130f79f8d55fdad48f2db52d Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 14 Feb 2019 10:19:27 +0300 Subject: drm/msm: fix an error code in the ioctl The copy_to/from_user() functions return the number of bytes remaining to be copied but we should return -EFAULT to the user. Fixes: f05c83e77460 ("drm/msm: add uapi to get/set debug name") Signed-off-by: Dan Carpenter Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_drv.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/msm/msm_drv.c') diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 5e7b5fa01401..87eae44a1006 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -851,8 +851,9 @@ static int msm_ioctl_gem_info(struct drm_device *dev, void *data, ret = -EINVAL; break; } - ret = copy_from_user(msm_obj->name, - u64_to_user_ptr(args->value), args->len); + if (copy_from_user(msm_obj->name, u64_to_user_ptr(args->value), + args->len)) + ret = -EFAULT; msm_obj->name[args->len] = '\0'; for (i = 0; i < args->len; i++) { if (!isprint(msm_obj->name[i])) { @@ -868,8 +869,9 @@ static int msm_ioctl_gem_info(struct drm_device *dev, void *data, } args->len = strlen(msm_obj->name); if (args->value) { - ret = copy_to_user(u64_to_user_ptr(args->value), - msm_obj->name, args->len); + if (copy_to_user(u64_to_user_ptr(args->value), + msm_obj->name, args->len)) + ret = -EFAULT; } break; } -- cgit v1.2.3 From 860433ed2a55dcd18f36c61b3c4fdb12dc76c869 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Tue, 19 Feb 2019 11:40:19 -0700 Subject: drm/msm: Truncate the buffer object name if the copy from user failed (Resend since there was a compile error that I forgot to commit before sending) If there is a error while doing a copy_from_user() for MSM_INFO_SET_NAME make sure to truncate the object name so that there isn't a chance that we'll have random data in the string. This is on top of [1] reported and fixed by Dan Carpenter. [1] https://patchwork.freedesktop.org/series/56656/ Fixes: f05c83e77460 ("drm/msm: add uapi to get/set debug name") Reported-by: Dan Carpenter Signed-off-by: Jordan Crouse Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_drv.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/msm/msm_drv.c') diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 87eae44a1006..906b2bb79f6a 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -852,8 +852,11 @@ static int msm_ioctl_gem_info(struct drm_device *dev, void *data, break; } if (copy_from_user(msm_obj->name, u64_to_user_ptr(args->value), - args->len)) + args->len)) { + msm_obj->name[0] = '\0'; ret = -EFAULT; + break; + } msm_obj->name[args->len] = '\0'; for (i = 0; i < args->len; i++) { if (!isprint(msm_obj->name[i])) { -- cgit v1.2.3