All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sharat Masetty <smasetty-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
To: freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org
Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Sharat Masetty <smasetty-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org
Subject: [PATCH 5/6] drm/msm/Adreno: Refactor some preemption code
Date: Thu,  8 Mar 2018 11:36:24 +0530	[thread overview]
Message-ID: <1520489185-21828-6-git-send-email-smasetty@codeaurora.org> (raw)
In-Reply-To: <1520489185-21828-1-git-send-email-smasetty-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>

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 <smasetty@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

  parent reply	other threads:[~2018-03-08  6:06 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-03-08  6:06 [PATCH 0/6] Preemption support for A6xx targets Sharat Masetty
2018-03-08  6:06 ` [PATCH 1/6] drm/msm: Add submitqueue setup and close Sharat Masetty
2018-03-08  6:06 ` [PATCH 3/6] drm/msm/A6xx: Implement preemption for A6XX targets Sharat Masetty
2018-03-08  6:06 ` [PATCH 4/6] drm/msm/A6xx: Enable preemption for A6xx targets Sharat Masetty
     [not found] ` <1520489185-21828-1-git-send-email-smasetty-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2018-03-08  6:06   ` [PATCH 2/6] drm/msm: Add new PM4 type7 opcodes Sharat Masetty
2018-03-08  6:06   ` Sharat Masetty [this message]
2018-03-08  6:06 ` [PATCH 6/6] drm/msm/A6xx: Enable L1 preemption level Sharat Masetty

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1520489185-21828-6-git-send-email-smasetty@codeaurora.org \
    --to=smasetty-sgv2jx0feol9jmxxk+q4oq@public.gmane.org \
    --cc=dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org \
    --cc=freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org \
    --cc=linux-arm-msm-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.