diff options
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drm.c | 173 |
1 files changed, 101 insertions, 72 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 905956809d21..2b2baf6e0e0d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c | |||
@@ -458,75 +458,8 @@ nouveau_accel_init(struct nouveau_drm *drm) | |||
458 | nouveau_bo_move_init(drm); | 458 | nouveau_bo_move_init(drm); |
459 | } | 459 | } |
460 | 460 | ||
461 | static int nouveau_drm_probe(struct pci_dev *pdev, | ||
462 | const struct pci_device_id *pent) | ||
463 | { | ||
464 | struct nvkm_device *device; | ||
465 | struct apertures_struct *aper; | ||
466 | bool boot = false; | ||
467 | int ret; | ||
468 | |||
469 | if (vga_switcheroo_client_probe_defer(pdev)) | ||
470 | return -EPROBE_DEFER; | ||
471 | |||
472 | /* We need to check that the chipset is supported before booting | ||
473 | * fbdev off the hardware, as there's no way to put it back. | ||
474 | */ | ||
475 | ret = nvkm_device_pci_new(pdev, NULL, "error", true, false, 0, &device); | ||
476 | if (ret) | ||
477 | return ret; | ||
478 | |||
479 | nvkm_device_del(&device); | ||
480 | |||
481 | /* Remove conflicting drivers (vesafb, efifb etc). */ | ||
482 | aper = alloc_apertures(3); | ||
483 | if (!aper) | ||
484 | return -ENOMEM; | ||
485 | |||
486 | aper->ranges[0].base = pci_resource_start(pdev, 1); | ||
487 | aper->ranges[0].size = pci_resource_len(pdev, 1); | ||
488 | aper->count = 1; | ||
489 | |||
490 | if (pci_resource_len(pdev, 2)) { | ||
491 | aper->ranges[aper->count].base = pci_resource_start(pdev, 2); | ||
492 | aper->ranges[aper->count].size = pci_resource_len(pdev, 2); | ||
493 | aper->count++; | ||
494 | } | ||
495 | |||
496 | if (pci_resource_len(pdev, 3)) { | ||
497 | aper->ranges[aper->count].base = pci_resource_start(pdev, 3); | ||
498 | aper->ranges[aper->count].size = pci_resource_len(pdev, 3); | ||
499 | aper->count++; | ||
500 | } | ||
501 | |||
502 | #ifdef CONFIG_X86 | ||
503 | boot = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW; | ||
504 | #endif | ||
505 | if (nouveau_modeset != 2) | ||
506 | drm_fb_helper_remove_conflicting_framebuffers(aper, "nouveaufb", boot); | ||
507 | kfree(aper); | ||
508 | |||
509 | ret = nvkm_device_pci_new(pdev, nouveau_config, nouveau_debug, | ||
510 | true, true, ~0ULL, &device); | ||
511 | if (ret) | ||
512 | return ret; | ||
513 | |||
514 | pci_set_master(pdev); | ||
515 | |||
516 | if (nouveau_atomic) | ||
517 | driver_pci.driver_features |= DRIVER_ATOMIC; | ||
518 | |||
519 | ret = drm_get_pci_dev(pdev, pent, &driver_pci); | ||
520 | if (ret) { | ||
521 | nvkm_device_del(&device); | ||
522 | return ret; | ||
523 | } | ||
524 | |||
525 | return 0; | ||
526 | } | ||
527 | |||
528 | static int | 461 | static int |
529 | nouveau_drm_load(struct drm_device *dev, unsigned long flags) | 462 | nouveau_drm_device_init(struct drm_device *dev) |
530 | { | 463 | { |
531 | struct nouveau_drm *drm; | 464 | struct nouveau_drm *drm; |
532 | int ret; | 465 | int ret; |
@@ -613,7 +546,7 @@ fail_alloc: | |||
613 | } | 546 | } |
614 | 547 | ||
615 | static void | 548 | static void |
616 | nouveau_drm_unload(struct drm_device *dev) | 549 | nouveau_drm_device_fini(struct drm_device *dev) |
617 | { | 550 | { |
618 | struct nouveau_drm *drm = nouveau_drm(dev); | 551 | struct nouveau_drm *drm = nouveau_drm(dev); |
619 | 552 | ||
@@ -642,18 +575,116 @@ nouveau_drm_unload(struct drm_device *dev) | |||
642 | kfree(drm); | 575 | kfree(drm); |
643 | } | 576 | } |
644 | 577 | ||
578 | static int nouveau_drm_probe(struct pci_dev *pdev, | ||
579 | const struct pci_device_id *pent) | ||
580 | { | ||
581 | struct nvkm_device *device; | ||
582 | struct drm_device *drm_dev; | ||
583 | struct apertures_struct *aper; | ||
584 | bool boot = false; | ||
585 | int ret; | ||
586 | |||
587 | if (vga_switcheroo_client_probe_defer(pdev)) | ||
588 | return -EPROBE_DEFER; | ||
589 | |||
590 | /* We need to check that the chipset is supported before booting | ||
591 | * fbdev off the hardware, as there's no way to put it back. | ||
592 | */ | ||
593 | ret = nvkm_device_pci_new(pdev, NULL, "error", true, false, 0, &device); | ||
594 | if (ret) | ||
595 | return ret; | ||
596 | |||
597 | nvkm_device_del(&device); | ||
598 | |||
599 | /* Remove conflicting drivers (vesafb, efifb etc). */ | ||
600 | aper = alloc_apertures(3); | ||
601 | if (!aper) | ||
602 | return -ENOMEM; | ||
603 | |||
604 | aper->ranges[0].base = pci_resource_start(pdev, 1); | ||
605 | aper->ranges[0].size = pci_resource_len(pdev, 1); | ||
606 | aper->count = 1; | ||
607 | |||
608 | if (pci_resource_len(pdev, 2)) { | ||
609 | aper->ranges[aper->count].base = pci_resource_start(pdev, 2); | ||
610 | aper->ranges[aper->count].size = pci_resource_len(pdev, 2); | ||
611 | aper->count++; | ||
612 | } | ||
613 | |||
614 | if (pci_resource_len(pdev, 3)) { | ||
615 | aper->ranges[aper->count].base = pci_resource_start(pdev, 3); | ||
616 | aper->ranges[aper->count].size = pci_resource_len(pdev, 3); | ||
617 | aper->count++; | ||
618 | } | ||
619 | |||
620 | #ifdef CONFIG_X86 | ||
621 | boot = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW; | ||
622 | #endif | ||
623 | if (nouveau_modeset != 2) | ||
624 | drm_fb_helper_remove_conflicting_framebuffers(aper, "nouveaufb", boot); | ||
625 | kfree(aper); | ||
626 | |||
627 | ret = nvkm_device_pci_new(pdev, nouveau_config, nouveau_debug, | ||
628 | true, true, ~0ULL, &device); | ||
629 | if (ret) | ||
630 | return ret; | ||
631 | |||
632 | pci_set_master(pdev); | ||
633 | |||
634 | if (nouveau_atomic) | ||
635 | driver_pci.driver_features |= DRIVER_ATOMIC; | ||
636 | |||
637 | drm_dev = drm_dev_alloc(&driver_pci, &pdev->dev); | ||
638 | if (IS_ERR(drm_dev)) { | ||
639 | ret = PTR_ERR(drm_dev); | ||
640 | goto fail_nvkm; | ||
641 | } | ||
642 | |||
643 | ret = pci_enable_device(pdev); | ||
644 | if (ret) | ||
645 | goto fail_drm; | ||
646 | |||
647 | drm_dev->pdev = pdev; | ||
648 | pci_set_drvdata(pdev, drm_dev); | ||
649 | |||
650 | ret = nouveau_drm_device_init(drm_dev); | ||
651 | if (ret) | ||
652 | goto fail_pci; | ||
653 | |||
654 | ret = drm_dev_register(drm_dev, pent->driver_data); | ||
655 | if (ret) | ||
656 | goto fail_drm_dev_init; | ||
657 | |||
658 | return 0; | ||
659 | |||
660 | fail_drm_dev_init: | ||
661 | nouveau_drm_device_fini(drm_dev); | ||
662 | fail_pci: | ||
663 | pci_disable_device(pdev); | ||
664 | fail_drm: | ||
665 | drm_dev_put(drm_dev); | ||
666 | fail_nvkm: | ||
667 | nvkm_device_del(&device); | ||
668 | return ret; | ||
669 | } | ||
670 | |||
645 | void | 671 | void |
646 | nouveau_drm_device_remove(struct drm_device *dev) | 672 | nouveau_drm_device_remove(struct drm_device *dev) |
647 | { | 673 | { |
674 | struct pci_dev *pdev = dev->pdev; | ||
648 | struct nouveau_drm *drm = nouveau_drm(dev); | 675 | struct nouveau_drm *drm = nouveau_drm(dev); |
649 | struct nvkm_client *client; | 676 | struct nvkm_client *client; |
650 | struct nvkm_device *device; | 677 | struct nvkm_device *device; |
651 | 678 | ||
679 | drm_dev_unregister(dev); | ||
680 | |||
652 | dev->irq_enabled = false; | 681 | dev->irq_enabled = false; |
653 | client = nvxx_client(&drm->client.base); | 682 | client = nvxx_client(&drm->client.base); |
654 | device = nvkm_device_find(client->device); | 683 | device = nvkm_device_find(client->device); |
655 | drm_put_dev(dev); | ||
656 | 684 | ||
685 | nouveau_drm_device_fini(dev); | ||
686 | pci_disable_device(pdev); | ||
687 | drm_dev_put(dev); | ||
657 | nvkm_device_del(&device); | 688 | nvkm_device_del(&device); |
658 | } | 689 | } |
659 | 690 | ||
@@ -1020,8 +1051,6 @@ driver_stub = { | |||
1020 | DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_RENDER | | 1051 | DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_RENDER | |
1021 | DRIVER_KMS_LEGACY_CONTEXT, | 1052 | DRIVER_KMS_LEGACY_CONTEXT, |
1022 | 1053 | ||
1023 | .load = nouveau_drm_load, | ||
1024 | .unload = nouveau_drm_unload, | ||
1025 | .open = nouveau_drm_open, | 1054 | .open = nouveau_drm_open, |
1026 | .postclose = nouveau_drm_postclose, | 1055 | .postclose = nouveau_drm_postclose, |
1027 | .lastclose = nouveau_vga_lastclose, | 1056 | .lastclose = nouveau_vga_lastclose, |