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 <[email protected]> > Tested-by: Andrew Randrianasulu <[email protected]> > Signed-off-by: Marcin Slusarz <[email protected]> > --- > 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)); _______________________________________________ Nouveau mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/nouveau
