Nouveau源码分析(四)
probe函数成功返回之后,DRM模块就会调用struct drm_driver的load函数,对应nouveau的nouveau_drm_load.
这个函数虽然看起来不是特别长,但每一个调用的函数展开后就会变得非常长了!
// /drivers/gpu/drm/nouveau/nouveau_drm.c
364 static int
365 nouveau_drm_load(struct drm_device *dev, unsigned long flags)
366 {
367 struct pci_dev *pdev = dev->pdev;
368 struct nouveau_drm *drm;
369 int ret;
370
371 ret = nouveau_cli_create(nouveau_name(dev), "DRM", sizeof(*drm),
372 (void **)&drm);
373 if (ret)
374 return ret;
375
376 dev->dev_private = drm;
377 drm->dev = dev;
378 nvkm_client(&drm->client.base)->debug =
379 nouveau_dbgopt(nouveau_debug, "DRM");
380
381 INIT_LIST_HEAD(&drm->clients);
382 spin_lock_init(&drm->tile.lock);
383
384 nouveau_get_hdmi_dev(drm);
385
386 /* make sure AGP controller is in a consistent state before we
387 * (possibly) execute vbios init tables (see nouveau_agp.h)
388 */
389 if (pdev && drm_pci_device_is_agp(dev) && dev->agp) {
390 const u64 enables = NV_DEVICE_V0_DISABLE_IDENTIFY |
391 NV_DEVICE_V0_DISABLE_MMIO;
392 /* dummy device object, doesn't init anything, but allows
393 * agp code access to registers
394 */
395 ret = nvif_device_init(&drm->client.base.base, NULL,
396 NVDRM_DEVICE, NV_DEVICE,
397 &(struct nv_device_v0) {
398 .device = ~0,
399 .disable = ~enables,
400 .debug0 = ~0,
401 }, sizeof(struct nv_device_v0),
402 &drm->device);
403 if (ret)
404 goto fail_device;
405
406 nouveau_agp_reset(drm);
407 nvif_device_fini(&drm->device);
408 }
409
410 ret = nvif_device_init(&drm->client.base.base, NULL, NVDRM_DEVICE,
411 NV_DEVICE,
412 &(struct nv_device_v0) {
413 .device = ~0,
414 .disable = 0,
415 .debug0 = 0,
416 }, sizeof(struct nv_device_v0),
417 &drm->device);
418 if (ret)
419 goto fail_device;
420
421 dev->irq_enabled = true;
422
423 /* workaround an odd issue on nvc1 by disabling the device's
424 * nosnoop capability. hopefully won't cause issues until a
425 * better fix is found - assuming there is one...
426 */
427 if (drm->device.info.chipset == 0xc1)
428 nvif_mask(&drm->device, 0x00088080, 0x00000800, 0x00000000);
429
430 nouveau_vga_init(drm);
431 nouveau_agp_init(drm);
432
433 if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA) {
434 ret = nouveau_vm_new(nvkm_device(&drm->device), 0, (1ULL << 40),
435 0x1000, &drm->client.vm);
436 if (ret)
437 goto fail_device;
438
439 nvkm_client(&drm->client.base)->vm = drm->client.vm;
440 }
441
442 ret = nouveau_ttm_init(drm);
443 if (ret)
444 goto fail_ttm;
445
446 ret = nouveau_bios_init(dev);
447 if (ret)
448 goto fail_bios;
449
450 ret = nouveau_display_create(dev);
451 if (ret)
452 goto fail_dispctor;
453
454 if (dev->mode_config.num_crtc) {
455 ret = nouveau_display_init(dev);
456 if (ret)
457 goto fail_dispinit;
458 }
459
460 nouveau_sysfs_init(dev);
461 nouveau_hwmon_init(dev);
462 nouveau_accel_init(drm);
463 nouveau_fbcon_init(dev);
464
465 if (nouveau_runtime_pm != 0) {
466 pm_runtime_use_autosuspend(dev->dev);
467 pm_runtime_set_autosuspend_delay(dev->dev, 5000);
468 pm_runtime_set_active(dev->dev);
469 pm_runtime_allow(dev->dev);
470 pm_runtime_mark_last_busy(dev->dev);
471 pm_runtime_put(dev->dev);
472 }
473 retu