drm/nouveau/mc: add helper function to handle device reset
authorBen Skeggs <bskeggs@redhat.com>
Fri, 8 Apr 2016 07:24:40 +0000 (17:24 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Fri, 20 May 2016 04:43:04 +0000 (14:43 +1000)
This will be later extended to handle PTOP-specified reset masks as well
as the hardcoded ones.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/include/nvkm/subdev/mc.h
drivers/gpu/drm/nouveau/nvkm/core/subdev.c
drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c

index 4de05e7..ac6321f 100644 (file)
@@ -10,6 +10,7 @@ struct nvkm_mc {
 void nvkm_mc_intr(struct nvkm_mc *, bool *handled);
 void nvkm_mc_intr_unarm(struct nvkm_mc *);
 void nvkm_mc_intr_rearm(struct nvkm_mc *);
+void nvkm_mc_reset(struct nvkm_mc *, enum nvkm_devidx);
 void nvkm_mc_unk260(struct nvkm_mc *, u32 data);
 
 int nv04_mc_new(struct nvkm_device *, int, struct nvkm_mc **);
index eece74d..68cf606 100644 (file)
@@ -24,6 +24,7 @@
 #include <core/subdev.h>
 #include <core/device.h>
 #include <core/option.h>
+#include <subdev/mc.h>
 
 static struct lock_class_key nvkm_subdev_lock_class[NVKM_SUBDEV_NR];
 
@@ -90,7 +91,6 @@ nvkm_subdev_fini(struct nvkm_subdev *subdev, bool suspend)
 {
        struct nvkm_device *device = subdev->device;
        const char *action = suspend ? "suspend" : "fini";
-       u32 pmc_enable = subdev->pmc_enable;
        s64 time;
 
        nvkm_trace(subdev, "%s running...\n", action);
@@ -105,11 +105,7 @@ nvkm_subdev_fini(struct nvkm_subdev *subdev, bool suspend)
                }
        }
 
-       if (pmc_enable) {
-               nvkm_mask(device, 0x000200, pmc_enable, 0x00000000);
-               nvkm_mask(device, 0x000200, pmc_enable, pmc_enable);
-               nvkm_rd32(device, 0x000200);
-       }
+       nvkm_mc_reset(device->mc, subdev->index);
 
        time = ktime_to_us(ktime_get()) - time;
        nvkm_trace(subdev, "%s completed in %lldus\n", action, time);
index e6c5bc4..9518301 100644 (file)
@@ -77,6 +77,26 @@ nvkm_mc_intr(struct nvkm_mc *mc, bool *handled)
        *handled = intr != 0;
 }
 
+static void
+nvkm_mc_reset_(struct nvkm_mc *mc, enum nvkm_devidx devidx)
+{
+       struct nvkm_device *device = mc->subdev.device;
+       struct nvkm_subdev *subdev = nvkm_device_subdev(device, devidx);
+       u64 pmc_enable = subdev->pmc_enable;
+       if (pmc_enable) {
+               nvkm_mask(device, 0x000200, pmc_enable, 0x00000000);
+               nvkm_mask(device, 0x000200, pmc_enable, pmc_enable);
+               nvkm_rd32(device, 0x000200);
+       }
+}
+
+void
+nvkm_mc_reset(struct nvkm_mc *mc, enum nvkm_devidx devidx)
+{
+       if (likely(mc))
+               nvkm_mc_reset_(mc, devidx);
+}
+
 static int
 nvkm_mc_fini(struct nvkm_subdev *subdev, bool suspend)
 {