All of lore.kernel.org
 help / color / mirror / Atom feed
From: Francisco Jerez <currojerez-sGOZH3hwPm2sTnJN9+BGXg@public.gmane.org>
To: Martin Peres <martin.peres-GANU6spQydw@public.gmane.org>
Cc: nouveau <Nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org>
Subject: Re: [PATCH] Add PFIFO and PGRAPH pausing methods
Date: Wed, 12 Jan 2011 21:27:36 +0100	[thread overview]
Message-ID: <87ipxtj29z.fsf@riseup.net> (raw)
In-Reply-To: <4D2A4B1C.6050908-GANU6spQydw@public.gmane.org> (Martin Peres's message of "Mon, 10 Jan 2011 00:56:12 +0100")


[-- Attachment #1.1.1: Type: text/plain, Size: 21720 bytes --]

Martin Peres <martin.peres-GANU6spQydw@public.gmane.org> writes:

> Hi,
>
> I'm still working on getting the reclocking work done right. There are
> several parts I identify:
> - Pausing PFIFO (with its caches), pause PGRAPH and wait for idle
> - Stop some PLL (I guess it is more, physically disconnect them from
> the engines) using the 0xc040 register.
> - reclock memory
> - reclock the other engines
> - Make sure the display doesn't blow up
> Depending on the cards, I have completed all of the steps or none.
>
> Anyway, pausing PFIFO and PGRAPH works well on all the card I tested
> and so, I would like it to be pushed.
> I have a new theory upon the PLL_SUPERVISOR(0xc040) that I want to
> test. When I'm done with this, I'll put together a patch for it and
> continue on the other steps.
>
> Please provide me with some feedback on the patch or push it if
> nothing bothers you.
>
Thanks, some comments inline.

> Martin
>
> PS: I'm quite busy at the moment, I'll write an in-depth mail when
> I've verified my theories and got proper support on other cards than
> the nv86 ones.
>
> From f7ad98f4a857dd4b1892712d15f93c13eb0669e3 Mon Sep 17 00:00:00 2001
> From: Martin Peres <martin.peres-Iz16wY1oaNPLSKGbIzaifA@public.gmane.org>
> Date: Mon, 10 Jan 2011 00:44:05 +0100
> Subject: [PATCH] Pause PFIFO and PGRAPH before reclocking
>
> Signed-off-by: Martin Peres <martin.peres-Iz16wY1oaNPLSKGbIzaifA@public.gmane.org>
> ---
>  drivers/gpu/drm/nouveau/nouveau_drv.h   |   15 +++++++
>  drivers/gpu/drm/nouveau/nouveau_pm.c    |   32 ++++++++++++++-
>  drivers/gpu/drm/nouveau/nouveau_reg.h   |    3 +
>  drivers/gpu/drm/nouveau/nouveau_state.c |   51 +++++++++++++++++++++++-
>  drivers/gpu/drm/nouveau/nv04_fifo.c     |   16 +++++++
>  drivers/gpu/drm/nouveau/nv50_fifo.c     |   20 +++++++++
>  drivers/gpu/drm/nouveau/nv50_graph.c    |   66 +++++++++++++++++++++++++++++++
>  7 files changed, 200 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
> index 6d749b7..b0c52c7 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_drv.h
> +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
> @@ -359,6 +359,12 @@ struct nouveau_fifo_engine {
>  	int  (*load_context)(struct nouveau_channel *);
>  	int  (*unload_context)(struct drm_device *);
>  	void (*tlb_flush)(struct drm_device *dev);
> +
> +	int  (*pause)(struct drm_device *);
> +	void  (*unpause)(struct drm_device *);
> +
> +	int  (*cache_pause)(struct drm_device *);
> +	void  (*cache_unpause)(struct drm_device *);

You could fold fifo->cache_pause() into fifo->pause(). I don't see any
reason to have two separate pairs of callbacks here, they're always
going to be called one after the other.

>  };
>  
>  struct nouveau_pgraph_engine {
> @@ -383,6 +389,9 @@ struct nouveau_pgraph_engine {
>  	void (*tlb_flush)(struct drm_device *dev);
>  
>  	void (*set_tile_region)(struct drm_device *dev, int i);
> +
> +	int  (*pause)(struct drm_device *);
> +	void  (*unpause)(struct drm_device *);
>  };
>  
>  struct nouveau_display_engine {
> @@ -1094,6 +1103,8 @@ extern void nv04_fifo_destroy_context(struct nouveau_channel *);
>  extern int  nv04_fifo_load_context(struct nouveau_channel *);
>  extern int  nv04_fifo_unload_context(struct drm_device *);
>  extern void nv04_fifo_isr(struct drm_device *);
> +extern void nv04_fifo_cache_pause(struct drm_device *dev);
> +extern void nv04_fifo_cache_unpause(struct drm_device *dev);
>  
>  /* nv10_fifo.c */
>  extern int  nv10_fifo_init(struct drm_device *);
> @@ -1117,6 +1128,8 @@ extern void nv50_fifo_destroy_context(struct nouveau_channel *);
>  extern int  nv50_fifo_load_context(struct nouveau_channel *);
>  extern int  nv50_fifo_unload_context(struct drm_device *);
>  extern void nv50_fifo_tlb_flush(struct drm_device *dev);
> +extern int  nv50_fifo_pause(struct drm_device *);
> +extern void nv50_fifo_unpause(struct drm_device *);
>  
>  /* nvc0_fifo.c */
>  extern int  nvc0_fifo_init(struct drm_device *);
> @@ -1189,6 +1202,8 @@ extern int  nv50_graph_unload_context(struct drm_device *);
>  extern int  nv50_grctx_init(struct nouveau_grctx *);
>  extern void nv50_graph_tlb_flush(struct drm_device *dev);
>  extern void nv86_graph_tlb_flush(struct drm_device *dev);
> +extern int  nv50_graph_pause(struct drm_device *dev);
> +extern void nv50_graph_unpause(struct drm_device *dev);
>  extern struct nouveau_enum nv50_data_error_names[];
>  
>  /* nvc0_graph.c */
> diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.c b/drivers/gpu/drm/nouveau/nouveau_pm.c
> index fb846a3..233deec 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_pm.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_pm.c
> @@ -59,6 +59,7 @@ nouveau_pm_perflvl_set(struct drm_device *dev, struct nouveau_pm_level *perflvl)
>  {
>  	struct drm_nouveau_private *dev_priv = dev->dev_private;
>  	struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
> +	unsigned long flags;
>  	int ret;
>  
>  	if (perflvl == pm->cur)
> @@ -72,13 +73,42 @@ nouveau_pm_perflvl_set(struct drm_device *dev, struct nouveau_pm_level *perflvl)
>  		}
>  	}
>  
> +	/* Do not allow the card to allocate/destroy a
> +	 * new channel while reclocking.
> +	 */
> +	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
> +
> +	/* Pause the engines, if possible */
> +	if (dev_priv->engine.fifo.pause(dev)) {
> +		ret = -EIO;
> +		goto out;
> +	}
> +	dev_priv->engine.fifo.cache_pause(dev);
> +	if (dev_priv->engine.graph.pause(dev)) {
> +		ret = -EIO;
> +		goto out;
> +	}

Just nitpicking here, but, if pause() is already returning an errno you
should just pass the same thing on, like:
|         ret = dev_priv->engine.fifo.pause(dev);
|         if (ret)
|                 goto out;
|
|         ret = dev_priv->engine.graph.pause(dev);
|         if (ret)
|                 goto out;


> +
>  	nouveau_pm_clock_set(dev, perflvl, PLL_CORE, perflvl->core);
>  	nouveau_pm_clock_set(dev, perflvl, PLL_SHADER, perflvl->shader);
>  	nouveau_pm_clock_set(dev, perflvl, PLL_MEMORY, perflvl->memory);
>  	nouveau_pm_clock_set(dev, perflvl, PLL_UNK05, perflvl->unk05);
>  
> +	/* Wait for PLLs to stabilize */
> +	udelay(100);
> +
>  	pm->cur = perflvl;
> -	return 0;
> +	ret = 0;
> +
> +out:
> +	/* Un-pause the engines */
> +	dev_priv->engine.fifo.cache_unpause(dev);
> +	dev_priv->engine.graph.unpause(dev);
> +	dev_priv->engine.fifo.unpause(dev);
> +
> +	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
> +
> +	return ret;
>  }
>  
>  static int
> diff --git a/drivers/gpu/drm/nouveau/nouveau_reg.h b/drivers/gpu/drm/nouveau/nouveau_reg.h
> index 04e8fb7..1722d13 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_reg.h
> +++ b/drivers/gpu/drm/nouveau/nouveau_reg.h
> @@ -695,8 +695,11 @@
>  #define NV50_PROM__ESIZE                                       0x10000
>  
>  #define NV50_PGRAPH                                         0x00400000
> +#define NV50_PGRAPH_CONTROL                                 0x00400500
> +#define NV50_PGRAPH_STATUS                                  0x00400700
>  #define NV50_PGRAPH__LEN                                           0x1
>  #define NV50_PGRAPH__ESIZE                                     0x10000
> +#define NV50_PFIFO_FREEZE                                       0x2504
>  
>  #define NV50_PDISPLAY                                                0x00610000
>  #define NV50_PDISPLAY_OBJECTS                                        0x00610010
> diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c
> index d5b17b6..c149cf8 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_state.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_state.c
> @@ -42,6 +42,12 @@
>  static void nouveau_stub_takedown(struct drm_device *dev) {}
>  static int nouveau_stub_init(struct drm_device *dev) { return 0; }
>  
> +int nouveau_fifo_pause_dummy(struct drm_device *dev) { return 0; }
> +void nouveau_fifo_unpause_dummy(struct drm_device *dev) { }
> +
> +int nouveau_graph_pause_dummy(struct drm_device *dev) {	return 0; }
> +void nouveau_graph_unpause_dummy(struct drm_device *dev) {}

This is just the nv04- implementation of graph->(un)pause(), nv04_graph.c
is the best place for it, and I'd call it "nv04_graph_(un)pause" for the
sake of consistency.

> +
>  static int nouveau_init_engine_ptrs(struct drm_device *dev)
>  {
>  	struct drm_nouveau_private *dev_priv = dev->dev_private;
> @@ -73,6 +79,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
>  		engine->graph.destroy_context	= nv04_graph_destroy_context;
>  		engine->graph.load_context	= nv04_graph_load_context;
>  		engine->graph.unload_context	= nv04_graph_unload_context;
> +		engine->graph.pause		= nouveau_graph_pause_dummy;
> +		engine->graph.unpause	= nouveau_graph_unpause_dummy;
>  		engine->fifo.channels		= 16;
>  		engine->fifo.init		= nv04_fifo_init;
>  		engine->fifo.takedown		= nv04_fifo_fini;
> @@ -85,6 +93,10 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
>  		engine->fifo.destroy_context	= nv04_fifo_destroy_context;
>  		engine->fifo.load_context	= nv04_fifo_load_context;
>  		engine->fifo.unload_context	= nv04_fifo_unload_context;
> +		engine->fifo.pause		= nouveau_fifo_pause_dummy;
> +		engine->fifo.unpause	= nouveau_fifo_unpause_dummy;
> +		engine->fifo.cache_pause = nv04_fifo_cache_pause;
> +		engine->fifo.cache_unpause = nv04_fifo_cache_unpause;
>  		engine->display.early_init	= nv04_display_early_init;
>  		engine->display.late_takedown	= nv04_display_late_takedown;
>  		engine->display.create		= nv04_display_create;
> @@ -132,6 +144,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
>  		engine->graph.load_context	= nv10_graph_load_context;
>  		engine->graph.unload_context	= nv10_graph_unload_context;
>  		engine->graph.set_tile_region	= nv10_graph_set_tile_region;
> +		engine->graph.pause		= nouveau_graph_pause_dummy;
> +		engine->graph.unpause	= nouveau_graph_unpause_dummy;
>  		engine->fifo.channels		= 32;
>  		engine->fifo.init		= nv10_fifo_init;
>  		engine->fifo.takedown		= nv04_fifo_fini;
> @@ -144,6 +158,10 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
>  		engine->fifo.destroy_context	= nv04_fifo_destroy_context;
>  		engine->fifo.load_context	= nv10_fifo_load_context;
>  		engine->fifo.unload_context	= nv10_fifo_unload_context;
> +		engine->fifo.pause		= nouveau_fifo_pause_dummy;
> +		engine->fifo.unpause	= nouveau_fifo_unpause_dummy;
> +		engine->fifo.cache_pause = nv04_fifo_cache_pause;
> +		engine->fifo.cache_unpause = nv04_fifo_cache_unpause;
>  		engine->display.early_init	= nv04_display_early_init;
>  		engine->display.late_takedown	= nv04_display_late_takedown;
>  		engine->display.create		= nv04_display_create;
> @@ -191,6 +209,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
>  		engine->graph.load_context	= nv20_graph_load_context;
>  		engine->graph.unload_context	= nv20_graph_unload_context;
>  		engine->graph.set_tile_region	= nv20_graph_set_tile_region;
> +		engine->graph.pause		= nouveau_graph_pause_dummy;
> +		engine->graph.unpause	= nouveau_graph_unpause_dummy;
>  		engine->fifo.channels		= 32;
>  		engine->fifo.init		= nv10_fifo_init;
>  		engine->fifo.takedown		= nv04_fifo_fini;
> @@ -203,6 +223,10 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
>  		engine->fifo.destroy_context	= nv04_fifo_destroy_context;
>  		engine->fifo.load_context	= nv10_fifo_load_context;
>  		engine->fifo.unload_context	= nv10_fifo_unload_context;
> +		engine->fifo.pause		= nouveau_fifo_pause_dummy;
> +		engine->fifo.unpause	= nouveau_fifo_unpause_dummy;
> +		engine->fifo.cache_pause = nv04_fifo_cache_pause;
> +		engine->fifo.cache_unpause = nv04_fifo_cache_unpause;
>  		engine->display.early_init	= nv04_display_early_init;
>  		engine->display.late_takedown	= nv04_display_late_takedown;
>  		engine->display.create		= nv04_display_create;
> @@ -250,6 +274,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
>  		engine->graph.load_context	= nv20_graph_load_context;
>  		engine->graph.unload_context	= nv20_graph_unload_context;
>  		engine->graph.set_tile_region	= nv20_graph_set_tile_region;
> +		engine->graph.pause		= nouveau_graph_pause_dummy;
> +		engine->graph.unpause	= nouveau_graph_unpause_dummy;
>  		engine->fifo.channels		= 32;
>  		engine->fifo.init		= nv10_fifo_init;
>  		engine->fifo.takedown		= nv04_fifo_fini;
> @@ -262,6 +288,10 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
>  		engine->fifo.destroy_context	= nv04_fifo_destroy_context;
>  		engine->fifo.load_context	= nv10_fifo_load_context;
>  		engine->fifo.unload_context	= nv10_fifo_unload_context;
> +		engine->fifo.pause		= nouveau_fifo_pause_dummy;
> +		engine->fifo.unpause	= nouveau_fifo_unpause_dummy;
> +		engine->fifo.cache_pause = nv04_fifo_cache_pause;
> +		engine->fifo.cache_unpause = nv04_fifo_cache_unpause;
>  		engine->display.early_init	= nv04_display_early_init;
>  		engine->display.late_takedown	= nv04_display_late_takedown;
>  		engine->display.create		= nv04_display_create;
> @@ -312,6 +342,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
>  		engine->graph.load_context	= nv40_graph_load_context;
>  		engine->graph.unload_context	= nv40_graph_unload_context;
>  		engine->graph.set_tile_region	= nv40_graph_set_tile_region;
> +		engine->graph.pause		= nouveau_graph_pause_dummy;
> +		engine->graph.unpause	= nouveau_graph_unpause_dummy;
>  		engine->fifo.channels		= 32;
>  		engine->fifo.init		= nv40_fifo_init;
>  		engine->fifo.takedown		= nv04_fifo_fini;
> @@ -324,6 +356,10 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
>  		engine->fifo.destroy_context	= nv04_fifo_destroy_context;
>  		engine->fifo.load_context	= nv40_fifo_load_context;
>  		engine->fifo.unload_context	= nv40_fifo_unload_context;
> +		engine->fifo.pause		= nouveau_fifo_pause_dummy;
> +		engine->fifo.unpause	= nouveau_fifo_unpause_dummy;
> +		engine->fifo.cache_pause = nv04_fifo_cache_pause;
> +		engine->fifo.cache_unpause = nv04_fifo_cache_unpause;
>  		engine->display.early_init	= nv04_display_early_init;
>  		engine->display.late_takedown	= nv04_display_late_takedown;
>  		engine->display.create		= nv04_display_create;
> @@ -376,6 +412,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
>  		engine->graph.destroy_context	= nv50_graph_destroy_context;
>  		engine->graph.load_context	= nv50_graph_load_context;
>  		engine->graph.unload_context	= nv50_graph_unload_context;
> +		engine->graph.pause		= nv50_graph_pause;
> +		engine->graph.unpause	= nv50_graph_unpause;
>  		if (dev_priv->chipset != 0x86)
>  			engine->graph.tlb_flush	= nv50_graph_tlb_flush;
>  		else {
> @@ -397,6 +435,10 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
>  		engine->fifo.load_context	= nv50_fifo_load_context;
>  		engine->fifo.unload_context	= nv50_fifo_unload_context;
>  		engine->fifo.tlb_flush		= nv50_fifo_tlb_flush;
> +		engine->fifo.pause			= nv50_fifo_pause;
> +		engine->fifo.unpause		= nv50_fifo_unpause;
> +		engine->fifo.cache_pause = nv04_fifo_cache_pause;
> +		engine->fifo.cache_unpause = nv04_fifo_cache_unpause;
>  		engine->display.early_init	= nv50_display_early_init;
>  		engine->display.late_takedown	= nv50_display_late_takedown;
>  		engine->display.create		= nv50_display_create;
> @@ -484,6 +526,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
>  		engine->graph.destroy_context	= nvc0_graph_destroy_context;
>  		engine->graph.load_context	= nvc0_graph_load_context;
>  		engine->graph.unload_context	= nvc0_graph_unload_context;
> +		engine->graph.pause		= nouveau_graph_pause_dummy;
> +		engine->graph.unpause	= nouveau_graph_unpause_dummy;
>  		engine->fifo.channels		= 128;
>  		engine->fifo.init		= nvc0_fifo_init;
>  		engine->fifo.takedown		= nvc0_fifo_takedown;
> @@ -495,6 +539,10 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
>  		engine->fifo.destroy_context	= nvc0_fifo_destroy_context;
>  		engine->fifo.load_context	= nvc0_fifo_load_context;
>  		engine->fifo.unload_context	= nvc0_fifo_unload_context;
> +		engine->fifo.pause		= nouveau_fifo_pause_dummy;
> +		engine->fifo.unpause	= nouveau_fifo_unpause_dummy;
> +		engine->fifo.cache_pause = nv04_fifo_cache_pause;
> +		engine->fifo.cache_unpause = nv04_fifo_cache_unpause;
>  		engine->display.early_init	= nv50_display_early_init;
>  		engine->display.late_takedown	= nv50_display_late_takedown;
>  		engine->display.create		= nv50_display_create;
> @@ -893,7 +941,7 @@ static int nouveau_remove_conflicting_drivers(struct drm_device *dev)
>  #ifdef CONFIG_X86
>  	primary = dev->pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
>  #endif
> -	
> +
>  	remove_conflicting_framebuffers(dev_priv->apertures, "nouveaufb", primary);
>  	return 0;
>  }
> @@ -1199,4 +1247,3 @@ bool nouveau_wait_for_idle(struct drm_device *dev)
>  
>  	return true;
>  }
> -

This is unrelated clean-up, please split it into separate patches if you
made them on purpose.

> diff --git a/drivers/gpu/drm/nouveau/nv04_fifo.c b/drivers/gpu/drm/nouveau/nv04_fifo.c
> index f89d104..df84586 100644
> --- a/drivers/gpu/drm/nouveau/nv04_fifo.c
> +++ b/drivers/gpu/drm/nouveau/nv04_fifo.c
> @@ -530,3 +530,19 @@ nv04_fifo_isr(struct drm_device *dev)
>  
>  	nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PFIFO_PENDING);
>  }
> +
> +void
> +nv04_fifo_cache_pause(struct drm_device *dev)
> +{
> +	nv04_fifo_reassign(dev, false);
> +	nv04_fifo_cache_pull(dev, false);
> +	nv_mask(dev, NV04_PFIFO_CACHE1_DMA_PUSH, 0x1, 0);
> +}
> +
> +void
> +nv04_fifo_cache_unpause(struct drm_device *dev)
> +{
> +	nv_mask(dev, NV04_PFIFO_CACHE1_DMA_PUSH, 0, 0x1);
> +	nv04_fifo_cache_pull(dev, true);
> +	nv04_fifo_reassign(dev, true);
> +}
> diff --git a/drivers/gpu/drm/nouveau/nv50_fifo.c b/drivers/gpu/drm/nouveau/nv50_fifo.c
> index 8dd04c5..90a3dc1 100644
> --- a/drivers/gpu/drm/nouveau/nv50_fifo.c
> +++ b/drivers/gpu/drm/nouveau/nv50_fifo.c
> @@ -501,3 +501,23 @@ nv50_fifo_tlb_flush(struct drm_device *dev)
>  {
>  	nv50_vm_flush_engine(dev, 5);
>  }
> +
> +int
> +nv50_fifo_pause(struct drm_device *dev)
> +{
> +	nv_wr32(dev, NV50_PFIFO_FREEZE, 1);
> +
> +	/* Wait up to 10ms for PFIFO to freeze */
> +	if (!nouveau_wait_eq(dev, 10000000, NV50_PFIFO_FREEZE,
> +		0x10, 0x10)) {
> +		NV_ERROR(dev, "PFIFO freeze fail!\n");
> +		return -EIO;
> +	}
> +	return 0;
> +}
> +
> +void
> +nv50_fifo_unpause(struct drm_device *dev)
> +{
> +	nv_wr32(dev, NV50_PFIFO_FREEZE, 0);
> +}
> diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c
> index 2d7ea75..79bc157 100644
> --- a/drivers/gpu/drm/nouveau/nv50_graph.c
> +++ b/drivers/gpu/drm/nouveau/nv50_graph.c
> @@ -1047,3 +1047,69 @@ nv50_graph_isr(struct drm_device *dev)
>  	if (nv_rd32(dev, 0x400824) & (1 << 31))
>  		nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) & ~(1 << 31));
>  }
> +
> +int
> +nv50_graph_pause(struct drm_device *dev)
> +{
> +	uint64_t start;
> +	/* initial guess... */
> +	uint32_t mask380 = 0xffffffff;
> +	uint32_t mask384 = 0xffffffff;
> +	uint32_t mask388 = 0xffffffff;
> +	uint32_t mask504 = 0x00000001;
> +	uint32_t mask700 = 0x00000001;
> +
> +	start = nv04_timer_read(dev);
> +
> +	/* Wait for the end of the execution of a ctxprog */
> +	while ((!(nv_rd32(dev, 0x400504) & mask504)) ||
> +		   (nv_rd32(dev, NV50_PGRAPH_STATUS) & 0x100)) {
> +		if (nv04_timer_read(dev) - start >= 10000000) {
> +			if (nv_rd32(dev, NV50_PGRAPH_STATUS) & 0x100)
> +				NV_ERROR(dev,
> +						"PGRAPH: PGRAPH paused while running a ctxprog,"
> +						" NV40_PGRAPH_CTXCTL_0310 = 0x%x\n",
> +						nv_rd32(dev, NV40_PGRAPH_CTXCTL_0310));

This (and the error messages below) goes over the 80-column limit, and
the indentation is a bit weird.

> +			return -EIO;
> +		}
> +	}
> +
> +	/* Stop PGRAPH */
> +	nv_mask(dev, NV50_PGRAPH_CONTROL, 0x1, 0);
> +
> +	/* Wait for PGRAPH to be really stopped */
> +	while ((nv_rd32(dev, 0x400380) & mask380) ||
> +		   (nv_rd32(dev, 0x400384) & mask384) ||
> +		   (nv_rd32(dev, 0x400388) & mask388) ||
> +		   (!(nv_rd32(dev, 0x400504) & mask504)) ||
> +		   (nv_rd32(dev, NV50_PGRAPH_STATUS) & mask700)) {
> +		if (nv04_timer_read(dev) - start >= 10000000) {
> +			/* if you see this message,
> +			 * mask* above probably need to be adjusted
> +			 * to not contain the bits you see failing */
> +			NV_ERROR(dev,
> +					 "PGRAPH: wait for idle fail: %08x %08x %08x %08x %08x!\n",
> +					 nv_rd32(dev, 0x400380),
> +					 nv_rd32(dev, 0x400384),
> +					 nv_rd32(dev, 0x400388),
> +					 nv_rd32(dev, 0x400504),
> +					 nv_rd32(dev, NV50_PGRAPH_STATUS));
> +
> +			if (nv_rd32(dev, NV50_PGRAPH_STATUS) & 0x100)
> +				NV_ERROR(dev,
> +						"PGRAPH: PGRAPH paused while running a ctxprog,"
> +						" NV40_PGRAPH_CTXCTL_0310 = 0x%x\n",
> +						nv_rd32(dev, NV40_PGRAPH_CTXCTL_0310));
> +
> +			nv50_graph_unpause(dev);
> +			return -EIO;
> +		}
> +	}
> +	return 0;
> +}

I'm OK with this function but I have a feeling it could be simplified a
lot if you implemented it in terms of "nv_wait(_ne)()" (e.g. all the
loops, maskXXX and timer handling could go away).

> +
> +void
> +nv50_graph_unpause(struct drm_device *dev)
> +{
> +	nv_mask(dev, NV50_PGRAPH_CONTROL, 0, 0x1);
> +}

[-- Attachment #1.2: Type: application/pgp-signature, Size: 229 bytes --]

[-- Attachment #2: Type: text/plain, Size: 181 bytes --]

_______________________________________________
Nouveau mailing list
Nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org
http://lists.freedesktop.org/mailman/listinfo/nouveau

      parent reply	other threads:[~2011-01-12 20:27 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-01-09 23:56 [PATCH] Add PFIFO and PGRAPH pausing methods Martin Peres
     [not found] ` <4D2A4B1C.6050908-GANU6spQydw@public.gmane.org>
2011-01-12 20:27   ` Francisco Jerez [this message]

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=87ipxtj29z.fsf@riseup.net \
    --to=currojerez-sgozh3hwpm2stnjn9+bgxg@public.gmane.org \
    --cc=Nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org \
    --cc=martin.peres-GANU6spQydw@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.