Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 10caad33 authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nouveau/device: tweak the device/subdev relationship a little



Fixes not-in-use engines not having their reset() method called on
resume.

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 066a5d09
Loading
Loading
Loading
Loading
+69 −86
Original line number Diff line number Diff line
@@ -55,7 +55,6 @@ nouveau_device_find(u64 name)
struct nouveau_devobj {
	struct nouveau_parent base;
	struct nouveau_object *subdev[NVDEV_SUBDEV_NR];
	bool created;
};

static const u64 disable_map[] = {
@@ -238,11 +237,16 @@ nouveau_devobj_ctor(struct nouveau_object *parent,
	}

	/* ensure requested subsystems are available for use */
	for (i = 0, c = 0; i < NVDEV_SUBDEV_NR; i++) {
	for (i = 1, c = 1; i < NVDEV_SUBDEV_NR; i++) {
		if (!(oclass = device->oclass[i]) || (disable & (1ULL << i)))
			continue;

		if (!device->subdev[i]) {
		if (device->subdev[i]) {
			nouveau_object_ref(device->subdev[i],
					  &devobj->subdev[i]);
			continue;
		}

		ret = nouveau_object_ctor(nv_object(device), NULL,
					  oclass, NULL, i,
					  &devobj->subdev[i]);
@@ -251,13 +255,6 @@ nouveau_devobj_ctor(struct nouveau_object *parent,
		if (ret)
			return ret;

			if (nv_iclass(devobj->subdev[i], NV_ENGINE_CLASS))
				nouveau_subdev_reset(devobj->subdev[i]);
		} else {
			nouveau_object_ref(device->subdev[i],
					  &devobj->subdev[i]);
		}

		/* note: can't init *any* subdevs until devinit has been run
		 * due to not knowing exactly what the vbios init tables will
		 * mess with.  devinit also can't be run until all of its
@@ -273,6 +270,10 @@ nouveau_devobj_ctor(struct nouveau_object *parent,
				ret = nouveau_object_inc(subdev);
				if (ret)
					return ret;
				atomic_dec(&nv_object(device)->usecount);
			} else
			if (subdev) {
				nouveau_subdev_reset(subdev);
			}
		}
	}
@@ -292,74 +293,6 @@ nouveau_devobj_dtor(struct nouveau_object *object)
	nouveau_parent_destroy(&devobj->base);
}

static int
nouveau_devobj_init(struct nouveau_object *object)
{
	struct nouveau_devobj *devobj = (void *)object;
	struct nouveau_object *subdev;
	int ret, i;

	ret = nouveau_parent_init(&devobj->base);
	if (ret)
		return ret;

	for (i = 0; devobj->created && i < NVDEV_SUBDEV_NR; i++) {
		if ((subdev = devobj->subdev[i])) {
			if (!nv_iclass(subdev, NV_ENGINE_CLASS)) {
				ret = nouveau_object_inc(subdev);
				if (ret)
					goto fail;
			}
		}
	}

	devobj->created = true;
	return 0;

fail:
	for (--i; i >= 0; i--) {
		if ((subdev = devobj->subdev[i])) {
			if (!nv_iclass(subdev, NV_ENGINE_CLASS))
				nouveau_object_dec(subdev, false);
		}
	}

	return ret;
}

static int
nouveau_devobj_fini(struct nouveau_object *object, bool suspend)
{
	struct nouveau_devobj *devobj = (void *)object;
	struct nouveau_object *subdev;
	int ret, i;

	for (i = NVDEV_SUBDEV_NR - 1; i >= 0; i--) {
		if ((subdev = devobj->subdev[i])) {
			if (!nv_iclass(subdev, NV_ENGINE_CLASS)) {
				ret = nouveau_object_dec(subdev, suspend);
				if (ret && suspend)
					goto fail;
			}
		}
	}

	ret = nouveau_parent_fini(&devobj->base, suspend);
fail:
	for (; ret && suspend && i < NVDEV_SUBDEV_NR; i++) {
		if ((subdev = devobj->subdev[i])) {
			if (!nv_iclass(subdev, NV_ENGINE_CLASS)) {
				ret = nouveau_object_inc(subdev);
				if (ret) {
					/* XXX */
				}
			}
		}
	}

	return ret;
}

static u8
nouveau_devobj_rd08(struct nouveau_object *object, u64 addr)
{
@@ -400,8 +333,8 @@ static struct nouveau_ofuncs
nouveau_devobj_ofuncs = {
	.ctor = nouveau_devobj_ctor,
	.dtor = nouveau_devobj_dtor,
	.init = nouveau_devobj_init,
	.fini = nouveau_devobj_fini,
	.init = _nouveau_parent_init,
	.fini = _nouveau_parent_fini,
	.rd08 = nouveau_devobj_rd08,
	.rd16 = nouveau_devobj_rd16,
	.rd32 = nouveau_devobj_rd32,
@@ -423,14 +356,64 @@ static int
nouveau_device_fini(struct nouveau_object *object, bool suspend)
{
	struct nouveau_device *device = (void *)object;
	return nouveau_subdev_fini(&device->base, suspend);
	struct nouveau_object *subdev;
	int ret, i;

	for (i = NVDEV_SUBDEV_NR - 1; i >= 0; i--) {
		if ((subdev = device->subdev[i])) {
			if (!nv_iclass(subdev, NV_ENGINE_CLASS)) {
				ret = nouveau_object_dec(subdev, suspend);
				if (ret && suspend)
					goto fail;
			}
		}
	}

	ret = 0;
fail:
	for (; ret && i < NVDEV_SUBDEV_NR; i++) {
		if ((subdev = device->subdev[i])) {
			if (!nv_iclass(subdev, NV_ENGINE_CLASS)) {
				ret = nouveau_object_inc(subdev);
				if (ret) {
					/* XXX */
				}
			}
		}
	}

	return ret;
}

static int
nouveau_device_init(struct nouveau_object *object)
{
	struct nouveau_device *device = (void *)object;
	return nouveau_subdev_init(&device->base);
	struct nouveau_object *subdev;
	int ret, i;

	for (i = 0; i < NVDEV_SUBDEV_NR; i++) {
		if ((subdev = device->subdev[i])) {
			if (!nv_iclass(subdev, NV_ENGINE_CLASS)) {
				ret = nouveau_object_inc(subdev);
				if (ret)
					goto fail;
			} else {
				nouveau_subdev_reset(subdev);
			}
		}
	}

	ret = 0;
fail:
	for (--i; ret && i >= 0; i--) {
		if ((subdev = device->subdev[i])) {
			if (!nv_iclass(subdev, NV_ENGINE_CLASS))
				nouveau_object_dec(subdev, false);
		}
	}

	return ret;
}

static void
+2 −2
Original line number Diff line number Diff line
@@ -51,8 +51,8 @@ int nouveau_parent_create_(struct nouveau_object *, struct nouveau_object *,
void nouveau_parent_destroy(struct nouveau_parent *);

void _nouveau_parent_dtor(struct nouveau_object *);
#define _nouveau_parent_init _nouveau_object_init
#define _nouveau_parent_fini _nouveau_object_fini
#define _nouveau_parent_init nouveau_object_init
#define _nouveau_parent_fini nouveau_object_fini

int nouveau_parent_sclass(struct nouveau_object *, u16 handle,
			  struct nouveau_object **pengine,