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

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));
-- 
1.7.5.3

_______________________________________________
Nouveau mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/nouveau

Reply via email to