[Nouveau] [PATCH] clock/nva3: Pause the GPU before reclocking

2014-08-29 Thread Roy Spliet
V2: always call post correctly even if pre fails
V3: move function prototype to nva3.h

Signed-off-by: Roy Spliet rspl...@eclipso.eu
---
 drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c | 52 +++-
 drivers/gpu/drm/nouveau/core/subdev/clock/nva3.h |  3 +-
 drivers/gpu/drm/nouveau/core/subdev/clock/nvaa.c | 37 ++---
 3 files changed, 66 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c 
b/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c
index 14a5060..1d1915b 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c
@@ -23,6 +23,7 @@
  *  Roy Spliet
  */
 
+#include engine/fifo.h
 #include subdev/bios.h
 #include subdev/bios/pll.h
 #include subdev/timer.h
@@ -293,6 +294,41 @@ calc_host(struct nva3_clock_priv *priv, struct 
nouveau_cstate *cstate)
return ret;
 }
 
+int
+nva3_clock_pre(struct nouveau_clock *clk, unsigned long *flags)
+{
+   struct nouveau_fifo *pfifo = nouveau_fifo(clk);
+
+   /* halt and idle execution engines */
+   nv_mask(clk, 0x020060, 0x0007, 0x);
+   nv_mask(clk, 0x002504, 0x0001, 0x0001);
+   /* Wait until the interrupt handler is finished */
+   if (!nv_wait(clk, 0x000100, 0x, 0x))
+   return -EBUSY;
+
+   if (pfifo)
+   pfifo-pause(pfifo, flags);
+
+   if (!nv_wait(clk, 0x002504, 0x0010, 0x0010))
+   return -EIO;
+   if (!nv_wait(clk, 0x00251c, 0x003f, 0x003f))
+   return -EIO;
+
+   return 0;
+}
+
+void
+nva3_clock_post(struct nouveau_clock *clk, unsigned long *flags)
+{
+   struct nouveau_fifo *pfifo = nouveau_fifo(clk);
+
+   if (pfifo  flags)
+   pfifo-start(pfifo, flags);
+
+   nv_mask(clk, 0x002504, 0x0001, 0x);
+   nv_mask(clk, 0x020060, 0x0007, 0x0004);
+}
+
 static void
 disable_clk_src(struct nva3_clock_priv *priv, u32 src)
 {
@@ -421,6 +457,13 @@ nva3_clock_prog(struct nouveau_clock *clk)
 {
struct nva3_clock_priv *priv = (void *)clk;
struct nva3_clock_info *core = priv-eng[nv_clk_src_core];
+   int ret = 0;
+   unsigned long flags;
+   unsigned long *f = flags;
+
+   ret = nva3_clock_pre(clk, f);
+   if (ret)
+   goto out;
 
if (core-pll)
prog_core(priv, nv_clk_src_core_intm);
@@ -430,7 +473,14 @@ nva3_clock_prog(struct nouveau_clock *clk)
prog_clk(priv, 0x20, nv_clk_src_disp);
prog_clk(priv, 0x21, nv_clk_src_vdec);
prog_host(priv);
-   return 0;
+
+out:
+   if (ret == -EBUSY)
+   f = NULL;
+
+   nva3_clock_post(clk, f);
+
+   return ret;
 }
 
 static void
diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.h 
b/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.h
index 0539be4..a45a103 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.h
@@ -15,5 +15,6 @@ struct nva3_clock_info {
 
 int nva3_pll_info(struct nouveau_clock *, int, u32, u32,
struct nva3_clock_info *);
-
+int nva3_clock_pre(struct nouveau_clock *clk, unsigned long *flags);
+void nva3_clock_post(struct nouveau_clock *clk, unsigned long *flags);
 #endif
diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nvaa.c 
b/drivers/gpu/drm/nouveau/core/subdev/clock/nvaa.c
index 6a65fc9..ecfdb59 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/clock/nvaa.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nvaa.c
@@ -28,6 +28,7 @@
 #include subdev/timer.h
 #include subdev/clock.h
 
+#include nva3.h
 #include pll.h
 
 struct nvaa_clock_priv {
@@ -299,25 +300,14 @@ static int
 nvaa_clock_prog(struct nouveau_clock *clk)
 {
struct nvaa_clock_priv *priv = (void *)clk;
-   struct nouveau_fifo *pfifo = nouveau_fifo(clk);
+   u32 pllmask = 0, mast;
unsigned long flags;
-   u32 pllmask = 0, mast, ptherm_gate;
-   int ret = -EBUSY;
-
-   /* halt and idle execution engines */
-   ptherm_gate = nv_mask(clk, 0x020060, 0x0007, 0x);
-   nv_mask(clk, 0x002504, 0x0001, 0x0001);
-   /* Wait until the interrupt handler is finished */
-   if (!nv_wait(clk, 0x000100, 0x, 0x))
-   goto resume;
-
-   if (pfifo)
-   pfifo-pause(pfifo, flags);
+   unsigned long *f = flags;
+   int ret = 0;
 
-   if (!nv_wait(clk, 0x002504, 0x0010, 0x0010))
-   goto resume;
-   if (!nv_wait(clk, 0x00251c, 0x003f, 0x003f))
-   goto resume;
+   ret = nva3_clock_pre(clk, f);
+   if (ret)
+   goto out;
 
/* First switch to safe clocks: href */
mast = nv_mask(clk, 0xc054, 0x03400e70, 0x03400640);
@@ -375,15 +365,8 @@ nvaa_clock_prog(struct nouveau_clock *clk)
}
 
nv_wr32(clk, 0xc054, mast);
-   ret = 0;

Re: [Nouveau] [PATCH] clock/nva3: Pause the GPU before reclocking

2014-08-27 Thread Ben Skeggs
On Sat, Aug 23, 2014 at 11:04 PM, Roy Spliet rspl...@eclipso.eu wrote:
 V2: always call post correctly even if pre fails

 Signed-off-by: Roy Spliet rspl...@eclipso.eu
 ---
  .../gpu/drm/nouveau/core/include/subdev/clock.h|  3 ++
  drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c   | 52 
 +-
  drivers/gpu/drm/nouveau/core/subdev/clock/nvaa.c   | 36 +--
  3 files changed, 66 insertions(+), 25 deletions(-)

 diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/clock.h 
 b/drivers/gpu/drm/nouveau/core/include/subdev/clock.h
 index 676b49e..52e65b8 100644
 --- a/drivers/gpu/drm/nouveau/core/include/subdev/clock.h
 +++ b/drivers/gpu/drm/nouveau/core/include/subdev/clock.h
 @@ -146,6 +146,9 @@ int nv04_clock_pll_prog(struct nouveau_clock *, u32 reg1,
  int nva3_clock_pll_calc(struct nouveau_clock *, struct nvbios_pll *,
 int clk, struct nouveau_pll_vals *);

 +int nva3_clock_pre(struct nouveau_clock *clk, unsigned long *flags);
 +void nva3_clock_post(struct nouveau_clock *clk, unsigned long *flags);
I'd stick these in the subdev/clock/nva3.h that already exists.

 +
  int nouveau_clock_ustate(struct nouveau_clock *, int req);
This hunk doesn't apply as-is anyway, due to ustate() gaining an extra
parameter.

I've merged the rest of the patches.

Thanks,
Ben.

  int nouveau_clock_astate(struct nouveau_clock *, int req, int rel);
  int nouveau_clock_dstate(struct nouveau_clock *, int req, int rel);
 diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c 
 b/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c
 index 14a5060..1d1915b 100644
 --- a/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c
 +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c
 @@ -23,6 +23,7 @@
   *  Roy Spliet
   */

 +#include engine/fifo.h
  #include subdev/bios.h
  #include subdev/bios/pll.h
  #include subdev/timer.h
 @@ -293,6 +294,41 @@ calc_host(struct nva3_clock_priv *priv, struct 
 nouveau_cstate *cstate)
 return ret;
  }

 +int
 +nva3_clock_pre(struct nouveau_clock *clk, unsigned long *flags)
 +{
 +   struct nouveau_fifo *pfifo = nouveau_fifo(clk);
 +
 +   /* halt and idle execution engines */
 +   nv_mask(clk, 0x020060, 0x0007, 0x);
 +   nv_mask(clk, 0x002504, 0x0001, 0x0001);
 +   /* Wait until the interrupt handler is finished */
 +   if (!nv_wait(clk, 0x000100, 0x, 0x))
 +   return -EBUSY;
 +
 +   if (pfifo)
 +   pfifo-pause(pfifo, flags);
 +
 +   if (!nv_wait(clk, 0x002504, 0x0010, 0x0010))
 +   return -EIO;
 +   if (!nv_wait(clk, 0x00251c, 0x003f, 0x003f))
 +   return -EIO;
 +
 +   return 0;
 +}
 +
 +void
 +nva3_clock_post(struct nouveau_clock *clk, unsigned long *flags)
 +{
 +   struct nouveau_fifo *pfifo = nouveau_fifo(clk);
 +
 +   if (pfifo  flags)
 +   pfifo-start(pfifo, flags);
 +
 +   nv_mask(clk, 0x002504, 0x0001, 0x);
 +   nv_mask(clk, 0x020060, 0x0007, 0x0004);
 +}
 +
  static void
  disable_clk_src(struct nva3_clock_priv *priv, u32 src)
  {
 @@ -421,6 +457,13 @@ nva3_clock_prog(struct nouveau_clock *clk)
  {
 struct nva3_clock_priv *priv = (void *)clk;
 struct nva3_clock_info *core = priv-eng[nv_clk_src_core];
 +   int ret = 0;
 +   unsigned long flags;
 +   unsigned long *f = flags;
 +
 +   ret = nva3_clock_pre(clk, f);
 +   if (ret)
 +   goto out;

 if (core-pll)
 prog_core(priv, nv_clk_src_core_intm);
 @@ -430,7 +473,14 @@ nva3_clock_prog(struct nouveau_clock *clk)
 prog_clk(priv, 0x20, nv_clk_src_disp);
 prog_clk(priv, 0x21, nv_clk_src_vdec);
 prog_host(priv);
 -   return 0;
 +
 +out:
 +   if (ret == -EBUSY)
 +   f = NULL;
 +
 +   nva3_clock_post(clk, f);
 +
 +   return ret;
  }

  static void
 diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nvaa.c 
 b/drivers/gpu/drm/nouveau/core/subdev/clock/nvaa.c
 index 6a65fc9..769ab26 100644
 --- a/drivers/gpu/drm/nouveau/core/subdev/clock/nvaa.c
 +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nvaa.c
 @@ -299,25 +299,14 @@ static int
  nvaa_clock_prog(struct nouveau_clock *clk)
  {
 struct nvaa_clock_priv *priv = (void *)clk;
 -   struct nouveau_fifo *pfifo = nouveau_fifo(clk);
 +   u32 pllmask = 0, mast;
 unsigned long flags;
 -   u32 pllmask = 0, mast, ptherm_gate;
 -   int ret = -EBUSY;
 -
 -   /* halt and idle execution engines */
 -   ptherm_gate = nv_mask(clk, 0x020060, 0x0007, 0x);
 -   nv_mask(clk, 0x002504, 0x0001, 0x0001);
 -   /* Wait until the interrupt handler is finished */
 -   if (!nv_wait(clk, 0x000100, 0x, 0x))
 -   goto resume;
 -
 -   if (pfifo)
 -   pfifo-pause(pfifo, flags);
 +   unsigned long *f = flags;
 +   int ret = 0;

 -