diff options
| author | Ben Skeggs <bskeggs@redhat.com> | 2013-04-24 21:43:54 -0400 |
|---|---|---|
| committer | Ben Skeggs <bskeggs@redhat.com> | 2013-04-26 01:38:14 -0400 |
| commit | 10caad339c458df47e5a9e16e148087fcde98fec (patch) | |
| tree | c704ebc81bd3f904eeda8a281d3c0c7efea072be | |
| parent | 066a5d0938c64bec665866b145d8538d9f96bcda (diff) | |
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>
| -rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/device/base.c | 155 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/core/include/core/parent.h | 4 |
2 files changed, 71 insertions, 88 deletions
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/base.c b/drivers/gpu/drm/nouveau/core/engine/device/base.c index 497d5f60a195..86d24904e9d3 100644 --- a/drivers/gpu/drm/nouveau/core/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/core/engine/device/base.c | |||
| @@ -55,7 +55,6 @@ nouveau_device_find(u64 name) | |||
| 55 | struct nouveau_devobj { | 55 | struct nouveau_devobj { |
| 56 | struct nouveau_parent base; | 56 | struct nouveau_parent base; |
| 57 | struct nouveau_object *subdev[NVDEV_SUBDEV_NR]; | 57 | struct nouveau_object *subdev[NVDEV_SUBDEV_NR]; |
| 58 | bool created; | ||
| 59 | }; | 58 | }; |
| 60 | 59 | ||
| 61 | static const u64 disable_map[] = { | 60 | static const u64 disable_map[] = { |
| @@ -238,26 +237,24 @@ nouveau_devobj_ctor(struct nouveau_object *parent, | |||
| 238 | } | 237 | } |
| 239 | 238 | ||
| 240 | /* ensure requested subsystems are available for use */ | 239 | /* ensure requested subsystems are available for use */ |
| 241 | for (i = 0, c = 0; i < NVDEV_SUBDEV_NR; i++) { | 240 | for (i = 1, c = 1; i < NVDEV_SUBDEV_NR; i++) { |
| 242 | if (!(oclass = device->oclass[i]) || (disable & (1ULL << i))) | 241 | if (!(oclass = device->oclass[i]) || (disable & (1ULL << i))) |
| 243 | continue; | 242 | continue; |
| 244 | 243 | ||
| 245 | if (!device->subdev[i]) { | 244 | if (device->subdev[i]) { |
| 246 | ret = nouveau_object_ctor(nv_object(device), NULL, | ||
| 247 | oclass, NULL, i, | ||
| 248 | &devobj->subdev[i]); | ||
| 249 | if (ret == -ENODEV) | ||
| 250 | continue; | ||
| 251 | if (ret) | ||
| 252 | return ret; | ||
| 253 | |||
| 254 | if (nv_iclass(devobj->subdev[i], NV_ENGINE_CLASS)) | ||
| 255 | nouveau_subdev_reset(devobj->subdev[i]); | ||
| 256 | } else { | ||
| 257 | nouveau_object_ref(device->subdev[i], | 245 | nouveau_object_ref(device->subdev[i], |
| 258 | &devobj->subdev[i]); | 246 | &devobj->subdev[i]); |
| 247 | continue; | ||
| 259 | } | 248 | } |
| 260 | 249 | ||
| 250 | ret = nouveau_object_ctor(nv_object(device), NULL, | ||
| 251 | oclass, NULL, i, | ||
| 252 | &devobj->subdev[i]); | ||
| 253 | if (ret == -ENODEV) | ||
| 254 | continue; | ||
| 255 | if (ret) | ||
| 256 | return ret; | ||
| 257 | |||
| 261 | /* note: can't init *any* subdevs until devinit has been run | 258 | /* note: can't init *any* subdevs until devinit has been run |
| 262 | * due to not knowing exactly what the vbios init tables will | 259 | * due to not knowing exactly what the vbios init tables will |
| 263 | * mess with. devinit also can't be run until all of its | 260 | * mess with. devinit also can't be run until all of its |
| @@ -273,6 +270,10 @@ nouveau_devobj_ctor(struct nouveau_object *parent, | |||
| 273 | ret = nouveau_object_inc(subdev); | 270 | ret = nouveau_object_inc(subdev); |
| 274 | if (ret) | 271 | if (ret) |
| 275 | return ret; | 272 | return ret; |
| 273 | atomic_dec(&nv_object(device)->usecount); | ||
| 274 | } else | ||
| 275 | if (subdev) { | ||
| 276 | nouveau_subdev_reset(subdev); | ||
| 276 | } | 277 | } |
| 277 | } | 278 | } |
| 278 | } | 279 | } |
| @@ -292,74 +293,6 @@ nouveau_devobj_dtor(struct nouveau_object *object) | |||
| 292 | nouveau_parent_destroy(&devobj->base); | 293 | nouveau_parent_destroy(&devobj->base); |
| 293 | } | 294 | } |
| 294 | 295 | ||
| 295 | static int | ||
| 296 | nouveau_devobj_init(struct nouveau_object *object) | ||
| 297 | { | ||
| 298 | struct nouveau_devobj *devobj = (void *)object; | ||
| 299 | struct nouveau_object *subdev; | ||
| 300 | int ret, i; | ||
| 301 | |||
| 302 | ret = nouveau_parent_init(&devobj->base); | ||
| 303 | if (ret) | ||
| 304 | return ret; | ||
| 305 | |||
| 306 | for (i = 0; devobj->created && i < NVDEV_SUBDEV_NR; i++) { | ||
| 307 | if ((subdev = devobj->subdev[i])) { | ||
| 308 | if (!nv_iclass(subdev, NV_ENGINE_CLASS)) { | ||
| 309 | ret = nouveau_object_inc(subdev); | ||
| 310 | if (ret) | ||
| 311 | goto fail; | ||
| 312 | } | ||
| 313 | } | ||
| 314 | } | ||
| 315 | |||
| 316 | devobj->created = true; | ||
| 317 | return 0; | ||
| 318 | |||
| 319 | fail: | ||
| 320 | for (--i; i >= 0; i--) { | ||
| 321 | if ((subdev = devobj->subdev[i])) { | ||
| 322 | if (!nv_iclass(subdev, NV_ENGINE_CLASS)) | ||
| 323 | nouveau_object_dec(subdev, false); | ||
| 324 | } | ||
| 325 | } | ||
| 326 | |||
| 327 | return ret; | ||
| 328 | } | ||
| 329 | |||
| 330 | static int | ||
| 331 | nouveau_devobj_fini(struct nouveau_object *object, bool suspend) | ||
| 332 | { | ||
| 333 | struct nouveau_devobj *devobj = (void *)object; | ||
| 334 | struct nouveau_object *subdev; | ||
| 335 | int ret, i; | ||
| 336 | |||
| 337 | for (i = NVDEV_SUBDEV_NR - 1; i >= 0; i--) { | ||
| 338 | if ((subdev = devobj->subdev[i])) { | ||
| 339 | if (!nv_iclass(subdev, NV_ENGINE_CLASS)) { | ||
| 340 | ret = nouveau_object_dec(subdev, suspend); | ||
| 341 | if (ret && suspend) | ||
| 342 | goto fail; | ||
| 343 | } | ||
| 344 | } | ||
| 345 | } | ||
| 346 | |||
| 347 | ret = nouveau_parent_fini(&devobj->base, suspend); | ||
| 348 | fail: | ||
| 349 | for (; ret && suspend && i < NVDEV_SUBDEV_NR; i++) { | ||
| 350 | if ((subdev = devobj->subdev[i])) { | ||
| 351 | if (!nv_iclass(subdev, NV_ENGINE_CLASS)) { | ||
| 352 | ret = nouveau_object_inc(subdev); | ||
| 353 | if (ret) { | ||
| 354 | /* XXX */ | ||
| 355 | } | ||
| 356 | } | ||
| 357 | } | ||
| 358 | } | ||
| 359 | |||
| 360 | return ret; | ||
| 361 | } | ||
| 362 | |||
| 363 | static u8 | 296 | static u8 |
| 364 | nouveau_devobj_rd08(struct nouveau_object *object, u64 addr) | 297 | nouveau_devobj_rd08(struct nouveau_object *object, u64 addr) |
| 365 | { | 298 | { |
| @@ -400,8 +333,8 @@ static struct nouveau_ofuncs | |||
| 400 | nouveau_devobj_ofuncs = { | 333 | nouveau_devobj_ofuncs = { |
| 401 | .ctor = nouveau_devobj_ctor, | 334 | .ctor = nouveau_devobj_ctor, |
| 402 | .dtor = nouveau_devobj_dtor, | 335 | .dtor = nouveau_devobj_dtor, |
| 403 | .init = nouveau_devobj_init, | 336 | .init = _nouveau_parent_init, |
| 404 | .fini = nouveau_devobj_fini, | 337 | .fini = _nouveau_parent_fini, |
| 405 | .rd08 = nouveau_devobj_rd08, | 338 | .rd08 = nouveau_devobj_rd08, |
| 406 | .rd16 = nouveau_devobj_rd16, | 339 | .rd16 = nouveau_devobj_rd16, |
| 407 | .rd32 = nouveau_devobj_rd32, | 340 | .rd32 = nouveau_devobj_rd32, |
| @@ -423,14 +356,64 @@ static int | |||
| 423 | nouveau_device_fini(struct nouveau_object *object, bool suspend) | 356 | nouveau_device_fini(struct nouveau_object *object, bool suspend) |
| 424 | { | 357 | { |
| 425 | struct nouveau_device *device = (void *)object; | 358 | struct nouveau_device *device = (void *)object; |
| 426 | return nouveau_subdev_fini(&device->base, suspend); | 359 | struct nouveau_object *subdev; |
| 360 | int ret, i; | ||
| 361 | |||
| 362 | for (i = NVDEV_SUBDEV_NR - 1; i >= 0; i--) { | ||
| 363 | if ((subdev = device->subdev[i])) { | ||
| 364 | if (!nv_iclass(subdev, NV_ENGINE_CLASS)) { | ||
| 365 | ret = nouveau_object_dec(subdev, suspend); | ||
| 366 | if (ret && suspend) | ||
| 367 | goto fail; | ||
| 368 | } | ||
| 369 | } | ||
| 370 | } | ||
| 371 | |||
| 372 | ret = 0; | ||
| 373 | fail: | ||
| 374 | for (; ret && i < NVDEV_SUBDEV_NR; i++) { | ||
| 375 | if ((subdev = device->subdev[i])) { | ||
| 376 | if (!nv_iclass(subdev, NV_ENGINE_CLASS)) { | ||
| 377 | ret = nouveau_object_inc(subdev); | ||
| 378 | if (ret) { | ||
| 379 | /* XXX */ | ||
| 380 | } | ||
| 381 | } | ||
| 382 | } | ||
| 383 | } | ||
| 384 | |||
| 385 | return ret; | ||
| 427 | } | 386 | } |
| 428 | 387 | ||
| 429 | static int | 388 | static int |
| 430 | nouveau_device_init(struct nouveau_object *object) | 389 | nouveau_device_init(struct nouveau_object *object) |
| 431 | { | 390 | { |
| 432 | struct nouveau_device *device = (void *)object; | 391 | struct nouveau_device *device = (void *)object; |
| 433 | return nouveau_subdev_init(&device->base); | 392 | struct nouveau_object *subdev; |
| 393 | int ret, i; | ||
| 394 | |||
| 395 | for (i = 0; i < NVDEV_SUBDEV_NR; i++) { | ||
| 396 | if ((subdev = device->subdev[i])) { | ||
| 397 | if (!nv_iclass(subdev, NV_ENGINE_CLASS)) { | ||
| 398 | ret = nouveau_object_inc(subdev); | ||
| 399 | if (ret) | ||
| 400 | goto fail; | ||
| 401 | } else { | ||
| 402 | nouveau_subdev_reset(subdev); | ||
| 403 | } | ||
| 404 | } | ||
| 405 | } | ||
| 406 | |||
| 407 | ret = 0; | ||
| 408 | fail: | ||
| 409 | for (--i; ret && i >= 0; i--) { | ||
| 410 | if ((subdev = device->subdev[i])) { | ||
| 411 | if (!nv_iclass(subdev, NV_ENGINE_CLASS)) | ||
| 412 | nouveau_object_dec(subdev, false); | ||
| 413 | } | ||
| 414 | } | ||
| 415 | |||
| 416 | return ret; | ||
| 434 | } | 417 | } |
| 435 | 418 | ||
| 436 | static void | 419 | static void |
diff --git a/drivers/gpu/drm/nouveau/core/include/core/parent.h b/drivers/gpu/drm/nouveau/core/include/core/parent.h index 31cd852c96df..9f5ea900ff00 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/parent.h +++ b/drivers/gpu/drm/nouveau/core/include/core/parent.h | |||
| @@ -51,8 +51,8 @@ int nouveau_parent_create_(struct nouveau_object *, struct nouveau_object *, | |||
| 51 | void nouveau_parent_destroy(struct nouveau_parent *); | 51 | void nouveau_parent_destroy(struct nouveau_parent *); |
| 52 | 52 | ||
| 53 | void _nouveau_parent_dtor(struct nouveau_object *); | 53 | void _nouveau_parent_dtor(struct nouveau_object *); |
| 54 | #define _nouveau_parent_init _nouveau_object_init | 54 | #define _nouveau_parent_init nouveau_object_init |
| 55 | #define _nouveau_parent_fini _nouveau_object_fini | 55 | #define _nouveau_parent_fini nouveau_object_fini |
| 56 | 56 | ||
| 57 | int nouveau_parent_sclass(struct nouveau_object *, u16 handle, | 57 | int nouveau_parent_sclass(struct nouveau_object *, u16 handle, |
| 58 | struct nouveau_object **pengine, | 58 | struct nouveau_object **pengine, |
