[Nouveau] [PATCH] drm/nouveau: restore subchannel<->object binding on resume
Ben Skeggs
skeggsb at gmail.com
Sun Jul 17 17:33:53 PDT 2011
On Sun, 2011-07-17 at 23:03 +0200, Marcin Slusarz wrote:
> On at least one nv43 after resume gdi subchannel on kernel channel
> is bound to M2MF object. It seems last used (before suspend) channel
> needs manual restore of subchannel binding.
> Addresses: https://bugzilla.kernel.org/show_bug.cgi?id=39422
NACK
Such hackery really shouldn't be required, that kind of state is
supposed to be saved in the context on suspend.
I actually noticed this problem myself at the end of last week while
doing a run through my "old" cards, took a look just now and tracked
down the cause I believe. I've pushed a fix to git.
Ben.
>
> Reported-by: Andrew Randrianasulu <randrik at mail.ru>
> Tested-by: Andrew Randrianasulu <randrik at mail.ru>
> Signed-off-by: Marcin Slusarz <marcin.slusarz at gmail.com>
> ---
> drivers/gpu/drm/nouveau/nouveau_dma.c | 3 +--
> drivers/gpu/drm/nouveau/nouveau_dma.h | 20 ++++++++++++++++++++
> drivers/gpu/drm/nouveau/nouveau_drv.c | 8 ++++++++
> drivers/gpu/drm/nouveau/nouveau_drv.h | 3 +++
> drivers/gpu/drm/nouveau/nouveau_fence.c | 3 +--
> drivers/gpu/drm/nouveau/nv04_fbcon.c | 18 ++++++------------
> drivers/gpu/drm/nouveau/nv50_fbcon.c | 3 +--
> drivers/gpu/drm/nouveau/nvc0_fbcon.c | 3 +--
> 8 files changed, 41 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.c b/drivers/gpu/drm/nouveau/nouveau_dma.c
> index 568caed..2711abd 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_dma.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_dma.c
> @@ -70,8 +70,7 @@ nouveau_dma_init(struct nouveau_channel *chan)
> if (ret)
> return ret;
>
> - BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0000, 1);
> - OUT_RING (chan, 0x00009039);
> + BIND_RING_C0(chan, NvSubM2MF, 0x00009039);
> FIRE_RING (chan);
> return 0;
> }
> diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.h b/drivers/gpu/drm/nouveau/nouveau_dma.h
> index 23d4edf..2ce4619 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_dma.h
> +++ b/drivers/gpu/drm/nouveau/nouveau_dma.h
> @@ -138,6 +138,26 @@ BEGIN_RING(struct nouveau_channel *chan, int subc, int mthd, int size)
> OUT_RING(chan, (subc << 13) | (size << 18) | mthd);
> }
>
> +static inline void
> +BIND_RING(struct nouveau_channel *chan, int subc, int handle)
> +{
> + BUG_ON(subc < 0 || subc > 7);
> + chan->subchannels[subc] = handle;
> +
> + BEGIN_RING(chan, subc, 0x0000, 1);
> + OUT_RING (chan, handle);
> +}
> +
> +static inline void
> +BIND_RING_C0(struct nouveau_channel *chan, int subc, int handle)
> +{
> + BUG_ON(subc < 0 || subc > 7);
> + chan->subchannels[subc] = handle;
> +
> + BEGIN_NVC0(chan, 2, subc, 0x0000, 1);
> + OUT_RING (chan, handle);
> +}
> +
> #define WRITE_PUT(val) do { \
> DRM_MEMORYBARRIER(); \
> nouveau_bo_rd32(chan->pushbuf_bo, 0); \
> diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c
> index 02c6f37..69afd95 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_drv.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c
> @@ -262,6 +262,7 @@ nouveau_pci_resume(struct pci_dev *pdev)
> struct drm_nouveau_private *dev_priv = dev->dev_private;
> struct nouveau_engine *engine = &dev_priv->engine;
> struct drm_crtc *crtc;
> + struct nouveau_channel *chan = dev_priv->channel;
> int ret, i;
>
> if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
> @@ -301,6 +302,13 @@ nouveau_pci_resume(struct pci_dev *pdev)
> NV_INFO(dev, "Restoring GPU objects...\n");
> nouveau_gpuobj_resume(dev);
>
> + for (i = 0; i < 8; ++i)
> + if (chan->subchannels[i])
> + if (dev_priv->card_type >= NV_C0)
> + BIND_RING_C0(chan, i, chan->subchannels[i]);
> + else
> + BIND_RING(chan, i, chan->subchannels[i]);
> +
> NV_INFO(dev, "Reinitialising engines...\n");
> engine->instmem.resume(dev);
> engine->mc.init(dev);
> diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
> index 9c56331..bc1adf8 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_drv.h
> +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
> @@ -287,6 +287,9 @@ struct nouveau_channel {
> struct list_head flip;
> } nvsw;
>
> + /* subchannel->object binding, valid only for kernel channel */
> + int subchannels[8];
> +
> struct {
> bool active;
> char name[32];
> diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c
> index 7347075..22998a7 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_fence.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c
> @@ -520,8 +520,7 @@ nouveau_fence_channel_init(struct nouveau_channel *chan)
> if (ret)
> return ret;
>
> - BEGIN_RING(chan, NvSubSw, 0, 1);
> - OUT_RING (chan, NvSw);
> + BIND_RING(chan, NvSubSw, NvSw);
> FIRE_RING (chan);
> }
>
> diff --git a/drivers/gpu/drm/nouveau/nv04_fbcon.c b/drivers/gpu/drm/nouveau/nv04_fbcon.c
> index 7a11893..9ab4fbe 100644
> --- a/drivers/gpu/drm/nouveau/nv04_fbcon.c
> +++ b/drivers/gpu/drm/nouveau/nv04_fbcon.c
> @@ -209,8 +209,7 @@ nv04_fbcon_accel_init(struct fb_info *info)
> return 0;
> }
>
> - BEGIN_RING(chan, sub, 0x0000, 1);
> - OUT_RING(chan, NvCtxSurf2D);
> + BIND_RING(chan, sub, NvCtxSurf2D);
> BEGIN_RING(chan, sub, 0x0184, 2);
> OUT_RING(chan, NvDmaFB);
> OUT_RING(chan, NvDmaFB);
> @@ -220,13 +219,11 @@ nv04_fbcon_accel_init(struct fb_info *info)
> OUT_RING(chan, info->fix.smem_start - dev->mode_config.fb_base);
> OUT_RING(chan, info->fix.smem_start - dev->mode_config.fb_base);
>
> - BEGIN_RING(chan, sub, 0x0000, 1);
> - OUT_RING(chan, NvRop);
> + BIND_RING(chan, sub, NvRop);
> BEGIN_RING(chan, sub, 0x0300, 1);
> OUT_RING(chan, 0x55);
>
> - BEGIN_RING(chan, sub, 0x0000, 1);
> - OUT_RING(chan, NvImagePatt);
> + BIND_RING(chan, sub, NvImagePatt);
> BEGIN_RING(chan, sub, 0x0300, 8);
> OUT_RING(chan, pattern_fmt);
> #ifdef __BIG_ENDIAN
> @@ -241,21 +238,18 @@ nv04_fbcon_accel_init(struct fb_info *info)
> OUT_RING(chan, ~0);
> OUT_RING(chan, ~0);
>
> - BEGIN_RING(chan, sub, 0x0000, 1);
> - OUT_RING(chan, NvClipRect);
> + BIND_RING(chan, sub, NvClipRect);
> BEGIN_RING(chan, sub, 0x0300, 2);
> OUT_RING(chan, 0);
> OUT_RING(chan, (info->var.yres_virtual << 16) | info->var.xres_virtual);
>
> - BEGIN_RING(chan, NvSubImageBlit, 0x0000, 1);
> - OUT_RING(chan, NvImageBlit);
> + BIND_RING(chan, NvSubImageBlit, NvImageBlit);
> BEGIN_RING(chan, NvSubImageBlit, 0x019c, 1);
> OUT_RING(chan, NvCtxSurf2D);
> BEGIN_RING(chan, NvSubImageBlit, 0x02fc, 1);
> OUT_RING(chan, 3);
>
> - BEGIN_RING(chan, NvSubGdiRect, 0x0000, 1);
> - OUT_RING(chan, NvGdiRect);
> + BIND_RING(chan, NvSubGdiRect, NvGdiRect);
> BEGIN_RING(chan, NvSubGdiRect, 0x0198, 1);
> OUT_RING(chan, NvCtxSurf2D);
> BEGIN_RING(chan, NvSubGdiRect, 0x0188, 2);
> diff --git a/drivers/gpu/drm/nouveau/nv50_fbcon.c b/drivers/gpu/drm/nouveau/nv50_fbcon.c
> index 791ded1..b819703 100644
> --- a/drivers/gpu/drm/nouveau/nv50_fbcon.c
> +++ b/drivers/gpu/drm/nouveau/nv50_fbcon.c
> @@ -199,8 +199,7 @@ nv50_fbcon_accel_init(struct fb_info *info)
> return ret;
> }
>
> - BEGIN_RING(chan, NvSub2D, 0x0000, 1);
> - OUT_RING(chan, Nv2D);
> + BIND_RING(chan, NvSub2D, Nv2D);
> BEGIN_RING(chan, NvSub2D, 0x0180, 4);
> OUT_RING(chan, NvNotify0);
> OUT_RING(chan, chan->vram_handle);
> diff --git a/drivers/gpu/drm/nouveau/nvc0_fbcon.c b/drivers/gpu/drm/nouveau/nvc0_fbcon.c
> index fa5d4c2..7d1f3c4 100644
> --- a/drivers/gpu/drm/nouveau/nvc0_fbcon.c
> +++ b/drivers/gpu/drm/nouveau/nvc0_fbcon.c
> @@ -200,8 +200,7 @@ nvc0_fbcon_accel_init(struct fb_info *info)
> return ret;
> }
>
> - BEGIN_NVC0(chan, 2, NvSub2D, 0x0000, 1);
> - OUT_RING (chan, 0x0000902d);
> + BIND_RING_C0(chan, NvSub2D, 0x0000902d);
> BEGIN_NVC0(chan, 2, NvSub2D, 0x0104, 2);
> OUT_RING (chan, upper_32_bits(chan->notifier_bo->bo.offset));
> OUT_RING (chan, lower_32_bits(chan->notifier_bo->bo.offset));
More information about the Nouveau
mailing list