From 4feb078717fe7986bc0dfdfbfc3f10e5d1d1fa63 Mon Sep 17 00:00:00 2001 From: Alex Waterman Date: Tue, 10 Jan 2017 16:26:56 -0800 Subject: gpu: nvgpu: Make driver rebind work Make the GPU bind and rebind operations work when the driver is idle. This required two changes. 1. Reset the GPU before doing SW init for PCI GPUs. This clears the SW state which may be stale in the case of a rebind attempt. 2. Cleanup the interrupt enable/disables. Firstly there was one place where nvgpu would accidentally disable the stalling interrupt twice when the stalling interrupt and non-stalling interrupt are the same. Secondly make sure when exiting nvgpu that the interrupt enable/disables are balanced. Leaving the interrupt in the -1 disable state means that next time the driver runs interrupts never quite get enabled. Bug 1816516 Signed-off-by: Alex Waterman Reviewed-on: http://git-master/r/1287643 Reviewed-on: http://git-master/r/1287649 (cherry picked from commit aa15af0aae5d0a95a8e765469be4354ab7ddd9f8) Change-Id: I945e21c1fbb3f096834acf850616b71b2aab9ee3 Reviewed-on: http://git-master/r/1292700 Reviewed-by: svccoveritychecker GVS: Gerrit_Virtual_Submit Reviewed-by: Terje Bergstrom --- drivers/gpu/nvgpu/gk20a/gk20a.c | 12 +++++++++++- drivers/gpu/nvgpu/gk20a/gk20a.h | 1 + drivers/gpu/nvgpu/pci.c | 2 ++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c index 069dfc95..44786e4b 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a.c @@ -822,7 +822,8 @@ static int gk20a_pm_prepare_poweroff(struct device *dev) * serviced. */ disable_irq(g->irq_stall); - disable_irq(g->irq_nonstall); + if (g->irq_stall != g->irq_nonstall) + disable_irq(g->irq_nonstall); ret |= gk20a_gr_suspend(g); ret |= gk20a_mm_suspend(g); @@ -907,6 +908,15 @@ int gk20a_pm_finalize_poweron(struct device *dev) if (err) goto done; + /* + * Before probing the GPU make sure the GPU's state is cleared. This is + * relevant for rebind operations. + */ + if (g->ops.xve.reset_gpu && !g->gpu_reset_done) { + g->ops.xve.reset_gpu(g); + g->gpu_reset_done = true; + } + if (g->ops.bios.init) err = g->ops.bios.init(g); if (err) diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index 30a3252a..ff354bc8 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h @@ -832,6 +832,7 @@ struct gk20a { void __iomem *bar1; void __iomem *bar1_saved; + bool gpu_reset_done; bool power_on; bool suspended; diff --git a/drivers/gpu/nvgpu/pci.c b/drivers/gpu/nvgpu/pci.c index ed681c75..88b743bc 100644 --- a/drivers/gpu/nvgpu/pci.c +++ b/drivers/gpu/nvgpu/pci.c @@ -400,6 +400,8 @@ static void nvgpu_pci_remove(struct pci_dev *pdev) platform->remove(g->dev); gk20a_dbg(gpu_dbg_shutdown, "Platform remove done.\b"); + enable_irq(g->irq_stall); + kfree(g); } -- cgit v1.2.2