The preemption state machine related code is same across Adreno targets,
so move the common code to a common header file to avoid code
duplication.

Signed-off-by: Sharat Masetty <smase...@codeaurora.org>
---
 drivers/gpu/drm/msm/adreno/a5xx_gpu.h     | 26 ---------------
 drivers/gpu/drm/msm/adreno/a5xx_preempt.c | 55 +++++++++----------------------
 drivers/gpu/drm/msm/adreno/a6xx_gpu.h     | 26 ---------------
 drivers/gpu/drm/msm/adreno/a6xx_preempt.c | 55 +++++++++----------------------
 drivers/gpu/drm/msm/adreno/adreno_gpu.h   | 54 ++++++++++++++++++++++++++++++
 5 files changed, 84 insertions(+), 132 deletions(-)

diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.h 
b/drivers/gpu/drm/msm/adreno/a5xx_gpu.h
index 7d71860..45535f7 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.h
@@ -54,32 +54,6 @@ struct a5xx_gpu {
 #endif
 
 /*
- * In order to do lockless preemption we use a simple state machine to progress
- * through the process.
- *
- * PREEMPT_NONE - no preemption in progress.  Next state START.
- * PREEMPT_START - The trigger is evaulating if preemption is possible. Next
- * states: TRIGGERED, NONE
- * PREEMPT_ABORT - An intermediate state before moving back to NONE. Next
- * state: NONE.
- * PREEMPT_TRIGGERED: A preemption has been executed on the hardware. Next
- * states: FAULTED, PENDING
- * PREEMPT_FAULTED: A preemption timed out (never completed). This will trigger
- * recovery.  Next state: N/A
- * PREEMPT_PENDING: Preemption complete interrupt fired - the callback is
- * checking the success of the operation. Next state: FAULTED, NONE.
- */
-
-enum preempt_state {
-       PREEMPT_NONE = 0,
-       PREEMPT_START,
-       PREEMPT_ABORT,
-       PREEMPT_TRIGGERED,
-       PREEMPT_FAULTED,
-       PREEMPT_PENDING,
-};
-
-/*
  * struct a5xx_preempt_record is a shared buffer between the microcode and the
  * CPU to store the state for preemption. The record itself is much larger
  * (64k) but most of that is used by the CP for storage.
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_preempt.c 
b/drivers/gpu/drm/msm/adreno/a5xx_preempt.c
index 40f4840..faf844b 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_preempt.c
+++ b/drivers/gpu/drm/msm/adreno/a5xx_preempt.c
@@ -14,37 +14,6 @@
 #include "msm_gem.h"
 #include "a5xx_gpu.h"
 
-/*
- * Try to transition the preemption state from old to new. Return
- * true on success or false if the original state wasn't 'old'
- */
-static inline bool try_preempt_state(struct a5xx_gpu *a5xx_gpu,
-               enum preempt_state old, enum preempt_state new)
-{
-       enum preempt_state cur = atomic_cmpxchg(&a5xx_gpu->preempt_state,
-               old, new);
-
-       return (cur == old);
-}
-
-/*
- * Force the preemption state to the specified state.  This is used in cases
- * where the current state is known and won't change
- */
-static inline void set_preempt_state(struct a5xx_gpu *gpu,
-               enum preempt_state new)
-{
-       /*
-        * preempt_state may be read by other cores trying to trigger a
-        * preemption or in the interrupt handler so barriers are needed
-        * before...
-        */
-       smp_mb__before_atomic();
-       atomic_set(&gpu->preempt_state, new);
-       /* ... and after*/
-       smp_mb__after_atomic();
-}
-
 /* Write the most recent wptr for the given ring into the hardware */
 static inline void update_wptr(struct msm_gpu *gpu, struct msm_ringbuffer 
*ring)
 {
@@ -89,7 +58,8 @@ static void a5xx_preempt_timer(unsigned long data)
        struct drm_device *dev = gpu->dev;
        struct msm_drm_private *priv = dev->dev_private;
 
-       if (!try_preempt_state(a5xx_gpu, PREEMPT_TRIGGERED, PREEMPT_FAULTED))
+       if (!adreno_try_preempt_state(&a5xx_gpu->preempt_state,
+                               PREEMPT_TRIGGERED, PREEMPT_FAULTED))
                return;
 
        dev_err(dev->dev, "%s: preemption timed out\n", gpu->name);
@@ -111,7 +81,8 @@ void a5xx_preempt_trigger(struct msm_gpu *gpu)
         * Try to start preemption by moving from NONE to START. If
         * unsuccessful, a preemption is already in flight
         */
-       if (!try_preempt_state(a5xx_gpu, PREEMPT_NONE, PREEMPT_START))
+       if (!adreno_try_preempt_state(&a5xx_gpu->preempt_state,
+                               PREEMPT_NONE, PREEMPT_START))
                return;
 
        /* Get the next ring to preempt to */
@@ -134,9 +105,11 @@ void a5xx_preempt_trigger(struct msm_gpu *gpu)
                 * and can safely update the write pointer.
                 */
 
-               set_preempt_state(a5xx_gpu, PREEMPT_ABORT);
+               adreno_set_preempt_state(&a5xx_gpu->preempt_state,
+                               PREEMPT_ABORT);
                update_wptr(gpu, a5xx_gpu->cur_ring);
-               set_preempt_state(a5xx_gpu, PREEMPT_NONE);
+               adreno_set_preempt_state(&a5xx_gpu->preempt_state,
+                               PREEMPT_NONE);
                return;
        }
 
@@ -156,7 +129,7 @@ void a5xx_preempt_trigger(struct msm_gpu *gpu)
        mod_timer(&a5xx_gpu->preempt_timer, jiffies + msecs_to_jiffies(10000));
 
        /* Set the preemption state to triggered */
-       set_preempt_state(a5xx_gpu, PREEMPT_TRIGGERED);
+       adreno_set_preempt_state(&a5xx_gpu->preempt_state, PREEMPT_TRIGGERED);
 
        /* Make sure everything is written before hitting the button */
        wmb();
@@ -173,7 +146,8 @@ void a5xx_preempt_irq(struct msm_gpu *gpu)
        struct drm_device *dev = gpu->dev;
        struct msm_drm_private *priv = dev->dev_private;
 
-       if (!try_preempt_state(a5xx_gpu, PREEMPT_TRIGGERED, PREEMPT_PENDING))
+       if (!adreno_try_preempt_state(&a5xx_gpu->preempt_state,
+                               PREEMPT_TRIGGERED, PREEMPT_PENDING))
                return;
 
        /* Delete the preemption watchdog timer */
@@ -187,7 +161,8 @@ void a5xx_preempt_irq(struct msm_gpu *gpu)
         */
        status = gpu_read(gpu, REG_A5XX_CP_CONTEXT_SWITCH_CNTL);
        if (unlikely(status)) {
-               set_preempt_state(a5xx_gpu, PREEMPT_FAULTED);
+               adreno_set_preempt_state(&a5xx_gpu->preempt_state,
+                               PREEMPT_FAULTED);
                dev_err(dev->dev, "%s: Preemption failed to complete\n",
                        gpu->name);
                queue_work(priv->wq, &gpu->recover_work);
@@ -199,7 +174,7 @@ void a5xx_preempt_irq(struct msm_gpu *gpu)
 
        update_wptr(gpu, a5xx_gpu->cur_ring);
 
-       set_preempt_state(a5xx_gpu, PREEMPT_NONE);
+       adreno_set_preempt_state(&a5xx_gpu->preempt_state, PREEMPT_NONE);
 }
 
 void a5xx_preempt_hw_init(struct msm_gpu *gpu)
@@ -219,7 +194,7 @@ void a5xx_preempt_hw_init(struct msm_gpu *gpu)
                REG_A5XX_CP_CONTEXT_SWITCH_SMMU_INFO_HI, 0);
 
        /* Reset the preemption state */
