drm/msm: subclass work object for vblank events
authorJeykumar Sankaran <jsanka@codeaurora.org>
Fri, 14 Dec 2018 23:57:55 +0000 (15:57 -0800)
committerSean Paul <seanpaul@chromium.org>
Fri, 1 Feb 2019 15:39:58 +0000 (10:39 -0500)
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 <jsanka@codeaurora.org>
Signed-off-by: Sean Paul <seanpaul@chromium.org>
drivers/gpu/drm/msm/msm_drv.c
drivers/gpu/drm/msm/msm_drv.h

index a8a0b246e3a91393f10d6183a85e0433eea21e14..5e7b5fa01401e67e710fec97e72843213cb97ed0 100644 (file)
@@ -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);
 
index 06f3aa876483b717ebdc9f37661d09f01a0b8a7b..cb642fefbd2f97d81dbaac9c4a3a0aa945397633 100644 (file)
@@ -77,12 +77,6 @@ enum msm_mdp_plane_property {
        PLANE_PROP_MAX_NUM
 };
 
-struct msm_vblank_ctrl {
-       struct work_struct work;
-       struct list_head event_list;
-       spinlock_t lock;
-};
-
 #define MSM_GPU_MAX_RINGS 4
 #define MAX_H_TILES_PER_DISPLAY 2
 
@@ -227,7 +221,6 @@ struct msm_drm_private {
        struct notifier_block vmap_notifier;
        struct shrinker shrinker;
 
-       struct msm_vblank_ctrl vblank_ctrl;
        struct drm_atomic_state *pm_state;
 };