mirror of https://gitee.com/openkylin/linux.git
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: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
parent
066a5d0938
commit
10caad339c
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue