aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2013-04-24 21:43:54 -0400
committerBen Skeggs <bskeggs@redhat.com>2013-04-26 01:38:14 -0400
commit10caad339c458df47e5a9e16e148087fcde98fec (patch)
treec704ebc81bd3f904eeda8a281d3c0c7efea072be
parent066a5d0938c64bec665866b145d8538d9f96bcda (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.c155
-rw-r--r--drivers/gpu/drm/nouveau/core/include/core/parent.h4
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)
55struct nouveau_devobj { 55struct 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
61static const u64 disable_map[] = { 60static 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
295static int
296nouveau_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
319fail:
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
330static int
331nouveau_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);
348fail:
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
363static u8 296static u8
364nouveau_devobj_rd08(struct nouveau_object *object, u64 addr) 297nouveau_devobj_rd08(struct nouveau_object *object, u64 addr)
365{ 298{
@@ -400,8 +333,8 @@ static struct nouveau_ofuncs
400nouveau_devobj_ofuncs = { 333nouveau_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
423nouveau_device_fini(struct nouveau_object *object, bool suspend) 356nouveau_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;
373fail:
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
429static int 388static int
430nouveau_device_init(struct nouveau_object *object) 389nouveau_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;
408fail:
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
436static void 419static 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 *,
51void nouveau_parent_destroy(struct nouveau_parent *); 51void nouveau_parent_destroy(struct nouveau_parent *);
52 52
53void _nouveau_parent_dtor(struct nouveau_object *); 53void _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
57int nouveau_parent_sclass(struct nouveau_object *, u16 handle, 57int nouveau_parent_sclass(struct nouveau_object *, u16 handle,
58 struct nouveau_object **pengine, 58 struct nouveau_object **pengine,