diff options
author | Deepak Nibade <dnibade@nvidia.com> | 2016-06-07 03:50:05 -0400 |
---|---|---|
committer | Terje Bergstrom <tbergstrom@nvidia.com> | 2016-06-08 14:22:59 -0400 |
commit | 2219f38727ffa17291e15c1898bd3e65f43d09fd (patch) | |
tree | be00266779b0632a5727c2d58f2b297c6cc4ebfd /drivers/gpu/nvgpu/gk20a/gk20a.c | |
parent | 6299b00beb9dabdd53c211b02658d022827b3232 (diff) |
gpu: nvgpu: take power refcount in ISR
We sometimes see race conditions where power refcount
is zero during ISR or bottom half.
If bottom half calls gk20a_busy(), it will lead to
boot up of GPU, but it is also possible that we are
already trying to poweroff GPU since power refcount
is zero
Fix this by taking a power refcount with gk20a_busy_noresume()
in ISR and then dropping this refcount at the end of
bottom half
Add new API gk20a_idle_nosuspend() to drop a refcount
without initiating suspend
Bug 200198908
Bug 1770522
Change-Id: Iec3d4dc8d468f49b71919d2bbc327da48b97bcab
Signed-off-by: Deepak Nibade <dnibade@nvidia.com>
Reviewed-on: http://git-master/r/1160035
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Tested-by: Terje Bergstrom <tbergstrom@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/gk20a.c')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.c | 41 |
1 files changed, 37 insertions, 4 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c index d21d0527..714b494f 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a.c | |||
@@ -545,15 +545,29 @@ int gk20a_sim_esc_read(struct gk20a *g, char *path, u32 index, u32 count, u32 *d | |||
545 | static irqreturn_t gk20a_intr_isr_stall(int irq, void *dev_id) | 545 | static irqreturn_t gk20a_intr_isr_stall(int irq, void *dev_id) |
546 | { | 546 | { |
547 | struct gk20a *g = dev_id; | 547 | struct gk20a *g = dev_id; |
548 | irqreturn_t ret; | ||
548 | 549 | ||
549 | return g->ops.mc.isr_stall(g); | 550 | ret = g->ops.mc.isr_stall(g); |
551 | if (ret == IRQ_WAKE_THREAD) { | ||
552 | /* balanced in gk20a_intr_thread_stall() */ | ||
553 | gk20a_busy_noresume(g->dev); | ||
554 | } | ||
555 | |||
556 | return ret; | ||
550 | } | 557 | } |
551 | 558 | ||
552 | static irqreturn_t gk20a_intr_isr_nonstall(int irq, void *dev_id) | 559 | static irqreturn_t gk20a_intr_isr_nonstall(int irq, void *dev_id) |
553 | { | 560 | { |
554 | struct gk20a *g = dev_id; | 561 | struct gk20a *g = dev_id; |
562 | irqreturn_t ret; | ||
563 | |||
564 | ret = g->ops.mc.isr_nonstall(g); | ||
565 | if (ret == IRQ_WAKE_THREAD) { | ||
566 | /* balanced in gk20a_intr_thread_nonstall() */ | ||
567 | gk20a_busy_noresume(g->dev); | ||
568 | } | ||
555 | 569 | ||
556 | return g->ops.mc.isr_nonstall(g); | 570 | return ret; |
557 | } | 571 | } |
558 | 572 | ||
559 | void gk20a_pbus_isr(struct gk20a *g) | 573 | void gk20a_pbus_isr(struct gk20a *g) |
@@ -593,13 +607,27 @@ void gk20a_pbus_isr(struct gk20a *g) | |||
593 | static irqreturn_t gk20a_intr_thread_stall(int irq, void *dev_id) | 607 | static irqreturn_t gk20a_intr_thread_stall(int irq, void *dev_id) |
594 | { | 608 | { |
595 | struct gk20a *g = dev_id; | 609 | struct gk20a *g = dev_id; |
596 | return g->ops.mc.isr_thread_stall(g); | 610 | irqreturn_t ret; |
611 | |||
612 | ret = g->ops.mc.isr_thread_stall(g); | ||
613 | |||
614 | /* refcount taken in gk20a_intr_isr_stall() */ | ||
615 | gk20a_idle_nosuspend(g->dev); | ||
616 | |||
617 | return ret; | ||
597 | } | 618 | } |
598 | 619 | ||
599 | static irqreturn_t gk20a_intr_thread_nonstall(int irq, void *dev_id) | 620 | static irqreturn_t gk20a_intr_thread_nonstall(int irq, void *dev_id) |
600 | { | 621 | { |
601 | struct gk20a *g = dev_id; | 622 | struct gk20a *g = dev_id; |
602 | return g->ops.mc.isr_thread_nonstall(g); | 623 | irqreturn_t ret; |
624 | |||
625 | ret = g->ops.mc.isr_thread_nonstall(g); | ||
626 | |||
627 | /* refcount taken in gk20a_intr_isr_nonstall() */ | ||
628 | gk20a_idle_nosuspend(g->dev); | ||
629 | |||
630 | return ret; | ||
603 | } | 631 | } |
604 | 632 | ||
605 | void gk20a_remove_support(struct device *dev) | 633 | void gk20a_remove_support(struct device *dev) |
@@ -1842,6 +1870,11 @@ fail: | |||
1842 | return ret < 0 ? ret : 0; | 1870 | return ret < 0 ? ret : 0; |
1843 | } | 1871 | } |
1844 | 1872 | ||
1873 | void gk20a_idle_nosuspend(struct device *dev) | ||
1874 | { | ||
1875 | pm_runtime_put_noidle(dev); | ||
1876 | } | ||
1877 | |||
1845 | void gk20a_idle(struct device *dev) | 1878 | void gk20a_idle(struct device *dev) |
1846 | { | 1879 | { |
1847 | #ifdef CONFIG_PM | 1880 | #ifdef CONFIG_PM |