summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorTerje Bergstrom <tbergstrom@nvidia.com>2018-02-09 17:42:07 -0500
committermobile promotions <svcmobile_promotions@nvidia.com>2018-02-15 00:43:43 -0500
commitec00a6c2db2b6e163c2bb1245584a2d009fa1252 (patch)
tree7676cdb8840ccbbac287e31b2a5087d210854a8f /drivers
parent1582bdb5eeff44a93f53987080a652910d51c3c4 (diff)
gpu: nvgpu: Use preallocated VPR buffer
To prevent deadlock while allocating VPR in nvgpu, allocate all the needed VPR memory at probe time and use an internal allocator to hand out space for VPR buffers. Change-Id: I584b9a0f746d5d1dec021cdfbd6f26b4b92e4412 Signed-off-by: Terje Bergstrom <tbergstrom@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/1655324 Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/nvgpu/common/linux/platform_gk20a.h5
-rw-r--r--drivers/gpu/nvgpu/common/linux/platform_gk20a_tegra.c107
-rw-r--r--drivers/gpu/nvgpu/common/linux/platform_gk20a_tegra.h6
-rw-r--r--drivers/gpu/nvgpu/common/linux/platform_gp10b_tegra.c10
-rw-r--r--drivers/gpu/nvgpu/common/linux/platform_gv11b_tegra.c9
-rw-r--r--drivers/gpu/nvgpu/gk20a/gr_gk20a.c21
6 files changed, 77 insertions, 81 deletions
diff --git a/drivers/gpu/nvgpu/common/linux/platform_gk20a.h b/drivers/gpu/nvgpu/common/linux/platform_gk20a.h
index 6994677e..ba4880af 100644
--- a/drivers/gpu/nvgpu/common/linux/platform_gk20a.h
+++ b/drivers/gpu/nvgpu/common/linux/platform_gk20a.h
@@ -32,7 +32,8 @@ struct gk20a_scale_profile;
32struct secure_page_buffer { 32struct secure_page_buffer {
33 void (*destroy)(struct gk20a *, struct secure_page_buffer *); 33 void (*destroy)(struct gk20a *, struct secure_page_buffer *);
34 size_t size; 34 size_t size;
35 u64 iova; 35 dma_addr_t phys;
36 size_t used;
36}; 37};
37 38
38struct gk20a_platform { 39struct gk20a_platform {
@@ -148,6 +149,8 @@ struct gk20a_platform {
148 /* Powerdown platform dependencies */ 149 /* Powerdown platform dependencies */
149 void (*idle)(struct device *dev); 150 void (*idle)(struct device *dev);
150 151
152 /* Preallocated VPR buffer for kernel */
153 size_t secure_buffer_size;
151 struct secure_page_buffer secure_buffer; 154 struct secure_page_buffer secure_buffer;
152 155
153 /* Device is going to be suspended */ 156 /* Device is going to be suspended */
diff --git a/drivers/gpu/nvgpu/common/linux/platform_gk20a_tegra.c b/drivers/gpu/nvgpu/common/linux/platform_gk20a_tegra.c
index 127a8ce9..219dcd40 100644
--- a/drivers/gpu/nvgpu/common/linux/platform_gk20a_tegra.c
+++ b/drivers/gpu/nvgpu/common/linux/platform_gk20a_tegra.c
@@ -103,103 +103,61 @@ static void gk20a_tegra_secure_page_destroy(struct gk20a *g,
103 DEFINE_DMA_ATTRS(attrs); 103 DEFINE_DMA_ATTRS(attrs);
104 dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, __DMA_ATTR(attrs)); 104 dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, __DMA_ATTR(attrs));
105 dma_free_attrs(&tegra_vpr_dev, secure_buffer->size, 105 dma_free_attrs(&tegra_vpr_dev, secure_buffer->size,
106 (void *)(uintptr_t)secure_buffer->iova, 106 (void *)(uintptr_t)secure_buffer->phys,
107 secure_buffer->iova, __DMA_ATTR(attrs)); 107 secure_buffer->phys, __DMA_ATTR(attrs));
108 108
109 secure_buffer->destroy = NULL; 109 secure_buffer->destroy = NULL;
110} 110}
111 111
112int gk20a_tegra_secure_page_alloc(struct device *dev)
113{
114 struct gk20a_platform *platform = dev_get_drvdata(dev);
115 struct gk20a *g = get_gk20a(dev);
116 struct secure_page_buffer *secure_buffer = &platform->secure_buffer;
117 DEFINE_DMA_ATTRS(attrs);
118 dma_addr_t iova;
119 size_t size = PAGE_SIZE;
120
121 if (nvgpu_is_enabled(g, NVGPU_IS_FMODEL))
122 return -EINVAL;
123
124 dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, __DMA_ATTR(attrs));
125 (void)dma_alloc_attrs(&tegra_vpr_dev, size, &iova,
126 GFP_KERNEL, __DMA_ATTR(attrs));
127 if (dma_mapping_error(&tegra_vpr_dev, iova))
128 return -ENOMEM;
129
130 secure_buffer->size = size;
131 secure_buffer->iova = iova;
132 secure_buffer->destroy = gk20a_tegra_secure_page_destroy;
133
134 return 0;
135}
136
137static void gk20a_tegra_secure_destroy(struct gk20a *g,
138 struct gr_ctx_buffer_desc *desc)
139{
140 DEFINE_DMA_ATTRS(attrs);
141
142 if (desc->mem.priv.sgt) {
143 u64 pa = nvgpu_mem_get_phys_addr(g, &desc->mem);
144
145 dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, __DMA_ATTR(attrs));
146 dma_free_attrs(&tegra_vpr_dev, desc->mem.size,
147 (void *)(uintptr_t)pa,
148 pa, __DMA_ATTR(attrs));
149 nvgpu_free_sgtable(g, &desc->mem.priv.sgt);
150 desc->mem.priv.sgt = NULL;
151 }
152}
153
154static int gk20a_tegra_secure_alloc(struct gk20a *g, 112static int gk20a_tegra_secure_alloc(struct gk20a *g,
155 struct gr_ctx_buffer_desc *desc, 113 struct gr_ctx_buffer_desc *desc,
156 size_t size) 114 size_t size)
157{ 115{
158 struct device *dev = dev_from_gk20a(g); 116 struct device *dev = dev_from_gk20a(g);
159 struct gk20a_platform *platform = dev_get_drvdata(dev); 117 struct gk20a_platform *platform = dev_get_drvdata(dev);
160 DEFINE_DMA_ATTRS(attrs); 118 struct secure_page_buffer *secure_buffer = &platform->secure_buffer;
161 dma_addr_t iova; 119 dma_addr_t phys;
162 struct sg_table *sgt; 120 struct sg_table *sgt;
163 struct page *page; 121 struct page *page;
164 int err = 0; 122 int err = 0;
123 size_t aligned_size = PAGE_ALIGN(size);
165 124
166 dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, __DMA_ATTR(attrs)); 125 /* We ran out of preallocated memory */
167 (void)dma_alloc_attrs(&tegra_vpr_dev, size, &iova, 126 if (secure_buffer->used + aligned_size > secure_buffer->size) {
168 GFP_KERNEL, __DMA_ATTR(attrs)); 127 nvgpu_err(platform->g, "failed to alloc %zu bytes of VPR, %zu/%zu used",
169 if (dma_mapping_error(&tegra_vpr_dev, iova)) 128 size, secure_buffer->used, secure_buffer->size);
170 return -ENOMEM; 129 return -ENOMEM;
130 }
131
132 phys = secure_buffer->phys + secure_buffer->used;
171 133
172 sgt = nvgpu_kzalloc(platform->g, sizeof(*sgt)); 134 sgt = nvgpu_kzalloc(platform->g, sizeof(*sgt));
173 if (!sgt) { 135 if (!sgt) {
174 nvgpu_err(platform->g, "failed to allocate memory"); 136 nvgpu_err(platform->g, "failed to allocate memory");
175 goto fail; 137 return -ENOMEM;
176 } 138 }
177 err = sg_alloc_table(sgt, 1, GFP_KERNEL); 139 err = sg_alloc_table(sgt, 1, GFP_KERNEL);
178 if (err) { 140 if (err) {
179 nvgpu_err(platform->g, "failed to allocate sg_table"); 141 nvgpu_err(platform->g, "failed to allocate sg_table");
180 goto fail_sgt; 142 goto fail_sgt;
181 } 143 }
182 page = phys_to_page(iova); 144 page = phys_to_page(phys);
183 sg_set_page(sgt->sgl, page, size, 0); 145 sg_set_page(sgt->sgl, page, size, 0);
184 /* This bypasses SMMU for VPR during gmmu_map. */ 146 /* This bypasses SMMU for VPR during gmmu_map. */
185 sg_dma_address(sgt->sgl) = 0; 147 sg_dma_address(sgt->sgl) = 0;
186 148
187 desc->destroy = gk20a_tegra_secure_destroy; 149 desc->destroy = NULL;
188 150
189 desc->mem.priv.sgt = sgt; 151 desc->mem.priv.sgt = sgt;
190 desc->mem.size = size; 152 desc->mem.size = size;
191 desc->mem.aperture = APERTURE_SYSMEM; 153 desc->mem.aperture = APERTURE_SYSMEM;
192 154
193 if (platform->secure_buffer.destroy) 155 secure_buffer->used += aligned_size;
194 platform->secure_buffer.destroy(g, &platform->secure_buffer);
195 156
196 return err; 157 return err;
197 158
198fail_sgt: 159fail_sgt:
199 nvgpu_kfree(platform->g, sgt); 160 nvgpu_kfree(platform->g, sgt);
200fail:
201 dma_free_attrs(&tegra_vpr_dev, desc->mem.size,
202 (void *)(uintptr_t)iova, iova, __DMA_ATTR(attrs));
203 return err; 161 return err;
204} 162}
205 163
@@ -664,10 +622,32 @@ void gk20a_tegra_idle(struct device *dev)
664#endif 622#endif
665} 623}
666 624
667void gk20a_tegra_init_secure_alloc(struct gk20a *g) 625int gk20a_tegra_init_secure_alloc(struct gk20a_platform *platform)
668{ 626{
627 struct gk20a *g = platform->g;
628 struct secure_page_buffer *secure_buffer = &platform->secure_buffer;
629 DEFINE_DMA_ATTRS(attrs);
630 dma_addr_t iova;
631
632 if (nvgpu_is_enabled(g, NVGPU_IS_FMODEL))
633 return 0;
634
635 dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, __DMA_ATTR(attrs));
636 (void)dma_alloc_attrs(&tegra_vpr_dev, platform->secure_buffer_size, &iova,
637 GFP_KERNEL, __DMA_ATTR(attrs));
638 /* Some platforms disable VPR. In that case VPR allocations always
639 * fail. Just disable VPR usage in nvgpu in that case. */
640 if (dma_mapping_error(&tegra_vpr_dev, iova))
641 return 0;
642
643 secure_buffer->size = platform->secure_buffer_size;
644 secure_buffer->phys = iova;
645 secure_buffer->destroy = gk20a_tegra_secure_page_destroy;
646
669 g->ops.secure_alloc = gk20a_tegra_secure_alloc; 647 g->ops.secure_alloc = gk20a_tegra_secure_alloc;
670 __nvgpu_set_enabled(g, NVGPU_SUPPORT_VPR, true); 648 __nvgpu_set_enabled(g, NVGPU_SUPPORT_VPR, true);
649
650 return 0;
671} 651}
672 652
673#ifdef CONFIG_COMMON_CLK 653#ifdef CONFIG_COMMON_CLK
@@ -836,7 +816,9 @@ static int gk20a_tegra_probe(struct device *dev)
836 816
837 gk20a_tegra_get_clocks(dev); 817 gk20a_tegra_get_clocks(dev);
838 nvgpu_linux_init_clk_support(platform->g); 818 nvgpu_linux_init_clk_support(platform->g);
839 gk20a_tegra_init_secure_alloc(platform->g); 819 ret = gk20a_tegra_init_secure_alloc(platform);
820 if (ret)
821 return ret;
840 822
841 if (platform->clk_register) { 823 if (platform->clk_register) {
842 ret = platform->clk_register(platform->g); 824 ret = platform->clk_register(platform->g);
@@ -851,9 +833,6 @@ static int gk20a_tegra_probe(struct device *dev)
851 833
852static int gk20a_tegra_late_probe(struct device *dev) 834static int gk20a_tegra_late_probe(struct device *dev)
853{ 835{
854 /* Cause early VPR resize */
855 gk20a_tegra_secure_page_alloc(dev);
856
857 return 0; 836 return 0;
858} 837}
859 838
@@ -974,4 +953,6 @@ struct gk20a_platform gm20b_tegra_platform = {
974 .soc_name = "tegra21x", 953 .soc_name = "tegra21x",
975 954
976 .unified_memory = true, 955 .unified_memory = true,
956
957 .secure_buffer_size = 335872,
977}; 958};
diff --git a/drivers/gpu/nvgpu/common/linux/platform_gk20a_tegra.h b/drivers/gpu/nvgpu/common/linux/platform_gk20a_tegra.h
index 1aa7c1e3..f7d50406 100644
--- a/drivers/gpu/nvgpu/common/linux/platform_gk20a_tegra.h
+++ b/drivers/gpu/nvgpu/common/linux/platform_gk20a_tegra.h
@@ -16,10 +16,8 @@
16#ifndef _NVGPU_PLATFORM_GK20A_TEGRA_H_ 16#ifndef _NVGPU_PLATFORM_GK20A_TEGRA_H_
17#define _NVGPU_PLATFORM_GK20A_TEGRA_H_ 17#define _NVGPU_PLATFORM_GK20A_TEGRA_H_
18 18
19struct device; 19struct gk20a_platform;
20struct gk20a;
21 20
22void gk20a_tegra_init_secure_alloc(struct gk20a *g); 21int gk20a_tegra_init_secure_alloc(struct gk20a_platform *platform);
23int gk20a_tegra_secure_page_alloc(struct device *dev);
24 22
25#endif 23#endif
diff --git a/drivers/gpu/nvgpu/common/linux/platform_gp10b_tegra.c b/drivers/gpu/nvgpu/common/linux/platform_gp10b_tegra.c
index 0b0ebeeb..2bca2bd5 100644
--- a/drivers/gpu/nvgpu/common/linux/platform_gp10b_tegra.c
+++ b/drivers/gpu/nvgpu/common/linux/platform_gp10b_tegra.c
@@ -137,6 +137,10 @@ static int gp10b_tegra_probe(struct device *dev)
137 return ret; 137 return ret;
138#endif 138#endif
139 139
140 ret = gk20a_tegra_init_secure_alloc(platform);
141 if (ret)
142 return ret;
143
140 platform->disable_bigpage = !device_is_iommuable(dev); 144 platform->disable_bigpage = !device_is_iommuable(dev);
141 145
142 platform->g->gr.ctx_vars.dump_ctxsw_stats_on_channel_close 146 platform->g->gr.ctx_vars.dump_ctxsw_stats_on_channel_close
@@ -149,16 +153,12 @@ static int gp10b_tegra_probe(struct device *dev)
149 153
150 gp10b_tegra_get_clocks(dev); 154 gp10b_tegra_get_clocks(dev);
151 nvgpu_linux_init_clk_support(platform->g); 155 nvgpu_linux_init_clk_support(platform->g);
152 gk20a_tegra_init_secure_alloc(platform->g);
153 156
154 return 0; 157 return 0;
155} 158}
156 159
157static int gp10b_tegra_late_probe(struct device *dev) 160static int gp10b_tegra_late_probe(struct device *dev)
158{ 161{
159 /* Cause early VPR resize */
160 gk20a_tegra_secure_page_alloc(dev);
161
162 return 0; 162 return 0;
163} 163}
164 164
@@ -422,6 +422,8 @@ struct gk20a_platform gp10b_tegra_platform = {
422 .unified_memory = true, 422 .unified_memory = true,
423 423
424 .ltc_streamid = TEGRA_SID_GPUB, 424 .ltc_streamid = TEGRA_SID_GPUB,
425
426 .secure_buffer_size = 401408,
425}; 427};
426 428
427 429
diff --git a/drivers/gpu/nvgpu/common/linux/platform_gv11b_tegra.c b/drivers/gpu/nvgpu/common/linux/platform_gv11b_tegra.c
index 40c75164..ad56167a 100644
--- a/drivers/gpu/nvgpu/common/linux/platform_gv11b_tegra.c
+++ b/drivers/gpu/nvgpu/common/linux/platform_gv11b_tegra.c
@@ -81,6 +81,10 @@ static int gv11b_tegra_probe(struct device *dev)
81 g->has_syncpoints = false; 81 g->has_syncpoints = false;
82#endif 82#endif
83 83
84 err = gk20a_tegra_init_secure_alloc(platform);
85 if (err)
86 return err;
87
84 platform->disable_bigpage = !device_is_iommuable(dev); 88 platform->disable_bigpage = !device_is_iommuable(dev);
85 89
86 platform->g->gr.ctx_vars.dump_ctxsw_stats_on_channel_close 90 platform->g->gr.ctx_vars.dump_ctxsw_stats_on_channel_close
@@ -93,15 +97,12 @@ static int gv11b_tegra_probe(struct device *dev)
93 97
94 gp10b_tegra_get_clocks(dev); 98 gp10b_tegra_get_clocks(dev);
95 nvgpu_linux_init_clk_support(platform->g); 99 nvgpu_linux_init_clk_support(platform->g);
96 gk20a_tegra_init_secure_alloc(platform->g);
97 100
98 return 0; 101 return 0;
99} 102}
100 103
101static int gv11b_tegra_late_probe(struct device *dev) 104static int gv11b_tegra_late_probe(struct device *dev)
102{ 105{
103 /* Cause early VPR resize */
104 gk20a_tegra_secure_page_alloc(dev);
105 return 0; 106 return 0;
106} 107}
107 108
@@ -263,6 +264,8 @@ struct gk20a_platform gv11b_tegra_platform = {
263 264
264 .reset_assert = gp10b_tegra_reset_assert, 265 .reset_assert = gp10b_tegra_reset_assert,
265 .reset_deassert = gp10b_tegra_reset_deassert, 266 .reset_deassert = gp10b_tegra_reset_deassert,
267
268 .secure_buffer_size = 667648,
266}; 269};
267 270
268static struct device_attribute *dev_attr_sm_l1_tag_ecc_corrected_err_count_array; 271static struct device_attribute *dev_attr_sm_l1_tag_ecc_corrected_err_count_array;
diff --git a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c
index fb02bb81..0e21f749 100644
--- a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c
@@ -2532,10 +2532,13 @@ static int gr_gk20a_alloc_global_ctx_buffers(struct gk20a *g)
2532 if (err) 2532 if (err)
2533 goto clean_up; 2533 goto clean_up;
2534 2534
2535 if (g->ops.secure_alloc) 2535 if (g->ops.secure_alloc) {
2536 g->ops.secure_alloc(g, 2536 err = g->ops.secure_alloc(g,
2537 &gr->global_ctx_buffer[CIRCULAR_VPR], 2537 &gr->global_ctx_buffer[CIRCULAR_VPR],
2538 cb_buffer_size); 2538 cb_buffer_size);
2539 if (err)
2540 goto clean_up;
2541 }
2539 2542
2540 gk20a_dbg_info("pagepool_buffer_size : %d", pagepool_buffer_size); 2543 gk20a_dbg_info("pagepool_buffer_size : %d", pagepool_buffer_size);
2541 2544
@@ -2544,10 +2547,13 @@ static int gr_gk20a_alloc_global_ctx_buffers(struct gk20a *g)
2544 if (err) 2547 if (err)
2545 goto clean_up; 2548 goto clean_up;
2546 2549
2547 if (g->ops.secure_alloc) 2550 if (g->ops.secure_alloc) {
2548 g->ops.secure_alloc(g, 2551 err = g->ops.secure_alloc(g,
2549 &gr->global_ctx_buffer[PAGEPOOL_VPR], 2552 &gr->global_ctx_buffer[PAGEPOOL_VPR],
2550 pagepool_buffer_size); 2553 pagepool_buffer_size);
2554 if (err)
2555 goto clean_up;
2556 }
2551 2557
2552 gk20a_dbg_info("attr_buffer_size : %d", attr_buffer_size); 2558 gk20a_dbg_info("attr_buffer_size : %d", attr_buffer_size);
2553 2559
@@ -2556,10 +2562,13 @@ static int gr_gk20a_alloc_global_ctx_buffers(struct gk20a *g)
2556 if (err) 2562 if (err)
2557 goto clean_up; 2563 goto clean_up;
2558 2564
2559 if (g->ops.secure_alloc) 2565 if (g->ops.secure_alloc) {
2560 g->ops.secure_alloc(g, 2566 err = g->ops.secure_alloc(g,
2561 &gr->global_ctx_buffer[ATTRIBUTE_VPR], 2567 &gr->global_ctx_buffer[ATTRIBUTE_VPR],
2562 attr_buffer_size); 2568 attr_buffer_size);
2569 if (err)
2570 goto clean_up;
2571 }
2563 2572
2564 gk20a_dbg_info("golden_image_size : %d", 2573 gk20a_dbg_info("golden_image_size : %d",
2565 gr->ctx_vars.golden_image_size); 2574 gr->ctx_vars.golden_image_size);