-       set_preempt_state(a5xx_gpu, PREEMPT_NONE);
+       adreno_set_preempt_state(&a5xx_gpu->preempt_state, PREEMPT_NONE);
 
        /* Always come up on rb 0 */
        a5xx_gpu->cur_ring = gpu->rb[0];
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h 
b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
index aca1d7d..21ab701 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
@@ -54,32 +54,6 @@ struct a6xx_gpu {
        (a6xx_gpu->scratch_iova + (ring_id * sizeof(uint64_t)))
 
 /*
- * In order to do lockless preemption we use a simple state machine to progress
- * through the process.
- *
- * PREEMPT_NONE - no preemption in progress.  Next state START.
- * PREEMPT_START - The trigger is evaluating if preemption is possible. Next
- * states: TRIGGERED, NONE
- * PREEMPT_ABORT - An intermediate state before moving back to NONE. Next
- * state: NONE.
- * PREEMPT_TRIGGERED: A preemption has been executed on the hardware. Next
- * states: FAULTED, PENDING
- * PREEMPT_FAULTED: A preemption timed out (never completed). This will trigger
- * recovery.  Next state: N/A
- * PREEMPT_PENDING: Preemption complete interrupt fired - the callback is
- * checking the success of the operation. Next state: FAULTED, NONE.
- */
-
-enum a6xx_preempt_state {
-       PREEMPT_NONE = 0,
-       PREEMPT_START,
-       PREEMPT_ABORT,
-       PREEMPT_TRIGGERED,
-       PREEMPT_FAULTED,
-       PREEMPT_PENDING,
-};
-
-/*
  * ID values used by SET_PSEUDO_REG PM4 command. These determine which of the
  * various internal CP registers to write to. Used in the save/restore
  * preemption sequence.
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_preempt.c 
b/drivers/gpu/drm/msm/adreno/a6xx_preempt.c
index 60df6c5..0d2b612 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_preempt.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_preempt.c
@@ -5,37 +5,6 @@
 #include "a6xx_gpu.h"
 #include "a6xx_gmu.xml.h"
 
-/*
- * Try to transition the preemption state from old to new. Return
- * true on success or false if the original state wasn't 'old'
- */
-static inline bool try_preempt_state(struct a6xx_gpu *a6xx_gpu,
-               enum a6xx_preempt_state old, enum a6xx_preempt_state new)
-{
-       enum a6xx_preempt_state cur = atomic_cmpxchg(&a6xx_gpu->preempt_state,
-               old, new);
-
-       return (cur == old);
-}
-
-/*
- * Force the preemption state to the specified state.  This is used in cases
- * where the current state is known and won't change
- */
-static inline void set_preempt_state(struct a6xx_gpu *gpu,
-               enum a6xx_preempt_state new)
-{
-       /*
-        * preempt_state may be read by other cores trying to trigger a
-        * preemption or in the interrupt handler so barriers are needed
-        * before...
-        */
-       smp_mb__before_atomic();
-       atomic_set(&gpu->preempt_state, new);
-       /* ... and after*/
-       smp_mb__after_atomic();
-}
-
 /* Write the most recent wptr for the given ring into the hardware */
 static inline void update_wptr(struct msm_gpu *gpu, struct msm_ringbuffer 
*ring)
 {
@@ -80,7 +49,8 @@ static void a6xx_preempt_timer(unsigned long data)
        struct drm_device *dev = gpu->dev;
        struct msm_drm_private *priv = dev->dev_private;
 
-       if (!try_preempt_state(a6xx_gpu, PREEMPT_TRIGGERED, PREEMPT_FAULTED))
+       if (!adreno_try_preempt_state(&a6xx_gpu->preempt_state,
+                               PREEMPT_TRIGGERED, PREEMPT_FAULTED))
                return;
 
        dev_err(dev->dev, "%s: preemption timed out\n", gpu->name);
@@ -95,7 +65,8 @@ void a6xx_preempt_irq(struct msm_gpu *gpu)
        struct drm_device *dev = gpu->dev;
        struct msm_drm_private *priv = dev->dev_private;
 
-       if (!try_preempt_state(a6xx_gpu, PREEMPT_TRIGGERED, PREEMPT_PENDING))
+       if (!adreno_try_preempt_state(&a6xx_gpu->preempt_state,
+                               PREEMPT_TRIGGERED, PREEMPT_PENDING))
                return;
 
        /* Delete the preemption watchdog timer */
@@ -110,7 +81,8 @@ void a6xx_preempt_irq(struct msm_gpu *gpu)
         */
        status = gpu_read(gpu, REG_A6XX_CP_CONTEXT_SWITCH_CNTL);
        if (unlikely(status & 0x1)) {
-               set_preempt_state(a6xx_gpu, PREEMPT_FAULTED);
+               adreno_set_preempt_state(&a6xx_gpu->preempt_state,
+                               PREEMPT_FAULTED);
                dev_err(dev->dev, "%s: Preemption failed to complete\n",
                        gpu->name);
                queue_work(priv->wq, &gpu->recover_work);
@@ -122,7 +94,7 @@ void a6xx_preempt_irq(struct msm_gpu *gpu)
 
        update_wptr(gpu, a6xx_gpu->cur_ring);
 
-       set_preempt_state(a6xx_gpu, PREEMPT_NONE);
+       adreno_set_preempt_state(&a6xx_gpu->preempt_state, PREEMPT_NONE);
 }
 
 void a6xx_preempt_hw_init(struct msm_gpu *gpu)
@@ -151,7 +123,7 @@ void a6xx_preempt_hw_init(struct msm_gpu *gpu)
        gpu_write(gpu, REG_A6XX_RB_CONTEXT_SWITCH_GMEM_SAVE_RESTORE, 0x1);
 
        /* Reset the preemption state */
-       set_preempt_state(a6xx_gpu, PREEMPT_NONE);
+       adreno_set_preempt_state(&a6xx_gpu->preempt_state, PREEMPT_NONE);
 
        /* Always come up on rb 0 */
        a6xx_gpu->cur_ring = gpu->rb[0];
@@ -175,7 +147,8 @@ void a6xx_preempt_trigger(struct msm_gpu *gpu)
         * Try to start preemption by moving from NONE to START. If
         * unsuccessful, a preemption is already in flight
         */
-       if (!try_preempt_state(a6xx_gpu, PREEMPT_NONE, PREEMPT_START))
+       if (!adreno_try_preempt_state(&a6xx_gpu->preempt_state,
+                               PREEMPT_NONE, PREEMPT_START))
                return;
 
        cntl = (((a6xx_gpu->preempt_level << 6) & 0xC0) |
@@ -190,9 +163,11 @@ void a6xx_preempt_trigger(struct msm_gpu *gpu)
         * one do nothing except to update the wptr to the latest and greatest
         */
        if (!ring || (a6xx_gpu->cur_ring == ring)) {
-               set_preempt_state(a6xx_gpu, PREEMPT_ABORT);
+               adreno_set_preempt_state(&a6xx_gpu->preempt_state,
+                               PREEMPT_ABORT);
                update_wptr(gpu, a6xx_gpu->cur_ring);
-               set_preempt_state(a6xx_gpu, PREEMPT_NONE);
+               adreno_set_preempt_state(&a6xx_gpu->preempt_state,
+                               PREEMPT_NONE);
                return;
        }
 
@@ -243,7 +218,7 @@ void a6xx_preempt_trigger(struct msm_gpu *gpu)
        mod_timer(&a6xx_gpu->preempt_timer, jiffies + msecs_to_jiffies(10000));
 
        /* Set the preemption state to triggered */
-       set_preempt_state(a6xx_gpu, PREEMPT_TRIGGERED);
+       adreno_set_preempt_state(&a6xx_gpu->preempt_state, PREEMPT_TRIGGERED);
 
        /* Make sure everything is written before hitting the button */
        wmb();
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h 
b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
index 94764d0..bb9affd 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
@@ -368,4 +368,58 @@ static inline uint32_t get_wptr(struct msm_ringbuffer 
*ring)
        ((1 << 29) \
        ((ilog2((_len)) & 0x1F) << 24) | (((_reg) << 2) & 0xFFFFF))
 
+/*
+ * In order to do lockless preemption we use a simple state machine to progress
+ * through the process.
+ *
+ * PREEMPT_NONE - no preemption in progress.  Next state START.
+ * PREEMPT_START - The trigger is evaluating if preemption is possible. Next
+ * states: TRIGGERED, NONE
+ * PREEMPT_ABORT - An intermediate state before moving back to NONE. Next
+ * state: NONE.
+ * PREEMPT_TRIGGERED: A preemption has been executed on the hardware. Next
+ * states: FAULTED, PENDING
+ * PREEMPT_FAULTED: A preemption timed out (never completed). This will trigger
+ * recovery.  Next state: N/A
+ * PREEMPT_PENDING: Preemption complete interrupt fired - the callback is
+ * checking the success of the operation. Next state: FAULTED, NONE.
+ */
+enum adreno_preempt_state {
+       PREEMPT_NONE = 0,
+       PREEMPT_START,
+       PREEMPT_ABORT,
+       PREEMPT_TRIGGERED,
+       PREEMPT_FAULTED,
+       PREEMPT_PENDING,
+};
+
+/*
+ * Try to transition the preemption state from old to new. Return
+ * true on success or false if the original state wasn't 'old'
+ */
+static inline bool adreno_try_preempt_state(atomic_t *preempt_state,
+               enum adreno_preempt_state old, enum adreno_preempt_state new)
+{
+       enum adreno_preempt_state cur = atomic_cmpxchg(preempt_state, old, new);
+
+       return (cur == old);
+}
+
+/*
+ * Force the preemption state to the specified state.  This is used in cases
+ * where the current state is known and won't change
+ */
+static inline void adreno_set_preempt_state(atomic_t *preempt_state,
+               enum adreno_preempt_state new)
+{
+       /*
+        * adreno_preempt_state may be read by other cores trying to trigger a
+        * preemption or in the interrupt handler so barriers are needed
+        * before...
+        */
+       smp_mb__before_atomic();
+       atomic_set(preempt_state, new);
+       /* ... and after*/
+       smp_mb__after_atomic();
+}
 #endif /* __ADRENO_GPU_H__ */
-- 
1.9.1

_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

Reply via email to