From: Michel D?nzer <michel.daen...@amd.com>

This is another line of defence against the panic fixed by the previous
change, and should make the life cycle of a page flip clearer.

Tested-by: Dieter N?tzel <Dieter at nuetzel-hh.de>
Signed-off-by: Michel D?nzer <michel.daenzer at amd.com>
---
 drivers/gpu/drm/radeon/radeon_display.c | 19 ++++++++++++++-----
 drivers/gpu/drm/radeon/radeon_mode.h    |  7 +++++++
 2 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_display.c 
b/drivers/gpu/drm/radeon/radeon_display.c
index 8b575a4..65882cd 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -284,7 +284,6 @@ static void radeon_unpin_work_func(struct work_struct 
*__work)
 void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id)
 {
        struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
-       struct radeon_flip_work *work;
        unsigned long flags;
        u32 update_pending;
        int vpos, hpos;
@@ -294,8 +293,11 @@ void radeon_crtc_handle_vblank(struct radeon_device *rdev, 
int crtc_id)
                return;

        spin_lock_irqsave(&rdev->ddev->event_lock, flags);
-       work = radeon_crtc->flip_work;
-       if (work == NULL) {
+       if (radeon_crtc->flip_status != RADEON_FLIP_SUBMITTED) {
+               DRM_DEBUG_DRIVER("radeon_crtc->flip_status = %d != "
+                                "RADEON_FLIP_SUBMITTED(%d)\n",
+                                radeon_crtc->flip_status,
+                                RADEON_FLIP_SUBMITTED);
                spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
                return;
        }
@@ -343,12 +345,17 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, 
int crtc_id)

        spin_lock_irqsave(&rdev->ddev->event_lock, flags);
        work = radeon_crtc->flip_work;
-       if (work == NULL) {
+       if (radeon_crtc->flip_status != RADEON_FLIP_SUBMITTED) {
+               DRM_DEBUG_DRIVER("radeon_crtc->flip_status = %d != "
+                                "RADEON_FLIP_SUBMITTED(%d)\n",
+                                radeon_crtc->flip_status,
+                                RADEON_FLIP_SUBMITTED);
                spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
                return;
        }

        /* Pageflip completed. Clean up. */
+       radeon_crtc->flip_status = RADEON_FLIP_NONE;
        radeon_crtc->flip_work = NULL;

        /* wakeup userspace */
@@ -475,6 +482,7 @@ static void radeon_flip_work_func(struct work_struct 
*__work)
        /* do the flip (mmio) */
        radeon_page_flip(rdev, radeon_crtc->crtc_id, base);

+       radeon_crtc->flip_status = RADEON_FLIP_SUBMITTED;
        spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
        up_read(&rdev->exclusive_lock);

@@ -543,7 +551,7 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
        /* We borrow the event spin lock for protecting flip_work */
        spin_lock_irqsave(&crtc->dev->event_lock, flags);

-       if (radeon_crtc->flip_work) {
+       if (radeon_crtc->flip_status != RADEON_FLIP_NONE) {
                DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
                spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
                drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base);
@@ -551,6 +559,7 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
                kfree(work);
                return -EBUSY;
        }
+       radeon_crtc->flip_status = RADEON_FLIP_PENDING;
        radeon_crtc->flip_work = work;

        /* update crtc fb */
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h 
b/drivers/gpu/drm/radeon/radeon_mode.h
index b59096f..ed6b6e0 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -301,6 +301,12 @@ struct radeon_atom_ss {
        uint16_t amount;
 };

+enum radeon_flip_status {
+       RADEON_FLIP_NONE,
+       RADEON_FLIP_PENDING,
+       RADEON_FLIP_SUBMITTED
+};
+
 struct radeon_crtc {
        struct drm_crtc base;
        int crtc_id;
@@ -326,6 +332,7 @@ struct radeon_crtc {
        /* page flipping */
        struct workqueue_struct *flip_queue;
        struct radeon_flip_work *flip_work;
+       enum radeon_flip_status flip_status;
        /* pll sharing */
        struct radeon_atom_ss ss;
        bool ss_enabled;
-- 
2.0.0

Reply via email to