drm/nouveau/core: fix subdev/engine/device lookup to not require engine pointer
authorBen Skeggs <bskeggs@redhat.com>
Fri, 5 Dec 2014 01:26:23 +0000 (11:26 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Thu, 22 Jan 2015 02:14:48 +0000 (12:14 +1000)
It's about to not be valid for objects that aren't in the client
object tree.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/core/core/engine.c
drivers/gpu/drm/nouveau/core/core/subdev.c
drivers/gpu/drm/nouveau/core/engine/device/base.c

index 4835056b068967e62bd6ca0462f36467e8549585..85bf4b3d1fe4ef85446c1ac02a42375bf2a7f770 100644 (file)
 #include <core/option.h>
 
 struct nouveau_engine *
-nouveau_engine(void *obj, int sub)
+nouveau_engine(void *obj, int idx)
 {
-       struct nouveau_subdev *subdev = nouveau_subdev(obj, sub);
-       if (subdev && nv_iclass(subdev, NV_ENGINE_CLASS))
-               return nv_engine(subdev);
+       obj = nouveau_subdev(obj, idx);
+       if (obj && nv_iclass(obj, NV_ENGINE_CLASS))
+               return nv_engine(obj);
        return NULL;
 }
 
index edae535406e572fad78160b6e515197621049229..69ba1482c3f50c08ab6b55c6fab3d3ac7a5d0d52 100644 (file)
 #include <core/option.h>
 
 struct nouveau_subdev *
-nouveau_subdev(void *obj, int sub)
+nouveau_subdev(void *obj, int idx)
 {
-       if (nv_device(obj)->subdev[sub])
-               return nv_subdev(nv_device(obj)->subdev[sub]);
-       return NULL;
+       struct nouveau_object *object = nv_object(obj);
+       while (object && !nv_iclass(object, NV_SUBDEV_CLASS))
+               object = object->parent;
+       if (object == NULL || nv_subidx(object) != idx)
+               object = nv_device(obj)->subdev[idx];
+       return object ? nv_subdev(object) : NULL;
 }
 
 void
index e2da1d4029cd692e92b682d42ea400e4e172116a..7c0cbcde7b2f344b8dc05d6a6a2d2e12d858be74 100644 (file)
@@ -511,22 +511,18 @@ nouveau_devobj_ofuncs = {
 struct nouveau_device *
 nv_device(void *obj)
 {
-       struct nouveau_object *object = nv_object(obj);
-       struct nouveau_object *device = object;
-
-       if (device->engine)
-               device = device->engine;
-       if (device->parent)
+       struct nouveau_object *device = nv_object(obj);
+       while (device && device->parent)
                device = device->parent;
-
-#if CONFIG_NOUVEAU_DEBUG >= NV_DBG_PARANOIA
-       if (unlikely(!nv_iclass(device, NV_SUBDEV_CLASS) ||
-                    (nv_hclass(device) & 0xff) != NVDEV_ENGINE_DEVICE)) {
-               nv_assert("BAD CAST -> NvDevice, 0x%08x 0x%08x",
-                         nv_hclass(object), nv_hclass(device));
+       if (!nv_iclass(device, NV_ENGINE_CLASS)) {
+               device = nv_object(obj)->engine;
+               if (device && device->parent)
+                       device = device->parent;
        }
+#if CONFIG_NOUVEAU_DEBUG >= NV_DBG_PARANOIA
+       if (unlikely(!device))
+               nv_assert("BAD CAST -> NvDevice, 0x%08x\n", nv_hclass(obj));
 #endif
-
        return (void *)device;
 }