drm/armada: avoid work allocation
authorRussell King <rmk+kernel@armlinux.org.uk>
Sat, 8 Jul 2017 09:22:25 +0000 (10:22 +0100)
committerRussell King <rmk+kernel@armlinux.org.uk>
Fri, 8 Dec 2017 12:20:00 +0000 (12:20 +0000)
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
drivers/gpu/drm/armada/armada_crtc.c
drivers/gpu/drm/armada/armada_crtc.h
drivers/gpu/drm/armada/armada_overlay.c

index 2f8e45976444ee0f7c05f075afdbbd77121bfc9b..98fb955f68899feb21913c6b34d3be1481e446f3 100644 (file)
@@ -214,13 +214,15 @@ static void armada_drm_plane_work_call(struct armada_crtc *dcrtc,
        void (*fn)(struct armada_crtc *, struct armada_plane_work *))
 {
        struct armada_plane *dplane = drm_to_armada_plane(work->plane);
-       struct drm_pending_vblank_event *event = work->event;
-       struct drm_framebuffer *fb = work->old_fb;
+       struct drm_pending_vblank_event *event;
+       struct drm_framebuffer *fb;
 
        if (fn)
                fn(dcrtc, work);
        drm_crtc_vblank_put(&dcrtc->crtc);
 
+       event = work->event;
+       fb = work->old_fb;
        if (event || fb) {
                struct drm_device *dev = dcrtc->crtc.dev;
                unsigned long flags;
@@ -233,6 +235,9 @@ static void armada_drm_plane_work_call(struct armada_crtc *dcrtc,
                spin_unlock_irqrestore(&dev->event_lock, flags);
        }
 
+       if (work->need_kfree)
+               kfree(work);
+
        wake_up(&dplane->frame_wait);
 }
 
@@ -278,12 +283,6 @@ void armada_drm_plane_work_cancel(struct armada_crtc *dcrtc,
                armada_drm_plane_work_call(dcrtc, work, work->cancel);
 }
 
-static void armada_drm_crtc_finish_frame_work(struct armada_crtc *dcrtc,
-       struct armada_plane_work *work)
-{
-       kfree(work);
-}
-
 static void armada_drm_crtc_complete_frame_work(struct armada_crtc *dcrtc,
        struct armada_plane_work *work)
 {
@@ -292,8 +291,6 @@ static void armada_drm_crtc_complete_frame_work(struct armada_crtc *dcrtc,
        spin_lock_irqsave(&dcrtc->irq_lock, flags);
        armada_drm_crtc_update_regs(dcrtc, work->regs);
        spin_unlock_irqrestore(&dcrtc->irq_lock, flags);
-
-       armada_drm_crtc_finish_frame_work(dcrtc, work);
 }
 
 static struct armada_plane_work *
@@ -308,7 +305,7 @@ armada_drm_crtc_alloc_plane_work(struct drm_plane *plane)
 
        work->plane = plane;
        work->fn = armada_drm_crtc_complete_frame_work;
-       work->cancel = armada_drm_crtc_finish_frame_work;
+       work->need_kfree = true;
        armada_reg_queue_end(work->regs, i);
 
        return work;
@@ -1173,6 +1170,11 @@ static const struct drm_plane_funcs armada_primary_plane_funcs = {
 
 int armada_drm_plane_init(struct armada_plane *plane)
 {
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(plane->works); i++)
+               plane->works[i].plane = &plane->base;
+
        init_waitqueue_head(&plane->frame_wait);
 
        return 0;
index 12ef9688a45ace7bfb11a063b2e6c4fb2bc9aaf2..0c7b519c09e896ac9522a1d16ac2422ab89fcf3b 100644 (file)
@@ -38,6 +38,7 @@ struct armada_variant;
 struct armada_plane_work {
        void (*fn)(struct armada_crtc *, struct armada_plane_work *);
        void (*cancel)(struct armada_crtc *, struct armada_plane_work *);
+       bool need_kfree;
        struct drm_plane *plane;
        struct drm_framebuffer *old_fb;
        struct drm_pending_vblank_event *event;
@@ -56,6 +57,8 @@ struct armada_plane_state {
 struct armada_plane {
        struct drm_plane        base;
        wait_queue_head_t       frame_wait;
+       bool                    next_work;
+       struct armada_plane_work works[2];
        struct armada_plane_work *work;
        struct armada_plane_state state;
 };
index 53edf42c5863ccffa2cee965ec34ae6506782928..bad966ae6758bd98f411d53327e6c38a8a466f43 100644 (file)
@@ -32,7 +32,6 @@ struct armada_ovl_plane_properties {
 
 struct armada_ovl_plane {
        struct armada_plane base;
-       struct armada_plane_work work;
        struct armada_ovl_plane_properties prop;
 };
 #define drm_to_armada_ovl_plane(p) \
@@ -85,7 +84,7 @@ armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
 {
        struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane);
        struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
-       struct armada_plane_work *work = &dplane->work;
+       struct armada_plane_work *work;
        const struct drm_format_info *format;
        struct drm_plane_state state = {
                .plane = plane,
@@ -119,6 +118,8 @@ armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
        if (ret)
                return ret;
 
+       work = &dplane->base.works[dplane->base.next_work];
+
        ctrl0 = CFG_DMA_FMT(drm_fb_to_armada_fb(fb)->fmt) |
                CFG_DMA_MOD(drm_fb_to_armada_fb(fb)->mod) |
                CFG_CBSH_ENA;
@@ -248,6 +249,8 @@ armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
                ret = armada_drm_plane_work_queue(dcrtc, work);
                if (ret)
                        DRM_ERROR("failed to queue plane work: %d\n", ret);
+
+               dplane->base.next_work = !dplane->base.next_work;
        }
        return 0;
 }
@@ -434,8 +437,8 @@ int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs)
                return ret;
        }
 
-       dplane->work.plane = &dplane->base.base;
-       dplane->work.fn = armada_ovl_plane_work;
+       dplane->base.works[0].fn = armada_ovl_plane_work;
+       dplane->base.works[1].fn = armada_ovl_plane_work;
 
        ret = drm_universal_plane_init(dev, &dplane->base.base, crtcs,
                                       &armada_ovl_plane_funcs,