From 97c6a10928cc463825479911c3a6518ade34ebc0 Mon Sep 17 00:00:00 2001 From: Nitin Kumbhar Date: Wed, 4 Jul 2018 22:59:36 +0530 Subject: gpu: nvgpu: add pm_rumtime fixes Runtime PM is enabled only for iGPU and not for dGPU. For dGPU, the .probe() of driver pm_runtime_disable()s, if rail-gating is not enabled. With nvgpu kernel module load/unload, .probe() is called multiple times for same struct device *. This results in an overflow of disable_depth (3 bit refcount) and enables runtime PM on 8th iteration and calls RTPM routines even if it's disabled. To effectively manage pm_runtime_disable(), move it from common nvgpu_remove() to iGPU/dGPU specific routines. Also, add restore pm_runtime state of device on driver .remove(). Bug 1987855 Change-Id: I781278da546ef9c9ef7d7da7dbea0757df32716f Signed-off-by: Nitin Kumbhar Reviewed-on: https://git-master.nvidia.com/r/1770804 Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/gpu/nvgpu/os/linux/module.c | 13 ++++++++++--- drivers/gpu/nvgpu/os/linux/pci.c | 39 ++++++++++++++++++++++++++++++++----- 2 files changed, 44 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/nvgpu/os/linux/module.c b/drivers/gpu/nvgpu/os/linux/module.c index a59ac1f1..e3667947 100644 --- a/drivers/gpu/nvgpu/os/linux/module.c +++ b/drivers/gpu/nvgpu/os/linux/module.c @@ -1060,6 +1060,13 @@ static int gk20a_pm_init(struct device *dev) return err; } +static int gk20a_pm_deinit(struct device *dev) +{ + pm_runtime_dont_use_autosuspend(dev); + pm_runtime_disable(dev); + return 0; +} + /* * Start the process for unloading the driver. Set NVGPU_DRIVER_IS_DYING. */ @@ -1309,9 +1316,6 @@ int nvgpu_remove(struct device *dev, struct class *class) platform->secure_buffer.destroy(g, &platform->secure_buffer); - if (pm_runtime_enabled(dev)) - pm_runtime_disable(dev); - if (platform->remove) platform->remove(dev); @@ -1332,8 +1336,11 @@ static int __exit gk20a_remove(struct platform_device *pdev) err = nvgpu_remove(dev, &nvgpu_class); set_gk20a(pdev, NULL); + gk20a_put(g); + gk20a_pm_deinit(dev); + return err; } diff --git a/drivers/gpu/nvgpu/os/linux/pci.c b/drivers/gpu/nvgpu/os/linux/pci.c index dba8a5df..3493b105 100644 --- a/drivers/gpu/nvgpu/os/linux/pci.c +++ b/drivers/gpu/nvgpu/os/linux/pci.c @@ -590,11 +590,21 @@ static int nvgpu_pci_pm_runtime_suspend(struct device *dev) return 0; } +static int nvgpu_pci_pm_resume(struct device *dev) +{ + return gk20a_pm_finalize_poweron(dev); +} + +static int nvgpu_pci_pm_suspend(struct device *dev) +{ + return 0; +} + static const struct dev_pm_ops nvgpu_pci_pm_ops = { .runtime_resume = nvgpu_pci_pm_runtime_resume, .runtime_suspend = nvgpu_pci_pm_runtime_suspend, - .resume = nvgpu_pci_pm_runtime_resume, - .suspend = nvgpu_pci_pm_runtime_suspend, + .resume = nvgpu_pci_pm_resume, + .suspend = nvgpu_pci_pm_suspend, }; #endif @@ -611,10 +621,15 @@ static int nvgpu_pci_pm_init(struct device *dev) g->railgate_delay); /* - * Runtime PM for PCI devices is disabled by default, - * so we need to enable it first + * set gpu dev's use_autosuspend flag to allow + * runtime power management of GPU */ pm_runtime_use_autosuspend(dev); + + /* + * runtime PM for PCI devices is forbidden + * by default, so unblock RTPM of GPU + */ pm_runtime_put_noidle(dev); pm_runtime_allow(dev); } @@ -622,6 +637,19 @@ static int nvgpu_pci_pm_init(struct device *dev) return 0; } +static int nvgpu_pci_pm_deinit(struct device *dev) +{ +#ifdef CONFIG_PM + struct gk20a *g = get_gk20a(dev); + + if (!nvgpu_is_enabled(g, NVGPU_CAN_RAILGATE)) + pm_runtime_enable(dev); + else + pm_runtime_forbid(dev); +#endif + return 0; +} + static int nvgpu_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pent) { @@ -826,11 +854,12 @@ static void nvgpu_pci_remove(struct pci_dev *pdev) enable_irq(g->irq_stall); } #endif + nvgpu_pci_pm_deinit(&pdev->dev); /* free allocated platform data space */ + gk20a_get_platform(&pdev->dev)->g = NULL; nvgpu_kfree(g, gk20a_get_platform(&pdev->dev)); - gk20a_get_platform(&pdev->dev)->g = NULL; gk20a_put(g); } -- cgit v1.2.2