diff options
author | Nitin Kumbhar <nkumbhar@nvidia.com> | 2018-05-25 07:09:07 -0400 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2018-07-06 16:24:45 -0400 |
commit | 4b889fb8b02e7b65eb7054463c0c1bda37688762 (patch) | |
tree | 02d94028beac3f39ba204ad1857a1fc2e7f177fc /drivers/gpu/nvgpu/os | |
parent | c8347c83697b75823f6e5141b06b8e4669061b99 (diff) |
gpu: nvgpu: use devm variants to ioremap
While removing nvgpu driver, devm mapped reg mappings
are released on driver_unregister. For iGPU, these
regs are explicitly unmapped with iounmap(). This
results in "Trying to vfree() nonexistent vm area"
warnings on driver removal.
Address this by using devm* variants to map all IO regions
of both iGPU and dGPU and let the driver unregister
release these mappings.
Also, lock out GPU regs in driver removal path.
Bug 1987855
Change-Id: I0388daf90bea3eaf8752255059cfd3ceabf66e7d
Signed-off-by: Nitin Kumbhar <nkumbhar@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1730539
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/os')
-rw-r--r-- | drivers/gpu/nvgpu/os/linux/module.c | 50 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/os/linux/module.h | 4 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/os/linux/pci.c | 18 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/os/linux/sim.c | 6 |
4 files changed, 38 insertions, 40 deletions
diff --git a/drivers/gpu/nvgpu/os/linux/module.c b/drivers/gpu/nvgpu/os/linux/module.c index 2df8ab42..28ade90f 100644 --- a/drivers/gpu/nvgpu/os/linux/module.c +++ b/drivers/gpu/nvgpu/os/linux/module.c | |||
@@ -606,8 +606,8 @@ static int gk20a_do_unidle(void *_g) | |||
606 | } | 606 | } |
607 | #endif | 607 | #endif |
608 | 608 | ||
609 | void __iomem *nvgpu_ioremap_resource(struct platform_device *dev, int i, | 609 | void __iomem *nvgpu_devm_ioremap_resource(struct platform_device *dev, int i, |
610 | struct resource **out) | 610 | struct resource **out) |
611 | { | 611 | { |
612 | struct resource *r = platform_get_resource(dev, IORESOURCE_MEM, i); | 612 | struct resource *r = platform_get_resource(dev, IORESOURCE_MEM, i); |
613 | 613 | ||
@@ -618,6 +618,12 @@ void __iomem *nvgpu_ioremap_resource(struct platform_device *dev, int i, | |||
618 | return devm_ioremap_resource(&dev->dev, r); | 618 | return devm_ioremap_resource(&dev->dev, r); |
619 | } | 619 | } |
620 | 620 | ||
621 | void __iomem *nvgpu_devm_ioremap(struct device *dev, resource_size_t offset, | ||
622 | resource_size_t size) | ||
623 | { | ||
624 | return devm_ioremap(dev, offset, size); | ||
625 | } | ||
626 | |||
621 | static irqreturn_t gk20a_intr_isr_stall(int irq, void *dev_id) | 627 | static irqreturn_t gk20a_intr_isr_stall(int irq, void *dev_id) |
622 | { | 628 | { |
623 | struct gk20a *g = dev_id; | 629 | struct gk20a *g = dev_id; |
@@ -673,46 +679,41 @@ void gk20a_remove_support(struct gk20a *g) | |||
673 | sim_linux->remove_support_linux(g); | 679 | sim_linux->remove_support_linux(g); |
674 | } | 680 | } |
675 | 681 | ||
676 | /* free mappings to registers, etc */ | ||
677 | if (l->regs) { | ||
678 | iounmap(l->regs); | ||
679 | l->regs = NULL; | ||
680 | } | ||
681 | if (l->bar1) { | ||
682 | iounmap(l->bar1); | ||
683 | l->bar1 = NULL; | ||
684 | } | ||
685 | |||
686 | nvgpu_remove_usermode_support(g); | 682 | nvgpu_remove_usermode_support(g); |
687 | 683 | ||
688 | nvgpu_free_enabled_flags(g); | 684 | nvgpu_free_enabled_flags(g); |
685 | |||
686 | gk20a_lockout_registers(g); | ||
689 | } | 687 | } |
690 | 688 | ||
691 | static int gk20a_init_support(struct platform_device *dev) | 689 | static int gk20a_init_support(struct platform_device *pdev) |
692 | { | 690 | { |
693 | int err = -ENOMEM; | 691 | struct device *dev = &pdev->dev; |
694 | struct gk20a *g = get_gk20a(&dev->dev); | 692 | struct gk20a *g = get_gk20a(dev); |
695 | struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); | 693 | struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); |
694 | int err = -ENOMEM; | ||
696 | 695 | ||
697 | tegra_register_idle_unidle(gk20a_do_idle, gk20a_do_unidle, g); | 696 | tegra_register_idle_unidle(gk20a_do_idle, gk20a_do_unidle, g); |
698 | 697 | ||
699 | l->regs = nvgpu_ioremap_resource(dev, GK20A_BAR0_IORESOURCE_MEM, | 698 | l->regs = nvgpu_devm_ioremap_resource(pdev, |
700 | &l->reg_mem); | 699 | GK20A_BAR0_IORESOURCE_MEM, |
700 | &l->reg_mem); | ||
701 | if (IS_ERR(l->regs)) { | 701 | if (IS_ERR(l->regs)) { |
702 | nvgpu_err(g, "failed to remap gk20a registers"); | 702 | nvgpu_err(g, "failed to remap gk20a registers"); |
703 | err = PTR_ERR(l->regs); | 703 | err = PTR_ERR(l->regs); |
704 | goto fail; | 704 | goto fail; |
705 | } | 705 | } |
706 | 706 | ||
707 | l->bar1 = nvgpu_ioremap_resource(dev, GK20A_BAR1_IORESOURCE_MEM, | 707 | l->bar1 = nvgpu_devm_ioremap_resource(pdev, |
708 | &l->bar1_mem); | 708 | GK20A_BAR1_IORESOURCE_MEM, |
709 | &l->bar1_mem); | ||
709 | if (IS_ERR(l->bar1)) { | 710 | if (IS_ERR(l->bar1)) { |
710 | nvgpu_err(g, "failed to remap gk20a bar1"); | 711 | nvgpu_err(g, "failed to remap gk20a bar1"); |
711 | err = PTR_ERR(l->bar1); | 712 | err = PTR_ERR(l->bar1); |
712 | goto fail; | 713 | goto fail; |
713 | } | 714 | } |
714 | 715 | ||
715 | err = nvgpu_init_sim_support_linux(g, dev); | 716 | err = nvgpu_init_sim_support_linux(g, pdev); |
716 | if (err) | 717 | if (err) |
717 | goto fail; | 718 | goto fail; |
718 | err = nvgpu_init_sim_support(g); | 719 | err = nvgpu_init_sim_support(g); |
@@ -725,14 +726,11 @@ static int gk20a_init_support(struct platform_device *dev) | |||
725 | fail_sim: | 726 | fail_sim: |
726 | nvgpu_remove_sim_support_linux(g); | 727 | nvgpu_remove_sim_support_linux(g); |
727 | fail: | 728 | fail: |
728 | if (l->regs) { | 729 | if (l->regs) |
729 | iounmap(l->regs); | ||
730 | l->regs = NULL; | 730 | l->regs = NULL; |
731 | } | 731 | |
732 | if (l->bar1) { | 732 | if (l->bar1) |
733 | iounmap(l->bar1); | ||
734 | l->bar1 = NULL; | 733 | l->bar1 = NULL; |
735 | } | ||
736 | 734 | ||
737 | return err; | 735 | return err; |
738 | } | 736 | } |
diff --git a/drivers/gpu/nvgpu/os/linux/module.h b/drivers/gpu/nvgpu/os/linux/module.h index ab4bca03..da61425d 100644 --- a/drivers/gpu/nvgpu/os/linux/module.h +++ b/drivers/gpu/nvgpu/os/linux/module.h | |||
@@ -25,8 +25,10 @@ int nvgpu_quiesce(struct gk20a *g); | |||
25 | int nvgpu_remove(struct device *dev, struct class *class); | 25 | int nvgpu_remove(struct device *dev, struct class *class); |
26 | void nvgpu_free_irq(struct gk20a *g); | 26 | void nvgpu_free_irq(struct gk20a *g); |
27 | struct device_node *nvgpu_get_node(struct gk20a *g); | 27 | struct device_node *nvgpu_get_node(struct gk20a *g); |
28 | void __iomem *nvgpu_ioremap_resource(struct platform_device *dev, int i, | 28 | void __iomem *nvgpu_devm_ioremap_resource(struct platform_device *dev, int i, |
29 | struct resource **out); | 29 | struct resource **out); |
30 | void __iomem *nvgpu_devm_ioremap(struct device *dev, resource_size_t offset, | ||
31 | resource_size_t size); | ||
30 | extern struct class nvgpu_class; | 32 | extern struct class nvgpu_class; |
31 | 33 | ||
32 | #endif | 34 | #endif |
diff --git a/drivers/gpu/nvgpu/os/linux/pci.c b/drivers/gpu/nvgpu/os/linux/pci.c index f62dacab..dba8a5df 100644 --- a/drivers/gpu/nvgpu/os/linux/pci.c +++ b/drivers/gpu/nvgpu/os/linux/pci.c | |||
@@ -525,17 +525,18 @@ static int nvgpu_pci_init_support(struct pci_dev *pdev) | |||
525 | int err = 0; | 525 | int err = 0; |
526 | struct gk20a *g = get_gk20a(&pdev->dev); | 526 | struct gk20a *g = get_gk20a(&pdev->dev); |
527 | struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); | 527 | struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); |
528 | struct device *dev = &pdev->dev; | ||
528 | 529 | ||
529 | l->regs = ioremap(pci_resource_start(pdev, 0), | 530 | l->regs = nvgpu_devm_ioremap(dev, pci_resource_start(pdev, 0), |
530 | pci_resource_len(pdev, 0)); | 531 | pci_resource_len(pdev, 0)); |
531 | if (IS_ERR(l->regs)) { | 532 | if (IS_ERR(l->regs)) { |
532 | nvgpu_err(g, "failed to remap gk20a registers"); | 533 | nvgpu_err(g, "failed to remap gk20a registers"); |
533 | err = PTR_ERR(l->regs); | 534 | err = PTR_ERR(l->regs); |
534 | goto fail; | 535 | goto fail; |
535 | } | 536 | } |
536 | 537 | ||
537 | l->bar1 = ioremap(pci_resource_start(pdev, 1), | 538 | l->bar1 = nvgpu_devm_ioremap(dev, pci_resource_start(pdev, 1), |
538 | pci_resource_len(pdev, 1)); | 539 | pci_resource_len(pdev, 1)); |
539 | if (IS_ERR(l->bar1)) { | 540 | if (IS_ERR(l->bar1)) { |
540 | nvgpu_err(g, "failed to remap gk20a bar1"); | 541 | nvgpu_err(g, "failed to remap gk20a bar1"); |
541 | err = PTR_ERR(l->bar1); | 542 | err = PTR_ERR(l->bar1); |
@@ -556,14 +557,11 @@ static int nvgpu_pci_init_support(struct pci_dev *pdev) | |||
556 | fail_sim: | 557 | fail_sim: |
557 | nvgpu_remove_sim_support_linux_pci(g); | 558 | nvgpu_remove_sim_support_linux_pci(g); |
558 | fail: | 559 | fail: |
559 | if (l->regs) { | 560 | if (l->regs) |
560 | iounmap(l->regs); | ||
561 | l->regs = NULL; | 561 | l->regs = NULL; |
562 | } | 562 | |
563 | if (l->bar1) { | 563 | if (l->bar1) |
564 | iounmap(l->bar1); | ||
565 | l->bar1 = NULL; | 564 | l->bar1 = NULL; |
566 | } | ||
567 | 565 | ||
568 | return err; | 566 | return err; |
569 | } | 567 | } |
diff --git a/drivers/gpu/nvgpu/os/linux/sim.c b/drivers/gpu/nvgpu/os/linux/sim.c index 8e964f39..abef45c7 100644 --- a/drivers/gpu/nvgpu/os/linux/sim.c +++ b/drivers/gpu/nvgpu/os/linux/sim.c | |||
@@ -78,9 +78,9 @@ int nvgpu_init_sim_support_linux(struct gk20a *g, | |||
78 | return err; | 78 | return err; |
79 | g->sim = &sim_linux->sim; | 79 | g->sim = &sim_linux->sim; |
80 | g->sim->g = g; | 80 | g->sim->g = g; |
81 | sim_linux->regs = nvgpu_ioremap_resource(dev, | 81 | sim_linux->regs = nvgpu_devm_ioremap_resource(dev, |
82 | GK20A_SIM_IORESOURCE_MEM, | 82 | GK20A_SIM_IORESOURCE_MEM, |
83 | &sim_linux->reg_mem); | 83 | &sim_linux->reg_mem); |
84 | if (IS_ERR(sim_linux->regs)) { | 84 | if (IS_ERR(sim_linux->regs)) { |
85 | nvgpu_err(g, "failed to remap gk20a sim regs"); | 85 | nvgpu_err(g, "failed to remap gk20a sim regs"); |
86 | err = PTR_ERR(sim_linux->regs); | 86 | err = PTR_ERR(sim_linux->regs); |