diff options
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/nvgpu/Makefile.nvgpu | 1 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/driver_common.c | 4 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/io.c | 110 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/module.c | 77 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/module.h | 4 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/nvgpu_mem.c | 13 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/os_linux.h | 14 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/pci.c | 13 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/common/pramin.c | 2 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.c | 26 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.h | 81 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gr_gk20a.c | 3 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/include/nvgpu/io.h | 49 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/vgpu/fifo_vgpu.c | 3 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/vgpu/vgpu.c | 18 |
15 files changed, 274 insertions, 144 deletions
diff --git a/drivers/gpu/nvgpu/Makefile.nvgpu b/drivers/gpu/nvgpu/Makefile.nvgpu index a792ab33..fa774566 100644 --- a/drivers/gpu/nvgpu/Makefile.nvgpu +++ b/drivers/gpu/nvgpu/Makefile.nvgpu | |||
@@ -46,6 +46,7 @@ nvgpu-y := \ | |||
46 | common/linux/intr.o \ | 46 | common/linux/intr.o \ |
47 | common/linux/sysfs.o \ | 47 | common/linux/sysfs.o \ |
48 | common/linux/cde.o \ | 48 | common/linux/cde.o \ |
49 | common/linux/io.o \ | ||
49 | common/mm/nvgpu_allocator.o \ | 50 | common/mm/nvgpu_allocator.o \ |
50 | common/mm/bitmap_allocator.o \ | 51 | common/mm/bitmap_allocator.o \ |
51 | common/mm/buddy_allocator.o \ | 52 | common/mm/buddy_allocator.o \ |
diff --git a/drivers/gpu/nvgpu/common/linux/driver_common.c b/drivers/gpu/nvgpu/common/linux/driver_common.c index 7c4645a8..734bc1d2 100644 --- a/drivers/gpu/nvgpu/common/linux/driver_common.c +++ b/drivers/gpu/nvgpu/common/linux/driver_common.c | |||
@@ -54,8 +54,8 @@ static void nvgpu_init_vars(struct gk20a *g) | |||
54 | nvgpu_mutex_init(&g->poweron_lock); | 54 | nvgpu_mutex_init(&g->poweron_lock); |
55 | nvgpu_mutex_init(&g->poweroff_lock); | 55 | nvgpu_mutex_init(&g->poweroff_lock); |
56 | 56 | ||
57 | g->regs_saved = g->regs; | 57 | l->regs_saved = l->regs; |
58 | g->bar1_saved = g->bar1; | 58 | l->bar1_saved = l->bar1; |
59 | 59 | ||
60 | g->emc3d_ratio = EMC3D_DEFAULT_RATIO; | 60 | g->emc3d_ratio = EMC3D_DEFAULT_RATIO; |
61 | 61 | ||
diff --git a/drivers/gpu/nvgpu/common/linux/io.c b/drivers/gpu/nvgpu/common/linux/io.c new file mode 100644 index 00000000..04a9fbe8 --- /dev/null +++ b/drivers/gpu/nvgpu/common/linux/io.c | |||
@@ -0,0 +1,110 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms and conditions of the GNU General Public License, | ||
6 | * version 2, as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
11 | * more details. | ||
12 | */ | ||
13 | |||
14 | #include <nvgpu/io.h> | ||
15 | #include <nvgpu/types.h> | ||
16 | |||
17 | #include "os_linux.h" | ||
18 | #include "gk20a/gk20a.h" | ||
19 | |||
20 | void nvgpu_writel(struct gk20a *g, u32 r, u32 v) | ||
21 | { | ||
22 | struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); | ||
23 | |||
24 | if (unlikely(!l->regs)) { | ||
25 | __gk20a_warn_on_no_regs(); | ||
26 | gk20a_dbg(gpu_dbg_reg, "r=0x%x v=0x%x (failed)", r, v); | ||
27 | } else { | ||
28 | writel_relaxed(v, l->regs + r); | ||
29 | nvgpu_smp_wmb(); | ||
30 | gk20a_dbg(gpu_dbg_reg, "r=0x%x v=0x%x", r, v); | ||
31 | } | ||
32 | } | ||
33 | |||
34 | u32 nvgpu_readl(struct gk20a *g, u32 r) | ||
35 | { | ||
36 | struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); | ||
37 | u32 v = 0xffffffff; | ||
38 | |||
39 | if (unlikely(!l->regs)) { | ||
40 | __gk20a_warn_on_no_regs(); | ||
41 | gk20a_dbg(gpu_dbg_reg, "r=0x%x v=0x%x (failed)", r, v); | ||
42 | } else { | ||
43 | v = readl(l->regs + r); | ||
44 | if (v == 0xffffffff) | ||
45 | __nvgpu_check_gpu_state(g); | ||
46 | gk20a_dbg(gpu_dbg_reg, "r=0x%x v=0x%x", r, v); | ||
47 | } | ||
48 | |||
49 | return v; | ||
50 | } | ||
51 | |||
52 | void nvgpu_writel_check(struct gk20a *g, u32 r, u32 v) | ||
53 | { | ||
54 | struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); | ||
55 | |||
56 | if (unlikely(!l->regs)) { | ||
57 | __gk20a_warn_on_no_regs(); | ||
58 | gk20a_dbg(gpu_dbg_reg, "r=0x%x v=0x%x (failed)", r, v); | ||
59 | } else { | ||
60 | nvgpu_smp_wmb(); | ||
61 | do { | ||
62 | writel_relaxed(v, l->regs + r); | ||
63 | } while (readl(l->regs + r) != v); | ||
64 | gk20a_dbg(gpu_dbg_reg, "r=0x%x v=0x%x", r, v); | ||
65 | } | ||
66 | } | ||
67 | |||
68 | void nvgpu_bar1_writel(struct gk20a *g, u32 b, u32 v) | ||
69 | { | ||
70 | struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); | ||
71 | |||
72 | if (unlikely(!l->bar1)) { | ||
73 | __gk20a_warn_on_no_regs(); | ||
74 | gk20a_dbg(gpu_dbg_reg, "b=0x%x v=0x%x (failed)", b, v); | ||
75 | } else { | ||
76 | nvgpu_smp_wmb(); | ||
77 | writel_relaxed(v, l->bar1 + b); | ||
78 | gk20a_dbg(gpu_dbg_reg, "b=0x%x v=0x%x", b, v); | ||
79 | } | ||
80 | } | ||
81 | |||
82 | u32 nvgpu_bar1_readl(struct gk20a *g, u32 b) | ||
83 | { | ||
84 | struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); | ||
85 | u32 v = 0xffffffff; | ||
86 | |||
87 | if (unlikely(!l->bar1)) { | ||
88 | __gk20a_warn_on_no_regs(); | ||
89 | gk20a_dbg(gpu_dbg_reg, "b=0x%x v=0x%x (failed)", b, v); | ||
90 | } else { | ||
91 | v = readl(l->bar1 + b); | ||
92 | gk20a_dbg(gpu_dbg_reg, "b=0x%x v=0x%x", b, v); | ||
93 | } | ||
94 | |||
95 | return v; | ||
96 | } | ||
97 | |||
98 | bool nvgpu_io_exists(struct gk20a *g) | ||
99 | { | ||
100 | struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); | ||
101 | |||
102 | return l->regs != NULL; | ||
103 | } | ||
104 | |||
105 | bool nvgpu_io_valid_reg(struct gk20a *g, u32 r) | ||
106 | { | ||
107 | struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); | ||
108 | |||
109 | return r < resource_size(l->regs); | ||
110 | } | ||
diff --git a/drivers/gpu/nvgpu/common/linux/module.c b/drivers/gpu/nvgpu/common/linux/module.c index 52f987b2..fe3e4e6f 100644 --- a/drivers/gpu/nvgpu/common/linux/module.c +++ b/drivers/gpu/nvgpu/common/linux/module.c | |||
@@ -137,6 +137,23 @@ void gk20a_idle(struct gk20a *g) | |||
137 | } | 137 | } |
138 | } | 138 | } |
139 | 139 | ||
140 | /* | ||
141 | * Undoes gk20a_lockout_registers(). | ||
142 | */ | ||
143 | static int gk20a_restore_registers(struct gk20a *g) | ||
144 | { | ||
145 | struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); | ||
146 | |||
147 | l->regs = l->regs_saved; | ||
148 | l->bar1 = l->bar1_saved; | ||
149 | |||
150 | #ifdef CONFIG_TEGRA_19x_GPU | ||
151 | t19x_restore_registers(g); | ||
152 | #endif | ||
153 | |||
154 | return 0; | ||
155 | } | ||
156 | |||
140 | int gk20a_pm_finalize_poweron(struct device *dev) | 157 | int gk20a_pm_finalize_poweron(struct device *dev) |
141 | { | 158 | { |
142 | struct gk20a *g = get_gk20a(dev); | 159 | struct gk20a *g = get_gk20a(dev); |
@@ -198,6 +215,27 @@ done: | |||
198 | return err; | 215 | return err; |
199 | } | 216 | } |
200 | 217 | ||
218 | /* | ||
219 | * Locks out the driver from accessing GPU registers. This prevents access to | ||
220 | * thse registers after the GPU has been clock or power gated. This should help | ||
221 | * find annoying bugs where register reads and writes are silently dropped | ||
222 | * after the GPU has been turned off. On older chips these reads and writes can | ||
223 | * also lock the entire CPU up. | ||
224 | */ | ||
225 | static int gk20a_lockout_registers(struct gk20a *g) | ||
226 | { | ||
227 | struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); | ||
228 | |||
229 | l->regs = NULL; | ||
230 | l->bar1 = NULL; | ||
231 | |||
232 | #ifdef CONFIG_TEGRA_19x_GPU | ||
233 | t19x_lockout_registers(g); | ||
234 | #endif | ||
235 | |||
236 | return 0; | ||
237 | } | ||
238 | |||
201 | static int gk20a_pm_prepare_poweroff(struct device *dev) | 239 | static int gk20a_pm_prepare_poweroff(struct device *dev) |
202 | { | 240 | { |
203 | struct gk20a *g = get_gk20a(dev); | 241 | struct gk20a *g = get_gk20a(dev); |
@@ -511,6 +549,8 @@ static irqreturn_t gk20a_intr_thread_stall(int irq, void *dev_id) | |||
511 | 549 | ||
512 | void gk20a_remove_support(struct gk20a *g) | 550 | void gk20a_remove_support(struct gk20a *g) |
513 | { | 551 | { |
552 | struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); | ||
553 | |||
514 | tegra_unregister_idle_unidle(gk20a_do_idle); | 554 | tegra_unregister_idle_unidle(gk20a_do_idle); |
515 | 555 | ||
516 | nvgpu_kfree(g, g->dbg_regops_tmp_buf); | 556 | nvgpu_kfree(g, g->dbg_regops_tmp_buf); |
@@ -535,36 +575,41 @@ void gk20a_remove_support(struct gk20a *g) | |||
535 | 575 | ||
536 | /* free mappings to registers, etc */ | 576 | /* free mappings to registers, etc */ |
537 | 577 | ||
538 | if (g->regs) { | 578 | if (l->regs) { |
539 | iounmap(g->regs); | 579 | iounmap(l->regs); |
540 | g->regs = NULL; | 580 | l->regs = NULL; |
541 | } | 581 | } |
542 | if (g->bar1) { | 582 | if (l->bar1) { |
543 | iounmap(g->bar1); | 583 | iounmap(l->bar1); |
544 | g->bar1 = NULL; | 584 | l->bar1 = NULL; |
545 | } | 585 | } |
586 | |||
587 | #ifdef CONFIG_TEGRA_19x_GPU | ||
588 | t19x_remove_support(g); | ||
589 | #endif | ||
546 | } | 590 | } |
547 | 591 | ||
548 | static int gk20a_init_support(struct platform_device *dev) | 592 | static int gk20a_init_support(struct platform_device *dev) |
549 | { | 593 | { |
550 | int err = 0; | 594 | int err = 0; |
551 | struct gk20a *g = get_gk20a(&dev->dev); | 595 | struct gk20a *g = get_gk20a(&dev->dev); |
596 | struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); | ||
552 | 597 | ||
553 | tegra_register_idle_unidle(gk20a_do_idle, gk20a_do_unidle, g); | 598 | tegra_register_idle_unidle(gk20a_do_idle, gk20a_do_unidle, g); |
554 | 599 | ||
555 | g->regs = gk20a_ioremap_resource(dev, GK20A_BAR0_IORESOURCE_MEM, | 600 | l->regs = gk20a_ioremap_resource(dev, GK20A_BAR0_IORESOURCE_MEM, |
556 | &g->reg_mem); | 601 | &l->reg_mem); |
557 | if (IS_ERR(g->regs)) { | 602 | if (IS_ERR(l->regs)) { |
558 | nvgpu_err(g, "failed to remap gk20a registers"); | 603 | nvgpu_err(g, "failed to remap gk20a registers"); |
559 | err = PTR_ERR(g->regs); | 604 | err = PTR_ERR(l->regs); |
560 | goto fail; | 605 | goto fail; |
561 | } | 606 | } |
562 | 607 | ||
563 | g->bar1 = gk20a_ioremap_resource(dev, GK20A_BAR1_IORESOURCE_MEM, | 608 | l->bar1 = gk20a_ioremap_resource(dev, GK20A_BAR1_IORESOURCE_MEM, |
564 | &g->bar1_mem); | 609 | &l->bar1_mem); |
565 | if (IS_ERR(g->bar1)) { | 610 | if (IS_ERR(l->bar1)) { |
566 | nvgpu_err(g, "failed to remap gk20a bar1"); | 611 | nvgpu_err(g, "failed to remap gk20a bar1"); |
567 | err = PTR_ERR(g->bar1); | 612 | err = PTR_ERR(l->bar1); |
568 | goto fail; | 613 | goto fail; |
569 | } | 614 | } |
570 | 615 | ||
@@ -584,6 +629,10 @@ static int gk20a_init_support(struct platform_device *dev) | |||
584 | goto fail; | 629 | goto fail; |
585 | } | 630 | } |
586 | 631 | ||
632 | #ifdef CONFIG_TEGRA_19x_GPU | ||
633 | t19x_init_support(g); | ||
634 | #endif | ||
635 | |||
587 | return 0; | 636 | return 0; |
588 | 637 | ||
589 | fail: | 638 | fail: |
diff --git a/drivers/gpu/nvgpu/common/linux/module.h b/drivers/gpu/nvgpu/common/linux/module.h index 55a3b692..5814d63a 100644 --- a/drivers/gpu/nvgpu/common/linux/module.h +++ b/drivers/gpu/nvgpu/common/linux/module.h | |||
@@ -13,6 +13,10 @@ | |||
13 | #ifndef __NVGPU_COMMON_LINUX_MODULE_H__ | 13 | #ifndef __NVGPU_COMMON_LINUX_MODULE_H__ |
14 | #define __NVGPU_COMMON_LINUX_MODULE_H__ | 14 | #define __NVGPU_COMMON_LINUX_MODULE_H__ |
15 | 15 | ||
16 | #ifdef CONFIG_TEGRA_19x_GPU | ||
17 | #include <nvgpu/linux/module_t19x.h> | ||
18 | #endif | ||
19 | |||
16 | struct gk20a; | 20 | struct gk20a; |
17 | struct device; | 21 | struct device; |
18 | 22 | ||
diff --git a/drivers/gpu/nvgpu/common/linux/nvgpu_mem.c b/drivers/gpu/nvgpu/common/linux/nvgpu_mem.c index 8740ac3d..1dbbd1a0 100644 --- a/drivers/gpu/nvgpu/common/linux/nvgpu_mem.c +++ b/drivers/gpu/nvgpu/common/linux/nvgpu_mem.c | |||
@@ -105,9 +105,10 @@ void nvgpu_mem_end(struct gk20a *g, struct nvgpu_mem *mem) | |||
105 | 105 | ||
106 | static void pramin_access_batch_rd_n(struct gk20a *g, u32 start, u32 words, u32 **arg) | 106 | static void pramin_access_batch_rd_n(struct gk20a *g, u32 start, u32 words, u32 **arg) |
107 | { | 107 | { |
108 | struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); | ||
108 | u32 r = start, *dest_u32 = *arg; | 109 | u32 r = start, *dest_u32 = *arg; |
109 | 110 | ||
110 | if (!g->regs) { | 111 | if (!l->regs) { |
111 | __gk20a_warn_on_no_regs(); | 112 | __gk20a_warn_on_no_regs(); |
112 | return; | 113 | return; |
113 | } | 114 | } |
@@ -182,15 +183,16 @@ void nvgpu_mem_rd_n(struct gk20a *g, struct nvgpu_mem *mem, | |||
182 | 183 | ||
183 | static void pramin_access_batch_wr_n(struct gk20a *g, u32 start, u32 words, u32 **arg) | 184 | static void pramin_access_batch_wr_n(struct gk20a *g, u32 start, u32 words, u32 **arg) |
184 | { | 185 | { |
186 | struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); | ||
185 | u32 r = start, *src_u32 = *arg; | 187 | u32 r = start, *src_u32 = *arg; |
186 | 188 | ||
187 | if (!g->regs) { | 189 | if (!l->regs) { |
188 | __gk20a_warn_on_no_regs(); | 190 | __gk20a_warn_on_no_regs(); |
189 | return; | 191 | return; |
190 | } | 192 | } |
191 | 193 | ||
192 | while (words--) { | 194 | while (words--) { |
193 | writel_relaxed(*src_u32++, g->regs + r); | 195 | writel_relaxed(*src_u32++, l->regs + r); |
194 | r += sizeof(u32); | 196 | r += sizeof(u32); |
195 | } | 197 | } |
196 | 198 | ||
@@ -256,15 +258,16 @@ void nvgpu_mem_wr_n(struct gk20a *g, struct nvgpu_mem *mem, u32 offset, | |||
256 | 258 | ||
257 | static void pramin_access_batch_set(struct gk20a *g, u32 start, u32 words, u32 **arg) | 259 | static void pramin_access_batch_set(struct gk20a *g, u32 start, u32 words, u32 **arg) |
258 | { | 260 | { |
261 | struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); | ||
259 | u32 r = start, repeat = **arg; | 262 | u32 r = start, repeat = **arg; |
260 | 263 | ||
261 | if (!g->regs) { | 264 | if (!l->regs) { |
262 | __gk20a_warn_on_no_regs(); | 265 | __gk20a_warn_on_no_regs(); |
263 | return; | 266 | return; |
264 | } | 267 | } |
265 | 268 | ||
266 | while (words--) { | 269 | while (words--) { |
267 | writel_relaxed(repeat, g->regs + r); | 270 | writel_relaxed(repeat, l->regs + r); |
268 | r += sizeof(u32); | 271 | r += sizeof(u32); |
269 | } | 272 | } |
270 | } | 273 | } |
diff --git a/drivers/gpu/nvgpu/common/linux/os_linux.h b/drivers/gpu/nvgpu/common/linux/os_linux.h index 48479843..4a3128c3 100644 --- a/drivers/gpu/nvgpu/common/linux/os_linux.h +++ b/drivers/gpu/nvgpu/common/linux/os_linux.h | |||
@@ -18,6 +18,9 @@ | |||
18 | 18 | ||
19 | #include <linux/cdev.h> | 19 | #include <linux/cdev.h> |
20 | 20 | ||
21 | #ifdef CONFIG_TEGRA_19x_GPU | ||
22 | #include <nvgpu/linux/os_linux_t19x.h> | ||
23 | #endif | ||
21 | #include "gk20a/gk20a.h" | 24 | #include "gk20a/gk20a.h" |
22 | #include "cde.h" | 25 | #include "cde.h" |
23 | 26 | ||
@@ -85,6 +88,17 @@ struct nvgpu_os_linux { | |||
85 | struct work_struct nonstall_fn_work; | 88 | struct work_struct nonstall_fn_work; |
86 | struct workqueue_struct *nonstall_work_queue; | 89 | struct workqueue_struct *nonstall_work_queue; |
87 | 90 | ||
91 | struct resource *reg_mem; | ||
92 | void __iomem *regs; | ||
93 | void __iomem *regs_saved; | ||
94 | |||
95 | struct resource *bar1_mem; | ||
96 | void __iomem *bar1; | ||
97 | void __iomem *bar1_saved; | ||
98 | |||
99 | #ifdef CONFIG_TEGRA_19x_GPU | ||
100 | struct nvgpu_os_linux_t19x t19x; | ||
101 | #endif | ||
88 | #ifdef CONFIG_DEBUG_FS | 102 | #ifdef CONFIG_DEBUG_FS |
89 | struct dentry *debugfs; | 103 | struct dentry *debugfs; |
90 | struct dentry *debugfs_alias; | 104 | struct dentry *debugfs_alias; |
diff --git a/drivers/gpu/nvgpu/common/linux/pci.c b/drivers/gpu/nvgpu/common/linux/pci.c index 401080ed..50d079bb 100644 --- a/drivers/gpu/nvgpu/common/linux/pci.c +++ b/drivers/gpu/nvgpu/common/linux/pci.c | |||
@@ -348,20 +348,21 @@ static int nvgpu_pci_init_support(struct pci_dev *pdev) | |||
348 | { | 348 | { |
349 | int err = 0; | 349 | int err = 0; |
350 | struct gk20a *g = get_gk20a(&pdev->dev); | 350 | struct gk20a *g = get_gk20a(&pdev->dev); |
351 | struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); | ||
351 | 352 | ||
352 | g->regs = ioremap(pci_resource_start(pdev, 0), | 353 | l->regs = ioremap(pci_resource_start(pdev, 0), |
353 | pci_resource_len(pdev, 0)); | 354 | pci_resource_len(pdev, 0)); |
354 | if (IS_ERR(g->regs)) { | 355 | if (IS_ERR(l->regs)) { |
355 | nvgpu_err(g, "failed to remap gk20a registers"); | 356 | nvgpu_err(g, "failed to remap gk20a registers"); |
356 | err = PTR_ERR(g->regs); | 357 | err = PTR_ERR(l->regs); |
357 | goto fail; | 358 | goto fail; |
358 | } | 359 | } |
359 | 360 | ||
360 | g->bar1 = ioremap(pci_resource_start(pdev, 1), | 361 | l->bar1 = ioremap(pci_resource_start(pdev, 1), |
361 | pci_resource_len(pdev, 1)); | 362 | pci_resource_len(pdev, 1)); |
362 | if (IS_ERR(g->bar1)) { | 363 | if (IS_ERR(l->bar1)) { |
363 | nvgpu_err(g, "failed to remap gk20a bar1"); | 364 | nvgpu_err(g, "failed to remap gk20a bar1"); |
364 | err = PTR_ERR(g->bar1); | 365 | err = PTR_ERR(l->bar1); |
365 | goto fail; | 366 | goto fail; |
366 | } | 367 | } |
367 | 368 | ||
diff --git a/drivers/gpu/nvgpu/common/pramin.c b/drivers/gpu/nvgpu/common/pramin.c index b6166f51..9b04d5a3 100644 --- a/drivers/gpu/nvgpu/common/pramin.c +++ b/drivers/gpu/nvgpu/common/pramin.c | |||
@@ -51,7 +51,7 @@ void nvgpu_pramin_access_batched(struct gk20a *g, struct nvgpu_mem *mem, | |||
51 | * driver should be refactored to prevent this from happening, but for | 51 | * driver should be refactored to prevent this from happening, but for |
52 | * now it is ok just to ignore the writes | 52 | * now it is ok just to ignore the writes |
53 | */ | 53 | */ |
54 | if (!g->regs && nvgpu_is_enabled(g, NVGPU_DRIVER_IS_DYING)) | 54 | if (!gk20a_io_exists(g) && nvgpu_is_enabled(g, NVGPU_DRIVER_IS_DYING)) |
55 | return; | 55 | return; |
56 | 56 | ||
57 | alloc = mem->vidmem_alloc; | 57 | alloc = mem->vidmem_alloc; |
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c index cac62db7..a4becda0 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a.c | |||
@@ -65,32 +65,6 @@ void __nvgpu_check_gpu_state(struct gk20a *g) | |||
65 | } | 65 | } |
66 | } | 66 | } |
67 | 67 | ||
68 | /* | ||
69 | * Locks out the driver from accessing GPU registers. This prevents access to | ||
70 | * thse registers after the GPU has been clock or power gated. This should help | ||
71 | * find annoying bugs where register reads and writes are silently dropped | ||
72 | * after the GPU has been turned off. On older chips these reads and writes can | ||
73 | * also lock the entire CPU up. | ||
74 | */ | ||
75 | int gk20a_lockout_registers(struct gk20a *g) | ||
76 | { | ||
77 | g->regs = NULL; | ||
78 | g->bar1 = NULL; | ||
79 | |||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | /* | ||
84 | * Undoes gk20a_lockout_registers(). | ||
85 | */ | ||
86 | int gk20a_restore_registers(struct gk20a *g) | ||
87 | { | ||
88 | g->regs = g->regs_saved; | ||
89 | g->bar1 = g->bar1_saved; | ||
90 | |||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | void __gk20a_warn_on_no_regs(void) | 68 | void __gk20a_warn_on_no_regs(void) |
95 | { | 69 | { |
96 | WARN_ONCE(1, "Attempted access to GPU regs after unmapping!"); | 70 | WARN_ONCE(1, "Attempted access to GPU regs after unmapping!"); |
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index a45a7b4e..bf10055a 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h | |||
@@ -44,6 +44,7 @@ struct nvgpu_mem_sgt; | |||
44 | 44 | ||
45 | #include <nvgpu/lock.h> | 45 | #include <nvgpu/lock.h> |
46 | #include <nvgpu/thread.h> | 46 | #include <nvgpu/thread.h> |
47 | #include <nvgpu/io.h> | ||
47 | #ifdef CONFIG_DEBUG_FS | 48 | #ifdef CONFIG_DEBUG_FS |
48 | #include <linux/debugfs.h> | 49 | #include <linux/debugfs.h> |
49 | #endif | 50 | #endif |
@@ -1067,14 +1068,6 @@ struct gk20a { | |||
1067 | 1068 | ||
1068 | struct nvgpu_ref refcount; | 1069 | struct nvgpu_ref refcount; |
1069 | 1070 | ||
1070 | struct resource *reg_mem; | ||
1071 | void __iomem *regs; | ||
1072 | void __iomem *regs_saved; | ||
1073 | |||
1074 | struct resource *bar1_mem; | ||
1075 | void __iomem *bar1; | ||
1076 | void __iomem *bar1_saved; | ||
1077 | |||
1078 | const char *name; | 1071 | const char *name; |
1079 | 1072 | ||
1080 | bool gpu_reset_done; | 1073 | bool gpu_reset_done; |
@@ -1339,81 +1332,9 @@ enum gk20a_nonstall_ops { | |||
1339 | }; | 1332 | }; |
1340 | 1333 | ||
1341 | /* register accessors */ | 1334 | /* register accessors */ |
1342 | int gk20a_lockout_registers(struct gk20a *g); | ||
1343 | int gk20a_restore_registers(struct gk20a *g); | ||
1344 | |||
1345 | void __nvgpu_check_gpu_state(struct gk20a *g); | 1335 | void __nvgpu_check_gpu_state(struct gk20a *g); |
1346 | void __gk20a_warn_on_no_regs(void); | 1336 | void __gk20a_warn_on_no_regs(void); |
1347 | 1337 | ||
1348 | static inline void gk20a_writel(struct gk20a *g, u32 r, u32 v) | ||
1349 | { | ||
1350 | if (unlikely(!g->regs)) { | ||
1351 | __gk20a_warn_on_no_regs(); | ||
1352 | gk20a_dbg(gpu_dbg_reg, "r=0x%x v=0x%x (failed)", r, v); | ||
1353 | } else { | ||
1354 | writel_relaxed(v, g->regs + r); | ||
1355 | nvgpu_smp_wmb(); | ||
1356 | gk20a_dbg(gpu_dbg_reg, "r=0x%x v=0x%x", r, v); | ||
1357 | } | ||
1358 | } | ||
1359 | static inline u32 gk20a_readl(struct gk20a *g, u32 r) | ||
1360 | { | ||
1361 | |||
1362 | u32 v = 0xffffffff; | ||
1363 | |||
1364 | if (unlikely(!g->regs)) { | ||
1365 | __gk20a_warn_on_no_regs(); | ||
1366 | gk20a_dbg(gpu_dbg_reg, "r=0x%x v=0x%x (failed)", r, v); | ||
1367 | } else { | ||
1368 | v = readl(g->regs + r); | ||
1369 | if (v == 0xffffffff) | ||
1370 | __nvgpu_check_gpu_state(g); | ||
1371 | gk20a_dbg(gpu_dbg_reg, "r=0x%x v=0x%x", r, v); | ||
1372 | } | ||
1373 | |||
1374 | return v; | ||
1375 | } | ||
1376 | static inline void gk20a_writel_check(struct gk20a *g, u32 r, u32 v) | ||
1377 | { | ||
1378 | if (unlikely(!g->regs)) { | ||
1379 | __gk20a_warn_on_no_regs(); | ||
1380 | gk20a_dbg(gpu_dbg_reg, "r=0x%x v=0x%x (failed)", r, v); | ||
1381 | } else { | ||
1382 | nvgpu_smp_wmb(); | ||
1383 | do { | ||
1384 | writel_relaxed(v, g->regs + r); | ||
1385 | } while (readl(g->regs + r) != v); | ||
1386 | gk20a_dbg(gpu_dbg_reg, "r=0x%x v=0x%x", r, v); | ||
1387 | } | ||
1388 | } | ||
1389 | |||
1390 | static inline void gk20a_bar1_writel(struct gk20a *g, u32 b, u32 v) | ||
1391 | { | ||
1392 | if (unlikely(!g->bar1)) { | ||
1393 | __gk20a_warn_on_no_regs(); | ||
1394 | gk20a_dbg(gpu_dbg_reg, "b=0x%x v=0x%x (failed)", b, v); | ||
1395 | } else { | ||
1396 | nvgpu_smp_wmb(); | ||
1397 | writel_relaxed(v, g->bar1 + b); | ||
1398 | gk20a_dbg(gpu_dbg_reg, "b=0x%x v=0x%x", b, v); | ||
1399 | } | ||
1400 | } | ||
1401 | |||
1402 | static inline u32 gk20a_bar1_readl(struct gk20a *g, u32 b) | ||
1403 | { | ||
1404 | u32 v = 0xffffffff; | ||
1405 | |||
1406 | if (unlikely(!g->bar1)) { | ||
1407 | __gk20a_warn_on_no_regs(); | ||
1408 | gk20a_dbg(gpu_dbg_reg, "b=0x%x v=0x%x (failed)", b, v); | ||
1409 | } else { | ||
1410 | v = readl(g->bar1 + b); | ||
1411 | gk20a_dbg(gpu_dbg_reg, "b=0x%x v=0x%x", b, v); | ||
1412 | } | ||
1413 | |||
1414 | return v; | ||
1415 | } | ||
1416 | |||
1417 | /* convenience */ | 1338 | /* convenience */ |
1418 | static inline struct gk20a *gk20a_from_as(struct gk20a_as *as) | 1339 | static inline struct gk20a *gk20a_from_as(struct gk20a_as *as) |
1419 | { | 1340 | { |
diff --git a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c index 707bfb87..6f829282 100644 --- a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c | |||
@@ -5256,8 +5256,7 @@ static inline bool is_valid_cyclestats_bar0_offset_gk20a(struct gk20a *g, | |||
5256 | is_bar0_global_offset_whitelisted_gk20a(g, offset); | 5256 | is_bar0_global_offset_whitelisted_gk20a(g, offset); |
5257 | /* resource size check in case there was a problem | 5257 | /* resource size check in case there was a problem |
5258 | * with allocating the assumed size of bar0 */ | 5258 | * with allocating the assumed size of bar0 */ |
5259 | valid = valid && | 5259 | valid = valid && gk20a_io_valid_reg(g, offset); |
5260 | offset < resource_size(g->regs); | ||
5261 | return valid; | 5260 | return valid; |
5262 | } | 5261 | } |
5263 | #endif | 5262 | #endif |
diff --git a/drivers/gpu/nvgpu/include/nvgpu/io.h b/drivers/gpu/nvgpu/include/nvgpu/io.h new file mode 100644 index 00000000..94ae8f95 --- /dev/null +++ b/drivers/gpu/nvgpu/include/nvgpu/io.h | |||
@@ -0,0 +1,49 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
20 | * DEALINGS IN THE SOFTWARE. | ||
21 | */ | ||
22 | #ifndef __NVGPU_IO_H__ | ||
23 | #define __NVGPU_IO_H__ | ||
24 | |||
25 | #include <nvgpu/types.h> | ||
26 | #ifdef CONFIG_TEGRA_19x_GPU | ||
27 | #include <nvgpu/io_t19x.h> | ||
28 | #endif | ||
29 | |||
30 | /* Legacy defines - should be removed once everybody uses nvgpu_* */ | ||
31 | #define gk20a_writel nvgpu_writel | ||
32 | #define gk20a_readl nvgpu_readl | ||
33 | #define gk20a_writel_check nvgpu_writel_check | ||
34 | #define gk20a_bar1_writel nvgpu_bar1_writel | ||
35 | #define gk20a_bar1_readl nvgpu_bar1_readl | ||
36 | #define gk20a_io_exists nvgpu_io_exists | ||
37 | #define gk20a_io_valid_reg nvgpu_io_valid_reg | ||
38 | |||
39 | struct gk20a; | ||
40 | |||
41 | void nvgpu_writel(struct gk20a *g, u32 r, u32 v); | ||
42 | u32 nvgpu_readl(struct gk20a *g, u32 r); | ||
43 | void nvgpu_writel_check(struct gk20a *g, u32 r, u32 v); | ||
44 | void nvgpu_bar1_writel(struct gk20a *g, u32 b, u32 v); | ||
45 | u32 nvgpu_bar1_readl(struct gk20a *g, u32 b); | ||
46 | bool nvgpu_io_exists(struct gk20a *g); | ||
47 | bool nvgpu_io_valid_reg(struct gk20a *g, u32 r); | ||
48 | |||
49 | #endif | ||
diff --git a/drivers/gpu/nvgpu/vgpu/fifo_vgpu.c b/drivers/gpu/nvgpu/vgpu/fifo_vgpu.c index 9010c4a3..73a67d91 100644 --- a/drivers/gpu/nvgpu/vgpu/fifo_vgpu.c +++ b/drivers/gpu/nvgpu/vgpu/fifo_vgpu.c | |||
@@ -268,6 +268,7 @@ clean_up_runlist: | |||
268 | 268 | ||
269 | static int vgpu_init_fifo_setup_sw(struct gk20a *g) | 269 | static int vgpu_init_fifo_setup_sw(struct gk20a *g) |
270 | { | 270 | { |
271 | struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); | ||
271 | struct fifo_gk20a *f = &g->fifo; | 272 | struct fifo_gk20a *f = &g->fifo; |
272 | struct device *d = dev_from_gk20a(g); | 273 | struct device *d = dev_from_gk20a(g); |
273 | struct vgpu_priv_data *priv = vgpu_get_priv_data(g); | 274 | struct vgpu_priv_data *priv = vgpu_get_priv_data(g); |
@@ -305,7 +306,7 @@ static int vgpu_init_fifo_setup_sw(struct gk20a *g) | |||
305 | /* if reduced BAR1 range is specified, use offset of 0 | 306 | /* if reduced BAR1 range is specified, use offset of 0 |
306 | * (server returns offset assuming full BAR1 range) | 307 | * (server returns offset assuming full BAR1 range) |
307 | */ | 308 | */ |
308 | if (resource_size(g->bar1_mem) == | 309 | if (resource_size(l->bar1_mem) == |
309 | (resource_size_t)f->userd.size) | 310 | (resource_size_t)f->userd.size) |
310 | f->userd.gpu_va = 0; | 311 | f->userd.gpu_va = 0; |
311 | } | 312 | } |
diff --git a/drivers/gpu/nvgpu/vgpu/vgpu.c b/drivers/gpu/nvgpu/vgpu/vgpu.c index c13d8ff0..b63202c1 100644 --- a/drivers/gpu/nvgpu/vgpu/vgpu.c +++ b/drivers/gpu/nvgpu/vgpu/vgpu.c | |||
@@ -216,6 +216,7 @@ static int vgpu_intr_thread(void *dev_id) | |||
216 | 216 | ||
217 | static void vgpu_remove_support(struct gk20a *g) | 217 | static void vgpu_remove_support(struct gk20a *g) |
218 | { | 218 | { |
219 | struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); | ||
219 | struct vgpu_priv_data *priv = | 220 | struct vgpu_priv_data *priv = |
220 | vgpu_get_priv_data_from_dev(dev_from_gk20a(g)); | 221 | vgpu_get_priv_data_from_dev(dev_from_gk20a(g)); |
221 | struct tegra_vgpu_intr_msg msg; | 222 | struct tegra_vgpu_intr_msg msg; |
@@ -245,18 +246,20 @@ static void vgpu_remove_support(struct gk20a *g) | |||
245 | 246 | ||
246 | /* free mappings to registers, etc*/ | 247 | /* free mappings to registers, etc*/ |
247 | 248 | ||
248 | if (g->bar1) { | 249 | if (l->bar1) { |
249 | iounmap(g->bar1); | 250 | iounmap(l->bar1); |
250 | g->bar1 = NULL; | 251 | l->bar1 = NULL; |
251 | } | 252 | } |
252 | } | 253 | } |
253 | 254 | ||
254 | static void vgpu_init_vars(struct gk20a *g, struct gk20a_platform *platform) | 255 | static void vgpu_init_vars(struct gk20a *g, struct gk20a_platform *platform) |
255 | { | 256 | { |
257 | struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); | ||
258 | |||
256 | nvgpu_mutex_init(&g->poweron_lock); | 259 | nvgpu_mutex_init(&g->poweron_lock); |
257 | nvgpu_mutex_init(&g->poweroff_lock); | 260 | nvgpu_mutex_init(&g->poweroff_lock); |
258 | g->regs_saved = g->regs; | 261 | l->regs_saved = l->regs; |
259 | g->bar1_saved = g->bar1; | 262 | l->bar1_saved = l->bar1; |
260 | 263 | ||
261 | nvgpu_init_list_node(&g->pending_sema_waits); | 264 | nvgpu_init_list_node(&g->pending_sema_waits); |
262 | nvgpu_raw_spinlock_init(&g->pending_sema_waits_lock); | 265 | nvgpu_raw_spinlock_init(&g->pending_sema_waits_lock); |
@@ -276,6 +279,7 @@ static int vgpu_init_support(struct platform_device *pdev) | |||
276 | { | 279 | { |
277 | struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 280 | struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
278 | struct gk20a *g = get_gk20a(&pdev->dev); | 281 | struct gk20a *g = get_gk20a(&pdev->dev); |
282 | struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); | ||
279 | void __iomem *regs; | 283 | void __iomem *regs; |
280 | int err = 0; | 284 | int err = 0; |
281 | 285 | ||
@@ -292,8 +296,8 @@ static int vgpu_init_support(struct platform_device *pdev) | |||
292 | err = PTR_ERR(regs); | 296 | err = PTR_ERR(regs); |
293 | goto fail; | 297 | goto fail; |
294 | } | 298 | } |
295 | g->bar1 = regs; | 299 | l->bar1 = regs; |
296 | g->bar1_mem = r; | 300 | l->bar1_mem = r; |
297 | } | 301 | } |
298 | 302 | ||
299 | nvgpu_mutex_init(&g->dbg_sessions_lock); | 303 | nvgpu_mutex_init(&g->dbg_sessions_lock); |