diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c index 2ab367a18..8d4bc6691 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a.c @@ -1379,31 +1379,61 @@ static int gk20a_pm_unrailgate(struct device *dev) static void gk20a_pm_shutdown(struct platform_device *pdev) { struct gk20a_platform *platform = platform_get_drvdata(pdev); + struct gk20a *g = platform->g; + int err; + + if (gk20a_gpu_is_virtual(&pdev->dev)) { + dev_info(&pdev->dev, "skip shutdown for vgpu"); + return; + } dev_info(&pdev->dev, "shutting down"); - gk20a_driver_start_unload(platform->g); + gk20a_driver_start_unload(g); /* If GPU is already railgated, * just prevent more requests, and return */ if (platform->is_railgated && platform->is_railgated(&pdev->dev)) { __pm_runtime_disable(&pdev->dev, false); + dev_info(&pdev->dev, "already railgated, shut down complete"); return; } /* Prevent more requests by disabling Runtime PM */ __pm_runtime_disable(&pdev->dev, false); - gk20a_wait_for_idle(&pdev->dev); + err = gk20a_wait_for_idle(&pdev->dev); + if (err) { + dev_err(&pdev->dev, "failed to idle GPU, err=%d", err); + goto finish; + } - /* Be ready for rail-gate after this point */ - if (gk20a_gpu_is_virtual(&pdev->dev)) - vgpu_pm_prepare_poweroff(&pdev->dev); - else - gk20a_pm_prepare_poweroff(&pdev->dev); + err = gk20a_fifo_disable_all_engine_activity(g, true); + if (err) { + dev_err(&pdev->dev, "failed to disable engine activity, err=%d", + err); + goto finish; + } - gk20a_pm_railgate(&pdev->dev); + err = gk20a_fifo_wait_engine_idle(g); + if (err) { + dev_err(&pdev->dev, "failed to idle engines, err=%d", + err); + goto finish; + } + err = gk20a_pm_prepare_poweroff(&pdev->dev); + if (err) { + dev_err(&pdev->dev, "failed to prepare for poweroff, err=%d", + err); + goto finish; + } + + err = gk20a_pm_railgate(&pdev->dev); + if (err) + dev_err(&pdev->dev, "failed to railgate, err=%d", err); + +finish: dev_info(&pdev->dev, "shut down complete\n"); }